TestSqlStatementExecution.cpp 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. /*
  2. * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
  3. * Copyright (c) 2021, Mahmoud Mandour <ma.mandourr@gmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <unistd.h>
  8. #include <AK/QuickSort.h>
  9. #include <AK/ScopeGuard.h>
  10. #include <LibSQL/AST/Parser.h>
  11. #include <LibSQL/Database.h>
  12. #include <LibSQL/Result.h>
  13. #include <LibSQL/ResultSet.h>
  14. #include <LibSQL/Row.h>
  15. #include <LibSQL/Value.h>
  16. #include <LibTest/TestCase.h>
  17. namespace {
  18. constexpr const char* db_name = "/tmp/test.db";
  19. SQL::ResultOr<SQL::ResultSet> try_execute(NonnullRefPtr<SQL::Database> database, String const& sql)
  20. {
  21. auto parser = SQL::AST::Parser(SQL::AST::Lexer(sql));
  22. auto statement = parser.next_statement();
  23. EXPECT(!parser.has_errors());
  24. if (parser.has_errors())
  25. outln("{}", parser.errors()[0].to_string());
  26. return statement->execute(move(database));
  27. }
  28. SQL::ResultSet execute(NonnullRefPtr<SQL::Database> database, String const& sql)
  29. {
  30. auto result = try_execute(move(database), sql);
  31. if (result.is_error()) {
  32. outln("{}", result.release_error().error_string());
  33. VERIFY_NOT_REACHED();
  34. }
  35. return result.release_value();
  36. }
  37. void create_schema(NonnullRefPtr<SQL::Database> database)
  38. {
  39. auto result = execute(database, "CREATE SCHEMA TestSchema;");
  40. EXPECT_EQ(result.command(), SQL::SQLCommand::Create);
  41. }
  42. void create_table(NonnullRefPtr<SQL::Database> database)
  43. {
  44. create_schema(database);
  45. auto result = execute(database, "CREATE TABLE TestSchema.TestTable ( TextColumn text, IntColumn integer );");
  46. EXPECT_EQ(result.command(), SQL::SQLCommand::Create);
  47. }
  48. void create_two_tables(NonnullRefPtr<SQL::Database> database)
  49. {
  50. create_schema(database);
  51. auto result = execute(database, "CREATE TABLE TestSchema.TestTable1 ( TextColumn1 text, IntColumn integer );");
  52. EXPECT_EQ(result.command(), SQL::SQLCommand::Create);
  53. result = execute(database, "CREATE TABLE TestSchema.TestTable2 ( TextColumn2 text, IntColumn integer );");
  54. EXPECT_EQ(result.command(), SQL::SQLCommand::Create);
  55. }
  56. TEST_CASE(create_schema)
  57. {
  58. ScopeGuard guard([]() { unlink(db_name); });
  59. auto database = SQL::Database::construct(db_name);
  60. EXPECT(!database->open().is_error());
  61. create_schema(database);
  62. auto schema_or_error = database->get_schema("TESTSCHEMA");
  63. EXPECT(!schema_or_error.is_error());
  64. EXPECT(schema_or_error.value());
  65. }
  66. TEST_CASE(create_table)
  67. {
  68. ScopeGuard guard([]() { unlink(db_name); });
  69. auto database = SQL::Database::construct(db_name);
  70. EXPECT(!database->open().is_error());
  71. create_table(database);
  72. auto table_or_error = database->get_table("TESTSCHEMA", "TESTTABLE");
  73. EXPECT(!table_or_error.is_error());
  74. EXPECT(table_or_error.value());
  75. }
  76. TEST_CASE(insert_into_table)
  77. {
  78. ScopeGuard guard([]() { unlink(db_name); });
  79. auto database = SQL::Database::construct(db_name);
  80. EXPECT(!database->open().is_error());
  81. create_table(database);
  82. auto result = execute(database, "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES ( 'Test', 42 );");
  83. EXPECT(result.size() == 1);
  84. auto table_or_error = database->get_table("TESTSCHEMA", "TESTTABLE");
  85. EXPECT(!table_or_error.is_error());
  86. auto table = table_or_error.value();
  87. int count = 0;
  88. auto rows_or_error = database->select_all(*table);
  89. EXPECT(!rows_or_error.is_error());
  90. for (auto& row : rows_or_error.value()) {
  91. EXPECT_EQ(row["TEXTCOLUMN"].to_string(), "Test");
  92. EXPECT_EQ(row["INTCOLUMN"].to_int().value(), 42);
  93. count++;
  94. }
  95. EXPECT_EQ(count, 1);
  96. }
  97. TEST_CASE(insert_into_table_wrong_data_types)
  98. {
  99. ScopeGuard guard([]() { unlink(db_name); });
  100. auto database = SQL::Database::construct(db_name);
  101. EXPECT(!database->open().is_error());
  102. create_table(database);
  103. auto result = try_execute(database, "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES (43, 'Test_2');");
  104. EXPECT(result.is_error());
  105. EXPECT(result.release_error().error() == SQL::SQLErrorCode::InvalidValueType);
  106. }
  107. TEST_CASE(insert_into_table_multiple_tuples_wrong_data_types)
  108. {
  109. ScopeGuard guard([]() { unlink(db_name); });
  110. auto database = SQL::Database::construct(db_name);
  111. EXPECT(!database->open().is_error());
  112. create_table(database);
  113. auto result = try_execute(database, "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES ('Test_1', 42), (43, 'Test_2');");
  114. EXPECT(result.is_error());
  115. EXPECT(result.release_error().error() == SQL::SQLErrorCode::InvalidValueType);
  116. }
  117. TEST_CASE(insert_wrong_number_of_values)
  118. {
  119. ScopeGuard guard([]() { unlink(db_name); });
  120. auto database = SQL::Database::construct(db_name);
  121. EXPECT(!database->open().is_error());
  122. create_table(database);
  123. auto result = try_execute(database, "INSERT INTO TestSchema.TestTable VALUES ( 42 );");
  124. EXPECT(result.is_error());
  125. EXPECT(result.release_error().error() == SQL::SQLErrorCode::InvalidNumberOfValues);
  126. }
  127. TEST_CASE(insert_identifier_as_value)
  128. {
  129. ScopeGuard guard([]() { unlink(db_name); });
  130. auto database = SQL::Database::construct(db_name);
  131. EXPECT(!database->open().is_error());
  132. create_table(database);
  133. auto result = try_execute(database, "INSERT INTO TestSchema.TestTable VALUES ( identifier, 42 );");
  134. EXPECT(result.is_error());
  135. EXPECT(result.release_error().error() == SQL::SQLErrorCode::SyntaxError);
  136. }
  137. TEST_CASE(insert_quoted_identifier_as_value)
  138. {
  139. ScopeGuard guard([]() { unlink(db_name); });
  140. auto database = SQL::Database::construct(db_name);
  141. EXPECT(!database->open().is_error());
  142. create_table(database);
  143. auto result = try_execute(database, "INSERT INTO TestSchema.TestTable VALUES ( \"QuotedIdentifier\", 42 );");
  144. EXPECT(result.is_error());
  145. EXPECT(result.release_error().error() == SQL::SQLErrorCode::SyntaxError);
  146. }
  147. TEST_CASE(insert_without_column_names)
  148. {
  149. ScopeGuard guard([]() { unlink(db_name); });
  150. auto database = SQL::Database::construct(db_name);
  151. EXPECT(!database->open().is_error());
  152. create_table(database);
  153. auto result = execute(database, "INSERT INTO TestSchema.TestTable VALUES ('Test_1', 42), ('Test_2', 43);");
  154. EXPECT(result.size() == 2);
  155. auto table_or_error = database->get_table("TESTSCHEMA", "TESTTABLE");
  156. EXPECT(!table_or_error.is_error());
  157. auto rows_or_error = database->select_all(*(table_or_error.value()));
  158. EXPECT(!rows_or_error.is_error());
  159. EXPECT_EQ(rows_or_error.value().size(), 2u);
  160. }
  161. TEST_CASE(select_from_empty_table)
  162. {
  163. ScopeGuard guard([]() { unlink(db_name); });
  164. auto database = SQL::Database::construct(db_name);
  165. EXPECT(!database->open().is_error());
  166. create_table(database);
  167. auto result = execute(database, "SELECT * FROM TestSchema.TestTable;");
  168. EXPECT(result.is_empty());
  169. }
  170. TEST_CASE(select_from_table)
  171. {
  172. ScopeGuard guard([]() { unlink(db_name); });
  173. auto database = SQL::Database::construct(db_name);
  174. EXPECT(!database->open().is_error());
  175. create_table(database);
  176. auto result = execute(database,
  177. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  178. "( 'Test_1', 42 ), "
  179. "( 'Test_2', 43 ), "
  180. "( 'Test_3', 44 ), "
  181. "( 'Test_4', 45 ), "
  182. "( 'Test_5', 46 );");
  183. EXPECT(result.size() == 5);
  184. result = execute(database, "SELECT * FROM TestSchema.TestTable;");
  185. EXPECT_EQ(result.size(), 5u);
  186. }
  187. TEST_CASE(select_with_column_names)
  188. {
  189. ScopeGuard guard([]() { unlink(db_name); });
  190. auto database = SQL::Database::construct(db_name);
  191. EXPECT(!database->open().is_error());
  192. create_table(database);
  193. auto result = execute(database,
  194. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  195. "( 'Test_1', 42 ), "
  196. "( 'Test_2', 43 ), "
  197. "( 'Test_3', 44 ), "
  198. "( 'Test_4', 45 ), "
  199. "( 'Test_5', 46 );");
  200. EXPECT(result.size() == 5);
  201. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable;");
  202. EXPECT_EQ(result.size(), 5u);
  203. EXPECT_EQ(result[0].row.size(), 1u);
  204. }
  205. TEST_CASE(select_with_nonexisting_column_name)
  206. {
  207. ScopeGuard guard([]() { unlink(db_name); });
  208. auto database = SQL::Database::construct(db_name);
  209. EXPECT(!database->open().is_error());
  210. create_table(database);
  211. auto result = execute(database,
  212. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  213. "( 'Test_1', 42 ), "
  214. "( 'Test_2', 43 ), "
  215. "( 'Test_3', 44 ), "
  216. "( 'Test_4', 45 ), "
  217. "( 'Test_5', 46 );");
  218. EXPECT(result.size() == 5);
  219. auto insert_result = try_execute(database, "SELECT Bogus FROM TestSchema.TestTable;");
  220. EXPECT(insert_result.is_error());
  221. EXPECT(insert_result.release_error().error() == SQL::SQLErrorCode::ColumnDoesNotExist);
  222. }
  223. TEST_CASE(select_with_where)
  224. {
  225. ScopeGuard guard([]() { unlink(db_name); });
  226. auto database = SQL::Database::construct(db_name);
  227. EXPECT(!database->open().is_error());
  228. create_table(database);
  229. auto result = execute(database,
  230. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  231. "( 'Test_1', 42 ), "
  232. "( 'Test_2', 43 ), "
  233. "( 'Test_3', 44 ), "
  234. "( 'Test_4', 45 ), "
  235. "( 'Test_5', 46 );");
  236. EXPECT(result.size() == 5);
  237. result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable WHERE IntColumn > 44;");
  238. EXPECT_EQ(result.size(), 2u);
  239. for (auto& row : result) {
  240. EXPECT(row.row[1].to_int().value() > 44);
  241. }
  242. }
  243. TEST_CASE(select_cross_join)
  244. {
  245. ScopeGuard guard([]() { unlink(db_name); });
  246. auto database = SQL::Database::construct(db_name);
  247. EXPECT(!database->open().is_error());
  248. create_two_tables(database);
  249. auto result = execute(database,
  250. "INSERT INTO TestSchema.TestTable1 ( TextColumn1, IntColumn ) VALUES "
  251. "( 'Test_1', 42 ), "
  252. "( 'Test_2', 43 ), "
  253. "( 'Test_3', 44 ), "
  254. "( 'Test_4', 45 ), "
  255. "( 'Test_5', 46 );");
  256. EXPECT(result.size() == 5);
  257. result = execute(database,
  258. "INSERT INTO TestSchema.TestTable2 ( TextColumn2, IntColumn ) VALUES "
  259. "( 'Test_10', 40 ), "
  260. "( 'Test_11', 41 ), "
  261. "( 'Test_12', 42 ), "
  262. "( 'Test_13', 47 ), "
  263. "( 'Test_14', 48 );");
  264. EXPECT(result.size() == 5);
  265. result = execute(database, "SELECT * FROM TestSchema.TestTable1, TestSchema.TestTable2;");
  266. EXPECT_EQ(result.size(), 25u);
  267. for (auto& row : result) {
  268. EXPECT(row.row.size() == 4);
  269. EXPECT(row.row[1].to_int().value() >= 42);
  270. EXPECT(row.row[1].to_int().value() <= 46);
  271. EXPECT(row.row[3].to_int().value() >= 40);
  272. EXPECT(row.row[3].to_int().value() <= 48);
  273. }
  274. }
  275. TEST_CASE(select_inner_join)
  276. {
  277. ScopeGuard guard([]() { unlink(db_name); });
  278. auto database = SQL::Database::construct(db_name);
  279. EXPECT(!database->open().is_error());
  280. create_two_tables(database);
  281. auto result = execute(database,
  282. "INSERT INTO TestSchema.TestTable1 ( TextColumn1, IntColumn ) VALUES "
  283. "( 'Test_1', 42 ), "
  284. "( 'Test_2', 43 ), "
  285. "( 'Test_3', 44 ), "
  286. "( 'Test_4', 45 ), "
  287. "( 'Test_5', 46 );");
  288. EXPECT(result.size() == 5);
  289. result = execute(database,
  290. "INSERT INTO TestSchema.TestTable2 ( TextColumn2, IntColumn ) VALUES "
  291. "( 'Test_10', 40 ), "
  292. "( 'Test_11', 41 ), "
  293. "( 'Test_12', 42 ), "
  294. "( 'Test_13', 47 ), "
  295. "( 'Test_14', 48 );");
  296. EXPECT(result.size() == 5);
  297. result = execute(database,
  298. "SELECT TestTable1.IntColumn, TextColumn1, TextColumn2 "
  299. "FROM TestSchema.TestTable1, TestSchema.TestTable2 "
  300. "WHERE TestTable1.IntColumn = TestTable2.IntColumn;");
  301. EXPECT_EQ(result.size(), 1u);
  302. EXPECT_EQ(result[0].row.size(), 3u);
  303. EXPECT_EQ(result[0].row[0].to_int().value(), 42);
  304. EXPECT_EQ(result[0].row[1].to_string(), "Test_1");
  305. EXPECT_EQ(result[0].row[2].to_string(), "Test_12");
  306. }
  307. TEST_CASE(select_with_like)
  308. {
  309. ScopeGuard guard([]() { unlink(db_name); });
  310. auto database = SQL::Database::construct(db_name);
  311. EXPECT(!database->open().is_error());
  312. create_table(database);
  313. auto result = execute(database,
  314. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  315. "( 'Test+1', 42 ), "
  316. "( 'Test+2', 43 ), "
  317. "( 'Test+3', 44 ), "
  318. "( 'Test+4', 45 ), "
  319. "( 'Test+5', 46 ), "
  320. "( 'Another+Test_6', 47 );");
  321. EXPECT(result.size() == 6);
  322. // Simple match
  323. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn LIKE 'Test+1';");
  324. EXPECT_EQ(result.size(), 1u);
  325. // Use % to match most rows
  326. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn LIKE 'T%';");
  327. EXPECT_EQ(result.size(), 5u);
  328. // Same as above but invert the match
  329. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn NOT LIKE 'T%';");
  330. EXPECT_EQ(result.size(), 1u);
  331. // Use _ and % to match all rows
  332. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn LIKE '%e_t%';");
  333. EXPECT_EQ(result.size(), 6u);
  334. // Use escape to match a single row. The escape character happens to be a
  335. // Regex metacharacter, let's make sure we don't get confused by that.
  336. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn LIKE '%Test^_%' ESCAPE '^';");
  337. EXPECT_EQ(result.size(), 1u);
  338. // Same as above but escape the escape character happens to be a SQL
  339. // metacharacter - we want to make sure it's treated as an escape.
  340. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn LIKE '%Test__%' ESCAPE '_';");
  341. EXPECT_EQ(result.size(), 1u);
  342. // (Unnecessarily) escaping a character that happens to be a Regex
  343. // metacharacter should have no effect.
  344. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn LIKE 'Test:+_' ESCAPE ':';");
  345. EXPECT_EQ(result.size(), 5u);
  346. // Make sure we error out if the ESCAPE is empty
  347. auto select_result = try_execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn LIKE '%' ESCAPE '';");
  348. EXPECT(select_result.is_error());
  349. EXPECT(select_result.release_error().error() == SQL::SQLErrorCode::SyntaxError);
  350. // Make sure we error out if the ESCAPE has more than a single character
  351. select_result = try_execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn LIKE '%' ESCAPE 'whf';");
  352. EXPECT(select_result.is_error());
  353. EXPECT(select_result.release_error().error() == SQL::SQLErrorCode::SyntaxError);
  354. }
  355. TEST_CASE(select_with_order)
  356. {
  357. ScopeGuard guard([]() { unlink(db_name); });
  358. auto database = SQL::Database::construct(db_name);
  359. EXPECT(!database->open().is_error());
  360. create_table(database);
  361. auto result = execute(database,
  362. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  363. "( 'Test_5', 44 ), "
  364. "( 'Test_2', 42 ), "
  365. "( 'Test_1', 47 ), "
  366. "( 'Test_3', 40 ), "
  367. "( 'Test_4', 41 );");
  368. EXPECT(result.size() == 5);
  369. result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable ORDER BY IntColumn;");
  370. EXPECT_EQ(result.size(), 5u);
  371. EXPECT_EQ(result[0].row[1].to_int().value(), 40);
  372. EXPECT_EQ(result[1].row[1].to_int().value(), 41);
  373. EXPECT_EQ(result[2].row[1].to_int().value(), 42);
  374. EXPECT_EQ(result[3].row[1].to_int().value(), 44);
  375. EXPECT_EQ(result[4].row[1].to_int().value(), 47);
  376. result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable ORDER BY TextColumn;");
  377. EXPECT_EQ(result.size(), 5u);
  378. EXPECT_EQ(result[0].row[0].to_string(), "Test_1");
  379. EXPECT_EQ(result[1].row[0].to_string(), "Test_2");
  380. EXPECT_EQ(result[2].row[0].to_string(), "Test_3");
  381. EXPECT_EQ(result[3].row[0].to_string(), "Test_4");
  382. EXPECT_EQ(result[4].row[0].to_string(), "Test_5");
  383. }
  384. TEST_CASE(select_with_regexp)
  385. {
  386. ScopeGuard guard([]() { unlink(db_name); });
  387. auto database = SQL::Database::construct(db_name);
  388. EXPECT(!database->open().is_error());
  389. create_table(database);
  390. auto result = execute(database,
  391. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  392. "( 'Test+1', 42 ), "
  393. "( 'Pröv+2', 43 ), "
  394. "( 'Test(3)', 44 ), "
  395. "( 'Test[4]', 45 ), "
  396. "( 'Test+5', 46 ), "
  397. "( 'Another-Test_6', 47 );");
  398. EXPECT(result.size() == 6);
  399. // Simple match
  400. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn REGEXP 'Test\\+1';");
  401. EXPECT_EQ(result.size(), 1u);
  402. // Match all
  403. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn REGEXP '.*';");
  404. EXPECT_EQ(result.size(), 6u);
  405. // Match with wildcards
  406. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn REGEXP '^Test.+';");
  407. EXPECT_EQ(result.size(), 4u);
  408. // Match with case insensitive basic Latin and case sensitive Swedish ö
  409. // FIXME: If LibRegex is changed to support case insensitive matches of Unicode characters
  410. // This test should be updated and changed to match 'PRÖV'.
  411. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn REGEXP 'PRöV.*';");
  412. EXPECT_EQ(result.size(), 1u);
  413. }
  414. TEST_CASE(handle_regexp_errors)
  415. {
  416. ScopeGuard guard([]() { unlink(db_name); });
  417. auto database = SQL::Database::construct(db_name);
  418. EXPECT(!database->open().is_error());
  419. create_table(database);
  420. auto result = execute(database,
  421. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  422. "( 'Test', 0 );");
  423. EXPECT(result.size() == 1);
  424. // Malformed regex, unmatched square bracket
  425. auto select_result = try_execute(database, "SELECT TextColumn FROM TestSchema.TestTable WHERE TextColumn REGEXP 'Test\\+[0-9.*';");
  426. EXPECT(select_result.is_error());
  427. }
  428. TEST_CASE(select_with_order_two_columns)
  429. {
  430. ScopeGuard guard([]() { unlink(db_name); });
  431. auto database = SQL::Database::construct(db_name);
  432. EXPECT(!database->open().is_error());
  433. create_table(database);
  434. auto result = execute(database,
  435. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  436. "( 'Test_5', 44 ), "
  437. "( 'Test_2', 42 ), "
  438. "( 'Test_1', 47 ), "
  439. "( 'Test_2', 40 ), "
  440. "( 'Test_4', 41 );");
  441. EXPECT(result.size() == 5);
  442. result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable ORDER BY TextColumn, IntColumn;");
  443. EXPECT_EQ(result.size(), 5u);
  444. EXPECT_EQ(result[0].row[0].to_string(), "Test_1");
  445. EXPECT_EQ(result[0].row[1].to_int().value(), 47);
  446. EXPECT_EQ(result[1].row[0].to_string(), "Test_2");
  447. EXPECT_EQ(result[1].row[1].to_int().value(), 40);
  448. EXPECT_EQ(result[2].row[0].to_string(), "Test_2");
  449. EXPECT_EQ(result[2].row[1].to_int().value(), 42);
  450. EXPECT_EQ(result[3].row[0].to_string(), "Test_4");
  451. EXPECT_EQ(result[3].row[1].to_int().value(), 41);
  452. EXPECT_EQ(result[4].row[0].to_string(), "Test_5");
  453. EXPECT_EQ(result[4].row[1].to_int().value(), 44);
  454. }
  455. TEST_CASE(select_with_order_by_column_not_in_result)
  456. {
  457. ScopeGuard guard([]() { unlink(db_name); });
  458. auto database = SQL::Database::construct(db_name);
  459. EXPECT(!database->open().is_error());
  460. create_table(database);
  461. auto result = execute(database,
  462. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  463. "( 'Test_5', 44 ), "
  464. "( 'Test_2', 42 ), "
  465. "( 'Test_1', 47 ), "
  466. "( 'Test_3', 40 ), "
  467. "( 'Test_4', 41 );");
  468. EXPECT(result.size() == 5);
  469. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable ORDER BY IntColumn;");
  470. EXPECT_EQ(result.size(), 5u);
  471. EXPECT_EQ(result[0].row[0].to_string(), "Test_3");
  472. EXPECT_EQ(result[1].row[0].to_string(), "Test_4");
  473. EXPECT_EQ(result[2].row[0].to_string(), "Test_2");
  474. EXPECT_EQ(result[3].row[0].to_string(), "Test_5");
  475. EXPECT_EQ(result[4].row[0].to_string(), "Test_1");
  476. }
  477. TEST_CASE(select_with_limit)
  478. {
  479. ScopeGuard guard([]() { unlink(db_name); });
  480. auto database = SQL::Database::construct(db_name);
  481. EXPECT(!database->open().is_error());
  482. create_table(database);
  483. for (auto count = 0; count < 100; count++) {
  484. auto result = execute(database,
  485. String::formatted("INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES ( 'Test_{}', {} );", count, count));
  486. EXPECT(result.size() == 1);
  487. }
  488. auto result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable LIMIT 10;");
  489. auto rows = result;
  490. EXPECT_EQ(rows.size(), 10u);
  491. }
  492. TEST_CASE(select_with_limit_and_offset)
  493. {
  494. ScopeGuard guard([]() { unlink(db_name); });
  495. auto database = SQL::Database::construct(db_name);
  496. EXPECT(!database->open().is_error());
  497. create_table(database);
  498. for (auto count = 0; count < 100; count++) {
  499. auto result = execute(database,
  500. String::formatted("INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES ( 'Test_{}', {} );", count, count));
  501. EXPECT(result.size() == 1);
  502. }
  503. auto result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable LIMIT 10 OFFSET 10;");
  504. EXPECT_EQ(result.size(), 10u);
  505. }
  506. TEST_CASE(select_with_order_limit_and_offset)
  507. {
  508. ScopeGuard guard([]() { unlink(db_name); });
  509. auto database = SQL::Database::construct(db_name);
  510. EXPECT(!database->open().is_error());
  511. create_table(database);
  512. for (auto count = 0; count < 100; count++) {
  513. auto result = execute(database,
  514. String::formatted("INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES ( 'Test_{}', {} );", count, count));
  515. EXPECT(result.size() == 1);
  516. }
  517. auto result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable ORDER BY IntColumn LIMIT 10 OFFSET 10;");
  518. EXPECT_EQ(result.size(), 10u);
  519. EXPECT_EQ(result[0].row[1].to_int().value(), 10);
  520. EXPECT_EQ(result[1].row[1].to_int().value(), 11);
  521. EXPECT_EQ(result[2].row[1].to_int().value(), 12);
  522. EXPECT_EQ(result[3].row[1].to_int().value(), 13);
  523. EXPECT_EQ(result[4].row[1].to_int().value(), 14);
  524. EXPECT_EQ(result[5].row[1].to_int().value(), 15);
  525. EXPECT_EQ(result[6].row[1].to_int().value(), 16);
  526. EXPECT_EQ(result[7].row[1].to_int().value(), 17);
  527. EXPECT_EQ(result[8].row[1].to_int().value(), 18);
  528. EXPECT_EQ(result[9].row[1].to_int().value(), 19);
  529. }
  530. TEST_CASE(select_with_limit_out_of_bounds)
  531. {
  532. ScopeGuard guard([]() { unlink(db_name); });
  533. auto database = SQL::Database::construct(db_name);
  534. EXPECT(!database->open().is_error());
  535. create_table(database);
  536. for (auto count = 0; count < 100; count++) {
  537. auto result = execute(database,
  538. String::formatted("INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES ( 'Test_{}', {} );", count, count));
  539. EXPECT(result.size() == 1);
  540. }
  541. auto result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable LIMIT 500;");
  542. EXPECT_EQ(result.size(), 100u);
  543. }
  544. TEST_CASE(select_with_offset_out_of_bounds)
  545. {
  546. ScopeGuard guard([]() { unlink(db_name); });
  547. auto database = SQL::Database::construct(db_name);
  548. EXPECT(!database->open().is_error());
  549. create_table(database);
  550. for (auto count = 0; count < 100; count++) {
  551. auto result = execute(database,
  552. String::formatted("INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES ( 'Test_{}', {} );", count, count));
  553. EXPECT(result.size() == 1);
  554. }
  555. auto result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable LIMIT 10 OFFSET 200;");
  556. EXPECT_EQ(result.size(), 0u);
  557. }
  558. TEST_CASE(describe_table)
  559. {
  560. ScopeGuard guard([]() { unlink(db_name); });
  561. auto database = SQL::Database::construct(db_name);
  562. EXPECT(!database->open().is_error());
  563. create_table(database);
  564. auto result = execute(database, "DESCRIBE TABLE TestSchema.TestTable;");
  565. EXPECT_EQ(result.size(), 2u);
  566. EXPECT_EQ(result[0].row[0].to_string(), "TEXTCOLUMN");
  567. EXPECT_EQ(result[0].row[1].to_string(), "text");
  568. EXPECT_EQ(result[1].row[0].to_string(), "INTCOLUMN");
  569. EXPECT_EQ(result[1].row[1].to_string(), "int");
  570. }
  571. TEST_CASE(binary_operator_execution)
  572. {
  573. ScopeGuard guard([]() { unlink(db_name); });
  574. auto database = SQL::Database::construct(db_name);
  575. EXPECT(!database->open().is_error());
  576. create_table(database);
  577. for (auto count = 0; count < 10; ++count) {
  578. auto result = execute(database, String::formatted("INSERT INTO TestSchema.TestTable VALUES ( 'T{}', {} );", count, count));
  579. EXPECT_EQ(result.size(), 1u);
  580. }
  581. auto compare_result = [](SQL::ResultSet const& result, Vector<int> const& expected) {
  582. EXPECT_EQ(result.command(), SQL::SQLCommand::Select);
  583. EXPECT_EQ(result.size(), expected.size());
  584. Vector<int> result_values;
  585. result_values.ensure_capacity(result.size());
  586. for (size_t i = 0; i < result.size(); ++i) {
  587. auto const& result_row = result.at(i).row;
  588. EXPECT_EQ(result_row.size(), 1u);
  589. auto result_column = result_row[0].to_int();
  590. result_values.append(result_column.value());
  591. }
  592. quick_sort(result_values);
  593. EXPECT_EQ(result_values, expected);
  594. };
  595. auto result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((IntColumn + 1) < 5);");
  596. compare_result(result, { 0, 1, 2, 3 });
  597. result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((IntColumn + 1) <= 5);");
  598. compare_result(result, { 0, 1, 2, 3, 4 });
  599. result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((IntColumn - 1) > 4);");
  600. compare_result(result, { 6, 7, 8, 9 });
  601. result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((IntColumn - 1) >= 4);");
  602. compare_result(result, { 5, 6, 7, 8, 9 });
  603. result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((IntColumn * 2) < 10);");
  604. compare_result(result, { 0, 1, 2, 3, 4 });
  605. result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((IntColumn * 2) <= 10);");
  606. compare_result(result, { 0, 1, 2, 3, 4, 5 });
  607. result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((IntColumn / 3) > 2);");
  608. compare_result(result, { 7, 8, 9 });
  609. result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((IntColumn / 3) >= 2);");
  610. compare_result(result, { 6, 7, 8, 9 });
  611. result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((IntColumn % 2) = 0);");
  612. compare_result(result, { 0, 2, 4, 6, 8 });
  613. result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((IntColumn % 2) = 1);");
  614. compare_result(result, { 1, 3, 5, 7, 9 });
  615. result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((1 << IntColumn) <= 32);");
  616. compare_result(result, { 0, 1, 2, 3, 4, 5 });
  617. result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((1024 >> IntColumn) >= 32);");
  618. compare_result(result, { 0, 1, 2, 3, 4, 5 });
  619. result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((IntColumn | 1) != IntColumn);");
  620. compare_result(result, { 0, 2, 4, 6, 8 });
  621. result = execute(database, "SELECT IntColumn FROM TestSchema.TestTable WHERE ((IntColumn & 1) = 1);");
  622. compare_result(result, { 1, 3, 5, 7, 9 });
  623. }
  624. TEST_CASE(binary_operator_failure)
  625. {
  626. ScopeGuard guard([]() { unlink(db_name); });
  627. auto database = SQL::Database::construct(db_name);
  628. EXPECT(!database->open().is_error());
  629. create_table(database);
  630. for (auto count = 0; count < 10; ++count) {
  631. auto result = execute(database, String::formatted("INSERT INTO TestSchema.TestTable VALUES ( 'T{}', {} );", count, count));
  632. EXPECT_EQ(result.size(), 1u);
  633. }
  634. auto expect_failure = [](auto result, auto op) {
  635. EXPECT(result.is_error());
  636. auto error = result.release_error();
  637. EXPECT_EQ(error.error(), SQL::SQLErrorCode::NumericOperatorTypeMismatch);
  638. auto message = String::formatted("NumericOperatorTypeMismatch: Cannot apply '{}' operator to non-numeric operands", op);
  639. EXPECT_EQ(error.error_string(), message);
  640. };
  641. auto result = try_execute(database, "SELECT * FROM TestSchema.TestTable WHERE ((IntColumn + TextColumn) < 5);");
  642. expect_failure(move(result), '+');
  643. result = try_execute(database, "SELECT * FROM TestSchema.TestTable WHERE ((IntColumn - TextColumn) < 5);");
  644. expect_failure(move(result), '-');
  645. result = try_execute(database, "SELECT * FROM TestSchema.TestTable WHERE ((IntColumn * TextColumn) < 5);");
  646. expect_failure(move(result), '*');
  647. result = try_execute(database, "SELECT * FROM TestSchema.TestTable WHERE ((IntColumn / TextColumn) < 5);");
  648. expect_failure(move(result), '/');
  649. result = try_execute(database, "SELECT * FROM TestSchema.TestTable WHERE ((IntColumn % TextColumn) < 5);");
  650. expect_failure(move(result), '%');
  651. result = try_execute(database, "SELECT * FROM TestSchema.TestTable WHERE ((IntColumn << TextColumn) < 5);");
  652. expect_failure(move(result), "<<"sv);
  653. result = try_execute(database, "SELECT * FROM TestSchema.TestTable WHERE ((IntColumn >> TextColumn) < 5);");
  654. expect_failure(move(result), ">>"sv);
  655. result = try_execute(database, "SELECT * FROM TestSchema.TestTable WHERE ((IntColumn | TextColumn) < 5);");
  656. expect_failure(move(result), '|');
  657. result = try_execute(database, "SELECT * FROM TestSchema.TestTable WHERE ((IntColumn & TextColumn) < 5);");
  658. expect_failure(move(result), '&');
  659. }
  660. }