Пример #1
0
 // Return the default collation sequence for the expression pExpr. If there is no default collation type, return 0.
 internal static CollSeq sqlite3ExprCollSeq(Parse pParse, Expr pExpr)
 {
     CollSeq pColl = null;
     var p = pExpr;
     while (ALWAYS(p))
     {
         pColl = pExpr.pColl;
         if (pColl != null)
             break;
         var op = p.op;
         if (p.pTab != null && (op == TK.AGG_COLUMN || op == TK.COLUMN || op == TK.REGISTER || op == TK.TRIGGER))
         {
             // op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally a TK_COLUMN but was previously evaluated and cached in a register
             var j = p.iColumn;
             if (j >= 0)
             {
                 var db = pParse.db;
                 var zColl = p.pTab.aCol[j].zColl;
                 pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0);
                 pExpr.pColl = pColl;
             }
             break;
         }
         if (op != TK.CAST && op != TK.UPLUS)
             break;
         p = p.pLeft;
     }
     if (sqlite3CheckCollSeq(pParse, pColl) != 0)
         pColl = null;
     return pColl;
 }
Пример #2
0
        // Return the 'affinity' of the expression pExpr if any.
        //
        // If pExpr is a column, a reference to a column via an 'AS' alias,
        // or a sub-select with a column as the return value, then the
        // affinity of that column is returned. Otherwise, 0x00 is returned,
        // indicating no affinity for the expression.
        //
        // i.e. the WHERE clause expresssions in the following statements all
        // have an affinity:
        //
        // CREATE TABLE t1(a);
        // SELECT * FROM t1 WHERE a;
        // SELECT a AS b FROM t1 WHERE b;
        // SELECT * FROM t1 WHERE (select a from t1);
        internal static char sqlite3ExprAffinity(Expr pExpr)
        {
            var op = pExpr.op;
            if (op == TK.SELECT)
            {
                Debug.Assert((pExpr.flags & Expr.EP_xIsSelect) != 0);
                return sqlite3ExprAffinity(pExpr.x.pSelect.pEList.a[0].pExpr);
            }
#if !SQLITE_OMIT_CAST
            if (op == TK.CAST)
            {
                Debug.Assert(!Expr.ExprHasProperty(pExpr, Expr.EP_IntValue));
                return sqlite3AffinityType(pExpr.u.zToken);
            }
#endif
            if ((op == TK.AGG_COLUMN || op == TK.COLUMN || op == TK.REGISTER) && pExpr.pTab != null)
            {
                // op==TK_REGISTER && pExpr.pTab!=0 happens when pExpr was originally a TK_COLUMN but was previously evaluated and cached in a register
                var j = pExpr.iColumn;
                if (j < 0) return SQLITE_AFF_INTEGER;
                Debug.Assert(pExpr.pTab != null && j < pExpr.pTab.nCol);
                return pExpr.pTab.aCol[j].affinity;
            }
            return pExpr.affinity;
        }
Пример #3
0
 // Set the collating sequence for expression pExpr to be the collating sequence named by pToken.   Return a pointer to the revised expression.
 // The collating sequence is marked as "explicit" using the EP_ExpCollate flag.  An explicit collating sequence will override implicit
 // collating sequences.
 internal static Expr sqlite3ExprSetCollByToken(Parse pParse, Expr pExpr, Token pCollName)
 {
     var db = pParse.db;
     var zColl = sqlite3NameFromToken(db, pCollName); // Dequoted name of collation sequence
     var pColl = sqlite3LocateCollSeq(pParse, zColl);
     sqlite3ExprSetColl(pExpr, pColl);
     sqlite3DbFree(db, ref zColl);
     return pExpr;
 }
Пример #4
0
 // Set the explicit collating sequence for an expression to the collating sequence supplied in the second argument.
 internal static Expr sqlite3ExprSetColl(Expr pExpr, CollSeq pColl)
 {
     if (pExpr != null && pColl != null)
     {
         pExpr.pColl = pColl;
         pExpr.flags |= Expr.EP_ExpCollate;
     }
     return pExpr;
 }
Пример #5
0
 internal static SrcList sqlite3SrcListAppendFromTerm(Parse pParse, SrcList p, Token pTable, Token pDatabase, Token pAlias, Select pSubquery, Expr pOn, IdList pUsing)
 {
     var db = pParse.db;
     if (null == p && (pOn != null || pUsing != null))
     {
         sqlite3ErrorMsg(pParse, "a JOIN clause is required before %s", pOn != null ? "ON" : "USING");
         goto append_from_error;
     }
     p = sqlite3SrcListAppend(db, p, pTable, pDatabase);
     var pItem = p.a[p.nSrc - 1];
     Debug.Assert(pAlias != null);
     if (pAlias.n != 0)
         pItem.zAlias = sqlite3NameFromToken(db, pAlias);
     pItem.pSelect = pSubquery;
     pItem.pOn = pOn;
     pItem.pUsing = pUsing;
     return p;
     append_from_error:
     Debug.Assert(p == null);
     sqlite3ExprDelete(db, ref pOn);
     sqlite3IdListDelete(db, ref pUsing);
     sqlite3SelectDelete(db, ref pSubquery);
     return null;
 }
Пример #6
0
 /*
 ** Join two expressions using an AND operator.  If either expression is
 ** NULL, then just return the other expression.
 */
 static Expr sqlite3ExprAnd(sqlite3 db, Expr pLeft, Expr pRight)
 {
     if (pLeft == null)
     {
         return pRight;
     }
     else if (pRight == null)
     {
         return pLeft;
     }
     else
     {
         Expr pNew = sqlite3ExprAlloc(db, TK_AND, null, 0);
         sqlite3ExprAttachSubtrees(db, pNew, pLeft, pRight);
         return pNew;
     }
 }
