/ Check-in [db829dc1]
Login

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

Overview
Comment:Have ALTER TABLE RENAME edit column references in CREATE VIEW statements.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | edit-trigger-wrapper
Files: files | file ages | folders
SHA3-256:db829dc1a2d7afa49798a2fd32d1f070185b23e513416e65d8144fda24f23b50
User & Date: dan 2018-08-14 20:18:50
Context
2018-08-14
20:40
Merge latest trunk and ALTER TABLE error message improvements into this branch. check-in: 7a45802d user: dan tags: edit-trigger-wrapper
20:18
Have ALTER TABLE RENAME edit column references in CREATE VIEW statements. check-in: db829dc1 user: dan tags: edit-trigger-wrapper
2018-08-13
17:14
Edit the WHEN and UPDATE OF clauses of trigger programs as part of ALTER TABLE RENAME COLUMN. check-in: 5fdb6b0a user: dan tags: edit-trigger-wrapper
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/alter.c.

840
841
842
843
844
845
846
847
848

849
850
851


852
853
854
855
856
857
858
...
892
893
894
895
896
897
898

899
900
901
902
903
904
905
...
938
939
940
941
942
943
944






945
946
947
948
949
950
951
952
953
954
955
956
957
958














959
960
961
962
963
964
965
966
967
968
969
970
971
972


973
974
975
976
977









978
979
980
981
982
983
984
...
986
987
988
989
990
991
992


993






















994
995
996
997
998
999
1000
1001
1002
1003


1004
1005
1006
1007

1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019

1020







1021
1022

1023
1024
1025
1026
1027
1028
1029
....
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074

1075
1076

1077


















1078
1079

1080
1081
1082
1083
1084
1085
1086

1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102

1103
1104
1105
1106
1107
1108
1109
....
1115
1116
1117
1118
1119
1120
1121

1122
1123
1124
1125
1126
1127
1128
....
1148
1149
1150
1151
1152
1153
1154


1155
1156
1157








1158
1159
1160
1161
1162
1163
1164
  */
  zNew = sqlite3NameFromToken(db, pNew);
  if( !zNew ) goto exit_rename_column;
  assert( pNew->n>0 );
  bQuote = sqlite3Isquote(pNew->z[0]);
  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\".%s SET "
      "sql = sqlite_rename_column(sql, %d, %d, %Q, %Q, %Q) "
      "WHERE name NOT LIKE 'sqlite_%%' AND ("

      "   type = 'table' OR (type IN ('index', 'trigger') AND tbl_name = %Q)"
      ")",
      zDb, MASTER_NAME, iCol, bQuote, zNew, pTab->zName, zOld, pTab->zName


  );

  /* Drop and reload the database schema. */
  if( pParse->pVdbe ){
    sqlite3ChangeCookie(pParse, iSchema);
    sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iSchema, 0);
  }
................................................................................
** down into the Walker.
*/
typedef struct RenameCtx RenameCtx;
struct RenameCtx {
  RenameToken *pList;             /* List of tokens to overwrite */
  int nList;                      /* Number of tokens in pList */
  int iCol;                       /* Index of column being renamed */

  const char *zOld;               /* Old column name */
};

/*
** Add a new RenameToken object mapping parse tree element pPtr into
** token *pToken to the Parse object currently under construction.
*/
................................................................................
  RenameToken *p;
  for(p=pToken; p; p=pNext){
    pNext = p->pNext;
    sqlite3DbFree(db, p);
  }
}







static void renameTokenFind(Parse *pParse, RenameCtx *pCtx, void *pPtr){
  RenameToken **pp;
  for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){
    if( (*pp)->p==pPtr ){
      RenameToken *pToken = *pp;
      *pp = pToken->pNext;
      pToken->pNext = pCtx->pList;
      pCtx->pList = pToken;
      pCtx->nList++;
      break;
    }
  }
}















static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){
  RenameCtx *p = pWalker->u.pRename;
  if( p->zOld && pExpr->op==TK_DOT ){
    Expr *pLeft = pExpr->pLeft;
    Expr *pRight = pExpr->pRight;
    assert( pLeft->op==TK_ID && pRight->op==TK_ID );
    if( 0==sqlite3_stricmp(pLeft->u.zToken, "old")
     || 0==sqlite3_stricmp(pLeft->u.zToken, "new")
    ){
      if( 0==sqlite3_stricmp(pRight->u.zToken, p->zOld) ){
        renameTokenFind(pWalker->pParse, p, (void*)pRight);
      }
    }
  }else if( pExpr->op==TK_COLUMN && pExpr->iColumn==p->iCol ){


    renameTokenFind(pWalker->pParse, p, (void*)pExpr);
  }
  return WRC_Continue;
}










static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){
  RenameToken *pBest = pCtx->pList;
  RenameToken *pToken;
  RenameToken **pp;

  for(pToken=pBest->pNext; pToken; pToken=pToken->pNext){
    if( pToken->t.z>pBest->t.z ) pBest = pToken;
................................................................................
  for(pp=&pCtx->pList; *pp!=pBest; pp=&(*pp)->pNext);
  *pp = pBest->pNext;

  return pBest;
}

/*


** sqlite_rename_column(SQL, iCol, bQuote, zNew, zTable, zOld)






















*/
static void renameColumnFunc(
  sqlite3_context *context,
  int NotUsed,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  RenameCtx sCtx;
  const char *zSql = (const char*)sqlite3_value_text(argv[0]);
  int nSql = sqlite3_value_bytes(argv[0]);


  int bQuote = sqlite3_value_int(argv[2]);
  const char *zNew = (const char*)sqlite3_value_text(argv[3]);
  int nNew = sqlite3_value_bytes(argv[3]);
  const char *zTable = (const char*)sqlite3_value_text(argv[4]);

  const char *zOld = (const char*)sqlite3_value_text(argv[5]);

  int rc;
  char *zErr = 0;
  Parse sParse;
  Walker sWalker;
  Index *pIdx;
  char *zOut = 0;

  char *zQuot = 0;                /* Quoted version of zNew */
  int nQuot = 0;                  /* Length of zQuot in bytes */
  int i;









  memset(&sCtx, 0, sizeof(sCtx));
  sCtx.iCol = sqlite3_value_int(argv[1]);


  memset(&sParse, 0, sizeof(sParse));
  sParse.eParseMode = PARSE_MODE_RENAME_COLUMN;
  sParse.db = db;
  sParse.nQueryLoop = 1;
  rc = sqlite3RunParser(&sParse, zSql, &zErr);
  assert( sParse.pNewTable==0 || sParse.pNewIndex==0 );
................................................................................
    if( zQuot==0 ){
      rc = SQLITE_NOMEM;
    }else{
      nQuot = sqlite3Strlen30(zQuot);
    }
  }

  if( rc!=SQLITE_OK ){
    if( zErr ){
      sqlite3_result_error(context, zErr, -1);
    }else{
      sqlite3_result_error_code(context, rc);
    }
    sqlite3DbFree(db, zErr);
    goto renameColumnFunc_done;
  }

  if( bQuote ){
    zNew = zQuot;
    nNew = nQuot;
  }

#ifdef SQLITE_DEBUG
  assert( sqlite3Strlen30(zSql)==nSql );
  {
    RenameToken *pToken;
    for(pToken=sParse.pRename; pToken; pToken=pToken->pNext){
      assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] );
    }
  }
#endif

  /* Find tokens that need to be replaced. */
  memset(&sWalker, 0, sizeof(Walker));
  sWalker.pParse = &sParse;
  sWalker.xExprCallback = renameColumnExprCb;

  sWalker.u.pRename = &sCtx;


  if( sParse.pNewTable ){


















    int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
    FKey *pFKey;

    if( bFKOnly==0 ){
      renameTokenFind(
          &sParse, &sCtx, (void*)sParse.pNewTable->aCol[sCtx.iCol].zName
      );
      assert( sCtx.iCol>=0 );
      if( sParse.pNewTable->iPKey==sCtx.iCol ){
        sCtx.iCol = -1;

      }
      sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
      for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){
        sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
      }
    }

    for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
      for(i=0; i<pFKey->nCol; i++){
        if( bFKOnly==0 && pFKey->aCol[i].iFrom==sCtx.iCol ){
          renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]);
        }
        if( 0==sqlite3_stricmp(pFKey->zTo, zTable)
         && 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld)
        ){
          renameTokenFind(&sParse, &sCtx, (void*)pFKey->aCol[i].zCol);

        }
      }
    }
  }else if( sParse.pNewIndex ){
    sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
    sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
  }else{
................................................................................
        if( 0==sqlite3_stricmp(zName, zOld) ){
          renameTokenFind(&sParse, &sCtx, (void*)zName);
        }
      }
    }
  }


  assert( nQuot>=nNew );
  zOut = sqlite3DbMallocZero(db, nSql + sCtx.nList*nQuot + 1);
  if( zOut ){
    int nOut = nSql;
    memcpy(zOut, zSql, nSql);
    while( sCtx.pList ){
      int iOff;                   /* Offset of token to replace in zOut */
................................................................................
      }
      memcpy(&zOut[iOff], zReplace, nReplace);
      sqlite3DbFree(db, pBest);
    }

    sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT);
    sqlite3DbFree(db, zOut);


  }

renameColumnFunc_done:








  if( sParse.pVdbe ){
    sqlite3VdbeFinalize(sParse.pVdbe);
  }
  sqlite3DeleteTable(db, sParse.pNewTable);
  if( sParse.pNewIndex ) sqlite3FreeIndex(db, sParse.pNewIndex);
  sqlite3DeleteTrigger(db, sParse.pNewTrigger);
  renameTokenFree(db, sParse.pRename);







|

>
|

|
>
>







 







>







 







>
>
>
>
>
>
|













>
>
>
>
>
>
>
>
>
>
>
>
>
>













|
>
>





>
>
>
>
>
>
>
>
>







 







>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>










>
>
|
|
|
<
>
|











>

>
>
>
>
>
>
>

<
>







 







<
<
<
<
<
<
<
<
<
<







|











>


>

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

|
|
|
|
|
|
|
|
|
>







 







>







 







>
>



>
>
>
>
>
>
>
>







840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
...
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
...
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
....
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067

1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090

1091
1092
1093
1094
1095
1096
1097
1098
....
1108
1109
1110
1111
1112
1113
1114










1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163


1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
....
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
....
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
  */
  zNew = sqlite3NameFromToken(db, pNew);
  if( !zNew ) goto exit_rename_column;
  assert( pNew->n>0 );
  bQuote = sqlite3Isquote(pNew->z[0]);
  sqlite3NestedParse(pParse, 
      "UPDATE \"%w\".%s SET "
      "sql = sqlite_rename_column(sql, %Q, %Q, %d, %Q, %d) "
      "WHERE name NOT LIKE 'sqlite_%%' AND ("
      "       type IN ('table', 'view') "
      "   OR (type IN ('index', 'trigger') AND tbl_name = %Q)"
      ")",
      zDb, MASTER_NAME, 
      zDb, pTab->zName, iCol, zNew, bQuote,
      pTab->zName
  );

  /* Drop and reload the database schema. */
  if( pParse->pVdbe ){
    sqlite3ChangeCookie(pParse, iSchema);
    sqlite3VdbeAddParseSchemaOp(pParse->pVdbe, iSchema, 0);
  }
................................................................................
** down into the Walker.
*/
typedef struct RenameCtx RenameCtx;
struct RenameCtx {
  RenameToken *pList;             /* List of tokens to overwrite */
  int nList;                      /* Number of tokens in pList */
  int iCol;                       /* Index of column being renamed */
  Table *pTab;                    /* Table being ALTERed */ 
  const char *zOld;               /* Old column name */
};

/*
** Add a new RenameToken object mapping parse tree element pPtr into
** token *pToken to the Parse object currently under construction.
*/
................................................................................
  RenameToken *p;
  for(p=pToken; p; p=pNext){
    pNext = p->pNext;
    sqlite3DbFree(db, p);
  }
}

/*
** Search the Parse object passed as the first argument for a RenameToken
** object associated with parse tree element pPtr. If found, remove it
** from the Parse object and add it to the list maintained by the
** RenameCtx object passed as the second argument.
*/
static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
  RenameToken **pp;
  for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){
    if( (*pp)->p==pPtr ){
      RenameToken *pToken = *pp;
      *pp = pToken->pNext;
      pToken->pNext = pCtx->pList;
      pCtx->pList = pToken;
      pCtx->nList++;
      break;
    }
  }
}

static int renameColumnSelectCb(Walker *pWalker, Select *p){
  return WRC_Continue;
}


