SQLite Forum

Tcl limit API
Login

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 [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 [link] [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; 
+  }