aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build.c2
-rw-r--r--src/expr.c44
-rw-r--r--src/sqliteInt.h2
3 files changed, 35 insertions, 13 deletions
diff --git a/src/build.c b/src/build.c
index 0c02a56fe..777831aab 100644
--- a/src/build.c
+++ b/src/build.c
@@ -1236,7 +1236,7 @@ void sqlite3AddDefaultValue(Parse *pParse, ExprSpan *pSpan){
p = pParse->pNewTable;
if( p!=0 ){
pCol = &(p->aCol[p->nCol-1]);
- if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr) ){
+ if( !sqlite3ExprIsConstantOrFunction(pSpan->pExpr, db->init.busy) ){
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
pCol->zName);
}else{
diff --git a/src/expr.c b/src/expr.c
index c8e8e7826..57e462ea6 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -1212,32 +1212,40 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
/*
** These routines are Walker callbacks. Walker.u.pi is a pointer
** to an integer. These routines are checking an expression to see
-** if it is a constant. Set *Walker.u.pi to 0 if the expression is
+** if it is a constant. Set *Walker.u.i to 0 if the expression is
** not constant.
**
** These callback routines are used to implement the following:
**
-** sqlite3ExprIsConstant()
-** sqlite3ExprIsConstantNotJoin()
-** sqlite3ExprIsConstantOrFunction()
+** sqlite3ExprIsConstant() pWalker->u.i==1
+** sqlite3ExprIsConstantNotJoin() pWalker->u.i==2
+** sqlite3ExprIsConstantOrFunction() pWalker->u.i==3 or 4
**
+** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions
+** in a CREATE TABLE statement. The Walker.u.i value is 4 when parsing
+** an existing schema and 3 when processing a new statement. A bound
+** parameter raises an error for new statements, but is silently converted
+** to NULL for existing schemas. This allows sqlite_master tables that
+** contain a bound parameter because they were generated by older versions
+** of SQLite to be parsed by newer versions of SQLite without raising a
+** malformed schema error.
*/
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
- /* If pWalker->u.i is 3 then any term of the expression that comes from
+ /* If pWalker->u.i is 2 then any term of the expression that comes from
** the ON or USING clauses of a join disqualifies the expression
** from being considered constant. */
- if( pWalker->u.i==3 && ExprHasProperty(pExpr, EP_FromJoin) ){
+ if( pWalker->u.i==2 && ExprHasProperty(pExpr, EP_FromJoin) ){
pWalker->u.i = 0;
return WRC_Abort;
}
switch( pExpr->op ){
/* Consider functions to be constant if all their arguments are constant
- ** and either pWalker->u.i==2 or the function as the SQLITE_FUNC_CONST
+ ** and either pWalker->u.i==3 or 4 or the function as the SQLITE_FUNC_CONST
** flag. */
case TK_FUNCTION:
- if( pWalker->u.i==2 || ExprHasProperty(pExpr,EP_Constant) ){
+ if( pWalker->u.i>=3 || ExprHasProperty(pExpr,EP_Constant) ){
return WRC_Continue;
}
/* Fall through */
@@ -1251,6 +1259,19 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_AGG_COLUMN );
pWalker->u.i = 0;
return WRC_Abort;
+ case TK_VARIABLE:
+ if( pWalker->u.i==4 ){
+ /* Silently convert bound parameters that appear inside of CREATE
+ ** statements into a NULL when parsing the CREATE statement text out
+ ** of the sqlite_master table */
+ pExpr->op = TK_NULL;
+ }else if( pWalker->u.i==3 ){
+ /* A bound parameter in a CREATE statement that originates from
+ ** sqlite3_prepare() causes an error */
+ pWalker->u.i = 0;
+ return WRC_Abort;
+ }
+ /* Fall through */
default:
testcase( pExpr->op==TK_SELECT ); /* selectNodeIsConstant will disallow */
testcase( pExpr->op==TK_EXISTS ); /* selectNodeIsConstant will disallow */
@@ -1291,7 +1312,7 @@ int sqlite3ExprIsConstant(Expr *p){
** an ON or USING clause.
*/
int sqlite3ExprIsConstantNotJoin(Expr *p){
- return exprIsConst(p, 3);
+ return exprIsConst(p, 2);
}
/*
@@ -1303,8 +1324,9 @@ int sqlite3ExprIsConstantNotJoin(Expr *p){
** is considered a variable but a single-quoted string (ex: 'abc') is
** a constant.
*/
-int sqlite3ExprIsConstantOrFunction(Expr *p){
- return exprIsConst(p, 2);
+int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
+ assert( isInit==0 || isInit==1 );
+ return exprIsConst(p, 3+isInit);
}
/*
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 9a9675b0a..414f30b66 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -3285,7 +3285,7 @@ void sqlite3CloseSavepoints(sqlite3 *);
void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
int sqlite3ExprIsConstant(Expr*);
int sqlite3ExprIsConstantNotJoin(Expr*);
-int sqlite3ExprIsConstantOrFunction(Expr*);
+int sqlite3ExprIsConstantOrFunction(Expr*, u8);
int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3ExprCanBeNull(const Expr*);
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);