/*
** This is a Walker expression callback.
**
** For every TK_COLUMN node in the expression tree, search to see
** if the column being references is the column being renamed by an
** ALTER TABLE statement.  If it is, then attach its associated
** RenameToken object to the list of RenameToken objects being
** constructed in RenameCtx object at pWalker->u.pRename.
*/
static int renameColumnExprCb(Walker *pWalker, Expr *pExpr){
  RenameCtx *p = pWalker->u.pRename;
  if( p->zOld && pExpr->op==TK_DOT ){
    Expr *pLeft = pExpr->pLeft;
    Expr *pRight = pExpr->pRight;
    assert( pLeft->op==TK_ID && pRight->op==TK_ID );
    if( 0==sqlite3_stricmp(pLeft->u.zToken, "old")
     || 0==sqlite3_stricmp(pLeft->u.zToken, "new")
    ){
      if( 0==sqlite3_stricmp(pRight->u.zToken, p->zOld) ){
        renameTokenFind(pWalker->pParse, p, (void*)pRight);
      }
    }
  }else if( pExpr->op==TK_COLUMN && pExpr->iColumn==p->iCol 
         && (p->pTab==0 || p->pTab==pExpr->pTab)
  ){
    renameTokenFind(pWalker->pParse, p, (void*)pExpr);
  }
  return WRC_Continue;
}

/*
** The RenameCtx contains a list of tokens that reference a column that
** is being renamed by an ALTER TABLE statement.  Return the "first"
** RenameToken in the RenameCtx and remove that RenameToken from the
** RenameContext.  "First" means the first RenameToken encountered when
** the input SQL from left to right.  Repeated calls to this routine
** return all column name tokens in the order that they are encountered
** in the SQL statement.
*/
static RenameToken *renameColumnTokenNext(RenameCtx *pCtx){
  RenameToken *pBest = pCtx->pList;
  RenameToken *pToken;
  RenameToken **pp;

  for(pToken=pBest->pNext; pToken; pToken=pToken->pNext){
    if( pToken->t.z>pBest->t.z ) pBest = pToken;
................................................................................
  for(pp=&pCtx->pList; *pp!=pBest; pp=&(*pp)->pNext);
  *pp = pBest->pNext;

  return pBest;
}

/*
** SQL function:
**
**     sqlite_rename_column(zSql, iCol, bQuote, zNew, zTable, zOld)
**
**   0. zSql:     SQL statement to rewrite
**   1. Database: Database name (e.g. "main")
**   2. Table:    Table name
**   3. iCol:     Index of column to rename
**   4. zNew:     New column name
**   5. bQuote: True if the new column name should be quoted
**
** Do a column rename operation on the CREATE statement given in zSql.
** The iCol-th column (left-most is 0) of table zTable is renamed from zCol
** into zNew.  The name should be quoted if bQuote is true.
**
** This function is used internally by the ALTER TABLE RENAME COLUMN command.
** Though accessible to application code, it is not intended for use by
** applications.  The existance of this function, and the way it works,
** is subject to change without notice.
**
** If any of the parameters are out-of-bounds, then simply return NULL.
** An out-of-bounds parameter can only occur when the application calls
** this function directly.  The parameters will always be well-formed when
** this routine is invoked by the bytecode for a legitimate ALTER TABLE
** statement.
*/
static void renameColumnFunc(
  sqlite3_context *context,
  int NotUsed,
  sqlite3_value **argv
){
  sqlite3 *db = sqlite3_context_db_handle(context);
  RenameCtx sCtx;
  const char *zSql = (const char*)sqlite3_value_text(argv[0]);
  int nSql = sqlite3_value_bytes(argv[0]);
  const char *zDb = (const char*)sqlite3_value_text(argv[1]);
  const char *zTable = (const char*)sqlite3_value_text(argv[2]);
  int iCol = sqlite3_value_int(argv[3]);
  const char *zNew = (const char*)sqlite3_value_text(argv[4]);
  int nNew = sqlite3_value_bytes(argv[4]);

  int bQuote = sqlite3_value_int(argv[5]);
  const char *zOld;

  int rc;
  char *zErr = 0;
  Parse sParse;
  Walker sWalker;
  Index *pIdx;
  char *zOut = 0;

  char *zQuot = 0;                /* Quoted version of zNew */
  int nQuot = 0;                  /* Length of zQuot in bytes */
  int i;
  Table *pTab;

  if( zSql==0 ) return;
  if( zNew==0 ) return;
  if( zTable==0 ) return;
  if( iCol<0 ) return;
  pTab = sqlite3FindTable(db, zTable, zDb);
  if( pTab==0 || iCol>=pTab->nCol ) return;
  zOld = pTab->aCol[iCol].zName;
  memset(&sCtx, 0, sizeof(sCtx));

  sCtx.iCol = ((iCol==pTab->iPKey) ? -1 : iCol);

  memset(&sParse, 0, sizeof(sParse));
  sParse.eParseMode = PARSE_MODE_RENAME_COLUMN;
  sParse.db = db;
  sParse.nQueryLoop = 1;
  rc = sqlite3RunParser(&sParse, zSql, &zErr);
  assert( sParse.pNewTable==0 || sParse.pNewIndex==0 );
................................................................................
    if( zQuot==0 ){
      rc = SQLITE_NOMEM;
    }else{
      nQuot = sqlite3Strlen30(zQuot);
    }
  }











  if( bQuote ){
    zNew = zQuot;
    nNew = nQuot;
  }

#ifdef SQLITE_DEBUG
  assert( sqlite3Strlen30(zSql)==nSql );
  if( rc==SQLITE_OK ){
    RenameToken *pToken;
    for(pToken=sParse.pRename; pToken; pToken=pToken->pNext){
      assert( pToken->t.z>=zSql && &pToken->t.z[pToken->t.n]<=&zSql[nSql] );
    }
  }
#endif

  /* Find tokens that need to be replaced. */
  memset(&sWalker, 0, sizeof(Walker));
  sWalker.pParse = &sParse;
  sWalker.xExprCallback = renameColumnExprCb;
  sWalker.xSelectCallback = renameColumnSelectCb;
  sWalker.u.pRename = &sCtx;

  if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
  if( sParse.pNewTable ){
    Select *pSelect = sParse.pNewTable->pSelect;
    if( pSelect ){
      sCtx.pTab = pTab;
      sParse.rc = SQLITE_OK;
      sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, 0);
      rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
      if( rc==SQLITE_OK ){
        sqlite3WalkSelect(&sWalker, pSelect);
      }else if( rc==SQLITE_ERROR ){
        /* Failed to resolve all symboles in the view. This is not an 
        ** error, but it will not be edited. */
        sqlite3DbFree(db, sParse.zErrMsg);
        sParse.zErrMsg = 0;
        rc = SQLITE_OK;
      }
      if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
    }else{
      /* A regular table */
      int bFKOnly = sqlite3_stricmp(zTable, sParse.pNewTable->zName);
      FKey *pFKey;
      assert( sParse.pNewTable->pSelect==0 );
      if( bFKOnly==0 ){
        renameTokenFind(
            &sParse, &sCtx, (void*)sParse.pNewTable->aCol[iCol].zName
        );


        if( sCtx.iCol<0 ){
          renameTokenFind(&sParse, &sCtx, (void*)&sParse.pNewTable->iPKey);
        }
        sqlite3WalkExprList(&sWalker, sParse.pNewTable->pCheck);
        for(pIdx=sParse.pNewTable->pIndex; pIdx; pIdx=pIdx->pNext){
          sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
        }
      }

      for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
        for(i=0; i<pFKey->nCol; i++){
          if( bFKOnly==0 && pFKey->aCol[i].iFrom==sCtx.iCol ){
            renameTokenFind(&sParse, &sCtx, (void*)&pFKey->aCol[i]);
          }
          if( 0==sqlite3_stricmp(pFKey->zTo, zTable)
           && 0==sqlite3_stricmp(pFKey->aCol[i].zCol, zOld)
          ){
            renameTokenFind(&sParse, &sCtx, (void*)pFKey->aCol[i].zCol);
          }
        }
      }
    }
  }else if( sParse.pNewIndex ){
    sqlite3WalkExprList(&sWalker, sParse.pNewIndex->aColExpr);
    sqlite3WalkExpr(&sWalker, sParse.pNewIndex->pPartIdxWhere);
  }else{
................................................................................
        if( 0==sqlite3_stricmp(zName, zOld) ){
          renameTokenFind(&sParse, &sCtx, (void*)zName);
        }
      }
    }
  }

  assert( rc==SQLITE_OK );
  assert( nQuot>=nNew );
  zOut = sqlite3DbMallocZero(db, nSql + sCtx.nList*nQuot + 1);
  if( zOut ){
    int nOut = nSql;
    memcpy(zOut, zSql, nSql);
    while( sCtx.pList ){
      int iOff;                   /* Offset of token to replace in zOut */
................................................................................
      }
      memcpy(&zOut[iOff], zReplace, nReplace);
      sqlite3DbFree(db, pBest);
    }

    sqlite3_result_text(context, zOut, -1, SQLITE_TRANSIENT);
    sqlite3DbFree(db, zOut);
  }else{
    rc = SQLITE_NOMEM;
  }

renameColumnFunc_done:
  if( rc!=SQLITE_OK ){
    if( zErr ){
      sqlite3_result_error(context, zErr, -1);
    }else{
      sqlite3_result_error_code(context, rc);
    }
  }

  if( sParse.pVdbe ){
    sqlite3VdbeFinalize(sParse.pVdbe);
  }
  sqlite3DeleteTable(db, sParse.pNewTable);
  if( sParse.pNewIndex ) sqlite3FreeIndex(db, sParse.pNewIndex);
  sqlite3DeleteTrigger(db, sParse.pNewTrigger);
  renameTokenFree(db, sParse.pRename);

Changes to src/build.c.

1366
1367
1368
1369
1370
1371
1372



1373
1374
1375
1376
1377
1378
1379
....
2168
2169
2170
2171
2172
2173
2174




2175

2176
2177
2178
2179
2180
2181
2182
    }
  }
  if( nTerm==1
   && pCol
   && sqlite3StrICmp(sqlite3ColumnType(pCol,""), "INTEGER")==0
   && sortOrder!=SQLITE_SO_DESC
  ){



    pTab->iPKey = iCol;
    pTab->keyConf = (u8)onError;
    assert( autoInc==0 || autoInc==1 );
    pTab->tabFlags |= autoInc*TF_Autoincrement;
    if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder;
  }else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
................................................................................
  if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail;

  /* Make a copy of the entire SELECT statement that defines the view.
  ** This will force all the Expr.token.z values to be dynamically
  ** allocated rather than point to the input string - which means that
  ** they will persist after the current sqlite3_exec() call returns.
  */




  p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);

  p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
  if( db->mallocFailed ) goto create_view_fail;

  /* Locate the end of the CREATE VIEW statement.  Make sEnd point to
  ** the end.
  */
  sEnd = pParse->sLastToken;







>
>
>







 







>
>
>
>
|
>







1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
....
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
    }
  }
  if( nTerm==1
   && pCol
   && sqlite3StrICmp(sqlite3ColumnType(pCol,""), "INTEGER")==0
   && sortOrder!=SQLITE_SO_DESC
  ){
    if( IN_RENAME_COLUMN && pList ){
      sqlite3MoveRenameToken(pParse, &pTab->iPKey, pList->a[0].pExpr);
    }
    pTab->iPKey = iCol;
    pTab->keyConf = (u8)onError;
    assert( autoInc==0 || autoInc==1 );
    pTab->tabFlags |= autoInc*TF_Autoincrement;
    if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder;
  }else if( autoInc ){
#ifndef SQLITE_OMIT_AUTOINCREMENT
................................................................................
  if( sqlite3FixSelect(&sFix, pSelect) ) goto create_view_fail;

  /* Make a copy of the entire SELECT statement that defines the view.
  ** This will force all the Expr.token.z values to be dynamically
  ** allocated rather than point to the input string - which means that
  ** they will persist after the current sqlite3_exec() call returns.
  */
  if( IN_RENAME_COLUMN ){
    p->pSelect = pSelect;
    pSelect = 0;
  }else{
    p->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE);
  }
  p->pCheck = sqlite3ExprListDup(db, pCNames, EXPRDUP_REDUCE);
  if( db->mallocFailed ) goto create_view_fail;

  /* Locate the end of the CREATE VIEW statement.  Make sEnd point to
  ** the end.
  */
  sEnd = pParse->sLastToken;

Changes to src/insert.c.

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
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
....
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332



