SQLiteHelpers.mod 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. MODULE SQLiteHelpers;
  2. (* Exercise SQLiteUtils and the typed handle aliases. *)
  3. FROM SYSTEM IMPORT ADDRESS, ADR;
  4. FROM SQLite IMPORT
  5. DbHandle, StmtHandle, ContextHandle, ValueHandle,
  6. SQLiteOk, SQLiteRow, SQLiteDone, SQLiteError, SQLiteText,
  7. SQLiteOpenReadWrite, SQLiteOpenCreate, SQLiteOpenMemory,
  8. SQLiteUtf8,
  9. sqlite3_open, sqlite3_open_v2, sqlite3_close,
  10. sqlite3_step, sqlite3_finalize,
  11. sqlite3_column_int, sqlite3_column_text, sqlite3_column_type,
  12. sqlite3_create_function_v2,
  13. sqlite3_value_type, SQLiteArrayAt, SQLiteTransient;
  14. FROM SQLiteUtils IMPORT
  15. CStrToM2, ErrMsg, ErrStr, LibVersionStr, StaticDestr, TransientDestr,
  16. BindTextCopy, BindBlobCopy, PrepareOne, ValueText, ResultTextCopy,
  17. BackupToFile, ExecSimple, ExecWithErr;
  18. VAR
  19. ExitCode : INTEGER;
  20. db, fileDb : DbHandle;
  21. stmt : StmtHandle;
  22. rc : INTEGER;
  23. ok : BOOLEAN;
  24. bin : ARRAY [0..7] OF CHAR;
  25. buf : ARRAY [0..127] OF CHAR;
  26. PROCEDURE SameText (a, b : ARRAY OF CHAR) : BOOLEAN;
  27. VAR
  28. i : INTEGER;
  29. BEGIN
  30. i := 0;
  31. WHILE (a[i] # CHR(0)) AND (a[i] = b[i]) DO i := i + 1 END;
  32. RETURN (a[i] = CHR(0)) AND (b[i] = CHR(0))
  33. END SameText;
  34. PROCEDURE Echo (ctx : ContextHandle; argc : INTEGER; argv : ADDRESS);
  35. VAR
  36. v : ValueHandle;
  37. text : ARRAY [0..63] OF CHAR;
  38. BEGIN
  39. IF argc = 1 THEN
  40. v := SQLiteArrayAt(argv, 0);
  41. IF sqlite3_value_type(v) = SQLiteText THEN
  42. ValueText(v, text);
  43. ResultTextCopy(ctx, text)
  44. END
  45. END
  46. END Echo;
  47. PROCEDURE QueryCount (h : DbHandle; VAR n : INTEGER) : BOOLEAN;
  48. VAR
  49. s : StmtHandle;
  50. code : INTEGER;
  51. good : BOOLEAN;
  52. BEGIN
  53. s := NIL; n := -1; good := FALSE;
  54. code := PrepareOne(h, "SELECT count(*) FROM t;", s);
  55. IF (code = SQLiteOk) AND (s # NIL) THEN
  56. IF sqlite3_step(s) = SQLiteRow THEN
  57. n := sqlite3_column_int(s, 0);
  58. IF sqlite3_step(s) = SQLiteDone THEN good := TRUE END
  59. END;
  60. IF sqlite3_finalize(s) # SQLiteOk THEN good := FALSE END
  61. END;
  62. RETURN good
  63. END QueryCount;
  64. BEGIN
  65. ExitCode := 1;
  66. db := NIL; fileDb := NIL; stmt := NIL; ok := FALSE;
  67. bin[0] := CHR(0); bin[1] := CHR(1); bin[2] := CHR(2);
  68. IF (sqlite3_open_v2(":memory:", db,
  69. SQLiteOpenReadWrite + SQLiteOpenCreate + SQLiteOpenMemory,
  70. NIL) = SQLiteOk) AND (db # NIL)
  71. AND (ExecSimple(db, "CREATE TABLE t(a TEXT, b BLOB);") = SQLiteOk)
  72. AND (PrepareOne(db, "INSERT INTO t(a,b) VALUES(?,?);", stmt) = SQLiteOk)
  73. AND (BindTextCopy(stmt, 1, "hello") = SQLiteOk)
  74. AND (BindBlobCopy(stmt, 2, ADR(bin[0]), 3) = SQLiteOk)
  75. AND (sqlite3_step(stmt) = SQLiteDone) THEN
  76. ok := sqlite3_finalize(stmt) = SQLiteOk;
  77. stmt := NIL
  78. END;
  79. IF ok THEN
  80. ok := (ExecWithErr(db, "INSERT INTO bogus(x) VALUES(1);", buf) # SQLiteOk)
  81. AND (buf[0] # CHR(0));
  82. IF ok THEN
  83. ErrMsg(db, buf);
  84. ok := buf[0] # CHR(0)
  85. END
  86. END;
  87. IF ok THEN
  88. ErrStr(SQLiteError, buf);
  89. ok := buf[0] # CHR(0)
  90. END;
  91. IF ok THEN
  92. LibVersionStr(buf);
  93. ok := buf[0] # CHR(0)
  94. END;
  95. IF ok THEN
  96. CStrToM2(NIL, buf);
  97. ok := buf[0] = CHR(0)
  98. END;
  99. IF ok THEN
  100. ok := (StaticDestr() = NIL) AND (TransientDestr() = SQLiteTransient())
  101. END;
  102. (* ResultTextCopy + ValueText through a UDF. *)
  103. IF ok THEN
  104. ok := sqlite3_create_function_v2(db, "m2_echo", 1, SQLiteUtf8,
  105. NIL, ADR(Echo), NIL, NIL, NIL) = SQLiteOk
  106. END;
  107. IF ok THEN
  108. stmt := NIL;
  109. ok := (PrepareOne(db, "SELECT m2_echo('hey');", stmt) = SQLiteOk)
  110. AND (stmt # NIL)
  111. AND (sqlite3_step(stmt) = SQLiteRow)
  112. AND (sqlite3_column_type(stmt, 0) = SQLiteText);
  113. IF ok THEN
  114. CStrToM2(sqlite3_column_text(stmt, 0), buf);
  115. ok := SameText(buf, "hey")
  116. END;
  117. IF stmt # NIL THEN
  118. IF sqlite3_finalize(stmt) # SQLiteOk THEN ok := FALSE END;
  119. stmt := NIL
  120. END
  121. END;
  122. (* BackupToFile and a file-backed verification query. *)
  123. IF ok THEN
  124. ok := BackupToFile(db, "/tmp/m2-sqlite-utils.db") = SQLiteOk
  125. END;
  126. IF ok THEN
  127. fileDb := NIL;
  128. ok := (sqlite3_open("/tmp/m2-sqlite-utils.db", fileDb) = SQLiteOk)
  129. AND (fileDb # NIL);
  130. IF ok THEN
  131. rc := 0;
  132. ok := QueryCount(fileDb, rc) AND (rc = 1)
  133. END;
  134. IF fileDb # NIL THEN
  135. IF sqlite3_close(fileDb) # SQLiteOk THEN ok := FALSE END;
  136. fileDb := NIL
  137. END
  138. END;
  139. IF stmt # NIL THEN
  140. IF sqlite3_finalize(stmt) # SQLiteOk THEN ok := FALSE END
  141. END;
  142. IF db # NIL THEN
  143. IF sqlite3_close(db) # SQLiteOk THEN ok := FALSE END
  144. END;
  145. IF ok THEN ExitCode := 42 END
  146. END SQLiteHelpers.