Check-in [b81147cbdc]
Not logged in

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

Overview
Comment:cleanup after merge
Timelines: family | ancestors | descendants | both | wtf-8-experiment
Files: files | file ages | folders
SHA1: b81147cbdc0168b7665ea19e3b08899225b79df6
User & Date: chw 2019-10-12 06:26:02.972
Context
2019-10-14
04:02
merge with trunk check-in: 7c1b45da8e user: chw tags: wtf-8-experiment
2019-10-12
06:26
cleanup after merge check-in: b81147cbdc user: chw tags: wtf-8-experiment
06:24
merge with trunk check-in: eed284ebf4 user: chw tags: wtf-8-experiment
Changes
Unified Diff Ignore Whitespace Patch
Changes to jni/tcl/pkgs/sqlite3.30.1/generic/tclsqlite3.c.
213
214
215
216
217
218
219

220
221
222
223
224
225
226
227
228
229
230









231
232
233
234
235
236
237
238
239
240
241
242
243
244



















245
246
247
248
249
250
251
  int nStep, nSort, nIndex;  /* Statistics for most recent operation */
  int nVMStep;               /* Another statistic for most recent operation */
  int nTransaction;          /* Number of nested [transaction] methods */
  int openFlags;             /* Flags used to open.  (SQLITE_OPEN_URI) */
#ifdef SQLITE_TEST
  int bLegacyPrepare;        /* True to use sqlite3_prepare() */
#endif

};

struct IncrblobChannel {
  sqlite3_blob *pBlob;      /* sqlite3 blob handle */
  SqliteDb *pDb;            /* Associated database connection */
  int iSeek;                /* Current seek offset */
  Tcl_Channel channel;      /* Channel identifier */
  IncrblobChannel *pNext;   /* Linked list of all open incrblob channels */
  IncrblobChannel *pPrev;   /* Linked list of all open incrblob channels */
};










/*
** Compute a string length that is limited to what can be stored in
** lower 30 bits of a 32-bit signed integer.
*/
static int strlen30(const char *z){
  const char *z2 = z;
  while( *z2 ){ z2++; }
  return 0x3fffffff & (int)(z2 - z);
}

#ifdef USE_TCL_STUBS
# define tclStubsPtr staticTclStubsPtr
static const TclStubs *tclStubsPtr = 0;
#endif




















#ifndef SQLITE_OMIT_INCRBLOB
/*
** Close all incrblob channels opened using database connection pDb.
** This is called when shutting down the database connection.
*/
static void closeIncrblobChannels(SqliteDb *pDb){







>











>
>
>
>
>
>
>
>
>














>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
  int nStep, nSort, nIndex;  /* Statistics for most recent operation */
  int nVMStep;               /* Another statistic for most recent operation */
  int nTransaction;          /* Number of nested [transaction] methods */
  int openFlags;             /* Flags used to open.  (SQLITE_OPEN_URI) */
#ifdef SQLITE_TEST
  int bLegacyPrepare;        /* True to use sqlite3_prepare() */
#endif
  Tcl_DString dsErr;         /* Used for error messages (utf8Encoding) */
};

struct IncrblobChannel {
  sqlite3_blob *pBlob;      /* sqlite3 blob handle */
  SqliteDb *pDb;            /* Associated database connection */
  int iSeek;                /* Current seek offset */
  Tcl_Channel channel;      /* Channel identifier */
  IncrblobChannel *pNext;   /* Linked list of all open incrblob channels */
  IncrblobChannel *pPrev;   /* Linked list of all open incrblob channels */
};

/*
 ** Tcl UTF-8 encoding; loaded and tested on module init. Depending
 ** on unicode support detected, it is reset to NULL or kept until
 ** module gets unloaded.
 */
static Tcl_Encoding utf8Encoding = NULL;
static int utf8EncInit = 0;
TCL_DECLARE_MUTEX(utf8EncMutex);

/*
** Compute a string length that is limited to what can be stored in
** lower 30 bits of a 32-bit signed integer.
*/
static int strlen30(const char *z){
  const char *z2 = z;
  while( *z2 ){ z2++; }
  return 0x3fffffff & (int)(z2 - z);
}

#ifdef USE_TCL_STUBS
# define tclStubsPtr staticTclStubsPtr
static const TclStubs *tclStubsPtr = 0;
#endif

/*
 ** Error message converter.
 */
static const char *SQLITEDB_ERRMSG(SqliteDb *pDb){
  if( pDb!=NULL ){
    if( pDb->db!=NULL ){
      if( utf8Encoding!=NULL ){
        Tcl_DStringFree(&pDb->dsErr);
        Tcl_ExternalToUtfDString(utf8Encoding, sqlite3_errmsg(pDb->db),
            -1, &pDb->dsErr);
        return Tcl_DStringValue(&pDb->dsErr);
      }
      return sqlite3_errmsg(pDb->db);
    }
    return "not a valid database";
  }
  return "unknown error";
}

#ifndef SQLITE_OMIT_INCRBLOB
/*
** Close all incrblob channels opened using database connection pDb.
** This is called when shutting down the database connection.
*/
static void closeIncrblobChannels(SqliteDb *pDb){
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
*/
static int SQLITE_TCLAPI incrblobClose(
  ClientData instanceData,
  Tcl_Interp *interp
){
  IncrblobChannel *p = (IncrblobChannel *)instanceData;
  int rc = sqlite3_blob_close(p->pBlob);
  sqlite3 *db = p->pDb->db;

  /* Remove the channel from the SqliteDb.pIncrblob list. */
  if( p->pNext ){
    p->pNext->pPrev = p->pPrev;
  }
  if( p->pPrev ){
    p->pPrev->pNext = p->pNext;
  }
  if( p->pDb->pIncrblob==p ){
    p->pDb->pIncrblob = p->pNext;
  }

  /* Free the IncrblobChannel structure */
  Tcl_Free((char *)p);

  if( rc!=SQLITE_OK ){
    Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Read data from an incremental blob channel.







|
















|







297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
*/
static int SQLITE_TCLAPI incrblobClose(
  ClientData instanceData,
  Tcl_Interp *interp
){
  IncrblobChannel *p = (IncrblobChannel *)instanceData;
  int rc = sqlite3_blob_close(p->pBlob);
  SqliteDb *pDb = p->pDb;

  /* Remove the channel from the SqliteDb.pIncrblob list. */
  if( p->pNext ){
    p->pNext->pPrev = p->pPrev;
  }
  if( p->pPrev ){
    p->pPrev->pNext = p->pNext;
  }
  if( p->pDb->pIncrblob==p ){
    p->pDb->pIncrblob = p->pNext;
  }

  /* Free the IncrblobChannel structure */
  Tcl_Free((char *)p);

  if( rc!=SQLITE_OK ){
    Tcl_SetResult(interp, (char*)SQLITEDB_ERRMSG(pDb), TCL_VOLATILE);
    return TCL_ERROR;
  }
  return TCL_OK;
}

/*
** Read data from an incremental blob channel.
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455

  /* This variable is used to name the channels: "incrblob_[incr count]" */
  static int count = 0;
  char zChannel[64];

  rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRow, !isReadonly, &pBlob);
  if( rc!=SQLITE_OK ){
    Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
    return TCL_ERROR;
  }

  p = (IncrblobChannel *)Tcl_Alloc(sizeof(IncrblobChannel));
  p->iSeek = 0;
  p->pBlob = pBlob;








|







470
471
472
473
474
475
476
477
478
479
480
481
482
483
484

  /* This variable is used to name the channels: "incrblob_[incr count]" */
  static int count = 0;
  char zChannel[64];

  rc = sqlite3_blob_open(db, zDb, zTable, zColumn, iRow, !isReadonly, &pBlob);
  if( rc!=SQLITE_OK ){
    Tcl_SetResult(interp, (char*)SQLITEDB_ERRMSG(pDb), TCL_VOLATILE);
    return TCL_ERROR;
  }

  p = (IncrblobChannel *)Tcl_Alloc(sizeof(IncrblobChannel));
  p->iSeek = 0;
  p->pBlob = pBlob;

607
608
609
610
611
612
613

614
615
616
617
618
619
620
  }
  if( pDb->pWalHook ){
    Tcl_DecrRefCount(pDb->pWalHook);
  }
  if( pDb->pCollateNeeded ){
    Tcl_DecrRefCount(pDb->pCollateNeeded);
  }

  Tcl_Free((char*)pDb);
}

/*
** This routine is called when a database file is locked while trying
** to execute SQL.
*/







>







636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
  }
  if( pDb->pWalHook ){
    Tcl_DecrRefCount(pDb->pWalHook);
  }
  if( pDb->pCollateNeeded ){
    Tcl_DecrRefCount(pDb->pCollateNeeded);
  }
  Tcl_DStringFree(&pDb->dsErr);
  Tcl_Free((char*)pDb);
}

/*
** This routine is called when a database file is locked while trying
** to execute SQL.
*/
877
878
879
880
881
882
883











884
885

886
887
888
889
890
891
892
  assert( pDb->pPreUpdateHook );
  assert( db==pDb->db );
  assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );

  pCmd = Tcl_DuplicateObj(pDb->pPreUpdateHook);
  Tcl_IncrRefCount(pCmd);
  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1));











  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1));
  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1));

  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey1));
  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey2));
  Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
  Tcl_DecrRefCount(pCmd);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */








>
>
>
>
>
>
>
>
>
>
>
|
|
>