Пример #7
0
        /*
        ** Generate code for a boolean expression such that a jump is made
        ** to the label "dest" if the expression is false but execution
        ** continues straight thru if the expression is true.
        **
        ** If the expression evaluates to NULL (neither true nor false) then
        ** jump if jumpIfNull is SQLITE_JUMPIFNULL or fall through if jumpIfNull
        ** is 0.
        */
        static void sqlite3ExprIfFalse(Parse pParse, Expr pExpr, int dest, int jumpIfNull)
        {
            Vdbe v = pParse.pVdbe;
            int op = 0;
            int regFree1 = 0;
            int regFree2 = 0;
            int r1 = 0, r2 = 0;

            Debug.Assert(jumpIfNull == SQLITE_JUMPIFNULL || jumpIfNull == 0);
            if (NEVER(v == null))
                return; /* Existance of VDBE checked by caller */
            if (pExpr == null)
                return;

            /* The value of pExpr.op and op are related as follows:
            **
            **       pExpr.op            op
            **       ---------          ----------
            **       TK_ISNULL          OP_NotNull
            **       TK_NOTNULL         OP_IsNull
            **       TK_NE              OP_Eq
            **       TK_EQ              OP_Ne
            **       TK_GT              OP_Le
            **       TK_LE              OP_Gt
            **       TK_GE              OP_Lt
            **       TK_LT              OP_Ge
            **
            ** For other values of pExpr.op, op is undefined and unused.
            ** The value of TK_ and OP_ constants are arranged such that we
            ** can compute the mapping above using the following expression.
            ** Assert()s verify that the computation is correct.
            */
            op = ((pExpr.op + (TK_ISNULL & 1)) ^ 1) - (TK_ISNULL & 1);

            /* Verify correct alignment of TK_ and OP_ constants
            */
            Debug.Assert(pExpr.op != TK_ISNULL || op == OP_NotNull);
            Debug.Assert(pExpr.op != TK_NOTNULL || op == OP_IsNull);
            Debug.Assert(pExpr.op != TK_NE || op == OP_Eq);
            Debug.Assert(pExpr.op != TK_EQ || op == OP_Ne);
            Debug.Assert(pExpr.op != TK_LT || op == OP_Ge);
            Debug.Assert(pExpr.op != TK_LE || op == OP_Gt);
            Debug.Assert(pExpr.op != TK_GT || op == OP_Le);
            Debug.Assert(pExpr.op != TK_GE || op == OP_Lt);

            switch (pExpr.op)
            {
                case TK_AND:
                    {
                        testcase(jumpIfNull == 0);
                        sqlite3ExprIfFalse(pParse, pExpr.pLeft, dest, jumpIfNull);
                        sqlite3ExprIfFalse(pParse, pExpr.pRight, dest, jumpIfNull);
                        break;
                    }
                case TK_OR:
                    {
                        int d2 = sqlite3VdbeMakeLabel(v);
                        testcase(jumpIfNull == 0);
                        sqlite3ExprCachePush(pParse);
                        sqlite3ExprIfTrue(pParse, pExpr.pLeft, d2, jumpIfNull ^ SQLITE_JUMPIFNULL);
                        sqlite3ExprIfFalse(pParse, pExpr.pRight, dest, jumpIfNull);
                        sqlite3VdbeResolveLabel(v, d2);
                        sqlite3ExprCachePop(pParse, 1);
                        break;
                    }
                case TK_NOT:
                    {
                        testcase(jumpIfNull == 0);
                        sqlite3ExprIfTrue(pParse, pExpr.pLeft, dest, jumpIfNull);
                        break;
                    }
                case TK_LT:
                case TK_LE:
                case TK_GT:
                case TK_GE:
                case TK_NE:
                case TK_EQ:
                    {
                        testcase(op == TK_LT);
                        testcase(op == TK_LE);
                        testcase(op == TK_GT);
                        testcase(op == TK_GE);
                        testcase(op == TK_EQ);
                        testcase(op == TK_NE);
                        testcase(jumpIfNull == 0);
                        r1 = sqlite3ExprCodeTemp(pParse, pExpr.pLeft, ref regFree1);
                        r2 = sqlite3ExprCodeTemp(pParse, pExpr.pRight, ref regFree2);
                        codeCompare(pParse, pExpr.pLeft, pExpr.pRight, op,
                        r1, r2, dest, jumpIfNull);
                        testcase(regFree1 == 0);
                        testcase(regFree2 == 0);
                        break;
                    }
                case TK_IS:
                case TK_ISNOT:
                    {
                        testcase(pExpr.op == TK_IS);
                        testcase(pExpr.op == TK_ISNOT);
                        r1 = sqlite3ExprCodeTemp(pParse, pExpr.pLeft, ref regFree1);
                        r2 = sqlite3ExprCodeTemp(pParse, pExpr.pRight, ref regFree2);
                        op = (pExpr.op == TK_IS) ? TK_NE : TK_EQ;
                        codeCompare(pParse, pExpr.pLeft, pExpr.pRight, op,
                        r1, r2, dest, SQLITE_NULLEQ);
                        testcase(regFree1 == 0);
                        testcase(regFree2 == 0);
                        break;
                    }
                case TK_ISNULL:
                case TK_NOTNULL:
                    {
                        testcase(op == TK_ISNULL);
                        testcase(op == TK_NOTNULL);
                        r1 = sqlite3ExprCodeTemp(pParse, pExpr.pLeft, ref regFree1);
                        sqlite3VdbeAddOp2(v, op, r1, dest);
                        testcase(regFree1 == 0);
                        break;
                    }
                case TK_BETWEEN:
                    {
                        testcase(jumpIfNull == 0);
                        exprCodeBetween(pParse, pExpr, dest, 0, jumpIfNull);
                        break;
                    }
#if SQLITE_OMIT_SUBQUERY
        case TK_IN:
          {
            if ( jumpIfNull != 0 )
            {
              sqlite3ExprCodeIN( pParse, pExpr, dest, dest );
            }
            else
            {
              int destIfNull = sqlite3VdbeMakeLabel( v );
              sqlite3ExprCodeIN( pParse, pExpr, dest, destIfNull );
              sqlite3VdbeResolveLabel( v, destIfNull );
            }
          break;
          }
#endif
                default:
                    {
                        r1 = sqlite3ExprCodeTemp(pParse, pExpr, ref regFree1);
                        sqlite3VdbeAddOp3(v, OP_IfNot, r1, dest, jumpIfNull != 0 ? 1 : 0);
                        testcase(regFree1 == 0);
                        testcase(jumpIfNull == 0);
                        break;
                    }
            }
            sqlite3ReleaseTempReg(pParse, regFree1);
            sqlite3ReleaseTempReg(pParse, regFree2);
        }
Пример #8
0
 static Expr sqlite3PExpr(Parse pParse, int op, Expr pLeft, Expr pRight, int null_5)
 {
     return sqlite3PExpr(pParse, op, pLeft, pRight, null);
 }
Пример #9
0
 static Expr sqlite3PExpr(
 Parse pParse,          /* Parsing context */
 int op,                 /* Expression opcode */
 Expr pLeft,            /* Left operand */
 Expr pRight,           /* Right operand */
 Token pToken     /* Argument Token */
 )
 {
     Expr p = sqlite3ExprAlloc(pParse.db, op, pToken, 1);
     sqlite3ExprAttachSubtrees(pParse.db, p, pLeft, pRight);
     if (p != null)
     {
         sqlite3ExprCheckHeight(pParse, p.nHeight);
     }
     return p;
 }
