SQLiteCapi3c.mod 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. MODULE SQLiteCapi3c;
  2. (* Broad C-API integration test, adapted from upstream
  3. sqlite-master/test/capi3c.test (public domain).
  4. Exercises open/exec/prepare_v2, bind, step, column metadata,
  5. scalar/BLOB column access, changes/rowid, autocommit, errors and
  6. close-with-outstanding-statement behavior. *)
  7. FROM SYSTEM IMPORT ADDRESS;
  8. FROM CStr IMPORT CString, Copy;
  9. FROM SQLite IMPORT
  10. SQLiteOk, SQLiteRow, SQLiteDone, SQLiteBusy,
  11. SQLiteInteger, SQLiteFloat, SQLiteText, SQLiteBlob, SQLiteNull,
  12. SQLiteOpenReadWrite, SQLiteOpenCreate, SQLiteOpenMemory,
  13. sqlite3_open_v2, sqlite3_close, sqlite3_exec,
  14. sqlite3_prepare_v2, sqlite3_step, sqlite3_finalize,
  15. sqlite3_bind_int, sqlite3_bind_text,
  16. sqlite3_column_count, sqlite3_column_name, sqlite3_column_decltype,
  17. sqlite3_column_type, sqlite3_column_int, sqlite3_column_int64,
  18. sqlite3_column_double, sqlite3_column_text, sqlite3_column_blob,
  19. sqlite3_column_bytes,
  20. sqlite3_changes, sqlite3_last_insert_rowid,
  21. sqlite3_errcode, sqlite3_errmsg, sqlite3_get_autocommit,
  22. sqlite3_free, SQLiteTransient;
  23. VAR
  24. ExitCode : INTEGER;
  25. db, stmt : ADDRESS;
  26. rc : INTEGER;
  27. ok : BOOLEAN;
  28. PROCEDURE SameText (a, b : ARRAY OF CHAR) : BOOLEAN;
  29. VAR
  30. i : INTEGER;
  31. BEGIN
  32. i := 0;
  33. WHILE (a[i] # CHR(0)) AND (a[i] = b[i]) DO
  34. i := i + 1
  35. END;
  36. RETURN (a[i] = CHR(0)) AND (b[i] = CHR(0))
  37. END SameText;
  38. PROCEDURE TextIs (s : CString; want : ARRAY OF CHAR) : BOOLEAN;
  39. VAR
  40. buf : ARRAY [0..127] OF CHAR;
  41. BEGIN
  42. IF s = NIL THEN RETURN FALSE END;
  43. IF Copy(s, buf) = 0 THEN RETURN FALSE END;
  44. RETURN SameText(buf, want)
  45. END TextIs;
  46. PROCEDURE ExecSQL (sql : ARRAY OF CHAR) : BOOLEAN;
  47. VAR
  48. errmsg : ADDRESS;
  49. good : BOOLEAN;
  50. BEGIN
  51. errmsg := NIL;
  52. good := sqlite3_exec(db, sql, NIL, NIL, errmsg) = SQLiteOk;
  53. IF errmsg # NIL THEN sqlite3_free(errmsg) END;
  54. RETURN good
  55. END ExecSQL;
  56. PROCEDURE Finish (VAR s : ADDRESS) : BOOLEAN;
  57. VAR
  58. good : BOOLEAN;
  59. BEGIN
  60. good := TRUE;
  61. IF s # NIL THEN
  62. IF sqlite3_finalize(s) # SQLiteOk THEN good := FALSE END;
  63. s := NIL
  64. END;
  65. RETURN good
  66. END Finish;
  67. BEGIN
  68. ExitCode := 1;
  69. db := NIL; stmt := NIL; ok := FALSE;
  70. IF (sqlite3_open_v2(":memory:", db,
  71. SQLiteOpenReadWrite + SQLiteOpenCreate + SQLiteOpenMemory,
  72. NIL) = SQLiteOk) AND (db # NIL) THEN
  73. ok := ExecSQL("CREATE TABLE t(a VARINT, b BLOB, c VARCHAR(16));")
  74. AND ExecSQL("INSERT INTO t VALUES(1, X'0102', 3);")
  75. AND ExecSQL("INSERT INTO t VALUES('one', 'two', NULL);")
  76. AND ExecSQL("INSERT INTO t VALUES(1.2, 1.3, 1.4);")
  77. END;
  78. (* Prepared SELECT and column metadata. *)
  79. IF ok THEN
  80. stmt := NIL;
  81. rc := sqlite3_prepare_v2(db, "SELECT * FROM t;", -1, stmt, NIL);
  82. ok := (rc = SQLiteOk) AND (stmt # NIL)
  83. AND (sqlite3_column_count(stmt) = 3)
  84. AND TextIs(sqlite3_column_name(stmt, 0), "a")
  85. AND TextIs(sqlite3_column_name(stmt, 1), "b")
  86. AND TextIs(sqlite3_column_name(stmt, 2), "c")
  87. AND TextIs(sqlite3_column_decltype(stmt, 0), "VARINT")
  88. AND TextIs(sqlite3_column_decltype(stmt, 1), "BLOB")
  89. AND TextIs(sqlite3_column_decltype(stmt, 2), "VARCHAR(16)")
  90. END;
  91. (* Integer + BLOB + integer row. *)
  92. IF ok THEN
  93. ok := sqlite3_step(stmt) = SQLiteRow;
  94. IF ok THEN
  95. ok := (sqlite3_column_type(stmt, 0) = SQLiteInteger)
  96. AND (sqlite3_column_int(stmt, 0) = 1)
  97. AND (sqlite3_column_int64(stmt, 0) = 1)
  98. AND (sqlite3_column_double(stmt, 0) = 1.0)
  99. AND (sqlite3_column_type(stmt, 1) = SQLiteBlob)
  100. AND (sqlite3_column_blob(stmt, 1) # NIL)
  101. AND (sqlite3_column_bytes(stmt, 1) = 2)
  102. AND (sqlite3_column_type(stmt, 2) = SQLiteText)
  103. AND (sqlite3_column_int(stmt, 2) = 3)
  104. AND TextIs(sqlite3_column_text(stmt, 2), "3")
  105. END
  106. END;
  107. (* Text + text + NULL row. *)
  108. IF ok THEN
  109. ok := sqlite3_step(stmt) = SQLiteRow;
  110. IF ok THEN
  111. ok := (sqlite3_column_type(stmt, 0) = SQLiteText)
  112. AND TextIs(sqlite3_column_text(stmt, 0), "one")
  113. AND (sqlite3_column_type(stmt, 1) = SQLiteText)
  114. AND (sqlite3_column_bytes(stmt, 1) = 3)
  115. AND TextIs(sqlite3_column_text(stmt, 1), "two")
  116. AND (sqlite3_column_type(stmt, 2) = SQLiteNull)
  117. AND (sqlite3_column_int(stmt, 2) = 0)
  118. END
  119. END;
  120. (* Real + real + real row. *)
  121. IF ok THEN
  122. ok := sqlite3_step(stmt) = SQLiteRow;
  123. IF ok THEN
  124. ok := (sqlite3_column_type(stmt, 0) = SQLiteFloat)
  125. AND (sqlite3_column_double(stmt, 0) = 1.2)
  126. AND (sqlite3_column_type(stmt, 1) = SQLiteFloat)
  127. AND (sqlite3_column_double(stmt, 1) = 1.3)
  128. AND (sqlite3_column_type(stmt, 2) = SQLiteText)
  129. AND (sqlite3_column_double(stmt, 2) = 1.4)
  130. AND TextIs(sqlite3_column_text(stmt, 2), "1.4")
  131. END
  132. END;
  133. IF ok THEN ok := sqlite3_step(stmt) = SQLiteDone END;
  134. IF NOT Finish(stmt) THEN ok := FALSE END;
  135. (* Bound insert and change counters. *)
  136. IF ok THEN
  137. stmt := NIL;
  138. rc := sqlite3_prepare_v2(db,
  139. "INSERT INTO t(a,c) VALUES(?,?);", -1, stmt, NIL);
  140. ok := (rc = SQLiteOk) AND (stmt # NIL)
  141. AND (sqlite3_bind_int(stmt, 1, 7) = SQLiteOk)
  142. AND (sqlite3_bind_text(stmt, 2, "seven", -1,
  143. SQLiteTransient()) = SQLiteOk);
  144. IF ok THEN ok := sqlite3_step(stmt) = SQLiteDone END;
  145. IF ok THEN
  146. ok := (sqlite3_changes(db) = 1)
  147. AND (sqlite3_last_insert_rowid(db) = 4)
  148. END;
  149. IF NOT Finish(stmt) THEN ok := FALSE END
  150. END;
  151. (* Autocommit state. *)
  152. IF ok THEN
  153. ok := (sqlite3_get_autocommit(db) = 1)
  154. AND ExecSQL("BEGIN;")
  155. AND (sqlite3_get_autocommit(db) = 0)
  156. AND ExecSQL("COMMIT;")
  157. AND (sqlite3_get_autocommit(db) = 1)
  158. END;
  159. (* A failed prepare leaves an error and a message. *)
  160. IF ok THEN
  161. stmt := NIL;
  162. rc := sqlite3_prepare_v2(db, "SELECT namex FROM sqlite_master;",
  163. -1, stmt, NIL);
  164. ok := (rc # SQLiteOk) AND (stmt = NIL)
  165. AND (sqlite3_errcode(db) # SQLiteOk)
  166. AND (sqlite3_errmsg(db) # NIL);
  167. IF NOT Finish(stmt) THEN ok := FALSE END
  168. END;
  169. (* close() must fail while a statement is outstanding. *)
  170. IF ok THEN
  171. stmt := NIL;
  172. rc := sqlite3_prepare_v2(db, "SELECT 1;", -1, stmt, NIL);
  173. ok := (rc = SQLiteOk) AND (stmt # NIL)
  174. AND (sqlite3_close(db) = SQLiteBusy);
  175. IF NOT Finish(stmt) THEN ok := FALSE END
  176. END;
  177. IF db # NIL THEN
  178. IF sqlite3_close(db) # SQLiteOk THEN ok := FALSE END;
  179. db := NIL
  180. END;
  181. IF ok THEN ExitCode := 42 END
  182. END SQLiteCapi3c.