907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
  assert( pDb->pPreUpdateHook );
  assert( db==pDb->db );
  assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );

  pCmd = Tcl_DuplicateObj(pDb->pPreUpdateHook);
  Tcl_IncrRefCount(pCmd);
  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1));
  if( utf8Encoding!=NULL ){
    Tcl_DString ds;
    Tcl_ExternalToUtfDString(utf8Encoding, zDb, -1, &ds);
    Tcl_ListObjAppendElement(0, pCmd,
        Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)));
    Tcl_DStringFree(&ds);
    Tcl_ExternalToUtfDString(utf8Encoding, zTbl, -1, &ds);
    Tcl_ListObjAppendElement(0, pCmd,
        Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)));
    Tcl_DStringFree(&ds);
  }else{
    Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1));
    Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1));
  }
  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey1));
  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(iKey2));
  Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
  Tcl_DecrRefCount(pCmd);
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */

907
908
909
910
911
912
913











914
915

916
917
918
919
920
921
922
923
924
925
926
927
928
929







930

931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950











951
952

953
954
955
956
957
958
959

  assert( pDb->pUpdateHook );
  assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );

  pCmd = Tcl_DuplicateObj(pDb->pUpdateHook);
  Tcl_IncrRefCount(pCmd);
  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1));











  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1));
  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1));

  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(rowid));
  Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
  Tcl_DecrRefCount(pCmd);
}

static void tclCollateNeeded(
  void *pCtx,
  sqlite3 *db,
  int enc,
  const char *zName
){
  SqliteDb *pDb = (SqliteDb *)pCtx;
  Tcl_Obj *pScript = Tcl_DuplicateObj(pDb->pCollateNeeded);
  Tcl_IncrRefCount(pScript);







  Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(zName, -1));

  Tcl_EvalObjEx(pDb->interp, pScript, 0);
  Tcl_DecrRefCount(pScript);
}

/*
** This routine is called to evaluate an SQL collation function implemented
** using TCL script.
*/
static int tclSqlCollate(
  void *pCtx,
  int nA,
  const void *zA,
  int nB,
  const void *zB
){
  SqlCollate *p = (SqlCollate *)pCtx;
  Tcl_Obj *pCmd;

  pCmd = Tcl_NewStringObj(p->zScript, -1);
  Tcl_IncrRefCount(pCmd);











  Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA));
  Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB));

  Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);
  Tcl_DecrRefCount(pCmd);
  return (atoi(Tcl_GetStringResult(p->interp)));
}

/*
** This routine is called to evaluate an SQL function implemented







>
>
>
>
>
>
>
>
>
>
>
|
|
>














>
>
>
>
>
>
>
|
>




















>
>
>
>
>
>
>
>
>
>
>
|
|
>







949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033

  assert( pDb->pUpdateHook );
  assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE );

  pCmd = Tcl_DuplicateObj(pDb->pUpdateHook);
  Tcl_IncrRefCount(pCmd);
  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(azStr[(op-1)/9], -1));
  if( utf8Encoding!=NULL ){
    Tcl_DString ds;
    Tcl_ExternalToUtfDString(utf8Encoding, zDb, -1, &ds);
    Tcl_ListObjAppendElement(0, pCmd,
        Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)));
    Tcl_DStringFree(&ds);
    Tcl_ExternalToUtfDString(utf8Encoding, zTbl, -1, &ds);
    Tcl_ListObjAppendElement(0, pCmd,
        Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)));
    Tcl_DStringFree(&ds);
  }else{
    Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zDb, -1));
    Tcl_ListObjAppendElement(0, pCmd, Tcl_NewStringObj(zTbl, -1));
  }
  Tcl_ListObjAppendElement(0, pCmd, Tcl_NewWideIntObj(rowid));
  Tcl_EvalObjEx(pDb->interp, pCmd, TCL_EVAL_DIRECT);
  Tcl_DecrRefCount(pCmd);
}

static void tclCollateNeeded(
  void *pCtx,
  sqlite3 *db,
  int enc,
  const char *zName
){
  SqliteDb *pDb = (SqliteDb *)pCtx;
  Tcl_Obj *pScript = Tcl_DuplicateObj(pDb->pCollateNeeded);
  Tcl_IncrRefCount(pScript);
  if( utf8Encoding!=NULL ){
    Tcl_DString ds;
    Tcl_ExternalToUtfDString(utf8Encoding, zName, -1, &ds);
    Tcl_ListObjAppendElement(0, pScript,
        Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds)));
    Tcl_DStringFree(&ds);
  }else{
    Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(zName, -1));
  }
  Tcl_EvalObjEx(pDb->interp, pScript, 0);
  Tcl_DecrRefCount(pScript);
}

/*
** This routine is called to evaluate an SQL collation function implemented
** using TCL script.
*/
static int tclSqlCollate(
  void *pCtx,
  int nA,
  const void *zA,
  int nB,
  const void *zB
){
  SqlCollate *p = (SqlCollate *)pCtx;
  Tcl_Obj *pCmd;

  pCmd = Tcl_NewStringObj(p->zScript, -1);
  Tcl_IncrRefCount(pCmd);
  if( utf8Encoding!=NULL ){
    Tcl_DString dsA, dsB;
    Tcl_ExternalToUtfDString(utf8Encoding, (char*)zA, nA, &dsA);
    Tcl_ExternalToUtfDString(utf8Encoding, (char*)zB, nB, &dsB);
    Tcl_ListObjAppendElement(p->interp, pCmd,
        Tcl_NewStringObj(Tcl_DStringValue(&dsA), Tcl_DStringLength(&dsA)));
    Tcl_ListObjAppendElement(p->interp, pCmd,
        Tcl_NewStringObj(Tcl_DStringValue(&dsB), Tcl_DStringLength(&dsB)));
    Tcl_DStringFree(&dsA);
    Tcl_DStringFree(&dsB);
  }else{
    Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zA, nA));
    Tcl_ListObjAppendElement(p->interp, pCmd, Tcl_NewStringObj(zB, nB));
  }
  Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);
  Tcl_DecrRefCount(pCmd);
  return (atoi(Tcl_GetStringResult(p->interp)));
}

/*
** This routine is called to evaluate an SQL function implemented
983
984
985
986
987
988
989









990

991
992
993
994
995
996
997
    ** That way, when Tcl_EvalObjv() is run and shimmers the first element
    ** of the list to tclCmdNameType, that alternate representation will
    ** be preserved and reused on the next invocation.
    */
    Tcl_Obj **aArg;
    int nArg;
    if( Tcl_ListObjGetElements(p->interp, p->pScript, &nArg, &aArg) ){









      sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);

      return;
    }
    pCmd = Tcl_NewListObj(nArg, aArg);
    Tcl_IncrRefCount(pCmd);
    for(i=0; i<argc; i++){
      sqlite3_value *pIn = argv[i];
      Tcl_Obj *pVal;







>
>
>
>
>
>
>
>
>
|
>







1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
    ** That way, when Tcl_EvalObjv() is run and shimmers the first element
    ** of the list to tclCmdNameType, that alternate representation will
    ** be preserved and reused on the next invocation.
    */
    Tcl_Obj **aArg;
    int nArg;
    if( Tcl_ListObjGetElements(p->interp, p->pScript, &nArg, &aArg) ){
resultError:
      if( utf8Encoding!=NULL ){
        Tcl_DString ds;
        Tcl_UtfToExternalDString(utf8Encoding, Tcl_GetStringResult(p->interp),
            -1, &ds);
        sqlite3_result_error(context, Tcl_DStringValue(&ds),
            Tcl_DStringLength(&ds));
        Tcl_DStringFree(&ds);
      }else{
        sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
      }
      return;
    }
    pCmd = Tcl_NewListObj(nArg, aArg);
    Tcl_IncrRefCount(pCmd);
    for(i=0; i<argc; i++){
      sqlite3_value *pIn = argv[i];
      Tcl_Obj *pVal;
1019
1020
1021
1022
1023
1024
1025








1026

1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
        }
        case SQLITE_NULL: {
          pVal = Tcl_NewStringObj(p->pDb->zNull, -1);
          break;
        }
        default: {
          int bytes = sqlite3_value_bytes(pIn);








          pVal = Tcl_NewStringObj((char *)sqlite3_value_text(pIn), bytes);

          break;
        }
      }
      rc = Tcl_ListObjAppendElement(p->interp, pCmd, pVal);
      if( rc ){
        Tcl_DecrRefCount(pCmd);
        sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
        return;
      }
    }
    if( !p->useEvalObjv ){
      /* Tcl_EvalObjEx() will automatically call Tcl_EvalObjv() if pCmd
      ** is a list without a string representation.  To prevent this from
      ** happening, make sure pCmd has a valid string representation */
      Tcl_GetString(pCmd);
    }
    rc = Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);
    Tcl_DecrRefCount(pCmd);
  }

  if( rc && rc!=TCL_RETURN ){
    sqlite3_result_error(context, Tcl_GetStringResult(p->interp), -1);
  }else{
    Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
    int n;
    u8 *data;
    const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
    char c = zType[0];
    int eType = p->eType;







>
>
>
>
>
>
>
>
|
>






<
|













|







1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125

1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
        }
        case SQLITE_NULL: {
          pVal = Tcl_NewStringObj(p->pDb->zNull, -1);
          break;
        }
        default: {
          int bytes = sqlite3_value_bytes(pIn);
          if( utf8Encoding!=NULL ){
            Tcl_DString ds;
            Tcl_ExternalToUtfDString(utf8Encoding,
                (char *)sqlite3_value_text(pIn), bytes, &ds);
            pVal = Tcl_NewStringObj(Tcl_DStringValue(&ds),
                       Tcl_DStringLength(&ds));
            Tcl_DStringFree(&ds);
          }else{
            pVal = Tcl_NewStringObj((char *)sqlite3_value_text(pIn), bytes);
          }
          break;
        }
      }
      rc = Tcl_ListObjAppendElement(p->interp, pCmd, pVal);
      if( rc ){
        Tcl_DecrRefCount(pCmd);

        goto resultError;
      }
    }
    if( !p->useEvalObjv ){
      /* Tcl_EvalObjEx() will automatically call Tcl_EvalObjv() if pCmd
      ** is a list without a string representation.  To prevent this from
      ** happening, make sure pCmd has a valid string representation */
      Tcl_GetString(pCmd);
    }
    rc = Tcl_EvalObjEx(p->interp, pCmd, TCL_EVAL_DIRECT);
    Tcl_DecrRefCount(pCmd);
  }

  if( rc && rc!=TCL_RETURN ){
    goto resultError;
  }else{
    Tcl_Obj *pVar = Tcl_GetObjResult(p->interp);
    int n;
    u8 *data;
    const char *zType = (pVar->typePtr ? pVar->typePtr->name : "");
    char c = zType[0];
    int eType = p->eType;
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
      ** 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, sqlite3_errmsg(pDb->db), (char*)0);
      rc = TCL_ERROR;
    }
    sqlite3_exec(pDb->db, "ROLLBACK", 0, 0, 0);
  }
  pDb->disableAuth--;

  return rc;