Пример #10
0
        /*
        ** This function is similar to sqlite3ExprDup(), except that if pzBuffer
        ** is not NULL then *pzBuffer is assumed to point to a buffer large enough
        ** to store the copy of expression p, the copies of p->u.zToken
        ** (if applicable), and the copies of the p->pLeft and p->pRight expressions,
        ** if any. Before returning, *pzBuffer is set to the first byte passed the
        ** portion of the buffer copied into by this function.
        */
        static Expr exprDup(sqlite3 db, Expr p, int flags, ref Expr pzBuffer)
        {
            Expr pNew = null;                      /* Value to return */
            if (p != null)
            {
                bool isReduced = (flags & EXPRDUP_REDUCE) != 0;
                Expr zAlloc = new Expr();
                u32 staticFlag = 0;

                Debug.Assert(pzBuffer == null || isReduced);

                /* Figure out where to write the new Expr structure. */
                //if ( pzBuffer !=null)
                //{
                //  zAlloc = pzBuffer;
                //  staticFlag = EP_Static;
                //}
                //else
                //{
                ///Expr  zAlloc = new Expr();//sqlite3DbMallocRaw( db, dupedExprSize( p, flags ) );
                //}
                // (Expr)zAlloc;

                //if ( pNew != null )
                {
                    /* Set nNewSize to the size allocated for the structure pointed to
                    ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or
                    ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed
                    ** by the copy of the p->u.zToken string (if any).
                    */
                    int nStructSize = dupedExprStructSize(p, flags);
                    int nNewSize = nStructSize & 0xfff;
                    int nToken;
                    if (!ExprHasProperty(p, EP_IntValue) && !String.IsNullOrEmpty(p.u.zToken))
                    {
                        nToken = sqlite3Strlen30(p.u.zToken);
                    }
                    else
                    {
                        nToken = 0;
                    }
                    if (isReduced)
                    {
                        Debug.Assert(!ExprHasProperty(p, EP_Reduced));
                        pNew = p.Copy(EXPR_TOKENONLYSIZE);//memcpy( zAlloc, p, nNewSize );
                    }
                    else
                    {
                        int nSize = exprStructSize(p);
                        //memcpy( zAlloc, p, nSize );
                        pNew = p.Copy();
                        //memset( &zAlloc[nSize], 0, EXPR_FULLSIZE - nSize );
                    }

                    /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */
                    unchecked
                    {
                        pNew.flags &= (ushort)(~(EP_Reduced | EP_TokenOnly | EP_Static));
                    }
                    pNew.flags |= (ushort)(nStructSize & (EP_Reduced | EP_TokenOnly));
                    pNew.flags |= (ushort)staticFlag;

                    /* Copy the p->u.zToken string, if any. */
                    if (nToken != 0)
                    {
                        string zToken;// = pNew.u.zToken = (char)&zAlloc[nNewSize];
                        zToken = p.u.zToken.Substring(0, nToken);// memcpy( zToken, p.u.zToken, nToken );
                    }

                    if (0 == ((p.flags | pNew.flags) & EP_TokenOnly))
                    {
                        /* Fill in the pNew.x.pSelect or pNew.x.pList member. */
                        if (ExprHasProperty(p, EP_xIsSelect))
                        {
                            pNew.x.pSelect = sqlite3SelectDup(db, p.x.pSelect, isReduced ? 1 : 0);
                        }
                        else
                        {
                            pNew.x.pList = sqlite3ExprListDup(db, p.x.pList, isReduced ? 1 : 0);
                        }
                    }

                    /* Fill in pNew.pLeft and pNew.pRight. */
                    if (ExprHasAnyProperty(pNew, EP_Reduced | EP_TokenOnly))
                    {
                        //zAlloc += dupedExprNodeSize( p, flags );
                        if (ExprHasProperty(pNew, EP_Reduced))
                        {
                            pNew.pLeft = exprDup(db, p.pLeft, EXPRDUP_REDUCE, ref pzBuffer);
                            pNew.pRight = exprDup(db, p.pRight, EXPRDUP_REDUCE, ref pzBuffer);
                        }
                        //if ( pzBuffer != null )
                        //{
                        //  pzBuffer = zAlloc;
                        //}
                    }
                    else
                    {
                        pNew.flags2 = 0;
                        if (!ExprHasAnyProperty(p, EP_TokenOnly))
                        {
                            pNew.pLeft = sqlite3ExprDup(db, p.pLeft, 0);
                            pNew.pRight = sqlite3ExprDup(db, p.pRight, 0);
                        }
                    }
                }
            }
            return pNew;
        }
Пример #11
0
 /*
 ** Set the Expr.nHeight variable using the exprSetHeight() function. If
 ** the height is greater than the maximum allowed expression depth,
 ** leave an error in pParse.
 */
 static void sqlite3ExprSetHeight(Parse pParse, Expr p)
 {
     exprSetHeight(p);
     sqlite3ExprCheckHeight(pParse, p.nHeight);
 }
Пример #12
0
 /*
 ** The dupedExpr*Size() routines each return the number of bytes required
 ** to store a copy of an expression or expression tree.  They differ in
 ** how much of the tree is measured.
 **
 **     dupedExprStructSize()     Size of only the Expr structure
 **     dupedExprNodeSize()       Size of Expr + space for token
 **     dupedExprSize()           Expr + token + subtree components
 **
 ***************************************************************************
 **
 ** The dupedExprStructSize() function returns two values OR-ed together:
 ** (1) the space required for a copy of the Expr structure only and
 ** (2) the EP_xxx flags that indicate what the structure size should be.
 ** The return values is always one of:
 **
 **      EXPR_FULLSIZE
 **      EXPR_REDUCEDSIZE   | EP_Reduced
 **      EXPR_TOKENONLYSIZE | EP_TokenOnly
 **
 ** The size of the structure can be found by masking the return value
 ** of this routine with 0xfff.  The flags can be found by masking the
 ** return value with EP_Reduced|EP_TokenOnly.
 **
 ** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size
 ** (unreduced) Expr objects as they or originally constructed by the parser.
 ** During expression analysis, extra information is computed and moved into
 ** later parts of teh Expr object and that extra information might get chopped
 ** off if the expression is reduced.  Note also that it does not work to
 ** make a EXPRDUP_REDUCE copy of a reduced expression.  It is only legal
 ** to reduce a pristine expression tree from the parser.  The implementation
 ** of dupedExprStructSize() contain multiple Debug.Assert() statements that attempt
 ** to enforce this constraint.
 */
 static int dupedExprStructSize(Expr p, int flags)
 {
     int nSize;
     Debug.Assert(flags == EXPRDUP_REDUCE || flags == 0); /* Only one flag value allowed */
     if (0 == (flags & EXPRDUP_REDUCE))
     {
         nSize = EXPR_FULLSIZE;
     }
     else
     {
         Debug.Assert(!ExprHasAnyProperty(p, EP_TokenOnly | EP_Reduced));
         Debug.Assert(!ExprHasProperty(p, EP_FromJoin));
         Debug.Assert((p.flags2 & EP2_MallocedToken) == 0);
         Debug.Assert((p.flags2 & EP2_Irreducible) == 0);
         if (p.pLeft != null || p.pRight != null || p.pColl != null || p.x.pList != null || p.x.pSelect != null)
         {
             nSize = EXPR_REDUCEDSIZE | EP_Reduced;
         }
         else
         {
             nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly;
         }
     }
     return nSize;
 }
Пример #13
0
 /*
 ** Generate code that evalutes the given expression and puts the result
 ** in register target.
 **
 ** Also make a copy of the expression results into another "cache" register
 ** and modify the expression so that the next time it is evaluated,
 ** the result is a copy of the cache register.
 **
 ** This routine is used for expressions that are used multiple
 ** times.  They are evaluated once and the results of the expression
 ** are reused.
 */
 static int sqlite3ExprCodeAndCache(Parse pParse, Expr pExpr, int target)
 {
     Vdbe v = pParse.pVdbe;
     int inReg;
     inReg = sqlite3ExprCode(pParse, pExpr, target);
     Debug.Assert(target > 0);
     /* This routine is called for terms to INSERT or UPDATE.  And the only
     ** other place where expressions can be converted into TK_REGISTER is
     ** in WHERE clause processing.  So as currently implemented, there is
     ** no way for a TK_REGISTER to exist here.  But it seems prudent to
     ** keep the ALWAYS() in case the conditions above change with future
     ** modifications or enhancements. */
     if (ALWAYS(pExpr.op != TK_REGISTER))
     {
         int iMem;
         iMem = ++pParse.nMem;
         sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
         pExpr.iTable = iMem;
         pExpr.op2 = pExpr.op;
         pExpr.op = TK_REGISTER;
     }
     return inReg;
 }