1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
....
1437
1438
1439
1440
1441
1442
1443

1444
1445
1446
1447
1448
1449
1450
1451
1452





1453
1454
1455
1456
1457
1458
1459
....
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
....
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518

1519
1520
1521
1522
1523
1524
1525
....
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
....
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641

1642
1643




1644
1645
1646
1647
1648
1649
1650
....
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
....
1839
1840
1841
1842
1843
1844
1845

1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856

1857

1858
1859
1860
1861
1862
1863
1864
  testcase( w.eCode==0 );
  testcase( w.eCode==CKCNSTRNT_COLUMN );
  testcase( w.eCode==CKCNSTRNT_ROWID );
  testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) );
  return !w.eCode;
}

/*
** An instance of the ConstraintAddr object remembers the byte-code addresses
** for sections of the constraint checks that deal with uniqueness constraints
** on the rowid and on the upsert constraint.
**
** This information is passed into checkReorderConstraintChecks() to insert
** some OP_Goto operations so that the rowid and upsert constraints occur
** in the correct order relative to other constraints.
*/
typedef struct ConstraintAddr ConstraintAddr;
struct ConstraintAddr {
  int ipkTop;          /* Subroutine for rowid constraint check */
  int upsertTop;       /* Label for upsert constraint check subroutine */
  int upsertTop2;      /* Copy of upsertTop not cleared by the call */
  int upsertBtm;       /* upsert constraint returns to this label */
  int ipkBtm;          /* Return opcode rowid constraint check */
};

/*
** Generate any OP_Goto operations needed to cause constraints to be
** run that haven't already been run.
*/
static void reorderConstraintChecks(Vdbe *v, ConstraintAddr *p){
  if( p->upsertTop ){
    testcase( sqlite3VdbeLabelHasBeenResolved(v, p->upsertTop) );
    sqlite3VdbeGoto(v, p->upsertTop);
    VdbeComment((v, "call upsert subroutine"));
    sqlite3VdbeResolveLabel(v, p->upsertBtm);
    p->upsertTop = 0;
  }
  if( p->ipkTop ){
    sqlite3VdbeGoto(v, p->ipkTop);
    VdbeComment((v, "call rowid unique-check subroutine"));
    sqlite3VdbeJumpHere(v, p->ipkBtm);
    p->ipkTop = 0;
  }
}

/*
** Generate code to do constraint checks prior to an INSERT or an UPDATE
** on table pTab.
**
** The regNewData parameter is the first register in a range that contains
** the data to be inserted or the data after the update.  There will be
** pTab->nCol+1 registers in this range.  The first register (the one
................................................................................
  int i;               /* loop counter */
  int ix;              /* Index loop counter */
  int nCol;            /* Number of columns */
  int onError;         /* Conflict resolution strategy */
  int addr1;           /* Address of jump instruction */
  int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
  int nPkField;        /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
  ConstraintAddr sAddr;/* Address information for constraint reordering */
  Index *pUpIdx = 0;   /* Index to which to apply the upsert */
  u8 isUpdate;         /* True if this is an UPDATE operation */
  u8 bAffinityDone = 0;  /* True if the OP_Affinity operation has been run */
  int upsertBypass = 0;  /* Address of Goto to bypass upsert subroutine */




  isUpdate = regOldData!=0;
  db = pParse->db;
  v = sqlite3GetVdbe(pParse);
  assert( v!=0 );
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  nCol = pTab->nCol;
  memset(&sAddr, 0, sizeof(sAddr));
  
  /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
  ** normal rowid tables.  nPkField is the number of key fields in the 
  ** pPk index or 1 for a rowid table.  In other words, nPkField is the
  ** number of fields in the true primary key of the table. */
  if( HasRowid(pTab) ){
    pPk = 0;
................................................................................
    pParse->iSelfTab = 0;
  }
#endif /* !defined(SQLITE_OMIT_CHECK) */

  /* UNIQUE and PRIMARY KEY constraints should be handled in the following
  ** order:
  **

  **   (1)  OE_Abort, OE_Fail, OE_Rollback, OE_Ignore
  **   (2)  OE_Update
  **   (3)  OE_Replace
  **
  ** OE_Fail and OE_Ignore must happen before any changes are made.
  ** OE_Update guarantees that only a single row will change, so it
  ** must happen before OE_Replace.  Technically, OE_Abort and OE_Rollback
  ** could happen in any order, but they are grouped up front for
  ** convenience.





  **
  ** Constraint checking code is generated in this order:
  **   (A)  The rowid constraint
  **   (B)  Unique index constraints that do not have OE_Replace as their
  **        default conflict resolution strategy
  **   (C)  Unique index that do use OE_Replace by default.
  **
................................................................................
    if( pUpsert->pUpsertTarget==0 ){
      /* An ON CONFLICT DO NOTHING clause, without a constraint-target.
      ** Make all unique constraint resolution be OE_Ignore */
      assert( pUpsert->pUpsertSet==0 );
      overrideError = OE_Ignore;
      pUpsert = 0;
    }else if( (pUpIdx = pUpsert->pUpsertIdx)!=0 ){
      /* If the constraint-target is on some column other than
      ** then ROWID, then we might need to move the UPSERT around
      ** so that it occurs in the correct order. */
      sAddr.upsertTop = sAddr.upsertTop2 = sqlite3VdbeMakeLabel(v);
      sAddr.upsertBtm = sqlite3VdbeMakeLabel(v);
    }
  }

  /* If rowid is changing, make sure the new rowid does not previously
  ** exist in the table.
  */
  if( pkChng && pPk==0 ){
................................................................................
    }

    /* If the response to a rowid conflict is REPLACE but the response
    ** to some other UNIQUE constraint is FAIL or IGNORE, then we need
    ** to defer the running of the rowid conflict checking until after
    ** the UNIQUE constraints have run.
    */
    assert( OE_Update>OE_Replace );
    assert( OE_Ignore<OE_Replace );
    assert( OE_Fail<OE_Replace );
    assert( OE_Abort<OE_Replace );
    assert( OE_Rollback<OE_Replace );
    if( onError>=OE_Replace
     && (pUpsert || onError!=overrideError)
     && pTab->pIndex
    ){
      sAddr.ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1;

    }

    if( isUpdate ){
      /* pkChng!=0 does not mean that the rowid has changed, only that
      ** it might have changed.  Skip the conflict logic below if the rowid
      ** is unchanged. */
      sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData);
................................................................................
      case OE_Ignore: {
        testcase( onError==OE_Ignore );
        sqlite3VdbeGoto(v, ignoreDest);
        break;
      }
    }
    sqlite3VdbeResolveLabel(v, addrRowidOk);
    if( sAddr.ipkTop ){
      sAddr.ipkBtm = sqlite3VdbeAddOp0(v, OP_Goto);
      sqlite3VdbeJumpHere(v, sAddr.ipkTop-1);
    }
  }

  /* Test all UNIQUE constraints by creating entries for each UNIQUE
  ** index and making sure that duplicate entries do not already exist.
  ** Compute the revised record entries for indices as we go.
  **
................................................................................
  for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){
    int regIdx;          /* Range of registers hold conent for pIdx */
    int regR;            /* Range of registers holding conflicting PK */
    int iThisCur;        /* Cursor for this UNIQUE index */
    int addrUniqueOk;    /* Jump here if the UNIQUE constraint is satisfied */

    if( aRegIdx[ix]==0 ) continue;  /* Skip indices that do not change */
    if( bAffinityDone==0 ){
      sqlite3TableAffinity(v, pTab, regNewData+1);
      bAffinityDone = 1;
    }
    if( pUpIdx==pIdx ){
      addrUniqueOk = sAddr.upsertBtm;
      upsertBypass = sqlite3VdbeGoto(v, 0);
      VdbeComment((v, "Skip upsert subroutine"));
      sqlite3VdbeResolveLabel(v, sAddr.upsertTop2);

    }else{
      addrUniqueOk = sqlite3VdbeMakeLabel(v);




    }
    VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName));
    iThisCur = iIdxCur+ix;


    /* Skip partial indices for which the WHERE clause is not true */
    if( pIdx->pPartIdxWhere ){
................................................................................
      if( pUpsert->pUpsertSet==0 ){
        onError = OE_Ignore;  /* DO NOTHING is the same as INSERT OR IGNORE */
      }else{
        onError = OE_Update;  /* DO UPDATE */
      }
    }

    /* Invoke subroutines to handle IPK replace and upsert prior to running
    ** the first REPLACE constraint check. */
    if( onError==OE_Replace ){
      testcase( sAddr.ipkTop );
      testcase( sAddr.upsertTop
             && sqlite3VdbeLabelHasBeenResolved(v,sAddr.upsertTop) );
      reorderConstraintChecks(v, &sAddr);
    }

    /* Collision detection may be omitted if all of the following are true:
    **   (1) The conflict resolution algorithm is REPLACE
    **   (2) The table is a WITHOUT ROWID table
    **   (3) There are no secondary indexes on the table
    **   (4) No delete triggers need to be fired if there is a conflict
    **   (5) No FK constraint counters need to be updated if a conflict occurs.
    */ 
................................................................................
            regR, nPkField, 0, OE_Replace,
            (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
        seenReplace = 1;
        break;
      }
    }
    if( pUpIdx==pIdx ){

      sqlite3VdbeJumpHere(v, upsertBypass);
    }else{
      sqlite3VdbeResolveLabel(v, addrUniqueOk);
    }
    if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);

  }
  testcase( sAddr.ipkTop!=0 );
  testcase( sAddr.upsertTop
         && sqlite3VdbeLabelHasBeenResolved(v,sAddr.upsertTop) );
  reorderConstraintChecks(v, &sAddr);

  

  *pbMayReplace = seenReplace;
  VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace));
}

#ifdef SQLITE_ENABLE_NULL_TRIM
/*
** Change the P5 operand on the last opcode (which should be an OP_MakeRecord)







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<




>
>
>







<







 







>
|
<







>
>
>
>
>







 







|
|
|
|
<







 







|
<
<
<
<
<
|
|

|
>







 







|
|
|







 







<
<
<
<

|


<
>


>
>
>
>







 







<
<
<
<
<
<
<
<
<







 







>





|
|
|
|
|
|
>
|
>







1174
1175
1176
1177
1178
1179
1180






































1181
1182
1183
1184
1185
1186
1187
....
1283
1284
1285
1286
1287
1288
1289

1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303

1304
1305
1306
1307
1308
1309
1310
....
1400
1401
1402
1403
1404
1405
1406
1407
1408

1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
....
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444

1445
1446
1447
1448
1449
1450
1451
....
1469
1470
1471
1472
1473
1474
1475
1476





1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
....
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
....
1589
1590
1591
1592
1593
1594
1595




1596
1597
1598
1599

1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
....
1672
1673
1674
1675
1676
1677
1678









1679
1680
1681
1682
1683
1684
1685
....
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
  testcase( w.eCode==0 );
  testcase( w.eCode==CKCNSTRNT_COLUMN );
  testcase( w.eCode==CKCNSTRNT_ROWID );
  testcase( w.eCode==(CKCNSTRNT_ROWID|CKCNSTRNT_COLUMN) );
  return !w.eCode;
}







































/*
** Generate code to do constraint checks prior to an INSERT or an UPDATE
** on table pTab.
**
** The regNewData parameter is the first register in a range that contains
** the data to be inserted or the data after the update.  There will be
** pTab->nCol+1 registers in this range.  The first register (the one
................................................................................
  int i;               /* loop counter */
  int ix;              /* Index loop counter */
  int nCol;            /* Number of columns */
  int onError;         /* Conflict resolution strategy */
  int addr1;           /* Address of jump instruction */
  int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
  int nPkField;        /* Number of fields in PRIMARY KEY. 1 for ROWID tables */

  Index *pUpIdx = 0;   /* Index to which to apply the upsert */
  u8 isUpdate;         /* True if this is an UPDATE operation */
  u8 bAffinityDone = 0;  /* True if the OP_Affinity operation has been run */
  int upsertBypass = 0;  /* Address of Goto to bypass upsert subroutine */
  int upsertJump = 0;    /* Address of Goto that jumps into upsert subroutine */
  int ipkTop = 0;        /* Top of the IPK uniqueness check */
  int ipkBottom = 0;     /* OP_Goto at the end of the IPK uniqueness check */

  isUpdate = regOldData!=0;
  db = pParse->db;
  v = sqlite3GetVdbe(pParse);
  assert( v!=0 );
  assert( pTab->pSelect==0 );  /* This table is not a VIEW */
  nCol = pTab->nCol;

  
  /* pPk is the PRIMARY KEY index for WITHOUT ROWID tables and NULL for
  ** normal rowid tables.  nPkField is the number of key fields in the 
  ** pPk index or 1 for a rowid table.  In other words, nPkField is the
  ** number of fields in the true primary key of the table. */
  if( HasRowid(pTab) ){
    pPk = 0;
................................................................................
    pParse->iSelfTab = 0;
  }
