SQLiteBlobErrors.mod 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. MODULE SQLiteBlobErrors;
  2. (* BLOB error paths:
  3. read-only writes, bounds, invalid opens and expired handles. *)
  4. FROM SYSTEM IMPORT ADDRESS, ADR;
  5. FROM SQLite IMPORT
  6. SQLiteOk, SQLiteError, SQLiteReadOnly, SQLiteAbort,
  7. SQLiteBlobReadOnly, SQLiteBlobReadWrite,
  8. SQLiteOpenReadWrite, SQLiteOpenCreate, SQLiteOpenMemory,
  9. sqlite3_open_v2, sqlite3_exec, sqlite3_close_v2,
  10. sqlite3_blob_open, sqlite3_blob_close, sqlite3_blob_read,
  11. sqlite3_blob_write, sqlite3_free;
  12. VAR
  13. ExitCode : INTEGER;
  14. db, blob : ADDRESS;
  15. rc : INTEGER;
  16. ok : BOOLEAN;
  17. buf : ARRAY [0..7] OF CHAR;
  18. PROCEDURE ExecSQL (sql : ARRAY OF CHAR) : BOOLEAN;
  19. VAR
  20. errmsg : ADDRESS;
  21. good : BOOLEAN;
  22. BEGIN
  23. errmsg := NIL;
  24. good := sqlite3_exec(db, sql, NIL, NIL, errmsg) = SQLiteOk;
  25. IF errmsg # NIL THEN
  26. sqlite3_free(errmsg)
  27. END;
  28. RETURN good
  29. END ExecSQL;
  30. PROCEDURE CloseBlob (VAR b : ADDRESS; want : INTEGER) : BOOLEAN;
  31. VAR
  32. got : INTEGER;
  33. BEGIN
  34. IF b = NIL THEN RETURN FALSE END;
  35. got := sqlite3_blob_close(b);
  36. b := NIL;
  37. RETURN got = want
  38. END CloseBlob;
  39. BEGIN
  40. ExitCode := 1;
  41. db := NIL; blob := NIL; ok := FALSE;
  42. buf[0] := 'X'; buf[1] := 'Y';
  43. IF (sqlite3_open_v2(":memory:", db,
  44. SQLiteOpenReadWrite + SQLiteOpenCreate + SQLiteOpenMemory,
  45. NIL) = SQLiteOk) AND (db # NIL) THEN
  46. IF ExecSQL("CREATE TABLE b(id INTEGER PRIMARY KEY, data BLOB);")
  47. AND ExecSQL("INSERT INTO b(data) VALUES(zeroblob(4));")
  48. AND ExecSQL("INSERT INTO b(data) VALUES(zeroblob(4));") THEN
  49. ok := TRUE
  50. END
  51. END;
  52. (* Flags 0 = read-only; a write must fail and remain pending at close. *)
  53. IF ok THEN
  54. rc := sqlite3_blob_open(db, "main", "b", "data", 1,
  55. SQLiteBlobReadOnly, blob);
  56. ok := (rc = SQLiteOk) AND (blob # NIL)
  57. END;
  58. IF ok THEN
  59. ok := sqlite3_blob_write(blob, ADR(buf[0]), 1, 0) = SQLiteReadOnly
  60. END;
  61. IF NOT CloseBlob(blob, SQLiteReadOnly) THEN ok := FALSE END;
  62. (* Bounds checks on a read-write handle. *)
  63. IF ok THEN
  64. rc := sqlite3_blob_open(db, "main", "b", "data", 1,
  65. SQLiteBlobReadWrite, blob);
  66. ok := (rc = SQLiteOk) AND (blob # NIL)
  67. END;
  68. IF ok THEN
  69. ok := sqlite3_blob_read(blob, ADR(buf[0]), 2, 3) = SQLiteError
  70. END;
  71. IF ok THEN
  72. ok := sqlite3_blob_write(blob, ADR(buf[0]), 2, 3) = SQLiteError
  73. END;
  74. IF ok THEN
  75. ok := sqlite3_blob_read(blob, ADR(buf[0]), 1, -1) = SQLiteError
  76. END;
  77. IF ok THEN
  78. ok := sqlite3_blob_write(blob, ADR(buf[0]), 1, -1) = SQLiteError
  79. END;
  80. IF NOT CloseBlob(blob, SQLiteOk) THEN ok := FALSE END;
  81. (* Invalid row/table/column and a non-BLOB column. *)
  82. IF ok THEN
  83. rc := sqlite3_blob_open(db, "main", "b", "data", 99,
  84. SQLiteBlobReadOnly, blob);
  85. ok := (rc # SQLiteOk) AND (blob = NIL)
  86. END;
  87. IF ok THEN
  88. rc := sqlite3_blob_open(db, "main", "b", "nope", 1,
  89. SQLiteBlobReadOnly, blob);
  90. ok := (rc # SQLiteOk) AND (blob = NIL)
  91. END;
  92. IF ok THEN
  93. rc := sqlite3_blob_open(db, "main", "nope", "data", 1,
  94. SQLiteBlobReadOnly, blob);
  95. ok := (rc # SQLiteOk) AND (blob = NIL)
  96. END;
  97. IF ok THEN
  98. rc := sqlite3_blob_open(db, "main", "b", "id", 1,
  99. SQLiteBlobReadOnly, blob);
  100. ok := (rc # SQLiteOk) AND (blob = NIL)
  101. END;
  102. (* An UPDATE expires an open BLOB handle. *)
  103. IF ok THEN
  104. rc := sqlite3_blob_open(db, "main", "b", "data", 2,
  105. SQLiteBlobReadWrite, blob);
  106. ok := (rc = SQLiteOk) AND (blob # NIL)
  107. END;
  108. IF ok THEN
  109. ok := sqlite3_blob_read(blob, ADR(buf[0]), 1, 0) = SQLiteOk
  110. END;
  111. IF ok THEN
  112. ok := ExecSQL("UPDATE b SET data = zeroblob(4) WHERE id = 2;")
  113. END;
  114. IF ok THEN
  115. ok := sqlite3_blob_read(blob, ADR(buf[0]), 1, 0) = SQLiteAbort
  116. END;
  117. IF NOT CloseBlob(blob, SQLiteOk) THEN ok := FALSE END;
  118. IF db # NIL THEN
  119. IF sqlite3_close_v2(db) # SQLiteOk THEN ok := FALSE END
  120. END;
  121. IF ok THEN ExitCode := 42 END
  122. END SQLiteBlobErrors.