TestSqlStatementExecution.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /*
  2. * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <unistd.h>
  7. #include <AK/ScopeGuard.h>
  8. #include <LibSQL/AST/Parser.h>
  9. #include <LibSQL/Database.h>
  10. #include <LibSQL/Row.h>
  11. #include <LibSQL/SQLResult.h>
  12. #include <LibSQL/Value.h>
  13. #include <LibTest/TestCase.h>
  14. namespace {
  15. constexpr const char* db_name = "/tmp/test.db";
  16. RefPtr<SQL::SQLResult> execute(NonnullRefPtr<SQL::Database> database, String const& sql)
  17. {
  18. auto parser = SQL::AST::Parser(SQL::AST::Lexer(sql));
  19. auto statement = parser.next_statement();
  20. EXPECT(!parser.has_errors());
  21. if (parser.has_errors())
  22. outln("{}", parser.errors()[0].to_string());
  23. auto result = statement->execute(move(database));
  24. if (result->error().code != SQL::SQLErrorCode::NoError)
  25. outln("{}", result->error().to_string());
  26. return result;
  27. }
  28. void create_schema(NonnullRefPtr<SQL::Database> database)
  29. {
  30. auto result = execute(database, "CREATE SCHEMA TestSchema;");
  31. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  32. EXPECT(result->inserted() == 1);
  33. }
  34. void create_table(NonnullRefPtr<SQL::Database> database)
  35. {
  36. create_schema(database);
  37. auto result = execute(database, "CREATE TABLE TestSchema.TestTable ( TextColumn text, IntColumn integer );");
  38. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  39. EXPECT(result->inserted() == 1);
  40. }
  41. void create_two_tables(NonnullRefPtr<SQL::Database> database)
  42. {
  43. create_schema(database);
  44. auto result = execute(database, "CREATE TABLE TestSchema.TestTable1 ( TextColumn1 text, IntColumn integer );");
  45. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  46. EXPECT(result->inserted() == 1);
  47. result = execute(database, "CREATE TABLE TestSchema.TestTable2 ( TextColumn2 text, IntColumn integer );");
  48. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  49. EXPECT(result->inserted() == 1);
  50. }
  51. TEST_CASE(create_schema)
  52. {
  53. ScopeGuard guard([]() { unlink(db_name); });
  54. auto database = SQL::Database::construct(db_name);
  55. EXPECT(!database->open().is_error());
  56. create_schema(database);
  57. auto schema_or_error = database->get_schema("TESTSCHEMA");
  58. EXPECT(!schema_or_error.is_error());
  59. EXPECT(schema_or_error.value());
  60. }
  61. TEST_CASE(create_table)
  62. {
  63. ScopeGuard guard([]() { unlink(db_name); });
  64. auto database = SQL::Database::construct(db_name);
  65. EXPECT(!database->open().is_error());
  66. create_table(database);
  67. auto table_or_error = database->get_table("TESTSCHEMA", "TESTTABLE");
  68. EXPECT(!table_or_error.is_error());
  69. EXPECT(table_or_error.value());
  70. }
  71. TEST_CASE(insert_into_table)
  72. {
  73. ScopeGuard guard([]() { unlink(db_name); });
  74. auto database = SQL::Database::construct(db_name);
  75. EXPECT(!database->open().is_error());
  76. create_table(database);
  77. auto result = execute(database, "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES ( 'Test', 42 );");
  78. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  79. EXPECT(result->inserted() == 1);
  80. auto table_or_error = database->get_table("TESTSCHEMA", "TESTTABLE");
  81. EXPECT(!table_or_error.is_error());
  82. auto table = table_or_error.value();
  83. int count = 0;
  84. auto rows_or_error = database->select_all(*table);
  85. EXPECT(!rows_or_error.is_error());
  86. for (auto& row : rows_or_error.value()) {
  87. EXPECT_EQ(row["TEXTCOLUMN"].to_string(), "Test");
  88. EXPECT_EQ(row["INTCOLUMN"].to_int().value(), 42);
  89. count++;
  90. }
  91. EXPECT_EQ(count, 1);
  92. }
  93. TEST_CASE(insert_into_table_wrong_data_types)
  94. {
  95. ScopeGuard guard([]() { unlink(db_name); });
  96. auto database = SQL::Database::construct(db_name);
  97. EXPECT(!database->open().is_error());
  98. create_table(database);
  99. auto result = execute(database, "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES (43, 'Test_2');");
  100. EXPECT(result->inserted() == 0);
  101. EXPECT(result->error().code == SQL::SQLErrorCode::InvalidValueType);
  102. }
  103. TEST_CASE(insert_into_table_multiple_tuples_wrong_data_types)
  104. {
  105. ScopeGuard guard([]() { unlink(db_name); });
  106. auto database = SQL::Database::construct(db_name);
  107. EXPECT(!database->open().is_error());
  108. create_table(database);
  109. auto result = execute(database, "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES ('Test_1', 42), (43, 'Test_2');");
  110. EXPECT(result->inserted() == 0);
  111. EXPECT(result->error().code == SQL::SQLErrorCode::InvalidValueType);
  112. }
  113. TEST_CASE(insert_wrong_number_of_values)
  114. {
  115. ScopeGuard guard([]() { unlink(db_name); });
  116. auto database = SQL::Database::construct(db_name);
  117. EXPECT(!database->open().is_error());
  118. create_table(database);
  119. auto result = execute(database, "INSERT INTO TestSchema.TestTable VALUES ( 42 );");
  120. EXPECT(result->error().code == SQL::SQLErrorCode::InvalidNumberOfValues);
  121. EXPECT(result->inserted() == 0);
  122. }
  123. TEST_CASE(insert_without_column_names)
  124. {
  125. ScopeGuard guard([]() { unlink(db_name); });
  126. auto database = SQL::Database::construct(db_name);
  127. EXPECT(!database->open().is_error());
  128. create_table(database);
  129. auto result = execute(database, "INSERT INTO TestSchema.TestTable VALUES ('Test_1', 42), ('Test_2', 43);");
  130. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  131. EXPECT(result->inserted() == 2);
  132. auto table_or_error = database->get_table("TESTSCHEMA", "TESTTABLE");
  133. EXPECT(!table_or_error.is_error());
  134. auto rows_or_error = database->select_all(*(table_or_error.value()));
  135. EXPECT(!rows_or_error.is_error());
  136. EXPECT_EQ(rows_or_error.value().size(), 2u);
  137. }
  138. TEST_CASE(select_from_table)
  139. {
  140. ScopeGuard guard([]() { unlink(db_name); });
  141. auto database = SQL::Database::construct(db_name);
  142. EXPECT(!database->open().is_error());
  143. create_table(database);
  144. auto result = execute(database,
  145. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  146. "( 'Test_1', 42 ), "
  147. "( 'Test_2', 43 ), "
  148. "( 'Test_3', 44 ), "
  149. "( 'Test_4', 45 ), "
  150. "( 'Test_5', 46 );");
  151. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  152. EXPECT(result->inserted() == 5);
  153. result = execute(database, "SELECT * FROM TestSchema.TestTable;");
  154. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  155. EXPECT(result->has_results());
  156. EXPECT_EQ(result->results().size(), 5u);
  157. }
  158. TEST_CASE(select_with_column_names)
  159. {
  160. ScopeGuard guard([]() { unlink(db_name); });
  161. auto database = SQL::Database::construct(db_name);
  162. EXPECT(!database->open().is_error());
  163. create_table(database);
  164. auto result = execute(database,
  165. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  166. "( 'Test_1', 42 ), "
  167. "( 'Test_2', 43 ), "
  168. "( 'Test_3', 44 ), "
  169. "( 'Test_4', 45 ), "
  170. "( 'Test_5', 46 );");
  171. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  172. EXPECT(result->inserted() == 5);
  173. result = execute(database, "SELECT TextColumn FROM TestSchema.TestTable;");
  174. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  175. EXPECT(result->has_results());
  176. EXPECT_EQ(result->results().size(), 5u);
  177. EXPECT_EQ(result->results()[0].size(), 1u);
  178. }
  179. TEST_CASE(select_with_nonexisting_column_name)
  180. {
  181. ScopeGuard guard([]() { unlink(db_name); });
  182. auto database = SQL::Database::construct(db_name);
  183. EXPECT(!database->open().is_error());
  184. create_table(database);
  185. auto result = execute(database,
  186. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  187. "( 'Test_1', 42 ), "
  188. "( 'Test_2', 43 ), "
  189. "( 'Test_3', 44 ), "
  190. "( 'Test_4', 45 ), "
  191. "( 'Test_5', 46 );");
  192. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  193. EXPECT(result->inserted() == 5);
  194. result = execute(database, "SELECT Bogus FROM TestSchema.TestTable;");
  195. EXPECT(result->error().code == SQL::SQLErrorCode::ColumnDoesNotExist);
  196. }
  197. TEST_CASE(select_with_where)
  198. {
  199. ScopeGuard guard([]() { unlink(db_name); });
  200. auto database = SQL::Database::construct(db_name);
  201. EXPECT(!database->open().is_error());
  202. create_table(database);
  203. auto result = execute(database,
  204. "INSERT INTO TestSchema.TestTable ( TextColumn, IntColumn ) VALUES "
  205. "( 'Test_1', 42 ), "
  206. "( 'Test_2', 43 ), "
  207. "( 'Test_3', 44 ), "
  208. "( 'Test_4', 45 ), "
  209. "( 'Test_5', 46 );");
  210. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  211. EXPECT(result->inserted() == 5);
  212. result = execute(database, "SELECT TextColumn, IntColumn FROM TestSchema.TestTable WHERE IntColumn > 44;");
  213. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  214. EXPECT(result->has_results());
  215. EXPECT_EQ(result->results().size(), 2u);
  216. for (auto& row : result->results()) {
  217. EXPECT(row[1].to_int().value() > 44);
  218. }
  219. }
  220. TEST_CASE(select_cross_join)
  221. {
  222. ScopeGuard guard([]() { unlink(db_name); });
  223. auto database = SQL::Database::construct(db_name);
  224. EXPECT(!database->open().is_error());
  225. create_two_tables(database);
  226. auto result = execute(database,
  227. "INSERT INTO TestSchema.TestTable1 ( TextColumn1, IntColumn ) VALUES "
  228. "( 'Test_1', 42 ), "
  229. "( 'Test_2', 43 ), "
  230. "( 'Test_3', 44 ), "
  231. "( 'Test_4', 45 ), "
  232. "( 'Test_5', 46 );");
  233. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  234. EXPECT(result->inserted() == 5);
  235. result = execute(database,
  236. "INSERT INTO TestSchema.TestTable2 ( TextColumn2, IntColumn ) VALUES "
  237. "( 'Test_10', 40 ), "
  238. "( 'Test_11', 41 ), "
  239. "( 'Test_12', 42 ), "
  240. "( 'Test_13', 47 ), "
  241. "( 'Test_14', 48 );");
  242. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  243. EXPECT(result->inserted() == 5);
  244. result = execute(database, "SELECT * FROM TestSchema.TestTable1, TestSchema.TestTable2;");
  245. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  246. EXPECT(result->has_results());
  247. EXPECT_EQ(result->results().size(), 25u);
  248. for (auto& row : result->results()) {
  249. EXPECT(row.size() == 4);
  250. EXPECT(row[1].to_int().value() >= 42);
  251. EXPECT(row[1].to_int().value() <= 46);
  252. EXPECT(row[3].to_int().value() >= 40);
  253. EXPECT(row[3].to_int().value() <= 48);
  254. }
  255. }
  256. TEST_CASE(select_inner_join)
  257. {
  258. ScopeGuard guard([]() { unlink(db_name); });
  259. auto database = SQL::Database::construct(db_name);
  260. EXPECT(!database->open().is_error());
  261. create_two_tables(database);
  262. auto result = execute(database,
  263. "INSERT INTO TestSchema.TestTable1 ( TextColumn1, IntColumn ) VALUES "
  264. "( 'Test_1', 42 ), "
  265. "( 'Test_2', 43 ), "
  266. "( 'Test_3', 44 ), "
  267. "( 'Test_4', 45 ), "
  268. "( 'Test_5', 46 );");
  269. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  270. EXPECT(result->inserted() == 5);
  271. result = execute(database,
  272. "INSERT INTO TestSchema.TestTable2 ( TextColumn2, IntColumn ) VALUES "
  273. "( 'Test_10', 40 ), "
  274. "( 'Test_11', 41 ), "
  275. "( 'Test_12', 42 ), "
  276. "( 'Test_13', 47 ), "
  277. "( 'Test_14', 48 );");
  278. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  279. EXPECT(result->inserted() == 5);
  280. result = execute(database,
  281. "SELECT TestTable1.IntColumn, TextColumn1, TextColumn2 "
  282. "FROM TestSchema.TestTable1, TestSchema.TestTable2 "
  283. "WHERE TestTable1.IntColumn = TestTable2.IntColumn;");
  284. EXPECT(result->error().code == SQL::SQLErrorCode::NoError);
  285. EXPECT(result->has_results());
  286. EXPECT_EQ(result->results().size(), 1u);
  287. auto& row = result->results()[0];
  288. EXPECT_EQ(row.size(), 3u);
  289. EXPECT_EQ(row[0].to_int().value(), 42);
  290. EXPECT_EQ(row[1].to_string(), "Test_1");
  291. EXPECT_EQ(row[2].to_string(), "Test_12");
  292. }
  293. }