#endif /* !defined(SQLITE_OMIT_CHECK) */

  /* UNIQUE and PRIMARY KEY constraints should be handled in the following
  ** order:
  **
  **   (1)  OE_Update
  **   (2)  OE_Abort, OE_Fail, OE_Rollback, OE_Ignore

  **   (3)  OE_Replace
  **
  ** OE_Fail and OE_Ignore must happen before any changes are made.
  ** OE_Update guarantees that only a single row will change, so it
  ** must happen before OE_Replace.  Technically, OE_Abort and OE_Rollback
  ** could happen in any order, but they are grouped up front for
  ** convenience.
  **
  ** 2018-08-14: Ticket https://www.sqlite.org/src/info/908f001483982c43
  ** The order of constraints used to have OE_Update as (2) and OE_Abort
  ** and so forth as (1). But apparently PostgreSQL checks the OE_Update
  ** constraint before any others, so it had to be moved.
  **
  ** Constraint checking code is generated in this order:
  **   (A)  The rowid constraint
  **   (B)  Unique index constraints that do not have OE_Replace as their
  **        default conflict resolution strategy
  **   (C)  Unique index that do use OE_Replace by default.
  **
................................................................................
    if( pUpsert->pUpsertTarget==0 ){
      /* An ON CONFLICT DO NOTHING clause, without a constraint-target.
      ** Make all unique constraint resolution be OE_Ignore */
      assert( pUpsert->pUpsertSet==0 );
      overrideError = OE_Ignore;
      pUpsert = 0;
    }else if( (pUpIdx = pUpsert->pUpsertIdx)!=0 ){
      /* If the constraint-target uniqueness check must be run first.
      ** Jump to that uniqueness check now */
      upsertJump = sqlite3VdbeAddOp0(v, OP_Goto);
      VdbeComment((v, "UPSERT constraint goes first"));

    }
  }

  /* If rowid is changing, make sure the new rowid does not previously
  ** exist in the table.
  */
  if( pkChng && pPk==0 ){
................................................................................
    }

    /* If the response to a rowid conflict is REPLACE but the response
    ** to some other UNIQUE constraint is FAIL or IGNORE, then we need
    ** to defer the running of the rowid conflict checking until after
    ** the UNIQUE constraints have run.
    */
    if( onError==OE_Replace      /* IPK rule is REPLACE */





     && onError!=overrideError   /* Rules for other contraints are different */
     && pTab->pIndex             /* There exist other constraints */
    ){
      ipkTop = sqlite3VdbeAddOp0(v, OP_Goto)+1;
      VdbeComment((v, "defer IPK REPLACE until last"));
    }

    if( isUpdate ){
      /* pkChng!=0 does not mean that the rowid has changed, only that
      ** it might have changed.  Skip the conflict logic below if the rowid
      ** is unchanged. */
      sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRowidOk, regOldData);
................................................................................
      case OE_Ignore: {
        testcase( onError==OE_Ignore );
        sqlite3VdbeGoto(v, ignoreDest);
        break;
      }
    }
    sqlite3VdbeResolveLabel(v, addrRowidOk);
    if( ipkTop ){
      ipkBottom = sqlite3VdbeAddOp0(v, OP_Goto);
      sqlite3VdbeJumpHere(v, ipkTop-1);
    }
  }

  /* Test all UNIQUE constraints by creating entries for each UNIQUE
  ** index and making sure that duplicate entries do not already exist.
  ** Compute the revised record entries for indices as we go.
  **
................................................................................
  for(ix=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, ix++){
    int regIdx;          /* Range of registers hold conent for pIdx */
    int regR;            /* Range of registers holding conflicting PK */
    int iThisCur;        /* Cursor for this UNIQUE index */
    int addrUniqueOk;    /* Jump here if the UNIQUE constraint is satisfied */

    if( aRegIdx[ix]==0 ) continue;  /* Skip indices that do not change */




    if( pUpIdx==pIdx ){
      addrUniqueOk = upsertJump+1;
      upsertBypass = sqlite3VdbeGoto(v, 0);
      VdbeComment((v, "Skip upsert subroutine"));

      sqlite3VdbeJumpHere(v, upsertJump);
    }else{
      addrUniqueOk = sqlite3VdbeMakeLabel(v);
    }
    if( bAffinityDone==0 && (pUpIdx==0 || pUpIdx==pIdx) ){
      sqlite3TableAffinity(v, pTab, regNewData+1);
      bAffinityDone = 1;
    }
    VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName));
    iThisCur = iIdxCur+ix;


    /* Skip partial indices for which the WHERE clause is not true */
    if( pIdx->pPartIdxWhere ){
................................................................................
      if( pUpsert->pUpsertSet==0 ){
        onError = OE_Ignore;  /* DO NOTHING is the same as INSERT OR IGNORE */
      }else{
        onError = OE_Update;  /* DO UPDATE */
      }
    }










    /* Collision detection may be omitted if all of the following are true:
    **   (1) The conflict resolution algorithm is REPLACE
    **   (2) The table is a WITHOUT ROWID table
    **   (3) There are no secondary indexes on the table
    **   (4) No delete triggers need to be fired if there is a conflict
    **   (5) No FK constraint counters need to be updated if a conflict occurs.
    */ 
................................................................................
            regR, nPkField, 0, OE_Replace,
            (pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
        seenReplace = 1;
        break;
      }
    }
    if( pUpIdx==pIdx ){
      sqlite3VdbeGoto(v, upsertJump+1);
      sqlite3VdbeJumpHere(v, upsertBypass);
    }else{
      sqlite3VdbeResolveLabel(v, addrUniqueOk);
    }
    if( regR!=regIdx ) sqlite3ReleaseTempRange(pParse, regR, nPkField);
  }

  /* If the IPK constraint is a REPLACE, run it last */
  if( ipkTop ){
    sqlite3VdbeGoto(v, ipkTop+1);
    VdbeComment((v, "Do IPK REPLACE"));
    sqlite3VdbeJumpHere(v, ipkBottom);
  }

  *pbMayReplace = seenReplace;
  VdbeModuleComment((v, "END: GenCnstCks(%d)", seenReplace));
}

#ifdef SQLITE_ENABLE_NULL_TRIM
/*
** Change the P5 operand on the last opcode (which should be an OP_MakeRecord)

Changes to src/os_unix.c.

698
699
700
701
702
703
704











705
706
707

708
709
710

711
712
713
714
715
716
717
....
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123




1124
1125
1126
1127
1128
1129
1130
1131

1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
....
1143
1144
1145
1146
1147
1148
1149
1150















1151
1152
1153
1154
1155
1156
1157
....
1249
1250
1251
1252
1253
1254
1255

1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273

1274
1275
1276
1277

1278

1279
1280
1281
1282
1283
1284
1285
....
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
....
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
....
1822
1823
1824
1825
1826
1827
1828

1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
....
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997

1998

1999
2000
2001
2002
2003
2004
2005
....
2062
2063
2064
2065
2066
2067
2068



2069
2070

2071
2072
2073
2074
2075
2076

2077
2078
2079
2080
2081
2082
2083
2084

2085
2086
2087
2088
2089
2090
2091
....
2675
2676
2677
2678
2679
2680
2681

2682
2683
2684
2685
2686
2687
2688
....
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128

3129

3130
3131
3132
3133
3134
3135
3136
3137
3138
3139
3140

3141



3142
3143
3144
3145
3146
3147
3148


3149
3150
3151
3152
3153
3154
3155
....
4447
4448
4449
4450
4451
4452
4453

4454
4455
4456
4457
4458
4459
4460
....
4829
4830
4831
4832
4833
4834
4835

4836
4837
4838
4839
4840
4841
4842
....
4870
4871
4872
4873
4874
4875
4876

4877
4878
4879
4880
4881
4882
4883
....
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
....
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708


5709
5710
5711
5712
5713
5714

5715
5716
5717
5718
5719
5720
5721
** Function unixMutexHeld() is used to assert() that the global mutex 
** is held when required. This function is only used as part of assert() 
** statements. e.g.
**
**   unixEnterMutex()
**     assert( unixMutexHeld() );
**   unixEnterLeave()











*/
static sqlite3_mutex *unixBigLock = 0;
static void unixEnterMutex(void){

  sqlite3_mutex_enter(unixBigLock);
}
static void unixLeaveMutex(void){

  sqlite3_mutex_leave(unixBigLock);
}
#ifdef SQLITE_DEBUG
static int unixMutexHeld(void) {
  return sqlite3_mutex_held(unixBigLock);
}
#endif
................................................................................
**
** A single inode can have multiple file descriptors, so each unixFile
** structure contains a pointer to an instance of this object and this
** object keeps a count of the number of unixFile pointing to it.
**
** Mutex rules:
**
**  (1) The pLockMutex mutex must be held in order to read or write
**      any of the locking fields:
**          nShared, nLock, eFileLock, or bProcessLock
**
**  (2) When nRef>0, then the following fields are unchanging and can
**      be read (but not written) without holding any mutex:
**          fileId, pLockMutex
**
**  (3) With the exceptions above, all the fields may only be read
**      or written while holding the global unixBigLock mutex.




*/
struct unixInodeInfo {
  struct unixFileId fileId;       /* The lookup key */
  sqlite3_mutex *pLockMutex;      /* Hold this mutex for... */
  int nShared;                      /* Number of SHARED locks held */
  int nLock;                        /* Number of outstanding file locks */
  unsigned char eFileLock;          /* One of SHARED_LOCK, RESERVED_LOCK etc. */
  unsigned char bProcessLock;       /* An exclusive process lock is held */

  int nRef;                       /* Number of pointers to this structure */
  unixShmNode *pShmNode;          /* Shared memory associated with this inode */
  UnixUnusedFd *pUnused;          /* Unused file descriptors to close */
  unixInodeInfo *pNext;           /* List of all unixInodeInfo objects */
  unixInodeInfo *pPrev;           /*    .... doubly linked */
#if SQLITE_ENABLE_LOCKING_STYLE
  unsigned long long sharedByte;  /* for AFP simulated shared lock */
#endif
#if OS_VXWORKS
  sem_t *pSem;                    /* Named POSIX semaphore */
................................................................................
#endif
};

/*
** A lists of all unixInodeInfo objects.
*/
static unixInodeInfo *inodeList = 0;  /* All unixInodeInfo objects */
static unsigned int nUnusedFd = 0;    /* Total unused file descriptors */
















/*
**
** This function - unixLogErrorAtLine(), is only ever called via the macro
** unixLogError().
**
** It is invoked after an error occurs in an OS function and errno has been
................................................................................
/*
** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
*/ 
static void closePendingFds(unixFile *pFile){
  unixInodeInfo *pInode = pFile->pInode;
  UnixUnusedFd *p;
  UnixUnusedFd *pNext;

  for(p=pInode->pUnused; p; p=pNext){
    pNext = p->pNext;
    robust_close(pFile, p->fd, __LINE__);
    sqlite3_free(p);
    nUnusedFd--;
  }
  pInode->pUnused = 0;
}

/*
** Release a unixInodeInfo structure previously allocated by findInodeInfo().
**
** The mutex entered using the unixEnterMutex() function must be held
** when this function is called.
*/
static void releaseInodeInfo(unixFile *pFile){
  unixInodeInfo *pInode = pFile->pInode;
  assert( unixMutexHeld() );

  if( ALWAYS(pInode) ){
    pInode->nRef--;
    if( pInode->nRef==0 ){
      assert( pInode->pShmNode==0 );

      closePendingFds(pFile);

      if( pInode->pPrev ){
        assert( pInode->pPrev->pNext==pInode );
        pInode->pPrev->pNext = pInode->pNext;
      }else{
        assert( inodeList==pInode );
        inodeList = pInode->pNext;
      }
................................................................................
        assert( pInode->pNext->pPrev==pInode );
        pInode->pNext->pPrev = pInode->pPrev;
      }
      sqlite3_mutex_free(pInode->pLockMutex);
      sqlite3_free(pInode);
    }
  }
  assert( inodeList!=0 || nUnusedFd==0 );
}

