SQLite4
Check-in [6833c6df33]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Remove the error message output parameter from sqlite4_exec().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6833c6df33e7596fcb525654d8f4f4da8e9b1564
User & Date: dan 2013-06-07 14:22:17
Context
2013-06-07
14:36
Change the order of the parameters passed to sqlite4_collation_needed() and needed16() to be consistent with other callback APIs. check-in: 22b6bdf65a user: dan tags: trunk
14:22
Remove the error message output parameter from sqlite4_exec(). check-in: 6833c6df33 user: dan tags: trunk
02:00
Replace placeholder sqlite4_num_to_int32. Change API to be analogous sqlite4_num_to_int64. Add tests. check-in: 762134b4a8 user: peterreid tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/legacy.c.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
** argument to xCall().  If xCall=NULL then no callback
** is invoked, even for queries.
*/
int sqlite4_exec(
  sqlite4 *db,                /* The database on which the SQL executes */
  const char *zSql,           /* The SQL to be executed */
  int (*xCall)(void*,int,sqlite4_value**,const char**),  /* Callback function */
  void *pArg,                 /* First argument to xCall() */
  char **pzErrMsg             /* Write error messages here */
){
  int rc = SQLITE4_OK;        /* Return code */
  int nRetry = 0;             /* Number of retry attempts */
  int bAbort = 0;             /* Set to true if callback returns non-zero */

  if( !sqlite4SafetyCheckOk(db) ) return SQLITE4_MISUSE_BKPT;
  if( zSql==0 ) zSql = "";
................................................................................

    sqlite4DbFree(db, azCol);
  }

  if( bAbort ) rc = SQLITE4_ABORT;
  rc = sqlite4ApiExit(db, rc);

  if( pzErrMsg ){
    if( rc!=SQLITE4_OK ){
      *pzErrMsg = sqlite4DbStrDup(0, sqlite4_errmsg(db));
      if( 0==*pzErrMsg ){
        rc = SQLITE4_NOMEM;
        sqlite4Error(db, SQLITE4_NOMEM, 0);
      }
    }else{
      *pzErrMsg = 0;
    }
  }

  sqlite4_mutex_leave(db->mutex);
  return rc;
}







|
<







 







<
<
<
<
<
<
<
<
<
<
<
<



27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
...
113
114
115
116
117
118
119












120
121
122
** argument to xCall().  If xCall=NULL then no callback
** is invoked, even for queries.
*/
int sqlite4_exec(
  sqlite4 *db,                /* The database on which the SQL executes */
  const char *zSql,           /* The SQL to be executed */
  int (*xCall)(void*,int,sqlite4_value**,const char**),  /* Callback function */
  void *pArg                  /* First argument to xCall() */

){
  int rc = SQLITE4_OK;        /* Return code */
  int nRetry = 0;             /* Number of retry attempts */
  int bAbort = 0;             /* Set to true if callback returns non-zero */

  if( !sqlite4SafetyCheckOk(db) ) return SQLITE4_MISUSE_BKPT;
  if( zSql==0 ) zSql = "";
................................................................................

    sqlite4DbFree(db, azCol);
  }

  if( bAbort ) rc = SQLITE4_ABORT;
  rc = sqlite4ApiExit(db, rc);













  sqlite4_mutex_leave(db->mutex);
  return rc;
}

Changes to src/prepare.c.

269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
        db->aDb[iDb].zName, zMasterName);
#ifndef SQLITE4_OMIT_AUTHORIZATION
    {
      Authorizer *pAuth;
      pAuth = db->pAuth;
      db->pAuth = 0;
#endif
      rc = sqlite4_exec(db, zSql, sqlite4InitCallback, &initData, 0);
#ifndef SQLITE4_OMIT_AUTHORIZATION
      db->pAuth = pAuth;
    }
#endif
    if( rc==SQLITE4_OK ) rc = initData.rc;
    sqlite4DbFree(db, zSql);
#ifndef SQLITE4_OMIT_ANALYZE







|







