extensions/sqlite/sqlite-source/callback.c
author David Anderson <dvander@alliedmods.net>
Sun Oct 28 05:48:06 2007 +0000 (2007-10-28)
changeset 1645 27307df4d711
parent 1203 633c25ce6405
permissions -rw-r--r--
updated to sqlite-3.5.1 now that it's stable
used new shared cache functionality (yay)
dvander@1203
     1
/*
dvander@1203
     2
** 2005 May 23 
dvander@1203
     3
**
dvander@1203
     4
** The author disclaims copyright to this source code.  In place of
dvander@1203
     5
** a legal notice, here is a blessing:
dvander@1203
     6
**
dvander@1203
     7
**    May you do good and not evil.
dvander@1203
     8
**    May you find forgiveness for yourself and forgive others.
dvander@1203
     9
**    May you share freely, never taking more than you give.
dvander@1203
    10
**
dvander@1203
    11
*************************************************************************
dvander@1203
    12
**
dvander@1203
    13
** This file contains functions used to access the internal hash tables
dvander@1203
    14
** of user defined functions and collation sequences.
dvander@1203
    15
**
dvander@1203
    16
** $Id$
dvander@1203
    17
*/
dvander@1203
    18
dvander@1203
    19
#include "sqliteInt.h"
dvander@1203
    20
dvander@1203
    21
/*
dvander@1203
    22
** Invoke the 'collation needed' callback to request a collation sequence
dvander@1203
    23
** in the database text encoding of name zName, length nName.
dvander@1203
    24
** If the collation sequence
dvander@1203
    25
*/
dvander@1203
    26
static void callCollNeeded(sqlite3 *db, const char *zName, int nName){
dvander@1203
    27
  assert( !db->xCollNeeded || !db->xCollNeeded16 );
dvander@1203
    28
  if( nName<0 ) nName = strlen(zName);
dvander@1203
    29
  if( db->xCollNeeded ){
dvander@1645
    30
    char *zExternal = sqlite3DbStrNDup(db, zName, nName);
dvander@1203
    31
    if( !zExternal ) return;
dvander@1203
    32
    db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal);
dvander@1645
    33
    sqlite3_free(zExternal);
dvander@1203
    34
  }
dvander@1203
    35
#ifndef SQLITE_OMIT_UTF16
dvander@1203
    36
  if( db->xCollNeeded16 ){
dvander@1203
    37
    char const *zExternal;
dvander@1645
    38
    sqlite3_value *pTmp = sqlite3ValueNew(db);
dvander@1203
    39
    sqlite3ValueSetStr(pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC);
dvander@1203
    40
    zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE);
dvander@1203
    41
    if( zExternal ){
dvander@1203
    42
      db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal);
dvander@1203
    43
    }
dvander@1203
    44
    sqlite3ValueFree(pTmp);
dvander@1203
    45
  }
dvander@1203
    46
#endif
dvander@1203
    47
}
dvander@1203
    48
dvander@1203
    49
/*
dvander@1203
    50
** This routine is called if the collation factory fails to deliver a
dvander@1203
    51
** collation function in the best encoding but there may be other versions
dvander@1203
    52
** of this collation function (for other text encodings) available. Use one
dvander@1203
    53
** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if
dvander@1203
    54
** possible.
dvander@1203
    55
*/
dvander@1203
    56
static int synthCollSeq(sqlite3 *db, CollSeq *pColl){
dvander@1203
    57
  CollSeq *pColl2;
dvander@1203
    58
  char *z = pColl->zName;
dvander@1203
    59
  int n = strlen(z);
dvander@1203
    60
  int i;
dvander@1203
    61
  static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 };
dvander@1203
    62
  for(i=0; i<3; i++){
dvander@1203
    63
    pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, n, 0);
dvander@1203
    64
    if( pColl2->xCmp!=0 ){
dvander@1203
    65
      memcpy(pColl, pColl2, sizeof(CollSeq));
dvander@1203
    66
      pColl->xDel = 0;         /* Do not copy the destructor */
dvander@1203
    67
      return SQLITE_OK;
dvander@1203
    68
    }
dvander@1203
    69
  }
dvander@1203
    70
  return SQLITE_ERROR;
dvander@1203
    71
}
dvander@1203
    72
dvander@1203
    73