/*
** Given a file descriptor, locate the unixInodeInfo object that
** describes that file descriptor.  Create a new one if necessary.  The
** return value might be uninitialized if an error occurs.
**
................................................................................
  memset(&fileId, 0, sizeof(fileId));
  fileId.dev = statbuf.st_dev;
#if OS_VXWORKS
  fileId.pId = pFile->pId;
#else
  fileId.ino = (u64)statbuf.st_ino;
#endif
  assert( inodeList!=0 || nUnusedFd==0 );
  pInode = inodeList;
  while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
    pInode = pInode->pNext;
  }
  if( pInode==0 ){
    pInode = sqlite3_malloc64( sizeof(*pInode) );
    if( pInode==0 ){
................................................................................
/*
** Add the file descriptor used by file handle pFile to the corresponding
** pUnused list.
*/
static void setPendingFd(unixFile *pFile){
  unixInodeInfo *pInode = pFile->pInode;
  UnixUnusedFd *p = pFile->pPreallocatedUnused;

  p->pNext = pInode->pUnused;
  pInode->pUnused = p;
  pFile->h = -1;
  pFile->pPreallocatedUnused = 0;
  nUnusedFd++;
}

/*
** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
................................................................................

    /* Decrement the count of locks against this same file.  When the
    ** count reaches zero, close any other file descriptors whose close
    ** was deferred because of outstanding locks.
    */
    pInode->nLock--;
    assert( pInode->nLock>=0 );
    if( pInode->nLock==0 ){
      closePendingFds(pFile);
    }
  }

end_unlock:
  sqlite3_mutex_leave(pInode->pLockMutex);

  if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;

  return rc;
}

/*
** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
** must be either NO_LOCK or SHARED_LOCK.
**
................................................................................

/*
** Close a file.
*/
static int unixClose(sqlite3_file *id){
  int rc = SQLITE_OK;
  unixFile *pFile = (unixFile *)id;



  verifyDbFile(pFile);
  unixUnlock(id, NO_LOCK);

  unixEnterMutex();

  /* unixFile.pInode is always valid here. Otherwise, a different close
  ** routine (e.g. nolockClose()) would be called instead.
  */
  assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );

  if( ALWAYS(pFile->pInode) && pFile->pInode->nLock ){
    /* If there are outstanding locks, do not actually close the file just
    ** yet because that would clear those locks.  Instead, add the file
    ** descriptor to pInode->pUnused list.  It will be automatically closed 
    ** when the last lock is cleared.
    */
    setPendingFd(pFile);
  }

  releaseInodeInfo(pFile);
  rc = closeUnixFile(id);
  unixLeaveMutex();
  return rc;
}

/************** End of the posix advisory lock implementation *****************
................................................................................
 ** Close a file.
 */
static int semXClose(sqlite3_file *id) {
  if( id ){
    unixFile *pFile = (unixFile*)id;
    semXUnlock(id, NO_LOCK);
    assert( pFile );

    unixEnterMutex();
    releaseInodeInfo(pFile);
    unixLeaveMutex();
    closeUnixFile(id);
  }
  return SQLITE_OK;
}
................................................................................
        pInode->eFileLock = NO_LOCK;
        pFile->eFileLock = NO_LOCK;
      }
    }
    if( rc==SQLITE_OK ){
      pInode->nLock--;
      assert( pInode->nLock>=0 );
      if( pInode->nLock==0 ){
        closePendingFds(pFile);
      }
    }
  }
  
  sqlite3_mutex_leave(pInode->pLockMutex);

  if( rc==SQLITE_OK ) pFile->eFileLock = eFileLock;

  return rc;
}

/*
** Close a file & cleanup AFP specific locking context 
*/
static int afpClose(sqlite3_file *id) {
  int rc = SQLITE_OK;
  unixFile *pFile = (unixFile*)id;
  assert( id!=0 );
  afpUnlock(id, NO_LOCK);

  unixEnterMutex();



  if( pFile->pInode && pFile->pInode->nLock ){
    /* If there are outstanding locks, do not actually close the file just
    ** yet because that would clear those locks.  Instead, add the file
    ** descriptor to pInode->aPending.  It will be automatically closed when
    ** the last lock is cleared.
    */
    setPendingFd(pFile);


  }
  releaseInodeInfo(pFile);
  sqlite3_free(pFile->lockingContext);
  rc = closeUnixFile(id);
  unixLeaveMutex();
  return rc;
}
................................................................................
  if( p==0 ) return SQLITE_NOMEM_BKPT;
  memset(p, 0, sizeof(*p));
  assert( pDbFd->pShm==0 );

  /* Check to see if a unixShmNode object already exists. Reuse an existing
  ** one if present. Create a new one if necessary.
  */

  unixEnterMutex();
  pInode = pDbFd->pInode;
  pShmNode = pInode->pShmNode;
  if( pShmNode==0 ){
    struct stat sStat;                 /* fstat() info for database file */
#ifndef SQLITE_SHM_DIRECTORY
    const char *zBasePath = pDbFd->zPath;
................................................................................
** any load or store begun after the barrier.
*/
static void unixShmBarrier(
  sqlite3_file *fd                /* Database file holding the shared memory */
){
  UNUSED_PARAMETER(fd);
  sqlite3MemoryBarrier();         /* compiler-defined memory barrier */

  unixEnterMutex();               /* Also mutex, for redundancy */
  unixLeaveMutex();
}

/*
** Close a connection to shared-memory.  Delete the underlying 
** storage if deleteFlag is true.
................................................................................
  /* Free the connection p */
  sqlite3_free(p);
  pDbFd->pShm = 0;
  sqlite3_mutex_leave(pShmNode->mutex);

  /* If pShmNode->nRef has reached 0, then close the underlying
  ** shared-memory file, too */

  unixEnterMutex();
  assert( pShmNode->nRef>0 );
  pShmNode->nRef--;
  if( pShmNode->nRef==0 ){
    if( deleteFlag && pShmNode->h>=0 ){
      osUnlink(pShmNode->zFilename);
    }
................................................................................
  unixUnlock,               /* xUnlock method */
  unixCheckReservedLock,    /* xCheckReservedLock method */
  unixShmMap                /* xShmMap method */
)
IOMETHODS(
  nolockIoFinder,           /* Finder function name */
  nolockIoMethods,          /* sqlite3_io_methods object name */
  3,                        /* shared memory is disabled */
  nolockClose,              /* xClose method */
  nolockLock,               /* xLock method */
  nolockUnlock,             /* xUnlock method */
  nolockCheckReservedLock,  /* xCheckReservedLock method */
  0                         /* xShmMap method */
)
IOMETHODS(
................................................................................
  ** almost certain that an open() call on the same path will also fail.
  ** For this reason, if an error occurs in the stat() call here, it is
  ** ignored and -1 is returned. The caller will try to open a new file
  ** descriptor on the same path, fail, and return an error to SQLite.
  **
  ** Even if a subsequent open() call does succeed, the consequences of
  ** not searching for a reusable file descriptor are not dire.  */
  if( nUnusedFd>0 && 0==osStat(zPath, &sStat) ){
    unixInodeInfo *pInode;

    pInode = inodeList;
    while( pInode && (pInode->fileId.dev!=sStat.st_dev
                     || pInode->fileId.ino!=(u64)sStat.st_ino) ){
       pInode = pInode->pNext;
    }
    if( pInode ){
      UnixUnusedFd **pp;


      for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
      pUnused = *pp;
      if( pUnused ){
        nUnusedFd--;
        *pp = pUnused->pNext;
      }

    }
  }
  unixLeaveMutex();
#endif    /* if !OS_VXWORKS */
  return pUnused;
}








>
>
>
>
>
>
>
>
>
>
>



>



>







 







|

|







>
>
>
>








>


<







 







<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>




<













>




>

>







 







<







 







<







 







>




<







 







<
|
<




>
|
>







 







>
>
>


>






>
|







>







 







>







 







<
|
<




>
|
>











>

>
>
>
|
|
|
|
|
|
|
>
>







 







>







 







>







 







>







 







|







 







|









>
>



<


>







698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
....
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151

1152
1153
1154
1155
1156
1157
1158
....
1160
1161
1162
1163
1164
1165
1166

1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
....
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291

1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
....
1321
1322
1323
1324
1325
1326
1327

1328
1329
1330
1331
1332
1333
1334
....
1390
1391
1392
1393
1394
1395
1396

1397
1398
1399
1400
1401
1402
1403
....
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865

1866
1867
1868
1869
1870
1871
1872
....
2016
2017
2018
2019
2020
2021
2022

2023

2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
....
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
....
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
....
3154
3155
3156
3157
3158
3159
3160

3161

3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
....
4492
4493
4494
4495
4496
4497
4498
4499
4500
4501
4502
4503
4504
4505
4506
....
4875
4876
4877
4878
4879
4880
4881
4882
4883
4884
4885
4886
4887
4888
4889
....
4917
4918
4919
4920
4921
4922
4923
4924
4925
4926
4927
4928
4929
4930
4931
....
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
....
5740
5741
5742
5743
5744
5745
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761

5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
** Function unixMutexHeld() is used to assert() that the global mutex 
** is held when required. This function is only used as part of assert() 
** statements. e.g.
**
**   unixEnterMutex()
**     assert( unixMutexHeld() );
**   unixEnterLeave()
**
** To prevent deadlock, the global unixBigLock must must be acquired
** before the unixInodeInfo.pLockMutex mutex, if both are held.  It is
** OK to get the pLockMutex without holding unixBigLock first, but if
** that happens, the unixBigLock mutex must not be acquired until after
** pLockMutex is released.
**
**      OK:     enter(unixBigLock),  enter(pLockInfo)
**      OK:     enter(unixBigLock)
**      OK:     enter(pLockInfo)
**   ERROR:     enter(pLockInfo), enter(unixBigLock)
*/
static sqlite3_mutex *unixBigLock = 0;
static void unixEnterMutex(void){
  assert( sqlite3_mutex_notheld(unixBigLock) );  /* Not a recursive mutex */
  sqlite3_mutex_enter(unixBigLock);
}
static void unixLeaveMutex(void){
  assert( sqlite3_mutex_held(unixBigLock) );
  sqlite3_mutex_leave(unixBigLock);
}
#ifdef SQLITE_DEBUG
static int unixMutexHeld(void) {
  return sqlite3_mutex_held(unixBigLock);
}
#endif
................................................................................
**
** A single inode can have multiple file descriptors, so each unixFile
** structure contains a pointer to an instance of this object and this
** object keeps a count of the number of unixFile pointing to it.
**
** Mutex rules:
**
**  (1) Only the pLockMutex mutex must be held in order to read or write
**      any of the locking fields:
**          nShared, nLock, eFileLock, bProcessLock, pUnused
**
**  (2) When nRef>0, then the following fields are unchanging and can
**      be read (but not written) without holding any mutex:
**          fileId, pLockMutex
**
**  (3) With the exceptions above, all the fields may only be read
**      or written while holding the global unixBigLock mutex.
**
** Deadlock prevention:  The global unixBigLock mutex may not
** be acquired while holding the pLockMutex mutex.  If both unixBigLock
** and pLockMutex are needed, then unixBigLock must be acquired first.
*/
struct unixInodeInfo {
  struct unixFileId fileId;       /* The lookup key */
  sqlite3_mutex *pLockMutex;      /* Hold this mutex for... */
  int nShared;                      /* Number of SHARED locks held */
  int nLock;                        /* Number of outstanding file locks */
  unsigned char eFileLock;          /* One of SHARED_LOCK, RESERVED_LOCK etc. */
  unsigned char bProcessLock;       /* An exclusive process lock is held */
  UnixUnusedFd *pUnused;            /* Unused file descriptors to close */
  int nRef;                       /* Number of pointers to this structure */
  unixShmNode *pShmNode;          /* Shared memory associated with this inode */

  unixInodeInfo *pNext;           /* List of all unixInodeInfo objects */
  unixInodeInfo *pPrev;           /*    .... doubly linked */
#if SQLITE_ENABLE_LOCKING_STYLE
  unsigned long long sharedByte;  /* for AFP simulated shared lock */
#endif
#if OS_VXWORKS
  sem_t *pSem;                    /* Named POSIX semaphore */
................................................................................
#endif
};

/*
** A lists of all unixInodeInfo objects.
*/
static unixInodeInfo *inodeList = 0;  /* All unixInodeInfo objects */


#ifdef SQLITE_DEBUG
/*
** True if the inode mutex is held, or not.  Used only within assert()
** to help verify correct mutex usage.
*/
int unixFileMutexHeld(unixFile *pFile){
  assert( pFile->pInode );
  return sqlite3_mutex_held(pFile->pInode->pLockMutex);
}
int unixFileMutexNotheld(unixFile *pFile){
  assert( pFile->pInode );
  return sqlite3_mutex_notheld(pFile->pInode->pLockMutex);
}
#endif

/*
**
** This function - unixLogErrorAtLine(), is only ever called via the macro
** unixLogError().
**
** It is invoked after an error occurs in an OS function and errno has been
................................................................................
/*
** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
*/ 
static void closePendingFds(unixFile *pFile){
  unixInodeInfo *pInode = pFile->pInode;
  UnixUnusedFd *p;
  UnixUnusedFd *pNext;
  assert( unixFileMutexHeld(pFile) );
  for(p=pInode->pUnused; p; p=pNext){
    pNext = p->pNext;
    robust_close(pFile, p->fd, __LINE__);
    sqlite3_free(p);

  }
  pInode->pUnused = 0;
}

/*
** Release a unixInodeInfo structure previously allocated by findInodeInfo().
**
** The mutex entered using the unixEnterMutex() function must be held
** when this function is called.
*/
static void releaseInodeInfo(unixFile *pFile){
  unixInodeInfo *pInode = pFile->pInode;
  assert( unixMutexHeld() );
  assert( unixFileMutexNotheld(pFile) );
  if( ALWAYS(pInode) ){
    pInode->nRef--;
    if( pInode->nRef==0 ){
      assert( pInode->pShmNode==0 );
      sqlite3_mutex_enter(pInode->pLockMutex);
      closePendingFds(pFile);
      sqlite3_mutex_leave(pInode->pLockMutex);
      if( pInode->pPrev ){
        assert( pInode->pPrev->pNext==pInode );
        pInode->pPrev->pNext = pInode->pNext;
      }else{
        assert( inodeList==pInode );
        inodeList = pInode->pNext;
      }
................................................................................
        assert( pInode->pNext->pPrev==pInode );
        pInode->pNext->pPrev = pInode->pPrev;
      }
      sqlite3_mutex_free(pInode->pLockMutex);
      sqlite3_free(pInode);
    }
  }

}

