]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Reinstate test cases for the limit tests. The sqlite3_limit() API is now
authordrh <drh@noemail.net>
Thu, 20 Mar 2008 16:30:17 +0000 (16:30 +0000)
committerdrh <drh@noemail.net>
Thu, 20 Mar 2008 16:30:17 +0000 (16:30 +0000)
tested and working. (CVS 4899)

FossilOrigin-Name: 4c4be4c3c8aae97f1d85442b25afba9f0b02c8b3

manifest
manifest.uuid
src/expr.c
src/func.c
src/main.c
src/parse.y
src/printf.c
src/sqlite.h.in
src/sqliteInt.h
src/test1.c
test/sqllimits1.test

index 23e1adb18d6ac7d4dd330c4f42aa25eaa561e1c1..d1c49637ab1ef160a601daa599715ce2ee49b4e7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Do\snot\srun\scrash7.test\sas\spart\sof\sa\squick\stest.\s(CVS\s4898)
-D 2008-03-20T16:26:49
+C Reinstate\stest\scases\sfor\sthe\slimit\stests.\s\sThe\ssqlite3_limit()\sAPI\sis\snow\ntested\sand\sworking.\s(CVS\s4899)
+D 2008-03-20T16:30:18
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -95,16 +95,16 @@ F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
 F src/date.c e41ce4513fb0e359dc678d6bddb4ace135fe365d
 F src/delete.c 217cd5559e00bb135dc626d4ea4ac713604729e8
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c 11e00cafa3c6c7e432b06f06c923d1332349354a
+F src/expr.c 8758d120f03f5856b594724732e42497efe00731
 F src/fault.c 039abb45c9dbcbdf575ec2a23ae38db01bc2f7b2
-F src/func.c 3ac6e84e601321519d1b452c95cf92a51403fc4d
+F src/func.c c9e8c7ff4c45027edee89bde7adbf86a3a3b2afe
 F src/hash.c 53655c312280211444bfe23af6490a460aec2980
 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
 F src/insert.c 358c80592c20a61a8d5b4a127215b5e25de652f4
 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
 F src/legacy.c cb1939fdeb91ea88fb44fbd2768a10e14bc44650
 F src/loadext.c f26b22f7c84153c9d5dbd7c240848823c6e6b6dc
-F src/main.c 03a53976e226dfb5867b3102db5b9ec2e40fc0e7
+F src/main.c 24711c8e40107aad521eaa56ddf16068222061db
 F src/malloc.c 60e392a4c12c839517f9b0db7b995f825444fb35
 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
 F src/mem1.c fc716ff521b6dd3e43eaa211967383308800e70a
@@ -130,21 +130,21 @@ F src/os_win.c 3a60bddd07ea6f8adb2314dd5996ac97b988f403
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
 F src/pager.c 22241b59c80ca083a96816df434adb8c097afcd4
 F src/pager.h b1e2258f03878c14b06a95bfa362e8c5c9638170
-F src/parse.y 00f2698c8ae84f315be5e3f10b63c94f531fdd6d
+F src/parse.y b0ee84d94218046ea88c2a6561005710d127ca7d
 F src/pragma.c f64eed914518c28d1863356163dea1e6f58e28f2
 F src/prepare.c 1b71b5d43ba3d88f2d3c2a6d084f28ac209df956
-F src/printf.c 88674589be4b9eac3987ff735e74681864c88c32
+F src/printf.c 05d2b44d7b5b80c8a4a09108ddad9c20e254370d
 F src/random.c 8b6ab5418cf0f4dde551730825d67da1457c2b3c
 F src/select.c 2a0f383a16c780b8ee8108e994c2f6c4f82233a9
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d
-F src/sqlite.h.in be6a431e128b831df7d62fc48b7ce2043f55cf90
+F src/sqlite.h.in 8c9d194ccb6b2b0d00078192c2c4f92d46a7abe4
 F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3
-F src/sqliteInt.h ec78c602dc2675f675ca4f9fbc72e60a262c40e9
+F src/sqliteInt.h c96aca7c69ba463ee09eac19b1ac9974752b467e
 F src/sqliteLimit.h eecbc288b410ae5565e71aaa4a439aae57bb0707
 F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a
 F src/tclsqlite.c d42912617d4734b8f9195416badf5b27e512ded2
-F src/test1.c 935f327fe989694a3aa07ab78ae5c00705651b34
+F src/test1.c aab521bef2a038dfdf1bcafb4f3372285be7d91b
 F src/test2.c da3c4016fc1e08fa1a133ca81591ee8ca99ce8e7
 F src/test3.c 5c7452038ab27aa698070799b10132f26cdd2a80
 F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071
@@ -450,7 +450,7 @@ F test/speed1.test 22e1b27af0683ed44dcd2f93ed817a9c3e65084a
 F test/speed2.test 53177056baf6556dcbdcf032bbdfc41c1aa74ded
 F test/speed3.test e312d7e442a5047d730569fdae2ba99bc94e1a13
 F test/speed4.test 20d8ea20bea3ca09c3ef3b5ec820a17e58e132cb
-F test/sqllimits1.test 29d87be26425de0dd185f6dc24a0440418646a0f
+F test/sqllimits1.test 9ecac01f2f51e3f5f7407a53af2483d096a3f540
 F test/subquery.test 8203f85db56ba022a57a0589890090c8feed4e59
 F test/subselect.test 974e87f8fc91c5f00dd565316d396a5a6c3106c4
 F test/substr.test 4be572ac017143e59b4058dc75c91a0d0dc6d4e0
