SQLiteUtils.mod 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. IMPLEMENTATION MODULE SQLiteUtils;
  2. (* Pure V3 helpers over the SQLite binding. *)
  3. FROM SYSTEM IMPORT ADDRESS;
  4. FROM CStr IMPORT Copy;
  5. FROM SQLite IMPORT
  6. DbHandle, StmtHandle, ContextHandle, ValueHandle, BackupHandle,
  7. SQLiteOk, SQLiteDone, SQLiteBusy, SQLiteLocked,
  8. sqlite3_libversion, sqlite3_errmsg, sqlite3_errstr,
  9. sqlite3_open, sqlite3_close, sqlite3_errcode,
  10. sqlite3_exec, sqlite3_free,
  11. sqlite3_bind_text, sqlite3_bind_blob,
  12. sqlite3_prepare_v3,
  13. sqlite3_value_text, sqlite3_result_text,
  14. sqlite3_backup_init, sqlite3_backup_step, sqlite3_backup_finish,
  15. SQLiteTransient;
  16. PROCEDURE CStrToM2 (src : ADDRESS; VAR dst : ARRAY OF CHAR);
  17. VAR
  18. n : CARDINAL;
  19. BEGIN
  20. n := Copy(src, dst)
  21. END CStrToM2;
  22. PROCEDURE ErrMsg (db : DbHandle; VAR buf : ARRAY OF CHAR);
  23. BEGIN
  24. CStrToM2(sqlite3_errmsg(db), buf)
  25. END ErrMsg;
  26. PROCEDURE ErrStr (code : INTEGER; VAR buf : ARRAY OF CHAR);
  27. BEGIN
  28. CStrToM2(sqlite3_errstr(code), buf)
  29. END ErrStr;
  30. PROCEDURE LibVersionStr (VAR buf : ARRAY OF CHAR);
  31. BEGIN
  32. CStrToM2(sqlite3_libversion(), buf)
  33. END LibVersionStr;
  34. PROCEDURE StaticDestr () : ADDRESS;
  35. BEGIN
  36. RETURN NIL
  37. END StaticDestr;
  38. PROCEDURE TransientDestr () : ADDRESS;
  39. BEGIN
  40. RETURN SQLiteTransient()
  41. END TransientDestr;
  42. PROCEDURE BindTextCopy (stmt : StmtHandle; idx : INTEGER;
  43. value : ARRAY OF CHAR) : INTEGER;
  44. BEGIN
  45. RETURN sqlite3_bind_text(stmt, idx, value, -1, TransientDestr())
  46. END BindTextCopy;
  47. PROCEDURE BindBlobCopy (stmt : StmtHandle; idx : INTEGER;
  48. data : ADDRESS; nBytes : INTEGER) : INTEGER;
  49. BEGIN
  50. RETURN sqlite3_bind_blob(stmt, idx, data, nBytes, TransientDestr())
  51. END BindBlobCopy;
  52. PROCEDURE PrepareOne (db : DbHandle; sql : ARRAY OF CHAR;
  53. VAR stmt : StmtHandle) : INTEGER;
  54. VAR
  55. tail : ADDRESS;
  56. BEGIN
  57. tail := NIL;
  58. RETURN sqlite3_prepare_v3(db, sql, -1, 0, stmt, tail)
  59. END PrepareOne;
  60. PROCEDURE ValueText (value : ValueHandle; VAR buf : ARRAY OF CHAR);
  61. BEGIN
  62. CStrToM2(sqlite3_value_text(value), buf)
  63. END ValueText;
  64. PROCEDURE ResultTextCopy (ctx : ContextHandle; value : ARRAY OF CHAR);
  65. BEGIN
  66. sqlite3_result_text(ctx, value, -1, TransientDestr())
  67. END ResultTextCopy;
  68. PROCEDURE BackupToFile (src : DbHandle;
  69. filename : ARRAY OF CHAR) : INTEGER;
  70. VAR
  71. dst : DbHandle;
  72. bk : BackupHandle;
  73. rc, rc2, tries : INTEGER;
  74. BEGIN
  75. rc := sqlite3_open(filename, dst);
  76. IF rc # SQLiteOk THEN RETURN rc END;
  77. bk := sqlite3_backup_init(dst, "main", src, "main");
  78. IF bk = NIL THEN
  79. rc := sqlite3_errcode(dst);
  80. rc2 := sqlite3_close(dst);
  81. RETURN rc
  82. END;
  83. tries := 0;
  84. LOOP
  85. rc := sqlite3_backup_step(bk, 50);
  86. IF (rc # SQLiteOk) AND (rc # SQLiteBusy)
  87. AND (rc # SQLiteLocked) THEN EXIT END;
  88. tries := tries + 1;
  89. IF tries > 100000 THEN
  90. rc := SQLiteBusy;
  91. EXIT
  92. END
  93. END;
  94. IF rc = SQLiteDone THEN rc := SQLiteOk END;
  95. rc2 := sqlite3_backup_finish(bk);
  96. IF rc = SQLiteOk THEN rc := rc2 END;
  97. rc2 := sqlite3_close(dst);
  98. RETURN rc
  99. END BackupToFile;
  100. PROCEDURE ExecSimple (db : DbHandle; sql : ARRAY OF CHAR) : INTEGER;
  101. VAR
  102. msg : ADDRESS;
  103. rc : INTEGER;
  104. BEGIN
  105. msg := NIL;
  106. rc := sqlite3_exec(db, sql, NIL, NIL, msg);
  107. IF msg # NIL THEN sqlite3_free(msg) END;
  108. RETURN rc
  109. END ExecSimple;
  110. PROCEDURE ExecWithErr (db : DbHandle; sql : ARRAY OF CHAR;
  111. VAR errbuf : ARRAY OF CHAR) : INTEGER;
  112. VAR
  113. msg : ADDRESS;
  114. rc : INTEGER;
  115. BEGIN
  116. msg := NIL;
  117. rc := sqlite3_exec(db, sql, NIL, NIL, msg);
  118. IF msg # NIL THEN
  119. CStrToM2(msg, errbuf);
  120. sqlite3_free(msg)
  121. ELSE
  122. errbuf[0] := CHR(0)
  123. END;
  124. RETURN rc
  125. END ExecWithErr;
  126. END SQLiteUtils.