|







1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
      ** 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, (char*)SQLITEDB_ERRMSG(pDb), (char*)0);
      rc = TCL_ERROR;
    }
    sqlite3_exec(pDb->db, "ROLLBACK", 0, 0, 0);
  }
  pDb->disableAuth--;

  return rc;
1351
1352
1353
1354
1355
1356
1357

1358
1359
1360
1361
1362
1363
1364
  int nVar = 0;                   /* Number of variables in statement */
  int iParm = 0;                  /* Next free entry in apParm */
  char c;
  int i;
  int needResultReset = 0;        /* Need to invoke Tcl_ResetResult() */
  int rc = SQLITE_OK;             /* Value to return */
  Tcl_Interp *interp = pDb->interp;


  *ppPreStmt = 0;

  /* Trim spaces from the start of zSql and calculate the remaining length. */
  while( (c = zSql[0])==' ' || c=='\t' || c=='\r' || c=='\n' ){ zSql++; }
  nSql = strlen30(zSql);








>







1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
  int nVar = 0;                   /* Number of variables in statement */
  int iParm = 0;                  /* Next free entry in apParm */
  char c;
  int i;
  int needResultReset = 0;        /* Need to invoke Tcl_ResetResult() */
  int rc = SQLITE_OK;             /* Value to return */
  Tcl_Interp *interp = pDb->interp;
  Tcl_DString ds;

  *ppPreStmt = 0;

  /* Trim spaces from the start of zSql and calculate the remaining length. */
  while( (c = zSql[0])==' ' || c=='\t' || c=='\r' || c=='\n' ){ zSql++; }
  nSql = strlen30(zSql);

1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413

  /* If no prepared statement was found. Compile the SQL text. Also allocate
  ** a new SqlPreparedStmt structure.  */
  if( pPreStmt==0 ){
    int nByte;

    if( SQLITE_OK!=dbPrepare(pDb, zSql, &pStmt, pzOut) ){
      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
      return TCL_ERROR;
    }
    if( pStmt==0 ){
      if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
        /* A compile-time error in the statement. */
        Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
        return TCL_ERROR;
      }else{
        /* The statement was a no-op.  Continue to the next statement
        ** in the SQL string.
        */
        return TCL_OK;
      }







|





|







1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506

  /* If no prepared statement was found. Compile the SQL text. Also allocate
  ** a new SqlPreparedStmt structure.  */
  if( pPreStmt==0 ){
    int nByte;

    if( SQLITE_OK!=dbPrepare(pDb, zSql, &pStmt, pzOut) ){
      Tcl_SetObjResult(interp, Tcl_NewStringObj(SQLITEDB_ERRMSG(pDb), -1));
      return TCL_ERROR;
    }
    if( pStmt==0 ){
      if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
        /* A compile-time error in the statement. */
        Tcl_SetObjResult(interp, Tcl_NewStringObj(SQLITEDB_ERRMSG(pDb), -1));
        return TCL_ERROR;
      }else{
        /* The statement was a no-op.  Continue to the next statement
        ** in the SQL string.
        */
        return TCL_OK;
      }
1433
1434
1435
1436
1437
1438
1439

1440
1441





1442
1443
1444
1445
1446
1447
1448
#endif
  }
  assert( pPreStmt );
  assert( strlen30(pPreStmt->zSql)==pPreStmt->nSql );
  assert( 0==memcmp(pPreStmt->zSql, zSql, pPreStmt->nSql) );

  /* Bind values to parameters that begin with $ or : */

  for(i=1; i<=nVar; i++){
    const char *zVar = sqlite3_bind_parameter_name(pStmt, i);





    if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':' || zVar[0]=='@') ){
      Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0);
      if( pVar==0 && pDb->zBindFallback!=0 ){
        Tcl_Obj *pCmd;
        int rx;
        pCmd = Tcl_NewStringObj(pDb->zBindFallback, -1);
        Tcl_IncrRefCount(pCmd);







>


>
>
>
>
>







1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
#endif
  }
  assert( pPreStmt );
  assert( strlen30(pPreStmt->zSql)==pPreStmt->nSql );
  assert( 0==memcmp(pPreStmt->zSql, zSql, pPreStmt->nSql) );

  /* Bind values to parameters that begin with $ or : */
  Tcl_DStringInit(&ds);
  for(i=1; i<=nVar; i++){
    const char *zVar = sqlite3_bind_parameter_name(pStmt, i);
    if( utf8Encoding!= NULL ){
      Tcl_DStringFree(&ds);
      Tcl_ExternalToUtfDString(utf8Encoding, zVar, -1, &ds);
      zVar = Tcl_DStringValue(&ds);
    }
    if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':' || zVar[0]=='@') ){
      Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0);
      if( pVar==0 && pDb->zBindFallback!=0 ){
        Tcl_Obj *pCmd;
        int rx;
        pCmd = Tcl_NewStringObj(pDb->zBindFallback, -1);
        Tcl_IncrRefCount(pCmd);
1484
1485
1486
1487
1488
1489
1490








1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502

1503
1504
1505
1506
1507
1508
1509
          Tcl_GetDoubleFromObj(interp, pVar, &r);
          sqlite3_bind_double(pStmt, i, r);
        }else if( (c=='w' && strcmp(zType,"wideInt")==0) ||
              (c=='i' && strcmp(zType,"int")==0) ){
          Tcl_WideInt v;
          Tcl_GetWideIntFromObj(interp, pVar, &v);
          sqlite3_bind_int64(pStmt, i, v);








        }else{
          data = (unsigned char *)Tcl_GetString(pVar);
          sqlite3_bind_text(pStmt, i, (char *)data, pVar->length, SQLITE_STATIC);
          Tcl_IncrRefCount(pVar);
          pPreStmt->apParm[iParm++] = pVar;
        }
      }else{
        sqlite3_bind_null(pStmt, i);
      }
      if( needResultReset ) Tcl_ResetResult(pDb->interp);
    }
  }

  pPreStmt->nParm = iParm;
  *ppPreStmt = pPreStmt;
  if( needResultReset && rc==TCL_OK ) Tcl_ResetResult(pDb->interp);

  return rc;
}








>
>
>
>
>
>
>
>












>







1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
          Tcl_GetDoubleFromObj(interp, pVar, &r);
          sqlite3_bind_double(pStmt, i, r);
        }else if( (c=='w' && strcmp(zType,"wideInt")==0) ||
              (c=='i' && strcmp(zType,"int")==0) ){
          Tcl_WideInt v;
          Tcl_GetWideIntFromObj(interp, pVar, &v);
          sqlite3_bind_int64(pStmt, i, v);
        }else if( utf8Encoding!=NULL ){
          Tcl_DStringFree(&ds);
          Tcl_UtfToExternalDString(utf8Encoding, Tcl_GetString(pVar),
              pVar->length, &ds);
          sqlite3_bind_text(pStmt, i, Tcl_DStringValue(&ds),
              Tcl_DStringLength(&ds), SQLITE_TRANSIENT);
          Tcl_IncrRefCount(pVar);
          pPreStmt->apParm[iParm++] = pVar;
        }else{
          data = (unsigned char *)Tcl_GetString(pVar);
          sqlite3_bind_text(pStmt, i, (char *)data, pVar->length, SQLITE_STATIC);
          Tcl_IncrRefCount(pVar);
          pPreStmt->apParm[iParm++] = pVar;
        }
      }else{
        sqlite3_bind_null(pStmt, i);
      }
      if( needResultReset ) Tcl_ResetResult(pDb->interp);
    }
  }
  Tcl_DStringFree(&ds);
  pPreStmt->nParm = iParm;
  *ppPreStmt = pPreStmt;
  if( needResultReset && rc==TCL_OK ) Tcl_ResetResult(pDb->interp);

  return rc;
}

1569
1570
1571
1572
1573
1574
1575

1576
1577
1578
1579
1580
1581
1582
**   dbEvalRowInfo()
**   dbEvalColumnValue()
*/
typedef struct DbEvalContext DbEvalContext;
struct DbEvalContext {
  SqliteDb *pDb;                  /* Database handle */
  Tcl_Obj *pSql;                  /* Object holding string zSql */

