|
From: <cre...@us...> - 2006-10-12 23:33:07
|
Revision: 1554
http://svn.sourceforge.net/frontierkernel/?rev=1554&view=rev
Author: creecode
Date: 2006-10-12 16:32:33 -0700 (Thu, 12 Oct 2006)
Log Message:
-----------
ported r1393:1553 (sqlite) from trunk. part 1
Added Paths:
-----------
Frontier/branches/FSRef_Migration/Common/sqlite3/
Frontier/branches/FSRef_Migration/Common/sqlite3/alter.c
Frontier/branches/FSRef_Migration/Common/sqlite3/analyze.c
Frontier/branches/FSRef_Migration/Common/sqlite3/attach.c
Frontier/branches/FSRef_Migration/Common/sqlite3/auth.c
Frontier/branches/FSRef_Migration/Common/sqlite3/btree.c
Frontier/branches/FSRef_Migration/Common/sqlite3/btree.h
Frontier/branches/FSRef_Migration/Common/sqlite3/build.c
Frontier/branches/FSRef_Migration/Common/sqlite3/callback.c
Frontier/branches/FSRef_Migration/Common/sqlite3/complete.c
Frontier/branches/FSRef_Migration/Common/sqlite3/date.c
Frontier/branches/FSRef_Migration/Common/sqlite3/delete.c
Frontier/branches/FSRef_Migration/Common/sqlite3/expr.c
Frontier/branches/FSRef_Migration/Common/sqlite3/func.c
Frontier/branches/FSRef_Migration/Common/sqlite3/hash.c
Frontier/branches/FSRef_Migration/Common/sqlite3/hash.h
Frontier/branches/FSRef_Migration/Common/sqlite3/insert.c
Frontier/branches/FSRef_Migration/Common/sqlite3/keywordhash.h
Frontier/branches/FSRef_Migration/Common/sqlite3/legacy.c
Frontier/branches/FSRef_Migration/Common/sqlite3/loadext.c
Frontier/branches/FSRef_Migration/Common/sqlite3/main.c
Frontier/branches/FSRef_Migration/Common/sqlite3/opcodes.c
Frontier/branches/FSRef_Migration/Common/sqlite3/opcodes.h
Frontier/branches/FSRef_Migration/Common/sqlite3/os.c
Frontier/branches/FSRef_Migration/Common/sqlite3/os.h
Frontier/branches/FSRef_Migration/Common/sqlite3/os_common.h
Frontier/branches/FSRef_Migration/Common/sqlite3/os_os2.c
Frontier/branches/FSRef_Migration/Common/sqlite3/os_unix.c
Frontier/branches/FSRef_Migration/Common/sqlite3/os_win.c
Frontier/branches/FSRef_Migration/Common/sqlite3/pager.c
Frontier/branches/FSRef_Migration/Common/sqlite3/pager.h
Frontier/branches/FSRef_Migration/Common/sqlite3/parse.c
Frontier/branches/FSRef_Migration/Common/sqlite3/parse.h
Frontier/branches/FSRef_Migration/Common/sqlite3/pragma.c
Frontier/branches/FSRef_Migration/Common/sqlite3/prepare.c
Frontier/branches/FSRef_Migration/Common/sqlite3/printf.c
Frontier/branches/FSRef_Migration/Common/sqlite3/random.c
Frontier/branches/FSRef_Migration/Common/sqlite3/select.c
Frontier/branches/FSRef_Migration/Common/sqlite3/shell.c
Frontier/branches/FSRef_Migration/Common/sqlite3/sqlite3.def
Frontier/branches/FSRef_Migration/Common/sqlite3/sqlite3.h
Frontier/branches/FSRef_Migration/Common/sqlite3/sqlite3ext.h
Frontier/branches/FSRef_Migration/Common/sqlite3/sqliteInt.h
Frontier/branches/FSRef_Migration/Common/sqlite3/table.c
Frontier/branches/FSRef_Migration/Common/sqlite3/tclsqlite.c
Frontier/branches/FSRef_Migration/Common/sqlite3/tokenize.c
Frontier/branches/FSRef_Migration/Common/sqlite3/trigger.c
Frontier/branches/FSRef_Migration/Common/sqlite3/update.c
Frontier/branches/FSRef_Migration/Common/sqlite3/utf.c
Frontier/branches/FSRef_Migration/Common/sqlite3/util.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vacuum.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbe.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbe.h
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbeInt.h
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbeapi.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbeaux.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbefifo.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbemem.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vtab.c
Frontier/branches/FSRef_Migration/Common/sqlite3/where.c
Removed Paths:
-------------
Frontier/branches/FSRef_Migration/Common/sqlite3/alter.c
Frontier/branches/FSRef_Migration/Common/sqlite3/analyze.c
Frontier/branches/FSRef_Migration/Common/sqlite3/attach.c
Frontier/branches/FSRef_Migration/Common/sqlite3/auth.c
Frontier/branches/FSRef_Migration/Common/sqlite3/btree.c
Frontier/branches/FSRef_Migration/Common/sqlite3/btree.h
Frontier/branches/FSRef_Migration/Common/sqlite3/build.c
Frontier/branches/FSRef_Migration/Common/sqlite3/callback.c
Frontier/branches/FSRef_Migration/Common/sqlite3/complete.c
Frontier/branches/FSRef_Migration/Common/sqlite3/date.c
Frontier/branches/FSRef_Migration/Common/sqlite3/delete.c
Frontier/branches/FSRef_Migration/Common/sqlite3/expr.c
Frontier/branches/FSRef_Migration/Common/sqlite3/func.c
Frontier/branches/FSRef_Migration/Common/sqlite3/hash.c
Frontier/branches/FSRef_Migration/Common/sqlite3/hash.h
Frontier/branches/FSRef_Migration/Common/sqlite3/insert.c
Frontier/branches/FSRef_Migration/Common/sqlite3/keywordhash.h
Frontier/branches/FSRef_Migration/Common/sqlite3/legacy.c
Frontier/branches/FSRef_Migration/Common/sqlite3/loadext.c
Frontier/branches/FSRef_Migration/Common/sqlite3/main.c
Frontier/branches/FSRef_Migration/Common/sqlite3/opcodes.c
Frontier/branches/FSRef_Migration/Common/sqlite3/opcodes.h
Frontier/branches/FSRef_Migration/Common/sqlite3/os.c
Frontier/branches/FSRef_Migration/Common/sqlite3/os.h
Frontier/branches/FSRef_Migration/Common/sqlite3/os_common.h
Frontier/branches/FSRef_Migration/Common/sqlite3/os_os2.c
Frontier/branches/FSRef_Migration/Common/sqlite3/os_unix.c
Frontier/branches/FSRef_Migration/Common/sqlite3/os_win.c
Frontier/branches/FSRef_Migration/Common/sqlite3/pager.c
Frontier/branches/FSRef_Migration/Common/sqlite3/pager.h
Frontier/branches/FSRef_Migration/Common/sqlite3/parse.c
Frontier/branches/FSRef_Migration/Common/sqlite3/parse.h
Frontier/branches/FSRef_Migration/Common/sqlite3/pragma.c
Frontier/branches/FSRef_Migration/Common/sqlite3/prepare.c
Frontier/branches/FSRef_Migration/Common/sqlite3/printf.c
Frontier/branches/FSRef_Migration/Common/sqlite3/random.c
Frontier/branches/FSRef_Migration/Common/sqlite3/select.c
Frontier/branches/FSRef_Migration/Common/sqlite3/shell.c
Frontier/branches/FSRef_Migration/Common/sqlite3/sqlite3.def
Frontier/branches/FSRef_Migration/Common/sqlite3/sqlite3.h
Frontier/branches/FSRef_Migration/Common/sqlite3/sqlite3ext.h
Frontier/branches/FSRef_Migration/Common/sqlite3/sqliteInt.h
Frontier/branches/FSRef_Migration/Common/sqlite3/table.c
Frontier/branches/FSRef_Migration/Common/sqlite3/tclsqlite.c
Frontier/branches/FSRef_Migration/Common/sqlite3/tokenize.c
Frontier/branches/FSRef_Migration/Common/sqlite3/trigger.c
Frontier/branches/FSRef_Migration/Common/sqlite3/update.c
Frontier/branches/FSRef_Migration/Common/sqlite3/utf.c
Frontier/branches/FSRef_Migration/Common/sqlite3/util.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vacuum.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbe.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbe.h
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbeInt.h
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbeapi.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbeaux.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbefifo.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vdbemem.c
Frontier/branches/FSRef_Migration/Common/sqlite3/vtab.c
Frontier/branches/FSRef_Migration/Common/sqlite3/where.c
Copied: Frontier/branches/FSRef_Migration/Common/sqlite3 (from rev 1553, Frontier/trunk/Common/sqlite3)
Deleted: Frontier/branches/FSRef_Migration/Common/sqlite3/alter.c
===================================================================
--- Frontier/trunk/Common/sqlite3/alter.c 2006-10-12 19:32:40 UTC (rev 1553)
+++ Frontier/branches/FSRef_Migration/Common/sqlite3/alter.c 2006-10-12 23:32:33 UTC (rev 1554)
@@ -1,575 +0,0 @@
-/*
-** 2005 February 15
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains C code routines that used to generate VDBE code
-** that implements the ALTER TABLE command.
-**
-** $Id: alter.c,v 1.21 2006/06/21 12:36:25 danielk1977 Exp $
-*/
-#include "sqliteInt.h"
-#include <ctype.h>
-
-/*
-** The code in this file only exists if we are not omitting the
-** ALTER TABLE logic from the build.
-*/
-#ifndef SQLITE_OMIT_ALTERTABLE
-
-
-/*
-** This function is used by SQL generated to implement the
-** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
-** CREATE INDEX command. The second is a table name. The table name in
-** the CREATE TABLE or CREATE INDEX statement is replaced with the second
-** argument and the result returned. Examples:
-**
-** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
-** -> 'CREATE TABLE def(a, b, c)'
-**
-** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def')
-** -> 'CREATE INDEX i ON def(a, b, c)'
-*/
-static void renameTableFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- unsigned char const *zSql = sqlite3_value_text(argv[0]);
- unsigned char const *zTableName = sqlite3_value_text(argv[1]);
-
- int token;
- Token tname;
- unsigned char const *zCsr = zSql;
- int len = 0;
- char *zRet;
-
- /* The principle used to locate the table name in the CREATE TABLE
- ** statement is that the table name is the first token that is immediatedly
- ** followed by a left parenthesis - TK_LP.
- */
- if( zSql ){
- do {
- /* Store the token that zCsr points to in tname. */
- tname.z = zCsr;
- tname.n = len;
-
- /* Advance zCsr to the next token. Store that token type in 'token',
- ** and it's length in 'len' (to be used next iteration of this loop).
- */
- do {
- zCsr += len;
- len = sqlite3GetToken(zCsr, &token);
- } while( token==TK_SPACE );
- assert( len>0 );
- } while( token!=TK_LP );
-
- zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql,
- zTableName, tname.z+tname.n);
- sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
- }
-}
-
-#ifndef SQLITE_OMIT_TRIGGER
-/* This function is used by SQL generated to implement the ALTER TABLE
-** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
-** statement. The second is a table name. The table name in the CREATE
-** TRIGGER statement is replaced with the second argument and the result
-** returned. This is analagous to renameTableFunc() above, except for CREATE
-** TRIGGER, not CREATE INDEX and CREATE TABLE.
-*/
-static void renameTriggerFunc(
- sqlite3_context *context,
- int argc,
- sqlite3_value **argv
-){
- unsigned char const *zSql = sqlite3_value_text(argv[0]);
- unsigned char const *zTableName = sqlite3_value_text(argv[1]);
-
- int token;
- Token tname;
- int dist = 3;
- unsigned char const *zCsr = zSql;
- int len = 0;
- char *zRet;
-
- /* The principle used to locate the table name in the CREATE TRIGGER
- ** statement is that the table name is the first token that is immediatedly
- ** preceded by either TK_ON or TK_DOT and immediatedly followed by one
- ** of TK_WHEN, TK_BEGIN or TK_FOR.
- */
- if( zSql ){
- do {
- /* Store the token that zCsr points to in tname. */
- tname.z = zCsr;
- tname.n = len;
-
- /* Advance zCsr to the next token. Store that token type in 'token',
- ** and it's length in 'len' (to be used next iteration of this loop).
- */
- do {
- zCsr += len;
- len = sqlite3GetToken(zCsr, &token);
- }while( token==TK_SPACE );
- assert( len>0 );
-
- /* Variable 'dist' stores the number of tokens read since the most
- ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN
- ** token is read and 'dist' equals 2, the condition stated above
- ** to be met.
- **
- ** Note that ON cannot be a database, table or column name, so
- ** there is no need to worry about syntax like
- ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
- */
- dist++;
- if( token==TK_DOT || token==TK_ON ){
- dist = 0;
- }
- } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) );
-
- /* Variable tname now contains the token that is the old table-name
- ** in the CREATE TRIGGER statement.
- */
- zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql,
- zTableName, tname.z+tname.n);
- sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
- }
-}
-#endif /* !SQLITE_OMIT_TRIGGER */
-
-/*
-** Register built-in functions used to help implement ALTER TABLE
-*/
-void sqlite3AlterFunctions(sqlite3 *db){
- static const struct {
- char *zName;
- signed char nArg;
- void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
- } aFuncs[] = {
- { "sqlite_rename_table", 2, renameTableFunc},
-#ifndef SQLITE_OMIT_TRIGGER
- { "sqlite_rename_trigger", 2, renameTriggerFunc},
-#endif
- };
- int i;
-
- for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
- sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
- SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
- }
-}
-
-/*
-** Generate the text of a WHERE expression which can be used to select all
-** temporary triggers on table pTab from the sqlite_temp_master table. If
-** table pTab has no temporary triggers, or is itself stored in the
-** temporary database, NULL is returned.
-*/
-static char *whereTempTriggers(Parse *pParse, Table *pTab){
- Trigger *pTrig;
- char *zWhere = 0;
- char *tmp = 0;
- const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */
-
- /* If the table is not located in the temp-db (in which case NULL is
- ** returned, loop through the tables list of triggers. For each trigger
- ** that is not part of the temp-db schema, add a clause to the WHERE
- ** expression being built up in zWhere.
- */
- if( pTab->pSchema!=pTempSchema ){
- for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){
- if( pTrig->pSchema==pTempSchema ){
- if( !zWhere ){
- zWhere = sqlite3MPrintf("name=%Q", pTrig->name);
- }else{
- tmp = zWhere;
- zWhere = sqlite3MPrintf("%s OR name=%Q", zWhere, pTrig->name);
- sqliteFree(tmp);
- }
- }
- }
- }
- return zWhere;
-}
-
-/*
-** Generate code to drop and reload the internal representation of table
-** pTab from the database, including triggers and temporary triggers.
-** Argument zName is the name of the table in the database schema at
-** the time the generated code is executed. This can be different from
-** pTab->zName if this function is being called to code part of an
-** "ALTER TABLE RENAME TO" statement.
-*/
-static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
- Vdbe *v;
- char *zWhere;
- int iDb; /* Index of database containing pTab */
-#ifndef SQLITE_OMIT_TRIGGER
- Trigger *pTrig;
-#endif
-
- v = sqlite3GetVdbe(pParse);
- if( !v ) return;
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- assert( iDb>=0 );
-
-#ifndef SQLITE_OMIT_TRIGGER
- /* Drop any table triggers from the internal schema. */
- for(pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext){
- int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
- assert( iTrigDb==iDb || iTrigDb==1 );
- sqlite3VdbeOp3(v, OP_DropTrigger, iTrigDb, 0, pTrig->name, 0);
- }
-#endif
-
- /* Drop the table and index from the internal schema */
- sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
-
- /* Reload the table, index and permanent trigger schemas. */
- zWhere = sqlite3MPrintf("tbl_name=%Q", zName);
- if( !zWhere ) return;
- sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
-
-#ifndef SQLITE_OMIT_TRIGGER
- /* Now, if the table is not stored in the temp database, reload any temp
- ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
- */
- if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
- sqlite3VdbeOp3(v, OP_ParseSchema, 1, 0, zWhere, P3_DYNAMIC);
- }
-#endif
-}
-
-/*
-** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
-** command.
-*/
-void sqlite3AlterRenameTable(
- Parse *pParse, /* Parser context. */
- SrcList *pSrc, /* The table to rename. */
- Token *pName /* The new table name. */
-){
- int iDb; /* Database that contains the table */
- char *zDb; /* Name of database iDb */
- Table *pTab; /* Table being renamed */
- char *zName = 0; /* NULL-terminated version of pName */
- sqlite3 *db = pParse->db; /* Database connection */
- Vdbe *v;
-#ifndef SQLITE_OMIT_TRIGGER
- char *zWhere = 0; /* Where clause to locate temp triggers */
-#endif
-
- if( sqlite3MallocFailed() ) goto exit_rename_table;
- assert( pSrc->nSrc==1 );
-
- pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
- if( !pTab ) goto exit_rename_table;
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pTab) ){
- sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
- goto exit_rename_table;
- }
-#endif
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- zDb = db->aDb[iDb].zName;
-
- /* Get a NULL terminated version of the new table name. */
- zName = sqlite3NameFromToken(pName);
- if( !zName ) goto exit_rename_table;
-
- /* Check that a table or index named 'zName' does not already exist
- ** in database iDb. If so, this is an error.
- */
- if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
- sqlite3ErrorMsg(pParse,
- "there is already another table or index with this name: %s", zName);
- goto exit_rename_table;
- }
-
- /* Make sure it is not a system table being altered, or a reserved name
- ** that the table is being renamed to.
- */
- if( strlen(pTab->zName)>6 && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ){
- sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
- goto exit_rename_table;
- }
- if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
- goto exit_rename_table;
- }
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
- /* Invoke the authorization callback. */
- if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
- goto exit_rename_table;
- }
-#endif
-
- /* Begin a transaction and code the VerifyCookie for database iDb.
- ** Then modify the schema cookie (since the ALTER TABLE modifies the
- ** schema).
- */
- v = sqlite3GetVdbe(pParse);
- if( v==0 ){
- goto exit_rename_table;
- }
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- sqlite3ChangeCookie(db, v, iDb);
-
- /* Modify the sqlite_master table to use the new table name. */
- sqlite3NestedParse(pParse,
- "UPDATE %Q.%s SET "
-#ifdef SQLITE_OMIT_TRIGGER
- "sql = sqlite_rename_table(sql, %Q), "
-#else
- "sql = CASE "
- "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)"
- "ELSE sqlite_rename_table(sql, %Q) END, "
-#endif
- "tbl_name = %Q, "
- "name = CASE "
- "WHEN type='table' THEN %Q "
- "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
- "'sqlite_autoindex_' || %Q || substr(name, %d+18,10) "
- "ELSE name END "
- "WHERE tbl_name=%Q AND "
- "(type='table' OR type='index' OR type='trigger');",
- zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
-#ifndef SQLITE_OMIT_TRIGGER
- zName,
-#endif
- zName, strlen(pTab->zName), pTab->zName
- );
-
-#ifndef SQLITE_OMIT_AUTOINCREMENT
- /* If the sqlite_sequence table exists in this database, then update
- ** it with the new table name.
- */
- if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
- sqlite3NestedParse(pParse,
- "UPDATE %Q.sqlite_sequence set name = %Q WHERE name = %Q",
- zDb, zName, pTab->zName);
- }
-#endif
-
-#ifndef SQLITE_OMIT_TRIGGER
- /* If there are TEMP triggers on this table, modify the sqlite_temp_master
- ** table. Don't do this if the table being ALTERed is itself located in
- ** the temp database.
- */
- if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
- sqlite3NestedParse(pParse,
- "UPDATE sqlite_temp_master SET "
- "sql = sqlite_rename_trigger(sql, %Q), "
- "tbl_name = %Q "
- "WHERE %s;", zName, zName, zWhere);
- sqliteFree(zWhere);
- }
-#endif
-
- /* Drop and reload the internal table schema. */
- reloadTableSchema(pParse, pTab, zName);
-
-exit_rename_table:
- sqlite3SrcListDelete(pSrc);
- sqliteFree(zName);
-}
-
-
-/*
-** This function is called after an "ALTER TABLE ... ADD" statement
-** has been parsed. Argument pColDef contains the text of the new
-** column definition.
-**
-** The Table structure pParse->pNewTable was extended to include
-** the new column during parsing.
-*/
-void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
- Table *pNew; /* Copy of pParse->pNewTable */
- Table *pTab; /* Table being altered */
- int iDb; /* Database number */
- const char *zDb; /* Database name */
- const char *zTab; /* Table name */
- char *zCol; /* Null-terminated column definition */
- Column *pCol; /* The new column */
- Expr *pDflt; /* Default value for the new column */
-
- if( pParse->nErr ) return;
- pNew = pParse->pNewTable;
- assert( pNew );
-
- iDb = sqlite3SchemaToIndex(pParse->db, pNew->pSchema);
- zDb = pParse->db->aDb[iDb].zName;
- zTab = pNew->zName;
- pCol = &pNew->aCol[pNew->nCol-1];
- pDflt = pCol->pDflt;
- pTab = sqlite3FindTable(pParse->db, zTab, zDb);
- assert( pTab );
-
-#ifndef SQLITE_OMIT_AUTHORIZATION
- /* Invoke the authorization callback. */
- if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
- return;
- }
-#endif
-
- /* If the default value for the new column was specified with a
- ** literal NULL, then set pDflt to 0. This simplifies checking
- ** for an SQL NULL default below.
- */
- if( pDflt && pDflt->op==TK_NULL ){
- pDflt = 0;
- }
-
- /* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
- ** If there is a NOT NULL constraint, then the default value for the
- ** column must not be NULL.
- */
- if( pCol->isPrimKey ){
- sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
- return;
- }
- if( pNew->pIndex ){
- sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
- return;
- }
- if( pCol->notNull && !pDflt ){
- sqlite3ErrorMsg(pParse,
- "Cannot add a NOT NULL column with default value NULL");
- return;
- }
-
- /* Ensure the default expression is something that sqlite3ValueFromExpr()
- ** can handle (i.e. not CURRENT_TIME etc.)
- */
- if( pDflt ){
- sqlite3_value *pVal;
- if( sqlite3ValueFromExpr(pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
- /* malloc() has failed */
- return;
- }
- if( !pVal ){
- sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
- return;
- }
- sqlite3ValueFree(pVal);
- }
-
- /* Modify the CREATE TABLE statement. */
- zCol = sqliteStrNDup((char*)pColDef->z, pColDef->n);
- if( zCol ){
- char *zEnd = &zCol[pColDef->n-1];
- while( (zEnd>zCol && *zEnd==';') || isspace(*(unsigned char *)zEnd) ){
- *zEnd-- = '\0';
- }
- sqlite3NestedParse(pParse,
- "UPDATE %Q.%s SET "
- "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d,length(sql)) "
- "WHERE type = 'table' AND name = %Q",
- zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
- zTab
- );
- sqliteFree(zCol);
- }
-
- /* If the default value of the new column is NULL, then set the file
- ** format to 2. If the default value of the new column is not NULL,
- ** the file format becomes 3.
- */
- sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2);
-
- /* Reload the schema of the modified table. */
- reloadTableSchema(pParse, pTab, pTab->zName);
-}
-
-/*
-** This function is called by the parser after the table-name in
-** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
-** pSrc is the full-name of the table being altered.
-**
-** This routine makes a (partial) copy of the Table structure
-** for the table being altered and sets Parse.pNewTable to point
-** to it. Routines called by the parser as the column definition
-** is parsed (i.e. sqlite3AddColumn()) add the new Column data to
-** the copy. The copy of the Table structure is deleted by tokenize.c
-** after parsing is finished.
-**
-** Routine sqlite3AlterFinishAddColumn() will be called to complete
-** coding the "ALTER TABLE ... ADD" statement.
-*/
-void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
- Table *pNew;
- Table *pTab;
- Vdbe *v;
- int iDb;
- int i;
- int nAlloc;
-
- /* Look up the table being altered. */
- assert( pParse->pNewTable==0 );
- if( sqlite3MallocFailed() ) goto exit_begin_add_column;
- pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
- if( !pTab ) goto exit_begin_add_column;
-
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- if( IsVirtual(pTab) ){
- sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
- goto exit_begin_add_column;
- }
-#endif
-
- /* Make sure this is not an attempt to ALTER a view. */
- if( pTab->pSelect ){
- sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
- goto exit_begin_add_column;
- }
-
- assert( pTab->addColOffset>0 );
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
-
- /* Put a copy of the Table struct in Parse.pNewTable for the
- ** sqlite3AddColumn() function and friends to modify.
- */
- pNew = (Table *)sqliteMalloc(sizeof(Table));
- if( !pNew ) goto exit_begin_add_column;
- pParse->pNewTable = pNew;
- pNew->nRef = 1;
- pNew->nCol = pTab->nCol;
- assert( pNew->nCol>0 );
- nAlloc = (((pNew->nCol-1)/8)*8)+8;
- assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
- pNew->aCol = (Column *)sqliteMalloc(sizeof(Column)*nAlloc);
- pNew->zName = sqliteStrDup(pTab->zName);
- if( !pNew->aCol || !pNew->zName ){
- goto exit_begin_add_column;
- }
- memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
- for(i=0; i<pNew->nCol; i++){
- Column *pCol = &pNew->aCol[i];
- pCol->zName = sqliteStrDup(pCol->zName);
- pCol->zColl = 0;
- pCol->zType = 0;
- pCol->pDflt = 0;
- }
- pNew->pSchema = pParse->db->aDb[iDb].pSchema;
- pNew->addColOffset = pTab->addColOffset;
- pNew->nRef = 1;
-
- /* Begin a transaction and increment the schema cookie. */
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- v = sqlite3GetVdbe(pParse);
- if( !v ) goto exit_begin_add_column;
- sqlite3ChangeCookie(pParse->db, v, iDb);
-
-exit_begin_add_column:
- sqlite3SrcListDelete(pSrc);
- return;
-}
-#endif /* SQLITE_ALTER_TABLE */
Copied: Frontier/branches/FSRef_Migration/Common/sqlite3/alter.c (from rev 1553, Frontier/trunk/Common/sqlite3/alter.c)
===================================================================
--- Frontier/branches/FSRef_Migration/Common/sqlite3/alter.c (rev 0)
+++ Frontier/branches/FSRef_Migration/Common/sqlite3/alter.c 2006-10-12 23:32:33 UTC (rev 1554)
@@ -0,0 +1,575 @@
+/*
+** 2005 February 15
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+*************************************************************************
+** This file contains C code routines that used to generate VDBE code
+** that implements the ALTER TABLE command.
+**
+** $Id: alter.c,v 1.21 2006/06/21 12:36:25 danielk1977 Exp $
+*/
+#include "sqliteInt.h"
+#include <ctype.h>
+
+/*
+** The code in this file only exists if we are not omitting the
+** ALTER TABLE logic from the build.
+*/
+#ifndef SQLITE_OMIT_ALTERTABLE
+
+
+/*
+** This function is used by SQL generated to implement the
+** ALTER TABLE command. The first argument is the text of a CREATE TABLE or
+** CREATE INDEX command. The second is a table name. The table name in
+** the CREATE TABLE or CREATE INDEX statement is replaced with the second
+** argument and the result returned. Examples:
+**
+** sqlite_rename_table('CREATE TABLE abc(a, b, c)', 'def')
+** -> 'CREATE TABLE def(a, b, c)'
+**
+** sqlite_rename_table('CREATE INDEX i ON abc(a)', 'def')
+** -> 'CREATE INDEX i ON def(a, b, c)'
+*/
+static void renameTableFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ unsigned char const *zSql = sqlite3_value_text(argv[0]);
+ unsigned char const *zTableName = sqlite3_value_text(argv[1]);
+
+ int token;
+ Token tname;
+ unsigned char const *zCsr = zSql;
+ int len = 0;
+ char *zRet;
+
+ /* The principle used to locate the table name in the CREATE TABLE
+ ** statement is that the table name is the first token that is immediatedly
+ ** followed by a left parenthesis - TK_LP.
+ */
+ if( zSql ){
+ do {
+ /* Store the token that zCsr points to in tname. */
+ tname.z = zCsr;
+ tname.n = len;
+
+ /* Advance zCsr to the next token. Store that token type in 'token',
+ ** and it's length in 'len' (to be used next iteration of this loop).
+ */
+ do {
+ zCsr += len;
+ len = sqlite3GetToken(zCsr, &token);
+ } while( token==TK_SPACE );
+ assert( len>0 );
+ } while( token!=TK_LP );
+
+ zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql,
+ zTableName, tname.z+tname.n);
+ sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
+ }
+}
+
+#ifndef SQLITE_OMIT_TRIGGER
+/* This function is used by SQL generated to implement the ALTER TABLE
+** ALTER TABLE command. The first argument is the text of a CREATE TRIGGER
+** statement. The second is a table name. The table name in the CREATE
+** TRIGGER statement is replaced with the second argument and the result
+** returned. This is analagous to renameTableFunc() above, except for CREATE
+** TRIGGER, not CREATE INDEX and CREATE TABLE.
+*/
+static void renameTriggerFunc(
+ sqlite3_context *context,
+ int argc,
+ sqlite3_value **argv
+){
+ unsigned char const *zSql = sqlite3_value_text(argv[0]);
+ unsigned char const *zTableName = sqlite3_value_text(argv[1]);
+
+ int token;
+ Token tname;
+ int dist = 3;
+ unsigned char const *zCsr = zSql;
+ int len = 0;
+ char *zRet;
+
+ /* The principle used to locate the table name in the CREATE TRIGGER
+ ** statement is that the table name is the first token that is immediatedly
+ ** preceded by either TK_ON or TK_DOT and immediatedly followed by one
+ ** of TK_WHEN, TK_BEGIN or TK_FOR.
+ */
+ if( zSql ){
+ do {
+ /* Store the token that zCsr points to in tname. */
+ tname.z = zCsr;
+ tname.n = len;
+
+ /* Advance zCsr to the next token. Store that token type in 'token',
+ ** and it's length in 'len' (to be used next iteration of this loop).
+ */
+ do {
+ zCsr += len;
+ len = sqlite3GetToken(zCsr, &token);
+ }while( token==TK_SPACE );
+ assert( len>0 );
+
+ /* Variable 'dist' stores the number of tokens read since the most
+ ** recent TK_DOT or TK_ON. This means that when a WHEN, FOR or BEGIN
+ ** token is read and 'dist' equals 2, the condition stated above
+ ** to be met.
+ **
+ ** Note that ON cannot be a database, table or column name, so
+ ** there is no need to worry about syntax like
+ ** "CREATE TRIGGER ... ON ON.ON BEGIN ..." etc.
+ */
+ dist++;
+ if( token==TK_DOT || token==TK_ON ){
+ dist = 0;
+ }
+ } while( dist!=2 || (token!=TK_WHEN && token!=TK_FOR && token!=TK_BEGIN) );
+
+ /* Variable tname now contains the token that is the old table-name
+ ** in the CREATE TRIGGER statement.
+ */
+ zRet = sqlite3MPrintf("%.*s%Q%s", tname.z - zSql, zSql,
+ zTableName, tname.z+tname.n);
+ sqlite3_result_text(context, zRet, -1, sqlite3FreeX);
+ }
+}
+#endif /* !SQLITE_OMIT_TRIGGER */
+
+/*
+** Register built-in functions used to help implement ALTER TABLE
+*/
+void sqlite3AlterFunctions(sqlite3 *db){
+ static const struct {
+ char *zName;
+ signed char nArg;
+ void (*xFunc)(sqlite3_context*,int,sqlite3_value **);
+ } aFuncs[] = {
+ { "sqlite_rename_table", 2, renameTableFunc},
+#ifndef SQLITE_OMIT_TRIGGER
+ { "sqlite_rename_trigger", 2, renameTriggerFunc},
+#endif
+ };
+ int i;
+
+ for(i=0; i<sizeof(aFuncs)/sizeof(aFuncs[0]); i++){
+ sqlite3CreateFunc(db, aFuncs[i].zName, aFuncs[i].nArg,
+ SQLITE_UTF8, 0, aFuncs[i].xFunc, 0, 0);
+ }
+}
+
+/*
+** Generate the text of a WHERE expression which can be used to select all
+** temporary triggers on table pTab from the sqlite_temp_master table. If
+** table pTab has no temporary triggers, or is itself stored in the
+** temporary database, NULL is returned.
+*/
+static char *whereTempTriggers(Parse *pParse, Table *pTab){
+ Trigger *pTrig;
+ char *zWhere = 0;
+ char *tmp = 0;
+ const Schema *pTempSchema = pParse->db->aDb[1].pSchema; /* Temp db schema */
+
+ /* If the table is not located in the temp-db (in which case NULL is
+ ** returned, loop through the tables list of triggers. For each trigger
+ ** that is not part of the temp-db schema, add a clause to the WHERE
+ ** expression being built up in zWhere.
+ */
+ if( pTab->pSchema!=pTempSchema ){
+ for( pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext ){
+ if( pTrig->pSchema==pTempSchema ){
+ if( !zWhere ){
+ zWhere = sqlite3MPrintf("name=%Q", pTrig->name);
+ }else{
+ tmp = zWhere;
+ zWhere = sqlite3MPrintf("%s OR name=%Q", zWhere, pTrig->name);
+ sqliteFree(tmp);
+ }
+ }
+ }
+ }
+ return zWhere;
+}
+
+/*
+** Generate code to drop and reload the internal representation of table
+** pTab from the database, including triggers and temporary triggers.
+** Argument zName is the name of the table in the database schema at
+** the time the generated code is executed. This can be different from
+** pTab->zName if this function is being called to code part of an
+** "ALTER TABLE RENAME TO" statement.
+*/
+static void reloadTableSchema(Parse *pParse, Table *pTab, const char *zName){
+ Vdbe *v;
+ char *zWhere;
+ int iDb; /* Index of database containing pTab */
+#ifndef SQLITE_OMIT_TRIGGER
+ Trigger *pTrig;
+#endif
+
+ v = sqlite3GetVdbe(pParse);
+ if( !v ) return;
+ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ assert( iDb>=0 );
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* Drop any table triggers from the internal schema. */
+ for(pTrig=pTab->pTrigger; pTrig; pTrig=pTrig->pNext){
+ int iTrigDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
+ assert( iTrigDb==iDb || iTrigDb==1 );
+ sqlite3VdbeOp3(v, OP_DropTrigger, iTrigDb, 0, pTrig->name, 0);
+ }
+#endif
+
+ /* Drop the table and index from the internal schema */
+ sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
+
+ /* Reload the table, index and permanent trigger schemas. */
+ zWhere = sqlite3MPrintf("tbl_name=%Q", zName);
+ if( !zWhere ) return;
+ sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* Now, if the table is not stored in the temp database, reload any temp
+ ** triggers. Don't use IN(...) in case SQLITE_OMIT_SUBQUERY is defined.
+ */
+ if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
+ sqlite3VdbeOp3(v, OP_ParseSchema, 1, 0, zWhere, P3_DYNAMIC);
+ }
+#endif
+}
+
+/*
+** Generate code to implement the "ALTER TABLE xxx RENAME TO yyy"
+** command.
+*/
+void sqlite3AlterRenameTable(
+ Parse *pParse, /* Parser context. */
+ SrcList *pSrc, /* The table to rename. */
+ Token *pName /* The new table name. */
+){
+ int iDb; /* Database that contains the table */
+ char *zDb; /* Name of database iDb */
+ Table *pTab; /* Table being renamed */
+ char *zName = 0; /* NULL-terminated version of pName */
+ sqlite3 *db = pParse->db; /* Database connection */
+ Vdbe *v;
+#ifndef SQLITE_OMIT_TRIGGER
+ char *zWhere = 0; /* Where clause to locate temp triggers */
+#endif
+
+ if( sqlite3MallocFailed() ) goto exit_rename_table;
+ assert( pSrc->nSrc==1 );
+
+ pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+ if( !pTab ) goto exit_rename_table;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
+ goto exit_rename_table;
+ }
+#endif
+ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+ zDb = db->aDb[iDb].zName;
+
+ /* Get a NULL terminated version of the new table name. */
+ zName = sqlite3NameFromToken(pName);
+ if( !zName ) goto exit_rename_table;
+
+ /* Check that a table or index named 'zName' does not already exist
+ ** in database iDb. If so, this is an error.
+ */
+ if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
+ sqlite3ErrorMsg(pParse,
+ "there is already another table or index with this name: %s", zName);
+ goto exit_rename_table;
+ }
+
+ /* Make sure it is not a system table being altered, or a reserved name
+ ** that the table is being renamed to.
+ */
+ if( strlen(pTab->zName)>6 && 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7) ){
+ sqlite3ErrorMsg(pParse, "table %s may not be altered", pTab->zName);
+ goto exit_rename_table;
+ }
+ if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
+ goto exit_rename_table;
+ }
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ /* Invoke the authorization callback. */
+ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
+ goto exit_rename_table;
+ }
+#endif
+
+ /* Begin a transaction and code the VerifyCookie for database iDb.
+ ** Then modify the schema cookie (since the ALTER TABLE modifies the
+ ** schema).
+ */
+ v = sqlite3GetVdbe(pParse);
+ if( v==0 ){
+ goto exit_rename_table;
+ }
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ sqlite3ChangeCookie(db, v, iDb);
+
+ /* Modify the sqlite_master table to use the new table name. */
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q.%s SET "
+#ifdef SQLITE_OMIT_TRIGGER
+ "sql = sqlite_rename_table(sql, %Q), "
+#else
+ "sql = CASE "
+ "WHEN type = 'trigger' THEN sqlite_rename_trigger(sql, %Q)"
+ "ELSE sqlite_rename_table(sql, %Q) END, "
+#endif
+ "tbl_name = %Q, "
+ "name = CASE "
+ "WHEN type='table' THEN %Q "
+ "WHEN name LIKE 'sqlite_autoindex%%' AND type='index' THEN "
+ "'sqlite_autoindex_' || %Q || substr(name, %d+18,10) "
+ "ELSE name END "
+ "WHERE tbl_name=%Q AND "
+ "(type='table' OR type='index' OR type='trigger');",
+ zDb, SCHEMA_TABLE(iDb), zName, zName, zName,
+#ifndef SQLITE_OMIT_TRIGGER
+ zName,
+#endif
+ zName, strlen(pTab->zName), pTab->zName
+ );
+
+#ifndef SQLITE_OMIT_AUTOINCREMENT
+ /* If the sqlite_sequence table exists in this database, then update
+ ** it with the new table name.
+ */
+ if( sqlite3FindTable(db, "sqlite_sequence", zDb) ){
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q.sqlite_sequence set name = %Q WHERE name = %Q",
+ zDb, zName, pTab->zName);
+ }
+#endif
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* If there are TEMP triggers on this table, modify the sqlite_temp_master
+ ** table. Don't do this if the table being ALTERed is itself located in
+ ** the temp database.
+ */
+ if( (zWhere=whereTempTriggers(pParse, pTab))!=0 ){
+ sqlite3NestedParse(pParse,
+ "UPDATE sqlite_temp_master SET "
+ "sql = sqlite_rename_trigger(sql, %Q), "
+ "tbl_name = %Q "
+ "WHERE %s;", zName, zName, zWhere);
+ sqliteFree(zWhere);
+ }
+#endif
+
+ /* Drop and reload the internal table schema. */
+ reloadTableSchema(pParse, pTab, zName);
+
+exit_rename_table:
+ sqlite3SrcListDelete(pSrc);
+ sqliteFree(zName);
+}
+
+
+/*
+** This function is called after an "ALTER TABLE ... ADD" statement
+** has been parsed. Argument pColDef contains the text of the new
+** column definition.
+**
+** The Table structure pParse->pNewTable was extended to include
+** the new column during parsing.
+*/
+void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
+ Table *pNew; /* Copy of pParse->pNewTable */
+ Table *pTab; /* Table being altered */
+ int iDb; /* Database number */
+ const char *zDb; /* Database name */
+ const char *zTab; /* Table name */
+ char *zCol; /* Null-terminated column definition */
+ Column *pCol; /* The new column */
+ Expr *pDflt; /* Default value for the new column */
+
+ if( pParse->nErr ) return;
+ pNew = pParse->pNewTable;
+ assert( pNew );
+
+ iDb = sqlite3SchemaToIndex(pParse->db, pNew->pSchema);
+ zDb = pParse->db->aDb[iDb].zName;
+ zTab = pNew->zName;
+ pCol = &pNew->aCol[pNew->nCol-1];
+ pDflt = pCol->pDflt;
+ pTab = sqlite3FindTable(pParse->db, zTab, zDb);
+ assert( pTab );
+
+#ifndef SQLITE_OMIT_AUTHORIZATION
+ /* Invoke the authorization callback. */
+ if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, 0) ){
+ return;
+ }
+#endif
+
+ /* If the default value for the new column was specified with a
+ ** literal NULL, then set pDflt to 0. This simplifies checking
+ ** for an SQL NULL default below.
+ */
+ if( pDflt && pDflt->op==TK_NULL ){
+ pDflt = 0;
+ }
+
+ /* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
+ ** If there is a NOT NULL constraint, then the default value for the
+ ** column must not be NULL.
+ */
+ if( pCol->isPrimKey ){
+ sqlite3ErrorMsg(pParse, "Cannot add a PRIMARY KEY column");
+ return;
+ }
+ if( pNew->pIndex ){
+ sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
+ return;
+ }
+ if( pCol->notNull && !pDflt ){
+ sqlite3ErrorMsg(pParse,
+ "Cannot add a NOT NULL column with default value NULL");
+ return;
+ }
+
+ /* Ensure the default expression is something that sqlite3ValueFromExpr()
+ ** can handle (i.e. not CURRENT_TIME etc.)
+ */
+ if( pDflt ){
+ sqlite3_value *pVal;
+ if( sqlite3ValueFromExpr(pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
+ /* malloc() has failed */
+ return;
+ }
+ if( !pVal ){
+ sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
+ return;
+ }
+ sqlite3ValueFree(pVal);
+ }
+
+ /* Modify the CREATE TABLE statement. */
+ zCol = sqliteStrNDup((char*)pColDef->z, pColDef->n);
+ if( zCol ){
+ char *zEnd = &zCol[pColDef->n-1];
+ while( (zEnd>zCol && *zEnd==';') || isspace(*(unsigned char *)zEnd) ){
+ *zEnd-- = '\0';
+ }
+ sqlite3NestedParse(pParse,
+ "UPDATE %Q.%s SET "
+ "sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d,length(sql)) "
+ "WHERE type = 'table' AND name = %Q",
+ zDb, SCHEMA_TABLE(iDb), pNew->addColOffset, zCol, pNew->addColOffset+1,
+ zTab
+ );
+ sqliteFree(zCol);
+ }
+
+ /* If the default value of the new column is NULL, then set the file
+ ** format to 2. If the default value of the new column is not NULL,
+ ** the file format becomes 3.
+ */
+ sqlite3MinimumFileFormat(pParse, iDb, pDflt ? 3 : 2);
+
+ /* Reload the schema of the modified table. */
+ reloadTableSchema(pParse, pTab, pTab->zName);
+}
+
+/*
+** This function is called by the parser after the table-name in
+** an "ALTER TABLE <table-name> ADD" statement is parsed. Argument
+** pSrc is the full-name of the table being altered.
+**
+** This routine makes a (partial) copy of the Table structure
+** for the table being altered and sets Parse.pNewTable to point
+** to it. Routines called by the parser as the column definition
+** is parsed (i.e. sqlite3AddColumn()) add the new Column data to
+** the copy. The copy of the Table structure is deleted by tokenize.c
+** after parsing is finished.
+**
+** Routine sqlite3AlterFinishAddColumn() will be called to complete
+** coding the "ALTER TABLE ... ADD" statement.
+*/
+void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
+ Table *pNew;
+ Table *pTab;
+ Vdbe *v;
+ int iDb;
+ int i;
+ int nAlloc;
+
+ /* Look up the table being altered. */
+ assert( pParse->pNewTable==0 );
+ if( sqlite3MallocFailed() ) goto exit_begin_add_column;
+ pTab = sqlite3LocateTable(pParse, pSrc->a[0].zName, pSrc->a[0].zDatabase);
+ if( !pTab ) goto exit_begin_add_column;
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( IsVirtual(pTab) ){
+ sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
+ goto exit_begin_add_column;
+ }
+#endif
+
+ /* Make sure this is not an attempt to ALTER a view. */
+ if( pTab->pSelect ){
+ sqlite3ErrorMsg(pParse, "Cannot add a column to a view");
+ goto exit_begin_add_column;
+ }
+
+ assert( pTab->addColOffset>0 );
+ iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
+
+ /* Put a copy of the Table struct in Parse.pNewTable for the
+ ** sqlite3AddColumn() function and friends to modify.
+ */
+ pNew = (Table *)sqliteMalloc(sizeof(Table));
+ if( !pNew ) goto exit_begin_add_column;
+ pParse->pNewTable = pNew;
+ pNew->nRef = 1;
+ pNew->nCol = pTab->nCol;
+ assert( pNew->nCol>0 );
+ nAlloc = (((pNew->nCol-1)/8)*8)+8;
+ assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
+ pNew->aCol = (Column *)sqliteMalloc(sizeof(Column)*nAlloc);
+ pNew->zName = sqliteStrDup(pTab->zName);
+ if( !pNew->aCol || !pNew->zName ){
+ goto exit_begin_add_column;
+ }
+ memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
+ for(i=0; i<pNew->nCol; i++){
+ Column *pCol = &pNew->aCol[i];
+ pCol->zName = sqliteStrDup(pCol->zName);
+ pCol->zColl = 0;
+ pCol->zType = 0;
+ pCol->pDflt = 0;
+ }
+ pNew->pSchema = pParse->db->aDb[iDb].pSchema;
+ pNew->addColOffset = pTab->addColOffset;
+ pNew->nRef = 1;
+
+ /* Begin a transaction and increment the schema cookie. */
+ sqlite3BeginWriteOperation(pParse, 0, iDb);
+ v = sqlite3GetVdbe(pParse);
+ if( !v ) goto exit_begin_add_column;
+ sqlite3ChangeCookie(pParse->db, v, iDb);
+
+exit_begin_add_column:
+ sqlite3SrcListDelete(pSrc);
+ return;
+}
+#endif /* SQLITE_ALTER_TABLE */
Deleted: Frontier/branches/FSRef_Migration/Common/sqlite3/analyze.c
===================================================================
--- Frontier/trunk/Common/sqlite3/analyze.c 2006-10-12 19:32:40 UTC (rev 1553)
+++ Frontier/branches/FSRef_Migration/Common/sqlite3/analyze.c 2006-10-12 23:32:33 UTC (rev 1554)
@@ -1,403 +0,0 @@
-/*
-** 2005 July 8
-**
-** The author disclaims copyright to this source code. In place of
-** a legal notice, here is a blessing:
-**
-** May you do good and not evil.
-** May you find forgiveness for yourself and forgive others.
-** May you share freely, never taking more than you give.
-**
-*************************************************************************
-** This file contains code associated with the ANALYZE command.
-**
-** @(#) $Id: analyze.c,v 1.16 2006/01/10 17:58:23 danielk1977 Exp $
-*/
-#ifndef SQLITE_OMIT_ANALYZE
-#include "sqliteInt.h"
-
-/*
-** This routine generates code that opens the sqlite_stat1 table on cursor
-** iStatCur.
-**
-** If the sqlite_stat1 tables does not previously exist, it is created.
-** If it does previously exist, all entires associated with table zWhere
-** are removed. If zWhere==0 then all entries are removed.
-*/
-static void openStatTable(
- Parse *pParse, /* Parsing context */
- int iDb, /* The database we are looking in */
- int iStatCur, /* Open the sqlite_stat1 table on this cursor */
- const char *zWhere /* Delete entries associated with this table */
-){
- sqlite3 *db = pParse->db;
- Db *pDb;
- int iRootPage;
- Table *pStat;
- Vdbe *v = sqlite3GetVdbe(pParse);
-
- pDb = &db->aDb[iDb];
- if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){
- /* The sqlite_stat1 tables does not exist. Create it.
- ** Note that a side-effect of the CREATE TABLE statement is to leave
- ** the rootpage of the new table on the top of the stack. This is
- ** important because the OpenWrite opcode below will be needing it. */
- sqlite3NestedParse(pParse,
- "CREATE TABLE %Q.sqlite_stat1(tbl,idx,stat)",
- pDb->zName
- );
- iRootPage = 0; /* Cause rootpage to be taken from top of stack */
- }else if( zWhere ){
- /* The sqlite_stat1 table exists. Delete all entries associated with
- ** the table zWhere. */
- sqlite3NestedParse(pParse,
- "DELETE FROM %Q.sqlite_stat1 WHERE tbl=%Q",
- pDb->zName, zWhere
- );
- iRootPage = pStat->tnum;
- }else{
- /* The sqlite_stat1 table already exists. Delete all rows. */
- iRootPage = pStat->tnum;
- sqlite3VdbeAddOp(v, OP_Clear, pStat->tnum, iDb);
- }
-
- /* Open the sqlite_stat1 table for writing. Unless it was created
- ** by this vdbe program, lock it for writing at the shared-cache level.
- ** If this vdbe did create the sqlite_stat1 table, then it must have
- ** already obtained a schema-lock, making the write-lock redundant.
- */
- if( iRootPage>0 ){
- sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1");
- }
- sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
- sqlite3VdbeAddOp(v, OP_OpenWrite, iStatCur, iRootPage);
- sqlite3VdbeAddOp(v, OP_SetNumColumns, iStatCur, 3);
-}
-
-/*
-** Generate code to do an analysis of all indices associated with
-** a single table.
-*/
-static void analyzeOneTable(
- Parse *pParse, /* Parser context */
- Table *pTab, /* Table whose indices are to be analyzed */
- int iStatCur, /* Cursor that writes to the sqlite_stat1 table */
- int iMem /* Available memory locations begin here */
-){
- Index *pIdx; /* An index to being analyzed */
- int iIdxCur; /* Cursor number for index being analyzed */
- int nCol; /* Number of columns in the index */
- Vdbe *v; /* The virtual machine being built up */
- int i; /* Loop counter */
- int topOfLoop; /* The top of the loop */
- int endOfLoop; /* The end of the loop */
- int addr; /* The address of an instruction */
- int iDb; /* Index of database containing pTab */
-
- v = sqlite3GetVdbe(pParse);
- if( pTab==0 || pTab->pIndex==0 ){
- /* Do no analysis for tables that have no indices */
- return;
- }
-
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- assert( iDb>=0 );
-#ifndef SQLITE_OMIT_AUTHORIZATION
- if( sqlite3AuthCheck(pParse, SQLITE_ANALYZE, pTab->zName, 0,
- pParse->db->aDb[iDb].zName ) ){
- return;
- }
-#endif
-
- /* Establish a read-lock on the table at the shared-cache level. */
- sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
-
- iIdxCur = pParse->nTab;
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
-
- /* Open a cursor to the index to be analyzed
- */
- assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) );
- sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
- VdbeComment((v, "# %s", pIdx->zName));
- sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum,
- (char *)pKey, P3_KEYINFO_HANDOFF);
- nCol = pIdx->nColumn;
- if( iMem+nCol*2>=pParse->nMem ){
- pParse->nMem = iMem+nCol*2+1;
- }
- sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, nCol+1);
-
- /* Memory cells are used as follows:
- **
- ** mem[iMem]: The total number of rows in the table.
- ** mem[iMem+1]: Number of distinct values in column 1
- ** ...
- ** mem[iMem+nCol]: Number of distinct values in column N
- ** mem[iMem+nCol+1] Last observed value of column 1
- ** ...
- ** mem[iMem+nCol+nCol]: Last observed value of column N
- **
- ** Cells iMem through iMem+nCol are initialized to 0. The others
- ** are initialized to NULL.
- */
- for(i=0; i<=nCol; i++){
- sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem+i);
- }
- for(i=0; i<nCol; i++){
- sqlite3VdbeAddOp(v, OP_MemNull, iMem+nCol+i+1, 0);
- }
-
- /* Do the analysis.
- */
- endOfLoop = sqlite3VdbeMakeLabel(v);
- sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, endOfLoop);
- topOfLoop = sqlite3VdbeCurrentAddr(v);
- sqlite3VdbeAddOp(v, OP_MemIncr, 1, iMem);
- for(i=0; i<nCol; i++){
- sqlite3VdbeAddOp(v, OP_Column, iIdxCur, i);
- sqlite3VdbeAddOp(v, OP_MemLoad, iMem+nCol+i+1, 0);
- sqlite3VdbeAddOp(v, OP_Ne, 0x100, 0);
- }
- sqlite3VdbeAddOp(v, OP_Goto, 0, endOfLoop);
- for(i=0; i<nCol; i++){
- addr = sqlite3VdbeAddOp(v, OP_MemIncr, 1, iMem+i+1);
- sqlite3VdbeChangeP2(v, topOfLoop + 3*i + 3, addr);
- sqlite3VdbeAddOp(v, OP_Column, iIdxCur, i);
- sqlite3VdbeAddOp(v, OP_MemStore, iMem+nCol+i+1, 1);
- }
- sqlite3VdbeResolveLabel(v, endOfLoop);
- sqlite3VdbeAddOp(v, OP_Next, iIdxCur, topOfLoop);
- sqlite3VdbeAddOp(v, OP_Close, iIdxCur, 0);
-
- /* Store the results.
- **
- ** The result is a single row of the sqlite_stmt1 table. The first
- ** two columns are the names of the table and index. The third column
- ** is a string composed of a list of integer statistics about the
- ** index. The first integer in the list is the total number of entires
- ** in the index. There is one additional integer in the list for each
- ** column of the table. This additional integer is a guess of how many
- ** rows of the table the index will select. If D is the count of distinct
- ** values and K is the total number of rows, then the integer is computed
- ** as:
- **
- ** I = (K+D-1)/D
- **
- ** If K==0 then no entry is made into the sqlite_stat1 table.
- ** If K>0 then it is always the case the D>0 so division by zero
- ** is never possible.
- */
- sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
- addr = sqlite3VdbeAddOp(v, OP_IfNot, 0, 0);
- sqlite3VdbeAddOp(v, OP_NewRowid, iStatCur, 0);
- sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0);
- sqlite3VdbeOp3(v, OP_String8, 0, 0, pIdx->zName, 0);
- sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
- sqlite3VdbeOp3(v, OP_String8, 0, 0, " ", 0);
- for(i=0; i<nCol; i++){
- sqlite3VdbeAddOp(v, OP_MemLoad, iMem, 0);
- sqlite3VdbeAddOp(v, OP_MemLoad, iMem+i+1, 0);
- sqlite3VdbeAddOp(v, OP_Add, 0, 0);
- sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);
- sqlite3VdbeAddOp(v, OP_MemLoad, iMem+i+1, 0);
- sqlite3VdbeAddOp(v, OP_Divide, 0, 0);
- sqlite3VdbeAddOp(v, OP_ToInt, 0, 0);
- if( i==nCol-1 ){
- sqlite3VdbeAddOp(v, OP_Concat, nCol*2-1, 0);
- }else{
- sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
- }
- }
- sqlite3VdbeOp3(v, OP_MakeRecord, 3, 0, "aaa", 0);
- sqlite3VdbeAddOp(v, OP_Insert, iStatCur, 0);
- sqlite3VdbeJumpHere(v, addr);
- }
-}
-
-/*
-** Generate code that will cause the most recent index analysis to
-** be laoded into internal hash tables where is can be used.
-*/
-static void loadAnalysis(Parse *pParse, int iDb){
- Vdbe *v = sqlite3GetVdbe(pParse);
- sqlite3VdbeAddOp(v, OP_LoadAnalysis, iDb, 0);
-}
-
-/*
-** Generate code that will do an analysis of an entire database
-*/
-static void analyzeDatabase(Parse *pParse, int iDb){
- sqlite3 *db = pParse->db;
- Schema *pSchema = db->aDb[iDb].pSchema; /* Schema of database iDb */
- HashElem *k;
- int iStatCur;
- int iMem;
-
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- iStatCur = pParse->nTab++;
- openStatTable(pParse, iDb, iStatCur, 0);
- iMem = pParse->nMem;
- for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
- Table *pTab = (Table*)sqliteHashData(k);
- analyzeOneTable(pParse, pTab, iStatCur, iMem);
- }
- loadAnalysis(pParse, iDb);
-}
-
-/*
-** Generate code that will do an analysis of a single table in
-** a database.
-*/
-static void analyzeTable(Parse *pParse, Table *pTab){
- int iDb;
- int iStatCur;
-
- assert( pTab!=0 );
- iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- sqlite3BeginWriteOperation(pParse, 0, iDb);
- iStatCur = pParse->nTab++;
- openStatTable(pParse, iDb, iStatCur, pTab->zName);
- analyzeOneTable(pParse, pTab, iStatCur, pParse->nMem);
- loadAnalysis(pParse, iDb);
-}
-
-/*
-** Generate code for the ANALYZE command. The parser calls this routine
-** when it recognizes an ANALYZE command.
-**
-** ANALYZE -- 1
-** ANALYZE <database> -- 2
-** ANALYZE ?<database>.?<tablename> -- 3
-**
-** Form 1 causes all indices in all attached databases to be analyzed.
-** Form 2 analyzes all indices the single database named.
-** Form 3 analyzes all indices associated with the named table.
-*/
-void sqlite3Analyze(Parse *pParse, Token *pName1, Token *pName2){
- sqlite3 *db = pParse->db;
- int iDb;
- int i;
- char *z, *zDb;
- Table *pTab;
- Token *pTableName;
-
- /* Read the database schema. If an error occurs, leave an error message
- ** and code in pParse and return NULL. */
- if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
- return;
- }
-
- if( pName1==0 ){
- /* Form 1: Analyze everything */
- for(i=0; i<db->nDb; i++){
- if( i==1 ) continue; /* Do not analyze the TEMP database */
- analyzeDatabase(pParse, i);
- }
- }else if( pName2==0 || pName2->n==0 ){
- /* Form 2: Analyze the database or table named */
- iDb = sqlite3FindDb(db, pName1);
- if( iDb>=0 ){
- analyzeDatabase(pParse, iDb);
- }else{
- z = sqlite3NameFromToken(pName1);
- pTab = sqlite3LocateTable(pParse, z, 0);
- sqliteFree(z);
- if( pTab ){
- analyzeTable(pParse, pTab);
- }
- }
- }else{
- /* Form 3: Analyze the fully qualified table name */
- iDb = sqlite3TwoPartName(pParse, pName1, pName2, &pTableName);
- if( iDb>=0 ){
- zDb = db->aDb[iDb].zName;
- z = sqlite3NameFromToken(pTableName);
- pTab = sqlite3LocateTable(pParse, z, zDb);
- sqliteFree(z);
- if( pTab ){
- analyzeTable(pParse, pTab);
- }
- }
- }
-}
-
-/*
-** Used to pass information from the analyzer reader through to the
-** callback routine.
-*/
-typedef struct analysisInfo analysisInfo;
-struct analysisInfo {
- sqlite3 *db;
- const char *zDatabase;
-};
-
-/*
-** This callback is invoked once for each index when reading the
-** sqlite_stat1 table.
-**
-** argv[0] = name of the index
-** argv[1] = results of analysis - on integer for each column
-*/
-static int analysisLoader(void *pData, int argc, char **argv, char **azNotUsed){
- analysisInfo *pInfo = (analysisInfo*)pData;
- Index *pIndex;
- int i, c;
- unsigned int v;
- const char *z;
-
- assert( argc==2 );
- if( argv==0 || argv[0]==0 || argv[1]==0 ){
- return 0;
- }
- pIndex = sqlite3FindIndex(pInfo->db, argv[0], pInfo->zDatabase);
- if( pIndex==0 ){
- return 0;
- }
- z = argv[1];
- for(i=0; *z && i<=pIndex->nColumn; i++){
- v = 0;
- while( (c=z[0])>='0' && c<='9' ){
- v = v*10 + c - '0';
- z++;
- }
- pIndex->aiRowEst[i] = v;
- if( *z==' ' ) z++;
- }
- return 0;
-}
-
-/*
-** Load the content of the sqlite_stat1 table into the index hash tables.
-*/
-void sqlite3AnalysisLoad(sqlite3 *db, int iDb){
- analysisInfo sInfo;
- HashElem *i;
- char *zSql;
-
- /* Clear any prior statistics */
- for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
- Index *pIdx = sqliteHashData(i);
- sqlite3DefaultRowEst(pIdx);
- }
-
- /* Check to make sure the sqlite_stat1 table existss */
- sInfo.db = db;
- sInfo.zDatabase = db->aDb[iDb].zName;
- if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){
- return;
- }
-
-
- /* Load new statistics out of t...
[truncated message content] |