Пример #14
0
        /*
        ** Assign a variable number to an expression that encodes a wildcard
        ** in the original SQL statement.
        **
        ** Wildcards consisting of a single "?" are assigned the next sequential
        ** variable number.
        **
        ** Wildcards of the form "?nnn" are assigned the number "nnn".  We make
        ** sure "nnn" is not too be to avoid a denial of service attack when
        ** the SQL statement comes from an external source.
        **
        ** Wildcards of the form ":aaa", "@aaa" or "$aaa" are assigned the same number
        ** as the previous instance of the same wildcard.  Or if this is the first
        ** instance of the wildcard, the next sequenial variable number is
        ** assigned.
        */
        static void sqlite3ExprAssignVarNumber(Parse pParse, Expr pExpr)
        {
            sqlite3 db = pParse.db;
            string z;

            if (pExpr == null)
                return;
            Debug.Assert(!ExprHasAnyProperty(pExpr, EP_IntValue | EP_Reduced | EP_TokenOnly));
            z = pExpr.u.zToken;
            Debug.Assert(z != null);
            Debug.Assert(z.Length != 0);
            if (z.Length == 1)
            {
                /* Wildcard of the form "?".  Assign the next variable number */
                Debug.Assert(z[0] == '?');
                pExpr.iColumn = (ynVar)(++pParse.nVar);
            }
            else
            {
                ynVar x = 0;
                int n = sqlite3Strlen30(z);
                if (z[0] == '?')
                {
                    /* Wildcard of the form "?nnn".  Convert "nnn" to an integer and
                    ** use it as the variable number */
                    long i = 0;
                    bool bOk = 0 == sqlite3Atoi64(z.Substring(1), ref i, n - 1, SQLITE_UTF8);
                    pExpr.iColumn = x = (ynVar)i;
                    testcase(i == 0);
                    testcase(i == 1);
                    testcase(i == db.aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] - 1);
                    testcase(i == db.aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
                    if (bOk == false || i < 1 || i > db.aLimit[SQLITE_LIMIT_VARIABLE_NUMBER])
                    {
                        sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
                        db.aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
                        x = 0;
                    }
                    if (i > pParse.nVar)
                    {
                        pParse.nVar = (int)i;
                    }
                }
                else
                {
                    /* Wildcards like ":aaa", "$aaa" or "@aaa".  Reuse the same variable
                    ** number as the prior appearance of the same name, or if the name
                    ** has never appeared before, reuse the same variable number
                    */
                    ynVar i;
                    for (i = 0; i < pParse.nzVar; i++)
                    {
                        if (pParse.azVar[i] != null && z.CompareTo(pParse.azVar[i]) == 0) //memcmp(pParse.azVar[i],z,n+1)==0 )
                        {
                            pExpr.iColumn = x = (ynVar)(i + 1);
                            break;
                        }
                    }
                    if (x == 0) x = pExpr.iColumn = (ynVar)(++pParse.nVar);
                }
                if (x > 0)
                {
                    if (x > pParse.nzVar)
                    {
                        //char **a;
                        //a = sqlite3DbRealloc(db, pParse.azVar, x*sizeof(a[0]));
                        //if( a==0 ) return;  /* Error reported through db.mallocFailed */
                        //pParse.azVar = a;
                        //memset(&a[pParse.nzVar], 0, (x-pParse.nzVar)*sizeof(a[0]));
                        Array.Resize(ref pParse.azVar, x);
                        pParse.nzVar = x;
                    }
                    if (z[0] != '?' || pParse.azVar[x - 1] == null)
                    {
                        //sqlite3DbFree(db, pParse.azVar[x-1]);
                        pParse.azVar[x - 1] = z.Substring(0, n);//sqlite3DbStrNDup( db, z, n );
                    }
                }
            }
            if (pParse.nErr == 0 && pParse.nVar > db.aLimit[SQLITE_LIMIT_VARIABLE_NUMBER])
            {
                sqlite3ErrorMsg(pParse, "too many SQL variables");
            }
        }
Пример #15
0
        /*
        ** Return TRUE if pExpr is an constant expression that is appropriate
        ** for factoring out of a loop.  Appropriate expressions are:
        **
        **    *  Any expression that evaluates to two or more opcodes.
        **
        **    *  Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null,
        **       or OP_Variable that does not need to be placed in a
        **       specific register.
        **
        ** There is no point in factoring out single-instruction constant
        ** expressions that need to be placed in a particular register.
        ** We could factor them out, but then we would end up adding an
        ** OP_SCopy instruction to move the value into the correct register
        ** later.  We might as well just use the original instruction and
        ** avoid the OP_SCopy.
        */
        static int isAppropriateForFactoring(Expr p)
        {
            if (sqlite3ExprIsConstantNotJoin(p) == 0)
            {
                return 0;  /* Only constant expressions are appropriate for factoring */
            }
            if ((p.flags & EP_FixedDest) == 0)
            {
                return 1;  /* Any constant without a fixed destination is appropriate */
            }
            while (p.op == TK_UPLUS)
                p = p.pLeft;
            switch (p.op)
            {
#if !SQLITE_OMIT_BLOB_LITERAL
                case TK_BLOB:
#endif
                case TK_VARIABLE:
                case TK_INTEGER:
                case TK_FLOAT:
                case TK_NULL:
                case TK_STRING:
                    {
                        testcase(p.op == TK_BLOB);
                        testcase(p.op == TK_VARIABLE);
                        testcase(p.op == TK_INTEGER);
                        testcase(p.op == TK_FLOAT);
                        testcase(p.op == TK_NULL);
                        testcase(p.op == TK_STRING);
                        /* Single-instruction constants with a fixed destination are
                        ** better done in-line.  If we factor them, they will just end
                        ** up generating an OP_SCopy to move the value to the destination
                        ** register. */
                        return 0;
                    }
                case TK_UMINUS:
                    {
                        if (p.pLeft.op == TK_FLOAT || p.pLeft.op == TK_INTEGER)
                        {
                            return 0;
                        }
                        break;
                    }
                default:
                    {
                        break;
                    }
            }
            return 1;
        }