  const char *zSql;               /* Remaining SQL to execute */
  SqlPreparedStmt *pPreStmt;      /* Current statement */
  int nCol;                       /* Number of columns returned by pStmt */
  int evalFlags;                  /* Flags used */
  Tcl_Obj *pArray;                /* Name of array variable */
  Tcl_Obj **apColName;            /* Array of column names */
};







>







1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
**   dbEvalRowInfo()
**   dbEvalColumnValue()
*/
typedef struct DbEvalContext DbEvalContext;
struct DbEvalContext {
  SqliteDb *pDb;                  /* Database handle */
  Tcl_Obj *pSql;                  /* Object holding string zSql */
  Tcl_DString dsSql;              /* Encoded SQL text */
  const char *zSql;               /* Remaining SQL to execute */
  SqlPreparedStmt *pPreStmt;      /* Current statement */
  int nCol;                       /* Number of columns returned by pStmt */
  int evalFlags;                  /* Flags used */
  Tcl_Obj *pArray;                /* Name of array variable */
  Tcl_Obj **apColName;            /* Array of column names */
};
1616
1617
1618
1619
1620
1621
1622





1623

1624
1625
1626
1627
1628
1629
1630
  SqliteDb *pDb,                  /* Database handle */
  Tcl_Obj *pSql,                  /* Object containing SQL script */
  Tcl_Obj *pArray,                /* Name of Tcl array to set (*) element of */
  int evalFlags                   /* Flags controlling evaluation */
){
  memset(p, 0, sizeof(DbEvalContext));
  p->pDb = pDb;





  p->zSql = Tcl_GetString(pSql);

  p->pSql = pSql;
  Tcl_IncrRefCount(pSql);
  if( pArray ){
    p->pArray = pArray;
    Tcl_IncrRefCount(pArray);
  }
  p->evalFlags = evalFlags;







>
>
>
>
>
|
>







1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
  SqliteDb *pDb,                  /* Database handle */
  Tcl_Obj *pSql,                  /* Object containing SQL script */
  Tcl_Obj *pArray,                /* Name of Tcl array to set (*) element of */
  int evalFlags                   /* Flags controlling evaluation */
){
  memset(p, 0, sizeof(DbEvalContext));
  p->pDb = pDb;
  if( utf8Encoding!=NULL ){
    p->zSql = Tcl_UtfToExternalDString(utf8Encoding, Tcl_GetString(pSql),
                  pSql->length, &p->dsSql);
  }else{
    Tcl_DStringInit(&p->dsSql);
    p->zSql = Tcl_GetString(pSql);
  }
  p->pSql = pSql;
  Tcl_IncrRefCount(pSql);
  if( pArray ){
    p->pArray = pArray;
    Tcl_IncrRefCount(pArray);
  }
  p->evalFlags = evalFlags;
1646
1647
1648
1649
1650
1651
1652








1653

1654
1655
1656
1657
1658
1659
1660
    int nCol;                     /* Number of columns returned by pStmt */
    Tcl_Obj **apColName = 0;      /* Array of column names */

    p->nCol = nCol = sqlite3_column_count(pStmt);
    if( nCol>0 && (papColName || p->pArray) ){
      apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol );
      for(i=0; i<nCol; i++){








        apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1);

        Tcl_IncrRefCount(apColName[i]);
      }
      p->apColName = apColName;
    }

    /* If results are being stored in an array variable, then create
    ** the array(*) entry for that array







>
>
>
>
>
>
>
>
|
>







1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
    int nCol;                     /* Number of columns returned by pStmt */
    Tcl_Obj **apColName = 0;      /* Array of column names */

    p->nCol = nCol = sqlite3_column_count(pStmt);
    if( nCol>0 && (papColName || p->pArray) ){
      apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol );
      for(i=0; i<nCol; i++){
        if( utf8Encoding!=NULL ){
          Tcl_DString ds;
          Tcl_ExternalToUtfDString(utf8Encoding, sqlite3_column_name(pStmt,i),
              -1, &ds);
          apColName[i] = Tcl_NewStringObj(Tcl_DStringValue(&ds),
                             Tcl_DStringLength(&ds));
          Tcl_DStringFree(&ds);
        }else{
          apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1);
        }
        Tcl_IncrRefCount(apColName[i]);
      }
      p->apColName = apColName;
    }

    /* If results are being stored in an array variable, then create
    ** the array(*) entry for that array
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
          ** This only happens once. If there is a second SQLITE_SCHEMA
          ** error, the error will be returned to the caller. */
          p->zSql = zPrevSql;
          continue;
        }
#endif
        Tcl_SetObjResult(pDb->interp,
                         Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
        return TCL_ERROR;
      }else{
        dbReleaseStmt(pDb, pPreStmt, 0);
      }
    }
  }








|







1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
          ** This only happens once. If there is a second SQLITE_SCHEMA
          ** error, the error will be returned to the caller. */
          p->zSql = zPrevSql;
          continue;
        }
#endif
        Tcl_SetObjResult(pDb->interp,
            Tcl_NewStringObj(SQLITEDB_ERRMSG(pDb), -1));
        return TCL_ERROR;
      }else{
        dbReleaseStmt(pDb, pPreStmt, 0);
      }
    }
  }

1762
1763
1764
1765
1766
1767
1768

1769
1770
1771
1772
1773
1774
1775
    dbReleaseStmt(p->pDb, p->pPreStmt, 0);
    p->pPreStmt = 0;
  }
  if( p->pArray ){
    Tcl_DecrRefCount(p->pArray);
    p->pArray = 0;
  }

  Tcl_DecrRefCount(p->pSql);
  dbReleaseColumnNames(p);
}