/*
dvander@1203
    74
** This function is responsible for invoking the collation factory callback
dvander@1203
    75
** or substituting a collation sequence of a different encoding when the
dvander@1203
    76
** requested collation sequence is not available in the database native
dvander@1203
    77
** encoding.
dvander@1203
    78
** 
dvander@1203
    79
** If it is not NULL, then pColl must point to the database native encoding 
dvander@1203
    80
** collation sequence with name zName, length nName.
dvander@1203
    81
**
dvander@1203
    82
** The return value is either the collation sequence to be used in database
dvander@1203
    83
** db for collation type name zName, length nName, or NULL, if no collation
dvander@1203
    84
** sequence can be found.
dvander@1203
    85
*/
dvander@1203
    86
CollSeq *sqlite3GetCollSeq(
dvander@1203
    87
  sqlite3* db, 
dvander@1203
    88
  CollSeq *pColl, 
dvander@1203
    89
  const char *zName, 
dvander@1203
    90
  int nName
dvander@1203
    91
){
dvander@1203
    92
  CollSeq *p;
dvander@1203
    93
dvander@1203
    94
  p = pColl;
dvander@1203
    95
  if( !p ){
dvander@1203
    96
    p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0);
dvander@1203
    97
  }
dvander@1203
    98
  if( !p || !p->xCmp ){
dvander@1203
    99
    /* No collation sequence of this type for this encoding is registered.
dvander@1203
   100
    ** Call the collation factory to see if it can supply us with one.
dvander@1203
   101
    */
dvander@1203
   102
    callCollNeeded(db, zName, nName);
dvander@1203
   103
    p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0);
dvander@1203
   104
  }
dvander@1203
   105
  if( p && !p->xCmp && synthCollSeq(db, p) ){
dvander@1203
   106
    p = 0;
dvander@1203
   107
  }
dvander@1203
   108
  assert( !p || p->xCmp );
dvander@1203
   109
  return p;
dvander@1203
   110
}
dvander@1203
   111
dvander@1203
   112
/*
dvander@1203
   113
** This routine is called on a collation sequence before it is used to
dvander@1203
   114
** check that it is defined. An undefined collation sequence exists when
dvander@1203
   115
** a database is loaded that contains references to collation sequences
dvander@1203
   116
** that have not been defined by sqlite3_create_collation() etc.
dvander@1203
   117
**
dvander@1203
   118
** If required, this routine calls the 'collation needed' callback to
dvander@1203
   119
** request a definition of the collating sequence. If this doesn't work, 
dvander@1203
   120
** an equivalent collating sequence that uses a text encoding different
dvander@1203
   121
** from the main database is substituted, if one is available.
dvander@1203
   122
*/
dvander@1203
   123
int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){
dvander@1203
   124
  if( pColl ){
dvander@1203
   125
    const char *zName = pColl->zName;
dvander@1203
   126
    CollSeq *p = sqlite3GetCollSeq(pParse->db, pColl, zName, -1);
dvander@1203
   127
    if( !p ){
dvander@1203
   128
      if( pParse->nErr==0 ){
dvander@1203
   129
        sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
dvander@1203
   130
      }
dvander@1203
   131
      pParse->nErr++;
dvander@1203
   132
      return SQLITE_ERROR;
dvander@1203
   133
    }
dvander@1203
   134
    assert( p==pColl );
dvander@1203
   135
  }
dvander@1203
   136
  return SQLITE_OK;
dvander@1203
   137
}
dvander@1203
   138
dvander@1203
   139
dvander@1203
   140
dvander@1203
   141
/*
dvander@1203
   142
** Locate and return an entry from the db.aCollSeq hash table. If the entry
dvander@1203
   143
** specified by zName and nName is not found and parameter 'create' is
dvander@1203
   144
** true, then create a new entry. Otherwise return NULL.
dvander@1203
   145
**
dvander@1203
   146
** Each pointer stored in the sqlite3.aCollSeq hash table contains an
dvander@1203
   147
** array of three CollSeq structures. The first is the collation sequence
dvander@1203
   148
** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be.
dvander@1203
   149
**
dvander@1203
   150
** Stored immediately after the three collation sequences is a copy of
dvander@1203
   151
** the collation sequence name. A pointer to this string is stored in
dvander@1203
   152
** each collation sequence structure.
dvander@1203
   153
*/
dvander@1203
   154
