Tcl limit API
(1) By Mark Benningfield (mbenningfield1) on 2021-01-11 11:21:39 [link] [source]
I'm working on updating a SQLite extension and I thought this would be a good time to learn Tcl and convert the (zillion) unit tests to Tcl. Does the Tcl interface for SQLite not contain a command for the sqlite3_limit()
API?
(2) By Richard Hipp (drh) on 2021-01-11 12:32:36 in reply to 1 [link] [source]
There is not. We have traditionally used an TCL extension to access sqlite3_limit() for testing.
(3) By Mark Benningfield (mbenningfield1) on 2021-01-11 13:26:19 in reply to 2 [link] [source]
Okay, thanks. I've just started out with Tcl, and I haven't really gotten around to the TEA aspects yet. Hopefully the books I've ordered will arrive this week and I can spend the weekend in a deep dip.
(4) By Dan Shearer (danshearer) on 2021-01-11 20:25:20 in reply to 3 [link] [source]
Hopefully the books I've ordered will arrive this week and I can spend the weekend in a deep dip.
I'm getting into Tcl too. Quite a few Tcl books are outdated, but I can recommend "The Tcl Programming Language" both Ashok P Nadkarani as being current up to 8.6, and a considerable amount of writing on the author's website about 8.7-related topics.
Dan Shearer
(5) By Mark Benningfield (mbenningfield1) on 2021-01-18 13:45:37 in reply to 2 [source]
Since I only needed the limit
command, and since the test1.c
extension is ~8600 LOC, I just added the code from the test_limit()
function as a new switch case in the tclsqlite
extension.
Here's a patch file for anyone that wants to use it:
--- C:/Differ/old/tclsqlite.c Fri Nov 27 06:59:17 2020
+++ C:/Differ/new/tclsqlite.c Mon Jan 18 06:51:47 2021
@@ -26,0 +27,14 @@
+
+/*==============================================================================
+ * 2021 January 16
+
+ * Modified to include the code in the test_limit() function from the test1.c
+ * file in the SQLite source. This adds the "limit" command to a database
+ * connection object, which invokes the "sqlite3_limit()" API.
+ *
+ * Changes are marked with /* EDIT: ...
+ *
+ * The author of these changes further disclaims copyright.
+ *
+ *============================================================================*/
+
@@ -1916 +1930 @@
- static const char *DB_strs[] = {
+ static const char *DB_strs[] = { /* EDIT: Added "limit" and DB_LIMIT */
@@ -1930 +1944,2 @@
- "version", "wal_hook", 0
+ "version", "wal_hook", "limit",
+ 0
@@ -1946 +1961 @@
- DB_VERSION, DB_WAL_HOOK
+ DB_VERSION, DB_WAL_HOOK, DB_LIMIT
@@ -3636,0 +3652,65 @@
+ /* EDIT: Added a case for DB_LIMIT
+ **
+ ** $db limit ID VALUE
+ **
+ ** Set or query the SQLITE_LIMIT_XX value
+ */
+ case DB_LIMIT: {
+ static const struct {
+ char *zName;
+ int id;
+ } aId[] = { /* EDIT: Permit exclusion of SQLITE_ prefix */
+ { "SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH },
+ { "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH },
+ { "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN },
+ { "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH },
+ { "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT },
+ { "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP },
+ { "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG },
+ { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED },
+ { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
+ { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER },
+ { "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH },
+ { "SQLITE_LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS },
+ { "LIMIT_LENGTH", SQLITE_LIMIT_LENGTH },
+ { "LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH },
+ { "LIMIT_COLUMN", SQLITE_LIMIT_COLUMN },
+ { "LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH },
+ { "LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT },
+ { "LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP },
+ { "LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG },
+ { "LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED },
+ { "LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
+ { "LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER },
+ { "LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH },
+ { "LIMIT_WORKER_THREADS", SQLITE_LIMIT_WORKER_THREADS },
+
+ /* Out of range test cases */
+ { "SQLITE_LIMIT_TOOSMALL", -1, },
+ { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS + 1 },
+ };
+ int i, id = 0;
+ int val;
+ const char *zId;
+
+ if( objc!=4 ) { /* EDIT: Added mising end-quote and changed db to limit */
+ Tcl_AppendResult(interp, "wrong # args: should be \"",
+ Tcl_GetStringFromObj(objv[0], 0), " limit ID VALUE\"", 0);
+ return TCL_ERROR;
+ }
+ zId = Tcl_GetString(objv[2]);
+ for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){
+ if( _stricmp(zId, aId[i].zName)==0 ){ /* EDIT: Permit case-insensitive */
+ id = aId[i].id;
+ break;
+ }
+ }
+ if( i>=sizeof(aId)/sizeof(aId[0]) ){
+ Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0);
+ return TCL_ERROR;
+ }
+ if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
+ rc = sqlite3_limit(pDb->db, id, val);
+ Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
+ return TCL_OK;
+ }