/*
** Given a file descriptor, locate the unixInodeInfo object that
** describes that file descriptor.  Create a new one if necessary.  The
** return value might be uninitialized if an error occurs.
**
................................................................................
  memset(&fileId, 0, sizeof(fileId));
  fileId.dev = statbuf.st_dev;
#if OS_VXWORKS
  fileId.pId = pFile->pId;
#else
  fileId.ino = (u64)statbuf.st_ino;
#endif

  pInode = inodeList;
  while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){
    pInode = pInode->pNext;
  }
  if( pInode==0 ){
    pInode = sqlite3_malloc64( sizeof(*pInode) );
    if( pInode==0 ){
................................................................................
/*
** Add the file descriptor used by file handle pFile to the corresponding
** pUnused list.
*/
static void setPendingFd(unixFile *pFile){
  unixInodeInfo *pInode = pFile->pInode;
  UnixUnusedFd *p = pFile->pPreallocatedUnused;
  assert( unixFileMutexHeld(pFile) );
  p->pNext = pInode->pUnused;
  pInode->pUnused = p;
  pFile->h = -1;
  pFile->pPreallocatedUnused = 0;

}

/*
** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
** must be either NO_LOCK or SHARED_LOCK.
**
** If the locking level of the file descriptor is already at or below
................................................................................

    /* Decrement the count of locks against this same file.  When the
    ** count reaches zero, close any other file descriptors whose close
    ** was deferred because of outstanding locks.
    */
    pInode->nLock--;
    assert( pInode->nLock>=0 );

    if( pInode->nLock==0 ) closePendingFds(pFile);

  }

end_unlock:
  sqlite3_mutex_leave(pInode->pLockMutex);
  if( rc==SQLITE_OK ){
    pFile->eFileLock = eFileLock;
  }
  return rc;
}

/*
** Lower the locking level on file descriptor pFile to eFileLock.  eFileLock
** must be either NO_LOCK or SHARED_LOCK.
**
................................................................................

/*
** Close a file.
*/
static int unixClose(sqlite3_file *id){
  int rc = SQLITE_OK;
  unixFile *pFile = (unixFile *)id;
  unixInodeInfo *pInode = pFile->pInode;

  assert( pInode!=0 );
  verifyDbFile(pFile);
  unixUnlock(id, NO_LOCK);
  assert( unixFileMutexNotheld(pFile) );
  unixEnterMutex();

  /* unixFile.pInode is always valid here. Otherwise, a different close
  ** routine (e.g. nolockClose()) would be called instead.
  */
  assert( pFile->pInode->nLock>0 || pFile->pInode->bProcessLock==0 );
  sqlite3_mutex_enter(pInode->pLockMutex);
  if( pFile->pInode->nLock ){
    /* If there are outstanding locks, do not actually close the file just
    ** yet because that would clear those locks.  Instead, add the file
    ** descriptor to pInode->pUnused list.  It will be automatically closed 
    ** when the last lock is cleared.
    */
    setPendingFd(pFile);
  }
  sqlite3_mutex_leave(pInode->pLockMutex);
  releaseInodeInfo(pFile);
  rc = closeUnixFile(id);
  unixLeaveMutex();
  return rc;
}

/************** End of the posix advisory lock implementation *****************
................................................................................
 ** Close a file.
 */
static int semXClose(sqlite3_file *id) {
  if( id ){
    unixFile *pFile = (unixFile*)id;
    semXUnlock(id, NO_LOCK);
    assert( pFile );
    assert( unixFileMutexNotheld(pFile) );
    unixEnterMutex();
    releaseInodeInfo(pFile);
    unixLeaveMutex();
    closeUnixFile(id);
  }
  return SQLITE_OK;
}
................................................................................
        pInode->eFileLock = NO_LOCK;
        pFile->eFileLock = NO_LOCK;
      }
    }
    if( rc==SQLITE_OK ){
      pInode->nLock--;
      assert( pInode->nLock>=0 );

      if( pInode->nLock==0 ) closePendingFds(pFile);

    }
  }
  
  sqlite3_mutex_leave(pInode->pLockMutex);
  if( rc==SQLITE_OK ){
    pFile->eFileLock = eFileLock;
  }
  return rc;
}

/*
** Close a file & cleanup AFP specific locking context 
*/
static int afpClose(sqlite3_file *id) {
  int rc = SQLITE_OK;
  unixFile *pFile = (unixFile*)id;
  assert( id!=0 );
  afpUnlock(id, NO_LOCK);
  assert( unixFileMutexNotheld(pFile) );
  unixEnterMutex();
  if( pFile->pInode ){
    unixInodeInfo *pInode = pFile->pInode;
    sqlite3_mutex_enter(pInode->pLockMutex);
    if( pFile->pInode->nLock ){
      /* If there are outstanding locks, do not actually close the file just
      ** yet because that would clear those locks.  Instead, add the file
      ** descriptor to pInode->aPending.  It will be automatically closed when
      ** the last lock is cleared.
      */
      setPendingFd(pFile);
    }
    sqlite3_mutex_leave(pInode->pLockMutex);
  }
  releaseInodeInfo(pFile);
  sqlite3_free(pFile->lockingContext);
  rc = closeUnixFile(id);
  unixLeaveMutex();
  return rc;
}
................................................................................
  if( p==0 ) return SQLITE_NOMEM_BKPT;
  memset(p, 0, sizeof(*p));
  assert( pDbFd->pShm==0 );

  /* Check to see if a unixShmNode object already exists. Reuse an existing
  ** one if present. Create a new one if necessary.
  */
  assert( unixFileMutexNotheld(pDbFd) );
  unixEnterMutex();
  pInode = pDbFd->pInode;
  pShmNode = pInode->pShmNode;
  if( pShmNode==0 ){
    struct stat sStat;                 /* fstat() info for database file */
#ifndef SQLITE_SHM_DIRECTORY
    const char *zBasePath = pDbFd->zPath;
................................................................................
** any load or store begun after the barrier.
*/
static void unixShmBarrier(
  sqlite3_file *fd                /* Database file holding the shared memory */
){
  UNUSED_PARAMETER(fd);
  sqlite3MemoryBarrier();         /* compiler-defined memory barrier */
  assert( unixFileMutexNotheld((unixFile*)fd) );
  unixEnterMutex();               /* Also mutex, for redundancy */
  unixLeaveMutex();
}

/*
** Close a connection to shared-memory.  Delete the underlying 
** storage if deleteFlag is true.
................................................................................
  /* Free the connection p */
  sqlite3_free(p);
  pDbFd->pShm = 0;
  sqlite3_mutex_leave(pShmNode->mutex);

  /* If pShmNode->nRef has reached 0, then close the underlying
  ** shared-memory file, too */
  assert( unixFileMutexNotheld(pDbFd) );
  unixEnterMutex();
  assert( pShmNode->nRef>0 );
  pShmNode->nRef--;
  if( pShmNode->nRef==0 ){
    if( deleteFlag && pShmNode->h>=0 ){
      osUnlink(pShmNode->zFilename);
    }
................................................................................
  unixUnlock,               /* xUnlock method */
  unixCheckReservedLock,    /* xCheckReservedLock method */
  unixShmMap                /* xShmMap method */
)
IOMETHODS(
  nolockIoFinder,           /* Finder function name */
  nolockIoMethods,          /* sqlite3_io_methods object name */
  3,                        /* shared memory and mmap are enabled */
  nolockClose,              /* xClose method */
  nolockLock,               /* xLock method */
  nolockUnlock,             /* xUnlock method */
  nolockCheckReservedLock,  /* xCheckReservedLock method */
  0                         /* xShmMap method */
)
IOMETHODS(
................................................................................
  ** almost certain that an open() call on the same path will also fail.
  ** For this reason, if an error occurs in the stat() call here, it is
  ** ignored and -1 is returned. The caller will try to open a new file
  ** descriptor on the same path, fail, and return an error to SQLite.
  **
  ** Even if a subsequent open() call does succeed, the consequences of
  ** not searching for a reusable file descriptor are not dire.  */
  if( inodeList!=0 && 0==osStat(zPath, &sStat) ){
    unixInodeInfo *pInode;

    pInode = inodeList;
    while( pInode && (pInode->fileId.dev!=sStat.st_dev
                     || pInode->fileId.ino!=(u64)sStat.st_ino) ){
       pInode = pInode->pNext;
    }
    if( pInode ){
      UnixUnusedFd **pp;
      assert( sqlite3_mutex_notheld(pInode->pLockMutex) );
      sqlite3_mutex_enter(pInode->pLockMutex);
      for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
      pUnused = *pp;
      if( pUnused ){

        *pp = pUnused->pNext;
      }
      sqlite3_mutex_leave(pInode->pLockMutex);
    }
  }
  unixLeaveMutex();
#endif    /* if !OS_VXWORKS */
  return pUnused;
}

Changes to src/prepare.c.

21
22
23
24
25
26
27







28


29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
...
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
...
163
164
165
166
167
168
169

170
171
172
173
174
175
176
...
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
*/
static void corruptSchema(
  InitData *pData,     /* Initialization context */
  const char *zObj,    /* Object being parsed at the point of error */
  const char *zExtra   /* Error information */
){
  sqlite3 *db = pData->db;







  if( !db->mallocFailed && (db->flags & SQLITE_WriteSchema)==0 ){


    char *z;
    if( zObj==0 ) zObj = "?";
    z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
    if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
    sqlite3DbFree(db, *pData->pzErrMsg);
    *pData->pzErrMsg = z;

  }
  pData->rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_CORRUPT_BKPT;
}

/*
** This is the callback routine for the code that initializes the
** database.  See sqlite3Init() below for additional information.
** This routine is also called from the OP_ParseSchema opcode of the VDBE.
**
................................................................................
** Attempt to read the database schema and initialize internal
** data structures for a single database file.  The index of the
** database file is given by iDb.  iDb==0 is used for the main
** database.  iDb==1 should never be used.  iDb>=2 is used for
** auxiliary databases.  Return one of the SQLITE_ error codes to
** indicate success or failure.
*/
int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
  int rc;
  int i;
#ifndef SQLITE_OMIT_DEPRECATED
  int size;
#endif
  Db *pDb;
  char const *azArg[4];
................................................................................
  azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
                            "rootpage int,sql text)";
  azArg[3] = 0;
  initData.db = db;
  initData.iDb = iDb;
  initData.rc = SQLITE_OK;
  initData.pzErrMsg = pzErrMsg;

  sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
  if( initData.rc ){
    rc = initData.rc;
    goto error_out;
  }

  /* Create a cursor to hold the database open
................................................................................
  assert( sqlite3_mutex_held(db->mutex) );
  assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) );
  assert( db->init.busy==0 );
  ENC(db) = SCHEMA_ENC(db);
  assert( db->nDb>0 );
  /* Do the main schema first */
  if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){
    rc = sqlite3InitOne(db, 0, pzErrMsg);
    if( rc ) return rc;
  }
  /* All other schemas after the main schema. The "temp" schema must be last */
  for(i=db->nDb-1; i>0; i--){
    assert( i==1 || sqlite3BtreeHoldsMutex(db->aDb[i].pBt) );
    if( !DbHasProperty(db, i, DB_SchemaLoaded) ){
      rc = sqlite3InitOne(db, i, pzErrMsg);
      if( rc ) return rc;
    }
  }
  if( commit_internal ){
    sqlite3CommitInternalChanges(db);
  }
  return SQLITE_OK;