@@ -624,7 +624,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 60c77882b2de9f6a45f8bd87c9c6a0cc613f8373
-R 470ea6093d2c3208cc1c3a8559153543
-U danielk1977
-Z bc9accc34d4c081a01d0d05b853c649a
+P 53b4a09040341a981b2f33399a1ddcee952ba3ef
+R aff205d8a20c135ccafeedae04a2e788
+U drh
+Z e01b238f8fcef143071d3d310a36fa66
index 39a006d782ae8d93b8c95e2541d9962002eed7fd..c1383387ce0ed29f811eb1872315c5a23b178e3e 100644 (file)
@@ -1 +1 @@
-53b4a09040341a981b2f33399a1ddcee952ba3ef
\ No newline at end of file
+4c4be4c3c8aae97f1d85442b25afba9f0b02c8b3
\ No newline at end of file
index 47f10fc3ba8174b082559dc69f8f97b81e7841bc..7ee47a4e7a3fe31fded7bb5ffbe0bed460d08f86 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.355 2008/03/20 14:03:29 drh Exp $
+** $Id: expr.c,v 1.356 2008/03/20 16:30:18 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -696,10 +696,10 @@ no_mem:
 void sqlite3ExprListCheckLength(
   Parse *pParse,
   ExprList *pEList,
-  int iLimit,
   const char *zObject
 ){
-  if( pEList && pEList->nExpr>iLimit ){
+  int mx = pParse->db->aLimit[SQLITE_LIMIT_COLUMN];
+  if( pEList && pEList->nExpr>mx ){
     sqlite3ErrorMsg(pParse, "too many columns in %s", zObject);
   }
 }
index ebb553947201cda156d4139431c48ef57c69e04c..1c1bbd7e2647e86c86b032941531a16e42ac6e13 100644 (file)
@@ -16,7 +16,7 @@
 ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
 ** All other code has file scope.
 **
-** $Id: func.c,v 1.190 2008/03/20 14:03:29 drh Exp $
+** $Id: func.c,v 1.191 2008/03/20 16:30:18 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -243,7 +243,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
 ** allocation fails, call sqlite3_result_error_nomem() to notify
 ** the database handle that malloc() has failed.
 */
-static void *contextMalloc(sqlite3_context *context, int nByte){
+static void *contextMalloc(sqlite3_context *context, i64 nByte){
   char *z;
   if( nByte>sqlite3_context_db_handle(context)->aLimit[SQLITE_LIMIT_LENGTH] ){
     sqlite3_result_error_toobig(context);
@@ -270,7 +270,7 @@ static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   /* Verify that the call to _bytes() does not invalidate the _text() pointer */
   assert( z2==(char*)sqlite3_value_text(argv[0]) );
   if( z2 ){
-    z1 = contextMalloc(context, n+1);
+    z1 = contextMalloc(context, ((i64)n)+1);
     if( z1 ){
       memcpy(z1, z2, n+1);
       for(i=0; z1[i]; i++){
@@ -290,7 +290,7 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   /* Verify that the call to _bytes() does not invalidate the _text() pointer */
   assert( z2==(char*)sqlite3_value_text(argv[0]) );
   if( z2 ){
-    z1 = contextMalloc(context, n+1);
+    z1 = contextMalloc(context, ((i64)n)+1);
     if( z1 ){
       memcpy(z1, z2, n+1);
       for(i=0; z1[i]; i++){
@@ -694,7 +694,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
       char const *zBlob = sqlite3_value_blob(argv[0]);
       int nBlob = sqlite3_value_bytes(argv[0]);
       assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
-      zText = (char *)contextMalloc(context, (2*nBlob)+4); 
+      zText = (char *)contextMalloc(context, (2*(i64)nBlob)+4); 
       if( zText ){
         int i;
         for(i=0; i<nBlob; i++){
@@ -718,7 +718,7 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
 
       if( zArg==0 ) return;
       for(i=0, n=0; zArg[i]; i++){ if( zArg[i]=='\'' ) n++; }
-      z = contextMalloc(context, i+n+3);
+      z = contextMalloc(context, ((i64)i)+((i64)n)+3);
       if( z ){
         z[0] = '\'';
         for(i=0, j=1; zArg[i]; i++){
@@ -751,7 +751,7 @@ static void hexFunc(
   pBlob = sqlite3_value_blob(argv[0]);
   n = sqlite3_value_bytes(argv[0]);
   assert( pBlob==sqlite3_value_blob(argv[0]) );  /* No encoding change */
-  z = zHex = contextMalloc(context, n*2 + 1);
+  z = zHex = contextMalloc(context, ((i64)n)*2 + 1);
   if( zHex ){
     for(i=0; i<n; i++, pBlob++){
       unsigned char c = *pBlob;
@@ -818,7 +818,7 @@ static void replaceFunc(
   assert( zRep==sqlite3_value_text(argv[2]) );
   nOut = nStr + 1;
   assert( nOut<SQLITE_MAX_LENGTH );
-  zOut = contextMalloc(context, (int)nOut);
+  zOut = contextMalloc(context, (i64)nOut);
   if( zOut==0 ){
     return;
   }
@@ -895,7 +895,7 @@ static void trimFunc(
       SQLITE_SKIP_UTF8(z);
     }
     if( nChar>0 ){
-      azChar = contextMalloc(context, nChar*(sizeof(char*)+1));
+      azChar = contextMalloc(context, ((i64)nChar)*(sizeof(char*)+1));
       if( azChar==0 ){
         return;
       }
index 609cf86fb34ac4b49429370d4f9e5d0c89608262..c472ba320efd09023cd7186f0757685781a7c800 100644 (file)
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.426 2008/03/20 14:03:29 drh Exp $
+** $Id: main.c,v 1.427 2008/03/20 16:30:18 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -933,7 +933,7 @@ static int createCollation(
 ** initializer must be kept in sync with the SQLITE_LIMIT_*
 ** #defines in sqlite3.h.
 */
-static const aHardLimit[] = {
+static const int aHardLimit[] = {
   SQLITE_MAX_LENGTH,
   SQLITE_MAX_SQL_LENGTH,
   SQLITE_MAX_COLUMN,
@@ -942,7 +942,6 @@ static const aHardLimit[] = {
   SQLITE_MAX_VDBE_OP,
   SQLITE_MAX_FUNCTION_ARG,
   SQLITE_MAX_ATTACHED,
-  SQLITE_MAX_PAGE_COUNT,
   SQLITE_MAX_LIKE_PATTERN_LENGTH,
   SQLITE_MAX_VARIABLE_NUMBER,
 };
@@ -977,9 +976,6 @@ static const aHardLimit[] = {
 #if SQLITE_MAX_ATTACH<0 || SQLITE_MAX_ATTACH>30
 # error SQLITE_MAX_ATTACH must be between 0 and 30
 #endif
-#if SQLITE_MAX_PAGE_COUNT<1
-# error SQLITE_MAX_PAGE_COUNT must be at least 1
-#endif
 #if SQLITE_MAX_LIKE_PATTERN_LENGTH<1
 # error SQLITE_MAX_LIKE_PATTERN_LENGTH must be at least 1
 #endif
index 776634195847ea27df9aad6e0d1620a185b0cb40..fee497f4aba9f30218b6821a0fb9efb1b1d0d450 100644 (file)
@@ -14,7 +14,7 @@
 ** the parser.  Lemon will also generate a header file containing
 ** numeric codes for all of the tokens.
 **
-** @(#) $Id: parse.y,v 1.240 2008/01/22 23:37:10 drh Exp $
+** @(#) $Id: parse.y,v 1.241 2008/03/20 16:30:18 drh Exp $
 */
 
 // All token codes are small integers with #defines that begin with "TK_"
@@ -573,7 +573,7 @@ where_opt(A) ::= WHERE expr(X).       {A = X;}
 ////////////////////////// The UPDATE command ////////////////////////////////
 //
 cmd ::= UPDATE orconf(R) fullname(X) SET setlist(Y) where_opt(Z).  {
-  sqlite3ExprListCheckLength(pParse,Y,SQLITE_MAX_COLUMN,"set list"); 
+  sqlite3ExprListCheckLength(pParse,Y,"set list"); 
   sqlite3Update(pParse,X,Y,Z,R);
 }
 
@@ -896,7 +896,7 @@ idxlist(A) ::= idxlist(X) COMMA idxitem(Y) collate(C) sortorder(Z).  {
     sqlite3ExprSetColl(pParse, p, &C);
   }
   A = sqlite3ExprListAppend(pParse,X, p, &Y);
-  sqlite3ExprListCheckLength(pParse, A, SQLITE_MAX_COLUMN, "index");
+  sqlite3ExprListCheckLength(pParse, A, "index");
   if( A ) A->a[A->nExpr-1].sortOrder = Z;
 }
 idxlist(A) ::= idxitem(Y) collate(C) sortorder(Z). {
@@ -906,7 +906,7 @@ idxlist(A) ::= idxitem(Y) collate(C) sortorder(Z). {
     sqlite3ExprSetColl(pParse, p, &C);
   }
   A = sqlite3ExprListAppend(pParse,0, p, &Y);
-  sqlite3ExprListCheckLength(pParse, A, SQLITE_MAX_COLUMN, "index");
+  sqlite3ExprListCheckLength(pParse, A, "index");
   if( A ) A->a[A->nExpr-1].sortOrder = Z;
 }
 idxitem(A) ::= nm(X).              {A = X;}
index 2cd02a85180a87a604ec97ec4743cbc67136b203..4e75257989cb13bc60768454b2c4bfc45db71478 100644 (file)
@@ -735,14 +735,17 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
         return;
       }
     }else{
-      p->nAlloc += p->nAlloc + N + 1;
-      if( p->nAlloc > p->mxAlloc ){
+      i64 szNew = p->nAlloc;
+      szNew += N + 1;
+      if( szNew > p->mxAlloc ){
         p->nAlloc = p->mxAlloc;
-        if( p->nChar+N >= p->nAlloc ){
+        if( ((i64)p->nChar)+((i64)N) >= p->nAlloc ){
           sqlite3StrAccumReset(p);
           p->tooBig = 1;
           return;
         }
+      }else{
+        p->nAlloc = szNew;
       }
       zNew = sqlite3_malloc( p->nAlloc );
       if( zNew ){
index 21a968e6dbf04f06833b6144ace6c7f752f82a68..6032cf8e5a2dbff50f9ae3ca9e085496b4c80b25 100644 (file)
@@ -30,7 +30,7 @@
 ** the version number) and changes its name to "sqlite3.h" as
 ** part of the build process.
 **
-** @(#) $Id: sqlite.h.in,v 1.296 2008/03/20 14:03:29 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.297 2008/03/20 16:30:18 drh Exp $
 */
 #ifndef _SQLITE3_H_
 #define _SQLITE3_H_
@@ -2245,9 +2245,6 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
 ** <dt>SQLITE_LIMIT_ATTACHED</dt>
 ** <dd>The maximum number of attached databases.</dd>
 **
-** <dt>SQLITE_LIMIT_PAGE_COUNT</dt>
-** <dd>The maximum number of pages in a database.</dd>
-**
 ** <dt>SQLITE_LIMIT_LIKE_PATTERN_LENGTH</dt>
 ** <dd>The maximum length of the pattern argument to the LIKE or
 ** GLOB operators.</dd>
@@ -2265,9 +2262,8 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
 #define SQLITE_LIMIT_VDBE_OP                   5
 #define SQLITE_LIMIT_FUNCTION_ARG              6
 #define SQLITE_LIMIT_ATTACHED                  7
-#define SQLITE_LIMIT_PAGE_COUNT                8
-#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH       9
-#define SQLITE_LIMIT_VARIABLE_NUMBER          10
+#define SQLITE_LIMIT_LIKE_PATTERN_LENGTH       8
+#define SQLITE_LIMIT_VARIABLE_NUMBER           9
 
 /*
 ** CAPI3REF: Compiling An SQL Statement {F13010}
index 66a7aebd7a43d84e6e819768ae2c4e2ad7f4eff7..8c7173b2f3fc4b6ddd57e80e40bccd97ca5cbdd5 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.677 2008/03/20 14:03:29 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.678 2008/03/20 16:30:18 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -2069,7 +2069,7 @@ int sqlite3VtabBegin(sqlite3 *, sqlite3_vtab *);
 FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
 void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
 int sqlite3Reprepare(Vdbe*);
-void sqlite3ExprListCheckLength(Parse*, ExprList*, int, const char*);
+void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
 CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
 
 
index 9319eb0b98f6f760cf0bfba70d1fe87aad06acd9..3f718aef62eb1c7e77ca39d955ca4dff82215d89 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test1.c,v 1.293 2008/03/19 14:15:35 drh Exp $
+** $Id: test1.c,v 1.294 2008/03/20 16:30:18 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -4320,6 +4320,62 @@ static int file_control_test(
   return TCL_OK;  
 }
 
+/*
+** tclcmd:   sqlite3_limit DB ID VALUE
+**
+** This TCL command runs the sqlite3_limit interface and
+** verifies correct operation of the same.
+*/
+static int test_limit(
+  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
+  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
+  int objc,              /* Number of arguments */
+  Tcl_Obj *CONST objv[]  /* Command arguments */
+){
+  sqlite3 *db;
+  int rc;
+  static const struct {
+     char *zName;
+     int id;
+  } aId[] = {
+    { "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      },
+  };
+  int i, id;
+  int val;
+  const char *zId;
+
+  if( objc!=4 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"",
+        Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0);
+    return TCL_ERROR;
+  }
+  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+  zId = Tcl_GetString(objv[2]);
+  for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){
+    if( strcmp(zId, aId[i].zName)==0 ){
+      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(db, id, val);
+  Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
+  return TCL_OK;  
+}
+
 /*
 ** tclcmd:  save_prng_state
 */
@@ -4456,6 +4512,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "sqlite3_load_extension",        test_load_extension,     0},
      { "sqlite3_enable_load_extension", test_enable_load,        0},
      { "sqlite3_extended_result_codes", test_extended_result_codes, 0},
+     { "sqlite3_limit",                 test_limit,                 0},
 
      { "save_prng_state",               save_prng_state,    0 },
      { "restore_prng_state",            restore_prng_state, 0 },
index 9db843adbc8d7ae26e00834ab943dc5c9d230691..91f0dfd0e1d90de91c1818dae6f98f39cbd39dff 100644 (file)
 # This file contains tests to verify that the limits defined in
 # sqlite source file limits.h are enforced.
 #
-# $Id: sqllimits1.test,v 1.24 2008/01/31 14:54:44 drh Exp $
+# $Id: sqllimits1.test,v 1.25 2008/03/20 16:30:18 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
 
-# Test organization:
+# Verify that the default per-connection limits are the same as
+# the compile-time hard limits.
 #
-#     sqllimits1-1.*:  SQLITE_MAX_LENGTH
-#     sqllimits1-2.*:  SQLITE_MAX_SQL_LENGTH
-#     sqllimits1-3.*:  SQLITE_MAX_PAGE_COUNT (and the max_page_count pragma)
-#     sqllimits1-4.*:  SQLITE_MAX_COLUMN
-#
-#
-#     sqllimits1-7.*:   SQLITE_MAX_FUNCTION_ARG  
-#     sqllimits1-8.*:   SQLITE_MAX_ATTACHED
-#     sqllimits1-9.*:   SQLITE_MAX_VARIABLE_NUMBER
-#     sqllimits1-10.*:  SQLITE_MAX_PAGE_SIZE
-#     sqllimits1-11.*:  SQLITE_MAX_LIKE_PATTERN_LENGTH
+sqlite3 db2 :memory:
+do_test sqllimits1-1.1 {
+  sqlite3_limit db SQLITE_LIMIT_LENGTH -1
+} $SQLITE_MAX_LENGTH
+do_test sqllimits1-1.2 {
+  sqlite3_limit db SQLITE_LIMIT_SQL_LENGTH -1
+} $SQLITE_MAX_SQL_LENGTH
+do_test sqllimits1-1.3 {
+  sqlite3_limit db SQLITE_LIMIT_COLUMN -1
+} $SQLITE_MAX_COLUMN
+do_test sqllimits1-1.4 {
+  sqlite3_limit db SQLITE_LIMIT_EXPR_DEPTH -1
+} $SQLITE_MAX_EXPR_DEPTH
+do_test sqllimits1-1.5 {
+  sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT -1
+} $SQLITE_MAX_COMPOUND_SELECT
+do_test sqllimits1-1.6 {
+  sqlite3_limit db SQLITE_LIMIT_VDBE_OP -1
+} $SQLITE_MAX_VDBE_OP
+do_test sqllimits1-1.7 {
+  sqlite3_limit db SQLITE_LIMIT_FUNCTION_ARG -1
+} $SQLITE_MAX_FUNCTION_ARG
+do_test sqllimits1-1.8 {
+  sqlite3_limit db SQLITE_LIMIT_ATTACHED -1
+} $SQLITE_MAX_ATTACHED
+do_test sqllimits1-1.9 {
+  sqlite3_limit db SQLITE_LIMIT_LIKE_PATTERN_LENGTH -1
+} $SQLITE_MAX_LIKE_PATTERN_LENGTH
+do_test sqllimits1-1.10 {
+  sqlite3_limit db SQLITE_LIMIT_VARIABLE_NUMBER -1
+} $SQLITE_MAX_VARIABLE_NUMBER
+
+# Decrease all limits by half.  Verify that the new limits take.
 #
-# Todo:
+if {$SQLITE_MAX_LENGTH>=2} {
+  do_test sqllimits1-2.1.1 {
+    sqlite3_limit db SQLITE_LIMIT_LENGTH \
+                    [expr {$::SQLITE_MAX_LENGTH/2}]
+  } $SQLITE_MAX_LENGTH
+  do_test sqllimits1-2.1.2 {
+    sqlite3_limit db SQLITE_LIMIT_LENGTH -1
+  } [expr {$SQLITE_MAX_LENGTH/2}]
+}
+if {$SQLITE_MAX_SQL_LENGTH>=2} {
+  do_test sqllimits1-2.2.1 {
+    sqlite3_limit db SQLITE_LIMIT_SQL_LENGTH \
+                    [expr {$::SQLITE_MAX_SQL_LENGTH/2}]
+  } $SQLITE_MAX_SQL_LENGTH
+  do_test sqllimits1-2.2.2 {
+    sqlite3_limit db SQLITE_LIMIT_SQL_LENGTH -1
+  } [expr {$SQLITE_MAX_SQL_LENGTH/2}]
+}
+if {$SQLITE_MAX_COLUMN>=2} {
+  do_test sqllimits1-2.3.1 {
+    sqlite3_limit db SQLITE_LIMIT_COLUMN \
+                    [expr {$::SQLITE_MAX_COLUMN/2}]
+  } $SQLITE_MAX_COLUMN
+  do_test sqllimits1-2.3.2 {
+    sqlite3_limit db SQLITE_LIMIT_COLUMN -1
+  } [expr {$SQLITE_MAX_COLUMN/2}]
+}
+if {$SQLITE_MAX_EXPR_DEPTH>=2} {
+  do_test sqllimits1-2.4.1 {
+    sqlite3_limit db SQLITE_LIMIT_EXPR_DEPTH \
+                    [expr {$::SQLITE_MAX_EXPR_DEPTH/2}]
+  } $SQLITE_MAX_EXPR_DEPTH
+  do_test sqllimits1-2.4.2 {
+    sqlite3_limit db SQLITE_LIMIT_EXPR_DEPTH -1
+  } [expr {$SQLITE_MAX_EXPR_DEPTH/2}]
+}
+if {$SQLITE_MAX_COMPOUND_SELECT>=2} {
+  do_test sqllimits1-2.5.1 {
+    sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT \
+                    [expr {$::SQLITE_MAX_COMPOUND_SELECT/2}]
+  } $SQLITE_MAX_COMPOUND_SELECT
+  do_test sqllimits1-2.5.2 {
+    sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT -1
+  } [expr {$SQLITE_MAX_COMPOUND_SELECT/2}]
+}
+if {$SQLITE_MAX_VDBE_OP>=2} {
+  do_test sqllimits1-2.6.1 {
+    sqlite3_limit db SQLITE_LIMIT_VDBE_OP \
+                    [expr {$::SQLITE_MAX_VDBE_OP/2}]
+  } $SQLITE_MAX_VDBE_OP
+  do_test sqllimits1-2.6.2 {
+    sqlite3_limit db SQLITE_LIMIT_VDBE_OP -1
+  } [expr {$SQLITE_MAX_VDBE_OP/2}]
+}
+if {$SQLITE_MAX_FUNCTION_ARG>=2} {
+  do_test sqllimits1-2.7.1 {
+    sqlite3_limit db SQLITE_LIMIT_FUNCTION_ARG \
+                    [expr {$::SQLITE_MAX_FUNCTION_ARG/2}]
+  } $SQLITE_MAX_FUNCTION_ARG
+  do_test sqllimits1-2.7.2 {
+    sqlite3_limit db SQLITE_LIMIT_FUNCTION_ARG -1
+  } [expr {$SQLITE_MAX_FUNCTION_ARG/2}]
+}
+if {$SQLITE_MAX_ATTACHED>=2} {
+  do_test sqllimits1-2.8.1 {
+    sqlite3_limit db SQLITE_LIMIT_ATTACHED \
+                    [expr {$::SQLITE_MAX_ATTACHED/2}]
+  } $SQLITE_MAX_ATTACHED
+  do_test sqllimits1-2.8.2 {
+    sqlite3_limit db SQLITE_LIMIT_ATTACHED -1
+  } [expr {$SQLITE_MAX_ATTACHED/2}]
+}
+if {$SQLITE_MAX_LIKE_PATTERN_LENGTH>=2} {
+  do_test sqllimits1-2.9.1 {
+    sqlite3_limit db SQLITE_LIMIT_LIKE_PATTERN_LENGTH \
+                    [expr {$::SQLITE_MAX_LIKE_PATTERN_LENGTH/2}]
+  } $SQLITE_MAX_LIKE_PATTERN_LENGTH
+  do_test sqllimits1-2.9.2 {
+    sqlite3_limit db SQLITE_LIMIT_LIKE_PATTERN_LENGTH -1
+  } [expr {$SQLITE_MAX_LIKE_PATTERN_LENGTH/2}]
+}
+if {$SQLITE_MAX_VARIABLE_NUMBER>=2} {
+  do_test sqllimits1-2.10.1 {
+    sqlite3_limit db SQLITE_LIMIT_VARIABLE_NUMBER \
+                    [expr {$::SQLITE_MAX_VARIABLE_NUMBER/2}]
+  } $SQLITE_MAX_VARIABLE_NUMBER
+  do_test sqllimits1-2.10.2 {
+    sqlite3_limit db SQLITE_LIMIT_VARIABLE_NUMBER -1
+  } [expr {$SQLITE_MAX_VARIABLE_NUMBER/2}]
+}
+
+# In a separate database connection, verify that the limits are unchanged.
 #
-#     sqllimits1-5.*:   SQLITE_MAX_EXPR_DEPTH            (sqlite todo)
-#     sqllimits1-6.*:   SQLITE_MAX_VDBE_OP               (sqlite todo)
-#     sqllimits1-12.*:  SQLITE_MAX_PAGE_COUNT            (sqlite todo)
+do_test sqllimits1-3.1 {
+  sqlite3_limit db2 SQLITE_LIMIT_LENGTH -1
+} $SQLITE_MAX_LENGTH
+do_test sqllimits1-3.2 {
+  sqlite3_limit db2 SQLITE_LIMIT_SQL_LENGTH -1
+} $SQLITE_MAX_SQL_LENGTH
+do_test sqllimits1-3.3 {
+  sqlite3_limit db2 SQLITE_LIMIT_COLUMN -1
+} $SQLITE_MAX_COLUMN
+do_test sqllimits1-3.4 {
+  sqlite3_limit db2 SQLITE_LIMIT_EXPR_DEPTH -1
+} $SQLITE_MAX_EXPR_DEPTH
+do_test sqllimits1-3.5 {
+  sqlite3_limit db2 SQLITE_LIMIT_COMPOUND_SELECT -1
+} $SQLITE_MAX_COMPOUND_SELECT
+do_test sqllimits1-3.6 {
+  sqlite3_limit db2 SQLITE_LIMIT_VDBE_OP -1
+} $SQLITE_MAX_VDBE_OP
+do_test sqllimits1-3.7 {
+  sqlite3_limit db2 SQLITE_LIMIT_FUNCTION_ARG -1
+} $SQLITE_MAX_FUNCTION_ARG
+do_test sqllimits1-3.8 {
+  sqlite3_limit db2 SQLITE_LIMIT_ATTACHED -1
+} $SQLITE_MAX_ATTACHED
+do_test sqllimits1-3.9 {
+  sqlite3_limit db2 SQLITE_LIMIT_LIKE_PATTERN_LENGTH -1
+} $SQLITE_MAX_LIKE_PATTERN_LENGTH
+do_test sqllimits1-3.10 {
+  sqlite3_limit db2 SQLITE_LIMIT_VARIABLE_NUMBER -1
+} $SQLITE_MAX_VARIABLE_NUMBER
+db2 close
+
+# Attempt to set all limits to the maximum 32-bit integer.  Verify
+# that the limit does not exceed the compile-time upper bound.
 #
+do_test sqllimits1-4.1.1 {
+  sqlite3_limit db SQLITE_LIMIT_LENGTH 0x7fffffff
+  sqlite3_limit db SQLITE_LIMIT_LENGTH -1
+} $SQLITE_MAX_LENGTH
+do_test sqllimits1-4.2.1 {
+  sqlite3_limit db SQLITE_LIMIT_SQL_LENGTH 0x7fffffff
+  sqlite3_limit db SQLITE_LIMIT_SQL_LENGTH -1
+} $SQLITE_MAX_SQL_LENGTH
+do_test sqllimits1-4.3.1 {
+  sqlite3_limit db SQLITE_LIMIT_COLUMN 0x7fffffff
+  sqlite3_limit db SQLITE_LIMIT_COLUMN -1
+} $SQLITE_MAX_COLUMN
+do_test sqllimits1-4.4.1 {
+  sqlite3_limit db SQLITE_LIMIT_EXPR_DEPTH 0x7fffffff
+  sqlite3_limit db SQLITE_LIMIT_EXPR_DEPTH -1
+} $SQLITE_MAX_EXPR_DEPTH
+do_test sqllimits1-4.5.1 {
+  sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT 0x7fffffff
+  sqlite3_limit db SQLITE_LIMIT_COMPOUND_SELECT -1
+} $SQLITE_MAX_COMPOUND_SELECT
+do_test sqllimits1-4.6.1 {
+  sqlite3_limit db SQLITE_LIMIT_VDBE_OP 0x7fffffff
+  sqlite3_limit db SQLITE_LIMIT_VDBE_OP -1
+} $SQLITE_MAX_VDBE_OP
+do_test sqllimits1-4.7.1 {
+  sqlite3_limit db SQLITE_LIMIT_FUNCTION_ARG 0x7fffffff
+  sqlite3_limit db SQLITE_LIMIT_FUNCTION_ARG -1
+} $SQLITE_MAX_FUNCTION_ARG
+do_test sqllimits1-4.8.1 {
+  sqlite3_limit db SQLITE_LIMIT_ATTACHED 0x7fffffff
+  sqlite3_limit db SQLITE_LIMIT_ATTACHED -1
+} $SQLITE_MAX_ATTACHED
+do_test sqllimits1-4.9.1 {
+  sqlite3_limit db SQLITE_LIMIT_LIKE_PATTERN_LENGTH 0x7fffffff
+  sqlite3_limit db SQLITE_LIMIT_LIKE_PATTERN_LENGTH -1
+} $SQLITE_MAX_LIKE_PATTERN_LENGTH
+do_test sqllimits1-4.10.1 {
+  sqlite3_limit db SQLITE_LIMIT_VARIABLE_NUMBER 0x7fffffff
+  sqlite3_limit db SQLITE_LIMIT_VARIABLE_NUMBER -1
+} $SQLITE_MAX_VARIABLE_NUMBER
 
-unset -nocomplain saved
-foreach var [info vars SQLITE_MAX_*] {
-  set saved($var) [set $var]
-}
 
-set SQLITE_MAX_LENGTH                 100000
-set SQLITE_MAX_COLUMN
-set SQLITE_MAX_SQL_LENGTH              50000
-set SQLITE_MAX_EXPR_DEPTH               1000
-set SQLITE_MAX_COMPOUND_SELECT             5
-set SQLITE_MAX_VDBE_OP
-set SQLITE_MAX_FUNCTION_ARG
-set SQLITE_MAX_VARIABLE_NUMBER
-set SQLITE_MAX_PAGE_SIZE
-set SQLITE_MAX_PAGE_COUNT
-set SQLITE_MAX_LIKE_PATTERN_LENGTH      1000
 
 #--------------------------------------------------------------------
-# Test cases sqllimits1-1.* test that the SQLITE_MAX_LENGTH limit
+# Test cases sqllimits1-5.* test that the SQLITE_MAX_LENGTH limit
 # is enforced.
 #
-do_test sqllimits1-1.1.1 {
+db close
+sqlite3 db test.db
+set LARGESIZE 99999
+set SQLITE_LIMIT_LENGTH 100000
+sqlite3_limit db SQLITE_LIMIT_LENGTH $SQLITE_LIMIT_LENGTH
+
+do_test sqllimits1-5.1.1 {
   catchsql { SELECT randomblob(2147483647) }
 } {1 {string or blob too big}}
-do_test sqllimits1-1.1.2 {
+do_test sqllimits1-5.1.2 {
   catchsql { SELECT zeroblob(2147483647) }
 } {1 {string or blob too big}}
 
-# Large, but allowable, blob-size.
-#
-set ::LARGESIZE [expr $SQLITE_MAX_LENGTH - 1] 
-
-do_test sqllimits1-1.2 {
+do_test sqllimits1-5.2 {
   catchsql { SELECT LENGTH(randomblob($::LARGESIZE)) }
-} "0 $::LARGESIZE"
+} [list 0 $LARGESIZE]
 
-do_test sqllimits1-1.3 {
+do_test sqllimits1-5.3 {
   catchsql { SELECT quote(randomblob($::LARGESIZE)) }
 } {1 {string or blob too big}}
 
-do_test sqllimits1-1.4 {
+do_test sqllimits1-5.4 {
   catchsql { SELECT LENGTH(zeroblob($::LARGESIZE)) }
-} "0 $::LARGESIZE"
+} [list 0 $LARGESIZE]
 
-do_test sqllimits1-1.5 {
+do_test sqllimits1-5.5 {
   catchsql { SELECT quote(zeroblob($::LARGESIZE)) }
 } {1 {string or blob too big}}
 
-do_test sqllimits1-1.6 {
+do_test sqllimits1-5.6 {
   catchsql { SELECT zeroblob(-1) }
 } {0 {{}}}
 
-do_test sqllimits1-1.9 {
+do_test sqllimits1-5.9 {
   set ::str [string repeat A 65537]
   set ::rep [string repeat B 65537]
   catchsql { SELECT replace($::str, 'A', $::rep) }
 } {1 {string or blob too big}}
 
-do_test sqllimits1-1.10 {
+do_test sqllimits1-5.10 {
   set ::str [string repeat %J 2100]
   catchsql { SELECT strftime($::str, '2003-10-31') }
 } {1 {string or blob too big}}
 
-do_test sqllimits1-1.11 {
-  set ::str1 [string repeat A [expr {$SQLITE_MAX_LENGTH - 10}]]
-  set ::str2 [string repeat B [expr {$SQLITE_MAX_LENGTH - 10}]]
+do_test sqllimits1-5.11 {
+  set ::str1 [string repeat A [expr {$SQLITE_LIMIT_LENGTH - 10}]]
+  set ::str2 [string repeat B [expr {$SQLITE_LIMIT_LENGTH - 10}]]
   catchsql { SELECT $::str1 || $::str2 }
 } {1 {string or blob too big}}
 
-do_test sqllimits1-1.12 {
-  set ::str1 [string repeat ' [expr {$SQLITE_MAX_LENGTH - 10}]]
+do_test sqllimits1-5.12 {
+  set ::str1 [string repeat ' [expr {$SQLITE_LIMIT_LENGTH - 10}]]
   catchsql { SELECT quote($::str1) }
 } {1 {string or blob too big}}
 
-do_test sqllimits1-1.13 {
-  set ::str1 [string repeat ' [expr {$SQLITE_MAX_LENGTH - 10}]]
+do_test sqllimits1-5.13 {
+  set ::str1 [string repeat ' [expr {$SQLITE_LIMIT_LENGTH - 10}]]
   catchsql { SELECT hex($::str1) }
 } {1 {string or blob too big}}
 
-do_test sqllimits1-1.14.1 {
+do_test sqllimits1-5.14.1 {
   set ::STMT [sqlite3_prepare $::DB "SELECT ?" -1 TAIL]
-  sqlite3_bind_zeroblob $::STMT 1 [expr {$SQLITE_MAX_LENGTH + 1}]
+  sqlite3_bind_zeroblob $::STMT 1 [expr {$SQLITE_LIMIT_LENGTH + 1}]
 } {}
-do_test sqllimits1-1.14.2 {
+do_test sqllimits1-5.14.2 {
   sqlite3_step $::STMT 
 } {SQLITE_ERROR}
-do_test sqllimits1-1.14.3 {
+do_test sqllimits1-5.14.3 {
   sqlite3_finalize $::STMT 
 } {SQLITE_TOOBIG}
 
-do_test sqllimits1-1.15 {
+do_test sqllimits1-5.15 {
   execsql {
     CREATE TABLE t4(x);
     INSERT INTO t4 VALUES(1);
@@ -141,80 +313,79 @@ do_test sqllimits1-1.15 {
 } {1 {string or blob too big}}
 db eval {DROP TABLE t4}
 
-set ::SQLITE_MAX_SQL_LENGTH 0
-set strvalue [string repeat A $::SQLITE_MAX_LENGTH]
-do_test sqllimits1-1.16 {
+sqlite3_limit db SQLITE_LIMIT_SQL_LENGTH 0x7fffffff
+set strvalue [string repeat A $::SQLITE_LIMIT_LENGTH]
+do_test sqllimits1-5.16 {
   catchsql "SELECT '$strvalue'"
 } [list 0 $strvalue]
-do_test sqllimits1-1.17 {
+do_test sqllimits1-5.17 {
   catchsql "SELECT 'A$strvalue'"
 } [list 1 {string or blob too big}]
-set blobvalue [string repeat 41 $::SQLITE_MAX_LENGTH]
-do_test sqllimits1-1.18 {
+set blobvalue [string repeat 41 $::SQLITE_LIMIT_LENGTH]
+do_test sqllimits1-5.18 {
   catchsql "SELECT x'$blobvalue'"
 } [list 0 $strvalue]
-do_test sqllimits1-1.19 {
+do_test sqllimits1-5.19 {
   catchsql "SELECT '41$blobvalue'"
 } [list 1 {string or blob too big}]
 unset blobvalue
 
 ifcapable datetime {
-  set strvalue [string repeat D [expr {$SQLITE_MAX_LENGTH-12}]]
-  do_test sqllimits1-1.20 {
+  set strvalue [string repeat D [expr {$SQLITE_LIMIT_LENGTH-12}]]
+  do_test sqllimits1-5.20 {
     catchsql {SELECT strftime('%Y ' || $::strvalue, '2008-01-02')}
   } [list 0 [list "2008 $strvalue"]]
-  do_test sqllimits1-1.21 {
+  do_test sqllimits1-5.21 {
     catchsql {SELECT strftime('%Y-%m-%d ' || $::strvalue, '2008-01-02')}
   } {1 {string or blob too big}}
 }
 unset strvalue
 
 #--------------------------------------------------------------------
-# Test cases sqllimits1-2.* test that the SQLITE_MAX_SQL_LENGTH limit
+# Test cases sqllimits1-6.* test that the SQLITE_MAX_SQL_LENGTH limit
 # is enforced.
 #
-do_test sqllimits1-2.1 {
-  set ::SQLITE_MAX_SQL_LENGTH 50000
+do_test sqllimits1-6.1 {
+  sqlite3_limit db SQLITE_LIMIT_SQL_LENGTH 50000
   set sql "SELECT 1 WHERE 1==1"
   set tail " /* A comment to take up space in order to make the string\
                 longer without increasing the expression depth */\
                 AND   1  ==  1"
-  set N [expr {($::SQLITE_MAX_SQL_LENGTH / [string length $tail])+1}]
+  set N [expr {(50000 / [string length $tail])+1}]
   append sql [string repeat $tail $N]
   catchsql $sql
 } {1 {String or BLOB exceeded size limit}}
-do_test sqllimits1-2.2 {
-  set ::SQLITE_MAX_SQL_LENGTH 0
+do_test sqllimits1-6.2 {
+  sqlite3_limit db SQLITE_LIMIT_SQL_LENGTH 0
   catchsql $sql
 } {0 1}
-do_test sqllimits1-2.3 {
-  set ::SQLITE_MAX_SQL_LENGTH 50000
+do_test sqllimits1-6.3 {
+  sqlite3_limit db SQLITE_LIMIT_SQL_LENGTH 50000
   set sql "SELECT 1 WHERE 1==1"
   set tail " /* A comment to take up space in order to make the string\
                 longer without increasing the expression depth */\
                 AND   1  ==  1"
-  set N [expr {($::SQLITE_MAX_SQL_LENGTH / [string length $tail])+1}]
+  set N [expr {(50000 / [string length $tail])+1}]
   append sql [string repeat $tail $N]
   set nbytes [string length $sql]
   append sql { AND 0}
   set rc [catch {sqlite3_prepare $DB $sql $nbytes TAIL} STMT]
   lappend rc $STMT
 } {1 {(18) statement too long}}
-do_test sqllimits1-2.4 {
+do_test sqllimits1-6.4 {
   sqlite3_errmsg $DB
 } {statement too long}
 
-
 #--------------------------------------------------------------------
-# Test cases sqllimits1-3.* test that the limit set using the
+# Test cases sqllimits1-7.* test that the limit set using the
 # max_page_count pragma.
 #
-do_test sqllimits1-3.1 {
+do_test sqllimits1-7.1 {
   execsql {
     PRAGMA max_page_count = 1000;
   }
 } {1000}
-do_test sqllimits1-3.2 {
+do_test sqllimits1-7.2 {
   execsql { CREATE TABLE trig (a INTEGER, b INTEGER); }
 
   # Set up a tree of triggers to fire when a row is inserted
@@ -261,13 +432,13 @@ do_test sqllimits1-3.2 {
   }
 } {}
 
-do_test sqllimits1-3.3 {
+do_test sqllimits1-7.3 {
   execsql {
     INSERT INTO trig VALUES (1,1); 
   }
 } {}
 
-do_test sqllimits1-3.4 {
+do_test sqllimits1-7.4 {
   execsql {
     SELECT COUNT(*) FROM trig;
   }
@@ -276,13 +447,13 @@ do_test sqllimits1-3.4 {
 # This tries to insert so many rows it fills up the database (limited
 # to 1MB, so not that noteworthy an achievement).
 #
-do_test sqllimits1-3.5 {
+do_test sqllimits1-7.5 {
   catchsql {
     INSERT INTO trig VALUES (1,10);
   }
 } {1 {database or disk is full}}
 
-do_test sqllimits1-3.6 {
+do_test sqllimits1-7.6 {
   catchsql {
     SELECT COUNT(*) FROM trig;
   }
@@ -296,7 +467,7 @@ if {[db eval {PRAGMA auto_vacuum}]} {
 } else {
    set fsize 1691
 }
-do_test sqllimits1-3.7.1 {
+do_test sqllimits1-7.7.1 {
   execsql {
     PRAGMA max_page_count = 1000000;
     CREATE TABLE abc(a, b, c);
@@ -315,7 +486,7 @@ do_test sqllimits1-3.7.1 {
   }
   expr [file size test.db] / 1024
 } $fsize
-do_test sqllimits1-3.7.2 {
+do_test sqllimits1-7.7.2 {
   db close
   sqlite3 db test.db
   execsql {
@@ -325,51 +496,53 @@ do_test sqllimits1-3.7.2 {
     SELECT count(*) FROM sqlite_master;
   }
 } {6}
-do_test sqllimits1-3.7.3 {
+do_test sqllimits1-7.7.3 {
   execsql {
     PRAGMA max_page_count;
   }
 } $fsize
-do_test sqllimits1-3.7.4 {
+do_test sqllimits1-7.7.4 {
   execsql {
     DROP TABLE abc;
   }
 } {}
 
 #--------------------------------------------------------------------
-# Test cases sqllimits1-4.* test the SQLITE_MAX_COLUMN limit.
+# Test cases sqllimits1-8.* test the SQLITE_MAX_COLUMN limit.
 #
-do_test sqllimits1-4.1 {
+set SQLITE_LIMIT_COLUMN 200
+sqlite3_limit db SQLITE_LIMIT_COLUMN $SQLITE_LIMIT_COLUMN
+do_test sqllimits1-8.1 {
   # Columns in a table.
   set cols [list]
-  for {set i 0} {$i <= $SQLITE_MAX_COLUMN} {incr i} {
+  for {set i 0} {$i <= $SQLITE_LIMIT_COLUMN} {incr i} {
     lappend cols "c$i"
   }
   catchsql "CREATE TABLE t([join $cols ,])" 
 } {1 {too many columns on t}}
 
-do_test sqllimits1-4.2 {
+do_test sqllimits1-8.2 {
   # Columns in the result-set of a SELECT.
   set cols [list]
-  for {set i 0} {$i <= $SQLITE_MAX_COLUMN} {incr i} {
+  for {set i 0} {$i <= $SQLITE_LIMIT_COLUMN} {incr i} {
     lappend cols "sql AS sql$i"
   }
   catchsql "SELECT [join $cols ,] FROM sqlite_master"
 } {1 {too many columns in result set}}
 
-do_test sqllimits1-4.3 {
+do_test sqllimits1-8.3 {
   # Columns in the result-set of a sub-SELECT.
   set cols [list]
-  for {set i 0} {$i <= $SQLITE_MAX_COLUMN} {incr i} {
+  for {set i 0} {$i <= $SQLITE_LIMIT_COLUMN} {incr i} {
     lappend cols "sql AS sql$i"
   }
   catchsql "SELECT sql4 FROM (SELECT [join $cols ,] FROM sqlite_master)"
 } {1 {too many columns in result set}}
 
-do_test sqllimits1-4.4 {
+do_test sqllimits1-8.4 {
   # Columns in an index.
   set cols [list]
-  for {set i 0} {$i <= $SQLITE_MAX_COLUMN} {incr i} {
+  for {set i 0} {$i <= $SQLITE_LIMIT_COLUMN} {incr i} {
     lappend cols c
   }
   set sql1 "CREATE TABLE t1(c);"
@@ -377,38 +550,38 @@ do_test sqllimits1-4.4 {
   catchsql "$sql1 ; $sql2"
 } {1 {too many columns in index}}
 
-do_test sqllimits1-4.5 {
+do_test sqllimits1-8.5 {
   # Columns in a GROUP BY clause.
   catchsql "SELECT * FROM t1 GROUP BY [join $cols ,]"
 } {1 {too many terms in GROUP BY clause}}
 
-do_test sqllimits1-4.6 {
+do_test sqllimits1-8.6 {
   # Columns in an ORDER BY clause.
   catchsql "SELECT * FROM t1 ORDER BY [join $cols ,]"
 } {1 {too many terms in ORDER BY clause}}
 
-do_test sqllimits1-4.7 {
+do_test sqllimits1-8.7 {
   # Assignments in an UPDATE statement.
   set cols [list]
-  for {set i 0} {$i <= $SQLITE_MAX_COLUMN} {incr i} {
+  for {set i 0} {$i <= $SQLITE_LIMIT_COLUMN} {incr i} {
     lappend cols "c = 1"
   }
   catchsql "UPDATE t1 SET [join $cols ,];"
 } {1 {too many columns in set list}}
 
-do_test sqllimits1-4.8 {
+do_test sqllimits1-8.8 {
   # Columns in a view definition:
   set cols [list]
-  for {set i 0} {$i <= $SQLITE_MAX_COLUMN} {incr i} {
+  for {set i 0} {$i <= $SQLITE_LIMIT_COLUMN} {incr i} {
     lappend cols "c$i"
   }
   catchsql "CREATE VIEW v1 AS SELECT [join $cols ,] FROM t1;"
 } {1 {too many columns in result set}}
 
-do_test sqllimits1-4.9 {
+do_test sqllimits1-8.9 {
   # Columns in a view definition (testing * expansion):
   set cols [list]
-  for {set i 0} {$i < $SQLITE_MAX_COLUMN} {incr i} {
+  for {set i 0} {$i < $SQLITE_LIMIT_COLUMN} {incr i} {
     lappend cols "c$i"
   }
   catchsql "CREATE TABLE t2([join $cols ,])"
@@ -416,15 +589,15 @@ do_test sqllimits1-4.9 {
 } {1 {too many columns in result set}}
 
 #--------------------------------------------------------------------
-# These tests - sqllimits1-5.* - test that the SQLITE_MAX_EXPR_DEPTH
+# These tests - sqllimits1-9.* - test that the SQLITE_LIMIT_EXPR_DEPTH
 # limit is enforced. The limit refers to the number of terms in 
 # the expression.
 #
-if {$::SQLITE_MAX_EXPR_DEPTH != 1000} {
+if {$SQLITE_MAX_EXPR_DEPTH==0} {
   puts -nonewline stderr "WARNING: Compile with -DSQLITE_MAX_EXPR_DEPTH to run "
-  puts stderr "tests sqllimits1-5.X"
+  puts stderr "tests sqllimits1-9.X"
 } else {
-  do_test sqllimits1-5.1 {
+  do_test sqllimits1-9.1 {
     set max $::SQLITE_MAX_EXPR_DEPTH
     set expr "(1 [string repeat {AND 1 } $max])"
     catchsql [subst {
@@ -434,7 +607,7 @@ if {$::SQLITE_MAX_EXPR_DEPTH != 1000} {
   
   # Attempting to beat the expression depth limit using nested SELECT
   # queries causes a parser stack overflow. 
-  do_test sqllimits1-5.2 {
+  do_test sqllimits1-9.2 {
     set max $::SQLITE_MAX_EXPR_DEPTH
     set expr "SELECT 1"
     for {set i 0} {$i <= $max} {incr i} {
@@ -444,7 +617,7 @@ if {$::SQLITE_MAX_EXPR_DEPTH != 1000} {
   } "1 {parser stack overflow}"
   
   
-  do_test sqllimits1-5.3 {
+  do_test sqllimits1-9.3 {
     execsql {
       PRAGMA max_page_count = 1000000;  -- 1 GB
       CREATE TABLE v0(a);
@@ -460,7 +633,7 @@ if {$::SQLITE_MAX_EXPR_DEPTH != 1000} {
     }
   } {}
   
-  do_test sqllimits1-5.4 {
+  do_test sqllimits1-9.4 {
     catchsql {
       SELECT a FROM v199
     }
@@ -468,17 +641,17 @@ if {$::SQLITE_MAX_EXPR_DEPTH != 1000} {
 }
 
 #--------------------------------------------------------------------
-# Test cases sqllimits1-6.* test that the SQLITE_MAX_VDBE_OP
+# Test cases sqllimits1-10.* test that the SQLITE_MAX_VDBE_OP
 # limit works as expected. The limit refers to the number of opcodes
 # in a single VDBE program.
 #
 # TODO
 
 #--------------------------------------------------------------------
-# Test the SQLITE_MAX_FUNCTION_ARG limit works. Test case names
-# match the pattern "sqllimits1-7.*".
+# Test the SQLITE_LIMIT_FUNCTION_ARG limit works. Test case names
+# match the pattern "sqllimits1-11.*".
 #
-do_test sqllimits1-7.1 {
+do_test sqllimits1-11.1 {
   set max $::SQLITE_MAX_FUNCTION_ARG
   set vals [list]
   for {set i 0} {$i < $SQLITE_MAX_FUNCTION_ARG} {incr i} {
@@ -486,7 +659,7 @@ do_test sqllimits1-7.1 {
   }
   catchsql "SELECT max([join $vals ,])"
 } "0 [expr {$::SQLITE_MAX_FUNCTION_ARG - 1}]"
-do_test sqllimits1-7.2 {
+do_test sqllimits1-11.2 {
   set max $::SQLITE_MAX_FUNCTION_ARG
   set vals [list]
   for {set i 0} {$i <= $SQLITE_MAX_FUNCTION_ARG} {incr i} {
@@ -498,7 +671,7 @@ do_test sqllimits1-7.2 {
 # Test that it is SQLite, and not the implementation of the
 # user function that is throwing the error.
 proc myfunc {args} {error "I don't like to be called!"}
-do_test sqllimits1-7.2 {
+do_test sqllimits1-11.2 {
   db function myfunc myfunc
   set max $::SQLITE_MAX_FUNCTION_ARG
   set vals [list]
@@ -508,11 +681,12 @@ do_test sqllimits1-7.2 {
   catchsql "SELECT myfunc([join $vals ,])"
 } {1 {too many arguments on function myfunc}}
 
+
 #--------------------------------------------------------------------
-# Test cases sqllimits1-8.*: Test the SQLITE_MAX_ATTACHED limit.
+# Test cases sqllimits1-12.*: Test the SQLITE_MAX_ATTACHED limit.
 #
 ifcapable attach {
-  do_test sqllimits1-8.1 {
+  do_test sqllimits1-12.1 {
     set max $::SQLITE_MAX_ATTACHED
     for {set i 0} {$i < ($max)} {incr i} {
       file delete -force test${i}.db test${i}.db-journal
@@ -522,7 +696,7 @@ ifcapable attach {
     }
     catchsql "ATTACH 'test${i}.db' AS aux${i}"
   } "1 {too many attached databases - max $::SQLITE_MAX_ATTACHED}"
-  do_test sqllimits1-8.2 {
+  do_test sqllimits1-12.2 {
     set max $::SQLITE_MAX_ATTACHED
     for {set i 0} {$i < ($max)} {incr i} {
       execsql "DETACH aux${i}"
@@ -531,14 +705,14 @@ ifcapable attach {
 }
 
 #--------------------------------------------------------------------
-# Test cases sqllimits1-9.*: Check that the SQLITE_MAX_VARIABLE_NUMBER 
+# Test cases sqllimits1-13.*: Check that the SQLITE_MAX_VARIABLE_NUMBER 
 # limit works.
 #
-do_test sqllimits1-9.1 {
+do_test sqllimits1-13.1 {
   set max $::SQLITE_MAX_VARIABLE_NUMBER
   catchsql "SELECT ?[expr {$max+1}] FROM t1"
 } "1 {variable number must be between ?1 and ?$::SQLITE_MAX_VARIABLE_NUMBER}"
-do_test sqllimits1-9.2 {
+do_test sqllimits1-13.2 {
   set max $::SQLITE_MAX_VARIABLE_NUMBER
   set vals [list]
   for {set i 0} {$i < ($max+3)} {incr i} {
@@ -549,57 +723,7 @@ do_test sqllimits1-9.2 {
 
 
 #--------------------------------------------------------------------
-# sqllimits1-10.*:  Test the SQLITE_MAX_PAGE_SIZE define is enforced. 
-# This is probably tested elsewhere too (pagerX.test). Attempts
-# to raise the page size above this limit are silently ignored.
-#
-do_test sqllimits1-10.1 {
-  db close
-  file delete -force test.db test.db-journal
-  sqlite3 db test.db
-  set max $::SQLITE_MAX_PAGE_SIZE
-  catchsql "PRAGMA page_size = [expr {$max*2}]"
-} {0 {}}
-do_test sqllimits1-10.2 {
-  catchsql "PRAGMA page_size"
-} {0 1024}
-do_test sqllimits1-10.3 {
-  set max $::SQLITE_MAX_PAGE_SIZE
-  catchsql "PRAGMA page_size = $max"
-} {0 {}}
-do_test sqllimits1-10.4 {
-  execsql "pragma page_size"
-} $::SQLITE_MAX_PAGE_SIZE
-do_test sqllimits1-10.5 {
-  set max $::SQLITE_MAX_PAGE_SIZE
-  execsql "pragma page_size = [expr {$max - 5}]"
-  execsql "pragma page_size"
-} $::SQLITE_MAX_PAGE_SIZE
-
-# Opening a database where the page size is too large should generate
-# an error.
-#
-do_test sqllimits1-10.5 {
-  db close
-  file delete -force test.db
-  set ::SQLITE_MAX_PAGE_SIZE 32768
-  sqlite3 db test.db
-  db eval {PRAGMA page_size=32768}
-  db eval {CREATE TABLE t1(x);}
-  db eval {PRAGMA page_size}
-} {32768}
-do_test sqllimits1-10.6 {
-  db close
-  set ::SQLITE_MAX_PAGE_SIZE 8192
-  sqlite3 db test.db
-  catchsql {SELECT name FROM sqlite_master}
-} {1 {file is encrypted or is not a database}}
-db close
-file delete -force test.db
-sqlite3 db test.db
-
-#--------------------------------------------------------------------
-# Test cases sqllimits1-11.* verify that the 
+# Test cases sqllimits1-15.* verify that the 
 # SQLITE_MAX_LIKE_PATTERN_LENGTH limit is enforced. This limit only
 # applies to the built-in LIKE operator, supplying an external 
 # implementation by overriding the like() scalar function bypasses
@@ -609,16 +733,18 @@ sqlite3 db test.db
 # the left-hand-side of the LIKE operator (the string being tested
 # against the pattern).
 #
-do_test sqllimits1-11.1 {
-  set max $::SQLITE_MAX_LIKE_PATTERN_LENGTH
+set SQLITE_LIMIT_LIKE_PATTERN 1000
+sqlite3_limit db SQLITE_LIMIT_LIKE_PATTERN_LENGTH $SQLITE_LIMIT_LIKE_PATTERN
+do_test sqllimits1-15.1 {
+  set max $::SQLITE_LIMIT_LIKE_PATTERN
   set ::pattern [string repeat "A%" [expr $max/2]]
   set ::string  [string repeat "A" [expr {$max*2}]]
   execsql {
     SELECT $::string LIKE $::pattern;
   }
 } {1}
-do_test sqllimits1-11.2 {
-  set max $::SQLITE_MAX_LIKE_PATTERN_LENGTH
+do_test sqllimits1-15.2 {
+  set max $::SQLITE_LIMIT_LIKE_PATTERN
   set ::pattern [string repeat "A%" [expr {($max/2) + 1}]]
   set ::string  [string repeat "A" [expr {$max*2}]]
   catchsql {
@@ -630,11 +756,11 @@ do_test sqllimits1-11.2 {
 # This test case doesn't really belong with the other limits tests.
 # It is in this file because it is taxing to run, like the limits tests.
 #
-do_test sqllimits1-12.1 {
+do_test sqllimits1-16.1 {
   set ::N [expr int(([expr pow(2,32)]/50) + 1)]
   expr (($::N*50) & 0xffffffff)<55
 } {1}
-do_test sqllimits1-12.2 {
+do_test sqllimits1-16.2 {
   set ::format "[string repeat A 60][string repeat "%J" $::N]"
   catchsql {
     SELECT strftime($::format, 1);