SQLiteParams.mod 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. MODULE SQLiteParams;
  2. (* Statement parameter introspection:
  3. count, names, indices, anonymous/named parameters, unbound NULL,
  4. reset/clear and a true 64-bit integer value. *)
  5. FROM SYSTEM IMPORT ADDRESS;
  6. FROM CStr IMPORT CString, Copy;
  7. FROM SQLite IMPORT
  8. SQLiteOk, SQLiteRow, SQLiteDone, SQLiteInteger, SQLiteText, SQLiteNull,
  9. SQLiteOpenReadWrite, SQLiteOpenCreate, SQLiteOpenMemory,
  10. sqlite3_open_v2, sqlite3_exec, sqlite3_close_v2,
  11. sqlite3_prepare_v2, sqlite3_step, sqlite3_reset,
  12. sqlite3_clear_bindings, sqlite3_finalize,
  13. sqlite3_bind_int, sqlite3_bind_int64, sqlite3_bind_double,
  14. sqlite3_bind_null, sqlite3_bind_text,
  15. sqlite3_bind_parameter_count, sqlite3_bind_parameter_name,
  16. sqlite3_bind_parameter_index,
  17. sqlite3_column_count, sqlite3_column_type, sqlite3_column_int,
  18. sqlite3_column_int64, sqlite3_column_double, sqlite3_column_text,
  19. sqlite3_changes, sqlite3_free, SQLiteTransient;
  20. VAR
  21. ExitCode : INTEGER;
  22. db, stmt : ADDRESS;
  23. rc : INTEGER;
  24. ok : BOOLEAN;
  25. PROCEDURE SameText (a, b : ARRAY OF CHAR) : BOOLEAN;
  26. VAR
  27. i : INTEGER;
  28. BEGIN
  29. i := 0;
  30. WHILE (a[i] # CHR(0)) AND (a[i] = b[i]) DO
  31. i := i + 1
  32. END;
  33. RETURN (a[i] = CHR(0)) AND (b[i] = CHR(0))
  34. END SameText;
  35. PROCEDURE ExecSQL (sql : ARRAY OF CHAR) : BOOLEAN;
  36. VAR
  37. errmsg : ADDRESS;
  38. good : BOOLEAN;
  39. BEGIN
  40. errmsg := NIL;
  41. good := sqlite3_exec(db, sql, NIL, NIL, errmsg) = SQLiteOk;
  42. IF errmsg # NIL THEN
  43. sqlite3_free(errmsg)
  44. END;
  45. RETURN good
  46. END ExecSQL;
  47. PROCEDURE NameIs (s : ADDRESS; idx : INTEGER;
  48. want : ARRAY OF CHAR) : BOOLEAN;
  49. VAR
  50. n : CString;
  51. buf : ARRAY [0..63] OF CHAR;
  52. BEGIN
  53. n := sqlite3_bind_parameter_name(s, idx);
  54. IF n = NIL THEN RETURN FALSE END;
  55. IF Copy(n, buf) = 0 THEN RETURN FALSE END;
  56. RETURN SameText(buf, want)
  57. END NameIs;
  58. PROCEDURE NameIsNil (s : ADDRESS; idx : INTEGER) : BOOLEAN;
  59. BEGIN
  60. RETURN sqlite3_bind_parameter_name(s, idx) = NIL
  61. END NameIsNil;
  62. BEGIN
  63. ExitCode := 1;
  64. db := NIL; stmt := NIL; ok := FALSE;
  65. IF (sqlite3_open_v2(":memory:", db,
  66. SQLiteOpenReadWrite + SQLiteOpenCreate + SQLiteOpenMemory,
  67. NIL) = SQLiteOk) AND (db # NIL) THEN
  68. IF ExecSQL("CREATE TABLE t(a INTEGER, b INTEGER, c REAL, d TEXT);") THEN
  69. ok := TRUE
  70. END;
  71. (* Four anonymous parameters, including a real 64-bit value. *)
  72. IF ok THEN
  73. stmt := NIL;
  74. rc := sqlite3_prepare_v2(db,
  75. "INSERT INTO t(a,b,c,d) VALUES(?,?,?,?);", -1, stmt, NIL);
  76. ok := (rc = SQLiteOk) AND (stmt # NIL)
  77. AND (sqlite3_bind_parameter_count(stmt) = 4)
  78. AND NameIsNil(stmt, 1)
  79. AND (sqlite3_bind_parameter_index(stmt, ":missing") = 0);
  80. IF ok THEN
  81. ok := (sqlite3_bind_int(stmt, 1, 42) = SQLiteOk)
  82. AND (sqlite3_bind_int64(stmt, 2,
  83. VAL(LONGINT, 9000000001)) = SQLiteOk)
  84. AND (sqlite3_bind_double(stmt, 3, 2.5) = SQLiteOk)
  85. AND (sqlite3_bind_text(stmt, 4, "hello", -1,
  86. SQLiteTransient()) = SQLiteOk)
  87. END;
  88. IF ok THEN ok := sqlite3_step(stmt) = SQLiteDone END;
  89. IF ok THEN ok := sqlite3_changes(db) = 1 END;
  90. IF stmt # NIL THEN
  91. IF sqlite3_finalize(stmt) # SQLiteOk THEN ok := FALSE END;
  92. stmt := NIL
  93. END
  94. END;
  95. IF ok THEN
  96. stmt := NIL;
  97. rc := sqlite3_prepare_v2(db,
  98. "SELECT a,b,c,d FROM t WHERE a = 42;", -1, stmt, NIL);
  99. ok := (rc = SQLiteOk) AND (stmt # NIL)
  100. AND (sqlite3_column_count(stmt) = 4);
  101. IF ok THEN
  102. ok := sqlite3_step(stmt) = SQLiteRow;
  103. IF ok THEN
  104. ok := (sqlite3_column_type(stmt, 0) = SQLiteInteger)
  105. AND (sqlite3_column_int(stmt, 0) = 42)
  106. AND (sqlite3_column_int64(stmt, 1)
  107. = VAL(LONGINT, 9000000001))
  108. AND (sqlite3_column_double(stmt, 2) = 2.5)
  109. AND (sqlite3_column_type(stmt, 3) = SQLiteText);
  110. IF sqlite3_step(stmt) # SQLiteDone THEN ok := FALSE END
  111. END
  112. END;
  113. IF stmt # NIL THEN
  114. IF sqlite3_finalize(stmt) # SQLiteOk THEN ok := FALSE END;
  115. stmt := NIL
  116. END
  117. END;
  118. (* Named parameters: :1, anonymous ?, and :abc. *)
  119. IF ok THEN
  120. stmt := NIL;
  121. rc := sqlite3_prepare_v2(db,
  122. "INSERT INTO t(a,b,d) VALUES(:1, ?, :abc);", -1, stmt, NIL);
  123. ok := (rc = SQLiteOk) AND (stmt # NIL)
  124. AND (sqlite3_bind_parameter_count(stmt) = 3)
  125. AND NameIs(stmt, 1, ":1")
  126. AND NameIsNil(stmt, 2)
  127. AND NameIs(stmt, 3, ":abc")
  128. AND (sqlite3_bind_parameter_index(stmt, ":1") = 1)
  129. AND (sqlite3_bind_parameter_index(stmt, ":abc") = 3)
  130. AND (sqlite3_bind_parameter_index(stmt, ":missing") = 0);
  131. IF ok THEN
  132. ok := (sqlite3_bind_int(stmt, 1, 100) = SQLiteOk)
  133. AND (sqlite3_bind_int(stmt, 2, 200) = SQLiteOk)
  134. AND (sqlite3_bind_text(stmt, 3, "named", -1,
  135. SQLiteTransient()) = SQLiteOk)
  136. END;
  137. IF ok THEN ok := sqlite3_step(stmt) = SQLiteDone END;
  138. IF ok THEN ok := sqlite3_reset(stmt) = SQLiteOk END;
  139. IF ok THEN ok := sqlite3_clear_bindings(stmt) = SQLiteOk END;
  140. (* After clear_bindings, bind only :1; other parameters are NULL. *)
  141. IF ok THEN ok := sqlite3_bind_int(stmt, 1, 7) = SQLiteOk END;
  142. IF ok THEN ok := sqlite3_step(stmt) = SQLiteDone END;
  143. IF stmt # NIL THEN
  144. IF sqlite3_finalize(stmt) # SQLiteOk THEN ok := FALSE END;
  145. stmt := NIL
  146. END
  147. END;
  148. IF ok THEN
  149. stmt := NIL;
  150. rc := sqlite3_prepare_v2(db,
  151. "SELECT b,d FROM t WHERE a = 7;", -1, stmt, NIL);
  152. ok := (rc = SQLiteOk) AND (stmt # NIL);
  153. IF ok THEN
  154. ok := sqlite3_step(stmt) = SQLiteRow;
  155. IF ok THEN
  156. ok := (sqlite3_column_type(stmt, 0) = SQLiteNull)
  157. AND (sqlite3_column_type(stmt, 1) = SQLiteNull);
  158. IF sqlite3_step(stmt) # SQLiteDone THEN ok := FALSE END
  159. END
  160. END;
  161. IF stmt # NIL THEN
  162. IF sqlite3_finalize(stmt) # SQLiteOk THEN ok := FALSE END;
  163. stmt := NIL
  164. END
  165. END
  166. END;
  167. IF stmt # NIL THEN
  168. IF sqlite3_finalize(stmt) # SQLiteOk THEN ok := FALSE END
  169. END;
  170. IF db # NIL THEN
  171. IF sqlite3_close_v2(db) # SQLiteOk THEN ok := FALSE END
  172. END;
  173. IF ok THEN ExitCode := 42 END
  174. END SQLiteParams.