|
|
@@ -0,0 +1,132 @@
|
|
|
+MODULE SQLiteScalar;
|
|
|
+(* Scalar binding/result metadata: int, int64, double, text, NULL. *)
|
|
|
+
|
|
|
+FROM SYSTEM IMPORT ADDRESS;
|
|
|
+FROM CStr IMPORT CString, Copy;
|
|
|
+FROM SQLite IMPORT
|
|
|
+ SQLiteOk, SQLiteRow, SQLiteDone,
|
|
|
+ SQLiteInteger, SQLiteFloat, SQLiteText, SQLiteNull,
|
|
|
+ sqlite3_open, sqlite3_exec, sqlite3_close,
|
|
|
+ sqlite3_prepare_v2, sqlite3_bind_int, sqlite3_bind_int64,
|
|
|
+ sqlite3_bind_double, sqlite3_bind_null, sqlite3_bind_text,
|
|
|
+ sqlite3_step, sqlite3_reset, sqlite3_clear_bindings,
|
|
|
+ sqlite3_column_count, sqlite3_data_count, sqlite3_column_type,
|
|
|
+ sqlite3_column_bytes, sqlite3_column_int, sqlite3_column_int64,
|
|
|
+ sqlite3_column_double, sqlite3_column_text, sqlite3_column_name,
|
|
|
+ sqlite3_column_decltype, sqlite3_finalize, sqlite3_free,
|
|
|
+ sqlite3_extended_result_codes, SQLiteTransient;
|
|
|
+
|
|
|
+VAR
|
|
|
+ ExitCode : INTEGER;
|
|
|
+ db : ADDRESS;
|
|
|
+
|
|
|
+PROCEDURE ExecSQL (sql : ARRAY OF CHAR) : BOOLEAN;
|
|
|
+VAR
|
|
|
+ errmsg : ADDRESS;
|
|
|
+ ok : BOOLEAN;
|
|
|
+BEGIN
|
|
|
+ errmsg := NIL;
|
|
|
+ ok := sqlite3_exec(db, sql, NIL, NIL, errmsg) = SQLiteOk;
|
|
|
+ IF errmsg # NIL THEN
|
|
|
+ sqlite3_free(errmsg)
|
|
|
+ END;
|
|
|
+ RETURN ok
|
|
|
+END ExecSQL;
|
|
|
+
|
|
|
+VAR
|
|
|
+ stmt : ADDRESS;
|
|
|
+ rc : INTEGER;
|
|
|
+ ok : BOOLEAN;
|
|
|
+ svalue : CString;
|
|
|
+ name : ARRAY [0..63] OF CHAR;
|
|
|
+ text : ARRAY [0..63] OF CHAR;
|
|
|
+ decl : ARRAY [0..63] OF CHAR;
|
|
|
+
|
|
|
+BEGIN
|
|
|
+ ExitCode := 1;
|
|
|
+ db := NIL;
|
|
|
+ stmt := NIL;
|
|
|
+ ok := FALSE;
|
|
|
+ IF (sqlite3_open(":memory:", db) = SQLiteOk) AND (db # NIL) THEN
|
|
|
+ IF sqlite3_extended_result_codes(db, 1) = SQLiteOk THEN
|
|
|
+ IF ExecSQL("CREATE TABLE t(i INTEGER, j INTEGER, r REAL, s TEXT, n TEXT);") THEN
|
|
|
+ rc := sqlite3_prepare_v2(db,
|
|
|
+ "INSERT INTO t VALUES (?, ?, ?, ?, ?);", -1, stmt, NIL);
|
|
|
+ ok := (rc = SQLiteOk) AND (stmt # NIL);
|
|
|
+ IF ok THEN
|
|
|
+ ok := (sqlite3_bind_int(stmt, 1, 42) = SQLiteOk)
|
|
|
+ AND (sqlite3_bind_int64(stmt, 2, 43) = SQLiteOk)
|
|
|
+ AND (sqlite3_bind_double(stmt, 3, 3.5) = SQLiteOk)
|
|
|
+ AND (sqlite3_bind_text(stmt, 4, "hello", -1,
|
|
|
+ SQLiteTransient()) = SQLiteOk)
|
|
|
+ AND (sqlite3_bind_null(stmt, 5) = SQLiteOk)
|
|
|
+ END;
|
|
|
+ IF ok THEN
|
|
|
+ ok := sqlite3_step(stmt) = SQLiteDone
|
|
|
+ END;
|
|
|
+ IF stmt # NIL THEN
|
|
|
+ IF sqlite3_reset(stmt) # SQLiteOk THEN ok := FALSE END;
|
|
|
+ IF sqlite3_clear_bindings(stmt) # SQLiteOk THEN ok := FALSE END;
|
|
|
+ IF sqlite3_finalize(stmt) # SQLiteOk THEN ok := FALSE END;
|
|
|
+ stmt := NIL
|
|
|
+ END
|
|
|
+ END
|
|
|
+ END
|
|
|
+ END;
|
|
|
+
|
|
|
+ IF ok THEN
|
|
|
+ rc := sqlite3_prepare_v2(db,
|
|
|
+ "SELECT i, j, r, s, n FROM t;", -1, stmt, NIL);
|
|
|
+ ok := (rc = SQLiteOk) AND (stmt # NIL);
|
|
|
+ IF ok THEN
|
|
|
+ IF sqlite3_column_count(stmt) = 5 THEN
|
|
|
+ rc := sqlite3_step(stmt);
|
|
|
+ IF rc = SQLiteRow THEN
|
|
|
+ ok := (sqlite3_data_count(stmt) = 5)
|
|
|
+ AND (sqlite3_column_type(stmt, 0) = SQLiteInteger)
|
|
|
+ AND (sqlite3_column_type(stmt, 1) = SQLiteInteger)
|
|
|
+ AND (sqlite3_column_type(stmt, 2) = SQLiteFloat)
|
|
|
+ AND (sqlite3_column_type(stmt, 3) = SQLiteText)
|
|
|
+ AND (sqlite3_column_type(stmt, 4) = SQLiteNull)
|
|
|
+ AND (sqlite3_column_int(stmt, 0) = 42)
|
|
|
+ AND (sqlite3_column_int64(stmt, 1) = 43)
|
|
|
+ AND (sqlite3_column_double(stmt, 2) = 3.5)
|
|
|
+ AND (sqlite3_column_bytes(stmt, 3) = 5);
|
|
|
+ svalue := sqlite3_column_text(stmt, 3);
|
|
|
+ IF (svalue = NIL) OR (Copy(svalue, text) # 5) THEN
|
|
|
+ ok := FALSE
|
|
|
+ ELSIF (text[0] # 'h') OR (text[4] # 'o') THEN
|
|
|
+ ok := FALSE
|
|
|
+ END;
|
|
|
+ svalue := sqlite3_column_name(stmt, 3);
|
|
|
+ IF (svalue = NIL) OR (Copy(svalue, name) # 1)
|
|
|
+ OR (name[0] # 's') THEN
|
|
|
+ ok := FALSE
|
|
|
+ END;
|
|
|
+ svalue := sqlite3_column_decltype(stmt, 3);
|
|
|
+ IF (svalue = NIL) OR (Copy(svalue, decl) # 4)
|
|
|
+ OR (decl[0] # 'T') OR (decl[3] # 'T') THEN
|
|
|
+ ok := FALSE
|
|
|
+ END;
|
|
|
+ IF sqlite3_step(stmt) # SQLiteDone THEN ok := FALSE END
|
|
|
+ ELSE
|
|
|
+ ok := FALSE
|
|
|
+ END
|
|
|
+ ELSE
|
|
|
+ ok := FALSE
|
|
|
+ END;
|
|
|
+ IF stmt # NIL THEN
|
|
|
+ IF sqlite3_finalize(stmt) # SQLiteOk THEN ok := FALSE END;
|
|
|
+ stmt := NIL
|
|
|
+ END
|
|
|
+ END
|
|
|
+ END;
|
|
|
+
|
|
|
+ IF stmt # NIL THEN
|
|
|
+ IF sqlite3_finalize(stmt) # SQLiteOk THEN ok := FALSE END
|
|
|
+ END;
|
|
|
+ IF db # NIL THEN
|
|
|
+ IF sqlite3_close(db) # SQLiteOk THEN ok := FALSE END
|
|
|
+ END;
|
|
|
+ IF ok THEN ExitCode := 42 END
|
|
|
+END SQLiteScalar.
|