/ Check-in [dbd11a0c]
Login

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

Overview
Comment:Move the special built-in SQL functions used by ALTER TABLE out of func.c and into alter.c. (CVS 2343)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: dbd11a0c581b447bb2f220a1a185d9fd36933ee3
User & Date: drh 2005-02-15 21:36:18
Context
2005-02-16
03:27
Get vacuum working on database that used to have autoincrement tables but where all such tables have been dropped. Ticket #1121. (CVS 2344) check-in: 8f7c639d user: drh tags: trunk
2005-02-15
21:36
Move the special built-in SQL functions used by ALTER TABLE out of func.c and into alter.c. (CVS 2343) check-in: dbd11a0c user: drh tags: trunk
20:47
Split the logic for the ALTER TABLE command off into a separate source code file. (CVS 2342) check-in: 90d6573c user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/alter.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that used to generate VDBE code
    13     13   ** that implements the ALTER TABLE command.
    14     14   **
    15         -** $Id: alter.c,v 1.1 2005/02/15 20:47:57 drh Exp $
           15  +** $Id: alter.c,v 1.2 2005/02/15 21:36:18 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19         -
           19  +/*
           20  +** The code in this file only exists if we are not omitting the
           21  +** ALTER TABLE logic from the build.
           22  +*/
    20     23   #ifndef SQLITE_OMIT_ALTERTABLE
           24  +
           25  +
           26  +/*
           27  +** This function is used by SQL generated to implement the 
           28  +** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
           29  +** CREATE INDEX command. The second is a table name. The table name in 
           30  +** the CREATE TABLE or CREATE INDEX statement is replaced with the second
           31  +** argument and the result returned. Examples:
           32  +**
           33  +** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
           34  +**     -> 'CREATE TABLE def(a, b, c)'
           35  +**
           36  +** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def')
           37  +**     -> 'CREATE INDEX i ON def(a, b, c)'
           38  +*/
           39  +static void renameTableFunc(
           40  +  sqlite3_context *context,
           41  +  int argc,
           42  +  sqlite3_value **argv
           43  +){
           44  +  unsigned char const *zSql = sqlite3_value_text(argv[0]);
           45  +  unsigned char const *zTableName = sqlite3_value_text(argv[1]);
           46  +
           47  +  int token;
           48  +  Token tname;
           49  +  char const *zCsr = zSql;
           50  +  int len = 0;
           51  +  char *zRet;
           52  +
           53  +  /* The principle used to locate the table name in the CREATE TABLE 
           54  +  ** statement is that the table name is the first token that is immediatedly
           55  +  ** followed by a left parenthesis - TK_LP.
           56  +  */
           57  +  if( zSql ){
           58  +    do {
           59  +      /* Store the token that zCsr points to in tname. */
           60  +      tname.z = zCsr;
           61  +      tname.n = len;
           62  +
           63  +      /* Advance zCsr to the next token. Store that token type in 'token',
           64  +      ** and it's length in 'len' (to be used next iteration of this loop).
           65  +      */
           66  +      do {
           67  +        zCsr += len;
           68  +        len = sqlite3GetToken(zCsr, &token);
           69  +      } while( token==TK_SPACE );
           70  +      assert( len>0 );
           71  +    } while( token!=TK_LP );
           72  +
           73  +    zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql, 
           74  +       zTableName, tname.z+tname.n);
           75  +    sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
           76  +  }
           77  +}
           78  +
           79  +#ifndef SQLITE_OMIT_TRIGGER
           80  +/* This function is used by SQL generated to implement the ALTER TABLE
           81  +** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER 
           82  +** statement. The second is a table name. The table name in the CREATE 
           83  +** TRIGGER statement is replaced with the second argument and the result 
           84  +** returned. This is analagous to renameTableFunc() above, except for CREATE
           85  +** TRIGGER, not CREATE INDEX and CREATE TABLE.
           86  +*/
           87  +static void renameTriggerFunc(
           88  +  sqlite3_context *context,
           89  +  int argc,
           90  +  sqlite3_value **argv
           91  +){
           92  +  unsigned char const *zSql = sqlite3_value_text(argv[0]);
           93  +  unsigned char const *zTableName = sqlite3_value_text(argv[1]);
           94  +
           95  +  int token;
           96  +  Token tname;
           97  +  int dist = 3;
           98  +  char const *zCsr = zSql;
           99  +  int len = 0;
          100  +  char *zRet;
          101  +
          102  +  /* The principle used to locate the table name in the CREATE TRIGGER 
          103  +  ** statement is that the table name is the first token that is immediatedly
          104  +  ** preceded by either TK_ON or TK_DOT and immediatedly followed by one
          105  +  ** of TK_WHEN, TK_BEGIN or TK_FOR.
          106  +  */
          107  +  if( zSql ){
          108  +    do {
          109  +      /* Store the token that zCsr points to in tname. */
          110  +      tname.z = zCsr;
          111  +      tname.n = len;
          112  +
          113  +      /* Advance zCsr to the next token. Store that token type in 'token',
          114  +      ** and it's length in 'len' (to be used next iteration of this loop).
          115  +      */
          116  +      do {
          117  +        zCsr += len;
          118  +        len = sqlite3GetToken(zCsr, &token);
          119  +      }while( token==TK_SPACE );
          120  +      assert( len>0 );
          121  +
          122  +      /* Variable 'dist' stores the number of tokens read since the most
          123  +      ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN 
          124  +      ** token is read and 'dist' equals 2, the condition stated above
          125  +      ** to be met.
          126  +      **
          127  +      ** Note that ON cannot be a database, table or column name, so
          128  +      ** there is no need to worry about syntax like 
          129  +      ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
          130  +      */
          131  +      dist++;
          132  +      if( token==TK_DOT || token==TK_ON ){
          133  +        dist = 0;
          134  +      }
          135  +    } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) );
          136  +
          137  +    /* Variable tname now contains the token that is the old table-name
          138  +    ** in the CREATE TRIGGER statement.
          139  +    */
          140  +    zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql, 
          141  +       zTableName, tname.z+tname.n);
          142  +    sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
          143  +  }
          144  +}
          145  +#endif   /* !SQLITE_OMIT_TRIGGER */
          146  +
          147  +/*
          148  +** Register built-in functions used to help implement ALTER TABLE
          149  +*/
          150  +void sqlite3AlterFunctions(sqlite3 *db){
          151  +  static const struct {
          152  +     char *zName;
          153  +     signed char nArg;
          154  +     void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
          155  +  } aFuncs[] = {
          156  +    { "sqlite_rename_table",    2, renameTableFunc},
          157  +#ifndef SQLITE_OMIT_TRIGGER
          158  +    { "sqlite_rename_trigger",  2, renameTriggerFunc},
          159  +#endif
          160  +  };
          161  +  int i;
          162  +
          163  +  for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
          164  +    sqlite3_create_function(db, aFuncs[i].zName, aFuncs[i].nArg,
          165  +        SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
          166  +  }
          167  +}
          168  +
    21    169   /*
    22    170   ** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy" 
    23    171   ** command. 
    24    172   */
    25    173   void sqlite3AlterRenameTable(
    26    174     Parse *pParse,            /* Parser context. */
    27    175     SrcList *pSrc,            /* The table to rename. */

Changes to src/func.c.

    12     12   ** This file contains the C functions that implement various SQL
    13     13   ** functions of SQLite.  
    14     14   **
    15     15   ** There is only one exported symbol in this file - the function
    16     16   ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
    17     17   ** All other code has file scope.
    18     18   **
    19         -** $Id: func.c,v 1.95 2005/02/15 20:47:57 drh Exp $
           19  +** $Id: func.c,v 1.96 2005/02/15 21:36:18 drh Exp $
    20     20   */
    21     21   #include "sqliteInt.h"
    22     22   #include <ctype.h>
    23     23   #include <math.h>
    24     24   #include <stdlib.h>
    25     25   #include <assert.h>
    26     26   #include "vdbeInt.h"
................................................................................
   529    529     sqlite3_context *context,
   530    530     int argc,
   531    531     sqlite3_value **argv
   532    532   ){
   533    533     sqlite3_result_text(context, sqlite3_version, -1, SQLITE_STATIC);
   534    534   }
   535    535   
   536         -#ifndef SQLITE_OMIT_ALTERTABLE
   537         -/*
   538         -** This function is used by SQL generated to implement the 
   539         -** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
   540         -** CREATE INDEX command. The second is a table name. The table name in 
   541         -** the CREATE TABLE or CREATE INDEX statement is replaced with the second
   542         -** argument and the result returned. Examples:
   543         -**
   544         -** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
   545         -**     -> 'CREATE TABLE def(a, b, c)'
   546         -**
   547         -** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def')
   548         -**     -> 'CREATE INDEX i ON def(a, b, c)'
   549         -*/
   550         -static void renameTableFunc(
   551         -  sqlite3_context *context,
   552         -  int argc,
   553         -  sqlite3_value **argv
   554         -){
   555         -  unsigned char const *zSql = sqlite3_value_text(argv[0]);
   556         -  unsigned char const *zTableName = sqlite3_value_text(argv[1]);
   557         -
   558         -  int token;
   559         -  Token tname;
   560         -  char const *zCsr = zSql;
   561         -  int len = 0;
   562         -  char *zRet;
   563         -
   564         -  /* The principle used to locate the table name in the CREATE TABLE 
   565         -  ** statement is that the table name is the first token that is immediatedly
   566         -  ** followed by a left parenthesis - TK_LP.
   567         -  */
   568         -  if( zSql ){
   569         -    do {
   570         -      /* Store the token that zCsr points to in tname. */
   571         -      tname.z = zCsr;
   572         -      tname.n = len;
   573         -
   574         -      /* Advance zCsr to the next token. Store that token type in 'token',
   575         -      ** and it's length in 'len' (to be used next iteration of this loop).
   576         -      */
   577         -      do {
   578         -        zCsr += len;
   579         -        len = sqlite3GetToken(zCsr, &token);
   580         -      } while( token==TK_SPACE );
   581         -      assert( len>0 );
   582         -    } while( token!=TK_LP );
   583         -
   584         -    zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql, 
   585         -       zTableName, tname.z+tname.n);
   586         -    sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
   587         -  }
   588         -}
   589         -#endif
   590         -
   591         -#ifndef SQLITE_OMIT_ALTERTABLE
   592         -#ifndef SQLITE_OMIT_TRIGGER
   593         -/* This function is used by SQL generated to implement the ALTER TABLE
   594         -** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER 
   595         -** statement. The second is a table name. The table name in the CREATE 
   596         -** TRIGGER statement is replaced with the second argument and the result 
   597         -** returned. This is analagous to renameTableFunc() above, except for CREATE
   598         -** TRIGGER, not CREATE INDEX and CREATE TABLE.
   599         -*/
   600         -static void renameTriggerFunc(
   601         -  sqlite3_context *context,
   602         -  int argc,
   603         -  sqlite3_value **argv
   604         -){
   605         -  unsigned char const *zSql = sqlite3_value_text(argv[0]);
   606         -  unsigned char const *zTableName = sqlite3_value_text(argv[1]);
   607         -
   608         -  int token;
   609         -  Token tname;
   610         -  int dist = 3;
   611         -  char const *zCsr = zSql;
   612         -  int len = 0;
   613         -  char *zRet;
   614         -
   615         -  /* The principle used to locate the table name in the CREATE TRIGGER 
   616         -  ** statement is that the table name is the first token that is immediatedly
   617         -  ** preceded by either TK_ON or TK_DOT and immediatedly followed by one
   618         -  ** of TK_WHEN, TK_BEGIN or TK_FOR.
   619         -  */
   620         -  if( zSql ){
   621         -    do {
   622         -      /* Store the token that zCsr points to in tname. */
   623         -      tname.z = zCsr;
   624         -      tname.n = len;
   625         -
   626         -      /* Advance zCsr to the next token. Store that token type in 'token',
   627         -      ** and it's length in 'len' (to be used next iteration of this loop).
   628         -      */
   629         -      do {
   630         -        zCsr += len;
   631         -        len = sqlite3GetToken(zCsr, &token);
   632         -      }while( token==TK_SPACE );
   633         -      assert( len>0 );
   634         -
   635         -      /* Variable 'dist' stores the number of tokens read since the most
   636         -      ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN 
   637         -      ** token is read and 'dist' equals 2, the condition stated above
   638         -      ** to be met.
   639         -      **
   640         -      ** Note that ON cannot be a database, table or column name, so
   641         -      ** there is no need to worry about syntax like 
   642         -      ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
   643         -      */
   644         -      dist++;
   645         -      if( token==TK_DOT || token==TK_ON ){
   646         -        dist = 0;
   647         -      }
   648         -    } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) );
   649         -
   650         -    /* Variable tname now contains the token that is the old table-name
   651         -    ** in the CREATE TRIGGER statement.
   652         -    */
   653         -    zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql, 
   654         -       zTableName, tname.z+tname.n);
   655         -    sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
   656         -  }
   657         -}
   658         -#endif   /* !SQLITE_OMIT_TRIGGER */
   659         -#endif   /* !SQLITE_OMIT_ALTERTABLE */
   660    536   
   661    537   /*
   662    538   ** EXPERIMENTAL - This is not an official function.  The interface may
   663    539   ** change.  This function may disappear.  Do not write code that depends
   664    540   ** on this function.
   665    541   **
   666    542   ** Implementation of the QUOTE() function.  This function takes a single
................................................................................
   971    847   typedef struct StdDevCtx StdDevCtx;
   972    848   struct StdDevCtx {
   973    849     double sum;     /* Sum of terms */
   974    850     double sum2;    /* Sum of the squares of terms */
   975    851     int cnt;        /* Number of terms counted */
   976    852   };
   977    853   
   978         -#if 0   /* Omit because math library is required */
   979         -/*
   980         -** Routines used to compute the standard deviation as an aggregate.
   981         -*/
   982         -static void stdDevStep(sqlite3_context *context, int argc, const char **argv){
   983         -  StdDevCtx *p;
   984         -  double x;
   985         -  if( argc<1 ) return;
   986         -  p = sqlite3_aggregate_context(context, sizeof(*p));
   987         -  if( p && argv[0] ){
   988         -    x = sqlite3AtoF(argv[0], 0);
   989         -    p->sum += x;
   990         -    p->sum2 += x*x;
   991         -    p->cnt++;
   992         -  }
   993         -}
   994         -static void stdDevFinalize(sqlite3_context *context){
   995         -  double rN = sqlite3_aggregate_count(context);
   996         -  StdDevCtx *p = sqlite3_aggregate_context(context, sizeof(*p));
   997         -  if( p && p->cnt>1 ){
   998         -    double rCnt = cnt;
   999         -    sqlite3_set_result_double(context, 
  1000         -       sqrt((p->sum2 - p->sum*p->sum/rCnt)/(rCnt-1.0)));
  1001         -  }
  1002         -}
  1003         -#endif
  1004         -
  1005    854   /*
  1006    855   ** The following structure keeps track of state information for the
  1007    856   ** count() aggregate function.
  1008    857   */
  1009    858   typedef struct CountCtx CountCtx;
  1010    859   struct CountCtx {
  1011    860     int n;
................................................................................
  1118    967       { "glob",               2, 0, SQLITE_UTF8,    0, globFunc   },
  1119    968       { "nullif",             2, 0, SQLITE_UTF8,    1, nullifFunc },
  1120    969       { "sqlite_version",     0, 0, SQLITE_UTF8,    0, versionFunc},
  1121    970       { "quote",              1, 0, SQLITE_UTF8,    0, quoteFunc  },
  1122    971       { "last_insert_rowid",  0, 1, SQLITE_UTF8,    0, last_insert_rowid },
  1123    972       { "changes",            0, 1, SQLITE_UTF8,    0, changes    },
  1124    973       { "total_changes",      0, 1, SQLITE_UTF8,    0, total_changes },
  1125         -#ifndef SQLITE_OMIT_ALTERTABLE
  1126         -    { "sqlite_rename_table",  2, 0, SQLITE_UTF8,  0, renameTableFunc},
  1127         -#ifndef SQLITE_OMIT_TRIGGER
  1128         -    { "sqlite_rename_trigger",2, 0, SQLITE_UTF8,  0, renameTriggerFunc},
  1129         -#endif
  1130         -#endif
  1131    974   #ifdef SQLITE_SOUNDEX
  1132    975       { "soundex",            1, 0, SQLITE_UTF8, 0, soundexFunc},
  1133    976   #endif
  1134    977   #ifdef SQLITE_TEST
  1135    978       { "randstr",               2, 0, SQLITE_UTF8, 0, randStr    },
  1136    979       { "test_destructor",       1, 1, SQLITE_UTF8, 0, test_destructor},
  1137    980       { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count},
................................................................................
  1149    992     } aAggs[] = {
  1150    993       { "min",    1, 0, 1, minmaxStep,   minMaxFinalize },
  1151    994       { "max",    1, 2, 1, minmaxStep,   minMaxFinalize },
  1152    995       { "sum",    1, 0, 0, sumStep,      sumFinalize    },
  1153    996       { "avg",    1, 0, 0, sumStep,      avgFinalize    },
  1154    997       { "count",  0, 0, 0, countStep,    countFinalize  },
  1155    998       { "count",  1, 0, 0, countStep,    countFinalize  },
  1156         -#if 0
  1157         -    { "stddev", 1, 0, stdDevStep,   stdDevFinalize },
  1158         -#endif
  1159    999     };
  1160   1000     int i;
  1161   1001   
  1162   1002     for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
  1163   1003       void *pArg = 0;
  1164   1004       switch( aFuncs[i].argType ){
  1165   1005         case 1: pArg = db; break;
................................................................................
  1171   1011         FuncDef *pFunc = sqlite3FindFunction(db, aFuncs[i].zName, 
  1172   1012             strlen(aFuncs[i].zName), aFuncs[i].nArg, aFuncs[i].eTextRep, 0);
  1173   1013         if( pFunc && aFuncs[i].needCollSeq ){
  1174   1014           pFunc->needCollSeq = 1;
  1175   1015         }
  1176   1016       }
  1177   1017     }
         1018  +#ifndef SQLITE_OMIT_ALTERTABLE
         1019  +  sqlite3AlterFunctions(db);
         1020  +#endif
  1178   1021     for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
  1179   1022       void *pArg = 0;
  1180   1023       switch( aAggs[i].argType ){
  1181   1024         case 1: pArg = db; break;
  1182   1025         case 2: pArg = (void *)(-1); break;
  1183   1026       }
  1184   1027       sqlite3_create_function(db, aAggs[i].zName, aAggs[i].nArg, SQLITE_UTF8, 

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.370 2005/02/09 01:40:25 danielk1977 Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.371 2005/02/15 21:36:18 drh Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   
    19     19   /*
    20     20   ** These #defines should enable >2GB file support on Posix if the
    21     21   ** underlying operating system supports it.  If the OS lacks
................................................................................
  1535   1535   void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*));
  1536   1536   void sqlite3ValueFree(sqlite3_value*);
  1537   1537   sqlite3_value *sqlite3ValueNew();
  1538   1538   sqlite3_value *sqlite3GetTransientValue(sqlite3*db);
  1539   1539   extern const unsigned char sqlite3UpperToLower[];
  1540   1540   void sqlite3RootPageMoved(Db*, int, int);
  1541   1541   void sqlite3Reindex(Parse*, Token*, Token*);
         1542  +void sqlite3AlterFunctions(sqlite3*);
  1542   1543   void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
  1543   1544   int sqlite3GetToken(const unsigned char *, int *);
  1544   1545   void sqlite3NestedParse(Parse*, const char*, ...);
  1545   1546   void sqlite3ExpirePreparedStatements(sqlite3*);
  1546   1547   void sqlite3CodeSubselect(Parse *, Expr *);
  1547   1548   int sqlite3SelectResolve(Parse *, Select *, NameContext *);
  1548   1549   
  1549   1550   #endif