/ Check-in [fc3b3a8f]
Login

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

Overview
Comment:Make sure VdbeFunc entries are initialized before trying to destroy them. Also, unrelated comment changes in build.c. (CVS 1643)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:fc3b3a8fe86980db4de402bb8e85f8f739fc3883
User & Date: drh 2004-06-19 17:33:07
Context
2004-06-20
03:06
fix fulltest error by restoring unset (CVS 1644) check-in: d2ccac9d user: dougcurrie tags: trunk
2004-06-19
17:33
Make sure VdbeFunc entries are initialized before trying to destroy them. Also, unrelated comment changes in build.c. (CVS 1643) check-in: fc3b3a8f user: drh tags: trunk
16:06
Omit the DB_Locked and DB_Cookie flags. Other minor cleanup. (CVS 1642) check-in: 01f74b42 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
58
59
60
61
62
63
64







65
66
67
68
69
70
71
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
...
353
354
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
...
440
441
442
443
444
445
446
















447
448
449
450
451
452
453

454
455
456
457
458
459
460
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.226 2004/06/19 16:06:12 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
................................................................................
  /* Begin by generating some termination code at the end of the
  ** vdbe program
  */
  db = pParse->db;
  v = sqlite3GetVdbe(pParse);
  if( v ){
    sqlite3VdbeAddOp(v, OP_Halt, 0, 0);







    if( pParse->cookieMask!=0 ){
      u32 mask;
      int iDb;
      sqlite3VdbeChangeP2(v, pParse->cookieGoto, sqlite3VdbeCurrentAddr(v));
      for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
        if( (mask & pParse->cookieMask)==0 ) continue;
        sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
................................................................................
    }
  }
  sqliteDeleteIndex(db, pIndex);
}

/*
** Erase all schema information from the in-memory hash tables of
** database connection.  This routine is called to reclaim memory
** before the connection closes.  It is also called during a rollback
** if there were schema changes during the transaction.
**
** If iDb<=0 then reset the internal schema tables for all database
** files.  If iDb>=2 then reset the internal schema for only the
** single file indicated.
*/
void sqlite3ResetInternalSchema(sqlite *db, int iDb){
................................................................................
                           pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
    sqliteFree(pFKey);
  }

  /* Delete the Table structure itself.
  */
  for(i=0; i<pTable->nCol; i++){
    sqliteFree(pTable->aCol[i].zName);
    sqliteFree(pTable->aCol[i].zDflt);
    sqliteFree(pTable->aCol[i].zType);

  }
  sqliteFree(pTable->zName);
  sqliteFree(pTable->aCol);
  if( pTable->zColAff ){
    sqliteFree(pTable->zColAff);
  }
  sqlite3SelectDelete(pTable->pSelect);
................................................................................
** table structure with all its indices and foreign keys.
*/
static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){
  Table *pOld;
  FKey *pF1, *pF2;
  int i = p->iDb;
  assert( db!=0 );
  pOld = sqlite3HashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1, 0);
  assert( pOld==0 || pOld==p );
  for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
    int nTo = strlen(pF1->zTo) + 1;
    pF2 = sqlite3HashFind(&db->aDb[i].aFKey, pF1->zTo, nTo);
    if( pF2==pF1 ){
      sqlite3HashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo);
    }else{
................................................................................
        0==sqlite3StrNICmp(db->aDb[i].zName, pName->z, pName->n) ){
      return i;
    }
  }
  return -1;
}

