Пример #16
0
//#define exprSetHeight(y)
#endif //* SQLITE_MAX_EXPR_DEPTH>0 */

        /*
** This routine is the core allocator for Expr nodes.
**
** Construct a new expression node and return a pointer to it.  Memory
** for this node and for the pToken argument is a single allocation
** obtained from sqlite3DbMalloc().  The calling function
** is responsible for making sure the node eventually gets freed.
**
** If dequote is true, then the token (if it exists) is dequoted.
** If dequote is false, no dequoting is performance.  The deQuote
** parameter is ignored if pToken is NULL or if the token does not
** appear to be quoted.  If the quotes were of the form "..." (double-quotes)
** then the EP_DblQuoted flag is set on the expression node.
**
** Special case:  If op==TK_INTEGER and pToken points to a string that
** can be translated into a 32-bit integer, then the token is not
** stored in u.zToken.  Instead, the integer values is written
** into u.iValue and the EP_IntValue flag is set.  No extra storage
** is allocated to hold the integer text and the dequote flag is ignored.
*/
        static Expr sqlite3ExprAlloc(
        sqlite3 db,           /* Handle for sqlite3DbMallocZero() (may be null) */
        int op,               /* Expression opcode */
        Token pToken,         /* Token argument.  Might be NULL */
        int dequote           /* True to dequote */
        )
        {
            Expr pNew;
            int nExtra = 0;
            int iValue = 0;

            if (pToken != null)
            {
                if (op != TK_INTEGER || pToken.z == null || pToken.z.Length == 0
                || sqlite3GetInt32(pToken.z.ToString(), ref iValue) == false)
                {
                    nExtra = pToken.n + 1;
                    Debug.Assert(iValue >= 0);
                }
            }
            pNew = new Expr();//sqlite3DbMallocZero(db, sizeof(Expr)+nExtra);
            if (pNew != null)
            {
                pNew.op = (byte)op;
                pNew.iAgg = -1;
                if (pToken != null)
                {
                    if (nExtra == 0)
                    {
                        pNew.flags |= EP_IntValue;
                        pNew.u.iValue = iValue;
                    }
                    else
                    {
                        int c;
                        //pNew.u.zToken = (char)&pNew[1];
                        if (pToken.n > 0)
                            pNew.u.zToken = pToken.z.Substring(0, pToken.n);//memcpy(pNew.u.zToken, pToken.z, pToken.n);
                        else if (pToken.n == 0 && pToken.z == "")
                            pNew.u.zToken = "";
                        //pNew.u.zToken[pToken.n] = 0;
                        if (dequote != 0 && nExtra >= 3
                        && ((c = pToken.z[0]) == '\'' || c == '"' || c == '[' || c == '`'))
                        {
#if DEBUG_CLASS_EXPR || DEBUG_CLASS_ALL
sqlite3Dequote(ref pNew.u._zToken);
#else
                            sqlite3Dequote(ref pNew.u.zToken);
#endif
                            if (c == '"')
                                pNew.flags |= EP_DblQuoted;
                        }
                    }
                }
#if SQLITE_MAX_EXPR_DEPTH//>0
                pNew.nHeight = 1;
#endif
            }
            return pNew;
        }
Пример #17
0
        /*
        ** Generate code for a boolean expression such that a jump is made
        ** to the label "dest" if the expression is true but execution
        ** continues straight thru if the expression is false.
        **
        ** If the expression evaluates to NULL (neither true nor false), then
        ** take the jump if the jumpIfNull flag is SQLITE_JUMPIFNULL.
        **
        ** This code depends on the fact that certain token values (ex: TK_EQ)
        ** are the same as opcode values (ex: OP_Eq) that implement the corresponding
        ** operation.  Special comments in vdbe.c and the mkopcodeh.awk script in
        ** the make process cause these values to align.  Assert()s in the code
        ** below verify that the numbers are aligned correctly.
        */
        static void sqlite3ExprIfTrue(Parse pParse, Expr pExpr, int dest, int jumpIfNull)
        {
            Vdbe v = pParse.pVdbe;
            int op = 0;
            int regFree1 = 0;
            int regFree2 = 0;
            int r1 = 0, r2 = 0;

            Debug.Assert(jumpIfNull == SQLITE_JUMPIFNULL || jumpIfNull == 0);
            if (NEVER(v == null))
                return;  /* Existance of VDBE checked by caller */
            if (NEVER(pExpr == null))
                return;  /* No way this can happen */
            op = pExpr.op;
            switch (op)
            {
                case TK_AND:
                    {
                        int d2 = sqlite3VdbeMakeLabel(v);
                        testcase(jumpIfNull == 0);
                        sqlite3ExprCachePush(pParse);
                        sqlite3ExprIfFalse(pParse, pExpr.pLeft, d2, jumpIfNull ^ SQLITE_JUMPIFNULL);
                        sqlite3ExprIfTrue(pParse, pExpr.pRight, dest, jumpIfNull);
                        sqlite3VdbeResolveLabel(v, d2);
                        sqlite3ExprCachePop(pParse, 1);
                        break;
                    }
                case TK_OR:
                    {
                        testcase(jumpIfNull == 0);
                        sqlite3ExprIfTrue(pParse, pExpr.pLeft, dest, jumpIfNull);
                        sqlite3ExprIfTrue(pParse, pExpr.pRight, dest, jumpIfNull);
                        break;
                    }
                case TK_NOT:
                    {
                        testcase(jumpIfNull == 0);
                        sqlite3ExprIfFalse(pParse, pExpr.pLeft, dest, jumpIfNull);
                        break;
                    }
                case TK_LT:
                case TK_LE:
                case TK_GT:
                case TK_GE:
                case TK_NE:
                case TK_EQ:
                    {
                        Debug.Assert(TK_LT == OP_Lt);
                        Debug.Assert(TK_LE == OP_Le);
                        Debug.Assert(TK_GT == OP_Gt);
                        Debug.Assert(TK_GE == OP_Ge);
                        Debug.Assert(TK_EQ == OP_Eq);
                        Debug.Assert(TK_NE == OP_Ne);
                        testcase(op == TK_LT);
                        testcase(op == TK_LE);
                        testcase(op == TK_GT);
                        testcase(op == TK_GE);
                        testcase(op == TK_EQ);
                        testcase(op == TK_NE);
                        testcase(jumpIfNull == 0);
                        r1 = sqlite3ExprCodeTemp(pParse, pExpr.pLeft, ref regFree1);
                        r2 = sqlite3ExprCodeTemp(pParse, pExpr.pRight, ref regFree2);
                        codeCompare(pParse, pExpr.pLeft, pExpr.pRight, op,
                        r1, r2, dest, jumpIfNull);
                        testcase(regFree1 == 0);
                        testcase(regFree2 == 0);
                        break;
                    }
                case TK_IS:
                case TK_ISNOT:
                    {
                        testcase(op == TK_IS);
                        testcase(op == TK_ISNOT);
                        r1 = sqlite3ExprCodeTemp(pParse, pExpr.pLeft, ref regFree1);
                        r2 = sqlite3ExprCodeTemp(pParse, pExpr.pRight, ref regFree2);
                        op = (op == TK_IS) ? TK_EQ : TK_NE;
                        codeCompare(pParse, pExpr.pLeft, pExpr.pRight, op,
                        r1, r2, dest, SQLITE_NULLEQ);
                        testcase(regFree1 == 0);
                        testcase(regFree2 == 0);
                        break;
                    }
                case TK_ISNULL:
                case TK_NOTNULL:
                    {
                        Debug.Assert(TK_ISNULL == OP_IsNull);
                        Debug.Assert(TK_NOTNULL == OP_NotNull);
                        testcase(op == TK_ISNULL);
                        testcase(op == TK_NOTNULL);
                        r1 = sqlite3ExprCodeTemp(pParse, pExpr.pLeft, ref regFree1);
                        sqlite3VdbeAddOp2(v, op, r1, dest);
                        testcase(regFree1 == 0);
                        break;
                    }
                case TK_BETWEEN:
                    {
                        testcase(jumpIfNull == 0);
                        exprCodeBetween(pParse, pExpr, dest, 1, jumpIfNull);
                        break;
                    }
#if SQLITE_OMIT_SUBQUERY
        case TK_IN:
          {
            int destIfFalse = sqlite3VdbeMakeLabel( v );
            int destIfNull = jumpIfNull != 0 ? dest : destIfFalse;
            sqlite3ExprCodeIN( pParse, pExpr, destIfFalse, destIfNull );
            sqlite3VdbeAddOp2( v, OP_Goto, 0, dest );
            sqlite3VdbeResolveLabel( v, destIfFalse );
            break;
          }
#endif
                default:
                    {
                        r1 = sqlite3ExprCodeTemp(pParse, pExpr, ref regFree1);
                        sqlite3VdbeAddOp3(v, OP_If, r1, dest, jumpIfNull != 0 ? 1 : 0);
                        testcase(regFree1 == 0);
                        testcase(jumpIfNull == 0);
                        break;
                    }
            }
            sqlite3ReleaseTempReg(pParse, regFree1);
            sqlite3ReleaseTempReg(pParse, regFree2);
        }