269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
        db->aDb[iDb].zName, zMasterName);
#ifndef SQLITE4_OMIT_AUTHORIZATION
    {
      Authorizer *pAuth;
      pAuth = db->pAuth;
      db->pAuth = 0;
#endif
      rc = sqlite4_exec(db, zSql, sqlite4InitCallback, &initData);
#ifndef SQLITE4_OMIT_AUTHORIZATION
      db->pAuth = pAuth;
    }
#endif
    if( rc==SQLITE4_OK ) rc = initData.rc;
    sqlite4DbFree(db, zSql);
#ifndef SQLITE4_OMIT_ANALYZE

Changes to src/shell.c.

1238
1239
1240
1241
1242
1243
1244
1245
1246
1247

1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
....
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
....
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
....
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
....
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
** "ORDER BY rowid DESC" to the end.
*/
static int run_schema_dump_query(
  struct callback_data *p, 
  const char *zQuery
){
  int rc;
  char *zErr = 0;
  rc = sqlite4_exec(p->db, zQuery, dump_callback, p, &zErr);
  if( rc==SQLITE4_CORRUPT ){

    char *zQ2;
    int len = strlen30(zQuery);
    fprintf(p->out, "/****** CORRUPTION ERROR *******/\n");
    if( zErr ){
      fprintf(p->out, "/****** %s ******/\n", zErr);
      sqlite4_free(0, zErr);
      zErr = 0;
    }
    zQ2 = malloc( len+100 );
    if( zQ2==0 ) return rc;
    sqlite4_snprintf(zQ2,sizeof(zQ2), "%s ORDER BY rowid DESC", zQuery);
    rc = sqlite4_exec(p->db, zQ2, dump_callback, p, &zErr);
    if( rc ){
      fprintf(p->out, "/****** ERROR: %s ******/\n", zErr);
    }else{
      rc = SQLITE4_CORRUPT;
    }
    sqlite4_free(0, zErr);
    free(zQ2);
  }
  return rc;
}

/*
** Text of a help message
................................................................................
    open_db(p);
    /* When playing back a "dump", the content might appear in an order
    ** which causes immediate foreign key constraints to be violated.
    ** So disable foreign-key constraint enforcement to prevent problems. */
    fprintf(p->out, "PRAGMA foreign_keys=OFF;\n");
    fprintf(p->out, "BEGIN TRANSACTION;\n");
    p->writableSchema = 0;
    sqlite4_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
    p->nErr = 0;
    if( nArg==1 ){
      run_schema_dump_query(p, 
        "SELECT name, type, sql FROM sqlite_master "
        "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
      );
      run_schema_dump_query(p, 
................................................................................
        zShellStatic = 0;
      }
    }
    if( p->writableSchema ){
      fprintf(p->out, "PRAGMA writable_schema=OFF;\n");
      p->writableSchema = 0;
    }
    sqlite4_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
    sqlite4_exec(p->db, "RELEASE dump;", 0, 0, 0);
    fprintf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
  }else

  if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){
    p->echoOn = booleanValue(azArg[1]);
  }else

