| 1 | #include "catch.hpp" |
| 2 | #include "duckdb/common/fstream_util.hpp" |
| 3 | #include "duckdb/common/gzip_stream.hpp" |
| 4 | #include "test_helpers.hpp" |
| 5 | |
| 6 | #include <fstream> |
| 7 | #include <sstream> |
| 8 | |
| 9 | using namespace duckdb; |
| 10 | using namespace std; |
| 11 | |
| 12 | TEST_CASE("Run Sakila test queries" , "[sakila][.]" ) { |
| 13 | unique_ptr<QueryResult> result; |
| 14 | DuckDB db(nullptr); |
| 15 | Connection con(db); |
| 16 | |
| 17 | string token; |
| 18 | |
| 19 | // read schema |
| 20 | fstream schema_file; |
| 21 | FstreamUtil::OpenFile("test/sakila/duckdb-sakila-schema.sql" , schema_file); |
| 22 | |
| 23 | // woo hacks, use getline to separate queries |
| 24 | while (getline(schema_file, token, ';')) { |
| 25 | REQUIRE_NO_FAIL(con.Query(token)); |
| 26 | } |
| 27 | |
| 28 | // read data |
| 29 | GzipStream data_file("test/sakila/duckdb-sakila-insert-data.sql.gz" ); |
| 30 | while (getline(data_file, token, ';')) { |
| 31 | REQUIRE_NO_FAIL(con.Query(token)); |
| 32 | } |
| 33 | // only enable verification here because of 40k or so inserts above |
| 34 | con.EnableQueryVerification(); |
| 35 | |
| 36 | result = con.Query("SELECT first_name,last_name FROM actor ORDER BY actor_id LIMIT 10" ); |
| 37 | REQUIRE_NO_FAIL(*result); |
| 38 | REQUIRE(CHECK_COLUMN( |
| 39 | result, 0, {"PENELOPE" , "NICK" , "ED" , "JENNIFER" , "JOHNNY" , "BETTE" , "GRACE" , "MATTHEW" , "JOE" , "CHRISTIAN" })); |
| 40 | REQUIRE(CHECK_COLUMN(result, 1, |
| 41 | {"GUINESS" , "WAHLBERG" , "CHASE" , "DAVIS" , "LOLLOBRIGIDA" , "NICHOLSON" , "MOSTEL" , "JOHANSSON" , |
| 42 | "SWANK" , "GABLE" })); |
| 43 | |
| 44 | result = con.Query("SELECT actor_id, first_name, last_name FROM actor WHERE first_name='JOE' ORDER BY actor_id" ); |
| 45 | REQUIRE_NO_FAIL(*result); |
| 46 | REQUIRE(CHECK_COLUMN(result, 0, {9})); |
| 47 | REQUIRE(CHECK_COLUMN(result, 1, {"JOE" })); |
| 48 | REQUIRE(CHECK_COLUMN(result, 2, {"SWANK" })); |
| 49 | |
| 50 | result = |
| 51 | con.Query("SELECT actor_id, first_name, last_name FROM actor WHERE last_name LIKE '%GEN%' ORDER BY actor_id" ); |
| 52 | REQUIRE_NO_FAIL(*result); |
| 53 | REQUIRE(CHECK_COLUMN(result, 0, {14, 41, 107, 166})); |
| 54 | REQUIRE(CHECK_COLUMN(result, 1, {"VIVIEN" , "JODIE" , "GINA" , "NICK" })); |
| 55 | REQUIRE(CHECK_COLUMN(result, 2, {"BERGEN" , "DEGENERES" , "DEGENERES" , "DEGENERES" })); |
| 56 | |
| 57 | result = con.Query("SELECT country_id, country FROM country WHERE country IN('Afghanistan', 'Bangladesh', 'China') " |
| 58 | "ORDER BY country_id" ); |
| 59 | REQUIRE_NO_FAIL(*result); |
| 60 | REQUIRE(CHECK_COLUMN(result, 0, {1, 12, 23})); |
| 61 | REQUIRE(CHECK_COLUMN(result, 1, {"Afghanistan" , "Bangladesh" , "China" })); |
| 62 | |
| 63 | result = con.Query("SELECT last_name, COUNT(*) as lnc FROM actor GROUP BY last_name HAVING COUNT(*) >=4 ORDER BY " |
| 64 | "lnc desc, last_name" ); |
| 65 | REQUIRE_NO_FAIL(*result); |
| 66 | REQUIRE(CHECK_COLUMN(result, 0, {"KILMER" , "NOLTE" , "TEMPLE" })); |
| 67 | REQUIRE(CHECK_COLUMN(result, 1, {5, 4, 4})); |
| 68 | |
| 69 | result = con.Query("SELECT first_name, last_name, address FROM staff INNER JOIN address ON staff.address_id = " |
| 70 | "address.address_id order by first_name, last_name" ); |
| 71 | REQUIRE_NO_FAIL(*result); |
| 72 | REQUIRE(CHECK_COLUMN(result, 0, {"Jon" , "Mike" })); |
| 73 | REQUIRE(CHECK_COLUMN(result, 1, {"Stephens" , "Hillyer" })); |
| 74 | REQUIRE(CHECK_COLUMN(result, 2, {"1411 Lillydale Drive" , "23 Workhaven Lane" })); |
| 75 | |
| 76 | result = |
| 77 | con.Query("SELECT first_name, last_name, SUM(amount) as total FROM staff INNER JOIN payment ON staff.staff_id " |
| 78 | "= payment.staff_id AND payment_date LIKE '2005-08%' GROUP BY first_name, last_name ORDER BY total" ); |
| 79 | REQUIRE_NO_FAIL(*result); |
| 80 | REQUIRE(CHECK_COLUMN(result, 0, {"Mike" , "Jon" })); |
| 81 | REQUIRE(CHECK_COLUMN(result, 1, {"Hillyer" , "Stephens" })); |
| 82 | REQUIRE(CHECK_COLUMN(result, 2, {11853.65, 12218.48})); |
| 83 | |
| 84 | result = con.Query("SELECT title, COUNT(actor_id) as actor_count FROM film_actor INNER JOIN film ON " |
| 85 | "film_actor.film_id = film.film_id GROUP BY title order by actor_count desc, title limit 10" ); |
| 86 | REQUIRE_NO_FAIL(*result); |
| 87 | REQUIRE(CHECK_COLUMN(result, 0, |
| 88 | {"LAMBS CINCINATTI" , "BOONDOCK BALLROOM" , "CHITTY LOCK" , "CRAZY HOME" , "DRACULA CRYSTAL" , |
| 89 | "MUMMY CREATURES" , "RANDOM GO" , "ARABIA DOGMA" , "HELLFIGHTERS SIERRA" , "LESSON CLEOPATRA" })); |
| 90 | REQUIRE(CHECK_COLUMN(result, 1, {15, 13, 13, 13, 13, 13, 13, 12, 12, 12})); |
| 91 | |
| 92 | result = con.Query("SELECT title, COUNT(title) as copies_available FROM film INNER JOIN inventory ON film.film_id " |
| 93 | "= inventory.film_id WHERE title = 'HUNCHBACK IMPOSSIBLE' GROUP BY title" ); |
| 94 | REQUIRE_NO_FAIL(*result); |
| 95 | REQUIRE(CHECK_COLUMN(result, 0, {"HUNCHBACK IMPOSSIBLE" })); |
| 96 | REQUIRE(CHECK_COLUMN(result, 1, {6})); |
| 97 | |
| 98 | result = con.Query("SELECT first_name, last_name, SUM(amount) as total_paid FROM payment INNER JOIN customer ON " |
| 99 | "payment.customer_id = customer.customer_id GROUP BY first_name, last_name ORDER BY total_paid " |
| 100 | "desc, first_name limit 10" ); |
| 101 | REQUIRE_NO_FAIL(*result); |
| 102 | REQUIRE(CHECK_COLUMN(result, 0, |
| 103 | {"KARL" , "ELEANOR" , "CLARA" , "MARION" , "RHONDA" , "TOMMY" , "WESLEY" , "TIM" , "MARCIA" , "ANA" })); |
| 104 | REQUIRE(CHECK_COLUMN(result, 1, |
| 105 | {"SEAL" , "HUNT" , "SHAW" , "SNYDER" , "KENNEDY" , "COLLAZO" , "BULL" , "CARY" , "DEAN" , "BRADLEY" })); |
| 106 | REQUIRE(CHECK_COLUMN(result, 2, {221.55, 216.54, 195.58, 194.61, 194.61, 186.62, 177.6, 175.61, 175.58, 174.66})); |
| 107 | |
| 108 | result = con.Query( |
| 109 | "SELECT title FROM film WHERE title LIKE 'K%' OR title LIKE 'Q%' AND title IN ( SELECT title FROM film WHERE " |
| 110 | "language_id IN ( SELECT language_id FROM language WHERE name ='English' ) ) ORDER BY title" ); |
| 111 | REQUIRE_NO_FAIL(*result); |
| 112 | REQUIRE(CHECK_COLUMN(result, 0, |
| 113 | {"KANE EXORCIST" , "KARATE MOON" , "KENTUCKIAN GIANT" , "KICK SAVANNAH" , "KILL BROTHERHOOD" , |
| 114 | "KILLER INNOCENT" , "KING EVOLUTION" , "KISS GLORY" , "KISSING DOLLS" , "KNOCK WARLOCK" , |
| 115 | "KRAMER CHOCOLATE" , "KWAI HOMEWARD" , "QUEEN LUKE" , "QUEST MUSSOLINI" , "QUILLS BULL" })); |
| 116 | |
| 117 | result = con.Query("SELECT first_name, last_name FROM actor WHERE actor_id IN ( SELECT actor_id FROM film_actor " |
| 118 | "WHERE film_id IN ( SELECT film_id FROM film WHERE title = 'ALONE TRIP' ) ) ORDER BY actor_id" ); |
| 119 | REQUIRE_NO_FAIL(*result); |
| 120 | REQUIRE(CHECK_COLUMN(result, 0, {"ED" , "KARL" , "UMA" , "WOODY" , "SPENCER" , "CHRIS" , "LAURENCE" , "RENEE" })); |
| 121 | REQUIRE(CHECK_COLUMN(result, 1, {"CHASE" , "BERRY" , "WOOD" , "JOLIE" , "DEPP" , "DEPP" , "BULLOCK" , "BALL" })); |
| 122 | |
| 123 | result = con.Query( |
| 124 | "SELECT first_name, last_name, email FROM customer JOIN address ON (customer.address_id = address.address_id) " |
| 125 | "JOIN city ON (city.city_id = address.city_id) JOIN country ON (country.country_id = city.country_id) WHERE " |
| 126 | "country.country= 'Canada' ORDER BY first_name, last_name" ); |
| 127 | REQUIRE_NO_FAIL(*result); |
| 128 | REQUIRE(CHECK_COLUMN(result, 0, {"CURTIS" , "DARRELL" , "DERRICK" , "LORETTA" , "TROY" })); |
| 129 | REQUIRE(CHECK_COLUMN(result, 1, {"IRBY" , "POWER" , "BOURQUE" , "CARPENTER" , "QUIGLEY" })); |
| 130 | REQUIRE(CHECK_COLUMN(result, 2, |
| 131 | {"CURTIS.IRBY@sakilacustomer.org" , "DARRELL.POWER@sakilacustomer.org" , |
| 132 | "DERRICK.BOURQUE@sakilacustomer.org" , "LORETTA.CARPENTER@sakilacustomer.org" , |
| 133 | "TROY.QUIGLEY@sakilacustomer.org" })); |
| 134 | |
| 135 | result = con.Query("SELECT title FROM film WHERE film_id IN ( SELECT film_id FROM film_category WHERE category_id " |
| 136 | "IN ( SELECT category_id FROM category WHERE name='Family' ) ) ORDER BY film_id LIMIT 10" ); |
| 137 | REQUIRE_NO_FAIL(*result); |
| 138 | REQUIRE( |
| 139 | CHECK_COLUMN(result, 0, |
| 140 | {"AFRICAN EGG" , "APACHE DIVINE" , "ATLANTIS CAUSE" , "BAKED CLEOPATRA" , "BANG KWAI" , |
| 141 | "BEDAZZLED MARRIED" , "BILKO ANONYMOUS" , "BLANKET BEVERLY" , "BLOOD ARGONAUTS" , "BLUES INSTINCT" })); |
| 142 | |
| 143 | result = con.Query("SELECT title, COUNT(rental_id) as rental_count FROM rental JOIN inventory ON " |
| 144 | "(rental.inventory_id = inventory.inventory_id) JOIN film ON (inventory.film_id = film.film_id) " |
| 145 | "GROUP BY film.title ORDER BY COUNT(rental_id) DESC, title limit 10" ); |
| 146 | REQUIRE_NO_FAIL(*result); |
| 147 | REQUIRE( |
| 148 | CHECK_COLUMN(result, 0, |
| 149 | {"BUCKET BROTHERHOOD" , "ROCKETEER MOTHER" , "FORWARD TEMPLE" , "GRIT CLOCKWORK" , "JUGGLER HARDLY" , |
| 150 | "RIDGEMONT SUBMARINE" , "SCALAWAG DUCK" , "APACHE DIVINE" , "GOODFELLAS SALUTE" , "HOBBIT ALIEN" })); |
| 151 | REQUIRE(CHECK_COLUMN(result, 1, {34, 33, 32, 32, 32, 32, 32, 31, 31, 31})); |
| 152 | |
| 153 | result = con.Query("SELECT store.store_id, SUM(amount) as sum_amount FROM store INNER JOIN staff ON store.store_id " |
| 154 | "= staff.store_id INNER JOIN payment ON payment.staff_id = staff.staff_id GROUP BY " |
| 155 | "store.store_id order by sum_amount" ); |
| 156 | REQUIRE_NO_FAIL(*result); |
| 157 | REQUIRE(CHECK_COLUMN(result, 0, {1, 2})); |
| 158 | REQUIRE(CHECK_COLUMN(result, 1, {33489.47, 33927.04})); |
| 159 | |
| 160 | result = con.Query("SELECT store_id, city, country FROM store INNER JOIN address ON store.address_id = " |
| 161 | "address.address_id INNER JOIN city ON city.city_id = address.city_id INNER JOIN country ON " |
| 162 | "country.country_id = city.country_id order by store_id" ); |
| 163 | REQUIRE_NO_FAIL(*result); |
| 164 | REQUIRE(CHECK_COLUMN(result, 0, {1, 2})); |
| 165 | REQUIRE(CHECK_COLUMN(result, 1, {"Lethbridge" , "Woodridge" })); |
| 166 | REQUIRE(CHECK_COLUMN(result, 2, {"Canada" , "Australia" })); |
| 167 | |
| 168 | result = con.Query("SELECT name, SUM(amount) FROM category INNER JOIN film_category ON category.category_id = " |
| 169 | "film_category.category_id INNER JOIN inventory ON film_category.film_id = inventory.film_id " |
| 170 | "INNER JOIN rental ON inventory.inventory_id = rental.inventory_id INNER JOIN payment ON " |
| 171 | "rental.rental_id = payment.rental_id GROUP BY name ORDER BY SUM(amount) DESC LIMIT 5" ); |
| 172 | REQUIRE_NO_FAIL(*result); |
| 173 | REQUIRE(CHECK_COLUMN(result, 0, {"Sports" , "Sci-Fi" , "Animation" , "Drama" , "Comedy" })); |
| 174 | REQUIRE(CHECK_COLUMN(result, 1, {5314.21, 4756.98, 4656.3, 4587.39, 4383.58})); |
| 175 | |
| 176 | // these four queries are equivalent, see https://www.jooq.org/benchmark |
| 177 | |
| 178 | result = con.Query("SELECT first_name, last_name, count(*) FROM actor a JOIN film_actor fa USING (actor_id) WHERE " |
| 179 | "last_name LIKE 'A%' GROUP BY fa.actor_id, a.first_name, a.last_name ORDER BY count(*) DESC" ); |
| 180 | REQUIRE_NO_FAIL(*result); |
| 181 | REQUIRE(CHECK_COLUMN(result, 0, {"KIRSTEN" , "CHRISTIAN" , "ANGELINA" , "KIM" , "CUBA" , "DEBBIE" , "MERYL" })); |
| 182 | REQUIRE(CHECK_COLUMN(result, 1, {"AKROYD" , "AKROYD" , "ASTAIRE" , "ALLEN" , "ALLEN" , "AKROYD" , "ALLEN" })); |
| 183 | REQUIRE(CHECK_COLUMN(result, 2, {34, 32, 31, 28, 25, 24, 22})); |
| 184 | |
| 185 | result = con.Query( |
| 186 | "SELECT first_name, last_name, count(*) FROM ( SELECT * FROM actor WHERE last_name LIKE 'A%' ) a JOIN " |
| 187 | "film_actor USING (actor_id) GROUP BY a.actor_id, a.first_name, a.last_name ORDER BY count(*) DESC" ); |
| 188 | REQUIRE_NO_FAIL(*result); |
| 189 | REQUIRE(CHECK_COLUMN(result, 0, {"KIRSTEN" , "CHRISTIAN" , "ANGELINA" , "KIM" , "CUBA" , "DEBBIE" , "MERYL" })); |
| 190 | REQUIRE(CHECK_COLUMN(result, 1, {"AKROYD" , "AKROYD" , "ASTAIRE" , "ALLEN" , "ALLEN" , "AKROYD" , "ALLEN" })); |
| 191 | REQUIRE(CHECK_COLUMN(result, 2, {34, 32, 31, 28, 25, 24, 22})); |
| 192 | |
| 193 | result = |
| 194 | con.Query("SELECT * FROM ( SELECT first_name, last_name, ( SELECT count(*) FROM film_actor fa WHERE a.actor_id " |
| 195 | "= fa.actor_id ) AS c FROM actor a WHERE last_name LIKE 'A%' ) a WHERE c > 0 ORDER BY c DESC" ); |
| 196 | REQUIRE_NO_FAIL(*result); |
| 197 | REQUIRE(CHECK_COLUMN(result, 0, {"KIRSTEN" , "CHRISTIAN" , "ANGELINA" , "KIM" , "CUBA" , "DEBBIE" , "MERYL" })); |
| 198 | REQUIRE(CHECK_COLUMN(result, 1, {"AKROYD" , "AKROYD" , "ASTAIRE" , "ALLEN" , "ALLEN" , "AKROYD" , "ALLEN" })); |
| 199 | REQUIRE(CHECK_COLUMN(result, 2, {34, 32, 31, 28, 25, 24, 22})); |
| 200 | |
| 201 | result = con.Query("SELECT first_name, last_name, c FROM actor JOIN ( SELECT actor_id, count(*) c FROM film_actor " |
| 202 | "GROUP BY actor_id ) fa USING (actor_id) WHERE last_name LIKE 'A%' ORDER BY c DESC" ); |
| 203 | REQUIRE_NO_FAIL(*result); |
| 204 | REQUIRE(CHECK_COLUMN(result, 0, {"KIRSTEN" , "CHRISTIAN" , "ANGELINA" , "KIM" , "CUBA" , "DEBBIE" , "MERYL" })); |
| 205 | REQUIRE(CHECK_COLUMN(result, 1, {"AKROYD" , "AKROYD" , "ASTAIRE" , "ALLEN" , "ALLEN" , "AKROYD" , "ALLEN" })); |
| 206 | REQUIRE(CHECK_COLUMN(result, 2, {34, 32, 31, 28, 25, 24, 22})); |
| 207 | } |
| 208 | |