Пример #18
0
        /*
        ** Generate code for a BETWEEN operator.
        **
        **    x BETWEEN y AND z
        **
        ** The above is equivalent to 
        **
        **    x>=y AND x<=z
        **
        ** Code it as such, taking care to do the common subexpression
        ** elementation of x.
        */
        static void exprCodeBetween(
        Parse pParse,     /* Parsing and code generating context */
        Expr pExpr,       /* The BETWEEN expression */
        int dest,         /* Jump here if the jump is taken */
        int jumpIfTrue,   /* Take the jump if the BETWEEN is true */
        int jumpIfNull    /* Take the jump if the BETWEEN is NULL */
        )
        {
            Expr exprAnd = new Expr();   /* The AND operator in  x>=y AND x<=z  */
            Expr compLeft = new Expr();  /* The  x>=y  term */
            Expr compRight = new Expr(); /* The  x<=z  term */
            Expr exprX;       /* The  x  subexpression */
            int regFree1 = 0; /* Temporary use register */

            Debug.Assert(!ExprHasProperty(pExpr, EP_xIsSelect));
            exprX = pExpr.pLeft.Copy();
            exprAnd.op = TK_AND;
            exprAnd.pLeft = compLeft;
            exprAnd.pRight = compRight;
            compLeft.op = TK_GE;
            compLeft.pLeft = exprX;
            compLeft.pRight = pExpr.x.pList.a[0].pExpr;
            compRight.op = TK_LE;
            compRight.pLeft = exprX;
            compRight.pRight = pExpr.x.pList.a[1].pExpr;
            exprX.iTable = sqlite3ExprCodeTemp(pParse, exprX, ref regFree1);
            exprX.op = TK_REGISTER;
            if (jumpIfTrue != 0)
            {
                sqlite3ExprIfTrue(pParse, exprAnd, dest, jumpIfNull);
            }
            else
            {
                sqlite3ExprIfFalse(pParse, exprAnd, dest, jumpIfNull);
            }
            sqlite3ReleaseTempReg(pParse, regFree1);

            /* Ensure adequate test coverage */
            testcase(jumpIfTrue == 0 && jumpIfNull == 0 && regFree1 == 0);
            testcase(jumpIfTrue == 0 && jumpIfNull == 0 && regFree1 != 0);
            testcase(jumpIfTrue == 0 && jumpIfNull != 0 && regFree1 == 0);
            testcase(jumpIfTrue == 0 && jumpIfNull != 0 && regFree1 != 0);
            testcase(jumpIfTrue != 0 && jumpIfNull == 0 && regFree1 == 0);
            testcase(jumpIfTrue != 0 && jumpIfNull == 0 && regFree1 != 0);
            testcase(jumpIfTrue != 0 && jumpIfNull != 0 && regFree1 == 0);
            testcase(jumpIfTrue != 0 && jumpIfNull != 0 && regFree1 != 0);
        }
Пример #19
0
 /*
 ** Preevaluate constant subexpressions within pExpr and store the
 ** results in registers.  Modify pExpr so that the constant subexpresions
 ** are TK_REGISTER opcodes that refer to the precomputed values.
 **
 ** This routine is a no-op if the jump to the cookie-check code has
 ** already occur.  Since the cookie-check jump is generated prior to
 ** any other serious processing, this check ensures that there is no
 ** way to accidently bypass the constant initializations.
 **
 ** This routine is also a no-op if the SQLITE_FactorOutConst optimization
 ** is disabled via the sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS)
 ** interface.  This allows test logic to verify that the same answer is
 ** obtained for queries regardless of whether or not constants are
 ** precomputed into registers or if they are inserted in-line.
 */
 static void sqlite3ExprCodeConstants(Parse pParse, Expr pExpr)
 {
     Walker w;
     if (pParse.cookieGoto != 0)
         return;
     if ((pParse.db.flags & SQLITE_FactorOutConst) != 0)
         return;
     w = new Walker();
     w.xExprCallback = (dxExprCallback)evalConstExpr;
     w.xSelectCallback = null;
     w.pParse = pParse;
     sqlite3WalkExpr(w, ref pExpr);
 }
Пример #20
0
 /*
 ** If pExpr is a constant expression that is appropriate for
 ** factoring out of a loop, then evaluate the expression
 ** into a register and convert the expression into a TK_REGISTER
 ** expression.
 */
 static int evalConstExpr(Walker pWalker, ref Expr pExpr)
 {
     Parse pParse = pWalker.pParse;
     switch (pExpr.op)
     {
         case TK_IN:
         case TK_REGISTER:
             {
                 return WRC_Prune;
             }
         case TK_FUNCTION:
         case TK_AGG_FUNCTION:
         case TK_CONST_FUNC:
             {
                 /* The arguments to a function have a fixed destination.
                 ** Mark them this way to avoid generated unneeded OP_SCopy
                 ** instructions.
                 */
                 ExprList pList = pExpr.x.pList;
                 Debug.Assert(!ExprHasProperty(pExpr, EP_xIsSelect));
                 if (pList != null)
                 {
                     int i = pList.nExpr;
                     ExprList_item pItem;//= pList.a;
                     for (; i > 0; i--)
                     {//, pItem++){
                         pItem = pList.a[pList.nExpr - i];
                         if (ALWAYS(pItem.pExpr != null))
                             pItem.pExpr.flags |= EP_FixedDest;
                     }
                 }
                 break;
             }
     }
     if (isAppropriateForFactoring(pExpr) != 0)
     {
         int r1 = ++pParse.nMem;
         int r2;
         r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
         if (NEVER(r1 != r2))
             sqlite3ReleaseTempReg(pParse, r1);
         pExpr.op2 = pExpr.op;
         pExpr.op = TK_REGISTER;
         pExpr.iTable = r2;
         return WRC_Prune;
     }
     return WRC_Continue;
 }
Пример #21
0
        /*
        ** Recursively delete an expression tree.
        */
        static void sqlite3ExprDelete(sqlite3 db, ref Expr p)
        {
            if (p == null)
                return;
            /* Sanity check: Assert that the IntValue is non-negative if it exists */
            Debug.Assert(!ExprHasProperty(p, EP_IntValue) || p.u.iValue >= 0);
            if (!ExprHasAnyProperty(p, EP_TokenOnly))
            {
                sqlite3ExprDelete(db, ref p.pLeft);
                sqlite3ExprDelete(db, ref p.pRight);
                if (!ExprHasProperty(p, EP_Reduced) && (p.flags2 & EP2_MallocedToken) != 0)
                {
#if DEBUG_CLASS_EXPR || DEBUG_CLASS_ALL
sqlite3DbFree( db, ref p.u._zToken );
#else
                    sqlite3DbFree(db, ref p.u.zToken);
#endif
                }
                if (ExprHasProperty(p, EP_xIsSelect))
                {
                    sqlite3SelectDelete(db, ref p.x.pSelect);
                }
                else
                {
                    sqlite3ExprListDelete(db, ref p.x.pList);
                }
            }
            if (!ExprHasProperty(p, EP_Static))
            {
                sqlite3DbFree(db, ref p);
            }
        }