................................................................................
    azCol = malloc( sizeof(azCol[0])*(nCol+1) );
    if( azCol==0 ){
      fprintf(stderr, "Error: out of memory\n");
      fclose(in);
      sqlite4_finalize(pStmt);
      return 1;
    }
    sqlite4_exec(p->db, "BEGIN", 0, 0, 0);
    zCommit = "COMMIT";
    while( (zLine = local_getline(0, in, 1))!=0 ){
      char *z, c;
      int inQuote = 0;
      lineno++;
      azCol[0] = zLine;
      for(i=0, z=zLine; (c = *z)!=0; z++){
................................................................................
        rc = 1;
        break; /* from while */
      }
    } /* end while */
    free(azCol);
    fclose(in);
    sqlite4_finalize(pStmt);
    sqlite4_exec(p->db, zCommit, 0, 0, 0);
  }else

  if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){
    struct callback_data data;
    char *zErrMsg = 0;
    open_db(p);
    memcpy(&data, p, sizeof(data));







<
|

>





<
<




|

|



<







 







|







 







|
|







 







|







 







|







1238
1239
1240
1241
1242
1243
1244

1245
1246
1247
1248
1249
1250
1251
1252


1253
1254
1255
1256
1257
1258
1259
1260
1261
1262

1263
1264
1265
1266
1267
1268
1269
....
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
....
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
....
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
....
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
** "ORDER BY rowid DESC" to the end.
*/
static int run_schema_dump_query(
  struct callback_data *p, 
  const char *zQuery
){
  int rc;

  rc = sqlite4_exec(p->db, zQuery, dump_callback, p);
  if( rc==SQLITE4_CORRUPT ){
    const char *zErr = sqlite4_errmsg(p->db);
    char *zQ2;
    int len = strlen30(zQuery);
    fprintf(p->out, "/****** CORRUPTION ERROR *******/\n");
    if( zErr ){
      fprintf(p->out, "/****** %s ******/\n", zErr);


    }
    zQ2 = malloc( len+100 );
    if( zQ2==0 ) return rc;
    sqlite4_snprintf(zQ2,sizeof(zQ2), "%s ORDER BY rowid DESC", zQuery);
    rc = sqlite4_exec(p->db, zQ2, dump_callback, p);
    if( rc ){
      fprintf(p->out, "/****** ERROR: %s ******/\n", sqlite4_errmsg(p->db));
    }else{
      rc = SQLITE4_CORRUPT;
    }

    free(zQ2);
  }
  return rc;
}

/*
** Text of a help message
................................................................................
    open_db(p);
    /* When playing back a "dump", the content might appear in an order
    ** which causes immediate foreign key constraints to be violated.
    ** So disable foreign-key constraint enforcement to prevent problems. */
    fprintf(p->out, "PRAGMA foreign_keys=OFF;\n");
    fprintf(p->out, "BEGIN TRANSACTION;\n");
    p->writableSchema = 0;
    sqlite4_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0);
    p->nErr = 0;
    if( nArg==1 ){
      run_schema_dump_query(p, 
        "SELECT name, type, sql FROM sqlite_master "
        "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
      );
      run_schema_dump_query(p, 
................................................................................
        zShellStatic = 0;
      }
    }
    if( p->writableSchema ){
      fprintf(p->out, "PRAGMA writable_schema=OFF;\n");
      p->writableSchema = 0;
    }
    sqlite4_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0);
    sqlite4_exec(p->db, "RELEASE dump;", 0, 0);
    fprintf(p->out, p->nErr ? "ROLLBACK; -- due to errors\n" : "COMMIT;\n");
  }else

  if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 && nArg<3 ){
    p->echoOn = booleanValue(azArg[1]);
  }else