static CollSeq *findCollSeqEntry(
dvander@1203
   155
  sqlite3 *db,
dvander@1203
   156
  const char *zName,
dvander@1203
   157
  int nName,
dvander@1203
   158
  int create
dvander@1203
   159
){
dvander@1203
   160
  CollSeq *pColl;
dvander@1203
   161
  if( nName<0 ) nName = strlen(zName);
dvander@1203
   162
  pColl = sqlite3HashFind(&db->aCollSeq, zName, nName);
dvander@1203
   163
dvander@1203
   164
  if( 0==pColl && create ){
dvander@1645
   165
    pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 );
dvander@1203
   166
    if( pColl ){
dvander@1203
   167
      CollSeq *pDel = 0;
dvander@1203
   168
      pColl[0].zName = (char*)&pColl[3];
dvander@1203
   169
      pColl[0].enc = SQLITE_UTF8;
dvander@1203
   170
      pColl[1].zName = (char*)&pColl[3];
dvander@1203
   171
      pColl[1].enc = SQLITE_UTF16LE;
dvander@1203
   172
      pColl[2].zName = (char*)&pColl[3];
dvander@1203
   173
      pColl[2].enc = SQLITE_UTF16BE;
dvander@1203
   174
      memcpy(pColl[0].zName, zName, nName);
dvander@1203
   175
      pColl[0].zName[nName] = 0;
dvander@1203
   176
      pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl);
dvander@1203
   177
dvander@1203
   178
      /* If a malloc() failure occured in sqlite3HashInsert(), it will 
dvander@1203
   179
      ** return the pColl pointer to be deleted (because it wasn't added
dvander@1203
   180
      ** to the hash table).
dvander@1203
   181
      */
dvander@1645
   182
      assert( pDel==0 || pDel==pColl );
dvander@1645
   183
      if( pDel!=0 ){
dvander@1645
   184
        db->mallocFailed = 1;
dvander@1645
   185
        sqlite3_free(pDel);
dvander@1203
   186
        pColl = 0;
dvander@1203
   187
      }
dvander@1203
   188
    }
dvander@1203
   189
  }
dvander@1203
   190
  return pColl;
dvander@1203
   191
}
dvander@1203
   192
dvander@1203
   193
/*
dvander@1203
   194
** Parameter zName points to a UTF-8 encoded string nName bytes long.
dvander@1203
   195
** Return the CollSeq* pointer for the collation sequence named zName
dvander@1203
   196
** for the encoding 'enc' from the database 'db'.
dvander@1203
   197
**
dvander@1203
   198
** If the entry specified is not found and 'create' is true, then create a
dvander@1203
   199
** new entry.  Otherwise return NULL.
dvander@1203
   200
**
dvander@1203
   201
** A separate function sqlite3LocateCollSeq() is a wrapper around
dvander@1203
   202
** this routine.  sqlite3LocateCollSeq() invokes the collation factory
dvander@1203
   203
** if necessary and generates an error message if the collating sequence
dvander@1203
   204
** cannot be found.
dvander@1203
   205
*/
dvander@1203
   206
CollSeq *sqlite3FindCollSeq(
dvander@1203
   207
  sqlite3 *db,
dvander@1203
   208
  u8 enc,
dvander@1203
   209
  const char *zName,
dvander@1203
   210
  int nName,
dvander@1203
   211
  int create
dvander@1203
   212
){
dvander@1203
   213
  CollSeq *pColl;
dvander@1203
   214
  if( zName ){
dvander@1203
   215
    pColl = findCollSeqEntry(db, zName, nName, create);
dvander@1203
   216
  }else{
dvander@1203
   217
    pColl = db->pDfltColl;
dvander@1203
   218
  }
dvander@1203
   219
  assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
dvander@1203
   220
  assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
dvander@1203
   221
  if( pColl ) pColl += enc-1;
dvander@1203
   222
  return pColl;
dvander@1203
   223
}
dvander@1203
   224
dvander@1203
   225