Пример #22
0
 /*
 ** Do a deep comparison of two expression trees.  Return 0 if the two
 ** expressions are completely identical.  Return 1 if they differ only
 ** by a COLLATE operator at the top level.  Return 2 if there are differences
 ** other than the top-level COLLATE operator.
 **
 ** Sometimes this routine will return 2 even if the two expressions
 ** really are equivalent.  If we cannot prove that the expressions are
 ** identical, we return 2 just to be safe.  So if this routine
 ** returns 2, then you do not really know for certain if the two
 ** expressions are the same.  But if you get a 0 or 1 return, then you
 ** can be sure the expressions are the same.  In the places where
 ** this routine is used, it does not hurt to get an extra 2 - that
 ** just might result in some slightly slower code.  But returning
 ** an incorrect 0 or 1 could lead to a malfunction.
 */
 static int sqlite3ExprCompare(Expr pA, Expr pB)
 {
     if (pA == null || pB == null)
     {
         return pB == pA ? 0 : 2;
     }
     Debug.Assert(!ExprHasAnyProperty(pA, EP_TokenOnly | EP_Reduced));
     Debug.Assert(!ExprHasAnyProperty(pB, EP_TokenOnly | EP_Reduced));
     if (ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect))
     {
         return 2;
     }
     if ((pA.flags & EP_Distinct) != (pB.flags & EP_Distinct))
         return 2;
     if (pA.op != pB.op)
         return 2;
     if (sqlite3ExprCompare(pA.pLeft, pB.pLeft) != 0)
         return 2;
     if (sqlite3ExprCompare(pA.pRight, pB.pRight) != 0)
         return 2;
     if (sqlite3ExprListCompare(pA.x.pList, pB.x.pList) != 0)
         return 2;
     if (pA.iTable != pB.iTable || pA.iColumn != pB.iColumn)
         return 2;
     if (ExprHasProperty(pA, EP_IntValue))
     {
         if (!ExprHasProperty(pB, EP_IntValue) || pA.u.iValue != pB.u.iValue)
         {
             return 2;
         }
     }
     else if (pA.op != TK_COLUMN && pA.u.zToken != null)
     {
         if (ExprHasProperty(pB, EP_IntValue) || NEVER(pB.u.zToken == null))
             return 2;
         if (!pA.u.zToken.Equals(pB.u.zToken, StringComparison.InvariantCultureIgnoreCase))
         {
             return 2;
         }
     }
     if ((pA.flags & EP_ExpCollate) != (pB.flags & EP_ExpCollate))
         return 1;
     if ((pA.flags & EP_ExpCollate) != 0 && pA.pColl != pB.pColl)
         return 2;
     return 0;
 }
Пример #23
0
 /*
 ** Return the number of bytes allocated for the expression structure
 ** passed as the first argument. This is always one of EXPR_FULLSIZE,
 ** EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE.
 */
 static int exprStructSize(Expr p)
 {
     if (ExprHasProperty(p, EP_TokenOnly))
         return EXPR_TOKENONLYSIZE;
     if (ExprHasProperty(p, EP_Reduced))
         return EXPR_REDUCEDSIZE;
     return EXPR_FULLSIZE;
 }
Пример #24
0
        /*
        ** This is the xExprCallback for a tree walker.  It is used to
        ** implement sqlite3ExprAnalyzeAggregates().  See sqlite3ExprAnalyzeAggregates
        ** for additional information.
        */
        static int analyzeAggregate(Walker pWalker, ref Expr pExpr)
        {
            int i;
            NameContext pNC = pWalker.u.pNC;
            Parse pParse = pNC.pParse;
            SrcList pSrcList = pNC.pSrcList;
            AggInfo pAggInfo = pNC.pAggInfo;

            switch (pExpr.op)
            {
                case TK_AGG_COLUMN:
                case TK_COLUMN:
                    {
                        testcase(pExpr.op == TK_AGG_COLUMN);
                        testcase(pExpr.op == TK_COLUMN);
                        /* Check to see if the column is in one of the tables in the FROM
                        ** clause of the aggregate query */
                        if (ALWAYS(pSrcList != null))
                        {
                            SrcList_item pItem;// = pSrcList.a;
                            for (i = 0; i < pSrcList.nSrc; i++)
                            {//, pItem++){
                                pItem = pSrcList.a[i];
                                AggInfo_col pCol;
                                Debug.Assert(!ExprHasAnyProperty(pExpr, EP_TokenOnly | EP_Reduced));
                                if (pExpr.iTable == pItem.iCursor)
                                {
                                    /* If we reach this point, it means that pExpr refers to a table
                                    ** that is in the FROM clause of the aggregate query.
                                    **
                                    ** Make an entry for the column in pAggInfo.aCol[] if there
                                    ** is not an entry there already.
                                    */
                                    int k;
                                    //pCol = pAggInfo.aCol;
                                    for (k = 0; k < pAggInfo.nColumn; k++)
                                    {//, pCol++){
                                        pCol = pAggInfo.aCol[k];
                                        if (pCol.iTable == pExpr.iTable &&
                                        pCol.iColumn == pExpr.iColumn)
                                        {
                                            break;
                                        }
                                    }
                                    if ((k >= pAggInfo.nColumn)
                                    && (k = addAggInfoColumn(pParse.db, pAggInfo)) >= 0
                                    )
                                    {
                                        pCol = pAggInfo.aCol[k];
                                        pCol.pTab = pExpr.pTab;
                                        pCol.iTable = pExpr.iTable;
                                        pCol.iColumn = pExpr.iColumn;
                                        pCol.iMem = ++pParse.nMem;
                                        pCol.iSorterColumn = -1;
                                        pCol.pExpr = pExpr;
                                        if (pAggInfo.pGroupBy != null)
                                        {
                                            int j, n;
                                            ExprList pGB = pAggInfo.pGroupBy;
                                            ExprList_item pTerm;// = pGB.a;
                                            n = pGB.nExpr;
                                            for (j = 0; j < n; j++)
                                            {//, pTerm++){
                                                pTerm = pGB.a[j];
                                                Expr pE = pTerm.pExpr;
                                                if (pE.op == TK_COLUMN && pE.iTable == pExpr.iTable &&
                                                pE.iColumn == pExpr.iColumn)
                                                {
                                                    pCol.iSorterColumn = j;
                                                    break;
                                                }
                                            }
                                        }
                                        if (pCol.iSorterColumn < 0)
                                        {
                                            pCol.iSorterColumn = pAggInfo.nSortingColumn++;
                                        }
                                    }
                                    /* There is now an entry for pExpr in pAggInfo.aCol[] (either
                                    ** because it was there before or because we just created it).
                                    ** Convert the pExpr to be a TK_AGG_COLUMN referring to that
                                    ** pAggInfo.aCol[] entry.
                                    */
                                    ExprSetIrreducible(pExpr);
                                    pExpr.pAggInfo = pAggInfo;
                                    pExpr.op = TK_AGG_COLUMN;
                                    pExpr.iAgg = (short)k;
                                    break;
                                } /* endif pExpr.iTable==pItem.iCursor */
                            } /* end loop over pSrcList */
                        }
                        return WRC_Prune;
                    }
                case TK_AGG_FUNCTION:
                    {
                        /* The pNC.nDepth==0 test causes aggregate functions in subqueries
                        ** to be ignored */
                        if (pNC.nDepth == 0)
                        {
                            /* Check to see if pExpr is a duplicate of another aggregate
                            ** function that is already in the pAggInfo structure
                            */
                            AggInfo_func pItem;// = pAggInfo.aFunc;
                            for (i = 0; i < pAggInfo.nFunc; i++)
                            {//, pItem++){
                                pItem = pAggInfo.aFunc[i];
                                if (sqlite3ExprCompare(pItem.pExpr, pExpr) == 0)
                                {
                                    break;
                                }
                            }
                            if (i >= pAggInfo.nFunc)
                            {
                                /* pExpr is original.  Make a new entry in pAggInfo.aFunc[]
                                */
                                u8 enc = pParse.db.aDbStatic[0].pSchema.enc;// ENC(pParse.db);
                                i = addAggInfoFunc(pParse.db, pAggInfo);
                                if (i >= 0)
                                {
                                    Debug.Assert(!ExprHasProperty(pExpr, EP_xIsSelect));
                                    pItem = pAggInfo.aFunc[i];
                                    pItem.pExpr = pExpr;
                                    pItem.iMem = ++pParse.nMem;
                                    Debug.Assert(!ExprHasProperty(pExpr, EP_IntValue));
                                    pItem.pFunc = sqlite3FindFunction(pParse.db,
                                    pExpr.u.zToken, sqlite3Strlen30(pExpr.u.zToken),
                                    pExpr.x.pList != null ? pExpr.x.pList.nExpr : 0, enc, 0);
                                    if ((pExpr.flags & EP_Distinct) != 0)
                                    {
                                        pItem.iDistinct = pParse.nTab++;
                                    }
                                    else
                                    {
                                        pItem.iDistinct = -1;
                                    }
                                }
                            }
                            /* Make pExpr point to the appropriate pAggInfo.aFunc[] entry
                            */
                            Debug.Assert(!ExprHasAnyProperty(pExpr, EP_TokenOnly | EP_Reduced));
                            ExprSetIrreducible(pExpr);
                            pExpr.iAgg = (short)i;
                            pExpr.pAggInfo = pAggInfo;
                            return WRC_Prune;
                        }
                        break;
                    }
            }
            return WRC_Continue;
        }