/*
** Return a pointer to a Tcl_Obj structure with ref-count 0 that contains
** the value for the iCol'th column of the row currently pointed to by







>







1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
    dbReleaseStmt(p->pDb, p->pPreStmt, 0);
    p->pPreStmt = 0;
  }
  if( p->pArray ){
    Tcl_DecrRefCount(p->pArray);
    p->pArray = 0;
  }
  Tcl_DStringFree(&p->dsSql);
  Tcl_DecrRefCount(p->pSql);
  dbReleaseColumnNames(p);
}

/*
** Return a pointer to a Tcl_Obj structure with ref-count 0 that contains
** the value for the iCol'th column of the row currently pointed to by
1795
1796
1797
1798
1799
1800
1801








1802
1803
1804
1805
1806
1807
1808
1809
    case SQLITE_FLOAT: {
      return Tcl_NewDoubleObj(sqlite3_column_double(pStmt, iCol));
    }
    case SQLITE_NULL: {
      return Tcl_NewStringObj(p->pDb->zNull, -1);
    }
  }









  return Tcl_NewStringObj((char*)sqlite3_column_text(pStmt, iCol), -1);
}

/*
** If using Tcl version 8.6 or greater, use the NR functions to avoid
** recursive evalution of scripts by the [db eval] and [db trans]
** commands. Even if the headers used while compiling the extension







>
>
>
>
>
>
>
>
|







1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
    case SQLITE_FLOAT: {
      return Tcl_NewDoubleObj(sqlite3_column_double(pStmt, iCol));
    }
    case SQLITE_NULL: {
      return Tcl_NewStringObj(p->pDb->zNull, -1);
    }
  }
  if( utf8Encoding!=NULL ){
    Tcl_DString ds;
    Tcl_Obj *obj;
    Tcl_ExternalToUtfDString(utf8Encoding,
        (char*)sqlite3_column_text(pStmt, iCol), -1, &ds);
    obj = Tcl_NewStringObj(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds));
    Tcl_DStringFree(&ds);
    return obj;
  }
  return Tcl_NewStringObj((char*)sqlite3_column_text(pStmt, iCol), -1);
}

/*
** If using Tcl version 8.6 or greater, use the NR functions to avoid
** recursive evalution of scripts by the [db eval] and [db trans]
** commands. Even if the headers used while compiling the extension
2082
2083
2084
2085
2086
2087
2088







2089
2090

2091



2092




2093

2094
2095
2096







2097

2098



2099




2100

2101
2102
2103
2104
2105
2106
2107
2108



2109




2110

2111
2112
2113
2114
2115
2116
2117
    }else if( objc==4 ){
      zSrcDb = Tcl_GetString(objv[2]);
      zDestFile = Tcl_GetString(objv[3]);
    }else{
      Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
      return TCL_ERROR;
    }







    rc = sqlite3_open_v2(zDestFile, &pDest,
               SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE| pDb->openFlags, 0);

    if( rc!=SQLITE_OK ){



      Tcl_AppendResult(interp, "cannot open target database: ",




           sqlite3_errmsg(pDest), (char*)0);

      sqlite3_close(pDest);
      return TCL_ERROR;
    }







    pBackup = sqlite3_backup_init(pDest, "main", pDb->db, zSrcDb);

    if( pBackup==0 ){



      Tcl_AppendResult(interp, "backup failed: ",




           sqlite3_errmsg(pDest), (char*)0);

      sqlite3_close(pDest);
      return TCL_ERROR;
    }
    while(  (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
    sqlite3_backup_finish(pBackup);
    if( rc==SQLITE_DONE ){
      rc = TCL_OK;
    }else{



      Tcl_AppendResult(interp, "backup failed: ",




           sqlite3_errmsg(pDest), (char*)0);

      rc = TCL_ERROR;
    }
    sqlite3_close(pDest);
    break;
  }

  /*    $db bind_fallback ?CALLBACK?







>
>
>
>
>
>
>
|

>

>
>
>
|
>
>
>
>
|
>



>
>
>
>
>
>
>
|
>

>
>
>
|
>
>
>
>
|
>








>
>
>
|
>
>
>
>
|
>







2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
    }else if( objc==4 ){
      zSrcDb = Tcl_GetString(objv[2]);
      zDestFile = Tcl_GetString(objv[3]);
    }else{
      Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
      return TCL_ERROR;
    }
    if( utf8Encoding!=NULL ){
      Tcl_DString ds;
      Tcl_UtfToExternalDString(utf8Encoding, zDestFile, -1, &ds);
      rc = sqlite3_open_v2(Tcl_DStringValue(&ds), &pDest,
               SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE| pDb->openFlags, 0);
      Tcl_DStringFree(&ds);
    }else{
      rc = sqlite3_open_v2(zDestFile, &pDest,
               SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE| pDb->openFlags, 0);
    }
    if( rc!=SQLITE_OK ){
      if( utf8Encoding!=NULL ){
        Tcl_DString ds;
        Tcl_ExternalToUtfDString(utf8Encoding, sqlite3_errmsg(pDest), -1, &ds);
        Tcl_AppendResult(interp, "cannot open target database: ",
             Tcl_DStringValue(&ds), (char*)0);
        Tcl_DStringFree(&ds);
      }else{
        Tcl_AppendResult(interp, "cannot open target database: ",
             sqlite3_errmsg(pDest), (char*)0);
      }
      sqlite3_close(pDest);
      return TCL_ERROR;
    }
    if( utf8Encoding!=NULL ){
      Tcl_DString ds;
      Tcl_UtfToExternalDString(utf8Encoding, zSrcDb, -1, &ds);
      pBackup = sqlite3_backup_init(pDest, "main", pDb->db,
                    Tcl_DStringValue(&ds));
      Tcl_DStringFree(&ds);
    }else{
      pBackup = sqlite3_backup_init(pDest, "main", pDb->db, zSrcDb);
    }
    if( pBackup==0 ){
      if( utf8Encoding!=NULL ){
        Tcl_DString ds;
        Tcl_ExternalToUtfDString(utf8Encoding, sqlite3_errmsg(pDest), -1, &ds);
        Tcl_AppendResult(interp, "backup failed: ",
             Tcl_DStringValue(&ds), (char*)0);
        Tcl_DStringFree(&ds);
      }else{
        Tcl_AppendResult(interp, "backup failed: ",
             sqlite3_errmsg(pDest), (char*)0);
      }
      sqlite3_close(pDest);
      return TCL_ERROR;
    }
    while(  (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK ){}
    sqlite3_backup_finish(pBackup);
    if( rc==SQLITE_DONE ){
      rc = TCL_OK;
    }else{
      if( utf8Encoding!=NULL ){
        Tcl_DString ds;
        Tcl_ExternalToUtfDString(utf8Encoding, sqlite3_errmsg(pDest), -1, &ds);
        Tcl_AppendResult(interp, "backup failed: ",
             Tcl_DStringValue(&ds), (char*)0);
        Tcl_DStringFree(&ds);
      }else{
        Tcl_AppendResult(interp, "backup failed: ",
             sqlite3_errmsg(pDest), (char*)0);
      }
      rc = TCL_ERROR;
    }
    sqlite3_close(pDest);
    break;
  }

  /*    $db bind_fallback ?CALLBACK?
2276
2277
2278
2279
2280
2281
2282

2283
2284
2285
2286
2287






2288
2289
2290
2291
2292
2293
2294
2295
2296
2297

2298
2299
2300

2301
2302
2303
2304
2305
2306
2307
  ** that function is called, invoke SCRIPT to evaluate the function.
  */
  case DB_COLLATE: {
    SqlCollate *pCollate;
    char *zName;
    char *zScript;
    int nScript;

    if( objc!=4 ){
      Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT");
      return TCL_ERROR;
    }
    zName = Tcl_GetString(objv[2]);






    zScript = Tcl_GetStringFromObj(objv[3], &nScript);
    pCollate = (SqlCollate*)Tcl_Alloc( sizeof(*pCollate) + nScript + 1 );
    if( pCollate==0 ) return TCL_ERROR;
    pCollate->interp = interp;
    pCollate->pNext = pDb->pCollate;
    pCollate->zScript = (char*)&pCollate[1];
    pDb->pCollate = pCollate;
    memcpy(pCollate->zScript, zScript, nScript+1);
    if( sqlite3_create_collation_v2(pDb->db, zName, SQLITE_UTF8,
        pCollate, tclSqlCollate, 0) ){

      Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
      return TCL_ERROR;
    }

    break;
  }

  /*
  **     $db collation_needed SCRIPT
  **
  ** Create a new SQL collation function called NAME.  Whenever







>





>
>
>
>
>
>










>
|


>







2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
  ** that function is called, invoke SCRIPT to evaluate the function.
  */
  case DB_COLLATE: {
    SqlCollate *pCollate;
    char *zName;
    char *zScript;
    int nScript;
    Tcl_DString ds;
    if( objc!=4 ){
      Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT");
      return TCL_ERROR;
    }
    zName = Tcl_GetString(objv[2]);
    if( utf8Encoding!=NULL ){
      Tcl_UtfToExternalDString(utf8Encoding, zName, -1, &ds);
      zName = Tcl_DStringValue(&ds);
    }else{
      Tcl_DStringInit(&ds);
    }
    zScript = Tcl_GetStringFromObj(objv[3], &nScript);
    pCollate = (SqlCollate*)Tcl_Alloc( sizeof(*pCollate) + nScript + 1 );
    if( pCollate==0 ) return TCL_ERROR;
    pCollate->interp = interp;
    pCollate->pNext = pDb->pCollate;
    pCollate->zScript = (char*)&pCollate[1];
    pDb->pCollate = pCollate;
    memcpy(pCollate->zScript, zScript, nScript+1);
    if( sqlite3_create_collation_v2(pDb->db, zName, SQLITE_UTF8,
        pCollate, tclSqlCollate, 0) ){
      Tcl_DStringFree(&ds);
      Tcl_AppendResult(interp, (char*)SQLITEDB_ERRMSG(pDb), (char*)0);
      return TCL_ERROR;
    }
    Tcl_DStringFree(&ds);
    break;
  }

  /*
  **     $db collation_needed SCRIPT
  **
  ** Create a new SQL collation function called NAME.  Whenever
2518
2519
2520
2521
2522
2523
2524






2525

2526
2527
2528
2529
2530
2531
2532
2533
2534

2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547



2548




2549

2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560

2561
2562
2563
2564
2565
2566
2567
       strcmp(zConflict, "ignore"  ) != 0 &&
       strcmp(zConflict, "replace" ) != 0 ) {
      Tcl_AppendResult(interp, "Error: \"", zConflict,
            "\", conflict-algorithm must be one of: rollback, "
            "abort, fail, ignore, or replace", (char*)0);
      return TCL_ERROR;
    }






    zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);

    if( zSql==0 ){
      Tcl_AppendResult(interp, "Error: no such table: ", zTable, (char*)0);
      return TCL_ERROR;
    }
    nByte = strlen30(zSql);
    rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
    if( rc ){
      Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0);

      nCol = 0;
    }else{
      nCol = sqlite3_column_count(pStmt);
    }
    sqlite3_finalize(pStmt);
    if( nCol==0 ) {
      return TCL_ERROR;
    }
    zSql = sqlite3_malloc( nByte + 50 + nCol*2 );
    if( zSql==0 ) {
      Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0);
      return TCL_ERROR;
    }



    sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?",




         zConflict, zTable);

    j = strlen30(zSql);
    for(i=1; i<nCol; i++){
      zSql[j++] = ',';
      zSql[j++] = '?';
    }
    zSql[j++] = ')';
    zSql[j] = 0;
    rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
    if( rc ){
      Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), (char*)0);

      sqlite3_finalize(pStmt);
      return TCL_ERROR;
    }
    in = Tcl_OpenFileChannel(interp, zFile, "r", 0666);
    if( in==0 ){
      sqlite3_finalize(pStmt);
      return TCL_ERROR;







>
>
>
>
>
>
|
>








|
>













>
>
>
|
>
>
>
>
|
>










|
>







2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
       strcmp(zConflict, "ignore"  ) != 0 &&
       strcmp(zConflict, "replace" ) != 0 ) {
      Tcl_AppendResult(interp, "Error: \"", zConflict,
            "\", conflict-algorithm must be one of: rollback, "
            "abort, fail, ignore, or replace", (char*)0);
      return TCL_ERROR;
    }
    if( utf8Encoding!=NULL ){
      Tcl_DString ds;
      Tcl_UtfToExternalDString(utf8Encoding, zTable, -1, &ds);
      zSql = sqlite3_mprintf("SELECT * FROM '%q'", Tcl_DStringValue(&ds));
      Tcl_DStringFree(&ds);
    }else{
      zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);
    }
    if( zSql==0 ){
      Tcl_AppendResult(interp, "Error: no such table: ", zTable, (char*)0);
      return TCL_ERROR;
    }
    nByte = strlen30(zSql);
    rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
    if( rc ){
      Tcl_AppendResult(interp, "Error: ", (char*)SQLITEDB_ERRMSG(pDb),
          (char*)0);
      nCol = 0;
    }else{
      nCol = sqlite3_column_count(pStmt);
    }
    sqlite3_finalize(pStmt);
    if( nCol==0 ) {
      return TCL_ERROR;
    }
    zSql = sqlite3_malloc( nByte + 50 + nCol*2 );
    if( zSql==0 ) {
      Tcl_AppendResult(interp, "Error: can't malloc()", (char*)0);
      return TCL_ERROR;
    }
    if( utf8Encoding!=NULL ){
      Tcl_DString ds;
      Tcl_UtfToExternalDString(utf8Encoding, zTable, -1, &ds);
      sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?",
                       zConflict, Tcl_DStringValue(&ds));
      Tcl_DStringFree(&ds);
    }else{
      sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?",
                       zConflict, zTable);
    }
    j = strlen30(zSql);
    for(i=1; i<nCol; i++){
      zSql[j++] = ',';
      zSql[j++] = '?';
    }
    zSql[j++] = ')';
    zSql[j] = 0;
    rc = sqlite3_prepare(pDb->db, zSql, -1, &pStmt, 0);
    sqlite3_free(zSql);
    if( rc ){
      Tcl_AppendResult(interp, "Error: ", (char*)SQLITEDB_ERRMSG(pDb),
          (char*)0);
      sqlite3_finalize(pStmt);
      return TCL_ERROR;
    }
    in = Tcl_OpenFileChannel(interp, zFile, "r", 0666);
    if( in==0 ){
      sqlite3_finalize(pStmt);
      return TCL_ERROR;
2605
2606
2607
2608
2609
2610
2611






2612
2613

2614
2615
2616
2617
2618
2619
2620

2621
2622
2623
2624
2625
2626
2627
        break;
      }
      for(i=0; i<nCol; i++){
        /* check for null data, if so, bind as null */
        if( (azCol[i][0]==0) || (nNull>0 && strcmp(azCol[i], zNull)==0)
        ){
          sqlite3_bind_null(pStmt, i+1);






        }else{
          sqlite3_bind_text(pStmt, i+1, azCol[i], strlen30(azCol[i]), SQLITE_STATIC);

        }
      }
      sqlite3_step(pStmt);
      rc = sqlite3_reset(pStmt);
      Tcl_DStringSetLength(&str, 0);
      if( rc!=SQLITE_OK ){
        Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), (char*)0);

        zCommit = "ROLLBACK";
        break;
      }
    }
    Tcl_DStringFree(&str);
    sqlite3_free(azCol);
    Tcl_Close(interp, in);