/*
dvander@1203
   226
** Locate a user function given a name, a number of arguments and a flag
dvander@1203
   227
** indicating whether the function prefers UTF-16 over UTF-8.  Return a
dvander@1203
   228
** pointer to the FuncDef structure that defines that function, or return
dvander@1203
   229
** NULL if the function does not exist.
dvander@1203
   230
**
dvander@1203
   231
** If the createFlag argument is true, then a new (blank) FuncDef
dvander@1203
   232
** structure is created and liked into the "db" structure if a
dvander@1203
   233
** no matching function previously existed.  When createFlag is true
dvander@1203
   234
** and the nArg parameter is -1, then only a function that accepts
dvander@1203
   235
** any number of arguments will be returned.
dvander@1203
   236
**
dvander@1203
   237
** If createFlag is false and nArg is -1, then the first valid
dvander@1203
   238
** function found is returned.  A function is valid if either xFunc
dvander@1203
   239
** or xStep is non-zero.
dvander@1203
   240
**
dvander@1203
   241
** If createFlag is false, then a function with the required name and
dvander@1203
   242
** number of arguments may be returned even if the eTextRep flag does not
dvander@1203
   243
** match that requested.
dvander@1203
   244
*/
dvander@1203
   245
FuncDef *sqlite3FindFunction(
dvander@1203
   246
  sqlite3 *db,       /* An open database */
dvander@1203
   247
  const char *zName, /* Name of the function.  Not null-terminated */
dvander@1203
   248
  int nName,         /* Number of characters in the name */
dvander@1203
   249
  int nArg,          /* Number of arguments.  -1 means any number */
dvander@1203
   250
  u8 enc,            /* Preferred text encoding */
dvander@1203
   251
  int createFlag     /* Create new entry if true and does not otherwise exist */
dvander@1203
   252
){
dvander@1203
   253
  FuncDef *p;         /* Iterator variable */
dvander@1203
   254
  FuncDef *pFirst;    /* First function with this name */
dvander@1203
   255
  FuncDef *pBest = 0; /* Best match found so far */
dvander@1203
   256
  int bestmatch = 0;  
dvander@1203
   257
dvander@1203
   258
dvander@1203
   259
  assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
dvander@1203
   260
  if( nArg<-1 ) nArg = -1;
dvander@1203
   261
dvander@1203
   262
  pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName);
dvander@1203
   263
  for(p=pFirst; p; p=p->pNext){
dvander@1203
   264
    /* During the search for the best function definition, bestmatch is set
dvander@1203
   265
    ** as follows to indicate the quality of the match with the definition
dvander@1203
   266
    ** pointed to by pBest:
dvander@1203
   267
    **
dvander@1203
   268
    ** 0: pBest is NULL. No match has been found.
dvander@1203
   269
    ** 1: A variable arguments function that prefers UTF-8 when a UTF-16
dvander@1203
   270
    **    encoding is requested, or vice versa.
dvander@1203
   271
    ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
dvander@1203
   272
    **    requested, or vice versa.
dvander@1203
   273
    ** 3: A variable arguments function using the same text encoding.
dvander@1203
   274
    ** 4: A function with the exact number of arguments requested that
dvander@1203
   275
    **    prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
dvander@1203
   276
    ** 5: A function with the exact number of arguments requested that
dvander@1203
   277
    **    prefers UTF-16LE when UTF-16BE is requested, or vice versa.
dvander@1203
   278
    ** 6: An exact match.
dvander@1203
   279
    **
dvander@1203
   280
    ** A larger value of 'matchqual' indicates a more desirable match.
dvander@1203
   281
    */
dvander@1203
   282
    if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
dvander@1203
   283
      int match = 1;          /* Quality of this match */
dvander@1203
   284
      if( p->nArg==nArg || nArg==-1 ){
dvander@1203
   285
        match = 4;
dvander@1203
   286
      }
dvander@1203
   287
      if( enc==p->iPrefEnc ){
dvander@1203
   288
        match += 2;
dvander@1203
   289
      }
dvander@1203
   290
      else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) ||
dvander@1203
   291
               (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){
dvander@1203
   292
        match += 1;
dvander@1203
   293
      }
dvander@1203
   294
dvander@1203
   295
      if( match>bestmatch ){
dvander@1203
   296
        pBest = p;
dvander@1203
   297
        bestmatch = match;
dvander@1203
   298
      }
dvander@1203
   299
    }
dvander@1203
   300
  }
dvander@1203
   301
dvander@1203
   302
  /* If the createFlag parameter is true, and the seach did not reveal an
dvander@1203
   303
  ** exact match for the name, number of arguments and encoding, then add a
dvander@1203
   304
  ** new entry to the hash table and return it.
dvander@1203
   305
  */
