1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-08 03:22:21 +03:00

First cut at supporting CHECK constraints. Everything appears to work,

but much more testing is needed as well as documentation. (CVS 2754)

FossilOrigin-Name: 2313d912baeca0fd516d524f16708953de483729
This commit is contained in:
drh
2005-11-03 00:41:17 +00:00
parent 8df447f0e6
commit ffe07b2dc1
12 changed files with 279 additions and 51 deletions

View File

@@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.232 2005/11/01 15:48:24 drh Exp $
** $Id: expr.c,v 1.233 2005/11/03 00:41:17 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -802,7 +802,7 @@ int sqlite3IsRowid(const char *z){
** in pParse and return non-zero. Return zero on success.
*/
static int lookupName(
Parse *pParse, /* The parsing context */
Parse *pParse, /* The parsing context */
Token *pDbToken, /* Name of the database containing table, or NULL */
Token *pTableToken, /* Name of table containing column, or NULL */
Token *pColumnToken, /* Name of the column. */
@@ -830,10 +830,9 @@ static int lookupName(
pExpr->iTable = -1;
while( pNC && cnt==0 ){
ExprList *pEList;
SrcList *pSrcList = pNC->pSrcList;
ExprList *pEList = pNC->pEList;
/* assert( zTab==0 || pEList==0 ); */
if( pSrcList ){
for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
Table *pTab = pItem->pTab;
@@ -952,7 +951,7 @@ static int lookupName(
** Note that the expression in the result set should have already been
** resolved by the time the WHERE clause is resolved.
*/
if( cnt==0 && pEList!=0 && zTab==0 ){
if( cnt==0 && (pEList = pNC->pEList)!=0 && zTab==0 ){
for(j=0; j<pEList->nExpr; j++){
char *zAs = pEList->a[j].zName;
if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
@@ -1081,7 +1080,7 @@ static int nameResolverStep(void *pArg, Expr *pExpr){
if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1;
ExprSetProperty(pExpr, EP_Resolved);
#ifndef NDEBUG
if( pSrcList ){
if( pSrcList && pSrcList->nAlloc>0 ){
int i;
for(i=0; i<pSrcList->nSrc; i++){
assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
@@ -1441,6 +1440,8 @@ static void codeInteger(Vdbe *v, const char *z, int n){
void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
Vdbe *v = pParse->pVdbe;
int op;
int stackChng = 1; /* Amount of change to stack depth */
if( v==0 ) return;
if( pExpr==0 ){
sqlite3VdbeAddOp(v, OP_Null, 0, 0);
@@ -1462,7 +1463,11 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
/* Otherwise, fall thru into the TK_COLUMN case */
}
case TK_COLUMN: {
if( pExpr->iColumn>=0 ){
if( pExpr->iTable<0 ){
/* This only happens when coding check constraints */
assert( pParse->ckOffset>0 );
sqlite3VdbeAddOp(v, OP_Dup, pParse->ckOffset-pExpr->iColumn-1, 1);
}else if( pExpr->iColumn>=0 ){
sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn);
sqlite3ColumnDefault(v, pExpr->pTab, pExpr->iColumn);
}else{
@@ -1525,6 +1530,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
case SQLITE_AFF_NONE: op = OP_ToBlob; break;
}
sqlite3VdbeAddOp(v, op, 0, 0);
stackChng = 0;
break;
}
#endif /* SQLITE_OMIT_CAST */
@@ -1543,6 +1549,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3ExprCode(pParse, pExpr->pLeft);
sqlite3ExprCode(pParse, pExpr->pRight);
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, 0, 0);
stackChng = -1;
break;
}
case TK_AND:
@@ -1571,6 +1578,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3ExprCode(pParse, pExpr->pLeft);
sqlite3ExprCode(pParse, pExpr->pRight);
sqlite3VdbeAddOp(v, op, 0, 0);
stackChng = -1;
break;
}
case TK_UMINUS: {
@@ -1596,6 +1604,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
assert( TK_NOT==OP_Not );
sqlite3ExprCode(pParse, pExpr->pLeft);
sqlite3VdbeAddOp(v, op, 0, 0);
stackChng = 0;
break;
}
case TK_ISNULL:
@@ -1608,6 +1617,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
dest = sqlite3VdbeCurrentAddr(v) + 2;
sqlite3VdbeAddOp(v, op, 1, dest);
sqlite3VdbeAddOp(v, OP_AddImm, -1, 0);
stackChng = 0;
break;
}
case TK_AGG_FUNCTION: {
@@ -1644,6 +1654,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ);
}
sqlite3VdbeOp3(v, OP_Function, constMask, nExpr, (char*)pDef, P3_FUNCDEF);
stackChng = 1-nExpr;
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
@@ -1702,6 +1713,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
case TK_UPLUS:
case TK_AS: {
sqlite3ExprCode(pParse, pExpr->pLeft);
stackChng = 0;
break;
}
case TK_CASE: {
@@ -1767,9 +1779,15 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeAddOp(v, OP_Goto, 0, pParse->trigStack->ignoreJump);
VdbeComment((v, "# raise(IGNORE)"));
}
stackChng = 0;
break;
}
#endif
break;
}
if( pParse->ckOffset ){
pParse->ckOffset += stackChng;
assert( pParse->ckOffset );
}
}
@@ -1837,6 +1855,7 @@ int sqlite3ExprCodeExprList(
void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
Vdbe *v = pParse->pVdbe;
int op = 0;
int ckOffset = pParse->ckOffset;
if( v==0 || pExpr==0 ) return;
op = pExpr->op;
switch( op ){
@@ -1911,6 +1930,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
break;
}
}
pParse->ckOffset = ckOffset;
}
/*
@@ -1924,6 +1944,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
Vdbe *v = pParse->pVdbe;
int op = 0;
int ckOffset = pParse->ckOffset;
if( v==0 || pExpr==0 ) return;
/* The value of pExpr->op and op are related as follows:
@@ -2020,6 +2041,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
break;
}
}
pParse->ckOffset = ckOffset;
}
/*