Пример #25
0
 /*
 ** This function returns the space in bytes required to store the copy
 ** of the Expr structure and a copy of the Expr.u.zToken string (if that
 ** string is defined.)
 */
 static int dupedExprNodeSize(Expr p, int flags)
 {
     int nByte = dupedExprStructSize(p, flags) & 0xfff;
     if (!ExprHasProperty(p, EP_IntValue) && p.u.zToken != null)
     {
         nByte += sqlite3Strlen30(p.u.zToken) + 1;
     }
     return ROUND8(nByte);
 }
Пример #26
0
 /*
 ** Analyze the given expression looking for aggregate functions and
 ** for variables that need to be added to the pParse.aAgg[] array.
 ** Make additional entries to the pParse.aAgg[] array as necessary.
 **
 ** This routine should only be called after the expression has been
 ** analyzed by sqlite3ResolveExprNames().
 */
 static void sqlite3ExprAnalyzeAggregates(NameContext pNC, ref Expr pExpr)
 {
     Walker w = new Walker();
     w.xExprCallback = (dxExprCallback)analyzeAggregate;
     w.xSelectCallback = (dxSelectCallback)analyzeAggregatesInSelect;
     w.u.pNC = pNC;
     Debug.Assert(pNC.pSrcList != null);
     sqlite3WalkExpr(w, ref pExpr);
 }
Пример #27
0
 /*
 ** Return the number of bytes required to create a duplicate of the
 ** expression passed as the first argument. The second argument is a
 ** mask containing EXPRDUP_XXX flags.
 **
 ** The value returned includes space to create a copy of the Expr struct
 ** itself and the buffer referred to by Expr.u.zToken, if any.
 **
 ** If the EXPRDUP_REDUCE flag is set, then the return value includes
 ** space to duplicate all Expr nodes in the tree formed by Expr.pLeft
 ** and Expr.pRight variables (but not for any structures pointed to or
 ** descended from the Expr.x.pList or Expr.x.pSelect variables).
 */
 static int dupedExprSize(Expr p, int flags)
 {
     int nByte = 0;
     if (p != null)
     {
         nByte = dupedExprNodeSize(p, flags);
         if ((flags & EXPRDUP_REDUCE) != 0)
         {
             nByte += dupedExprSize(p.pLeft, flags) + dupedExprSize(p.pRight, flags);
         }
     }
     return nByte;
 }
Пример #28
0
 /*
 ** Attach subtrees pLeft and pRight to the Expr node pRoot.
 **
 ** If pRoot==NULL that means that a memory allocation error has occurred.
 ** In that case, delete the subtrees pLeft and pRight.
 */
 static void sqlite3ExprAttachSubtrees(
 sqlite3 db,
 Expr pRoot,
 Expr pLeft,
 Expr pRight
 )
 {
     if (pRoot == null)
     {
         //Debug.Assert( db.mallocFailed != 0 );
         sqlite3ExprDelete(db, ref pLeft);
         sqlite3ExprDelete(db, ref pRight);
     }
     else
     {
         if (pRight != null)
         {
             pRoot.pRight = pRight;
             if ((pRight.flags & EP_ExpCollate) != 0)
             {
                 pRoot.flags |= EP_ExpCollate;
                 pRoot.pColl = pRight.pColl;
             }
         }
         if (pLeft != null)
         {
             pRoot.pLeft = pLeft;
             if ((pLeft.flags & EP_ExpCollate) != 0)
             {
                 pRoot.flags |= EP_ExpCollate;
                 pRoot.pColl = pLeft.pColl;
             }
         }
         exprSetHeight(pRoot);
     }
 }
Пример #29
0
 /*
 ** The following group of routines make deep copies of expressions,
 ** expression lists, ID lists, and select statements.  The copies can
 ** be deleted (by being passed to their respective ...Delete() routines)
 ** without effecting the originals.
 **
 ** The expression list, ID, and source lists return by sqlite3ExprListDup(),
 ** sqlite3IdListDup(), and sqlite3SrcListDup() can not be further expanded
 ** by subsequent calls to sqlite*ListAppend() routines.
 **
 ** Any tables that the SrcList might point to are not duplicated.
 **
 ** The flags parameter contains a combination of the EXPRDUP_XXX flags.
 ** If the EXPRDUP_REDUCE flag is set, then the structure returned is a
 ** truncated version of the usual Expr structure that will be stored as
 ** part of the in-memory representation of the database schema.
 */
 static Expr sqlite3ExprDup(sqlite3 db, Expr p, int flags)
 {
     Expr ExprDummy = null;
     return exprDup(db, p, flags, ref ExprDummy);
 }
Пример #30
0
 static Expr sqlite3PExpr(Parse pParse, int op, Expr pLeft, int null_4, Token pToken)
 {
     return sqlite3PExpr(pParse, op, pLeft, null, pToken);
 }