int sqlite3TwoPartName(
  Parse *pParse, 
  Token *pName1, 
  Token *pName2, 
  Token **pUnqual
){
  int iDb;

  sqlite3 *db = pParse->db;

  if( pName2 && pName2->n>0 ){
    assert( !db->init.busy );
    *pUnqual = pName2;
    iDb = findDb(db, pName1);
    if( iDb<0 ){







|







 







>
>
>
>
>
>
>







 







|
|







 







|
|
|
>







 







|







 







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

|
|
|
|

<
>







19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
...
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
...
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
...
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476

477
478
479
480
481
482
483
484
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.227 2004/06/19 17:33:07 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
................................................................................
  /* Begin by generating some termination code at the end of the
  ** vdbe program
  */
  db = pParse->db;
  v = sqlite3GetVdbe(pParse);
  if( v ){
    sqlite3VdbeAddOp(v, OP_Halt, 0, 0);

    /* The cookie mask contains one bit for each database file open.
    ** (Bit 0 is for main, bit 1 is for temp, and so forth.)  Bits are
    ** set for each database that is used.  Generate code to start a
    ** transaction on each used database and to verify the schema cookie
    ** on each used database.
    */
    if( pParse->cookieMask!=0 ){
      u32 mask;
      int iDb;
      sqlite3VdbeChangeP2(v, pParse->cookieGoto, sqlite3VdbeCurrentAddr(v));
      for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
        if( (mask & pParse->cookieMask)==0 ) continue;
        sqlite3VdbeAddOp(v, OP_Transaction, iDb, (mask & pParse->writeMask)!=0);
................................................................................
    }
  }
  sqliteDeleteIndex(db, pIndex);
}

/*
** Erase all schema information from the in-memory hash tables of
** a sigle database.  This routine is called to reclaim memory
** before the closes.  It is also called during a rollback
** if there were schema changes during the transaction.
**
** If iDb<=0 then reset the internal schema tables for all database
** files.  If iDb>=2 then reset the internal schema for only the
** single file indicated.
*/
void sqlite3ResetInternalSchema(sqlite *db, int iDb){
................................................................................
                           pFKey->zTo, strlen(pFKey->zTo)+1)!=pFKey );
    sqliteFree(pFKey);
  }

  /* Delete the Table structure itself.
  */
  for(i=0; i<pTable->nCol; i++){
    Column *pCol = &pTable->aCol[i];
    sqliteFree(pCol->zName);
    sqliteFree(pCol->zDflt);
    sqliteFree(pCol->zType);
  }
  sqliteFree(pTable->zName);
  sqliteFree(pTable->aCol);
  if( pTable->zColAff ){
    sqliteFree(pTable->zColAff);
  }
  sqlite3SelectDelete(pTable->pSelect);
................................................................................
** table structure with all its indices and foreign keys.
*/
static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){
  Table *pOld;
  FKey *pF1, *pF2;
  int i = p->iDb;
  assert( db!=0 );
  pOld = sqlite3HashInsert(&db->aDb[i].tblHash, p->zName, strlen(p->zName)+1,0);
  assert( pOld==0 || pOld==p );
  for(pF1=p->pFKey; pF1; pF1=pF1->pNextFrom){
    int nTo = strlen(pF1->zTo) + 1;
    pF2 = sqlite3HashFind(&db->aDb[i].aFKey, pF1->zTo, nTo);
    if( pF2==pF1 ){
      sqlite3HashInsert(&db->aDb[i].aFKey, pF1->zTo, nTo, pF1->pNextTo);
    }else{
................................................................................
        0==sqlite3StrNICmp(db->aDb[i].zName, pName->z, pName->n) ){
      return i;
    }
  }
  return -1;
}

/* The table or view or trigger name is passed to this routine via tokens
** pName1 and pName2. If the table name was fully qualified, for example:
**
** CREATE TABLE xxx.yyy (...);
** 
** Then pName1 is set to "xxx" and pName2 "yyy". On the other hand if
** the table name is not fully qualified, i.e.:
**
** CREATE TABLE yyy(...);
**
** Then pName1 is set to "yyy" and pName2 is "".
**
** This routine sets the *ppUnqual pointer to point at the token (pName1 or
** pName2) that stores the unqualified table name.  The index of the
** database "xxx" is returned.
*/
int sqlite3TwoPartName(
  Parse *pParse,      /* Parsing and code generating context */
  Token *pName1,      /* The "xxx" in the name "xxx.yyy" */
  Token *pName2,      /* The "yyy" in the name "xxx.yyy" */
  Token **pUnqual     /* Write the unqualified object name here */
){

  int iDb;                    /* Database holding the object */
  sqlite3 *db = pParse->db;

  if( pName2 && pName2->n>0 ){
    assert( !db->init.busy );
    *pUnqual = pName2;
    iDb = findDb(db, pName1);
    if( iDb<0 ){

Changes to src/func.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
764
765
766
767
768
769
770

771

772
773
774
775
776
777
778
...
806
807
808
809
810
811
812

813












814
815
816
817
818
819
820
...
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.73 2004/06/19 15:40:23 drh Exp $
*/
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "sqliteInt.h"
#include "vdbeInt.h"
................................................................................
  sqlite3Randomness(n, zBuf);
  for(i=0; i<n; i++){
    zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)];
  }
  zBuf[n] = 0;
  sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT);
}