>
>
>
>
>
>

|
>






|
>







2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
        break;
      }
      for(i=0; i<nCol; i++){
        /* check for null data, if so, bind as null */
        if( (azCol[i][0]==0) || (nNull>0 && strcmp(azCol[i], zNull)==0)
        ){
          sqlite3_bind_null(pStmt, i+1);
        }else if( utf8Encoding!=NULL ){
          Tcl_DString ds;
          Tcl_UtfToExternalDString(utf8Encoding, azCol[i], -1, &ds);
          sqlite3_bind_text(pStmt, i+1, Tcl_DStringValue(&ds),
              Tcl_DStringLength(&ds), SQLITE_TRANSIENT);
          Tcl_DStringFree(&ds);
        }else{
          sqlite3_bind_text(pStmt, i+1, azCol[i], strlen30(azCol[i]),
              SQLITE_STATIC);
        }
      }
      sqlite3_step(pStmt);
      rc = sqlite3_reset(pStmt);
      Tcl_DStringSetLength(&str, 0);
      if( rc!=SQLITE_OK ){
        Tcl_AppendResult(interp,"Error: ", (char*)SQLITEDB_ERRMSG(pDb),
            (char*)0);
        zCommit = "ROLLBACK";
        break;
      }
    }
    Tcl_DStringFree(&str);
    sqlite3_free(azCol);
    Tcl_Close(interp, in);
2699
2700
2701
2702
2703
2704
2705







2706

2707
2708
2709
2710
2711
2712
2713
      int flags;
      if( len>0 ) memcpy(pData, pBA, len);
      if( isReadonly ){
        flags = SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_READONLY;
      }else{
        flags = SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_RESIZEABLE;
      }







      xrc = sqlite3_deserialize(pDb->db, zSchema, pData, len, len, flags);

      if( xrc ){
        Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0);
        rc = TCL_ERROR;
      }
      if( mxSize>0 ){
        sqlite3_file_control(pDb->db, zSchema,SQLITE_FCNTL_SIZE_LIMIT,&mxSize);
      }







>
>
>
>
>
>
>
|
>







2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
      int flags;
      if( len>0 ) memcpy(pData, pBA, len);
      if( isReadonly ){
        flags = SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_READONLY;
      }else{
        flags = SQLITE_DESERIALIZE_FREEONCLOSE | SQLITE_DESERIALIZE_RESIZEABLE;
      }
      if( utf8Encoding!=NULL ){
        Tcl_DString ds;
        Tcl_ExternalToUtfDString(utf8Encoding, (char*)zSchema, -1, &ds);
        xrc = sqlite3_deserialize(pDb->db, Tcl_DStringValue(&ds),
                  pData, len, len, flags);
        Tcl_DStringFree(&ds);
      } else {
        xrc = sqlite3_deserialize(pDb->db, zSchema, pData, len, len, flags);
      }
      if( xrc ){
        Tcl_AppendResult(interp, "unable to set MEMDB content", (char*)0);
        rc = TCL_ERROR;
      }
      if( mxSize>0 ){
        sqlite3_file_control(pDb->db, zSchema,SQLITE_FCNTL_SIZE_LIMIT,&mxSize);
      }
2875
2876
2877
2878
2879
2880
2881

2882
2883
2884
2885
2886
2887
2888
    int flags = SQLITE_UTF8;
    SqlFunc *pFunc;
    Tcl_Obj *pScript;
    char *zName;
    int nArg = -1;
    int i;
    int eType = SQLITE_NULL;

    if( objc<4 ){
      Tcl_WrongNumArgs(interp, 2, objv, "NAME ?SWITCHES? SCRIPT");
      return TCL_ERROR;
    }
    for(i=3; i<(objc-1); i++){
      const char *z = Tcl_GetString(objv[i]);
      int n = strlen30(z);







>







3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
    int flags = SQLITE_UTF8;
    SqlFunc *pFunc;
    Tcl_Obj *pScript;
    char *zName;
    int nArg = -1;
    int i;
    int eType = SQLITE_NULL;
    Tcl_DString ds;
    if( objc<4 ){
      Tcl_WrongNumArgs(interp, 2, objv, "NAME ?SWITCHES? SCRIPT");
      return TCL_ERROR;
    }
    for(i=3; i<(objc-1); i++){
      const char *z = Tcl_GetString(objv[i]);
      int n = strlen30(z);
2925
2926
2927
2928
2929
2930
2931






2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942

2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
        );
        return TCL_ERROR;
      }
    }

    pScript = objv[objc-1];
    zName = Tcl_GetString(objv[2]);






    pFunc = findSqlFunc(pDb, zName);
    if( pFunc==0 ) return TCL_ERROR;
    if( pFunc->pScript ){
      Tcl_DecrRefCount(pFunc->pScript);
    }
    pFunc->pScript = pScript;
    Tcl_IncrRefCount(pScript);
    pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript);
    pFunc->eType = eType;
    rc = sqlite3_create_function(pDb->db, zName, nArg, flags,
        pFunc, tclSqlFunc, 0, 0);

    if( rc!=SQLITE_OK ){
      rc = TCL_ERROR;
      Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);
    }
    break;
  }

  /*
  **     $db incrblob ?-readonly? ?DB? TABLE COLUMN ROWID
  */







>
>
>
>
>
>











>


|







3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
        );
        return TCL_ERROR;
      }
    }

    pScript = objv[objc-1];
    zName = Tcl_GetString(objv[2]);
    if( utf8Encoding!=NULL ){
      Tcl_UtfToExternalDString(utf8Encoding, zName, -1, &ds);
      zName = Tcl_DStringValue(&ds);
    }else{
      Tcl_DStringInit(&ds);
    }
    pFunc = findSqlFunc(pDb, zName);
    if( pFunc==0 ) return TCL_ERROR;
    if( pFunc->pScript ){
      Tcl_DecrRefCount(pFunc->pScript);
    }
    pFunc->pScript = pScript;
    Tcl_IncrRefCount(pScript);
    pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript);
    pFunc->eType = eType;
    rc = sqlite3_create_function(pDb->db, zName, nArg, flags,
        pFunc, tclSqlFunc, 0, 0);
    Tcl_DStringFree(&ds);
    if( rc!=SQLITE_OK ){
      rc = TCL_ERROR;
      Tcl_SetResult(interp, (char*)SQLITEDB_ERRMSG(pDb), TCL_VOLATILE);
    }
    break;
  }

  /*
  **     $db incrblob ?-readonly? ?DB? TABLE COLUMN ROWID
  */
2975
2976
2977
2978
2979
2980
2981





2982








2983
2984

2985
2986
2987
2988
2989
2990
2991
      zDb = Tcl_GetString(objv[2]);
    }
    zTable = Tcl_GetString(objv[objc-3]);
    zColumn = Tcl_GetString(objv[objc-2]);
    rc = Tcl_GetWideIntFromObj(interp, objv[objc-1], &iRow);

    if( rc==TCL_OK ){





      rc = createIncrblobChannel(








          interp, pDb, zDb, zTable, zColumn, (sqlite3_int64)iRow, isReadonly
      );

    }
