From 91e48a5b46d7cec9d3e0ca580a13e66667381758 Mon Sep 17 00:00:00 2001 From: Ronaldo Ferreira de Lima Date: Sun, 26 Oct 2025 19:06:52 -0300 Subject: [PATCH 1/5] * proof of concept --- .../concept/intro-select/create_fixture.sql | 10 +++ .../intro-select/create_test_table.sql | 23 +++++ exercises/concept/intro-select/data.csv | 6 ++ .../concept/intro-select/intro-select.sql | 14 +++ .../intro-select/intro-select_test.sql | 85 +++++++++++++++++++ exercises/concept/intro-select/outputs.txt | 27 ++++++ 6 files changed, 165 insertions(+) create mode 100644 exercises/concept/intro-select/create_fixture.sql create mode 100644 exercises/concept/intro-select/create_test_table.sql create mode 100644 exercises/concept/intro-select/data.csv create mode 100644 exercises/concept/intro-select/intro-select.sql create mode 100644 exercises/concept/intro-select/intro-select_test.sql create mode 100644 exercises/concept/intro-select/outputs.txt diff --git a/exercises/concept/intro-select/create_fixture.sql b/exercises/concept/intro-select/create_fixture.sql new file mode 100644 index 00000000..37d4b63f --- /dev/null +++ b/exercises/concept/intro-select/create_fixture.sql @@ -0,0 +1,10 @@ +DROP TABLE IF EXISTS weather_readings; +CREATE TABLE weather_readings ( + date TEXT NOT NULL, + location TEXT NOT NULL, + temperature REAL NOT NULL, + humidity INTEGER NOT NULL +); + +.mode csv +.import ./data.csv weather_readings diff --git a/exercises/concept/intro-select/create_test_table.sql b/exercises/concept/intro-select/create_test_table.sql new file mode 100644 index 00000000..7f4bd05f --- /dev/null +++ b/exercises/concept/intro-select/create_test_table.sql @@ -0,0 +1,23 @@ +DROP TABLE IF EXISTS tests; +CREATE TABLE IF NOT EXISTS tests ( + description TEXT NOT NULL, + -- The following section is needed by the online test-runner + status TEXT DEFAULT 'fail', + message TEXT, + output TEXT, + test_code TEXT, + task_id INTEGER DEFAULT NULL, + -- Here are columns for the actual tests + expected TEXT NOT NULL +); + +INSERT INTO tests (description, expected) +VALUES + ('ALL records => SELECT * FROM weather_readings', '[{"date":"2025-10-22","location":"Portland","temperature":53.1,"humidity":72},{"date":"2025-10-22","location":"Seattle","temperature":56.2,"humidity":66},{"date":"2025-10-22","location":"Boise","temperature":60.4,"humidity":55},{"date":"2025-10-23","location":"Portland","temperature":54.6,"humidity":70},{"date":"2025-10-23","location":"Seattle","temperature":57.8,"humidity":68},{"date":"2025-10-23","location":"Boise","temperature":62.0,"humidity":58}]'), + ('Just location and temperature columns => SELECT location, temperature FROM weather_readings', '[{"location":"Portland","temperature":53.1},{"location":"Seattle","temperature":56.2},{"location":"Boise","temperature":60.4},{"location":"Portland","temperature":54.6},{"location":"Seattle","temperature":57.8},{"location":"Boise","temperature":62.0}]'), + ('Without "FROM" => SELECT ''Hello, world.''', '[{"''Hello, world.''":"Hello, world."}]'), + ('All records from Seatle location => SELECT * FROM weather_readings WHERE location = ''Seattle''', '[{"date":"2025-10-22","location":"Seattle","temperature":56.2,"humidity":66},{"date":"2025-10-23","location":"Seattle","temperature":57.8,"humidity":68}]'), + ('All records where humity in range => SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70', '[{"date":"2025-10-22","location":"Seattle","temperature":56.2,"humidity":66},{"date":"2025-10-23","location":"Portland","temperature":54.6,"humidity":70},{"date":"2025-10-23","location":"Seattle","temperature":57.8,"humidity":68}]'), + ('Just location column => SELECT location FROM weather_readings', '[{"location":"Portland"},{"location":"Seattle"},{"location":"Boise"},{"location":"Portland"},{"location":"Seattle"},{"location":"Boise"}]'), + ('Only unique locations => SELECT DISTINCT location FROM weather_readings', '[{"location":"Portland"},{"location":"Seattle"},{"location":"Boise"}]'); +; diff --git a/exercises/concept/intro-select/data.csv b/exercises/concept/intro-select/data.csv new file mode 100644 index 00000000..808ccddf --- /dev/null +++ b/exercises/concept/intro-select/data.csv @@ -0,0 +1,6 @@ +"2025-10-22","Portland",53.1,72 +"2025-10-22","Seattle",56.2,66 +"2025-10-22","Boise",60.4,55 +"2025-10-23","Portland",54.6,70 +"2025-10-23","Seattle",57.8,68 +"2025-10-23","Boise",62.0,58 diff --git a/exercises/concept/intro-select/intro-select.sql b/exercises/concept/intro-select/intro-select.sql new file mode 100644 index 00000000..265301d8 --- /dev/null +++ b/exercises/concept/intro-select/intro-select.sql @@ -0,0 +1,14 @@ +SELECT * FROM weather_readings; + +SELECT location, temperature FROM weather_readings; + +-- This one will fail on purpose +SELECT 'Hello, world.' AS say_hi; + +SELECT * FROM weather_readings WHERE location = 'Seattle'; + +SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70; + +SELECT location FROM weather_readings; + +SELECT DISTINCT location FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select_test.sql b/exercises/concept/intro-select/intro-select_test.sql new file mode 100644 index 00000000..6010d111 --- /dev/null +++ b/exercises/concept/intro-select/intro-select_test.sql @@ -0,0 +1,85 @@ +-- Create database: +.read ./create_fixture.sql +-- Read user student solution and save any output as markdown in user_output.md: +.mode markdown +.output user_output.md +.echo on +.read ./intro-select.sql +.echo off +.output +.shell sed -i 1d user_output.md + +-- Re-run stub file to collect the results as json arrays +.mode json +.output outputs.txt +.read ./intro-select.sql +.output +-- Creating the results table from the outputs.txt file +DROP TABLE IF EXISTS outputs; +CREATE TEMPORARY TABLE outputs (line TEXT NOT NULL); +.mode tabs +.import ./outputs.txt outputs +DROP TABLE IF EXISTS results; +CREATE TABLE results (result TEXT NOT NULL); +WITH inputs (input) AS ( + SELECT JSON(PRINTF('[%s]', GROUP_CONCAT(RTRIM(TRIM(line), ','), ','))) + FROM outputs +) +INSERT INTO results (result) +SELECT j.value + FROM inputs, JSON_EACH(input) j +; + +-- Create a clean testing environment: +.read ./create_test_table.sql +-- Comparison of user input and the tests updates the status for each test: +UPDATE tests + SET status = 'pass' + FROM (SELECT result FROM results) AS actual + WHERE NOT EXISTS ( + SELECT key, value, type, path + FROM JSON_TREE(result) + WHERE type NOT IN ('array', 'object') + EXCEPT + SELECT key, value, type, path + FROM JSON_TREE(expected) + WHERE type NOT IN ('array', 'object') + ) + AND NOT EXISTS ( + SELECT key, value, type, path + FROM JSON_TREE(expected) + WHERE type NOT IN ('array', 'object') + EXCEPT + SELECT key, value, type, path + FROM JSON_TREE(result) + WHERE type NOT IN ('array', 'object') + ) +; + +-- Update message for failed tests to give helpful information: +UPDATE tests + -- SET message = 'Result for "' || tests.description || '"' || ' is <' || COALESCE(actual.result, 'NULL') || '> but should be <' || tests.expected || '>' + SET message = 'Result for <"' || tests.description || '">' || ' NOT FOUND' -- need improvements +WHERE tests.status = 'fail'; + +-- Save results to ./output.json (needed by the online test-runner) +.mode json +.once './output.json' +SELECT + description, + status, + message, + output, + test_code, + task_id +FROM + tests; + +-- Display test results in readable form for the student: +.mode table +SELECT + description, + status, + message +FROM + tests; diff --git a/exercises/concept/intro-select/outputs.txt b/exercises/concept/intro-select/outputs.txt new file mode 100644 index 00000000..9e837a4a --- /dev/null +++ b/exercises/concept/intro-select/outputs.txt @@ -0,0 +1,27 @@ +[{"date":"2025-10-22","location":"Portland","temperature":53.10000000000000142,"humidity":72}, +{"date":"2025-10-22","location":"Seattle","temperature":56.20000000000000284,"humidity":66}, +{"date":"2025-10-22","location":"Boise","temperature":60.39999999999999858,"humidity":55}, +{"date":"2025-10-23","location":"Portland","temperature":54.60000000000000142,"humidity":70}, +{"date":"2025-10-23","location":"Seattle","temperature":57.79999999999999716,"humidity":68}, +{"date":"2025-10-23","location":"Boise","temperature":62.0,"humidity":58}] +[{"location":"Portland","temperature":53.10000000000000142}, +{"location":"Seattle","temperature":56.20000000000000284}, +{"location":"Boise","temperature":60.39999999999999858}, +{"location":"Portland","temperature":54.60000000000000142}, +{"location":"Seattle","temperature":57.79999999999999716}, +{"location":"Boise","temperature":62.0}] +[{"say_hi":"Hello, world."}] +[{"date":"2025-10-22","location":"Seattle","temperature":56.20000000000000284,"humidity":66}, +{"date":"2025-10-23","location":"Seattle","temperature":57.79999999999999716,"humidity":68}] +[{"date":"2025-10-22","location":"Seattle","temperature":56.20000000000000284,"humidity":66}, +{"date":"2025-10-23","location":"Portland","temperature":54.60000000000000142,"humidity":70}, +{"date":"2025-10-23","location":"Seattle","temperature":57.79999999999999716,"humidity":68}] +[{"location":"Portland"}, +{"location":"Seattle"}, +{"location":"Boise"}, +{"location":"Portland"}, +{"location":"Seattle"}, +{"location":"Boise"}] +[{"location":"Portland"}, +{"location":"Seattle"}, +{"location":"Boise"}] From 1c3d67fb5c41510d72d64bb55fb74df9c68af8ee Mon Sep 17 00:00:00 2001 From: Todd Schwartz Date: Sat, 1 Nov 2025 07:33:34 -0700 Subject: [PATCH 2/5] Generate textual results --- .../intro-select/create_test_table.sql | 23 ----- .../concept/intro-select/intro-select.sql | 28 ++++++ .../intro-select/intro-select_exemplar.sql | 41 +++++++++ .../intro-select/intro-select_test.sql | 87 ++----------------- exercises/concept/intro-select/outputs.txt | 27 ------ 5 files changed, 78 insertions(+), 128 deletions(-) delete mode 100644 exercises/concept/intro-select/create_test_table.sql create mode 100644 exercises/concept/intro-select/intro-select_exemplar.sql delete mode 100644 exercises/concept/intro-select/outputs.txt diff --git a/exercises/concept/intro-select/create_test_table.sql b/exercises/concept/intro-select/create_test_table.sql deleted file mode 100644 index 7f4bd05f..00000000 --- a/exercises/concept/intro-select/create_test_table.sql +++ /dev/null @@ -1,23 +0,0 @@ -DROP TABLE IF EXISTS tests; -CREATE TABLE IF NOT EXISTS tests ( - description TEXT NOT NULL, - -- The following section is needed by the online test-runner - status TEXT DEFAULT 'fail', - message TEXT, - output TEXT, - test_code TEXT, - task_id INTEGER DEFAULT NULL, - -- Here are columns for the actual tests - expected TEXT NOT NULL -); - -INSERT INTO tests (description, expected) -VALUES - ('ALL records => SELECT * FROM weather_readings', '[{"date":"2025-10-22","location":"Portland","temperature":53.1,"humidity":72},{"date":"2025-10-22","location":"Seattle","temperature":56.2,"humidity":66},{"date":"2025-10-22","location":"Boise","temperature":60.4,"humidity":55},{"date":"2025-10-23","location":"Portland","temperature":54.6,"humidity":70},{"date":"2025-10-23","location":"Seattle","temperature":57.8,"humidity":68},{"date":"2025-10-23","location":"Boise","temperature":62.0,"humidity":58}]'), - ('Just location and temperature columns => SELECT location, temperature FROM weather_readings', '[{"location":"Portland","temperature":53.1},{"location":"Seattle","temperature":56.2},{"location":"Boise","temperature":60.4},{"location":"Portland","temperature":54.6},{"location":"Seattle","temperature":57.8},{"location":"Boise","temperature":62.0}]'), - ('Without "FROM" => SELECT ''Hello, world.''', '[{"''Hello, world.''":"Hello, world."}]'), - ('All records from Seatle location => SELECT * FROM weather_readings WHERE location = ''Seattle''', '[{"date":"2025-10-22","location":"Seattle","temperature":56.2,"humidity":66},{"date":"2025-10-23","location":"Seattle","temperature":57.8,"humidity":68}]'), - ('All records where humity in range => SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70', '[{"date":"2025-10-22","location":"Seattle","temperature":56.2,"humidity":66},{"date":"2025-10-23","location":"Portland","temperature":54.6,"humidity":70},{"date":"2025-10-23","location":"Seattle","temperature":57.8,"humidity":68}]'), - ('Just location column => SELECT location FROM weather_readings', '[{"location":"Portland"},{"location":"Seattle"},{"location":"Boise"},{"location":"Portland"},{"location":"Seattle"},{"location":"Boise"}]'), - ('Only unique locations => SELECT DISTINCT location FROM weather_readings', '[{"location":"Portland"},{"location":"Seattle"},{"location":"Boise"}]'); -; diff --git a/exercises/concept/intro-select/intro-select.sql b/exercises/concept/intro-select/intro-select.sql index 265301d8..c3634b46 100644 --- a/exercises/concept/intro-select/intro-select.sql +++ b/exercises/concept/intro-select/intro-select.sql @@ -1,14 +1,42 @@ +.print +.print "All data" +.print "========" +.print SELECT * FROM weather_readings; +.print +.print "Location and temperature only" +.print "=============================" +.print SELECT location, temperature FROM weather_readings; +.print +.print "Greeting" +.print "========" +.print -- This one will fail on purpose SELECT 'Hello, world.' AS say_hi; +.print +.print "Data for Seattle" +.print "================" +.print SELECT * FROM weather_readings WHERE location = 'Seattle'; +.print +.print "Data with humidity constraints" +.print "==============================" +.print SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70; +.print +.print "Locations" +.print "=========" +.print SELECT location FROM weather_readings; +.print +.print "Unique locations" +.print "================" +.print SELECT DISTINCT location FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select_exemplar.sql b/exercises/concept/intro-select/intro-select_exemplar.sql new file mode 100644 index 00000000..d5859e11 --- /dev/null +++ b/exercises/concept/intro-select/intro-select_exemplar.sql @@ -0,0 +1,41 @@ +.print +.print "All data" +.print "========" +.print +SELECT * FROM weather_readings; + +.print +.print "Location and temperature only" +.print "=============================" +.print +SELECT location, temperature FROM weather_readings; + +.print +.print "Greeting" +.print "========" +.print +SELECT 'Hello, world.'; + +.print +.print "Data for Seattle" +.print "================" +.print +SELECT * FROM weather_readings WHERE location = 'Seattle'; + +.print +.print "Data with humidity constraints" +.print "==============================" +.print +SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70; + +.print +.print "Locations" +.print "=========" +.print +SELECT location FROM weather_readings; + +.print +.print "Unique locations" +.print "================" +.print +SELECT DISTINCT location FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select_test.sql b/exercises/concept/intro-select/intro-select_test.sql index 6010d111..8a479edb 100644 --- a/exercises/concept/intro-select/intro-select_test.sql +++ b/exercises/concept/intro-select/intro-select_test.sql @@ -1,85 +1,16 @@ -- Create database: .read ./create_fixture.sql --- Read user student solution and save any output as markdown in user_output.md: -.mode markdown -.output user_output.md -.echo on -.read ./intro-select.sql -.echo off -.output -.shell sed -i 1d user_output.md --- Re-run stub file to collect the results as json arrays -.mode json -.output outputs.txt -.read ./intro-select.sql -.output --- Creating the results table from the outputs.txt file -DROP TABLE IF EXISTS outputs; -CREATE TEMPORARY TABLE outputs (line TEXT NOT NULL); -.mode tabs -.import ./outputs.txt outputs -DROP TABLE IF EXISTS results; -CREATE TABLE results (result TEXT NOT NULL); -WITH inputs (input) AS ( - SELECT JSON(PRINTF('[%s]', GROUP_CONCAT(RTRIM(TRIM(line), ','), ','))) - FROM outputs -) -INSERT INTO results (result) -SELECT j.value - FROM inputs, JSON_EACH(input) j -; +.mode columns --- Create a clean testing environment: -.read ./create_test_table.sql --- Comparison of user input and the tests updates the status for each test: -UPDATE tests - SET status = 'pass' - FROM (SELECT result FROM results) AS actual - WHERE NOT EXISTS ( - SELECT key, value, type, path - FROM JSON_TREE(result) - WHERE type NOT IN ('array', 'object') - EXCEPT - SELECT key, value, type, path - FROM JSON_TREE(expected) - WHERE type NOT IN ('array', 'object') - ) - AND NOT EXISTS ( - SELECT key, value, type, path - FROM JSON_TREE(expected) - WHERE type NOT IN ('array', 'object') - EXCEPT - SELECT key, value, type, path - FROM JSON_TREE(result) - WHERE type NOT IN ('array', 'object') - ) -; +-- Generate expected output +.output expected_output.txt +.read ./intro-select_exemplar.sql --- Update message for failed tests to give helpful information: -UPDATE tests - -- SET message = 'Result for "' || tests.description || '"' || ' is <' || COALESCE(actual.result, 'NULL') || '> but should be <' || tests.expected || '>' - SET message = 'Result for <"' || tests.description || '">' || ' NOT FOUND' -- need improvements -WHERE tests.status = 'fail'; +-- Run user solution +.output user_output.txt +.read ./intro-select.sql --- Save results to ./output.json (needed by the online test-runner) -.mode json -.once './output.json' -SELECT - description, - status, - message, - output, - test_code, - task_id -FROM - tests; +-- Compare expected vs actual +.shell diff expected_output.txt user_output.txt --- Display test results in readable form for the student: -.mode table -SELECT - description, - status, - message -FROM - tests; diff --git a/exercises/concept/intro-select/outputs.txt b/exercises/concept/intro-select/outputs.txt deleted file mode 100644 index 9e837a4a..00000000 --- a/exercises/concept/intro-select/outputs.txt +++ /dev/null @@ -1,27 +0,0 @@ -[{"date":"2025-10-22","location":"Portland","temperature":53.10000000000000142,"humidity":72}, -{"date":"2025-10-22","location":"Seattle","temperature":56.20000000000000284,"humidity":66}, -{"date":"2025-10-22","location":"Boise","temperature":60.39999999999999858,"humidity":55}, -{"date":"2025-10-23","location":"Portland","temperature":54.60000000000000142,"humidity":70}, -{"date":"2025-10-23","location":"Seattle","temperature":57.79999999999999716,"humidity":68}, -{"date":"2025-10-23","location":"Boise","temperature":62.0,"humidity":58}] -[{"location":"Portland","temperature":53.10000000000000142}, -{"location":"Seattle","temperature":56.20000000000000284}, -{"location":"Boise","temperature":60.39999999999999858}, -{"location":"Portland","temperature":54.60000000000000142}, -{"location":"Seattle","temperature":57.79999999999999716}, -{"location":"Boise","temperature":62.0}] -[{"say_hi":"Hello, world."}] -[{"date":"2025-10-22","location":"Seattle","temperature":56.20000000000000284,"humidity":66}, -{"date":"2025-10-23","location":"Seattle","temperature":57.79999999999999716,"humidity":68}] -[{"date":"2025-10-22","location":"Seattle","temperature":56.20000000000000284,"humidity":66}, -{"date":"2025-10-23","location":"Portland","temperature":54.60000000000000142,"humidity":70}, -{"date":"2025-10-23","location":"Seattle","temperature":57.79999999999999716,"humidity":68}] -[{"location":"Portland"}, -{"location":"Seattle"}, -{"location":"Boise"}, -{"location":"Portland"}, -{"location":"Seattle"}, -{"location":"Boise"}] -[{"location":"Portland"}, -{"location":"Seattle"}, -{"location":"Boise"}] From 93bc0008c5f1348089f466593f886d3b7d4925b8 Mon Sep 17 00:00:00 2001 From: Todd Schwartz Date: Sat, 1 Nov 2025 08:08:07 -0700 Subject: [PATCH 3/5] Move each SELECT to separate file --- .../intro-select/intro-select-task1.sql | 1 + .../intro-select-task1_exemplar.sql | 1 + .../intro-select/intro-select-task2.sql | 1 + .../intro-select-task2_exemplar.sql | 1 + .../intro-select/intro-select-task3.sql | 2 + .../intro-select-task3_exemplar.sql | 1 + .../intro-select/intro-select-task4.sql | 1 + .../intro-select-task4_exemplar.sql | 1 + .../intro-select/intro-select-task5.sql | 1 + .../intro-select-task5_exemplar.sql | 1 + .../intro-select/intro-select-task6.sql | 1 + .../intro-select-task6_exemplar.sql | 1 + .../concept/intro-select/intro-select.sql | 42 ---------- .../intro-select/intro-select_exemplar.sql | 41 ---------- .../intro-select/intro-select_test.sql | 77 ++++++++++++++++++- 15 files changed, 87 insertions(+), 86 deletions(-) create mode 100644 exercises/concept/intro-select/intro-select-task1.sql create mode 100644 exercises/concept/intro-select/intro-select-task1_exemplar.sql create mode 100644 exercises/concept/intro-select/intro-select-task2.sql create mode 100644 exercises/concept/intro-select/intro-select-task2_exemplar.sql create mode 100644 exercises/concept/intro-select/intro-select-task3.sql create mode 100644 exercises/concept/intro-select/intro-select-task3_exemplar.sql create mode 100644 exercises/concept/intro-select/intro-select-task4.sql create mode 100644 exercises/concept/intro-select/intro-select-task4_exemplar.sql create mode 100644 exercises/concept/intro-select/intro-select-task5.sql create mode 100644 exercises/concept/intro-select/intro-select-task5_exemplar.sql create mode 100644 exercises/concept/intro-select/intro-select-task6.sql create mode 100644 exercises/concept/intro-select/intro-select-task6_exemplar.sql delete mode 100644 exercises/concept/intro-select/intro-select.sql delete mode 100644 exercises/concept/intro-select/intro-select_exemplar.sql diff --git a/exercises/concept/intro-select/intro-select-task1.sql b/exercises/concept/intro-select/intro-select-task1.sql new file mode 100644 index 00000000..ca7640a1 --- /dev/null +++ b/exercises/concept/intro-select/intro-select-task1.sql @@ -0,0 +1 @@ +SELECT * FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select-task1_exemplar.sql b/exercises/concept/intro-select/intro-select-task1_exemplar.sql new file mode 100644 index 00000000..ca7640a1 --- /dev/null +++ b/exercises/concept/intro-select/intro-select-task1_exemplar.sql @@ -0,0 +1 @@ +SELECT * FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select-task2.sql b/exercises/concept/intro-select/intro-select-task2.sql new file mode 100644 index 00000000..93b757f2 --- /dev/null +++ b/exercises/concept/intro-select/intro-select-task2.sql @@ -0,0 +1 @@ +SELECT location, temperature FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select-task2_exemplar.sql b/exercises/concept/intro-select/intro-select-task2_exemplar.sql new file mode 100644 index 00000000..93b757f2 --- /dev/null +++ b/exercises/concept/intro-select/intro-select-task2_exemplar.sql @@ -0,0 +1 @@ +SELECT location, temperature FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select-task3.sql b/exercises/concept/intro-select/intro-select-task3.sql new file mode 100644 index 00000000..c60b7b89 --- /dev/null +++ b/exercises/concept/intro-select/intro-select-task3.sql @@ -0,0 +1,2 @@ +-- Expected to fail +SELECT 'Hello, world.' AS say_hi; diff --git a/exercises/concept/intro-select/intro-select-task3_exemplar.sql b/exercises/concept/intro-select/intro-select-task3_exemplar.sql new file mode 100644 index 00000000..215327a6 --- /dev/null +++ b/exercises/concept/intro-select/intro-select-task3_exemplar.sql @@ -0,0 +1 @@ +SELECT 'Hello, world.'; diff --git a/exercises/concept/intro-select/intro-select-task4.sql b/exercises/concept/intro-select/intro-select-task4.sql new file mode 100644 index 00000000..9383fe0d --- /dev/null +++ b/exercises/concept/intro-select/intro-select-task4.sql @@ -0,0 +1 @@ +SELECT * FROM weather_readings WHERE location = 'Seattle'; diff --git a/exercises/concept/intro-select/intro-select-task4_exemplar.sql b/exercises/concept/intro-select/intro-select-task4_exemplar.sql new file mode 100644 index 00000000..9383fe0d --- /dev/null +++ b/exercises/concept/intro-select/intro-select-task4_exemplar.sql @@ -0,0 +1 @@ +SELECT * FROM weather_readings WHERE location = 'Seattle'; diff --git a/exercises/concept/intro-select/intro-select-task5.sql b/exercises/concept/intro-select/intro-select-task5.sql new file mode 100644 index 00000000..82da3538 --- /dev/null +++ b/exercises/concept/intro-select/intro-select-task5.sql @@ -0,0 +1 @@ +SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70; diff --git a/exercises/concept/intro-select/intro-select-task5_exemplar.sql b/exercises/concept/intro-select/intro-select-task5_exemplar.sql new file mode 100644 index 00000000..82da3538 --- /dev/null +++ b/exercises/concept/intro-select/intro-select-task5_exemplar.sql @@ -0,0 +1 @@ +SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70; diff --git a/exercises/concept/intro-select/intro-select-task6.sql b/exercises/concept/intro-select/intro-select-task6.sql new file mode 100644 index 00000000..442c8046 --- /dev/null +++ b/exercises/concept/intro-select/intro-select-task6.sql @@ -0,0 +1 @@ +SELECT DISTINCT location FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select-task6_exemplar.sql b/exercises/concept/intro-select/intro-select-task6_exemplar.sql new file mode 100644 index 00000000..442c8046 --- /dev/null +++ b/exercises/concept/intro-select/intro-select-task6_exemplar.sql @@ -0,0 +1 @@ +SELECT DISTINCT location FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select.sql b/exercises/concept/intro-select/intro-select.sql deleted file mode 100644 index c3634b46..00000000 --- a/exercises/concept/intro-select/intro-select.sql +++ /dev/null @@ -1,42 +0,0 @@ -.print -.print "All data" -.print "========" -.print -SELECT * FROM weather_readings; - -.print -.print "Location and temperature only" -.print "=============================" -.print -SELECT location, temperature FROM weather_readings; - -.print -.print "Greeting" -.print "========" -.print --- This one will fail on purpose -SELECT 'Hello, world.' AS say_hi; - -.print -.print "Data for Seattle" -.print "================" -.print -SELECT * FROM weather_readings WHERE location = 'Seattle'; - -.print -.print "Data with humidity constraints" -.print "==============================" -.print -SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70; - -.print -.print "Locations" -.print "=========" -.print -SELECT location FROM weather_readings; - -.print -.print "Unique locations" -.print "================" -.print -SELECT DISTINCT location FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select_exemplar.sql b/exercises/concept/intro-select/intro-select_exemplar.sql deleted file mode 100644 index d5859e11..00000000 --- a/exercises/concept/intro-select/intro-select_exemplar.sql +++ /dev/null @@ -1,41 +0,0 @@ -.print -.print "All data" -.print "========" -.print -SELECT * FROM weather_readings; - -.print -.print "Location and temperature only" -.print "=============================" -.print -SELECT location, temperature FROM weather_readings; - -.print -.print "Greeting" -.print "========" -.print -SELECT 'Hello, world.'; - -.print -.print "Data for Seattle" -.print "================" -.print -SELECT * FROM weather_readings WHERE location = 'Seattle'; - -.print -.print "Data with humidity constraints" -.print "==============================" -.print -SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70; - -.print -.print "Locations" -.print "=========" -.print -SELECT location FROM weather_readings; - -.print -.print "Unique locations" -.print "================" -.print -SELECT DISTINCT location FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select_test.sql b/exercises/concept/intro-select/intro-select_test.sql index 8a479edb..a108fbb1 100644 --- a/exercises/concept/intro-select/intro-select_test.sql +++ b/exercises/concept/intro-select/intro-select_test.sql @@ -5,11 +5,82 @@ -- Generate expected output .output expected_output.txt -.read ./intro-select_exemplar.sql --- Run user solution +.print +.print "All data" +.print "========" +.print +.read intro-select-task1_exemplar.sql + +.print +.print "Location and temperature only" +.print "=============================" +.print +.read intro-select-task2_exemplar.sql + +.print +.print "Greeting" +.print "========" +.print +.read intro-select-task3_exemplar.sql + +.print +.print "Data for Seattle" +.print "================" +.print +.read intro-select-task4_exemplar.sql + +.print +.print "Data with humidity constraints" +.print "==============================" +.print +.read intro-select-task5_exemplar.sql + +.print +.print "Locations" +.print "=========" +.print +.read intro-select-task6_exemplar.sql + + +-- Run user solutions .output user_output.txt -.read ./intro-select.sql +.print +.print "All data" +.print "========" +.print +.read intro-select-task1.sql + +.print +.print "Location and temperature only" +.print "=============================" +.print +.read intro-select-task2.sql + +.print +.print "Greeting" +.print "========" +.print +.read intro-select-task3.sql + +.print +.print "Data for Seattle" +.print "================" +.print +.read intro-select-task4.sql + +.print +.print "Data with humidity constraints" +.print "==============================" +.print +.read intro-select-task5.sql + +.print +.print "Locations" +.print "=========" +.print +.read intro-select-task6.sql + -- Compare expected vs actual .shell diff expected_output.txt user_output.txt From ac316d11dfd59d918ecad554e2e4b504ae408eb8 Mon Sep 17 00:00:00 2001 From: Todd Schwartz Date: Mon, 3 Nov 2025 16:05:36 -0800 Subject: [PATCH 4/5] Revert "Move each SELECT to separate file" This reverts commit 93bc0008c5f1348089f466593f886d3b7d4925b8. --- .../intro-select/intro-select-task1.sql | 1 - .../intro-select-task1_exemplar.sql | 1 - .../intro-select/intro-select-task2.sql | 1 - .../intro-select-task2_exemplar.sql | 1 - .../intro-select/intro-select-task3.sql | 2 - .../intro-select-task3_exemplar.sql | 1 - .../intro-select/intro-select-task4.sql | 1 - .../intro-select-task4_exemplar.sql | 1 - .../intro-select/intro-select-task5.sql | 1 - .../intro-select-task5_exemplar.sql | 1 - .../intro-select/intro-select-task6.sql | 1 - .../intro-select-task6_exemplar.sql | 1 - .../concept/intro-select/intro-select.sql | 42 ++++++++++ .../intro-select/intro-select_exemplar.sql | 41 ++++++++++ .../intro-select/intro-select_test.sql | 77 +------------------ 15 files changed, 86 insertions(+), 87 deletions(-) delete mode 100644 exercises/concept/intro-select/intro-select-task1.sql delete mode 100644 exercises/concept/intro-select/intro-select-task1_exemplar.sql delete mode 100644 exercises/concept/intro-select/intro-select-task2.sql delete mode 100644 exercises/concept/intro-select/intro-select-task2_exemplar.sql delete mode 100644 exercises/concept/intro-select/intro-select-task3.sql delete mode 100644 exercises/concept/intro-select/intro-select-task3_exemplar.sql delete mode 100644 exercises/concept/intro-select/intro-select-task4.sql delete mode 100644 exercises/concept/intro-select/intro-select-task4_exemplar.sql delete mode 100644 exercises/concept/intro-select/intro-select-task5.sql delete mode 100644 exercises/concept/intro-select/intro-select-task5_exemplar.sql delete mode 100644 exercises/concept/intro-select/intro-select-task6.sql delete mode 100644 exercises/concept/intro-select/intro-select-task6_exemplar.sql create mode 100644 exercises/concept/intro-select/intro-select.sql create mode 100644 exercises/concept/intro-select/intro-select_exemplar.sql diff --git a/exercises/concept/intro-select/intro-select-task1.sql b/exercises/concept/intro-select/intro-select-task1.sql deleted file mode 100644 index ca7640a1..00000000 --- a/exercises/concept/intro-select/intro-select-task1.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT * FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select-task1_exemplar.sql b/exercises/concept/intro-select/intro-select-task1_exemplar.sql deleted file mode 100644 index ca7640a1..00000000 --- a/exercises/concept/intro-select/intro-select-task1_exemplar.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT * FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select-task2.sql b/exercises/concept/intro-select/intro-select-task2.sql deleted file mode 100644 index 93b757f2..00000000 --- a/exercises/concept/intro-select/intro-select-task2.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT location, temperature FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select-task2_exemplar.sql b/exercises/concept/intro-select/intro-select-task2_exemplar.sql deleted file mode 100644 index 93b757f2..00000000 --- a/exercises/concept/intro-select/intro-select-task2_exemplar.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT location, temperature FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select-task3.sql b/exercises/concept/intro-select/intro-select-task3.sql deleted file mode 100644 index c60b7b89..00000000 --- a/exercises/concept/intro-select/intro-select-task3.sql +++ /dev/null @@ -1,2 +0,0 @@ --- Expected to fail -SELECT 'Hello, world.' AS say_hi; diff --git a/exercises/concept/intro-select/intro-select-task3_exemplar.sql b/exercises/concept/intro-select/intro-select-task3_exemplar.sql deleted file mode 100644 index 215327a6..00000000 --- a/exercises/concept/intro-select/intro-select-task3_exemplar.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT 'Hello, world.'; diff --git a/exercises/concept/intro-select/intro-select-task4.sql b/exercises/concept/intro-select/intro-select-task4.sql deleted file mode 100644 index 9383fe0d..00000000 --- a/exercises/concept/intro-select/intro-select-task4.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT * FROM weather_readings WHERE location = 'Seattle'; diff --git a/exercises/concept/intro-select/intro-select-task4_exemplar.sql b/exercises/concept/intro-select/intro-select-task4_exemplar.sql deleted file mode 100644 index 9383fe0d..00000000 --- a/exercises/concept/intro-select/intro-select-task4_exemplar.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT * FROM weather_readings WHERE location = 'Seattle'; diff --git a/exercises/concept/intro-select/intro-select-task5.sql b/exercises/concept/intro-select/intro-select-task5.sql deleted file mode 100644 index 82da3538..00000000 --- a/exercises/concept/intro-select/intro-select-task5.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70; diff --git a/exercises/concept/intro-select/intro-select-task5_exemplar.sql b/exercises/concept/intro-select/intro-select-task5_exemplar.sql deleted file mode 100644 index 82da3538..00000000 --- a/exercises/concept/intro-select/intro-select-task5_exemplar.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70; diff --git a/exercises/concept/intro-select/intro-select-task6.sql b/exercises/concept/intro-select/intro-select-task6.sql deleted file mode 100644 index 442c8046..00000000 --- a/exercises/concept/intro-select/intro-select-task6.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT DISTINCT location FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select-task6_exemplar.sql b/exercises/concept/intro-select/intro-select-task6_exemplar.sql deleted file mode 100644 index 442c8046..00000000 --- a/exercises/concept/intro-select/intro-select-task6_exemplar.sql +++ /dev/null @@ -1 +0,0 @@ -SELECT DISTINCT location FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select.sql b/exercises/concept/intro-select/intro-select.sql new file mode 100644 index 00000000..c3634b46 --- /dev/null +++ b/exercises/concept/intro-select/intro-select.sql @@ -0,0 +1,42 @@ +.print +.print "All data" +.print "========" +.print +SELECT * FROM weather_readings; + +.print +.print "Location and temperature only" +.print "=============================" +.print +SELECT location, temperature FROM weather_readings; + +.print +.print "Greeting" +.print "========" +.print +-- This one will fail on purpose +SELECT 'Hello, world.' AS say_hi; + +.print +.print "Data for Seattle" +.print "================" +.print +SELECT * FROM weather_readings WHERE location = 'Seattle'; + +.print +.print "Data with humidity constraints" +.print "==============================" +.print +SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70; + +.print +.print "Locations" +.print "=========" +.print +SELECT location FROM weather_readings; + +.print +.print "Unique locations" +.print "================" +.print +SELECT DISTINCT location FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select_exemplar.sql b/exercises/concept/intro-select/intro-select_exemplar.sql new file mode 100644 index 00000000..d5859e11 --- /dev/null +++ b/exercises/concept/intro-select/intro-select_exemplar.sql @@ -0,0 +1,41 @@ +.print +.print "All data" +.print "========" +.print +SELECT * FROM weather_readings; + +.print +.print "Location and temperature only" +.print "=============================" +.print +SELECT location, temperature FROM weather_readings; + +.print +.print "Greeting" +.print "========" +.print +SELECT 'Hello, world.'; + +.print +.print "Data for Seattle" +.print "================" +.print +SELECT * FROM weather_readings WHERE location = 'Seattle'; + +.print +.print "Data with humidity constraints" +.print "==============================" +.print +SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70; + +.print +.print "Locations" +.print "=========" +.print +SELECT location FROM weather_readings; + +.print +.print "Unique locations" +.print "================" +.print +SELECT DISTINCT location FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select_test.sql b/exercises/concept/intro-select/intro-select_test.sql index a108fbb1..8a479edb 100644 --- a/exercises/concept/intro-select/intro-select_test.sql +++ b/exercises/concept/intro-select/intro-select_test.sql @@ -5,82 +5,11 @@ -- Generate expected output .output expected_output.txt +.read ./intro-select_exemplar.sql -.print -.print "All data" -.print "========" -.print -.read intro-select-task1_exemplar.sql - -.print -.print "Location and temperature only" -.print "=============================" -.print -.read intro-select-task2_exemplar.sql - -.print -.print "Greeting" -.print "========" -.print -.read intro-select-task3_exemplar.sql - -.print -.print "Data for Seattle" -.print "================" -.print -.read intro-select-task4_exemplar.sql - -.print -.print "Data with humidity constraints" -.print "==============================" -.print -.read intro-select-task5_exemplar.sql - -.print -.print "Locations" -.print "=========" -.print -.read intro-select-task6_exemplar.sql - - --- Run user solutions +-- Run user solution .output user_output.txt -.print -.print "All data" -.print "========" -.print -.read intro-select-task1.sql - -.print -.print "Location and temperature only" -.print "=============================" -.print -.read intro-select-task2.sql - -.print -.print "Greeting" -.print "========" -.print -.read intro-select-task3.sql - -.print -.print "Data for Seattle" -.print "================" -.print -.read intro-select-task4.sql - -.print -.print "Data with humidity constraints" -.print "==============================" -.print -.read intro-select-task5.sql - -.print -.print "Locations" -.print "=========" -.print -.read intro-select-task6.sql - +.read ./intro-select.sql -- Compare expected vs actual .shell diff expected_output.txt user_output.txt From 581bda6f8e41cc794aa9690fb4d9bc2495221b57 Mon Sep 17 00:00:00 2001 From: Todd Schwartz Date: Tue, 4 Nov 2025 18:17:44 -0800 Subject: [PATCH 5/5] Evaluate results in python --- exercises/concept/intro-select/evaluate.py | 60 +++++++++++++++++ .../concept/intro-select/intro-select.sql | 28 -------- .../intro-select/intro-select_exemplar.sql | 41 ------------ .../intro-select/intro-select_test.sql | 9 +-- exercises/concept/intro-select/test_data.json | 64 +++++++++++++++++++ 5 files changed, 126 insertions(+), 76 deletions(-) create mode 100644 exercises/concept/intro-select/evaluate.py delete mode 100644 exercises/concept/intro-select/intro-select_exemplar.sql create mode 100644 exercises/concept/intro-select/test_data.json diff --git a/exercises/concept/intro-select/evaluate.py b/exercises/concept/intro-select/evaluate.py new file mode 100644 index 00000000..0cedc7b7 --- /dev/null +++ b/exercises/concept/intro-select/evaluate.py @@ -0,0 +1,60 @@ +from pathlib import Path +import json +import sys + + +def gather_results(filename): + text = Path(filename).read_text() + list_start_indices = find_all_occurrences('[', text) + list_end_indices = find_all_occurrences(']', text) + return [ + json.loads(text[begin:end+1]) + for begin, end in zip(list_start_indices, list_end_indices) + ] + + +def find_all_occurrences(char, string): + return [i for i, c, in enumerate(string) if c == char] + + +def format_diff(expected, actual): + return ( + f"\tExpected:\n" + f"\t\t{expected}\n" + f"\tActual:\n" + f"\t\t{actual}" + ) + +def report_results(all_test_data, actual_results): + results = [] + for test_data, actual in zip(all_test_data, actual_results): + result = {'description': test_data['description']} + if test_data['expected'] == actual: + result['status'] = 'pass' + else: + result['status'] = 'fail' + result['message'] = "Expected: " + json.dumps(test_data['expected']) + result['output'] = "Actual: " + json.dumps(actual) + results.append(result) + return make_result_report(results) + + +def make_result_report(results): + status = 'pass' if all(r['status'] == 'pass' for r in results) else 'fail' + return { + "version": 3, + "status": status, + "tests": results + } + + +def main(): + test_data_filename, user_output_filename = sys.argv[1:3] + test_data = json.loads(Path(test_data_filename).read_text()) + actual_results = gather_results(user_output_filename) + results = report_results(test_data, actual_results) + Path('results.json').write_text(json.dumps(results, indent=2)) + + +if __name__ == '__main__': + main() diff --git a/exercises/concept/intro-select/intro-select.sql b/exercises/concept/intro-select/intro-select.sql index c3634b46..265301d8 100644 --- a/exercises/concept/intro-select/intro-select.sql +++ b/exercises/concept/intro-select/intro-select.sql @@ -1,42 +1,14 @@ -.print -.print "All data" -.print "========" -.print SELECT * FROM weather_readings; -.print -.print "Location and temperature only" -.print "=============================" -.print SELECT location, temperature FROM weather_readings; -.print -.print "Greeting" -.print "========" -.print -- This one will fail on purpose SELECT 'Hello, world.' AS say_hi; -.print -.print "Data for Seattle" -.print "================" -.print SELECT * FROM weather_readings WHERE location = 'Seattle'; -.print -.print "Data with humidity constraints" -.print "==============================" -.print SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70; -.print -.print "Locations" -.print "=========" -.print SELECT location FROM weather_readings; -.print -.print "Unique locations" -.print "================" -.print SELECT DISTINCT location FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select_exemplar.sql b/exercises/concept/intro-select/intro-select_exemplar.sql deleted file mode 100644 index d5859e11..00000000 --- a/exercises/concept/intro-select/intro-select_exemplar.sql +++ /dev/null @@ -1,41 +0,0 @@ -.print -.print "All data" -.print "========" -.print -SELECT * FROM weather_readings; - -.print -.print "Location and temperature only" -.print "=============================" -.print -SELECT location, temperature FROM weather_readings; - -.print -.print "Greeting" -.print "========" -.print -SELECT 'Hello, world.'; - -.print -.print "Data for Seattle" -.print "================" -.print -SELECT * FROM weather_readings WHERE location = 'Seattle'; - -.print -.print "Data with humidity constraints" -.print "==============================" -.print -SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70; - -.print -.print "Locations" -.print "=========" -.print -SELECT location FROM weather_readings; - -.print -.print "Unique locations" -.print "================" -.print -SELECT DISTINCT location FROM weather_readings; diff --git a/exercises/concept/intro-select/intro-select_test.sql b/exercises/concept/intro-select/intro-select_test.sql index 8a479edb..dc1fde83 100644 --- a/exercises/concept/intro-select/intro-select_test.sql +++ b/exercises/concept/intro-select/intro-select_test.sql @@ -1,16 +1,11 @@ -- Create database: .read ./create_fixture.sql -.mode columns - --- Generate expected output -.output expected_output.txt -.read ./intro-select_exemplar.sql +.mode json -- Run user solution .output user_output.txt .read ./intro-select.sql -- Compare expected vs actual -.shell diff expected_output.txt user_output.txt - +.shell python evaluate.py test_data.json user_output.txt diff --git a/exercises/concept/intro-select/test_data.json b/exercises/concept/intro-select/test_data.json new file mode 100644 index 00000000..e150eeaa --- /dev/null +++ b/exercises/concept/intro-select/test_data.json @@ -0,0 +1,64 @@ +[ + { + "description": "ALL records => SELECT * FROM weather_readings", + "expected": [ + {"date":"2025-10-22","location":"Portland","temperature":53.1,"humidity":72}, + {"date":"2025-10-22","location":"Seattle","temperature":56.2,"humidity":66}, + {"date":"2025-10-22","location":"Boise","temperature":60.4,"humidity":55}, + {"date":"2025-10-23","location":"Portland","temperature":54.6,"humidity":70}, + {"date":"2025-10-23","location":"Seattle","temperature":57.79999999999999,"humidity":68}, + {"date":"2025-10-23","location":"Boise","temperature":62.0,"humidity":58} + ] + }, + { + "description": "Just location and temperature columns => SELECT location, temperature FROM weather_readings", + "expected": [ + {"location":"Portland","temperature":53.1}, + {"location":"Seattle","temperature":56.2}, + {"location":"Boise","temperature":60.4}, + {"location":"Portland","temperature":54.6}, + {"location":"Seattle","temperature":57.79999999999999}, + {"location":"Boise","temperature":62.0} + ] + }, + { + "description": "Without \"FROM\" => SELECT 'Hello, world.'", + "expected": [ + {"'Hello, world.'":"Hello, world."} + ] + }, + { + "description": "All records from Seatle location => SELECT * FROM weather_readings WHERE location = 'Seattle'", + "expected": [ + {"date":"2025-10-22","location":"Seattle","temperature":56.2,"humidity":66}, + {"date":"2025-10-23","location":"Seattle","temperature":57.79999999999999,"humidity":68} + ] + }, + { + "description": "All records where humidity in range => SELECT * FROM weather_readings WHERE humidity BETWEEN 60 AND 70", + "expected": [ + {"date":"2025-10-22","location":"Seattle","temperature":56.2,"humidity":66}, + {"date":"2025-10-23","location":"Portland","temperature":54.6,"humidity":70}, + {"date":"2025-10-23","location":"Seattle","temperature":57.79999999999999,"humidity":68} + ] + }, + { + "description": "Just location column => SELECT location FROM weather_readings", + "expected": [ + {"location":"Portland"}, + {"location":"Seattle"}, + {"location":"Boise"}, + {"location":"Portland"}, + {"location":"Seattle"}, + {"location":"Boise"} + ] + }, + { + "description": "Only unique locations => SELECT DISTINCT location FROM weather_readings", + "expected": [ + {"location":"Portland"}, + {"location":"Seattle"}, + {"location":"Boise"} + ] + } +] \ No newline at end of file