/*
** The following two SQL functions are used to test returning a text
** result with a destructor. Function 'test_destructor' takes one argument
** and returns the same argument interpreted as TEXT. A destructor is
** passed with the sqlite3_result_text() call.
**
** SQL function 'test_destructor_count' returns the number of outstanding 
................................................................................
static void test_destructor_count(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **argv
){
  sqlite3_result_int(pCtx, test_destructor_count_var);
}














static void free_test_auxdata(void *p) {sqliteFree(p);}
static void test_auxdata(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **argv
){
  int i;
................................................................................
        sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata);
      }
      zRet[i*2+1] = ' ';
    }
  }
  sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata);
}
#endif

/*
** An instance of the following structure holds the context of a
** sum() or avg() aggregate computation.
*/
typedef struct SumCtx SumCtx;
struct SumCtx {







|







 







>

>







 







>

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







 







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
...
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
...
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.74 2004/06/19 17:33:07 drh Exp $
*/
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include "sqliteInt.h"
#include "vdbeInt.h"
................................................................................
  sqlite3Randomness(n, zBuf);
  for(i=0; i<n; i++){
    zBuf[i] = zSrc[zBuf[i]%(sizeof(zSrc)-1)];
  }
  zBuf[n] = 0;
  sqlite3_result_text(context, zBuf, n, SQLITE_TRANSIENT);
}
#endif /* SQLITE_TEST */

#ifdef SQLITE_TEST
/*
** The following two SQL functions are used to test returning a text
** result with a destructor. Function 'test_destructor' takes one argument
** and returns the same argument interpreted as TEXT. A destructor is
** passed with the sqlite3_result_text() call.
**
** SQL function 'test_destructor_count' returns the number of outstanding 
................................................................................
static void test_destructor_count(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **argv
){
  sqlite3_result_int(pCtx, test_destructor_count_var);
}
#endif /* SQLITE_TEST */

#ifdef SQLITE_TEST
/*
** Routines for testing the sqlite3_get_auxdata() and sqlite3_set_auxdata()
** interface.
**
** The test_auxdata() SQL function attempts to register each of its arguments
** as auxiliary data.  If there are no prior registrations of aux data for
** that argument (meaning the argument is not a constant or this is its first
** call) then the result for that argument is 0.  If there is a prior
** registration, the result for that argument is 1.  The overall result
** is the individual argument results separated by spaces.
*/
static void free_test_auxdata(void *p) {sqliteFree(p);}
static void test_auxdata(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **argv
){
  int i;
................................................................................
        sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata);
      }
      zRet[i*2+1] = ' ';
    }
  }
  sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata);
}
#endif /* SQLITE_TEST */

/*
** An instance of the following structure holds the context of a
** sum() or avg() aggregate computation.
*/
typedef struct SumCtx SumCtx;
struct SumCtx {

Changes to src/vdbeapi.c.

237
238
239
240
241
242
243


244
245
246
247
248
249
250
  if( iArg<0 ) return;

  pVdbeFunc = pCtx->pVdbeFunc;
  if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){
    int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg;
    pCtx->pVdbeFunc = pVdbeFunc = sqliteRealloc(pVdbeFunc, nMalloc);
    if( !pVdbeFunc ) return;


    pVdbeFunc->nAux = iArg+1;
    pVdbeFunc->pFunc = pCtx->pFunc;
  }

  pAuxData = &pVdbeFunc->apAux[iArg];
  if( pAuxData->pAux && pAuxData->xDelete ){
    pAuxData->xDelete(pAuxData->pAux);







>
>







237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
  if( iArg<0 ) return;

  pVdbeFunc = pCtx->pVdbeFunc;
  if( !pVdbeFunc || pVdbeFunc->nAux<=iArg ){
    int nMalloc = sizeof(VdbeFunc) + sizeof(struct AuxData)*iArg;
    pCtx->pVdbeFunc = pVdbeFunc = sqliteRealloc(pVdbeFunc, nMalloc);
    if( !pVdbeFunc ) return;
    memset(&pVdbeFunc->apAux[pVdbeFunc->nAux], 0, 
             sizeof(struct AuxData)*(iArg+1-pVdbeFunc->nAux));
    pVdbeFunc->nAux = iArg+1;
    pVdbeFunc->pFunc = pCtx->pFunc;
  }

  pAuxData = &pVdbeFunc->apAux[iArg];
  if( pAuxData->pAux && pAuxData->xDelete ){
    pAuxData->xDelete(pAuxData->pAux);

Changes to test/func.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
432
433
434
435
436
437
438
439
440
441
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing built-in functions.
#
# $Id: func.test,v 1.23 2004/06/19 00:16:31 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
do_test func-0.0 {
................................................................................
    lappend res [sqlite3_column_text $STMT 0]
  }
  lappend res [sqlite3_finalize $STMT]
} {{0 0} {1 0} SQLITE_OK}


finish_test










|







 







<
<
<
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
432
433
434
435
436
437
438



#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing built-in functions.
#
# $Id: func.test,v 1.24 2004/06/19 17:33:08 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create a table to work with.
#
do_test func-0.0 {
................................................................................
    lappend res [sqlite3_column_text $STMT 0]
  }
  lappend res [sqlite3_finalize $STMT]
} {{0 0} {1 0} SQLITE_OK}


finish_test