#endif
    break;
  }

  /*
  **     $db interrupt







>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
|
>







3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
      zDb = Tcl_GetString(objv[2]);
    }
    zTable = Tcl_GetString(objv[objc-3]);
    zColumn = Tcl_GetString(objv[objc-2]);
    rc = Tcl_GetWideIntFromObj(interp, objv[objc-1], &iRow);

    if( rc==TCL_OK ){
      if( utf8Encoding!=NULL ){
        Tcl_DString ds1, ds2, ds3;
        Tcl_UtfToExternalDString(utf8Encoding, zDb, -1, &ds1);
        Tcl_UtfToExternalDString(utf8Encoding, zTable, -1, &ds2);
        Tcl_UtfToExternalDString(utf8Encoding, zColumn, -1, &ds3);
        rc = createIncrblobChannel(
            interp, pDb, Tcl_DStringValue(&ds1), Tcl_DStringValue(&ds2),
            Tcl_DStringValue(&ds3), (sqlite3_int64)iRow, isReadonly
        );
        Tcl_DStringFree(&ds1);
        Tcl_DStringFree(&ds2);
        Tcl_DStringFree(&ds3);
      }else{
        rc = createIncrblobChannel(
            interp, pDb, zDb, zTable, zColumn, (sqlite3_int64)iRow, isReadonly
        );
      }
    }
#endif
    break;
  }

  /*
  **     $db interrupt
3147
3148
3149
3150
3151
3152
3153






3154

3155
3156
3157
3158
3159
3160
3161
      Tcl_WrongNumArgs(interp, 2, objv, "KEY");
      return TCL_ERROR;
    }
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
    pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
    rc = sqlite3_rekey(pDb->db, pKey, nKey);
    if( rc ){






      Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0);

      rc = TCL_ERROR;
    }
#endif
    break;
  }

  /*    $db restore ?DATABASE? FILENAME







>
>
>
>
>
>
|
>







3384
3385
3386
3387
3388
3389
3390
3391
3392
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
      Tcl_WrongNumArgs(interp, 2, objv, "KEY");
      return TCL_ERROR;
    }
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
    pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
    rc = sqlite3_rekey(pDb->db, pKey, nKey);
    if( rc ){
      if( utf8Encoding!=NULL){
        Tcl_DString ds;
        Tcl_ExternalToUtfDString(utf8Encoding, sqlite3_errstr(rc), -1, &ds);
        Tcl_AppendResult(interp, Tcl_DStringValue(&ds), (char*)0);
        Tcl_DStringFree(&ds);
      }else{
        Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0);
      }
      rc = TCL_ERROR;
    }
#endif
    break;
  }

  /*    $db restore ?DATABASE? FILENAME
3176
3177
3178
3179
3180
3181
3182







3183
3184

3185



3186




3187

3188
3189
3190







3191

3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
    }else if( objc==4 ){
      zDestDb = Tcl_GetString(objv[2]);
      zSrcFile = Tcl_GetString(objv[3]);
    }else{
      Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
      return TCL_ERROR;
    }







    rc = sqlite3_open_v2(zSrcFile, &pSrc,
                         SQLITE_OPEN_READONLY | pDb->openFlags, 0);

    if( rc!=SQLITE_OK ){



      Tcl_AppendResult(interp, "cannot open source database: ",




           sqlite3_errmsg(pSrc), (char*)0);

      sqlite3_close(pSrc);
      return TCL_ERROR;
    }







    pBackup = sqlite3_backup_init(pDb->db, zDestDb, pSrc, "main");

    if( pBackup==0 ){
      Tcl_AppendResult(interp, "restore failed: ",
           sqlite3_errmsg(pDb->db), (char*)0);
      sqlite3_close(pSrc);
      return TCL_ERROR;
    }
    while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
              || rc==SQLITE_BUSY ){
      if( rc==SQLITE_BUSY ){
        if( nTimeout++ >= 3 ) break;
        sqlite3_sleep(100);
      }
    }
    sqlite3_backup_finish(pBackup);
    if( rc==SQLITE_DONE ){
      rc = TCL_OK;
    }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
      Tcl_AppendResult(interp, "restore failed: source database busy",
                       (char*)0);
      rc = TCL_ERROR;
    }else{
      Tcl_AppendResult(interp, "restore failed: ",
           sqlite3_errmsg(pDb->db), (char*)0);
      rc = TCL_ERROR;
    }
    sqlite3_close(pSrc);
    break;
  }

  /*







>
>
>
>
>
>
>
|
|
>

>
>
>
|
>
>
>
>
|
>



>
>
>
>
>
>
>
|
>


|



















|







3420
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
3438
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
    }else if( objc==4 ){
      zDestDb = Tcl_GetString(objv[2]);
      zSrcFile = Tcl_GetString(objv[3]);
    }else{
      Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE? FILENAME");
      return TCL_ERROR;
    }
    if( utf8Encoding!=NULL ){
      Tcl_DString ds;
      Tcl_UtfToExternalDString(utf8Encoding, zSrcFile, -1, &ds);
      rc = sqlite3_open_v2(Tcl_DStringValue(&ds), &pSrc,
               SQLITE_OPEN_READONLY | pDb->openFlags, 0);
      Tcl_DStringFree(&ds);
    }else{
      rc = sqlite3_open_v2(zSrcFile, &pSrc,
                           SQLITE_OPEN_READONLY | pDb->openFlags, 0);
    }
    if( rc!=SQLITE_OK ){
      if( utf8Encoding!=NULL ){
        Tcl_DString ds;
        Tcl_ExternalToUtfDString(utf8Encoding, sqlite3_errmsg(pSrc), -1, &ds);
        Tcl_AppendResult(interp, "cannot open source database: ",
             Tcl_DStringValue(&ds), (char*)0);
        Tcl_DStringFree(&ds);
      }else{
        Tcl_AppendResult(interp, "cannot open source database: ",
             sqlite3_errmsg(pSrc), (char*)0);
      }
      sqlite3_close(pSrc);
      return TCL_ERROR;
    }
    if( utf8Encoding!=NULL ){
      Tcl_DString ds;
      Tcl_UtfToExternalDString(utf8Encoding, zDestDb, -1, &ds);
      pBackup = sqlite3_backup_init(pDb->db, Tcl_DStringValue(&ds), pSrc,
                    "main");
      Tcl_DStringFree(&ds);
    }else{
      pBackup = sqlite3_backup_init(pDb->db, zDestDb, pSrc, "main");
    }
    if( pBackup==0 ){
      Tcl_AppendResult(interp, "restore failed: ",
          (char*)SQLITEDB_ERRMSG(pDb), (char*)0);
      sqlite3_close(pSrc);
      return TCL_ERROR;
    }
    while( (rc = sqlite3_backup_step(pBackup,100))==SQLITE_OK
              || rc==SQLITE_BUSY ){
      if( rc==SQLITE_BUSY ){
        if( nTimeout++ >= 3 ) break;
        sqlite3_sleep(100);
      }
    }
    sqlite3_backup_finish(pBackup);
    if( rc==SQLITE_DONE ){
      rc = TCL_OK;
    }else if( rc==SQLITE_BUSY || rc==SQLITE_LOCKED ){
      Tcl_AppendResult(interp, "restore failed: source database busy",
                       (char*)0);
      rc = TCL_ERROR;
    }else{
      Tcl_AppendResult(interp, "restore failed: ",
          (char*)SQLITEDB_ERRMSG(pDb), (char*)0);
      rc = TCL_ERROR;
    }
    sqlite3_close(pSrc);
    break;
  }

  /*
3233
3234
3235
3236
3237
3238
3239







3240


3241
3242
3243
3244
3245
3246
3247
    sqlite3_int64 sz = 0;
    unsigned char *pData;
    if( objc!=2 && objc!=3 ){
      Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE?");
      rc = TCL_ERROR;
    }else{
      int needFree;







      pData = sqlite3_serialize(pDb->db, zSchema, &sz, SQLITE_SERIALIZE_NOCOPY);


      if( pData ){
        needFree = 0;
      }else{
        pData = sqlite3_serialize(pDb->db, zSchema, &sz, 0);
        needFree = 1;
      }
      Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pData,sz));







>
>
>
>
>
>
>
|
>
>







3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
    sqlite3_int64 sz = 0;
    unsigned char *pData;
    if( objc!=2 && objc!=3 ){
      Tcl_WrongNumArgs(interp, 2, objv, "?DATABASE?");
      rc = TCL_ERROR;
    }else{
      int needFree;
      if( utf8Encoding!=NULL ){
        Tcl_DString ds;
        Tcl_ExternalToUtfDString(utf8Encoding, (char*)zSchema, -1, &ds);
        pData = sqlite3_serialize(pDb->db, Tcl_DStringValue(&ds), &sz,
                    SQLITE_SERIALIZE_NOCOPY);
        Tcl_DStringFree(&ds);
      } else {
        pData = sqlite3_serialize(pDb->db, zSchema, &sz,
                    SQLITE_SERIALIZE_NOCOPY);
      }
      if( pData ){
        needFree = 0;
      }else{
        pData = sqlite3_serialize(pDb->db, zSchema, &sz, 0);
        needFree = 1;
      }
      Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pData,sz));
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
    pScript = objv[objc-1];

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

    /* If using NRE, schedule a callback to invoke the script pScript, then
    ** a second callback to commit (or rollback) the transaction or savepoint
    ** opened above. If not using NRE, evaluate the script directly, then







|







3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
3768
3769
    pScript = objv[objc-1];

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

    /* If using NRE, schedule a callback to invoke the script pScript, then
    ** a second callback to commit (or rollback) the transaction or savepoint
    ** opened above. If not using NRE, evaluate the script directly, then
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
        xNotify = DbUnlockNotify;
        pNotifyArg = (void *)pDb;
        pDb->pUnlockNotify = objv[2];
        Tcl_IncrRefCount(pDb->pUnlockNotify);
      }

      if( sqlite3_unlock_notify(pDb->db, xNotify, pNotifyArg) ){
        Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
        rc = TCL_ERROR;
      }
    }
#endif
    break;
  }








|







3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
        xNotify = DbUnlockNotify;
        pNotifyArg = (void *)pDb;
        pDb->pUnlockNotify = objv[2];
        Tcl_IncrRefCount(pDb->pUnlockNotify);
      }

      if( sqlite3_unlock_notify(pDb->db, xNotify, pNotifyArg) ){
        Tcl_AppendResult(interp, (char*)SQLITEDB_ERRMSG(pDb), (char*)0);
        rc = TCL_ERROR;
      }
    }
#endif
    break;
  }

3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
        }

        if( rc==SQLITE_OK ){
          Tcl_Obj *pObj;
          pObj = Tcl_NewStringObj((char*)sqlite3_value_text(pValue), -1);
          Tcl_SetObjResult(interp, pObj);
        }else{
          Tcl_AppendResult(interp, sqlite3_errmsg(pDb->db), (char*)0);
          return TCL_ERROR;
        }
      }
    }
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
    break;
  }







|







3887
3888
3889
3890
3891
3892
3893
3894
3895
3896
3897
3898
3899
3900
3901
        }

        if( rc==SQLITE_OK ){
          Tcl_Obj *pObj;
          pObj = Tcl_NewStringObj((char*)sqlite3_value_text(pValue), -1);
          Tcl_SetObjResult(interp, pObj);
        }else{
          Tcl_AppendResult(interp, (char*)SQLITEDB_ERRMSG(pDb), (char*)0);
          return TCL_ERROR;
        }
      }
    }
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */
    break;
  }