................................................................................
    azCol = malloc( sizeof(azCol[0])*(nCol+1) );
    if( azCol==0 ){
      fprintf(stderr, "Error: out of memory\n");
      fclose(in);
      sqlite4_finalize(pStmt);
      return 1;
    }
    sqlite4_exec(p->db, "BEGIN", 0, 0);
    zCommit = "COMMIT";
    while( (zLine = local_getline(0, in, 1))!=0 ){
      char *z, c;
      int inQuote = 0;
      lineno++;
      azCol[0] = zLine;
      for(i=0, z=zLine; (c = *z)!=0; z++){
................................................................................
        rc = 1;
        break; /* from while */
      }
    } /* end while */
    free(azCol);
    fclose(in);
    sqlite4_finalize(pStmt);
    sqlite4_exec(p->db, zCommit, 0, 0);
  }else

  if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg<3 ){
    struct callback_data data;
    char *zErrMsg = 0;
    open_db(p);
    memcpy(&data, p, sizeof(data));

Changes to src/sqlite.h.in.

483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
...
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
**
** The sqlite4_exec() interface is a convenience wrapper around
** [sqlite4_prepare()], [sqlite4_step()], and [sqlite4_finalize()],
** that allows an application to run multiple statements of SQL
** without having to use a lot of C code. 
**
** ^The sqlite4_exec() interface runs zero or more UTF-8 encoded,
** semicolon-separate SQL statements passed into its 2nd argument,
** in the context of the [database connection] passed in as its 1st
** argument.  ^If the callback function of the 3rd argument to
** sqlite4_exec() is not NULL, then it is invoked for each result row
** coming out of the evaluated SQL statements.  ^The 4th argument to
** sqlite4_exec() is relayed through to the 1st argument of each
** callback invocation.  ^If the callback pointer to sqlite4_exec()
** is NULL, then no callback is ever invoked and result rows are
** ignored.
**
** ^If an error occurs while evaluating the SQL statements passed into
** sqlite4_exec(), then execution of the current statement stops and
** any subsequent statements are not executed.  ^If the 5th parameter 
** to sqlite4_exec() is not NULL then any error message is written into 
** memory obtained from [sqlite4_malloc()] and passed back through the 5th 
** parameter. To avoid memory leaks, the application should invoke 
** [sqlite4_free()] on error message strings returned through the 5th 
** parameter of of sqlite4_exec() after the error message string is no 
** longer needed. ^If the 5th parameter to sqlite4_exec() is not NULL and 
** no errors occur, then sqlite4_exec() sets the pointer in its 5th 
** parameter to NULL before returning.
**
** ^If an sqlite4_exec() callback returns non-zero, the sqlite4_exec()
** routine returns SQLITE4_ABORT without invoking the callback again and
** without running any subsequent SQL statements.
**
** ^The 2nd argument to the sqlite4_exec() callback function is the
** number of columns in the result.  ^The 3rd argument to the sqlite4_exec()
................................................................................
**      the 2nd parameter of sqlite4_exec() while sqlite4_exec() is running.
** </ul>
*/
int sqlite4_exec(
  sqlite4 *,                      /* An open database */
  const char *zSql,               /* SQL to be evaluated */
  int (*)(void*,int,sqlite4_value**,const char**),    /* Callback function */
  void *,                         /* Context for callback */
  char **pzErrmsg                 /* Error msg written here */
);

/*
** CAPIREF: Result Codes
** KEYWORDS: SQLITE4_OK {error code} {error codes}
** KEYWORDS: {result code} {result codes}
**







|










|
|
|
<
<
<
<
<
<
<







 







|
<







483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503







504
505
506
507
508
509
510
...
530
531
532
533
534
535
536
537

538
539
540
541
542
543
544
**
** The sqlite4_exec() interface is a convenience wrapper around
** [sqlite4_prepare()], [sqlite4_step()], and [sqlite4_finalize()],
** that allows an application to run multiple statements of SQL
** without having to use a lot of C code. 
**
** ^The sqlite4_exec() interface runs zero or more UTF-8 encoded,
** semicolon-separated SQL statements passed into its 2nd argument,
** in the context of the [database connection] passed in as its 1st
** argument.  ^If the callback function of the 3rd argument to
** sqlite4_exec() is not NULL, then it is invoked for each result row
** coming out of the evaluated SQL statements.  ^The 4th argument to
** sqlite4_exec() is relayed through to the 1st argument of each
** callback invocation.  ^If the callback pointer to sqlite4_exec()
** is NULL, then no callback is ever invoked and result rows are
** ignored.
**
** ^If an error occurs while evaluating the SQL statements passed into
** sqlite4_exec(), then execution of the current statement stops, an
** error code is returned to the user and no subsequent statements are 
** executed.







**
** ^If an sqlite4_exec() callback returns non-zero, the sqlite4_exec()
** routine returns SQLITE4_ABORT without invoking the callback again and
** without running any subsequent SQL statements.
**
** ^The 2nd argument to the sqlite4_exec() callback function is the
** number of columns in the result.  ^The 3rd argument to the sqlite4_exec()
................................................................................
**      the 2nd parameter of sqlite4_exec() while sqlite4_exec() is running.
** </ul>
*/
int sqlite4_exec(
  sqlite4 *,                      /* An open database */
  const char *zSql,               /* SQL to be evaluated */
  int (*)(void*,int,sqlite4_value**,const char**),    /* Callback function */
  void *                          /* Context for callback */

);

/*
** CAPIREF: Result Codes
** KEYWORDS: SQLITE4_OK {error code} {error codes}
** KEYWORDS: {result code} {result codes}
**

Changes to src/tclsqlite.c.

652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
...
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
....
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
....
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
....
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
  int rc = result;
  const char *zEnd;

  pDb->nTransaction--;
  zEnd = azEnd[(rc==TCL_ERROR)*2 + (pDb->nTransaction==0)];

  pDb->disableAuth++;
  if( sqlite4_exec(pDb->db, zEnd, 0, 0, 0) ){
      /* This is a tricky scenario to handle. The most likely cause of an
      ** error is that the exec() above was an attempt to commit the 
      ** top-level transaction that returned SQLITE4_BUSY. Or, less likely,
      ** that an IO-error has occured. In either case, throw a Tcl exception
      ** and try to rollback the transaction.
      **
      ** But it could also be that the user executed one or more BEGIN, 
................................................................................
      ** COMMIT, SAVEPOINT, RELEASE or ROLLBACK commands that are confusing
      ** this method's logic. Not clear how this would be best handled.
      */
    if( rc!=TCL_ERROR ){
      Tcl_AppendResult(interp, sqlite4_errmsg(pDb->db), 0);
      rc = TCL_ERROR;
    }
    sqlite4_exec(pDb->db, "ROLLBACK", 0, 0, 0);
  }
  pDb->disableAuth--;

  return rc;
}

