/ Check-in [ff868e22]
Login

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

Overview
Comment:Allow the default value for columns added using ALTER TABLE ADD COLUMN to be a function in existing schemas loaded from disk. But prevent this version of SQLite from being used to create such a column.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | stat4-function
Files: files | file ages | folders
SHA1: ff868e22ca0393eaac417872a4c10738f0d7d970
User & Date: dan 2015-03-11 20:59:42
Context
2015-03-12
06:46
The valueFromFunction() routine is better able to handle OOM errors. Omit unreachable branches. check-in: 8fb6bd9b user: drh tags: stat4-function
2015-03-11
20:59
Allow the default value for columns added using ALTER TABLE ADD COLUMN to be a function in existing schemas loaded from disk. But prevent this version of SQLite from being used to create such a column. check-in: ff868e22 user: dan tags: stat4-function
20:06
Allow the query planner to evaluate deterministic scalar SQL functions used in WHERE constraints if all arguments are SQL literals in order to compare the results with sqlite_stat4 sample data. check-in: b7f1fc26 user: dan tags: stat4-function
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/alter.c.

686
687
688
689
690
691
692

693

694
695
696
697
698
699
700
  }

  /* Ensure the default expression is something that sqlite3ValueFromExpr()
  ** can handle (i.e. not CURRENT_TIME etc.)
  */
  if( pDflt ){
    sqlite3_value *pVal = 0;

    if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){

      db->mallocFailed = 1;
      return;
    }
    if( !pVal ){
      sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
      return;
    }







>
|
>







686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
  }

  /* Ensure the default expression is something that sqlite3ValueFromExpr()
  ** can handle (i.e. not CURRENT_TIME etc.)
  */
  if( pDflt ){
    sqlite3_value *pVal = 0;
    if( pDflt->op!=TK_FUNCTION
     && sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) 
    ){
      db->mallocFailed = 1;
      return;
    }
    if( !pVal ){
      sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
      return;
    }

Changes to src/vdbemem.c.

1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
....
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196

1197
1198
1199
1200
1201
1202
1203
....
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
}

/*
** The expression object indicated by the second argument is guaranteed
** to be a scalar SQL function. If
**
**   * all function arguments are SQL literals,
**   * the SQLITE_FUNC_CONSTANT function flag is set,
**   * the SQLITE_FUNC_NEEDCOLL function flag is not set, and
**   * this routine is being invoked as part of examining stat4 data,
**     not as part of handling a default value on a column created using
**     ALTER TABLE ADD COLUMN, 
**
** then this routine attempts to invoke the SQL function. Assuming no
** error occurs, output parameter (*ppVal) is set to point to a value 
** object containing the result before returning SQLITE_OK.
**
** Affinity aff is applied to the result of the function before returning.
** If the result is a text value, the sqlite3_value object uses encoding 
................................................................................
  sqlite3_context ctx;            /* Context object for function invocation */
  sqlite3_value **apVal = 0;      /* Function arguments */
  int nVal = 0;                   /* Size of apVal[] array */
  FuncDef *pFunc = 0;             /* Function definition */
  sqlite3_value *pVal = 0;        /* New value */
  int rc = SQLITE_OK;             /* Return code */
  int nName;                      /* Size of function name in bytes */
  ExprList *pList;                /* Function arguments */
  int i;                          /* Iterator variable */

  /* If pCtx==0, then this is probably being called to to obtain an 
  ** sqlite3_value object for the default value of a column. In that case
  ** function expressions are not supported. Function expressions are
  ** only supported when extracting values to compare with sqlite_stat4 
  ** records.
  **
  ** It may also be that this function expression is an argument passed
  ** to another function expression. As in "f2(...)" within the query:
  **
  **   SELECT * FROM tbl WHERE tbl.c = f1(0, f2(...), 1);
  **
  ** For now, extracting the value of "f1(...)" is not supported either.
  */
  if( pCtx==0 ) return SQLITE_OK;
  
  assert( (p->flags & (EP_TokenOnly|EP_Reduced))==0 );
  pList = p->x.pList;
  if( pList ) nVal = pList->nExpr;

  nName = sqlite3Strlen30(p->u.zToken);
  pFunc = sqlite3FindFunction(db, p->u.zToken, nName, nVal, enc, 0);
  assert( pFunc );
  if( (pFunc->funcFlags & SQLITE_FUNC_CONSTANT)==0 
   || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
  ){
    return SQLITE_OK;
................................................................................

  memset(&ctx, 0, sizeof(ctx));
  ctx.pOut = pVal;
  ctx.pFunc = pFunc;
  pFunc->xFunc(&ctx, nVal, apVal);
  if( ctx.isError ){
    rc = ctx.isError;
    sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal));
  }else{
    sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8);
    if( rc==SQLITE_OK ){
      rc = sqlite3VdbeChangeEncoding(pVal, enc);
    }
    if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){
      rc = SQLITE_TOOBIG;







|
|
<
<
<







 







|


|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|
|
>







 







|







1135
1136
1137
1138
1139
1140
1141
1142
1143



1144
1145
1146
1147
1148
1149
1150
....
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176















1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
....
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
}

/*
** The expression object indicated by the second argument is guaranteed
** to be a scalar SQL function. If
**
**   * all function arguments are SQL literals,
**   * the SQLITE_FUNC_CONSTANT function flag is set, and
**   * the SQLITE_FUNC_NEEDCOLL function flag is not set,



**
** then this routine attempts to invoke the SQL function. Assuming no
** error occurs, output parameter (*ppVal) is set to point to a value 
** object containing the result before returning SQLITE_OK.
**
** Affinity aff is applied to the result of the function before returning.
** If the result is a text value, the sqlite3_value object uses encoding 
................................................................................
  sqlite3_context ctx;            /* Context object for function invocation */
  sqlite3_value **apVal = 0;      /* Function arguments */
  int nVal = 0;                   /* Size of apVal[] array */
  FuncDef *pFunc = 0;             /* Function definition */
  sqlite3_value *pVal = 0;        /* New value */
  int rc = SQLITE_OK;             /* Return code */
  int nName;                      /* Size of function name in bytes */
  ExprList *pList = 0;            /* Function arguments */
  int i;                          /* Iterator variable */

  if( (p->flags & EP_TokenOnly)==0 ){















    pList = p->x.pList;
    if( pList ) nVal = pList->nExpr;
  }
  nName = sqlite3Strlen30(p->u.zToken);
  pFunc = sqlite3FindFunction(db, p->u.zToken, nName, nVal, enc, 0);
  assert( pFunc );
  if( (pFunc->funcFlags & SQLITE_FUNC_CONSTANT)==0 
   || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
  ){
    return SQLITE_OK;
................................................................................

  memset(&ctx, 0, sizeof(ctx));
  ctx.pOut = pVal;
  ctx.pFunc = pFunc;
  pFunc->xFunc(&ctx, nVal, apVal);
  if( ctx.isError ){
    rc = ctx.isError;
    if( pCtx ) sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal));
  }else{
    sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8);
    if( rc==SQLITE_OK ){
      rc = sqlite3VdbeChangeEncoding(pVal, enc);
    }
    if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){
      rc = SQLITE_TOOBIG;