>
>
>
>
>
>
>
|
>
>




<

>

<







 







|







 







>







 







|






|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

42
43
44

45
46
47
48
49
50
51
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
...
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
...
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
*/
static void corruptSchema(
  InitData *pData,     /* Initialization context */
  const char *zObj,    /* Object being parsed at the point of error */
  const char *zExtra   /* Error information */
){
  sqlite3 *db = pData->db;
  if( db->mallocFailed ){
    pData->rc = SQLITE_NOMEM_BKPT;
  }else if( pData->pzErrMsg[0]!=0 ){
    /* A error message has already been generated.  Do not overwrite it */
  }else if( pData->mInitFlags & INITFLAG_AlterTable ){
    *pData->pzErrMsg = sqlite3DbStrDup(db, zExtra);
    pData->rc = SQLITE_ERROR;
  }else if( db->flags & SQLITE_WriteSchema ){
    pData->rc = SQLITE_CORRUPT_BKPT;
  }else{
    char *z;
    if( zObj==0 ) zObj = "?";
    z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
    if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);

    *pData->pzErrMsg = z;
    pData->rc = SQLITE_CORRUPT_BKPT;
  }

}

/*
** This is the callback routine for the code that initializes the
** database.  See sqlite3Init() below for additional information.
** This routine is also called from the OP_ParseSchema opcode of the VDBE.
**
................................................................................
** Attempt to read the database schema and initialize internal
** data structures for a single database file.  The index of the
** database file is given by iDb.  iDb==0 is used for the main
** database.  iDb==1 should never be used.  iDb>=2 is used for
** auxiliary databases.  Return one of the SQLITE_ error codes to
** indicate success or failure.
*/
int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
  int rc;
  int i;
#ifndef SQLITE_OMIT_DEPRECATED
  int size;
#endif
  Db *pDb;
  char const *azArg[4];
................................................................................
  azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
                            "rootpage int,sql text)";
  azArg[3] = 0;
  initData.db = db;
  initData.iDb = iDb;
  initData.rc = SQLITE_OK;
  initData.pzErrMsg = pzErrMsg;
  initData.mInitFlags = mFlags;
  sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
  if( initData.rc ){
    rc = initData.rc;
    goto error_out;
  }

  /* Create a cursor to hold the database open
................................................................................
  assert( sqlite3_mutex_held(db->mutex) );
  assert( sqlite3BtreeHoldsMutex(db->aDb[0].pBt) );
  assert( db->init.busy==0 );
  ENC(db) = SCHEMA_ENC(db);
  assert( db->nDb>0 );
  /* Do the main schema first */
  if( !DbHasProperty(db, 0, DB_SchemaLoaded) ){
    rc = sqlite3InitOne(db, 0, pzErrMsg, 0);
    if( rc ) return rc;
  }
  /* All other schemas after the main schema. The "temp" schema must be last */
  for(i=db->nDb-1; i>0; i--){
    assert( i==1 || sqlite3BtreeHoldsMutex(db->aDb[i].pBt) );
    if( !DbHasProperty(db, i, DB_SchemaLoaded) ){
      rc = sqlite3InitOne(db, i, pzErrMsg, 0);
      if( rc ) return rc;
    }
  }
  if( commit_internal ){
    sqlite3CommitInternalChanges(db);
  }
  return SQLITE_OK;

Changes to src/sqliteInt.h.

3325
3326
3327
3328
3329
3330
3331

3332
3333





3334
3335
3336
3337
3338
3339
3340
....
3797
3798
3799
3800
3801
3802
3803
3804
3805
3806
3807
3808
3809
3810
3811
** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback.
*/
typedef struct {
  sqlite3 *db;        /* The database being initialized */
  char **pzErrMsg;    /* Error message stored here */
  int iDb;            /* 0 for main database.  1 for TEMP, 2.. for ATTACHed */
  int rc;             /* Result code stored here */

} InitData;






/*
** Structure containing global configuration data for the SQLite library.
**
** This structure also contains some state information.
*/
struct Sqlite3Config {
  int bMemstat;                     /* True to enable memory status */
................................................................................
void sqlite3ExprListSetSortOrder(ExprList*,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
void sqlite3ExprListDelete(sqlite3*, ExprList*);
u32 sqlite3ExprListFlags(const ExprList*);
int sqlite3Init(sqlite3*, char**);
int sqlite3InitCallback(void*, int, char**, char**);
int sqlite3InitOne(sqlite3*, int, char**);
void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
#ifndef SQLITE_OMIT_VIRTUALTABLE
Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
#endif
void sqlite3ResetAllSchemasOfConnection(sqlite3*);
void sqlite3ResetOneSchema(sqlite3*,int);
void sqlite3CollapseDatabaseArray(sqlite3*);







>


>
>
>
>
>







 







|







3325
3326
3327
3328
3329
3330
3331
3332
3333
3334
3335
3336
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
....
3803
3804
3805
3806
3807
3808
3809
3810
3811
3812
3813
3814
3815
3816
3817
** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback.
*/
typedef struct {
  sqlite3 *db;        /* The database being initialized */
  char **pzErrMsg;    /* Error message stored here */
  int iDb;            /* 0 for main database.  1 for TEMP, 2.. for ATTACHed */
  int rc;             /* Result code stored here */
  u32 mInitFlags;     /* Flags controlling error messages */
} InitData;

/*
** Allowed values for mInitFlags
*/
#define INITFLAG_AlterTable   0x0001  /* This is a reparse after ALTER TABLE */

/*
** Structure containing global configuration data for the SQLite library.
**
** This structure also contains some state information.
*/
struct Sqlite3Config {
  int bMemstat;                     /* True to enable memory status */
................................................................................
void sqlite3ExprListSetSortOrder(ExprList*,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
void sqlite3ExprListDelete(sqlite3*, ExprList*);
u32 sqlite3ExprListFlags(const ExprList*);
int sqlite3Init(sqlite3*, char**);
int sqlite3InitCallback(void*, int, char**, char**);
int sqlite3InitOne(sqlite3*, int, char**, u32);
void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
#ifndef SQLITE_OMIT_VIRTUALTABLE
Module *sqlite3PragmaVtabRegister(sqlite3*,const char *zName);
#endif
void sqlite3ResetAllSchemasOfConnection(sqlite3*);
void sqlite3ResetOneSchema(sqlite3*,int);
void sqlite3CollapseDatabaseArray(sqlite3*);

Changes to src/vdbe.c.

5718
5719
5720
5721
5722
5723
5724
5725

5726
5727
5728
5729
5730
5731
5732
....
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
  if( rc ) goto abort_due_to_error;
  break;
}

/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
** that match the WHERE clause P4. 

**
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine.  It is thus a re-entrant opcode.
*/
case OP_ParseSchema: {
  int iDb;
  const char *zMaster;
................................................................................
  assert( iDb>=0 && iDb<db->nDb );
  assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );

#ifndef SQLITE_OMIT_ALTERTABLE
  if( pOp->p4.z==0 ){
    sqlite3SchemaClear(db->aDb[iDb].pSchema);
    db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
    rc = sqlite3InitOne(db, iDb, &p->zErrMsg);
    db->mDbFlags |= DBFLAG_SchemaChange;
  }else
#endif
  /* Used to be a conditional */ {
    zMaster = MASTER_NAME;
    initData.db = db;
    initData.iDb = pOp->p1;
    initData.pzErrMsg = &p->zErrMsg;
    zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
       db->aDb[iDb].zDbSName, zMaster, pOp->p4.z);







|
>







 







|



|







5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
....
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
  if( rc ) goto abort_due_to_error;
  break;
}

/* Opcode: ParseSchema P1 * * P4 *
**
** Read and parse all entries from the SQLITE_MASTER table of database P1
** that match the WHERE clause P4.  If P4 is a NULL pointer, then the
** entire schema for P1 is reparsed.
**
** This opcode invokes the parser to create a new virtual machine,
** then runs the new virtual machine.  It is thus a re-entrant opcode.
*/
case OP_ParseSchema: {
  int iDb;
  const char *zMaster;
................................................................................
  assert( iDb>=0 && iDb<db->nDb );
  assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );

#ifndef SQLITE_OMIT_ALTERTABLE
  if( pOp->p4.z==0 ){
    sqlite3SchemaClear(db->aDb[iDb].pSchema);
    db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
    rc = sqlite3InitOne(db, iDb, &p->zErrMsg, INITFLAG_AlterTable);
    db->mDbFlags |= DBFLAG_SchemaChange;
  }else
#endif
  {
    zMaster = MASTER_NAME;
    initData.db = db;
    initData.iDb = pOp->p1;
    initData.pzErrMsg = &p->zErrMsg;
    zSql = sqlite3MPrintf(db,
       "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
       db->aDb[iDb].zDbSName, zMaster, pOp->p4.z);

Changes to src/vdbe.h.

234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
void sqlite3VdbeRunOnlyOnce(Vdbe*);
void sqlite3VdbeReusable(Vdbe*);
void sqlite3VdbeDelete(Vdbe*);
void sqlite3VdbeClearObject(sqlite3*,Vdbe*);
void sqlite3VdbeMakeReady(Vdbe*,Parse*);
int sqlite3VdbeFinalize(Vdbe*);
void sqlite3VdbeResolveLabel(Vdbe*, int);
#ifdef SQLITE_COVERAGE_TEST
  int sqlite3VdbeLabelHasBeenResolved(Vdbe*,int);
#endif
int sqlite3VdbeCurrentAddr(Vdbe*);
#ifdef SQLITE_DEBUG
  int sqlite3VdbeAssertMayAbort(Vdbe *, int);
#endif
void sqlite3VdbeResetStepResult(Vdbe*);
void sqlite3VdbeRewind(Vdbe*);
int sqlite3VdbeReset(Vdbe*);







<
<
<







234
235
236
237
238
239
240



241
242
243
244
245
246
247
void sqlite3VdbeRunOnlyOnce(Vdbe*);
void sqlite3VdbeReusable(Vdbe*);
void sqlite3VdbeDelete(Vdbe*);
void sqlite3VdbeClearObject(sqlite3*,Vdbe*);
void sqlite3VdbeMakeReady(Vdbe*,Parse*);
int sqlite3VdbeFinalize(Vdbe*);
void sqlite3VdbeResolveLabel(Vdbe*, int);



int sqlite3VdbeCurrentAddr(Vdbe*);
#ifdef SQLITE_DEBUG
  int sqlite3VdbeAssertMayAbort(Vdbe *, int);
#endif
void sqlite3VdbeResetStepResult(Vdbe*);
void sqlite3VdbeRewind(Vdbe*);
int sqlite3VdbeReset(Vdbe*);

Changes to src/vdbeaux.c.

433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
    }
#endif
    assert( p->aLabel[j]==(-1) ); /* Labels may only be resolved once */
    p->aLabel[j] = v->nOp;
  }
}

#ifdef SQLITE_COVERAGE_TEST
/*
** Return TRUE if and only if the label x has already been resolved.
** Return FALSE (zero) if label x is still unresolved.
**
** This routine is only used inside of testcase() macros, and so it
** only exists when measuring test coverage.
*/
int sqlite3VdbeLabelHasBeenResolved(Vdbe *v, int x){
  return v->pParse->aLabel && v->pParse->aLabel[ADDR(x)]>=0;
}
#endif /* SQLITE_COVERAGE_TEST */

/*
** Mark the VDBE as one that can only be run one time.
*/
void sqlite3VdbeRunOnlyOnce(Vdbe *p){
  p->runOnlyOnce = 1;
}








<
<
<
<
<
<
<
<
<
<
<
<
<







433
434
435
436
437
438
439













440
441
442
443
444
445
446
    }