/*
................................................................................
    }
    azCol = malloc( sizeof(azCol[0])*(nCol+1) );
    if( azCol==0 ) {
      Tcl_AppendResult(interp, "Error: can't malloc()", 0);
      fclose(in);
      return TCL_ERROR;
    }
    (void)sqlite4_exec(pDb->db, "BEGIN", 0, 0, 0);
    zCommit = "COMMIT";
    while( (zLine = local_getline(0, in))!=0 ){
      char *z;
      lineno++;
      azCol[0] = zLine;
      for(i=0, z=zLine; *z; z++){
        if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){
................................................................................
        zCommit = "ROLLBACK";
        break;
      }
    }
    free(azCol);
    fclose(in);
    sqlite4_finalize(pStmt);
    (void)sqlite4_exec(pDb->db, zCommit, 0, 0, 0);

    if( zCommit[0] == 'C' ){
      /* success, set result as number of lines processed */
      pResult = Tcl_GetObjResult(interp);
      Tcl_SetIntObj(pResult, lineno);
      rc = TCL_OK;
    }else{
................................................................................
        case TTYPE_IMMEDIATE:   zBegin = "BEGIN IMMEDIATE";  break;
      }
    }
    pScript = objv[objc-1];

    /* Run the SQLite BEGIN command to open a transaction or savepoint. */
    pDb->disableAuth++;
    rc = sqlite4_exec(pDb->db, zBegin, 0, 0, 0);
    pDb->disableAuth--;
    if( rc!=SQLITE4_OK ){
      Tcl_AppendResult(interp, sqlite4_errmsg(pDb->db), 0);
      return TCL_ERROR;
    }
    pDb->nTransaction++;








|







 







|







 







|







 







|







 







|







652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
...
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
....
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
....
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
....
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
  int rc = result;
  const char *zEnd;

  pDb->nTransaction--;
  zEnd = azEnd[(rc==TCL_ERROR)*2 + (pDb->nTransaction==0)];

  pDb->disableAuth++;
  if( sqlite4_exec(pDb->db, zEnd, 0, 0) ){
      /* This is a tricky scenario to handle. The most likely cause of an
      ** error is that the exec() above was an attempt to commit the 
      ** top-level transaction that returned SQLITE4_BUSY. Or, less likely,
      ** that an IO-error has occured. In either case, throw a Tcl exception
      ** and try to rollback the transaction.
      **
      ** But it could also be that the user executed one or more BEGIN, 
................................................................................
      ** COMMIT, SAVEPOINT, RELEASE or ROLLBACK commands that are confusing
      ** this method's logic. Not clear how this would be best handled.
      */
    if( rc!=TCL_ERROR ){
      Tcl_AppendResult(interp, sqlite4_errmsg(pDb->db), 0);
      rc = TCL_ERROR;
    }
    sqlite4_exec(pDb->db, "ROLLBACK", 0, 0);
  }
  pDb->disableAuth--;

  return rc;
}