3860
3861
3862
3863
3864
3865
3866

3867
3868













3869

3870
3871
3872
3873
3874
3875
3876
3877
3878
3879
3880
3881
3882
3883
3884
3885






3886

3887
3888
3889
3890
3891
3892
3893
      Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0);
      return TCL_ERROR;
    }
  }
  zErrMsg = 0;
  p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
  memset(p, 0, sizeof(*p));

  if( zFile==0 ) zFile = "";
  zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);













  rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs);

  Tcl_DStringFree(&translatedFilename);
  if( p->db ){
    if( SQLITE_OK!=sqlite3_errcode(p->db) ){
      zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
      sqlite3_close(p->db);
      p->db = 0;
    }
  }else{
    zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc));
  }
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
  if( p->db ){
    sqlite3_key(p->db, pKey, nKey);
  }
#endif
  if( p->db==0 ){






    Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);

    Tcl_Free((char*)p);
    sqlite3_free(zErrMsg);
    return TCL_ERROR;
  }
  p->maxStmt = NUM_PREPARED_STMTS;
  p->openFlags = flags & SQLITE_OPEN_URI;
  p->interp = interp;







>


>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
















>
>
>
>
>
>
|
>







4137
4138
4139
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
      Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0);
      return TCL_ERROR;
    }
  }
  zErrMsg = 0;
  p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
  memset(p, 0, sizeof(*p));
  Tcl_DStringInit(&p->dsErr);
  if( zFile==0 ) zFile = "";
  zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);
  if( utf8Encoding!=NULL ){
    Tcl_DString ds1, ds2;
    Tcl_UtfToExternalDString(utf8Encoding, zFile, -1, &ds1);
    if ( zVfs!=NULL ){
      Tcl_UtfToExternalDString(utf8Encoding, zVfs, -1, &ds2);
      zVfs = Tcl_DStringValue(&ds2);
    }
    rc = sqlite3_open_v2(Tcl_DStringValue(&ds1), &p->db, flags, zVfs);
    Tcl_DStringFree(&ds1);
    if( zVfs!=NULL ){
      Tcl_DStringFree(&ds2);
    }
  }else{
    rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs);
  }
  Tcl_DStringFree(&translatedFilename);
  if( p->db ){
    if( SQLITE_OK!=sqlite3_errcode(p->db) ){
      zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
      sqlite3_close(p->db);
      p->db = 0;
    }
  }else{
    zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc));
  }
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
  if( p->db ){
    sqlite3_key(p->db, pKey, nKey);
  }
#endif
  if( p->db==0 ){
    if( utf8Encoding!=NULL && zErrMsg ){
      Tcl_DString ds;
      Tcl_ExternalToUtfDString(utf8Encoding, zErrMsg, -1, &ds);
      Tcl_AppendResult(interp, Tcl_DStringValue(&ds), (char*)0);
      Tcl_DStringFree(&ds);
    }else{
      Tcl_AppendResult(interp, zErrMsg, (char*)0);
    }
    Tcl_Free((char*)p);
    sqlite3_free(zErrMsg);
    return TCL_ERROR;
  }
  p->maxStmt = NUM_PREPARED_STMTS;
  p->openFlags = flags & SQLITE_OPEN_URI;
  p->interp = interp;
3958
3959
3960
3961
3962
3963
3964







































3965
3966
3967
3968
















3969


3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983


3984


3985
3986
3987
3988
3989
3990
3991
    /* The "sqlite" alias is undocumented.  It is here only to support
    ** legacy scripts.  All new scripts should use only the "sqlite3"
    ** command. */
    Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0);
#endif
    rc = Tcl_PkgProvideEx(interp, "sqlite3", PACKAGE_VERSION, NULL);
  }







































  return rc;
}
DLLEXPORT int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
DLLEXPORT int Sqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }
















DLLEXPORT int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }



/* Because it accesses the file-system and uses persistent state, SQLite
** is not considered appropriate for safe interpreters.  Hence, we cause
** the _SafeInit() interfaces return TCL_ERROR.
*/
DLLEXPORT int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_ERROR; }
DLLEXPORT int Sqlite3_SafeUnload(Tcl_Interp *interp, int flags){return TCL_ERROR;}



#ifndef SQLITE_3_SUFFIX_ONLY
int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
int Sqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }


int Tclsqlite_Unload(Tcl_Interp *interp, int flags){ return TCL_OK; }


#endif

/*
** If the TCLSH macro is defined, add code to make a stand-alone program.
*/
#if defined(TCLSH)








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>













|
>
>
|
>
>







4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
4267
4268
4269
4270
4271
4272
4273
4274
4275
4276
4277
4278
4279
4280
4281
4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
    /* The "sqlite" alias is undocumented.  It is here only to support
    ** legacy scripts.  All new scripts should use only the "sqlite3"
    ** command. */
    Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0);
#endif
    rc = Tcl_PkgProvideEx(interp, "sqlite3", PACKAGE_VERSION, NULL);
  }
  if( !utf8EncInit ){
    Tcl_Encoding enc;
    Tcl_MutexLock(&utf8EncMutex);
    if( ++utf8EncInit>1 ){
      goto utf8EncInitDone;
    }
    enc = Tcl_GetEncoding(NULL, "utf-8");
    /*
     ** Try to detect the level of UTF-8 support in the Tcl core.
     */
    if( enc!=NULL ){
      const char probe1[] = { 0xF0, 0x9F, 0x98, 0x82 };
      const char probe1sp[] = { 0xED, 0xA0, 0xBD, 0xED, 0xB8, 0x82 };
      Tcl_DString ds;
      Tcl_ExternalToUtfDString(enc, probe1, sizeof(probe1), &ds);
      if( Tcl_DStringLength(&ds)==sizeof(probe1) &&
          memcmp(probe1, Tcl_DStringValue(&ds), sizeof(probe1))==0 ){
        /*
         ** Tcl core supports full Unicode.
         */
        Tcl_FreeEncoding(enc);
      }else if( Tcl_DStringLength(&ds)==sizeof(probe1sp) &&
          memcmp(probe1sp, Tcl_DStringValue(&ds), sizeof(probe1sp))==0 ){
        /*
         ** Tcl core supports full Unicode using surrogate pairs,
         ** keep utf8Encoding for conversion to/from 4 byte UTF-8 sequences.
         */
        utf8Encoding = enc;
      }else{
        /*
         ** Tcl core supports BMP only, let SQLite handle corner cases.
         */
        Tcl_FreeEncoding(enc);
      }
      Tcl_DStringFree(&ds);
    }
utf8EncInitDone:
    Tcl_MutexUnlock(&utf8EncMutex);
  }
  return rc;
}

DLLEXPORT int Sqlite3_Unload(Tcl_Interp *interp, int flags){
  Tcl_MutexLock(&utf8EncMutex);
  if( --utf8EncInit<1 ){
    if( utf8Encoding!=NULL ){
      Tcl_FreeEncoding(utf8Encoding);
      utf8Encoding = NULL;
    }
    utf8EncInit = 0;
  }
  Tcl_MutexUnlock(&utf8EncMutex);
  return TCL_OK;
}

DLLEXPORT int Tclsqlite3_Init(Tcl_Interp *interp){
  return Sqlite3_Init(interp);
}

DLLEXPORT int Tclsqlite3_Unload(Tcl_Interp *interp, int flags){
  return Sqlite3_Unload(interp, flags);
}

/* Because it accesses the file-system and uses persistent state, SQLite
** is not considered appropriate for safe interpreters.  Hence, we cause
** the _SafeInit() interfaces return TCL_ERROR.
*/
DLLEXPORT int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_ERROR; }
DLLEXPORT int Sqlite3_SafeUnload(Tcl_Interp *interp, int flags){return TCL_ERROR;}



#ifndef SQLITE_3_SUFFIX_ONLY
int Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }
int Sqlite_Unload(Tcl_Interp *interp, int flags){
  return SqLite3_Unload(interp, flags);
}
int Tclsqlite_Unload(Tcl_Interp *interp, int flags){
  return Sqlite3_Unload(interp, flags);
}
#endif

/*
** If the TCLSH macro is defined, add code to make a stand-alone program.
*/
#if defined(TCLSH)