|
366 | 366 | if (!idx) { |
367 | 367 | span.className = 'selected'; |
368 | 368 | query_elem.value = queries[example]; |
| 369 | + last_selected_example = example; |
369 | 370 | } |
370 | 371 | span.append(document.createTextNode(example)); |
371 | 372 | span.addEventListener('click', e => { |
| 373 | + /// Extract WHERE patch from user's edits before switching. |
| 374 | + let patch = null; |
| 375 | + if (last_selected_example && queries[last_selected_example]) { |
| 376 | + patch = getWherePatch(query_elem.value, queries[last_selected_example]); |
| 377 | + } |
| 378 | + |
372 | 379 | for (other of examples_elem.querySelectorAll('.selected')) { |
373 | 380 | other.classList.remove('selected'); |
374 | 381 | } |
375 | 382 | e.target.classList.add('selected'); |
376 | | - setQuery(queries[example]); |
| 383 | + last_selected_example = example; |
| 384 | + |
| 385 | + let new_query = queries[example]; |
| 386 | + if (patch) { |
| 387 | + new_query = applyWherePatch(new_query, patch); |
| 388 | + } |
| 389 | + setQuery(new_query); |
377 | 390 | }); |
378 | 391 | examples_elem.append(span); |
379 | 392 | }); |
|
499 | 512 | let map_elem = document.getElementById('map'); |
500 | 513 | let selected_box = []; |
501 | 514 | let cached_tiles = {}; |
| 515 | + let last_selected_example = null; |
502 | 516 |
|
503 | 517 | /// Protect from race conditions. |
504 | 518 | let report_sequence_num = 0; |
|
527 | 541 | if (selected_box.length == 2) showReport(); |
528 | 542 | } |
529 | 543 |
|
| 544 | + /// Extract the WHERE clause content (between WHERE and GROUP BY) from a query. |
| 545 | + function extractWhereClause(query) { |
| 546 | + const match = /WHERE(.+?)GROUP\s+BY/is.exec(query); |
| 547 | + return match ? match[1].trim() : null; |
| 548 | + } |
| 549 | + |
| 550 | + /// Get user's WHERE clause modifications by comparing with the original example. |
| 551 | + function getWherePatch(currentQuery, originalQuery) { |
| 552 | + const currentWhere = extractWhereClause(currentQuery); |
| 553 | + const originalWhere = extractWhereClause(originalQuery); |
| 554 | + if (!currentWhere || !originalWhere) return null; |
| 555 | + |
| 556 | + /// Normalize whitespace for comparison. |
| 557 | + const normalize = s => s.replace(/\s+/g, ' ').trim(); |
| 558 | + const normCurrent = normalize(currentWhere); |
| 559 | + const normOriginal = normalize(originalWhere); |
| 560 | + |
| 561 | + if (normCurrent === normOriginal) return null; |
| 562 | + |
| 563 | + /// Check if the current WHERE starts with the original WHERE content. |
| 564 | + if (normCurrent.startsWith(normOriginal)) { |
| 565 | + return normCurrent.slice(normOriginal.length).trim(); |
| 566 | + } |
| 567 | + |
| 568 | + return null; |
| 569 | + } |
| 570 | + |
| 571 | + /// Apply a WHERE patch to a new query. |
| 572 | + function applyWherePatch(query, patch) { |
| 573 | + if (!patch) return query; |
| 574 | + return query.replace(/(WHERE\s+.+?)\s*(GROUP\s+BY)/is, '$1 ' + patch + '\n$2'); |
| 575 | + } |
| 576 | + |
530 | 577 | function setQuery(value) { |
531 | 578 | query_elem.value = value; |
532 | 579 | collapseQueryEditor(); |
|
779 | 826 | example.classList.remove('selected'); |
780 | 827 | if (query == queries[example.innerText]) { |
781 | 828 | example.classList.add('selected'); |
| 829 | + last_selected_example = example.innerText; |
782 | 830 | } |
783 | 831 | } |
784 | 832 | }); |
|
0 commit comments