/*
................................................................................
    }
    azCol = malloc( sizeof(azCol[0])*(nCol+1) );
    if( azCol==0 ) {
      Tcl_AppendResult(interp, "Error: can't malloc()", 0);
      fclose(in);
      return TCL_ERROR;
    }
    (void)sqlite4_exec(pDb->db, "BEGIN", 0, 0);
    zCommit = "COMMIT";
    while( (zLine = local_getline(0, in))!=0 ){
      char *z;
      lineno++;
      azCol[0] = zLine;
      for(i=0, z=zLine; *z; z++){
        if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){
................................................................................
        zCommit = "ROLLBACK";
        break;
      }
    }
    free(azCol);
    fclose(in);
    sqlite4_finalize(pStmt);
    (void)sqlite4_exec(pDb->db, zCommit, 0, 0);

    if( zCommit[0] == 'C' ){
      /* success, set result as number of lines processed */
      pResult = Tcl_GetObjResult(interp);
      Tcl_SetIntObj(pResult, lineno);
      rc = TCL_OK;
    }else{
................................................................................
        case TTYPE_IMMEDIATE:   zBegin = "BEGIN IMMEDIATE";  break;
      }
    }
    pScript = objv[objc-1];

    /* Run the SQLite BEGIN command to open a transaction or savepoint. */
    pDb->disableAuth++;
    rc = sqlite4_exec(pDb->db, zBegin, 0, 0);
    pDb->disableAuth--;
    if( rc!=SQLITE4_OK ){
      Tcl_AppendResult(interp, sqlite4_errmsg(pDb->db), 0);
      return TCL_ERROR;
    }
    pDb->nTransaction++;

Changes to src/vdbe.c.

3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
    if( zSql==0 ){
      rc = SQLITE4_NOMEM;
    }else{
      assert( db->init.busy==0 );
      db->init.busy = 1;
      initData.rc = SQLITE4_OK;
      assert( !db->mallocFailed );
      rc = sqlite4_exec(db, zSql, sqlite4InitCallback, &initData, 0);
      if( rc==SQLITE4_OK ) rc = initData.rc;
      sqlite4DbFree(db, zSql);
      db->init.busy = 0;
    }
  }
  if( rc==SQLITE4_NOMEM ){
    goto no_mem;







|







3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
    if( zSql==0 ){
      rc = SQLITE4_NOMEM;
    }else{
      assert( db->init.busy==0 );
      db->init.busy = 1;
      initData.rc = SQLITE4_OK;
      assert( !db->mallocFailed );
      rc = sqlite4_exec(db, zSql, sqlite4InitCallback, &initData);
      if( rc==SQLITE4_OK ) rc = initData.rc;
      sqlite4DbFree(db, zSql);
      db->init.busy = 0;
    }
  }
  if( rc==SQLITE4_NOMEM ){
    goto no_mem;

Changes to test/test_main.c.

338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
...
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
...
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
...
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
...
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
...
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
....
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
       " DB FORMAT STRING", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  Tcl_DStringInit(&str);
  zSql = sqlite4_mprintf(0, argv[2], argv[3]);
  rc = sqlite4_exec(db, zSql, exec_printf_cb, &str, &zErr);
  sqlite4_free(0, zSql);
  sprintf(zBuf, "%d", rc);
  Tcl_AppendElement(interp, zBuf);
  Tcl_AppendElement(interp, rc==SQLITE4_OK ? Tcl_DStringValue(&str) : zErr);
  Tcl_DStringFree(&str);
  if( zErr ) sqlite4_free(0, zErr);
  if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR;
  return TCL_OK;
}