#endif
    assert( p->aLabel[j]==(-1) ); /* Labels may only be resolved once */
    p->aLabel[j] = v->nOp;
  }
}














/*
** Mark the VDBE as one that can only be run one time.
*/
void sqlite3VdbeRunOnlyOnce(Vdbe *p){
  p->runOnlyOnce = 1;
}

Changes to test/altercol.test.

62
63
64
65
66
67
68















69
70
71
72
73
74
75
...
205
206
207
208
209
210
211

212
213
214
215
216
217
218
...
231
232
233
234
235
236
237
238


239









































































 12 {CREATE TABLE t1(a, b, c);   CREATE INDEX t1i ON t1(b+b+b+b, c) WHERE b>0}
    {{CREATE TABLE t1(a, d, c)} {CREATE INDEX t1i ON t1(d+d+d+d, c) WHERE d>0}}

 13 {CREATE TABLE t1(a, b, c, FOREIGN KEY (b) REFERENCES t2)}
    {CREATE TABLE t1(a, d, c, FOREIGN KEY (d) REFERENCES t2)}
















} {
  reset_db
  do_execsql_test 1.$tn.0 $before

  do_execsql_test 1.$tn.1 {
    INSERT INTO t1 VALUES(1, 2, 3);
  }
................................................................................
} {0 {}}

do_execsql_test 6.3 {
  SELECT "where" FROM blob;
} {}

#-------------------------------------------------------------------------

#
reset_db
do_execsql_test 7.0 {
  CREATE TABLE c(x);
  INSERT INTO c VALUES(0);
  CREATE TABLE t6("col a", "col b", "col c");
  CREATE TRIGGER zzz AFTER UPDATE OF "col a", "col c" ON t6 BEGIN
................................................................................
}

do_execsql_test 7.3 {
  UPDATE t6 SET "col 3" = 0;
  SELECT * FROM c;
} {2}

finish_test


















































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







<
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
...
247
248
249
250
251
252
253

254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328

 12 {CREATE TABLE t1(a, b, c);   CREATE INDEX t1i ON t1(b+b+b+b, c) WHERE b>0}
    {{CREATE TABLE t1(a, d, c)} {CREATE INDEX t1i ON t1(d+d+d+d, c) WHERE d>0}}

 13 {CREATE TABLE t1(a, b, c, FOREIGN KEY (b) REFERENCES t2)}
    {CREATE TABLE t1(a, d, c, FOREIGN KEY (d) REFERENCES t2)}

 15 {CREATE TABLE t1(a INTEGER, b INTEGER, c BLOB, PRIMARY KEY(b))}
    {CREATE TABLE t1(a INTEGER, d INTEGER, c BLOB, PRIMARY KEY(d))}

 16 {CREATE TABLE t1(a INTEGER, b INTEGER PRIMARY KEY, c BLOB)}
    {CREATE TABLE t1(a INTEGER, d INTEGER PRIMARY KEY, c BLOB)}

 14 {CREATE TABLE t1(a INTEGER, b TEXT, c BLOB, PRIMARY KEY(b))}
    {CREATE TABLE t1(a INTEGER, d TEXT, c BLOB, PRIMARY KEY(d))}

 15 {CREATE TABLE t1(a INTEGER, b INTEGER, c BLOB, PRIMARY KEY(b))}
    {CREATE TABLE t1(a INTEGER, d INTEGER, c BLOB, PRIMARY KEY(d))}

 16 {CREATE TABLE t1(a INTEGER, b INTEGER PRIMARY KEY, c BLOB)}
    {CREATE TABLE t1(a INTEGER, d INTEGER PRIMARY KEY, c BLOB)}

} {
  reset_db
  do_execsql_test 1.$tn.0 $before

  do_execsql_test 1.$tn.1 {
    INSERT INTO t1 VALUES(1, 2, 3);
  }
................................................................................
} {0 {}}

do_execsql_test 6.3 {
  SELECT "where" FROM blob;
} {}

#-------------------------------------------------------------------------
# Triggers.
#
reset_db
do_execsql_test 7.0 {
  CREATE TABLE c(x);
  INSERT INTO c VALUES(0);
  CREATE TABLE t6("col a", "col b", "col c");
  CREATE TRIGGER zzz AFTER UPDATE OF "col a", "col c" ON t6 BEGIN
................................................................................
}

do_execsql_test 7.3 {
  UPDATE t6 SET "col 3" = 0;
  SELECT * FROM c;
} {2}


#-------------------------------------------------------------------------
# Views.
#
reset_db
do_execsql_test 8.0 {
  CREATE TABLE a1(x INTEGER, y TEXT, z BLOB, PRIMARY KEY(x));
  CREATE TABLE a2(a, b, c);
  CREATE VIEW v1 AS SELECT x, y, z FROM a1;
}

do_execsql_test 8.1 {
  ALTER TABLE a1 RENAME y TO yyy;
  SELECT sql FROM sqlite_master WHERE type='view';
} {{CREATE VIEW v1 AS SELECT x, yyy, z FROM a1}}

do_execsql_test 8.2.1 {
  DROP VIEW v1;
  CREATE VIEW v2 AS SELECT x, x+x, a, a+a FROM a1, a2;
} {}
do_execsql_test 8.2.2 {
  ALTER TABLE a1 RENAME x TO xxx;
}
do_execsql_test 8.2.3 {
  SELECT sql FROM sqlite_master WHERE type='view';
} {{CREATE VIEW v2 AS SELECT xxx, xxx+xxx, a, a+a FROM a1, a2}}

do_execsql_test 8.3.1 {
  DROP TABLE a2;
  DROP VIEW v2;
  CREATE TABLE a2(a INTEGER PRIMARY KEY, b, c);
  CREATE VIEW v2 AS SELECT xxx, xxx+xxx, a, a+a FROM a1, a2;
} {}
do_execsql_test 8.3.2 {
  ALTER TABLE a1 RENAME xxx TO x;
}
do_execsql_test 8.3.3 {
  SELECT sql FROM sqlite_master WHERE type='view';
} {{CREATE VIEW v2 AS SELECT x, x+x, a, a+a FROM a1, a2}}

do_execsql_test 8.4.0 {
  CREATE TABLE b1(a, b, c);
  CREATE TABLE b2(x, y, z);
}

do_execsql_test 8.4.1 {
  CREATE VIEW vvv AS SELECT c+c || coalesce(c, c) FROM b1, b2 WHERE x=c GROUP BY c HAVING c>0;
  ALTER TABLE b1 RENAME c TO "a;b";
  SELECT sql FROM sqlite_master WHERE name='vvv';
} {{CREATE VIEW vvv AS SELECT "a;b"+"a;b" || coalesce("a;b", "a;b") FROM b1, b2 WHERE x="a;b" GROUP BY "a;b" HAVING "a;b">0}}

do_execsql_test 8.4.2 {
  CREATE VIEW www AS SELECT b FROM b1 UNION ALL SELECT y FROM b2;
  ALTER TABLE b1 RENAME b TO bbb;
  SELECT sql FROM sqlite_master WHERE name='www';
} {{CREATE VIEW www AS SELECT bbb FROM b1 UNION ALL SELECT y FROM b2}}

db collate nocase {string compare}

do_execsql_test 8.4.3 {
  CREATE VIEW xxx AS SELECT a FROM b1 UNION SELECT x FROM b2 ORDER BY 1 COLLATE nocase;
}

do_execsql_test 8.4.4 {
  ALTER TABLE b2 RENAME x TO hello;
  SELECT sql FROM sqlite_master WHERE name='xxx';
} {{CREATE VIEW xxx AS SELECT a FROM b1 UNION SELECT hello FROM b2 ORDER BY 1 COLLATE nocase}}

do_execsql_test 8.4.5 {
  CREATE VIEW zzz AS SELECT george, ringo FROM b1;
  ALTER TABLE b1 RENAME a TO aaa;
  SELECT sql FROM sqlite_master WHERE name = 'zzz'
} {{CREATE VIEW zzz AS SELECT george, ringo FROM b1}}


finish_test

Changes to test/trigger7.test.

109
110
111
112
113
114
115
116
117
118
  execsql {
    PRAGMA writable_schema=on;
    UPDATE sqlite_master SET sql='nonsense';
  }
  db close
  catch { sqlite3 db test.db }
  catchsql { DROP TRIGGER t2r5 }
} {1 {malformed database schema (t2r12)}}

finish_test







|


109
110
111
112
113
114
115
116
117
118
  execsql {
    PRAGMA writable_schema=on;
    UPDATE sqlite_master SET sql='nonsense';
  }
  db close
  catch { sqlite3 db test.db }
  catchsql { DROP TRIGGER t2r5 }
} {/1 {malformed database schema .*}/}

finish_test

Changes to test/upsert1.test.

123
124
125
126
127
128
129
130



















































































131
  PRAGMA integrity_check;
} {ok}
do_execsql_test upsert1-610 {
  DELETE FROM t1;
  INSERT OR IGNORE INTO t1(a) VALUES('1'),(1) ON CONFLICT(a) DO NOTHING;
  PRAGMA integrity_check;
} {ok}




















































































finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>

123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
  PRAGMA integrity_check;
} {ok}
do_execsql_test upsert1-610 {
  DELETE FROM t1;
  INSERT OR IGNORE INTO t1(a) VALUES('1'),(1) ON CONFLICT(a) DO NOTHING;
  PRAGMA integrity_check;
} {ok}

# 2018-08-14
# Ticket https://www.sqlite.org/src/info/908f001483982c43
# If there are multiple uniqueness contraints, the UPSERT should fire
# if the one constraint it targets fails, regardless of whether or not
# the other constraints pass or fail.  In other words, the UPSERT constraint
# should be tested first.
#
do_execsql_test upsert1-700 {
  DROP TABLE t1;
  CREATE TABLE t1(a INTEGER PRIMARY KEY, b INT, c INT, d INT, e INT);
  CREATE UNIQUE INDEX t1b ON t1(b);
  CREATE UNIQUE INDEX t1e ON t1(e);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5)
    ON CONFLICT(e) DO UPDATE SET c=excluded.c;
  SELECT * FROM t1;
} {1 2 33 4 5}
do_execsql_test upsert1-710 {
  DELETE FROM t1;
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5)
    ON CONFLICT(a) DO UPDATE SET c=excluded.c;
  SELECT * FROM t1;
} {1 2 33 4 5}
do_execsql_test upsert1-720 {
  DELETE FROM t1;
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5)
    ON CONFLICT(b) DO UPDATE SET c=excluded.c;
  SELECT * FROM t1;
} {1 2 33 4 5}
do_execsql_test upsert1-730 {
  DROP TABLE t1;
  CREATE TABLE t1(a INT, b INT, c INT, d INT, e INT);
  CREATE UNIQUE INDEX t1a ON t1(a);
  CREATE UNIQUE INDEX t1b ON t1(b);
  CREATE UNIQUE INDEX t1e ON t1(e);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5)
    ON CONFLICT(e) DO UPDATE SET c=excluded.c;
  SELECT * FROM t1;
} {1 2 33 4 5}
do_execsql_test upsert1-740 {
  DELETE FROM t1;
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5)
    ON CONFLICT(a) DO UPDATE SET c=excluded.c;
  SELECT * FROM t1;
} {1 2 33 4 5}
do_execsql_test upsert1-750 {
  DELETE FROM t1;
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5)
    ON CONFLICT(b) DO UPDATE SET c=excluded.c;
  SELECT * FROM t1;
} {1 2 33 4 5}
do_execsql_test upsert1-760 {
  DROP TABLE t1;
  CREATE TABLE t1(a INT PRIMARY KEY, b INT, c INT, d INT, e INT) WITHOUT ROWID;
  CREATE UNIQUE INDEX t1a ON t1(a);
  CREATE UNIQUE INDEX t1b ON t1(b);
  CREATE UNIQUE INDEX t1e ON t1(e);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5)
    ON CONFLICT(e) DO UPDATE SET c=excluded.c;
  SELECT * FROM t1;
} {1 2 33 4 5}
do_execsql_test upsert1-770 {
  DELETE FROM t1;
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5)
    ON CONFLICT(a) DO UPDATE SET c=excluded.c;
  SELECT * FROM t1;
} {1 2 33 4 5}
do_execsql_test upsert1-780 {
  DELETE FROM t1;
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,3,4,5);
  INSERT INTO t1(a,b,c,d,e) VALUES(1,2,33,44,5)
    ON CONFLICT(b) DO UPDATE SET c=excluded.c;
  SELECT * FROM t1;
} {1 2 33 4 5}


finish_test