dvander@1203
   306
  if( createFlag && bestmatch<6 && 
dvander@1645
   307
      (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName))!=0 ){
dvander@1203
   308
    pBest->nArg = nArg;
dvander@1203
   309
    pBest->pNext = pFirst;
dvander@1203
   310
    pBest->iPrefEnc = enc;
dvander@1203
   311
    memcpy(pBest->zName, zName, nName);
dvander@1203
   312
    pBest->zName[nName] = 0;
dvander@1203
   313
    if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){
dvander@1645
   314
      db->mallocFailed = 1;
dvander@1645
   315
      sqlite3_free(pBest);
dvander@1203
   316
      return 0;
dvander@1203
   317
    }
dvander@1203
   318
  }
dvander@1203
   319
dvander@1203
   320
  if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){
dvander@1203
   321
    return pBest;
dvander@1203
   322
  }
dvander@1203
   323
  return 0;
dvander@1203
   324
}
dvander@1203
   325
dvander@1203
   326
/*
dvander@1203
   327
** Free all resources held by the schema structure. The void* argument points
dvander@1645
   328
** at a Schema struct. This function does not call sqlite3_free() on the 
dvander@1203
   329
** pointer itself, it just cleans up subsiduary resources (i.e. the contents
dvander@1203
   330
** of the schema hash tables).
dvander@1203
   331
*/
dvander@1203
   332
void sqlite3SchemaFree(void *p){
dvander@1203
   333
  Hash temp1;
dvander@1203
   334
  Hash temp2;
dvander@1203
   335
  HashElem *pElem;
dvander@1203
   336
  Schema *pSchema = (Schema *)p;
dvander@1203
   337
dvander@1203
   338
  temp1 = pSchema->tblHash;
dvander@1203
   339
  temp2 = pSchema->trigHash;
dvander@1203
   340
  sqlite3HashInit(&pSchema->trigHash, SQLITE_HASH_STRING, 0);
dvander@1203
   341
  sqlite3HashClear(&pSchema->aFKey);
dvander@1203
   342
  sqlite3HashClear(&pSchema->idxHash);
dvander@1203
   343
  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
dvander@1203
   344
    sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem));
dvander@1203
   345
  }
dvander@1203
   346
  sqlite3HashClear(&temp2);
dvander@1203
   347
  sqlite3HashInit(&pSchema->tblHash, SQLITE_HASH_STRING, 0);
dvander@1203
   348
  for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
dvander@1203
   349
    Table *pTab = sqliteHashData(pElem);
dvander@1203
   350
    sqlite3DeleteTable(pTab);
dvander@1203
   351
  }
dvander@1203
   352
  sqlite3HashClear(&temp1);
dvander@1203
   353
  pSchema->pSeqTab = 0;
dvander@1203
   354
  pSchema->flags &= ~DB_SchemaLoaded;
dvander@1203
   355
}
dvander@1203
   356
dvander@1203
   357
/*
dvander@1203
   358
** Find and return the schema associated with a BTree.  Create
dvander@1203
   359
** a new one if necessary.
dvander@1203
   360
*/
dvander@1645
   361
Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
dvander@1203
   362
  Schema * p;
dvander@1203
   363
  if( pBt ){
dvander@1645
   364
    p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaFree);
dvander@1203
   365
  }else{
dvander@1645
   366
    p = (Schema *)sqlite3MallocZero(sizeof(Schema));
dvander@1203
   367
  }
dvander@1645
   368
  if( !p ){
dvander@1645
   369
    db->mallocFailed = 1;
dvander@1645
   370
  }else if ( 0==p->file_format ){
dvander@1203
   371
    sqlite3HashInit(&p->tblHash, SQLITE_HASH_STRING, 0);
dvander@1203
   372
    sqlite3HashInit(&p->idxHash, SQLITE_HASH_STRING, 0);
dvander@1203
   373
    sqlite3HashInit(&p->trigHash, SQLITE_HASH_STRING, 0);
dvander@1203
   374
    sqlite3HashInit(&p->aFKey, SQLITE_HASH_STRING, 1);
dvander@1203
   375
    p->enc = SQLITE_UTF8;
dvander@1203
   376
  }
dvander@1203
   377
  return p;
dvander@1203
   378
}