/*
** Usage:  sqlite4_exec_hex  DB  HEX
**
................................................................................
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  sqlite4 *db;
  Tcl_DString str;
  int rc, i, j;
  char *zErr = 0;
  char *zHex;
  char zSql[500];
  char zBuf[30];
  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
       " DB HEX", 0);
    return TCL_ERROR;
................................................................................
      j += 2;
    }else{
      zSql[i] = zHex[j];
    }
  }
  zSql[i] = 0;
  Tcl_DStringInit(&str);
  rc = sqlite4_exec(db, zSql, exec_printf_cb, &str, &zErr);
  sprintf(zBuf, "%d", rc);
  Tcl_AppendElement(interp, zBuf);
  Tcl_AppendElement(interp, rc==SQLITE4_OK ? Tcl_DStringValue(&str) : zErr);
  Tcl_DStringFree(&str);
  if( zErr ) sqlite4_free(0, zErr);
  if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR;
  return TCL_OK;
}

/*
** Usage:  db_enter DB
**         db_leave DB
................................................................................
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  sqlite4 *db;
  Tcl_DString str;
  int rc;
  char *zErr = 0;
  char *zSql;
  int i, j;
  char zBuf[30];
  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
       " DB SQL", 0);
    return TCL_ERROR;
................................................................................
      zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]);
      i += 3;
    }else{
      zSql[j++] = zSql[i++];
    }
  }
  zSql[j] = 0;
  rc = sqlite4_exec(db, zSql, exec_printf_cb, &str, &zErr);
  sqlite4_free(0, zSql);
  sprintf(zBuf, "%d", rc);
  Tcl_AppendElement(interp, zBuf);
  Tcl_AppendElement(interp, rc==SQLITE4_OK ? Tcl_DStringValue(&str) : zErr);
  Tcl_DStringFree(&str);
  if( zErr ) sqlite4_free(0, zErr);
  if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR;
  return TCL_OK;
}

/*
** Usage:  sqlite4_exec_nr  DB  SQL
**
................................................................................
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  sqlite4 *db;
  int rc;
  char *zErr = 0;
  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
       " DB SQL", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  rc = sqlite4_exec(db, argv[2], 0, 0, &zErr);
  if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR;
  return TCL_OK;
}

/*
** Usage:  sqlite4_mprintf_z_test  SEPARATOR  ARG0  ARG1 ...
**
................................................................................
  int argc,  
  sqlite4_value **argv
){
  struct dstr x;
  sqlite4 *db = (sqlite4 *)sqlite4_context_appdata(context);
  const char *zSql = sqlite4_value_text(argv[0], 0);
  memset(&x, 0, sizeof(x));
  (void)sqlite4_exec(db, zSql, execFuncCallback, &x, 0);
  sqlite4_result_text(context, x.z, x.nUsed, SQLITE4_TRANSIENT, 0);
  sqlite4_free(0, x.z);
}

/*
** Implementation of tkt2213func(), a scalar function that takes exactly
** one argument. It has two interesting features:
................................................................................
  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
        " DB SQL", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  prepStack();
  (void)sqlite4_exec(db, argv[2], 0, 0, 0);
  for(i=65535; i>=0 && ((u32*)sqlite4_stack_baseline)[-i]==0xdeadbeef; i--){}
  Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4));
  return TCL_OK;
}

/*
** Usage: sqlite_delete_function DB function-name







|



|

<







 







<







 







|


|

<







 







<







 







|



|

<







 







<






|







 







|







 







|







338
339
340
341
342
343
344
345
346
347
348
349
350

351
352
353
354
355
356
357
...
364
365
366
367
368
369
370

371
372
373
374
375
376
377
...
384
385
386
387
388
389
390
391
392
393
394
395

396
397
398
399
400
401
402
...
446
447
448
449
450
451
452

453
454
455
456
457
458
459
...
466
467
468
469
470
471
472
473
474
475
476
477
478

479
480
481
482
483
484
485
...
490
491
492
493
494
495
496

497
498
499
500
501
502
503
504
505
506
507
508
509
510
...
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
....
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
       " DB FORMAT STRING", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  Tcl_DStringInit(&str);
  zSql = sqlite4_mprintf(0, argv[2], argv[3]);
  rc = sqlite4_exec(db, zSql, exec_printf_cb, &str);
  sqlite4_free(0, zSql);
  sprintf(zBuf, "%d", rc);
  Tcl_AppendElement(interp, zBuf);
  Tcl_AppendElement(interp, !rc ? Tcl_DStringValue(&str) : sqlite4_errmsg(db));
  Tcl_DStringFree(&str);

  if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR;
  return TCL_OK;
}

/*
** Usage:  sqlite4_exec_hex  DB  HEX
**
................................................................................
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  sqlite4 *db;
  Tcl_DString str;
  int rc, i, j;

  char *zHex;
  char zSql[500];
  char zBuf[30];
  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
       " DB HEX", 0);
    return TCL_ERROR;
................................................................................
      j += 2;
    }else{
      zSql[i] = zHex[j];
    }
  }
  zSql[i] = 0;
  Tcl_DStringInit(&str);
  rc = sqlite4_exec(db, zSql, exec_printf_cb, &str);
  sprintf(zBuf, "%d", rc);
  Tcl_AppendElement(interp, zBuf);
  Tcl_AppendElement(interp, !rc ? Tcl_DStringValue(&str) : sqlite4_errmsg(db));
  Tcl_DStringFree(&str);

  if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR;
  return TCL_OK;
}

/*
** Usage:  db_enter DB
**         db_leave DB
................................................................................
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  sqlite4 *db;
  Tcl_DString str;
  int rc;

  char *zSql;
  int i, j;
  char zBuf[30];
  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
       " DB SQL", 0);
    return TCL_ERROR;
................................................................................
      zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]);
      i += 3;
    }else{
      zSql[j++] = zSql[i++];
    }
  }
  zSql[j] = 0;
  rc = sqlite4_exec(db, zSql, exec_printf_cb, &str);
  sqlite4_free(0, zSql);
  sprintf(zBuf, "%d", rc);
  Tcl_AppendElement(interp, zBuf);
  Tcl_AppendElement(interp, !rc ? Tcl_DStringValue(&str) : sqlite4_errmsg(db));
  Tcl_DStringFree(&str);

  if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR;
  return TCL_OK;
}

/*
** Usage:  sqlite4_exec_nr  DB  SQL
**
................................................................................
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  char **argv            /* Text of each argument */
){
  sqlite4 *db;
  int rc;

  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
       " DB SQL", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  rc = sqlite4_exec(db, argv[2], 0, 0);
  if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR;
  return TCL_OK;
}

/*
** Usage:  sqlite4_mprintf_z_test  SEPARATOR  ARG0  ARG1 ...
**
................................................................................
  int argc,  
  sqlite4_value **argv
){
  struct dstr x;
  sqlite4 *db = (sqlite4 *)sqlite4_context_appdata(context);
  const char *zSql = sqlite4_value_text(argv[0], 0);
  memset(&x, 0, sizeof(x));
  (void)sqlite4_exec(db, zSql, execFuncCallback, &x);
  sqlite4_result_text(context, x.z, x.nUsed, SQLITE4_TRANSIENT, 0);
  sqlite4_free(0, x.z);
}

/*
** Implementation of tkt2213func(), a scalar function that takes exactly
** one argument. It has two interesting features:
................................................................................
  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
        " DB SQL", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
  prepStack();
  (void)sqlite4_exec(db, argv[2], 0, 0);
  for(i=65535; i>=0 && ((u32*)sqlite4_stack_baseline)[-i]==0xdeadbeef; i--){}
  Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4));
  return TCL_OK;
}

/*
** Usage: sqlite_delete_function DB function-name