public async Task <IActionResult> Index()
        {
            var db = new NameContext();

            db.Add <Name>(new Name
            {
                FirstName = "Trausti Thor",
                LastName  = "Johannsson"
            });
            db.Add <Name>(new Name
            {
                FirstName = "Elsa Þóra",
                LastName  = "Eggerstdóttir"
            });
            db.Add <Name>(new Name
            {
                FirstName = "Ósk",
                LastName  = "Traustadóttir"
            });
            db.Add <Name>(new Name
            {
                FirstName = "Íris Rós",
                LastName  = "Traustadóttir"
            });

            await db.SaveChangesAsync();

            return(Ok());
        }
        /// <inheritdoc/>
        public string ToDelimitedString()
        {
            System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
            string separator = IsSubcomponent ? Configuration.SubcomponentSeparator : Configuration.ComponentSeparator;

            return(string.Format(
                       culture,
                       StringHelper.StringFormatSequence(0, 15, separator),
                       FamilyName?.ToDelimitedString(),
                       GivenName,
                       SecondAndFurtherGivenNamesOrInitialsThereof,
                       Suffix,
                       Prefix,
                       Degree,
                       NameTypeCode,
                       NameRepresentationCode,
                       NameContext?.ToDelimitedString(),
                       NameValidityRange?.ToDelimitedString(),
                       NameAssemblyOrder,
                       EffectiveDate.HasValue ? EffectiveDate.Value.ToString(Consts.DateTimeFormatPrecisionSecond, culture) : null,
                       ExpirationDate.HasValue ? ExpirationDate.Value.ToString(Consts.DateTimeFormatPrecisionSecond, culture) : null,
                       ProfessionalSuffix,
                       CalledBy
                       ).TrimEnd(separator.ToCharArray()));
        }
Esempio n. 3
0
 internal virtual void AssertCanAppend(DomNode node, DomNode willReplace)
 {
     if (node.IsElement || node.IsAttribute)
     {
         NameContext.DemandValidName(nameof(node), node);
     }
 }
        /// <inheritdoc/>
        public string ToDelimitedString()
        {
            System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
            string separator = IsSubcomponent ? Configuration.SubcomponentSeparator : Configuration.ComponentSeparator;

            return(string.Format(
                       culture,
                       StringHelper.StringFormatSequence(0, 18, separator),
                       PersonIdentifier,
                       FamilyName?.ToDelimitedString(),
                       GivenName,
                       SecondAndFurtherGivenNamesOrInitialsThereof,
                       Suffix,
                       Prefix,
                       Degree,
                       SourceTable,
                       AssigningAuthority?.ToDelimitedString(),
                       NameTypeCode,
                       IdentifierCheckDigit,
                       CheckDigitScheme,
                       IdentifierTypeCode,
                       AssigningFacility?.ToDelimitedString(),
                       NameRepresentationCode,
                       NameContext?.ToDelimitedString(),
                       NameValidityRange?.ToDelimitedString(),
                       NameAssemblyOrder
                       ).TrimEnd(separator.ToCharArray()));
        }
        /// <inheritdoc/>
        public string ToDelimitedString()
        {
            System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;
            string separator = IsSubcomponent ? Configuration.SubcomponentSeparator : Configuration.ComponentSeparator;

            return(string.Format(
                       culture,
                       StringHelper.StringFormatSequence(0, 23, separator),
                       PersonIdentifier,
                       FamilyName?.ToDelimitedString(),
                       GivenName,
                       SecondAndFurtherGivenNamesOrInitialsThereof,
                       Suffix,
                       Prefix,
                       Degree,
                       SourceTable,
                       AssigningAuthority?.ToDelimitedString(),
                       NameTypeCode,
                       IdentifierCheckDigit,
                       CheckDigitScheme,
                       IdentifierTypeCode,
                       AssigningFacility?.ToDelimitedString(),
                       NameRepresentationCode,
                       NameContext?.ToDelimitedString(),
                       NameValidityRange?.ToDelimitedString(),
                       NameAssemblyOrder,
                       EffectiveDate.HasValue ? EffectiveDate.Value.ToString(Consts.DateTimeFormatPrecisionSecond, culture) : null,
                       ExpirationDate.HasValue ? ExpirationDate.Value.ToString(Consts.DateTimeFormatPrecisionSecond, culture) : null,
                       ProfessionalSuffix,
                       AssigningJurisdiction?.ToDelimitedString(),
                       AssigningAgencyOrDepartment?.ToDelimitedString()
                       ).TrimEnd(separator.ToCharArray()));
        }
 protected virtual void RenderName(HtmlTextWriter output, string id, NameContext context)
 {
     Assert.ArgumentNotNull(output, "output");
     Assert.ArgumentNotNullOrEmpty(id, "id");
     if (!context.Editable)
     {
         output.Write("<span class='header-title'>");
         output.Write(context.Name);
         output.Write("</span>");
     }
     else
     {
         output.Write("<a href='#' class='header-title'>");
         output.Write(StringUtil.EscapeQuote(context.Name));
         output.Write("</a>");
         string str  = "onkeydown='javascript:return Sitecore.CollapsiblePanel.editNameChanging(this, event);'";
         string str2 = string.IsNullOrEmpty(context.OnNameChanging)
                                         ? string.Empty
                                         : ("onkeyup=\"" + context.OnNameChanging + "\"");
         string str3 = string.IsNullOrEmpty(context.OnNameChanged)
                                         ? string.Empty
                                         : ("onchange=\"" + context.OnNameChanged + "\"");
         output.Write(
             "<input type='text' {0} {1} id='{2}_name' name='{2}_name' data-meta-id='{2}' data-validation-msg=\"{3}\" style='display:none' class='header-title-edit' value=\"{4}\" {5} />",
             new object[]
             { str2, str3, id, Translate.Text("The name cannot be blank."), StringUtil.EscapeQuote(context.Name), str });
     }
 }
        // Methods
        public string Render(string id, string panelHtml, bool draggable, NameContext nameContext,
                             ActionsContext actionsContext)
        {
            Assert.ArgumentNotNullOrEmpty(id, "id");
            Assert.ArgumentNotNullOrEmpty(panelHtml, "panelHtml");
            var output = new HtmlTextWriter(new StringWriter());

            output.Write("<div id='{0}' class='{1}'>", id, CssClass);
            output.Write("<div id='{0}_header' class='panel-header'>", id);
            output.Write("<div class='header-actions'>");
            output.Write("<a href='#'>");
            output.Write("<div class='icon-expand'></div>");
            output.Write("</a>");
            output.Write("</div>");
            RenderActions(output, id, actionsContext);
            if (draggable)
            {
                output.Write("<img src='/sitecore modules/shell/analytics/images/draghandle9x15.png' class='drag-handle' />");
            }
            RenderName(output, id, nameContext);
            output.Write("</div>");
            output.Write("<div id='{0}_panel' class='panel'>", id);
            output.Write(panelHtml);
            output.Write("</div>");
            output.Write("</div>");
            return(output.InnerWriter.ToString());
        }
Esempio n. 8
0
        public NameAnalyser(NameContext context, NameAnalysisOptions options)
        {
            if (context == null)
                throw new ArgumentNullException("context");
            if (options == null)
                throw new ArgumentNullException("options");

            this.context = context;
            this.options = options;
        }
            public virtual string ToString(char separator)
            {
                var ns = NextSeparator(separator);

                return
                    ($"{FamilyName}{separator}{GivenName}{separator}{SecondGivenNamesOrInitials}" +
                     $"{separator}{Suffix}{separator}{Prefix}{separator}{Degree.BestValue}{separator}" +
                     $"{NameTypeCode.BestValue}{separator}{NameRepresentationCode.BestValue}{separator}" +
                     $"{NameContext?.ToString(ns)}{separator}{NameAssemblyOrder?.BestValue}"
                     .TrimEnd(separator));
            }
Esempio n. 10
0
        public override string VisitName(NameContext context)
        {
            if (context.TEXT() != null)
            {
                return(Text(context.TEXT()));
            }

            return(context.RANDOMNAME() != null
               ? Generator.FullName
               : "Nameless");
        }
Esempio n. 11
0
        public static void ResolveSelectNames(Parse parse, Select p, NameContext outerNC)
        {
            Debug.Assert(p != null);
            Walker w = new Walker();

            w.ExprCallback   = ResolveExprStep;
            w.SelectCallback = ResolveSelectStep;
            w.Parse          = parse;
            w.u.NC           = outerNC;
            w.WalkSelect(p);
        }
Esempio n. 12
0
        static bool ResolveOrderGroupBy(NameContext nc, Select select, ExprList orderBy, string type)
        {
            if (orderBy == null)
            {
                return(false);
            }
            int   result = select.EList.Exprs; // Number of terms in the result set
            Parse parse  = nc.Parse;           // Parsing context
            int   i;

            ExprList.ExprListItem item; // A term of the ORDER BY clause
            for (i = 0; i < orderBy.Exprs; i++)
            {
                item = orderBy.Ids[i];
                Expr expr  = item.Expr;
                int  colId = ResolveAsName(parse, select.EList, expr); // Column number
                if (colId > 0)
                {
                    // If an AS-name match is found, mark this ORDER BY column as being a copy of the iCol-th result-set column.  The subsequent call to
                    // sqlite3ResolveOrderGroupBy() will convert the expression to a copy of the iCol-th result-set expression.
                    item.OrderByCol = (ushort)colId;
                    continue;
                }
                if (expr.SkipCollate().IsInteger(ref colId))
                {
                    // The ORDER BY term is an integer constant.  Again, set the column number so that sqlite3ResolveOrderGroupBy() will convert the
                    // order-by term to a copy of the result-set expression
                    if (colId < 1 || colId > 0xffff)
                    {
                        ResolveOutOfRangeError(parse, type, i + 1, result);
                        return(true);
                    }
                    item.OrderByCol = (ushort)colId;
                    continue;
                }

                // Otherwise, treat the ORDER BY term as an ordinary expression
                item.OrderByCol = 0;
                if (Walker.ResolveExprNames(nc, ref expr))
                {
                    return(true);
                }
                for (int j = 0; j < select.EList.Exprs; j++)
                {
                    if (Expr.Compare(expr, select.EList.Ids[j].Expr) == 0)
                    {
                        item.OrderByCol = (ushort)(j + 1);
                    }
                }
            }
            return(Walker.ResolveOrderGroupBy(parse, select, orderBy, type));
        }
Esempio n. 13
0
            public override string ToString(char separator)
            {
                var ns = NextSeparator(separator);

                return
                    ($"{ID}{separator}{FamilyName}{separator}{GivenName}{separator}{SecondGivenNamesOrInitials}" +
                     $"{separator}{Suffix}{separator}{Prefix}{separator}{Degree}{separator}" +
                     $"{SourceTable}{separator}{AssigningAuthority?.ToString(ns)}{separator}" +
                     $"{NameTypeCode}{separator}{IdentifierCheckDigit}{separator}{CheckDigitScheme}{separator}" +
                     $"{IdentifierTypeCode}{separator}{AssigningFacility?.ToString(ns)}{separator}" +
                     $"{NameRepresentationCode}{separator}{NameContext?.ToString(ns)}{separator}" +
                     $"{NameValidityRange?.ToString(ns)}{separator}{NameAssemblyOrder}"
                     .TrimEnd(separator));
            }
Esempio n. 14
0
        public NameAnalyser(NameContext context, NameAnalysisOptions options)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }

            this.context = context;
            this.options = options;
        }
        public override object VisitLine(SpeakParser.LineContext context)
        {
            NameContext    name    = context.name();
            OpinionContext opinion = context.opinion();

            SpeakLine line = new SpeakLine()
            {
                Person = name.GetText(), Text = opinion.GetText().Trim('"')
            };

            Lines.Add(line);

            return(line);
        }
Esempio n. 16
0
        static void CodeAttach(Parse parse, AUTH type, FuncDef func, Expr authArg, Expr filename, Expr dbName, Expr key)
        {
            Context ctx = parse.Ctx;

            NameContext sName;

            sName       = new NameContext();
            sName.Parse = parse;

            if (ResolveAttachExpr(sName, filename) != RC.OK || ResolveAttachExpr(sName, dbName) != RC.OK || ResolveAttachExpr(sName, key) != RC.OK)
            {
                parse.Errs++;
                goto attach_end;
            }

#if !OMIT_AUTHORIZATION
            if (authArg != null)
            {
                string authArgToken = (authArg.OP == TK.STRING ? authArg.u.Token : null);
                ARC    arc          = Auth.Check(parse, type, authArgToken, null, null);
                if (arc != ARC.OK)
                {
                    goto attach_end;
                }
            }
#endif
            Vdbe v       = parse.GetVdbe();
            int  regArgs = Expr.GetTempRange(parse, 4);
            Expr.Code(parse, filename, regArgs);
            Expr.Code(parse, dbName, regArgs + 1);
            Expr.Code(parse, key, regArgs + 2);

            Debug.Assert(v != null || ctx.MallocFailed);
            if (v != null)
            {
                v.AddOp3(OP.Function, 0, regArgs + 3 - func.Args, regArgs + 3);
                Debug.Assert(func.Args == -1 || (func.Args & 0xff) == func.Args);
                v.ChangeP5((byte)(func.Args));
                v.ChangeP4(-1, func, Vdbe.P4T.FUNCDEF);

                // Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this statement only). For DETACH, set it to false (expire all existing statements).
                v.AddOp1(OP.Expire, (type == AUTH.ATTACH ? 1 : 0));
            }

attach_end:
            Expr.Delete(ctx, ref filename);
            Expr.Delete(ctx, ref dbName);
            Expr.Delete(ctx, ref key);
        }
Esempio n. 17
0
        public override object VisitName(NameContext context)
        {
            var obj = "";

            foreach (var i in range(0, context.id().Length - 1, 1, true, true))
            {
                var id = (Result)(Visit(context.id(i)));
                if (i == 0)
                {
                    obj += id.text;
                }
                else
                {
                    obj += "." + id.text;
                }
            }
            return(obj);
        }
Esempio n. 18
0
        public override object VisitName([NotNull] NameContext context)
        {
            var obj = "";

            for (int i = 0; i < context.id().Length; i++)
            {
                var id = (Result)Visit(context.id(i));
                if (i == 0)
                {
                    obj += "" + id.text;
                }
                else
                {
                    obj += "." + id.text;
                }
            }
            return(obj);
        }
Esempio n. 19
0
        /// <summary>
        /// Disposes of the database context if possible and then initialises a new instance.
        /// </summary>
        private void InitContext()
        {
            // if the context is not null and RecycleContext is enabled,
            // dispose of the current context
            if (this.context != null && this.RecycleContext)
            {
                this.context.Dispose();
                this.context = null;
            }

            // initialise the database context
            if (this.context == null)
            {
                this.context = new NameContext();
                this.context.Configuration.ValidateOnSaveEnabled    = false;
                this.context.Configuration.AutoDetectChangesEnabled = false;
            }
        }
Esempio n. 20
0
 static void Main(string[] args)
 {
     if (args.Length == 0)
     {
         Console.WriteLine("Generate basic code files.");
     }
     else if (args[0][0] == '/')
     {
         Console.WriteLine("There is no flags.");
     }
     else
     {
         var ctx = new NameContext(args);
         var fg  = new FileGenerator(ctx);
         fg.CreateFolder();
         fg.CreateFiles();
     }
 }
Esempio n. 21
0
        public override object VisitName(NameContext context)
        {
            var obj = "";

            foreach (var(i, v) in context.id().WithIndex())
            {
                var id = ((Result)Visit(v));
                if (i == 0)
                {
                    obj += id.text;
                }
                else
                {
                    obj += "." + id.text;
                }
            }
            return(obj);
        }
Esempio n. 22
0
 static RC ResolveAttachExpr(NameContext name, Expr expr)
 {
     RC rc = RC.OK;
     if (expr != null)
     {
         if (expr.OP != TK.ID)
         {
             rc = sqlite3ResolveExprNames(name, ref expr);
             if (rc == RC.OK && !expr.IsConstant())
             {
                 name.Parse.ErrorMsg("invalid name: \"%s\"", expr.u.Token);
                 return RC.ERROR;
             }
         }
         else
             expr.OP = TK.STRING;
     }
     return rc;
 }
Esempio n. 23
0
        public override string TransformName(IMetaInfo info, string name, NameContext context)
        {
            var prefix       = string.Empty;
            var suffix       = string.Empty;
            var forBlueprint = true;

            if (info is TypeInfo typeInfo)
            {
                var asBaseClass = false;

                typeInfo.ForAttribute <UnrealTypeAttributeBase>(attr =>
                {
                    forBlueprint = attr.ForBlueprint;

                    prefix      = forBlueprint ? "U" : "F";
                    asBaseClass = attr.AsBaseClass;
                });

                typeInfo.ForAttribute <UnrealActorAttribute>(attr =>
                {
                    prefix = "A";
                    suffix = "Actor";
                });

                typeInfo.ForAttribute <UnrealComponentAttribute>(attr =>
                {
                    suffix = "Component";
                });

                typeInfo.ForAttribute <UnrealStructAttribute>(attr =>
                {
                    prefix = "F";
                });

                if (asBaseClass)
                {
                    suffix += "Base";
                }
            }

            return($"{prefix}{name.ToPascalCase()}{suffix}");
        }
Esempio n. 24
0
        public static bool ResolveExprNames(NameContext nc, ref Expr expr)
        {
            if (expr == null)
            {
                return(false);
            }
#if MAX_EXPR_DEPTH
            {
                Parse parse = nc.Parse;
                if (Expr.CheckHeight(parse, expr.Height + nc.Parse.Height) != 0)
                {
                    return(true);
                }
                parse.Height += expr.Height;
            }
#endif
            bool savedHasAgg = ((nc.NCFlags & NC.HasAgg) != 0);
            nc.NCFlags &= ~NC.HasAgg;
            Walker w = new Walker();
            w.ExprCallback   = ResolveExprStep;
            w.SelectCallback = ResolveSelectStep;
            w.Parse          = nc.Parse;
            w.u.NC           = nc;
            w.WalkExpr(expr);
#if MAX_EXPR_DEPTH
            nc.Parse.Height -= expr.Height;
#endif
            if (nc.Errs > 0 || w.Parse.Errs > 0)
            {
                E.ExprSetProperty(expr, EP.Error);
            }
            if ((nc.NCFlags & NC.HasAgg) != 0)
            {
                E.ExprSetProperty(expr, EP.Agg);
            }
            else if (savedHasAgg)
            {
                nc.NCFlags |= NC.HasAgg;
            }
            return(E.ExprHasProperty(expr, EP.Error));
        }
Esempio n. 25
0
/*
** 2003 April 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the ATTACH and DETACH commands.
*************************************************************************
**  Included in SQLite3 port to C#-SQLite;  2008 Noah B Hart
**  C#-SQLite is an independent reimplementation of the SQLite software library
**
**  SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2
**
*************************************************************************
*/
//#include "sqliteInt.h"

#if !SQLITE_OMIT_ATTACH
/*
** Resolve an expression that was part of an ATTACH or DETACH statement. This
** is slightly different from resolving a normal SQL expression, because simple
** identifiers are treated as strings, not possible column names or aliases.
**
** i.e. if the parser sees:
**
**     ATTACH DATABASE abc AS def
**
** it treats the two expressions as literal strings 'abc' and 'def' instead of
** looking for columns of the same name.
**
** This only applies to the root node of pExpr, so the statement:
**
**     ATTACH DATABASE abc||def AS 'db2'
**
** will fail because neither abc or def can be resolved.
*/
static int resolveAttachExpr( NameContext pName, Expr pExpr )
{
  int rc = SQLITE_OK;
  if ( pExpr != null )
  {
    if ( pExpr.op != TK_ID )
    {
      rc = sqlite3ResolveExprNames( pName, ref pExpr );
      if ( rc == SQLITE_OK && sqlite3ExprIsConstant( pExpr ) == 0 )
      {
        sqlite3ErrorMsg( pName.pParse, "invalid name: \"%s\"", pExpr.u.zToken );
        return SQLITE_ERROR;
      }
    }
    else
    {
      pExpr.op = TK_STRING;
    }
  }
  return rc;
}
Esempio n. 26
0
    public NameContext name()
    {
        NameContext _localctx = new NameContext(Context, State);

        EnterRule(_localctx, 4, RULE_name);
        try {
            EnterOuterAlt(_localctx, 1);
            {
                State = 19; Match(WORD);
            }
        }
        catch (RecognitionException re) {
            _localctx.exception = re;
            ErrorHandler.ReportError(this, re);
            ErrorHandler.Recover(this, re);
        }
        finally {
            ExitRule();
        }
        return(_localctx);
    }
Esempio n. 27
0
        static RC ResolveAttachExpr(NameContext name, Expr expr)
        {
            RC rc = RC.OK;

            if (expr != null)
            {
                if (expr.OP != TK.ID)
                {
                    rc = sqlite3ResolveExprNames(name, ref expr);
                    if (rc == RC.OK && !expr.IsConstant())
                    {
                        name.Parse.ErrorMsg("invalid name: \"%s\"", expr.u.Token);
                        return(RC.ERROR);
                    }
                }
                else
                {
                    expr.OP = TK.STRING;
                }
            }
            return(rc);
        }
Esempio n. 28
0
        /*
        ** 2003 April 6
        **
        ** The author disclaims copyright to this source code.  In place of
        ** a legal notice, here is a blessing:
        **
        **    May you do good and not evil.
        **    May you find forgiveness for yourself and forgive others.
        **    May you share freely, never taking more than you give.
        **
        *************************************************************************
        ** This file contains code used to implement the ATTACH and DETACH commands.
        **
        ** $Id: attach.c,v 1.93 2009/05/31 21:21:41 drh Exp $
        **
        *************************************************************************
        **  Included in SQLite3 port to C#-SQLite;  2008 Noah B Hart
        **  C#-SQLite is an independent reimplementation of the SQLite software library
        **
        **  $Header$
        *************************************************************************
        */
        //#include "sqliteInt.h"

#if !SQLITE_OMIT_ATTACH
        /*
        ** Resolve an expression that was part of an ATTACH or DETACH statement. This
        ** is slightly different from resolving a normal SQL expression, because simple
        ** identifiers are treated as strings, not possible column names or aliases.
        **
        ** i.e. if the parser sees:
        **
        **     ATTACH DATABASE abc AS def
        **
        ** it treats the two expressions as literal strings 'abc' and 'def' instead of
        ** looking for columns of the same name.
        **
        ** This only applies to the root node of pExpr, so the statement:
        **
        **     ATTACH DATABASE abc||def AS 'db2'
        **
        ** will fail because neither abc or def can be resolved.
        */
        static int resolveAttachExpr(NameContext pName, Expr pExpr)
        {
            int rc = SQLITE_OK;

            if (pExpr != null)
            {
                if (pExpr.op != TK_ID)
                {
                    rc = sqlite3ResolveExprNames(pName, ref pExpr);
                    if (rc == SQLITE_OK && sqlite3ExprIsConstant(pExpr) == 0)
                    {
                        sqlite3ErrorMsg(pName.pParse, "invalid name: \"%s\"", pExpr.u.zToken);
                        return(SQLITE_ERROR);
                    }
                }
                else
                {
                    pExpr.op = TK_STRING;
                }
            }
            return(rc);
        }
Esempio n. 29
0
        static int ResolveOrderByTermToExprList(Parse parse, Select select, Expr expr)
        {
            int i = 0;

            Debug.Assert(!expr.IsInteger(ref i));
            ExprList list = select.EList;       // The columns of the result set
            // Resolve all names in the ORDER BY term expression
            NameContext nc = new NameContext(); // Name context for resolving pE

            nc.Parse   = parse;
            nc.SrcList = select.Src;
            nc.EList   = list;
            nc.NCFlags = NC.AllowAgg;
            nc.Errs    = 0;
            Context ctx          = parse.Ctx;       // Database connection
            byte    savedSuppErr = ctx.SuppressErr; // Saved value of db->suppressErr

            ctx.SuppressErr = 1;
            bool r = Walker.ResolveExprNames(nc, ref expr);

            ctx.SuppressErr = savedSuppErr;
            if (r)
            {
                return(0);
            }
            // Try to match the ORDER BY expression against an expression in the result set.  Return an 1-based index of the matching result-set entry.
            for (i = 0; i < list.Exprs; i++)
            {
                if (Expr.Compare(list.Ids[i].Expr, expr) < 2)
                {
                    return(i + 1);
                }
            }
            // If no match, return 0.
            return(0);
        }
Esempio n. 30
0
    /*
    ** Resolve all names in all expressions of a SELECT and in all
    ** decendents of the SELECT, including compounds off of p.pPrior,
    ** subqueries in expressions, and subqueries used as FROM clause
    ** terms.
    **
    ** See sqlite3ResolveExprNames() for a description of the kinds of
    ** transformations that occur.
    **
    ** All SELECT statements should have been expanded using
    ** sqlite3SelectExpand() prior to invoking this routine.
    */
    static void sqlite3ResolveSelectNames(
    Parse pParse,         /* The parser context */
    Select p,             /* The SELECT statement being coded. */
    NameContext pOuterNC  /* Name context for parent SELECT statement */
    )
    {
      Walker w = new Walker();

      Debug.Assert( p != null );
      w.xExprCallback = resolveExprStep;
      w.xSelectCallback = resolveSelectStep;
      w.pParse = pParse;
      w.u.pNC = pOuterNC;
      sqlite3WalkSelect( w, p );
    }
Esempio n. 31
0
    /*
    ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
    ** that name in the set of source tables in pSrcList and make the pExpr
    ** expression node refer back to that source column.  The following changes
    ** are made to pExpr:
    **
    **    pExpr->iDb           Set the index in db->aDb[] of the database X
    **                         (even if X is implied).
    **    pExpr->iTable        Set to the cursor number for the table obtained
    **                         from pSrcList.
    **    pExpr->pTab          Points to the Table structure of X.Y (even if
    **                         X and/or Y are implied.)
    **    pExpr->iColumn       Set to the column number within the table.
    **    pExpr->op            Set to TK_COLUMN.
    **    pExpr->pLeft         Any expression this points to is deleted
    **    pExpr->pRight        Any expression this points to is deleted.
    **
    ** The zDb variable is the name of the database (the "X").  This value may be
    ** NULL meaning that name is of the form Y.Z or Z.  Any available database
    ** can be used.  The zTable variable is the name of the table (the "Y").  This
    ** value can be NULL if zDb is also NULL.  If zTable is NULL it
    ** means that the form of the name is Z and that columns from any table
    ** can be used.
    **
    ** If the name cannot be resolved unambiguously, leave an error message
    ** in pParse and return WRC_Abort.  Return WRC_Prune on success.
    */
    static int lookupName(
    Parse pParse,       /* The parsing context */
    string zDb,         /* Name of the database containing table, or NULL */
    string zTab,        /* Name of table containing column, or NULL */
    string zCol,        /* Name of the column. */
    NameContext pNC,    /* The name context used to resolve the name */
    Expr pExpr          /* Make this EXPR node point to the selected column */
    )
    {
      int i, j;            /* Loop counters */
      int cnt = 0;                      /* Number of matching column names */
      int cntTab = 0;                   /* Number of matching table names */
      sqlite3 db = pParse.db;         /* The database connection */
      SrcList_item pItem;       /* Use for looping over pSrcList items */
      SrcList_item pMatch = null;  /* The matching pSrcList item */
      NameContext pTopNC = pNC;        /* First namecontext in the list */
      Schema pSchema = null;              /* Schema of the expression */
      int isTrigger = 0;

      Debug.Assert( pNC != null ); /* the name context cannot be NULL. */
      Debug.Assert( zCol != null );    /* The Z in X.Y.Z cannot be NULL */
      Debug.Assert( !ExprHasAnyProperty( pExpr, EP_TokenOnly | EP_Reduced ) );

      /* Initialize the node to no-match */
      pExpr.iTable = -1;
      pExpr.pTab = null;
      ExprSetIrreducible( pExpr );

      /* Start at the inner-most context and move outward until a match is found */
      while ( pNC != null && cnt == 0 )
      {
        ExprList pEList;
        SrcList pSrcList = pNC.pSrcList;

        if ( pSrcList != null )
        {
          for ( i = 0; i < pSrcList.nSrc; i++ )//, pItem++ )
          {
            pItem = pSrcList.a[i];
            Table pTab;
            int iDb;
            Column pCol;

            pTab = pItem.pTab;
            Debug.Assert( pTab != null && pTab.zName != null );
            iDb = sqlite3SchemaToIndex( db, pTab.pSchema );
            Debug.Assert( pTab.nCol > 0 );
            if ( zTab != null )
            {
              if ( pItem.zAlias != null )
              {
                string zTabName = pItem.zAlias;
                if ( !zTabName.Equals( zTab, StringComparison.OrdinalIgnoreCase ) )
                  continue;
              }
              else
              {
                string zTabName = pTab.zName;
                if ( NEVER( zTabName == null ) || !zTabName.Equals( zTab ,StringComparison.OrdinalIgnoreCase )  )
                {
                  continue;
                }
                if ( zDb != null && !db.aDb[iDb].zName.Equals( zDb ,StringComparison.OrdinalIgnoreCase )  )
                {
                  continue;
                }
              }
            }
            if ( 0 == ( cntTab++ ) )
            {
              pExpr.iTable = pItem.iCursor;
              pExpr.pTab = pTab;
              pSchema = pTab.pSchema;
              pMatch = pItem;
            }
            for ( j = 0; j < pTab.nCol; j++ )//, pCol++ )
            {
              pCol = pTab.aCol[j];
              if ( pCol.zName.Equals( zCol, StringComparison.OrdinalIgnoreCase ) )
              {
                IdList pUsing;
                cnt++;
                pExpr.iTable = pItem.iCursor;
                pExpr.pTab = pTab;
                pMatch = pItem;
                pSchema = pTab.pSchema;
                /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
                pExpr.iColumn = (short)( j == pTab.iPKey ? -1 : j );
                if ( i < pSrcList.nSrc - 1 )
                {
                  if ( ( pSrcList.a[i + 1].jointype & JT_NATURAL ) != 0 )// pItem[1].jointype
                  {
                    /* If this match occurred in the left table of a natural join,
                    ** then skip the right table to avoid a duplicate match */
                    //pItem++;
                    i++;
                  }
                  else if ( ( pUsing = pSrcList.a[i + 1].pUsing ) != null )//pItem[1].pUsing
                  {
                    /* If this match occurs on a column that is in the USING clause
                    ** of a join, skip the search of the right table of the join
                    ** to avoid a duplicate match there. */
                    int k;
                    for ( k = 0; k < pUsing.nId; k++ )
                    {
                      if ( pUsing.a[k].zName.Equals( zCol ,StringComparison.OrdinalIgnoreCase )  )
                      {
                        //pItem++;
                        i++;
                        break;
                      }
                    }
                  }
                }
                break;
              }
            }
          }
        }

#if !SQLITE_OMIT_TRIGGER
        /* If we have not already resolved the name, then maybe
        ** it is a new.* or old.* trigger argument reference
        */
        if ( zDb == null && zTab != null && cnt == 0 && pParse.pTriggerTab != null )
        {
          int op = pParse.eTriggerOp;
          Table pTab = null;
          Debug.Assert( op == TK_DELETE || op == TK_UPDATE || op == TK_INSERT );
          if ( op != TK_DELETE && "new".Equals( zTab ,StringComparison.OrdinalIgnoreCase )  )
          {
            pExpr.iTable = 1;
            pTab = pParse.pTriggerTab;
          }
          else if ( op != TK_INSERT && "old".Equals( zTab ,StringComparison.OrdinalIgnoreCase )  )
          {
            pExpr.iTable = 0;
            pTab = pParse.pTriggerTab;
          }

          if ( pTab != null )
          {
            int iCol;
            pSchema = pTab.pSchema;
            cntTab++;
            for ( iCol = 0; iCol < pTab.nCol; iCol++ )
            {
              Column pCol = pTab.aCol[iCol];
              if ( pCol.zName.Equals( zCol ,StringComparison.OrdinalIgnoreCase )  )
              {
                if ( iCol == pTab.iPKey )
                {
                  iCol = -1;
                }
                break;
              }
            }
            if ( iCol >= pTab.nCol && sqlite3IsRowid( zCol ) )
            {
              iCol = -1;        /* IMP: R-44911-55124 */
            }
            if ( iCol < pTab.nCol )
            {
              cnt++;
              if ( iCol < 0 )
              {
                pExpr.affinity = SQLITE_AFF_INTEGER;
              }
              else if ( pExpr.iTable == 0 )
              {
                testcase( iCol == 31 );
                testcase( iCol == 32 );
                pParse.oldmask |= ( iCol >= 32 ? 0xffffffff : ( ( (u32)1 ) << iCol ) );
              }
              else
              {
                testcase( iCol == 31 );
                testcase( iCol == 32 );
                pParse.newmask |= ( iCol >= 32 ? 0xffffffff : ( ( (u32)1 ) << iCol ) );
              }
              pExpr.iColumn = (i16)iCol;
              pExpr.pTab = pTab;
              isTrigger = 1;
            }
          }
        }
#endif //* !SQLITE_OMIT_TRIGGER) */

        /*
        ** Perhaps the name is a reference to the ROWID
        */
        if ( cnt == 0 && cntTab == 1 && sqlite3IsRowid( zCol ) )
        {
          cnt = 1;
          pExpr.iColumn = -1; /* IMP: R-44911-55124 */
          pExpr.affinity = SQLITE_AFF_INTEGER;
        }

        /*
        ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
        ** might refer to an result-set alias.  This happens, for example, when
        ** we are resolving names in the WHERE clause of the following command:
        **
        **     SELECT a+b AS x FROM table WHERE x<10;
        **
        ** In cases like this, replace pExpr with a copy of the expression that
        ** forms the result set entry ("a+b" in the example) and return immediately.
        ** 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 = pNC.pEList ) != null && zTab == null )
        {
          for ( j = 0; j < pEList.nExpr; j++ )
          {
            string zAs = pEList.a[j].zName;
            if ( zAs != null && zAs.Equals( zCol ,StringComparison.OrdinalIgnoreCase )  )
            {
              Expr pOrig;
              Debug.Assert( pExpr.pLeft == null && pExpr.pRight == null );
              Debug.Assert( pExpr.x.pList == null );
              Debug.Assert( pExpr.x.pSelect == null );
              pOrig = pEList.a[j].pExpr;
              if ( 0 == pNC.allowAgg && ExprHasProperty( pOrig, EP_Agg ) )
              {
                sqlite3ErrorMsg( pParse, "misuse of aliased aggregate %s", zAs );
                return WRC_Abort;
              }
              resolveAlias( pParse, pEList, j, pExpr, "" );
              cnt = 1;
              pMatch = null;
              Debug.Assert( zTab == null && zDb == null );
              goto lookupname_end;
            }
          }
        }

        /* Advance to the next name context.  The loop will exit when either
        ** we have a match (cnt>0) or when we run out of name contexts.
        */
        if ( cnt == 0 )
        {
          pNC = pNC.pNext;
        }
      }

      /*
      ** If X and Y are NULL (in other words if only the column name Z is
      ** supplied) and the value of Z is enclosed in double-quotes, then
      ** Z is a string literal if it doesn't match any column names.  In that
      ** case, we need to return right away and not make any changes to
      ** pExpr.
      **
      ** Because no reference was made to outer contexts, the pNC.nRef
      ** fields are not changed in any context.
      */
      if ( cnt == 0 && zTab == null && ExprHasProperty( pExpr, EP_DblQuoted ) )
      {
        pExpr.op = TK_STRING;
        pExpr.pTab = null;
        return WRC_Prune;
      }

      /*
      ** cnt==0 means there was not match.  cnt>1 means there were two or
      ** more matches.  Either way, we have an error.
      */
      if ( cnt != 1 )
      {
        string zErr;
        zErr = cnt == 0 ? "no such column" : "ambiguous column name";
        if ( zDb != null )
        {
          sqlite3ErrorMsg( pParse, "%s: %s.%s.%s", zErr, zDb, zTab, zCol );
        }
        else if ( zTab != null )
        {
          sqlite3ErrorMsg( pParse, "%s: %s.%s", zErr, zTab, zCol );
        }
        else
        {
          sqlite3ErrorMsg( pParse, "%s: %s", zErr, zCol );
        }
        pParse.checkSchema = 1;
        pTopNC.nErr++;
      }

      /* If a column from a table in pSrcList is referenced, then record
      ** this fact in the pSrcList.a[].colUsed bitmask.  Column 0 causes
      ** bit 0 to be set.  Column 1 sets bit 1.  And so forth.  If the
      ** column number is greater than the number of bits in the bitmask
      ** then set the high-order bit of the bitmask.
      */
      if ( pExpr.iColumn >= 0 && pMatch != null )
      {
        int n = pExpr.iColumn;
        testcase( n == BMS - 1 );
        if ( n >= BMS )
        {
          n = BMS - 1;
        }
        Debug.Assert( pMatch.iCursor == pExpr.iTable );
        pMatch.colUsed |= ( (Bitmask)1 ) << n;
      }

      /* Clean up and return
      */
      sqlite3ExprDelete( db, ref pExpr.pLeft );
      pExpr.pLeft = null;
      sqlite3ExprDelete( db, ref pExpr.pRight );
      pExpr.pRight = null;
      pExpr.op = (u8)( isTrigger != 0 ? TK_TRIGGER : TK_COLUMN );
lookupname_end:
      if ( cnt == 1 )
      {
        Debug.Assert( pNC != null );
        sqlite3AuthRead( pParse, pExpr, pSchema, pNC.pSrcList );
        /* Increment the nRef value on all name contexts from TopNC up to
        ** the point where the name matched. */
        for ( ; ; )
        {
          Debug.Assert( pTopNC != null );
          pTopNC.nRef++;
          if ( pTopNC == pNC )
            break;
          pTopNC = pTopNC.pNext;
        }
        return WRC_Prune;
      }
      else
      {
        return WRC_Abort;
      }
    }
Esempio n. 32
0
    /*
    ** This function is called to generate code executed when a row is deleted
    ** from the parent table of foreign key constraint pFKey and, if pFKey is 
    ** deferred, when a row is inserted into the same table. When generating
    ** code for an SQL UPDATE operation, this function may be called twice -
    ** once to "delete" the old row and once to "insert" the new row.
    **
    ** The code generated by this function scans through the rows in the child
    ** table that correspond to the parent table row being deleted or inserted.
    ** For each child row found, one of the following actions is taken:
    **
    **   Operation | FK type   | Action taken
    **   --------------------------------------------------------------------------
    **   DELETE      immediate   Increment the "immediate constraint counter".
    **                           Or, if the ON (UPDATE|DELETE) action is RESTRICT,
    **                           throw a "foreign key constraint failed" exception.
    **
    **   INSERT      immediate   Decrement the "immediate constraint counter".
    **
    **   DELETE      deferred    Increment the "deferred constraint counter".
    **                           Or, if the ON (UPDATE|DELETE) action is RESTRICT,
    **                           throw a "foreign key constraint failed" exception.
    **
    **   INSERT      deferred    Decrement the "deferred constraint counter".
    **
    ** These operations are identified in the comment at the top of this file 
    ** (fkey.c) as "I.2" and "D.2".
    */
    static void fkScanChildren(
      Parse pParse,                   /* Parse context */
      SrcList pSrc,                   /* SrcList containing the table to scan */
      Table pTab,
      Index pIdx,                     /* Foreign key index */
      FKey pFKey,                     /* Foreign key relationship */
      int[] aiCol,                    /* Map from pIdx cols to child table cols */
      int regData,                    /* Referenced table data starts here */
      int nIncr                       /* Amount to increment deferred counter by */
    )
    {
      sqlite3 db = pParse.db;        /* Database handle */
      int i;                          /* Iterator variable */
      Expr pWhere = null;             /* WHERE clause to scan with */
      NameContext sNameContext;       /* Context used to resolve WHERE clause */
      WhereInfo pWInfo;               /* Context used by sqlite3WhereXXX() */
      int iFkIfZero = 0;              /* Address of OP_FkIfZero */
      Vdbe v = sqlite3GetVdbe( pParse );

      Debug.Assert( null == pIdx || pIdx.pTable == pTab );

      if ( nIncr < 0 )
      {
        iFkIfZero = sqlite3VdbeAddOp2( v, OP_FkIfZero, pFKey.isDeferred, 0 );
      }

      /* Create an Expr object representing an SQL expression like:
      **
      **   <parent-key1> = <child-key1> AND <parent-key2> = <child-key2> ...
      **
      ** The collation sequence used for the comparison should be that of
      ** the parent key columns. The affinity of the parent key column should
      ** be applied to each child key value before the comparison takes place.
      */
      for ( i = 0; i < pFKey.nCol; i++ )
      {
        Expr pLeft;                  /* Value from parent table row */
        Expr pRight;                 /* Column ref to child table */
        Expr pEq;                    /* Expression (pLeft = pRight) */
        int iCol;                     /* Index of column in child table */
        string zCol;             /* Name of column in child table */

        pLeft = sqlite3Expr( db, TK_REGISTER, null );
        if ( pLeft != null )
        {
          /* Set the collation sequence and affinity of the LHS of each TK_EQ
          ** expression to the parent key column defaults.  */
          if ( pIdx != null )
          {
            Column pCol;
            iCol = pIdx.aiColumn[i];
            pCol = pTab.aCol[iCol];
            if ( pTab.iPKey == iCol )
              iCol = -1;
            pLeft.iTable = regData + iCol + 1;
            pLeft.affinity = pCol.affinity;
            pLeft.pColl = sqlite3LocateCollSeq( pParse, pCol.zColl );
          }
          else
          {
            pLeft.iTable = regData;
            pLeft.affinity = SQLITE_AFF_INTEGER;
          }
        }
        iCol = aiCol != null ? aiCol[i] : pFKey.aCol[0].iFrom;
        Debug.Assert( iCol >= 0 );
        zCol = pFKey.pFrom.aCol[iCol].zName;
        pRight = sqlite3Expr( db, TK_ID, zCol );
        pEq = sqlite3PExpr( pParse, TK_EQ, pLeft, pRight, 0 );
        pWhere = sqlite3ExprAnd( db, pWhere, pEq );
      }

      /* If the child table is the same as the parent table, and this scan
      ** is taking place as part of a DELETE operation (operation D.2), omit the
      ** row being deleted from the scan by adding ($rowid != rowid) to the WHERE 
      ** clause, where $rowid is the rowid of the row being deleted.  */
      if ( pTab == pFKey.pFrom && nIncr > 0 )
      {
        Expr pEq;                    /* Expression (pLeft = pRight) */
        Expr pLeft;                  /* Value from parent table row */
        Expr pRight;                 /* Column ref to child table */
        pLeft = sqlite3Expr( db, TK_REGISTER, null );
        pRight = sqlite3Expr( db, TK_COLUMN, null );
        if ( pLeft != null && pRight != null )
        {
          pLeft.iTable = regData;
          pLeft.affinity = SQLITE_AFF_INTEGER;
          pRight.iTable = pSrc.a[0].iCursor;
          pRight.iColumn = -1;
        }
        pEq = sqlite3PExpr( pParse, TK_NE, pLeft, pRight, 0 );
        pWhere = sqlite3ExprAnd( db, pWhere, pEq );
      }

      /* Resolve the references in the WHERE clause. */
      sNameContext = new NameContext();// memset( &sNameContext, 0, sizeof( NameContext ) );
      sNameContext.pSrcList = pSrc;
      sNameContext.pParse = pParse;
      sqlite3ResolveExprNames( sNameContext, ref pWhere );

      /* Create VDBE to loop through the entries in pSrc that match the WHERE
      ** clause. If the constraint is not deferred, throw an exception for
      ** each row found. Otherwise, for deferred constraints, increment the
      ** deferred constraint counter by nIncr for each row selected.  */
      ExprList elDummy = null;
      pWInfo = sqlite3WhereBegin( pParse, pSrc, pWhere, ref elDummy, 0 );
      if ( nIncr > 0 && pFKey.isDeferred == 0 )
      {
        sqlite3ParseToplevel( pParse ).mayAbort = 1;
      }
      sqlite3VdbeAddOp2( v, OP_FkCounter, pFKey.isDeferred, nIncr );
      if ( pWInfo != null )
      {
        sqlite3WhereEnd( pWInfo );
      }

      /* Clean up the WHERE clause constructed above. */
      sqlite3ExprDelete( db, ref pWhere );
      if ( iFkIfZero != 0 )
      {
        sqlite3VdbeJumpHere( v, iFkIfZero );
      }
    }
Esempio n. 33
0
    /*
    ** This routine walks an expression tree and resolves references to
    ** table columns and result-set columns.  At the same time, do error
    ** checking on function usage and set a flag if any aggregate functions
    ** are seen.
    **
    ** To resolve table columns references we look for nodes (or subtrees) of the
    ** form X.Y.Z or Y.Z or just Z where
    **
    **      X:   The name of a database.  Ex:  "main" or "temp" or
    **           the symbolic name assigned to an ATTACH-ed database.
    **
    **      Y:   The name of a table in a FROM clause.  Or in a trigger
    **           one of the special names "old" or "new".
    **
    **      Z:   The name of a column in table Y.
    **
    ** The node at the root of the subtree is modified as follows:
    **
    **    Expr.op        Changed to TK_COLUMN
    **    Expr.pTab      Points to the Table object for X.Y
    **    Expr.iColumn   The column index in X.Y.  -1 for the rowid.
    **    Expr.iTable    The VDBE cursor number for X.Y
    **
    **
    ** To resolve result-set references, look for expression nodes of the
    ** form Z (with no X and Y prefix) where the Z matches the right-hand
    ** size of an AS clause in the result-set of a SELECT.  The Z expression
    ** is replaced by a copy of the left-hand side of the result-set expression.
    ** Table-name and function resolution occurs on the substituted expression
    ** tree.  For example, in:
    **
    **      SELECT a+b AS x, c+d AS y FROM t1 ORDER BY x;
    **
    ** The "x" term of the order by is replaced by "a+b" to render:
    **
    **      SELECT a+b AS x, c+d AS y FROM t1 ORDER BY a+b;
    **
    ** Function calls are checked to make sure that the function is
    ** defined and that the correct number of arguments are specified.
    ** If the function is an aggregate function, then the pNC.hasAgg is
    ** set and the opcode is changed from TK_FUNCTION to TK_AGG_FUNCTION.
    ** If an expression contains aggregate functions then the EP_Agg
    ** property on the expression is set.
    **
    ** An error message is left in pParse if anything is amiss.  The number
    ** if errors is returned.
    */
    static int sqlite3ResolveExprNames(
    NameContext pNC,       /* Namespace to resolve expressions in. */
    ref Expr pExpr         /* The expression to be analyzed. */
    )
    {
      u8 savedHasAgg;
      Walker w = new Walker();

      if ( pExpr == null )
        return 0;
#if SQLITE_MAX_EXPR_DEPTH//>0
{
Parse pParse = pNC.pParse;
if( sqlite3ExprCheckHeight(pParse, pExpr.nHeight+pNC.pParse.nHeight) ){
return 1;
}
pParse.nHeight += pExpr.nHeight;
}
#endif
      savedHasAgg = pNC.hasAgg;
      pNC.hasAgg = 0;
      w.xExprCallback = resolveExprStep;
      w.xSelectCallback = resolveSelectStep;
      w.pParse = pNC.pParse;
      w.u.pNC = pNC;
      sqlite3WalkExpr( w, ref pExpr );
#if SQLITE_MAX_EXPR_DEPTH//>0
pNC.pParse.nHeight -= pExpr.nHeight;
#endif
      if ( pNC.nErr > 0 || w.pParse.nErr > 0 )
      {
        ExprSetProperty( pExpr, EP_Error );
      }
      if ( pNC.hasAgg != 0 )
      {
        ExprSetProperty( pExpr, EP_Agg );
      }
      else if ( savedHasAgg != 0 )
      {
        pNC.hasAgg = 1;
      }
      return ExprHasProperty( pExpr, EP_Error ) ? 1 : 0;
    }
Esempio n. 34
0
        static string ColumnType(NameContext nc, Expr expr, ref string originDbNameOut, ref string originTableNameOut, ref string originColumnNameOut)
        {
            string typeName = null;
            string originDbName = null;
            string originTableName = null;
            string originColumnName = null;
            int j;
            if (C._NEVER(expr == null) || nc.SrcList == null) return null;

            switch (expr.OP)
            {
                case TK.AGG_COLUMN:
                case TK.COLUMN:
                    {
                        // The expression is a column. Locate the table the column is being extracted from in NameContext.pSrcList. This table may be real
                        // database table or a subquery.
                        Table table = null; // Table structure column is extracted from
                        Select s = null; // Select the column is extracted from
                        int colId = expr.ColumnIdx; // Index of column in pTab
                        C.ASSERTCOVERAGE(expr.OP == TK.AGG_COLUMN);
                        C.ASSERTCOVERAGE(expr.OP == TK.COLUMN);
                        while (nc != null && table == null)
                        {
                            SrcList tabList = nc.SrcList;
                            for (j = 0; j < tabList.Srcs && tabList.Ids[j].Cursor != expr.TableId; j++) ;
                            if (j < tabList.Srcs)
                            {
                                table = tabList.Ids[j].Table;
                                s = tabList.Ids[j].Select;
                            }
                            else
                                nc = nc.Next;
                        }

                        if (table == null)
                        {
                            // At one time, code such as "SELECT new.x" within a trigger would cause this condition to run.  Since then, we have restructured how
                            // trigger code is generated and so this condition is no longer possible. However, it can still be true for statements like
                            // the following:
                            //
                            //   CREATE TABLE t1(col INTEGER);
                            //   SELECT (SELECT t1.col) FROM FROM t1;
                            //
                            // when columnType() is called on the expression "t1.col" in the sub-select. In this case, set the column type to NULL, even
                            // though it should really be "INTEGER".
                            //
                            // This is not a problem, as the column type of "t1.col" is never used. When columnType() is called on the expression 
                            // "(SELECT t1.col)", the correct type is returned (see the TK_SELECT branch below.
                            break;
                        }

                        Debug.Assert(table != null && expr.Table == table);
                        if (s != null)
                        {
                            // The "table" is actually a sub-select or a view in the FROM clause of the SELECT statement. Return the declaration type and origin
                            // data for the result-set column of the sub-select.
                            if (colId >= 0 && C._ALWAYS(colId < s.EList.Exprs))
                            {
                                // If colId is less than zero, then the expression requests the rowid of the sub-select or view. This expression is legal (see 
                                // test case misc2.2.2) - it always evaluates to NULL.
                                NameContext sNC = new NameContext();
                                Expr p = s.EList.Ids[colId].Expr;
                                sNC.SrcList = s.Src;
                                sNC.Next = nc;
                                sNC.Parse = nc.Parse;
                                typeName = ColumnType(sNC, p, ref originDbName, ref originTableName, ref originColumnName);
                            }
                        }
                        else if (C._ALWAYS(table.Schema))
                        {
                            // A real table
                            Debug.Assert(s == null);
                            if (colId < 0) colId = table.PKey;
                            Debug.Assert(colId == -1 || (colId >= 0 && colId < table.Cols.length));
                            if (colId < 0)
                            {
                                typeName = "INTEGER";
                                originColumnName = "rowid";
                            }
                            else
                            {
                                typeName = table.Cols[colId].Type;
                                originColumnName = table.Cols[colId].Name;
                            }
                            originTableName = table.Name;
                            if (nc.Parse != null)
                            {
                                Context ctx = nc.Parse.Ctx;
                                int db = Prepare.SchemaToIndex(ctx, table.Schema);
                                originDbName = ctx.DBs[db].Name;
                            }
                        }
                        break;
                    }
#if !OMIT_SUBQUERY
                case TK.SELECT:
                    {
                        // The expression is a sub-select. Return the declaration type and origin info for the single column in the result set of the SELECT statement.
                        NameContext sNC = new NameContext();
                        Select s = expr.x.Select;
                        Expr p = s.EList.Ids[0].Expr;
                        Debug.Assert(E.ExprHasProperty(expr, EP.xIsSelect));
                        sNC.SrcList = s.Src;
                        sNC.Next = nc;
                        sNC.Parse = nc.Parse;
                        typeName = ColumnType(sNC, p, ref originDbName, ref originTableName, ref originColumnName);
                        break;
                    }
#endif
            }

            originDbNameOut = originDbName;
            originTableNameOut = originTableName;
            originColumnNameOut = originColumnName;
            return typeName;
        }
Esempio n. 35
0
        /*
        ** Generate code for a DELETE FROM statement.
        **
        **     DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
        **                 \________/       \________________/
        **                  pTabList              pWhere
        */
        static void sqlite3DeleteFrom(
            Parse pParse,     /* The parser context */
            SrcList pTabList, /* The table from which we should delete things */
            Expr pWhere       /* The WHERE clause.  May be null */
            )
        {
            Vdbe        v;             /* The virtual database engine */
            Table       pTab;          /* The table from which records will be deleted */
            string      zDb;           /* Name of database holding pTab */
            int         end, addr = 0; /* A couple addresses of generated code */
            int         i;             /* Loop counter */
            WhereInfo   pWInfo;        /* Information about the WHERE clause */
            Index       pIdx;          /* For looping over indices of the table */
            int         iCur;          /* VDBE VdbeCursor number for pTab */
            sqlite3     db;            /* Main database structure */
            AuthContext sContext;      /* Authorization context */
            int         oldIdx = -1;   /* VdbeCursor for the OLD table of AFTER triggers */
            NameContext sNC;           /* Name context to resolve expressions in */
            int         iDb;           /* Database number */
            int         memCnt = -1;   /* Memory cell used for change counting */
            int         rcauth;        /* Value returned by authorization callback */

#if !SQLITE_OMIT_TRIGGER
            bool    isView;               /* True if attempting to delete from a view */
            Trigger pTrigger;             /* List of table triggers, if required */
#endif
            int iBeginAfterTrigger  = 0;  /* Address of after trigger program */
            int iEndAfterTrigger    = 0;  /* Exit of after trigger program */
            int iBeginBeforeTrigger = 0;  /* Address of before trigger program */
            int iEndBeforeTrigger   = 0;  /* Exit of before trigger program */
            u32 old_col_mask        = 0;  /* Mask of OLD.* columns in use */

            sContext = new AuthContext(); //memset(&sContext, 0, sizeof(sContext));

            db = pParse.db;
            if (pParse.nErr != 0 /*|| db.mallocFailed != 0 */)
            {
                goto delete_from_cleanup;
            }
            Debug.Assert(pTabList.nSrc == 1);

            /* Locate the table which we want to delete.  This table has to be
            ** put in an SrcList structure because some of the subroutines we
            ** will be calling are designed to work with multiple tables and expect
            ** an SrcList* parameter instead of just a Table* parameter.
            */
            pTab = sqlite3SrcListLookup(pParse, pTabList);
            if (pTab == null)
            {
                goto delete_from_cleanup;
            }

            /* Figure out if we have any triggers and if the table being
            ** deleted from is a view
            */
#if !SQLITE_OMIT_TRIGGER
            int iDummy = 0;
            pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, null, ref iDummy);
            isView   = pTab.pSelect != null;
#else
            const Trigger pTrigger = null;
            isView = false;
#endif
#if SQLITE_OMIT_VIEW
//# undef isView
            isView = false;
#endif

            /* If pTab is really a view, make sure it has been initialized.
             */
            if (sqlite3ViewGetColumnNames(pParse, pTab) != 0)
            {
                goto delete_from_cleanup;
            }

            if (sqlite3IsReadOnly(pParse, pTab, (pTrigger != null ? 1 : 0)))
            {
                goto delete_from_cleanup;
            }
            iDb = sqlite3SchemaToIndex(db, pTab.pSchema);
            Debug.Assert(iDb < db.nDb);
            zDb = db.aDb[iDb].zName;
#if !SQLITE_OMIT_AUTHORIZATION
            rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb);
#else
            rcauth = SQLITE_OK;
#endif
            Debug.Assert(rcauth == SQLITE_OK || rcauth == SQLITE_DENY || rcauth == SQLITE_IGNORE);
            if (rcauth == SQLITE_DENY)
            {
                goto delete_from_cleanup;
            }
            Debug.Assert(!isView || pTrigger != null);

            /* Allocate a cursor used to store the old.* data for a trigger.
             */
            if (pTrigger != null)
            {
                oldIdx = pParse.nTab++;
            }

            /* Assign  cursor number to the table and all its indices.
             */
            Debug.Assert(pTabList.nSrc == 1);
            iCur = pTabList.a[0].iCursor = pParse.nTab++;
            for (pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext)
            {
                pParse.nTab++;
            }

#if !SQLITE_OMIT_AUTHORIZATION
/* Start the view context
 */
            if (isView)
            {
                sqlite3AuthContextPush(pParse, sContext, pTab.zName);
            }
#endif

            /* Begin generating code.
             */
            v = sqlite3GetVdbe(pParse);
            if (v == null)
            {
                goto delete_from_cleanup;
            }
            if (pParse.nested == 0)
            {
                sqlite3VdbeCountChanges(v);
            }
            sqlite3BeginWriteOperation(pParse, pTrigger != null ? 1 : 0, iDb);

#if !SQLITE_OMIT_TRIGGER
            if (pTrigger != null)
            {
                int orconf = ((pParse.trigStack != null) ? pParse.trigStack.orconf : OE_Default);
                int iGoto  = sqlite3VdbeAddOp0(v, OP_Goto);
                addr = sqlite3VdbeMakeLabel(v);

                iBeginBeforeTrigger = sqlite3VdbeCurrentAddr(v);
                u32 Ref_0 = 0;
                sqlite3CodeRowTrigger(pParse, pTrigger, TK_DELETE, null,
                                      TRIGGER_BEFORE, pTab, -1, oldIdx, orconf, addr, ref old_col_mask, ref Ref_0);
                iEndBeforeTrigger = sqlite3VdbeAddOp0(v, OP_Goto);

                iBeginAfterTrigger = sqlite3VdbeCurrentAddr(v);
                Ref_0 = 0;
                sqlite3CodeRowTrigger(pParse, pTrigger, TK_DELETE, null,
                                      TRIGGER_AFTER, pTab, -1, oldIdx, orconf, addr, ref old_col_mask, ref Ref_0);
                iEndAfterTrigger = sqlite3VdbeAddOp0(v, OP_Goto);

                sqlite3VdbeJumpHere(v, iGoto);
            }
#endif

            /* If we are trying to delete from a view, realize that view into
            ** a ephemeral table.
            */
#if !(SQLITE_OMIT_VIEW) && !(SQLITE_OMIT_TRIGGER)
            if (isView)
            {
                sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
            }

            /* Resolve the column names in the WHERE clause.
             */
            sNC          = new NameContext();// memset( &sNC, 0, sizeof( sNC ) );
            sNC.pParse   = pParse;
            sNC.pSrcList = pTabList;
            if (sqlite3ResolveExprNames(sNC, ref pWhere) != 0)
            {
                goto delete_from_cleanup;
            }
#endif

            /* Initialize the counter of the number of rows deleted, if
            ** we are counting rows.
            */
            if ((db.flags & SQLITE_CountRows) != 0)
            {
                memCnt = ++pParse.nMem;
                sqlite3VdbeAddOp2(v, OP_Integer, 0, memCnt);
            }

#if !SQLITE_OMIT_TRUNCATE_OPTIMIZATION
            /* Special case: A DELETE without a WHERE clause deletes everything.
            ** It is easier just to erase the whole table.  Note, however, that
            ** this means that the row change count will be incorrect.
            */
            if (rcauth == SQLITE_OK && pWhere == null && null == pTrigger && !IsVirtual(pTab))
            {
                Debug.Assert(!isView);
                sqlite3VdbeAddOp4(v, OP_Clear, pTab.tnum, iDb, memCnt,
                                  pTab.zName, P4_STATIC);
                for (pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext)
                {
                    Debug.Assert(pIdx.pSchema == pTab.pSchema);
                    sqlite3VdbeAddOp2(v, OP_Clear, pIdx.tnum, iDb);
                }
            }
            else
#endif //* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */

            /* The usual case: There is a WHERE clause so we have to scan through
            ** the table and pick which records to delete.
            */
            {
                int iRowid  = ++pParse.nMem; /* Used for storing rowid values. */
                int iRowSet = ++pParse.nMem; /* Register for rowset of rows to delete */
                int regRowid;                /* Actual register containing rowids */

                /* Collect rowids of every row to be deleted.
                 */
                sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet);
                ExprList elDummy = null;
                pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, ref elDummy, WHERE_DUPLICATES_OK);
                if (pWInfo == null)
                {
                    goto delete_from_cleanup;
                }
                regRowid = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, iRowid, false);
                sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, regRowid);
                if ((db.flags & SQLITE_CountRows) != 0)
                {
                    sqlite3VdbeAddOp2(v, OP_AddImm, memCnt, 1);
                }

                sqlite3WhereEnd(pWInfo);

                /* Open the pseudo-table used to store OLD if there are triggers.
                 */
                if (pTrigger != null)
                {
                    sqlite3VdbeAddOp3(v, OP_OpenPseudo, oldIdx, 0, pTab.nCol);
                }

                /* Delete every item whose key was written to the list during the
                ** database scan.  We have to delete items after the scan is complete
                ** because deleting an item can change the scan order.
                */
                end = sqlite3VdbeMakeLabel(v);

                if (!isView)
                {
                    /* Open cursors for the table we are deleting from and
                    ** all its indices.
                    */
                    sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
                }

                /* This is the beginning of the delete loop. If a trigger encounters
                ** an IGNORE constraint, it jumps back to here.
                */
                if (pTrigger != null)
                {
                    sqlite3VdbeResolveLabel(v, addr);
                }
                addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, iRowSet, end, iRowid);

                if (pTrigger != null)
                {
                    int iData = ++pParse.nMem; /* For storing row data of OLD table */

                    /* If the record is no longer present in the table, jump to the
                    ** next iteration of the loop through the contents of the fifo.
                    */
                    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid);

                    /* Populate the OLD.* pseudo-table */
                    if (old_col_mask != 0)
                    {
                        sqlite3VdbeAddOp2(v, OP_RowData, iCur, iData);
                    }
                    else
                    {
                        sqlite3VdbeAddOp2(v, OP_Null, 0, iData);
                    }
                    sqlite3VdbeAddOp3(v, OP_Insert, oldIdx, iData, iRowid);

                    /* Jump back and run the BEFORE triggers */
                    sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginBeforeTrigger);
                    sqlite3VdbeJumpHere(v, iEndBeforeTrigger);
                }

                if (!isView)
                {
                    /* Delete the row */
#if !SQLITE_OMIT_VIRTUALTABLE
                    if (IsVirtual(pTab))
                    {
                        const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
                        sqlite3VtabMakeWritable(pParse, pTab);
                        sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB);
                    }
                    else
#endif
                    {
                        sqlite3GenerateRowDelete(pParse, pTab, iCur, iRowid, pParse.nested == 0 ? 1 : 0);
                    }
                }

                /* If there are row triggers, close all cursors then invoke
                ** the AFTER triggers
                */
                if (pTrigger != null)
                {
                    /* Jump back and run the AFTER triggers */
                    sqlite3VdbeAddOp2(v, OP_Goto, 0, iBeginAfterTrigger);
                    sqlite3VdbeJumpHere(v, iEndAfterTrigger);
                }

                /* End of the delete loop */
                sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
                sqlite3VdbeResolveLabel(v, end);

                /* Close the cursors after the loop if there are no row triggers */
                if (!isView && !IsVirtual(pTab))
                {
                    for (i = 1, pIdx = pTab.pIndex; pIdx != null; i++, pIdx = pIdx.pNext)
                    {
                        sqlite3VdbeAddOp2(v, OP_Close, iCur + i, pIdx.tnum);
                    }
                    sqlite3VdbeAddOp1(v, OP_Close, iCur);
                }
            }

            /* Update the sqlite_sequence table by storing the content of the
            ** maximum rowid counter values recorded while inserting into
            ** autoincrement tables.
            */
            if (pParse.nested == 0 && pParse.trigStack == null)
            {
                sqlite3AutoincrementEnd(pParse);
            }

            /*
            ** Return the number of rows that were deleted. If this routine is
            ** generating code because of a call to sqlite3NestedParse(), do not
            ** invoke the callback function.
            */
            if ((db.flags & SQLITE_CountRows) != 0 && pParse.nested == 0 && pParse.trigStack == null)
            {
                sqlite3VdbeAddOp2(v, OP_ResultRow, memCnt, 1);
                sqlite3VdbeSetNumCols(v, 1);
                sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC);
            }

delete_from_cleanup:
#if !SQLITE_OMIT_AUTHORIZATION
            sqlite3AuthContextPop(sContext);
#endif
            sqlite3SrcListDelete(db, ref pTabList);
            sqlite3ExprDelete(db, ref pWhere);
            return;
        }
Esempio n. 36
0
 /*
 ** Call sqlite3ExprAnalyzeAggregates() for every expression in an
 ** expression list.  Return the number of errors.
 **
 ** If an error is found, the analysis is cut short.
 */
 static void sqlite3ExprAnalyzeAggList( NameContext pNC, ExprList pList )
 {
   ExprList_item pItem;
   int i;
   if ( pList != null )
   {
     for ( i = 0; i < pList.nExpr; i++ )//, pItem++)
     {
       pItem = pList.a[i];
       sqlite3ExprAnalyzeAggregates( pNC, ref pItem.pExpr );
     }
   }
 }
Esempio n. 37
0
        static void sqlite3EndTable(
            Parse pParse,          /* Parse context */
            Token pCons,           /* The ',' token after the last column defn. */
            Token pEnd,            /* The final ')' token in the CREATE TABLE */
            Select pSelect         /* Select from a "CREATE ... AS SELECT" */
            )
        {
            Table p;
            sqlite3 db = pParse.db;
            int iDb;

            if ((pEnd == null && pSelect == null) /*|| db.mallocFailed != 0 */ )
            {
                return;
            }
            p = pParse.pNewTable;
            if (p == null)
                return;

            Debug.Assert(0 == db.init.busy || pSelect == null);

            iDb = sqlite3SchemaToIndex(db, p.pSchema);

            #if !SQLITE_OMIT_CHECK
            /* Resolve names in all CHECK constraint expressions.
            */
            if (p.pCheck != null)
            {
                SrcList sSrc;                   /* Fake SrcList for pParse.pNewTable */
                NameContext sNC;                /* Name context for pParse.pNewTable */

                sNC = new NameContext();// memset(sNC, 0, sizeof(sNC));
                sSrc = new SrcList();// memset(sSrc, 0, sizeof(sSrc));
                sSrc.nSrc = 1;
                sSrc.a = new SrcList_item[1];
                sSrc.a[0] = new SrcList_item();
                sSrc.a[0].zName = p.zName;
                sSrc.a[0].pTab = p;
                sSrc.a[0].iCursor = -1;
                sNC.pParse = pParse;
                sNC.pSrcList = sSrc;
                sNC.isCheck = 1;
                if (sqlite3ResolveExprNames(sNC, ref p.pCheck) != 0)
                {
                    return;
                }
            }
            #endif // * !SQLITE_OMIT_CHECK) */

            /* If the db.init.busy is 1 it means we are reading the SQL off the
            ** "sqlite_master" or "sqlite_temp_master" table on the disk.
            ** So do not write to the disk again.  Extract the root page number
            ** for the table from the db.init.newTnum field.  (The page number
            ** should have been put there by the sqliteOpenCb routine.)
            */
            if (db.init.busy != 0)
            {
                p.tnum = db.init.newTnum;
            }

            /* If not initializing, then create a record for the new table
            ** in the SQLITE_MASTER table of the database.
            **
            ** If this is a TEMPORARY table, write the entry into the auxiliary
            ** file instead of into the main database file.
            */
            if (0 == db.init.busy)
            {
                int n;
                Vdbe v;
                String zType = "";    /* "view" or "table" */
                String zType2 = "";    /* "VIEW" or "TABLE" */
                String zStmt = "";    /* Text of the CREATE TABLE or CREATE VIEW statement */

                v = sqlite3GetVdbe(pParse);
                if (NEVER(v == null))
                    return;

                sqlite3VdbeAddOp1(v, OP_Close, 0);

                /*
                ** Initialize zType for the new view or table.
                */
                if (p.pSelect == null)
                {
                    /* A regular table */
                    zType = "table";
                    zType2 = "TABLE";
            #if !SQLITE_OMIT_VIEW
                }
                else
                {
                    /* A view */
                    zType = "view";
                    zType2 = "VIEW";
            #endif
                }

                /* If this is a CREATE TABLE xx AS SELECT ..., execute the SELECT
                ** statement to populate the new table. The root-page number for the
                ** new table is in register pParse->regRoot.
                **
                ** Once the SELECT has been coded by sqlite3Select(), it is in a
                ** suitable state to query for the column names and types to be used
                ** by the new table.
                **
                ** A shared-cache write-lock is not required to write to the new table,
                ** as a schema-lock must have already been obtained to create it. Since
                ** a schema-lock excludes all other database users, the write-lock would
                ** be redundant.
                */
                if (pSelect != null)
                {
                    SelectDest dest = new SelectDest();
                    Table pSelTab;

                    Debug.Assert(pParse.nTab == 1);
                    sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse.regRoot, iDb);
                    sqlite3VdbeChangeP5(v, 1);
                    pParse.nTab = 2;
                    sqlite3SelectDestInit(dest, SRT_Table, 1);
                    sqlite3Select(pParse, pSelect, ref dest);
                    sqlite3VdbeAddOp1(v, OP_Close, 1);
                    if (pParse.nErr == 0)
                    {
                        pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
                        if (pSelTab == null)
                            return;
                        Debug.Assert(p.aCol == null);
                        p.nCol = pSelTab.nCol;
                        p.aCol = pSelTab.aCol;
                        pSelTab.nCol = 0;
                        pSelTab.aCol = null;
                        sqlite3DeleteTable(db, ref pSelTab);
                    }
                }

                /* Compute the complete text of the CREATE statement */
                if (pSelect != null)
                {
                    zStmt = createTableStmt(db, p);
                }
                else
                {
                    n = (int)(pParse.sNameToken.z.Length - pEnd.z.Length) + 1;
                    zStmt = sqlite3MPrintf(db,
                    "CREATE %s %.*s", zType2, n, pParse.sNameToken.z
                    );
                }

                /* A slot for the record has already been allocated in the
                ** SQLITE_MASTER table.  We just need to update that slot with all
                ** the information we've collected.
                */
                sqlite3NestedParse(pParse,
                "UPDATE %Q.%s " +
                "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q " +
                "WHERE rowid=#%d",
                db.aDb[iDb].zName, SCHEMA_TABLE(iDb),
                zType,
                p.zName,
                p.zName,
                pParse.regRoot,
                zStmt,
                pParse.regRowid
                );
                sqlite3DbFree(db, ref zStmt);
                sqlite3ChangeCookie(pParse, iDb);

            #if !SQLITE_OMIT_AUTOINCREMENT
                /* Check to see if we need to create an sqlite_sequence table for
            ** keeping track of autoincrement keys.
            */
                if ((p.tabFlags & TF_Autoincrement) != 0)
                {
                    Db pDb = db.aDb[iDb];
                    Debug.Assert(sqlite3SchemaMutexHeld(db, iDb, null));
                    if (pDb.pSchema.pSeqTab == null)
                    {
                        sqlite3NestedParse(pParse,
                        "CREATE TABLE %Q.sqlite_sequence(name,seq)",
                        pDb.zName
                        );
                    }
                }
            #endif

                /* Reparse everything to update our internal data structures */
                sqlite3VdbeAddParseSchemaOp(v, iDb,
                           sqlite3MPrintf(db, "tbl_name='%q'", p.zName));
            }

            /* Add the table to the in-memory representation of the database.
            */
            if (db.init.busy != 0)
            {
                Table pOld;
                Schema pSchema = p.pSchema;
                Debug.Assert(sqlite3SchemaMutexHeld(db, iDb, null));
                pOld = sqlite3HashInsert(ref pSchema.tblHash, p.zName,
                sqlite3Strlen30(p.zName), p);
                if (pOld != null)
                {
                    Debug.Assert(p == pOld);  /* Malloc must have failed inside HashInsert() */
                    //        db.mallocFailed = 1;
                    return;
                }
                pParse.pNewTable = null;
                db.nTable++;
                db.flags |= SQLITE_InternChanges;

            #if !SQLITE_OMIT_ALTERTABLE
                if (p.pSelect == null)
                {
                    string zName = pParse.sNameToken.z;
                    int nName;
                    Debug.Assert(pSelect == null && pCons != null && pEnd != null);
                    if (pCons.z == null)
                    {
                        pCons = pEnd;
                    }
                    nName = zName.Length - pCons.z.Length;
                    p.addColOffset = 13 + nName; // sqlite3Utf8CharLen(zName, nName);
                }
            #endif
            }
        }
Esempio n. 38
0
    /*
    ** pE is a pointer to an expression which is a single term in the
    ** ORDER BY of a compound SELECT.  The expression has not been
    ** name resolved.
    **
    ** At the point this routine is called, we already know that the
    ** ORDER BY term is not an integer index into the result set.  That
    ** case is handled by the calling routine.
    **
    ** Attempt to match pE against result set columns in the left-most
    ** SELECT statement.  Return the index i of the matching column,
    ** as an indication to the caller that it should sort by the i-th column.
    ** The left-most column is 1.  In other words, the value returned is the
    ** same integer value that would be used in the SQL statement to indicate
    ** the column.
    **
    ** If there is no match, return 0.  Return -1 if an error occurs.
    */
    static int resolveOrderByTermToExprList(
    Parse pParse,     /* Parsing context for error messages */
    Select pSelect,   /* The SELECT statement with the ORDER BY clause */
    Expr pE           /* The specific ORDER BY term */
    )
    {
      int i = 0;         /* Loop counter */
      ExprList pEList;   /* The columns of the result set */
      NameContext nc;    /* Name context for resolving pE */
      sqlite3 db;        /* Database connection */
      int rc;            /* Return code from subprocedures */
      u8 savedSuppErr;   /* Saved value of db->suppressErr */

      Debug.Assert( sqlite3ExprIsInteger( pE, ref i ) == 0 );
      pEList = pSelect.pEList;

      /* Resolve all names in the ORDER BY term expression
      */
      nc = new NameContext();// memset( &nc, 0, sizeof( nc ) );
      nc.pParse = pParse;
      nc.pSrcList = pSelect.pSrc;
      nc.pEList = pEList;
      nc.allowAgg = 1;
      nc.nErr = 0;
      db = pParse.db;
      savedSuppErr = db.suppressErr;
      db.suppressErr = 1;
      rc = sqlite3ResolveExprNames( nc, ref pE );
      db.suppressErr = savedSuppErr;
      if ( rc != 0 )
        return 0;

      /* Try to match the ORDER BY expression against an expression
      ** in the result set.  Return an 1-based index of the matching
      ** result-set entry.
      */
      for ( i = 0; i < pEList.nExpr; i++ )
      {
        if ( sqlite3ExprCompare( pEList.a[i].pExpr, pE ) < 2 )
        {
          return i + 1;
        }
      }

      /* If no match, return 0. */
      return 0;
    }
Esempio n. 39
0
        /// <summary>
        /// Resolve all names in all expressions of a SELECT and in all
        /// decendents of the SELECT, including compounds off of p.pPrior,
        /// subqueries in expressions, and subqueries used as FROM clause
        /// terms.
        /// 
        /// See sqlite3ResolveExprNames() for a description of the kinds of
        /// transformations that occur.
        /// 
        /// All SELECT statements should have been expanded using
        /// sqlite3SelectExpand() prior to invoking this routine.
        /// </summary>
        /// <param name='pParse'>
        /// The parser context
        /// </param>
        /// <param name='p'>
        /// The SELECT statement being coded.
        /// </param>
        /// <param name='pOuterNC'>
        /// Name context for parent SELECT statement
        /// </param>
        static void sqlite3ResolveSelectNames(Parse pParse, Select p, NameContext pOuterNC)
        {
            Walker w = new Walker();

            Debug.Assert(p != null);
            w.xExprCallback = resolveExprStep;
            w.xSelectCallback = resolveSelectStep;
            w.pParse = pParse;
            w.u.pNC = pOuterNC;
            sqlite3WalkSelect(w, p);
        }
Esempio n. 40
0
    /*
    ** Return a pointer to a string containing the 'declaration type' of the
    ** expression pExpr. The string may be treated as static by the caller.
    **
    ** The declaration type is the exact datatype definition extracted from the
    ** original CREATE TABLE statement if the expression is a column. The
    ** declaration type for a ROWID field is INTEGER. Exactly when an expression
    ** is considered a column can be complex in the presence of subqueries. The
    ** result-set expression in all of the following SELECT statements is
    ** considered a column by this function.
    **
    **   SELECT col FROM tbl;
    **   SELECT (SELECT col FROM tbl;
    **   SELECT (SELECT col FROM tbl);
    **   SELECT abc FROM (SELECT col AS abc FROM tbl);
    **
    ** The declaration type for any expression other than a column is NULL.
    */
    static string columnType(
    NameContext pNC,
    Expr pExpr,
    ref string pzOriginDb,
    ref string pzOriginTab,
    ref string pzOriginCol
    )
    {
      string zType = null;
      string zOriginDb = null;
      string zOriginTab = null;
      string zOriginCol = null;
      int j;
      if ( NEVER( pExpr == null ) || pNC.pSrcList == null ) return null;

      switch ( pExpr.op )
      {
        case TK_AGG_COLUMN:
        case TK_COLUMN:
          {
            /* The expression is a column. Locate the table the column is being
            ** extracted from in NameContext.pSrcList. This table may be real
            ** database table or a subquery.
            */
            Table pTab = null;            /* Table structure column is extracted from */
            Select pS = null;            /* Select the column is extracted from */
            int iCol = pExpr.iColumn;  /* Index of column in pTab */
            testcase( pExpr.op == TK_AGG_COLUMN );
            testcase( pExpr.op == TK_COLUMN );
            while ( pNC != null && pTab == null )
            {
              SrcList pTabList = pNC.pSrcList;
              for ( j = 0 ; j < pTabList.nSrc && pTabList.a[j].iCursor != pExpr.iTable ; j++ ) ;
              if ( j < pTabList.nSrc )
              {
                pTab = pTabList.a[j].pTab;
                pS = pTabList.a[j].pSelect;
              }
              else
              {
                pNC = pNC.pNext;
              }
            }

            if ( pTab == null )
            {
              /* FIX ME:
              ** This can occurs if you have something like "SELECT new.x;" inside
              ** a trigger.  In other words, if you reference the special "new"
              ** table in the result set of a select.  We do not have a good way
              ** to find the actual table type, so call it "TEXT".  This is really
              ** something of a bug, but I do not know how to fix it.
              **
              ** This code does not produce the correct answer - it just prevents
              ** a segfault.  See ticket #1229.
              */
              zType = "TEXT";
              break;
            }

            Debug.Assert( pTab != null );
            if ( pS != null )
            {
              /* The "table" is actually a sub-select or a view in the FROM clause
              ** of the SELECT statement. Return the declaration type and origin
              ** data for the result-set column of the sub-select.
              */
              if ( ALWAYS( iCol >= 0 && iCol < pS.pEList.nExpr ) )
              {
                /* If iCol is less than zero, then the expression requests the
                ** rowid of the sub-select or view. This expression is legal (see
                ** test case misc2.2.2) - it always evaluates to NULL.
                */
                NameContext sNC = new NameContext();
                Expr p = pS.pEList.a[iCol].pExpr;
                sNC.pSrcList = pS.pSrc;
                sNC.pNext = null;
                sNC.pParse = pNC.pParse;
                zType = columnType( sNC, p, ref zOriginDb, ref zOriginTab, ref zOriginCol );
              }
            }
            else if ( ALWAYS( pTab.pSchema ) )
            {
              /* A real table */
              Debug.Assert( pS == null );
              if ( iCol < 0 ) iCol = pTab.iPKey;
              Debug.Assert( iCol == -1 || ( iCol >= 0 && iCol < pTab.nCol ) );
              if ( iCol < 0 )
              {
                zType = "INTEGER";
                zOriginCol = "rowid";
              }
              else
              {
                zType = pTab.aCol[iCol].zType;
                zOriginCol = pTab.aCol[iCol].zName;
              }
              zOriginTab = pTab.zName;
              if ( pNC.pParse != null )
              {
                int iDb = sqlite3SchemaToIndex( pNC.pParse.db, pTab.pSchema );
                zOriginDb = pNC.pParse.db.aDb[iDb].zName;
              }
            }
            break;
          }
#if !SQLITE_OMIT_SUBQUERY
        case TK_SELECT:
          {
            /* The expression is a sub-select. Return the declaration type and
            ** origin info for the single column in the result set of the SELECT
            ** statement.
            */
            NameContext sNC = new NameContext();
            Select pS = pExpr.x.pSelect;
            Expr p = pS.pEList.a[0].pExpr;
            Debug.Assert( ExprHasProperty( pExpr, EP_xIsSelect ) );
            sNC.pSrcList = pS.pSrc;
            sNC.pNext = pNC;
            sNC.pParse = pNC.pParse;
            zType = columnType( sNC, p, ref zOriginDb, ref zOriginTab, ref zOriginCol );
            break;
          }
#endif
      }

      if ( pzOriginDb != null )
      {
        Debug.Assert( pzOriginTab != null && pzOriginCol != null );
        pzOriginDb = zOriginDb;
        pzOriginTab = zOriginTab;
        pzOriginCol = zOriginCol;
      }
      return zType;
    }
Esempio n. 41
0
        /*
        ** Generate code for a DELETE FROM statement.
        **
        **     DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
        **                 \________/       \________________/
        **                  pTabList              pWhere
        */
        static void sqlite3DeleteFrom(
            Parse pParse,          /* The parser context */
            SrcList pTabList,      /* The table from which we should delete things */
            Expr pWhere            /* The WHERE clause.  May be null */
            )
        {
            Vdbe v;                /* The virtual database engine */
              Table pTab;            /* The table from which records will be deleted */
              string zDb;            /* Name of database holding pTab */
              int end, addr = 0;     /* A couple addresses of generated code */
              int i;                 /* Loop counter */
              WhereInfo pWInfo;      /* Information about the WHERE clause */
              Index pIdx;            /* For looping over indices of the table */
              int iCur;              /* VDBE VdbeCursor number for pTab */
              sqlite3 db;            /* Main database structure */
              AuthContext sContext;  /* Authorization context */
              NameContext sNC;       /* Name context to resolve expressions in */
              int iDb;               /* Database number */
              int memCnt = -1;        /* Memory cell used for change counting */
              int rcauth;            /* Value returned by authorization callback */

            #if !SQLITE_OMIT_TRIGGER
              bool isView;                 /* True if attempting to delete from a view */
              Trigger pTrigger;            /* List of table triggers, if required */
            #endif
              sContext = new AuthContext();//memset(&sContext, 0, sizeof(sContext));

              db = pParse.db;
              if ( pParse.nErr != 0 /*|| db.mallocFailed != 0 */ )
              {
            goto delete_from_cleanup;
              }
              Debug.Assert( pTabList.nSrc == 1 );

              /* Locate the table which we want to delete.  This table has to be
              ** put in an SrcList structure because some of the subroutines we
              ** will be calling are designed to work with multiple tables and expect
              ** an SrcList* parameter instead of just a Table* parameter.
              */
              pTab = sqlite3SrcListLookup( pParse, pTabList );
              if ( pTab == null )
            goto delete_from_cleanup;

              /* Figure out if we have any triggers and if the table being
              ** deleted from is a view
              */
            #if !SQLITE_OMIT_TRIGGER
              int iDummy = 0;
              pTrigger = sqlite3TriggersExist( pParse, pTab, TK_DELETE, null, ref iDummy );
              isView = pTab.pSelect != null;
            #else
              const Trigger pTrigger = null;
              bool isView = false;
            #endif
            #if SQLITE_OMIT_VIEW
            //# undef isView
            isView = false;
            #endif

              /* If pTab is really a view, make sure it has been initialized.
            */
              if ( sqlite3ViewGetColumnNames( pParse, pTab ) != 0 )
              {
            goto delete_from_cleanup;
              }

              if ( sqlite3IsReadOnly( pParse, pTab, ( pTrigger != null ? 1 : 0 ) ) )
              {
            goto delete_from_cleanup;
              }
              iDb = sqlite3SchemaToIndex( db, pTab.pSchema );
              Debug.Assert( iDb < db.nDb );
              zDb = db.aDb[iDb].zName;
            #if !SQLITE_OMIT_AUTHORIZATION
            rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb);
            #else
              rcauth = SQLITE_OK;
            #endif
              Debug.Assert( rcauth == SQLITE_OK || rcauth == SQLITE_DENY || rcauth == SQLITE_IGNORE );
              if ( rcauth == SQLITE_DENY )
              {
            goto delete_from_cleanup;
              }
              Debug.Assert( !isView || pTrigger != null );

              /* Assign  cursor number to the table and all its indices.
              */
              Debug.Assert( pTabList.nSrc == 1 );
              iCur = pTabList.a[0].iCursor = pParse.nTab++;
              for ( pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext )
              {
            pParse.nTab++;
              }

            #if !SQLITE_OMIT_AUTHORIZATION
            /* Start the view context
            */
            if( isView ){
            sqlite3AuthContextPush(pParse, sContext, pTab.zName);
            }
            #endif
              /* Begin generating code.
            */
              v = sqlite3GetVdbe( pParse );
              if ( v == null )
              {
            goto delete_from_cleanup;
              }
              if ( pParse.nested == 0 )
            sqlite3VdbeCountChanges( v );
              sqlite3BeginWriteOperation( pParse, 1, iDb );

              /* If we are trying to delete from a view, realize that view into
              ** a ephemeral table.
              */
            #if !(SQLITE_OMIT_VIEW) && !(SQLITE_OMIT_TRIGGER)
              if ( isView )
              {
            sqlite3MaterializeView( pParse, pTab, pWhere, iCur );
              }
            #endif
              /* Resolve the column names in the WHERE clause.
              */
              sNC = new NameContext();// memset( &sNC, 0, sizeof( sNC ) );
              sNC.pParse = pParse;
              sNC.pSrcList = pTabList;
              if ( sqlite3ResolveExprNames( sNC, ref pWhere ) != 0 )
              {
            goto delete_from_cleanup;
              }

              /* Initialize the counter of the number of rows deleted, if
            ** we are counting rows.
            */
              if ( ( db.flags & SQLITE_CountRows ) != 0 )
              {
            memCnt = ++pParse.nMem;
            sqlite3VdbeAddOp2( v, OP_Integer, 0, memCnt );
              }

            #if !SQLITE_OMIT_TRUNCATE_OPTIMIZATION
              /* Special case: A DELETE without a WHERE clause deletes everything.
              ** It is easier just to erase the whole table. Prior to version 3.6.5,
              ** this optimization caused the row change count (the value returned by
              ** API function sqlite3_count_changes) to be set incorrectly.  */
              if ( rcauth == SQLITE_OK && pWhere == null && null == pTrigger && !IsVirtual( pTab )
            && 0 == sqlite3FkRequired( pParse, pTab, null, 0 )
            )
              {
            Debug.Assert( !isView );
            sqlite3VdbeAddOp4( v, OP_Clear, pTab.tnum, iDb, memCnt,
              pTab.zName, P4_STATIC );
            for ( pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext )
            {
              Debug.Assert( pIdx.pSchema == pTab.pSchema );
              sqlite3VdbeAddOp2( v, OP_Clear, pIdx.tnum, iDb );
            }
              }
              else
            #endif //* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */
              /* The usual case: There is a WHERE clause so we have to scan through
            ** the table and pick which records to delete.
            */
              {
            int iRowSet = ++pParse.nMem;    /* Register for rowset of rows to delete */
            int iRowid = ++pParse.nMem;     /* Used for storing rowid values. */
            int regRowid;                   /* Actual register containing rowids */

            /* Collect rowids of every row to be deleted.
            */
            sqlite3VdbeAddOp2( v, OP_Null, 0, iRowSet );
            ExprList elDummy = null;
            pWInfo = sqlite3WhereBegin( pParse, pTabList, pWhere, ref elDummy, WHERE_DUPLICATES_OK );
            if ( pWInfo == null )
              goto delete_from_cleanup;
            regRowid = sqlite3ExprCodeGetColumn( pParse, pTab, -1, iCur, iRowid );
            sqlite3VdbeAddOp2( v, OP_RowSetAdd, iRowSet, regRowid );
            if ( ( db.flags & SQLITE_CountRows ) != 0 )
            {
              sqlite3VdbeAddOp2( v, OP_AddImm, memCnt, 1 );
            }

            sqlite3WhereEnd( pWInfo );

            /* Delete every item whose key was written to the list during the
            ** database scan.  We have to delete items after the scan is complete
            ** because deleting an item can change the scan order. */
            end = sqlite3VdbeMakeLabel( v );

            /* Unless this is a view, open cursors for the table we are
            ** deleting from and all its indices. If this is a view, then the
            ** only effect this statement has is to fire the INSTEAD OF
            ** triggers.  */
            if ( !isView )
            {
              sqlite3OpenTableAndIndices( pParse, pTab, iCur, OP_OpenWrite );
            }

            addr = sqlite3VdbeAddOp3( v, OP_RowSetRead, iRowSet, end, iRowid );

            /* Delete the row */
            #if !SQLITE_OMIT_VIRTUALTABLE
            if( IsVirtual(pTab) ){
            const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
            sqlite3VtabMakeWritable(pParse, pTab);
            sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB);
            sqlite3MayAbort(pParse);
            }else
            #endif
            {
              int count = ( pParse.nested == 0 ) ? 1 : 0;    /* True to count changes */
              sqlite3GenerateRowDelete( pParse, pTab, iCur, iRowid, count, pTrigger, OE_Default );
            }

            /* End of the delete loop */
            sqlite3VdbeAddOp2( v, OP_Goto, 0, addr );
            sqlite3VdbeResolveLabel( v, end );

            /* Close the cursors open on the table and its indexes. */
            if ( !isView && !IsVirtual( pTab ) )
            {
              for ( i = 1, pIdx = pTab.pIndex; pIdx != null; i++, pIdx = pIdx.pNext )
              {
            sqlite3VdbeAddOp2( v, OP_Close, iCur + i, pIdx.tnum );
              }
              sqlite3VdbeAddOp1( v, OP_Close, iCur );
            }
              }

              /* Update the sqlite_sequence table by storing the content of the
              ** maximum rowid counter values recorded while inserting into
              ** autoincrement tables.
              */
              if ( pParse.nested == 0 && pParse.pTriggerTab == null )
              {
            sqlite3AutoincrementEnd( pParse );
              }

              /* Return the number of rows that were deleted. If this routine is
              ** generating code because of a call to sqlite3NestedParse(), do not
              ** invoke the callback function.
              */

              if ( ( db.flags & SQLITE_CountRows ) != 0 && 0 == pParse.nested && null == pParse.pTriggerTab )
              {
            sqlite3VdbeAddOp2( v, OP_ResultRow, memCnt, 1 );
            sqlite3VdbeSetNumCols( v, 1 );
            sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "rows deleted", SQLITE_STATIC );
              }

            delete_from_cleanup:
            #if !SQLITE_OMIT_AUTHORIZATION
            sqlite3AuthContextPop(sContext);
            #endif
              sqlite3SrcListDelete( db, ref pTabList );
              sqlite3ExprDelete( db, ref pWhere );
              return;
        }
Esempio n. 42
0
    /*
    ** Return a pointer to a string containing the 'declaration type' of the
    ** expression pExpr. The string may be treated as static by the caller.
    **
    ** The declaration type is the exact datatype definition extracted from the
    ** original CREATE TABLE statement if the expression is a column. The
    ** declaration type for a ROWID field is INTEGER. Exactly when an expression
    ** is considered a column can be complex in the presence of subqueries. The
    ** result-set expression in all of the following SELECT statements is
    ** considered a column by this function.
    **
    **   SELECT col FROM tbl;
    **   SELECT (SELECT col FROM tbl;
    **   SELECT (SELECT col FROM tbl);
    **   SELECT abc FROM (SELECT col AS abc FROM tbl);
    **
    ** The declaration type for any expression other than a column is NULL.
    */
    static string columnType(
    NameContext pNC,
    Expr pExpr,
    ref string pzOriginDb,
    ref string pzOriginTab,
    ref string pzOriginCol
    )
    {
      string zType = null;
      string zOriginDb = null;
      string zOriginTab = null;
      string zOriginCol = null;
      int j;
      if ( NEVER( pExpr == null ) || pNC.pSrcList == null )
        return null;

      switch ( pExpr.op )
      {
        case TK_AGG_COLUMN:
        case TK_COLUMN:
          {
            /* The expression is a column. Locate the table the column is being
            ** extracted from in NameContext.pSrcList. This table may be real
            ** database table or a subquery.
            */
            Table pTab = null;            /* Table structure column is extracted from */
            Select pS = null;            /* Select the column is extracted from */
            int iCol = pExpr.iColumn;  /* Index of column in pTab */
            testcase( pExpr.op == TK_AGG_COLUMN );
            testcase( pExpr.op == TK_COLUMN );
            while ( pNC != null && pTab == null )
            {
              SrcList pTabList = pNC.pSrcList;
              for ( j = 0; j < pTabList.nSrc && pTabList.a[j].iCursor != pExpr.iTable; j++ )
                ;
              if ( j < pTabList.nSrc )
              {
                pTab = pTabList.a[j].pTab;
                pS = pTabList.a[j].pSelect;
              }
              else
              {
                pNC = pNC.pNext;
              }
            }

            if ( pTab == null )
            {
              /* At one time, code such as "SELECT new.x" within a trigger would
              ** cause this condition to run.  Since then, we have restructured how
              ** trigger code is generated and so this condition is no longer 
              ** possible. However, it can still be true for statements like
              ** the following:
              **
              **   CREATE TABLE t1(col INTEGER);
              **   SELECT (SELECT t1.col) FROM FROM t1;
              **
              ** when columnType() is called on the expression "t1.col" in the 
              ** sub-select. In this case, set the column type to NULL, even
              ** though it should really be "INTEGER".
              **
              ** This is not a problem, as the column type of "t1.col" is never
              ** used. When columnType() is called on the expression 
              ** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT
              ** branch below.  */
              break;
            }

            //Debug.Assert( pTab != null && pExpr.pTab == pTab );
            if ( pS != null )
            {
              /* The "table" is actually a sub-select or a view in the FROM clause
              ** of the SELECT statement. Return the declaration type and origin
              ** data for the result-set column of the sub-select.
              */
              if ( iCol >= 0 && ALWAYS( iCol < pS.pEList.nExpr ) )
              {
                /* If iCol is less than zero, then the expression requests the
                ** rowid of the sub-select or view. This expression is legal (see
                ** test case misc2.2.2) - it always evaluates to NULL.
                */
                NameContext sNC = new NameContext();
                Expr p = pS.pEList.a[iCol].pExpr;
                sNC.pSrcList = pS.pSrc;
                sNC.pNext = pNC;
                sNC.pParse = pNC.pParse;
                zType = columnType( sNC, p, ref zOriginDb, ref zOriginTab, ref zOriginCol );
              }
            }
            else if ( ALWAYS( pTab.pSchema ) )
            {
              /* A real table */
              Debug.Assert( pS == null );
              if ( iCol < 0 )
                iCol = pTab.iPKey;
              Debug.Assert( iCol == -1 || ( iCol >= 0 && iCol < pTab.nCol ) );
              if ( iCol < 0 )
              {
                zType = "INTEGER";
                zOriginCol = "rowid";
              }
              else
              {
                zType = pTab.aCol[iCol].zType;
                zOriginCol = pTab.aCol[iCol].zName;
              }
              zOriginTab = pTab.zName;
              if ( pNC.pParse != null )
              {
                int iDb = sqlite3SchemaToIndex( pNC.pParse.db, pTab.pSchema );
                zOriginDb = pNC.pParse.db.aDb[iDb].zName;
              }
            }
            break;
          }
#if !SQLITE_OMIT_SUBQUERY
        case TK_SELECT:
          {
            /* The expression is a sub-select. Return the declaration type and
            ** origin info for the single column in the result set of the SELECT
            ** statement.
            */
            NameContext sNC = new NameContext();
            Select pS = pExpr.x.pSelect;
            Expr p = pS.pEList.a[0].pExpr;
            Debug.Assert( ExprHasProperty( pExpr, EP_xIsSelect ) );
            sNC.pSrcList = pS.pSrc;
            sNC.pNext = pNC;
            sNC.pParse = pNC.pParse;
            zType = columnType( sNC, p, ref zOriginDb, ref zOriginTab, ref zOriginCol );
            break;
          }
#endif
      }

      //if ( pzOriginDb != null )
      {
        //Debug.Assert( pzOriginTab != null && pzOriginCol != null );
        pzOriginDb = zOriginDb;
        pzOriginTab = zOriginTab;
        pzOriginCol = zOriginCol;
      }
      return zType;
    }
Esempio n. 43
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 );
 }
Esempio n. 44
0
    /*
    ** Add type and collation information to a column list based on
    ** a SELECT statement.
    **
    ** The column list presumably came from selectColumnNamesFromExprList().
    ** The column list has only names, not types or collations.  This
    ** routine goes through and adds the types and collations.
    **
    ** This routine requires that all identifiers in the SELECT
    ** statement be resolved.
    */
    static void selectAddColumnTypeAndCollation(
    Parse pParse,         /* Parsing contexts */
    int nCol,             /* Number of columns */
    Column[] aCol,        /* List of columns */
    Select pSelect        /* SELECT used to determine types and collations */
    )
    {
      ////sqlite3 db = pParse.db;
      NameContext sNC;
      Column pCol;
      CollSeq pColl;
      int i;
      Expr p;
      ExprList_item[] a;

      Debug.Assert( pSelect != null );
      Debug.Assert( ( pSelect.selFlags & SF_Resolved ) != 0 );
      Debug.Assert( nCol == pSelect.pEList.nExpr /*|| db.mallocFailed != 0 */ );
      //      if ( db.mallocFailed != 0 ) return;
      sNC = new NameContext();// memset( &sNC, 0, sizeof( sNC ) );
      sNC.pSrcList = pSelect.pSrc;
      a = pSelect.pEList.a;
      for ( i = 0; i < nCol; i++ )//, pCol++ )
      {
        pCol = aCol[i];
        p = a[i].pExpr;
        string bDummy = null;
        pCol.zType = columnType( sNC, p, ref bDummy, ref bDummy, ref bDummy );// sqlite3DbStrDup( db, columnType( sNC, p, 0, 0, 0 ) );
        pCol.affinity = sqlite3ExprAffinity( p );
        if ( pCol.affinity == 0 )
          pCol.affinity = SQLITE_AFF_NONE;
        pColl = sqlite3ExprCollSeq( pParse, p );
        if ( pColl != null )
        {
          pCol.zColl = pColl.zName;// sqlite3DbStrDup( db, pColl.zName );
        }
      }
    }
Esempio n. 45
0
 static void SelectAddColumnTypeAndCollation(Parse parse, int colsLength, Column[] cols, Select select)
 {
     Context ctx = parse.Ctx;
     Debug.Assert(select != null);
     Debug.Assert((select.SelFlags & SF.Resolved) != 0);
     Debug.Assert(colsLength == select.EList.Exprs || ctx.MallocFailed);
     if (ctx.MallocFailed) return;
     NameContext sNC = new NameContext();
     sNC.SrcList = select.Src;
     ExprList.ExprListItem[] ids = select.EList.Ids;
     int i;
     Column col;
     for (i = 0; i < colsLength; i++)
     {
         col = cols[i];
         Expr p = ids[i].Expr;
         string dummy1 = null;
         col.Type = ColumnType(sNC, p, ref dummy1, ref dummy1, ref dummy1);
         col.Affinity = p.Affinity();
         if (col.Affinity == 0) col.Affinity = AFF.NONE;
         CollSeq coll = p.CollSeq(parse);
         if (coll != null)
             col.Coll = coll.Name;
     }
 }
Esempio n. 46
0
    static int sqlite3Select(
    Parse pParse,         /* The parser context */
    Select p,             /* The SELECT statement being coded. */
    ref SelectDest pDest /* What to do with the query results */
    )
    {
      int i, j;               /* Loop counters */
      WhereInfo pWInfo;       /* Return from sqlite3WhereBegin() */
      Vdbe v;                 /* The virtual machine under construction */
      bool isAgg;             /* True for select lists like "count()" */
      ExprList pEList = new ExprList();      /* List of columns to extract. */
      SrcList pTabList = new SrcList();     /* List of tables to select from */
      Expr pWhere;            /* The WHERE clause.  May be NULL */
      ExprList pOrderBy;      /* The ORDER BY clause.  May be NULL */
      ExprList pGroupBy;      /* The GROUP BY clause.  May be NULL */
      Expr pHaving;           /* The HAVING clause.  May be NULL */
      bool isDistinct;        /* True if the DISTINCT keyword is present */
      int distinct;           /* Table to use for the distinct set */
      int rc = 1;             /* Value to return from this function */
      int addrSortIndex;      /* Address of an OP_OpenEphemeral instruction */
      AggInfo sAggInfo;       /* Information used by aggregate queries */
      int iEnd;               /* Address of the end of the query */
      sqlite3 db;             /* The database connection */

#if !SQLITE_OMIT_EXPLAIN
      int iRestoreSelectId = pParse.iSelectId;
      pParse.iSelectId = pParse.iNextSelectId++;
#endif

      db = pParse.db;
      if ( p == null /*|| db.mallocFailed != 0 */ || pParse.nErr != 0 )
      {
        return 1;
      }
#if !SQLITE_OMIT_AUTHORIZATION
if (sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0)) return 1;
#endif
      sAggInfo = new AggInfo();// memset(sAggInfo, 0, sAggInfo).Length;

      if ( pDest.eDest <= SRT_Discard ) //IgnorableOrderby(pDest))
      {
        Debug.Assert( pDest.eDest == SRT_Exists || pDest.eDest == SRT_Union ||
        pDest.eDest == SRT_Except || pDest.eDest == SRT_Discard );
        /* If ORDER BY makes no difference in the output then neither does
        ** DISTINCT so it can be removed too. */
        sqlite3ExprListDelete( db, ref p.pOrderBy );
        p.pOrderBy = null;
        p.selFlags = (u16)( p.selFlags & ~SF_Distinct );
      }
      sqlite3SelectPrep( pParse, p, null );
      pOrderBy = p.pOrderBy;
      pTabList = p.pSrc;
      pEList = p.pEList;
      if ( pParse.nErr != 0 /*|| db.mallocFailed != 0 */ )
      {
        goto select_end;
      }
      isAgg = ( p.selFlags & SF_Aggregate ) != 0;
      Debug.Assert( pEList != null );

      /* Begin generating code.
      */
      v = sqlite3GetVdbe( pParse );
      if ( v == null )
        goto select_end;

      /* If writing to memory or generating a set
      ** only a single column may be output.
      */
#if !SQLITE_OMIT_SUBQUERY
      if ( checkForMultiColumnSelectError( pParse, pDest, pEList.nExpr ) )
      {
        goto select_end;
      }
#endif

      /* Generate code for all sub-queries in the FROM clause
*/
#if !SQLITE_OMIT_SUBQUERY || !SQLITE_OMIT_VIEW
      for ( i = 0; p.pPrior == null && i < pTabList.nSrc; i++ )
      {
        SrcList_item pItem = pTabList.a[i];
        SelectDest dest = new SelectDest();
        Select pSub = pItem.pSelect;
        bool isAggSub;

        if ( pSub == null || pItem.isPopulated != 0 )
          continue;

        /* Increment Parse.nHeight by the height of the largest expression
        ** tree refered to by this, the parent select. The child select
        ** may contain expression trees of at most
        ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
        ** more conservative than necessary, but much easier than enforcing
        ** an exact limit.
        */
        pParse.nHeight += sqlite3SelectExprHeight( p );

        /* Check to see if the subquery can be absorbed into the parent. */
        isAggSub = ( pSub.selFlags & SF_Aggregate ) != 0;
        if ( flattenSubquery( pParse, p, i, isAgg, isAggSub ) != 0 )
        {
          if ( isAggSub )
          {
            isAgg = true;
            p.selFlags |= SF_Aggregate;
          }
          i = -1;
        }
        else
        {
          sqlite3SelectDestInit( dest, SRT_EphemTab, pItem.iCursor );
          Debug.Assert( 0 == pItem.isPopulated );
          explainSetInteger( ref pItem.iSelectId, (int)pParse.iNextSelectId );
          sqlite3Select( pParse, pSub, ref dest );
          pItem.isPopulated = 1;
          pItem.pTab.nRowEst = (uint)pSub.nSelectRow;
        }
        //if ( /* pParse.nErr != 0 || */ db.mallocFailed != 0 )
        //{
        //  goto select_end;
        //}
        pParse.nHeight -= sqlite3SelectExprHeight( p );
        pTabList = p.pSrc;
        if ( !( pDest.eDest <= SRT_Discard ) )//        if( null==IgnorableOrderby(pDest) )
        {
          pOrderBy = p.pOrderBy;
        }
      }
      pEList = p.pEList;
#endif
      pWhere = p.pWhere;
      pGroupBy = p.pGroupBy;
      pHaving = p.pHaving;
      isDistinct = ( p.selFlags & SF_Distinct ) != 0;

#if  !SQLITE_OMIT_COMPOUND_SELECT
      /* If there is are a sequence of queries, do the earlier ones first.
*/
      if ( p.pPrior != null )
      {
        if ( p.pRightmost == null )
        {
          Select pLoop, pRight = null;
          int cnt = 0;
          int mxSelect;
          for ( pLoop = p; pLoop != null; pLoop = pLoop.pPrior, cnt++ )
          {
            pLoop.pRightmost = p;
            pLoop.pNext = pRight;
            pRight = pLoop;
          }
          mxSelect = db.aLimit[SQLITE_LIMIT_COMPOUND_SELECT];
          if ( mxSelect != 0 && cnt > mxSelect )
          {
            sqlite3ErrorMsg( pParse, "too many terms in compound SELECT" );
            goto select_end;
          }
        }
        rc = multiSelect( pParse, p, pDest );
        explainSetInteger( ref pParse.iSelectId, iRestoreSelectId );
        return rc;
      }
#endif

      /* If possible, rewrite the query to use GROUP BY instead of DISTINCT.
** GROUP BY might use an index, DISTINCT never does.
*/
      Debug.Assert( p.pGroupBy == null || ( p.selFlags & SF_Aggregate ) != 0 );
      if ( ( p.selFlags & ( SF_Distinct | SF_Aggregate ) ) == SF_Distinct )
      {
        p.pGroupBy = sqlite3ExprListDup( db, p.pEList, 0 );
        pGroupBy = p.pGroupBy;
        p.selFlags = (u16)( p.selFlags & ~SF_Distinct );
      }

      /* If there is both a GROUP BY and an ORDER BY clause and they are
      ** identical, then disable the ORDER BY clause since the GROUP BY
      ** will cause elements to come out in the correct order.  This is
      ** an optimization - the correct answer should result regardless.
      ** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
      ** to disable this optimization for testing purposes.
      */
      if ( sqlite3ExprListCompare( p.pGroupBy, pOrderBy ) == 0
      && ( db.flags & SQLITE_GroupByOrder ) == 0 )
      {
        pOrderBy = null;
      }

      /* If there is an ORDER BY clause, then this sorting
      ** index might end up being unused if the data can be
      ** extracted in pre-sorted order.  If that is the case, then the
      ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
      ** we figure out that the sorting index is not needed.  The addrSortIndex
      ** variable is used to facilitate that change.
      */
      if ( pOrderBy != null )
      {
        KeyInfo pKeyInfo;
        pKeyInfo = keyInfoFromExprList( pParse, pOrderBy );
        pOrderBy.iECursor = pParse.nTab++;
        p.addrOpenEphm[2] = addrSortIndex =
        sqlite3VdbeAddOp4( v, OP_OpenEphemeral,
        pOrderBy.iECursor, pOrderBy.nExpr + 2, 0,
        pKeyInfo, P4_KEYINFO_HANDOFF );
      }
      else
      {
        addrSortIndex = -1;
      }

      /* If the output is destined for a temporary table, open that table.
      */
      if ( pDest.eDest == SRT_EphemTab )
      {
        sqlite3VdbeAddOp2( v, OP_OpenEphemeral, pDest.iParm, pEList.nExpr );
      }

      /* Set the limiter.
      */
      iEnd = sqlite3VdbeMakeLabel( v );
      p.nSelectRow = (double)LARGEST_INT64;
      computeLimitRegisters( pParse, p, iEnd );

      /* Open a virtual index to use for the distinct set.
      */
      if ( ( p.selFlags & SF_Distinct ) != 0 )
      {
        KeyInfo pKeyInfo;
        Debug.Assert( isAgg || pGroupBy != null );
        distinct = pParse.nTab++;
        pKeyInfo = keyInfoFromExprList( pParse, p.pEList );
        sqlite3VdbeAddOp4( v, OP_OpenEphemeral, distinct, 0, 0,
        pKeyInfo, P4_KEYINFO_HANDOFF );
        sqlite3VdbeChangeP5( v, BTREE_UNORDERED );
      }
      else
      {
        distinct = -1;
      }

      /* Aggregate and non-aggregate queries are handled differently */
      if ( !isAgg && pGroupBy == null )
      {
        /* This case is for non-aggregate queries
        ** Begin the database scan
        */
        pWInfo = sqlite3WhereBegin( pParse, pTabList, pWhere, ref pOrderBy, 0 );
        if ( pWInfo == null )
          goto select_end;
        if ( pWInfo.nRowOut < p.nSelectRow )
          p.nSelectRow = pWInfo.nRowOut;

        /* If sorting index that was created by a prior OP_OpenEphemeral
        ** instruction ended up not being needed, then change the OP_OpenEphemeral
        ** into an OP_Noop.
        */
        if ( addrSortIndex >= 0 && pOrderBy == null )
        {
          sqlite3VdbeChangeToNoop( v, addrSortIndex, 1 );
          p.addrOpenEphm[2] = -1;
        }

        /* Use the standard inner loop
        */
        Debug.Assert( !isDistinct );
        selectInnerLoop( pParse, p, pEList, 0, 0, pOrderBy, -1, pDest,
        pWInfo.iContinue, pWInfo.iBreak );

        /* End the database scan loop.
        */
        sqlite3WhereEnd( pWInfo );
      }
      else
      {
        /* This is the processing for aggregate queries */
        NameContext sNC;    /* Name context for processing aggregate information */
        int iAMem;          /* First Mem address for storing current GROUP BY */
        int iBMem;          /* First Mem address for previous GROUP BY */
        int iUseFlag;       /* Mem address holding flag indicating that at least
** one row of the input to the aggregator has been
** processed */
        int iAbortFlag;     /* Mem address which causes query abort if positive */
        int groupBySort;    /* Rows come from source in GR BY' clause thanROUP BY order */

        int addrEnd;        /* End of processing for this SELECT */

        /* Remove any and all aliases between the result set and the
        ** GROUP BY clause.
        */
        if ( pGroupBy != null )
        {
          int k;                        /* Loop counter */
          ExprList_item pItem;          /* For looping over expression in a list */

          for ( k = p.pEList.nExpr; k > 0; k-- )//, pItem++)
          {
            pItem = p.pEList.a[p.pEList.nExpr - k];
            pItem.iAlias = 0;
          }
          for ( k = pGroupBy.nExpr; k > 0; k-- )//, pItem++ )
          {
            pItem = pGroupBy.a[pGroupBy.nExpr - k];
            pItem.iAlias = 0;
          }
          if ( p.nSelectRow > (double)100 )
            p.nSelectRow = (double)100;
        }
        else
        {
          p.nSelectRow = (double)1;
        }

        /* Create a label to jump to when we want to abort the query */
        addrEnd = sqlite3VdbeMakeLabel( v );

        /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in
        ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the
        ** SELECT statement.
        */
        sNC = new NameContext(); // memset(sNC, 0, sNC).Length;
        sNC.pParse = pParse;
        sNC.pSrcList = pTabList;
        sNC.pAggInfo = sAggInfo;
        sAggInfo.nSortingColumn = pGroupBy != null ? pGroupBy.nExpr + 1 : 0;
        sAggInfo.pGroupBy = pGroupBy;
        sqlite3ExprAnalyzeAggList( sNC, pEList );
        sqlite3ExprAnalyzeAggList( sNC, pOrderBy );
        if ( pHaving != null )
        {
          sqlite3ExprAnalyzeAggregates( sNC, ref pHaving );
        }
        sAggInfo.nAccumulator = sAggInfo.nColumn;
        for ( i = 0; i < sAggInfo.nFunc; i++ )
        {
          Debug.Assert( !ExprHasProperty( sAggInfo.aFunc[i].pExpr, EP_xIsSelect ) );
          sqlite3ExprAnalyzeAggList( sNC, sAggInfo.aFunc[i].pExpr.x.pList );
        }
        //      if ( db.mallocFailed != 0 ) goto select_end;

        /* Processing for aggregates with GROUP BY is very different and
        ** much more complex than aggregates without a GROUP BY.
        */
        if ( pGroupBy != null )
        {
          KeyInfo pKeyInfo;  /* Keying information for the group by clause */
          int j1;             /* A-vs-B comparision jump */
          int addrOutputRow;  /* Start of subroutine that outputs a result row */
          int regOutputRow;   /* Return address register for output subroutine */
          int addrSetAbort;   /* Set the abort flag and return */
          int addrTopOfLoop;  /* Top of the input loop */
          int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
          int addrReset;      /* Subroutine for resetting the accumulator */
          int regReset;       /* Return address register for reset subroutine */

          /* If there is a GROUP BY clause we might need a sorting index to
          ** implement it.  Allocate that sorting index now.  If it turns out
          ** that we do not need it after all, the OpenEphemeral instruction
          ** will be converted into a Noop.
          */
          sAggInfo.sortingIdx = pParse.nTab++;
          pKeyInfo = keyInfoFromExprList( pParse, pGroupBy );
          addrSortingIdx = sqlite3VdbeAddOp4( v, OP_OpenEphemeral,
          sAggInfo.sortingIdx, sAggInfo.nSortingColumn,
          0, pKeyInfo, P4_KEYINFO_HANDOFF );

          /* Initialize memory locations used by GROUP BY aggregate processing
          */
          iUseFlag = ++pParse.nMem;
          iAbortFlag = ++pParse.nMem;
          regOutputRow = ++pParse.nMem;
          addrOutputRow = sqlite3VdbeMakeLabel( v );
          regReset = ++pParse.nMem;
          addrReset = sqlite3VdbeMakeLabel( v );
          iAMem = pParse.nMem + 1;
          pParse.nMem += pGroupBy.nExpr;
          iBMem = pParse.nMem + 1;
          pParse.nMem += pGroupBy.nExpr;
          sqlite3VdbeAddOp2( v, OP_Integer, 0, iAbortFlag );
#if SQLITE_DEBUG
          VdbeComment( v, "clear abort flag" );
#endif
          sqlite3VdbeAddOp2( v, OP_Integer, 0, iUseFlag );
#if SQLITE_DEBUG
          VdbeComment( v, "indicate accumulator empty" );
#endif

          /* Begin a loop that will extract all source rows in GROUP BY order.
** This might involve two separate loops with an OP_Sort in between, or
** it might be a single loop that uses an index to extract information
** in the right order to begin with.
*/
          sqlite3VdbeAddOp2( v, OP_Gosub, regReset, addrReset );
          pWInfo = sqlite3WhereBegin( pParse, pTabList, pWhere, ref pGroupBy, 0 );
          if ( pWInfo == null )
            goto select_end;
          if ( pGroupBy == null )
          {
            /* The optimizer is able to deliver rows in group by order so
            ** we do not have to sort.  The OP_OpenEphemeral table will be
            ** cancelled later because we still need to use the pKeyInfo
            */
            pGroupBy = p.pGroupBy;
            groupBySort = 0;
          }
          else
          {
            /* Rows are coming out in undetermined order.  We have to push
            ** each row into a sorting index, terminate the first loop,
            ** then loop over the sorting index in order to get the output
            ** in sorted order
            */
            int regBase;
            int regRecord;
            int nCol;
            int nGroupBy;

            explainTempTable( pParse,
            isDistinct && 0 == ( p.selFlags & SF_Distinct ) ? "DISTINCT" : "GROUP BY" );

            groupBySort = 1;
            nGroupBy = pGroupBy.nExpr;
            nCol = nGroupBy + 1;
            j = nGroupBy + 1;
            for ( i = 0; i < sAggInfo.nColumn; i++ )
            {
              if ( sAggInfo.aCol[i].iSorterColumn >= j )
              {
                nCol++;
                j++;
              }
            }
            regBase = sqlite3GetTempRange( pParse, nCol );
            sqlite3ExprCacheClear( pParse );
            sqlite3ExprCodeExprList( pParse, pGroupBy, regBase, false );
            sqlite3VdbeAddOp2( v, OP_Sequence, sAggInfo.sortingIdx, regBase + nGroupBy );
            j = nGroupBy + 1;
            for ( i = 0; i < sAggInfo.nColumn; i++ )
            {
              AggInfo_col pCol = sAggInfo.aCol[i];
              if ( pCol.iSorterColumn >= j )
              {
                int r1 = j + regBase;
                int r2;
                r2 = sqlite3ExprCodeGetColumn( pParse,
                pCol.pTab, pCol.iColumn, pCol.iTable, r1 );
                if ( r1 != r2 )
                {
                  sqlite3VdbeAddOp2( v, OP_SCopy, r2, r1 );
                }
                j++;
              }
            }
            regRecord = sqlite3GetTempReg( pParse );
            sqlite3VdbeAddOp3( v, OP_MakeRecord, regBase, nCol, regRecord );
            sqlite3VdbeAddOp2( v, OP_IdxInsert, sAggInfo.sortingIdx, regRecord );
            sqlite3ReleaseTempReg( pParse, regRecord );
            sqlite3ReleaseTempRange( pParse, regBase, nCol );
            sqlite3WhereEnd( pWInfo );
            sqlite3VdbeAddOp2( v, OP_Sort, sAggInfo.sortingIdx, addrEnd );
#if SQLITE_DEBUG
            VdbeComment( v, "GROUP BY sort" );
#endif
            sAggInfo.useSortingIdx = 1;
            sqlite3ExprCacheClear( pParse );
          }

          /* Evaluate the current GROUP BY terms and store in b0, b1, b2...
          ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth)
          ** Then compare the current GROUP BY terms against the GROUP BY terms
          ** from the previous row currently stored in a0, a1, a2...
          */
          addrTopOfLoop = sqlite3VdbeCurrentAddr( v );
          sqlite3ExprCacheClear( pParse );
          for ( j = 0; j < pGroupBy.nExpr; j++ )
          {
            if ( groupBySort != 0 )
            {
              sqlite3VdbeAddOp3( v, OP_Column, sAggInfo.sortingIdx, j, iBMem + j );
            }
            else
            {
              sAggInfo.directMode = 1;
              sqlite3ExprCode( pParse, pGroupBy.a[j].pExpr, iBMem + j );
            }
          }
          sqlite3VdbeAddOp4( v, OP_Compare, iAMem, iBMem, pGroupBy.nExpr,
          pKeyInfo, P4_KEYINFO );
          j1 = sqlite3VdbeCurrentAddr( v );
          sqlite3VdbeAddOp3( v, OP_Jump, j1 + 1, 0, j1 + 1 );

          /* Generate code that runs whenever the GROUP BY changes.
          ** Changes in the GROUP BY are detected by the previous code
          ** block.  If there were no changes, this block is skipped.
          **
          ** This code copies current group by terms in b0,b1,b2,...
          ** over to a0,a1,a2.  It then calls the output subroutine
          ** and resets the aggregate accumulator registers in preparation
          ** for the next GROUP BY batch.
          */
          sqlite3ExprCodeMove( pParse, iBMem, iAMem, pGroupBy.nExpr );
          sqlite3VdbeAddOp2( v, OP_Gosub, regOutputRow, addrOutputRow );
#if SQLITE_DEBUG
          VdbeComment( v, "output one row" );
#endif
          sqlite3VdbeAddOp2( v, OP_IfPos, iAbortFlag, addrEnd );
#if SQLITE_DEBUG
          VdbeComment( v, "check abort flag" );
#endif
          sqlite3VdbeAddOp2( v, OP_Gosub, regReset, addrReset );
#if SQLITE_DEBUG
          VdbeComment( v, "reset accumulator" );
#endif

          /* Update the aggregate accumulators based on the content of
** the current row
*/
          sqlite3VdbeJumpHere( v, j1 );
          updateAccumulator( pParse, sAggInfo );
          sqlite3VdbeAddOp2( v, OP_Integer, 1, iUseFlag );
#if SQLITE_DEBUG
          VdbeComment( v, "indicate data in accumulator" );
#endif
          /* End of the loop
*/
          if ( groupBySort != 0 )
          {
            sqlite3VdbeAddOp2( v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop );
          }
          else
          {
            sqlite3WhereEnd( pWInfo );
            sqlite3VdbeChangeToNoop( v, addrSortingIdx, 1 );
          }

          /* Output the final row of result
          */
          sqlite3VdbeAddOp2( v, OP_Gosub, regOutputRow, addrOutputRow );
#if SQLITE_DEBUG
          VdbeComment( v, "output final row" );
#endif
          /* Jump over the subroutines
*/
          sqlite3VdbeAddOp2( v, OP_Goto, 0, addrEnd );

          /* Generate a subroutine that outputs a single row of the result
          ** set.  This subroutine first looks at the iUseFlag.  If iUseFlag
          ** is less than or equal to zero, the subroutine is a no-op.  If
          ** the processing calls for the query to abort, this subroutine
          ** increments the iAbortFlag memory location before returning in
          ** order to signal the caller to abort.
          */
          addrSetAbort = sqlite3VdbeCurrentAddr( v );
          sqlite3VdbeAddOp2( v, OP_Integer, 1, iAbortFlag );
          VdbeComment( v, "set abort flag" );
          sqlite3VdbeAddOp1( v, OP_Return, regOutputRow );
          sqlite3VdbeResolveLabel( v, addrOutputRow );
          addrOutputRow = sqlite3VdbeCurrentAddr( v );
          sqlite3VdbeAddOp2( v, OP_IfPos, iUseFlag, addrOutputRow + 2 );
          VdbeComment( v, "Groupby result generator entry point" );
          sqlite3VdbeAddOp1( v, OP_Return, regOutputRow );
          finalizeAggFunctions( pParse, sAggInfo );
          sqlite3ExprIfFalse( pParse, pHaving, addrOutputRow + 1, SQLITE_JUMPIFNULL );
          selectInnerLoop( pParse, p, p.pEList, 0, 0, pOrderBy,
          distinct, pDest,
          addrOutputRow + 1, addrSetAbort );
          sqlite3VdbeAddOp1( v, OP_Return, regOutputRow );
          VdbeComment( v, "end groupby result generator" );

          /* Generate a subroutine that will reset the group-by accumulator
          */
          sqlite3VdbeResolveLabel( v, addrReset );
          resetAccumulator( pParse, sAggInfo );
          sqlite3VdbeAddOp1( v, OP_Return, regReset );

        } /* endif pGroupBy.  Begin aggregate queries without GROUP BY: */
        else
        {
          ExprList pDel = null;
#if !SQLITE_OMIT_BTREECOUNT
          Table pTab;
          if ( ( pTab = isSimpleCount( p, sAggInfo ) ) != null )
          {
            /* If isSimpleCount() returns a pointer to a Table structure, then
            ** the SQL statement is of the form:
            **
            **   SELECT count() FROM <tbl>
            **
            ** where the Table structure returned represents table <tbl>.
            **
            ** This statement is so common that it is optimized specially. The
            ** OP_Count instruction is executed either on the intkey table that
            ** contains the data for table <tbl> or on one of its indexes. It
            ** is better to execute the op on an index, as indexes are almost
            ** always spread across less pages than their corresponding tables.
            */
            int iDb = sqlite3SchemaToIndex( pParse.db, pTab.pSchema );
            int iCsr = pParse.nTab++;     /* Cursor to scan b-tree */
            Index pIdx;                   /* Iterator variable */
            KeyInfo pKeyInfo = null;      /* Keyinfo for scanned index */
            Index pBest = null;           /* Best index found so far */
            int iRoot = pTab.tnum;        /* Root page of scanned b-tree */

            sqlite3CodeVerifySchema( pParse, iDb );
            sqlite3TableLock( pParse, iDb, pTab.tnum, 0, pTab.zName );

            /* Search for the index that has the least amount of columns. If
            ** there is such an index, and it has less columns than the table
            ** does, then we can assume that it consumes less space on disk and
            ** will therefore be cheaper to scan to determine the query result.
            ** In this case set iRoot to the root page number of the index b-tree
            ** and pKeyInfo to the KeyInfo structure required to navigate the
            ** index.
            **
            ** (2011-04-15) Do not do a full scan of an unordered index.
            **
            ** In practice the KeyInfo structure will not be used. It is only
            ** passed to keep OP_OpenRead happy.
            */
            for ( pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext )
            {
              if ( pIdx.bUnordered == 0 && ( null == pBest || pIdx.nColumn < pBest.nColumn ) )
              {
                pBest = pIdx;
              }
            }
            if ( pBest != null && pBest.nColumn < pTab.nCol )
            {
              iRoot = pBest.tnum;
              pKeyInfo = sqlite3IndexKeyinfo( pParse, pBest );
            }

            /* Open a read-only cursor, execute the OP_Count, close the cursor. */
            sqlite3VdbeAddOp3( v, OP_OpenRead, iCsr, iRoot, iDb );
            if ( pKeyInfo != null )
            {
              sqlite3VdbeChangeP4( v, -1, pKeyInfo, P4_KEYINFO_HANDOFF );
            }
            sqlite3VdbeAddOp2( v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem );
            sqlite3VdbeAddOp1( v, OP_Close, iCsr );
            explainSimpleCount( pParse, pTab, pBest );
          }
          else
#endif //* SQLITE_OMIT_BTREECOUNT */
          {

            /* Check if the query is of one of the following forms:
            **
            **   SELECT min(x) FROM ...
            **   SELECT max(x) FROM ...
            **
            ** If it is, then ask the code in where.c to attempt to sort results
            ** as if there was an "ORDER ON x" or "ORDER ON x DESC" clause.
            ** If where.c is able to produce results sorted in this order, then
            ** add vdbe code to break out of the processing loop after the
            ** first iteration (since the first iteration of the loop is
            ** guaranteed to operate on the row with the minimum or maximum
            ** value of x, the only row required).
            **
            ** A special flag must be passed to sqlite3WhereBegin() to slightly
            ** modify behavior as follows:
            **
            **   + If the query is a "SELECT min(x)", then the loop coded by
            **     where.c should not iterate over any values with a NULL value
            **     for x.
            **
            **   + The optimizer code in where.c (the thing that decides which
            **     index or indices to use) should place a different priority on
            **     satisfying the 'ORDER BY' clause than it does in other cases.
            **     Refer to code and comments in where.c for details.
            */
            ExprList pMinMax = null;
            int flag = minMaxQuery( p );
            if ( flag != 0 )
            {
              Debug.Assert( !ExprHasProperty( p.pEList.a[0].pExpr, EP_xIsSelect ) );
              pMinMax = sqlite3ExprListDup( db, p.pEList.a[0].pExpr.x.pList, 0 );
              pDel = pMinMax;
              if ( pMinMax != null )///* && 0 == db.mallocFailed */ )
              {
                pMinMax.a[0].sortOrder = (u8)( flag != WHERE_ORDERBY_MIN ? 1 : 0 );
                pMinMax.a[0].pExpr.op = TK_COLUMN;
              }
            }

            /* This case runs if the aggregate has no GROUP BY clause.  The
            ** processing is much simpler since there is only a single row
            ** of output.
            */
            resetAccumulator( pParse, sAggInfo );
            pWInfo = sqlite3WhereBegin( pParse, pTabList, pWhere, ref pMinMax, (byte)flag );
            if ( pWInfo == null )
            {
              sqlite3ExprListDelete( db, ref pDel );
              goto select_end;
            }
            updateAccumulator( pParse, sAggInfo );
            if ( pMinMax == null && flag != 0 )
            {
              sqlite3VdbeAddOp2( v, OP_Goto, 0, pWInfo.iBreak );
#if SQLITE_DEBUG
              VdbeComment( v, "%s() by index",
              ( flag == WHERE_ORDERBY_MIN ? "min" : "max" ) );
#endif
            }
            sqlite3WhereEnd( pWInfo );
            finalizeAggFunctions( pParse, sAggInfo );
          }

          pOrderBy = null;
          sqlite3ExprIfFalse( pParse, pHaving, addrEnd, SQLITE_JUMPIFNULL );
          selectInnerLoop( pParse, p, p.pEList, 0, 0, null, -1,
          pDest, addrEnd, addrEnd );

          sqlite3ExprListDelete( db, ref pDel );
        }
        sqlite3VdbeResolveLabel( v, addrEnd );

      } /* endif aggregate query */

      if ( distinct >= 0 )
      {
        explainTempTable( pParse, "DISTINCT" );
      }

      /* If there is an ORDER BY clause, then we need to sort the results
      ** and send them to the callback one by one.
      */
      if ( pOrderBy != null )
      {
        explainTempTable( pParse, "ORDER BY" );
        generateSortTail( pParse, p, v, pEList.nExpr, pDest );
      }

      /* Jump here to skip this query
      */
      sqlite3VdbeResolveLabel( v, iEnd );

      /* The SELECT was successfully coded.   Set the return code to 0
      ** to indicate no errors.
      */
      rc = 0;

    /* Control jumps to here if an error is encountered above, or upon
    ** successful coding of the SELECT.
    */
select_end:
      explainSetInteger( ref pParse.iSelectId, iRestoreSelectId );

      /* Identify column names if results of the SELECT are to be output.
      */
      if ( rc == SQLITE_OK && pDest.eDest == SRT_Output )
      {
        generateColumnNames( pParse, pTabList, pEList );
      }

      sqlite3DbFree( db, ref sAggInfo.aCol );
      sqlite3DbFree( db, ref sAggInfo.aFunc );
      return rc;
    }
Esempio n. 47
0
        static void GenerateColumnTypes(Parse parse, SrcList tabList, ExprList list)
        {
#if !OMIT_DECLTYPE
            Vdbe v = parse.V;
            NameContext sNC = new NameContext();
            sNC.SrcList = tabList;
            sNC.Parse = parse;
            for (int i = 0; i < list.Exprs; i++)
            {
                Expr p = list.Ids[i].Expr;
                string typeName;
#if ENABLE_COLUMN_METADATA
                string origDbName = null;
                string origTableName = null;
                string origColumnName = null;
                typeName = ColumnType(sNC, p, ref origDbName, ref origTableName, ref origColumnName);

                // The vdbe must make its own copy of the column-type and other column specific strings, in case the schema is reset before this
                // virtual machine is deleted.
                v.SetColName(i, COLNAME_DATABASE, origDbName, C.DESTRUCTOR_TRANSIENT);
                v.SetColName(i, COLNAME_TABLE, origTableName, C.DESTRUCTOR_TRANSIENT);
                v.SetColName(i, COLNAME_COLUMN, origColumnName, C.DESTRUCTOR_TRANSIENT);
#else
                string dummy1 = null;
                typeName = ColumnType(sNC, p, ref dummy1, ref dummy1, ref dummy1);
#endif
                v.SetColName(i, COLNAME_DECLTYPE, typeName, C.DESTRUCTOR_TRANSIENT);
            }
#endif
        }
Esempio n. 48
0
		/*
		** Process an UPDATE statement.
		**
		**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
		**          \_______/ \________/     \______/       \________________/
		*            onError   pTabList      pChanges             pWhere
		*/
		static void sqlite3Update(
		Parse pParse,         /* The parser context */
		SrcList pTabList,     /* The table in which we should change things */
		ExprList pChanges,    /* Things to be changed */
		Expr pWhere,          /* The WHERE clause.  May be null */
		int onError           /* How to handle constraint errors */
		)
		{
			int i, j;                   /* Loop counters */
			Table pTab;                 /* The table to be updated */
			int addr = 0;               /* VDBE instruction address of the start of the loop */
			WhereInfo pWInfo;           /* Information about the WHERE clause */
			Vdbe v;                     /* The virtual database engine */
			Index pIdx;                 /* For looping over indices */
			int nIdx;                   /* Number of indices that need updating */
			int iCur;                   /* VDBE Cursor number of pTab */
			sqlite3 db;                 /* The database structure */
			int[] aRegIdx = null;       /* One register assigned to each index to be updated */
			int[] aXRef = null;         /* aXRef[i] is the index in pChanges.a[] of the
** an expression for the i-th column of the table.
** aXRef[i]==-1 if the i-th column is not changed. */
			bool chngRowid;             /* True if the record number is being changed */
			Expr pRowidExpr = null;     /* Expression defining the new record number */
			bool openAll = false;       /* True if all indices need to be opened */
			AuthContext sContext;       /* The authorization context */
			NameContext sNC;            /* The name-context to resolve expressions in */
			int iDb;                    /* Database containing the table being updated */
			bool okOnePass;             /* True for one-pass algorithm without the FIFO */
			bool hasFK;                 /* True if foreign key processing is required */

#if !SQLITE_OMIT_TRIGGER
			bool isView;            /* True when updating a view (INSTEAD OF trigger) */
			Trigger pTrigger;      /* List of triggers on pTab, if required */
			int tmask = 0;         /* Mask of TRIGGER_BEFORE|TRIGGER_AFTER */
#endif
			int newmask;           /* Mask of NEW.* columns accessed by BEFORE triggers */

			/* Register Allocations */
			int regRowCount = 0;         /* A count of rows changed */
			int regOldRowid;             /* The old rowid */
			int regNewRowid;             /* The new rowid */
			int regNew;
			int regOld = 0;
			int regRowSet = 0;           /* Rowset of rows to be updated */

			sContext = new AuthContext(); //memset( &sContext, 0, sizeof( sContext ) );
			db = pParse.db;
			if (pParse.nErr != 0 /*|| db.mallocFailed != 0 */ )
			{
				goto update_cleanup;
			}
			Debug.Assert(pTabList.nSrc == 1);

			/* Locate the table which we want to update.
			*/
			pTab = sqlite3SrcListLookup(pParse, pTabList);
			if (pTab == null)
				goto update_cleanup;
			iDb = sqlite3SchemaToIndex(pParse.db, pTab.pSchema);

			/* Figure out if we have any triggers and if the table being
			** updated is a view.
			*/
#if !SQLITE_OMIT_TRIGGER
			pTrigger = sqlite3TriggersExist(pParse, pTab, TK_UPDATE, pChanges, out tmask);
			isView = pTab.pSelect != null;
			Debug.Assert(pTrigger != null || tmask == 0);
#else
	  const Trigger pTrigger = null;//# define pTrigger 0
	  const int tmask = 0;          //# define tmask 0
#endif
#if SQLITE_OMIT_TRIGGER || SQLITE_OMIT_VIEW
//    # undef isView
	  const bool isView = false;    //# define isView 0
#endif

			if (sqlite3ViewGetColumnNames(pParse, pTab) != 0)
			{
				goto update_cleanup;
			}
			if (sqlite3IsReadOnly(pParse, pTab, tmask))
			{
				goto update_cleanup;
			}
			aXRef = new int[pTab.nCol];// sqlite3DbMallocRaw(db, sizeof(int) * pTab.nCol);
			//if ( aXRef == null ) goto update_cleanup;
			for (i = 0; i < pTab.nCol; i++)
				aXRef[i] = -1;

			/* Allocate a cursors for the main database table and for all indices.
			** The index cursors might not be used, but if they are used they
			** need to occur right after the database cursor.  So go ahead and
			** allocate enough space, just in case.
			*/
			pTabList.a[0].iCursor = iCur = pParse.nTab++;
			for (pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext)
			{
				pParse.nTab++;
			}

			/* Initialize the name-context */
			sNC = new NameContext();// memset(&sNC, 0, sNC).Length;
			sNC.pParse = pParse;
			sNC.pSrcList = pTabList;

			/* Resolve the column names in all the expressions of the
			** of the UPDATE statement.  Also find the column index
			** for each column to be updated in the pChanges array.  For each
			** column to be updated, make sure we have authorization to change
			** that column.
			*/
			chngRowid = false;
			for (i = 0; i < pChanges.nExpr; i++)
			{
				if (sqlite3ResolveExprNames(sNC, ref pChanges.a[i].pExpr) != 0)
				{
					goto update_cleanup;
				}
				for (j = 0; j < pTab.nCol; j++)
				{
					if (pTab.aCol[j].zName.Equals(pChanges.a[i].zName, StringComparison.InvariantCultureIgnoreCase))
					{
						if (j == pTab.iPKey)
						{
							chngRowid = true;
							pRowidExpr = pChanges.a[i].pExpr;
						}
						aXRef[j] = i;
						break;
					}
				}
				if (j >= pTab.nCol)
				{
					if (sqlite3IsRowid(pChanges.a[i].zName))
					{
						chngRowid = true;
						pRowidExpr = pChanges.a[i].pExpr;
					}
					else
					{
						sqlite3ErrorMsg(pParse, "no such column: %s", pChanges.a[i].zName);
						pParse.checkSchema = 1;
						goto update_cleanup;
					}
				}
#if !SQLITE_OMIT_AUTHORIZATION
{
int rc;
rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab.zName,
pTab.aCol[j].zName, db.aDb[iDb].zName);
if( rc==SQLITE_DENY ){
goto update_cleanup;
}else if( rc==SQLITE_IGNORE ){
aXRef[j] = -1;
}
}
#endif
			}

			hasFK = sqlite3FkRequired(pParse, pTab, aXRef, chngRowid ? 1 : 0) != 0;

			/* Allocate memory for the array aRegIdx[].  There is one entry in the
			** array for each index associated with table being updated.  Fill in
			** the value with a register number for indices that are to be used
			** and with zero for unused indices.
			*/
			for (nIdx = 0, pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext, nIdx++)
			{
			}
			if (nIdx > 0)
			{
				aRegIdx = new int[nIdx]; // sqlite3DbMallocRaw(db, Index*.Length * nIdx);
				if (aRegIdx == null)
					goto update_cleanup;
			}
			for (j = 0, pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext, j++)
			{
				int reg;
				if (hasFK || chngRowid)
				{
					reg = ++pParse.nMem;
				}
				else
				{
					reg = 0;
					for (i = 0; i < pIdx.nColumn; i++)
					{
						if (aXRef[pIdx.aiColumn[i]] >= 0)
						{
							reg = ++pParse.nMem;
							break;
						}
					}
				}
				aRegIdx[j] = reg;
			}

			/* Begin generating code. */
			v = sqlite3GetVdbe(pParse);
			if (v == null)
				goto update_cleanup;
			if (pParse.nested == 0)
				sqlite3VdbeCountChanges(v);
			sqlite3BeginWriteOperation(pParse, 1, iDb);

#if !SQLITE_OMIT_VIRTUALTABLE
			/* Virtual tables must be handled separately */
			if (IsVirtual(pTab))
			{
				updateVirtualTable(pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef,
								   pWhere, onError);
				pWhere = null;
				pTabList = null;
				goto update_cleanup;
			}
#endif

			/* Allocate required registers. */
			regOldRowid = regNewRowid = ++pParse.nMem;
			if (pTrigger != null || hasFK)
			{
				regOld = pParse.nMem + 1;
				pParse.nMem += pTab.nCol;
			}
			if (chngRowid || pTrigger != null || hasFK)
			{
				regNewRowid = ++pParse.nMem;
			}
			regNew = pParse.nMem + 1;
			pParse.nMem += pTab.nCol;

			/* Start the view context. */
			if (isView)
			{
				sqlite3AuthContextPush(pParse, sContext, pTab.zName);
			}

			/* If we are trying to update a view, realize that view into
			** a ephemeral table.
			*/
#if !(SQLITE_OMIT_VIEW) && !(SQLITE_OMIT_TRIGGER)
			if (isView)
			{
				sqlite3MaterializeView(pParse, pTab, pWhere, iCur);
			}
#endif

			/* Resolve the column names in all the expressions in the
** WHERE clause.
*/
			if (sqlite3ResolveExprNames(sNC, ref pWhere) != 0)
			{
				goto update_cleanup;
			}

			/* Begin the database scan
			*/
			sqlite3VdbeAddOp2(v, OP_Null, 0, regOldRowid);
			ExprList NullOrderby = null;
			pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, ref NullOrderby, WHERE_ONEPASS_DESIRED);
			if (pWInfo == null)
				goto update_cleanup;
			okOnePass = pWInfo.okOnePass != 0;

			/* Remember the rowid of every item to be updated.
			*/
			sqlite3VdbeAddOp2(v, OP_Rowid, iCur, regOldRowid);
			if (!okOnePass)
			{
				regRowSet = ++pParse.nMem;
				sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, regOldRowid);
			}

			/* End the database scan loop.
			*/
			sqlite3WhereEnd(pWInfo);

			/* Initialize the count of updated rows
			*/
			if ((db.flags & SQLITE_CountRows) != 0 && null == pParse.pTriggerTab)
			{
				regRowCount = ++pParse.nMem;
				sqlite3VdbeAddOp2(v, OP_Integer, 0, regRowCount);
			}

			if (!isView)
			{
				/*
				** Open every index that needs updating.  Note that if any
				** index could potentially invoke a REPLACE conflict resolution
				** action, then we need to open all indices because we might need
				** to be deleting some records.
				*/
				if (!okOnePass)
					sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
				if (onError == OE_Replace)
				{
					openAll = true;
				}
				else
				{
					openAll = false;
					for (pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext)
					{
						if (pIdx.onError == OE_Replace)
						{
							openAll = true;
							break;
						}
					}
				}
				for (i = 0, pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext, i++)
				{
					if (openAll || aRegIdx[i] > 0)
					{
						KeyInfo pKey = sqlite3IndexKeyinfo(pParse, pIdx);
						sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur + i + 1, pIdx.tnum, iDb,
						pKey, P4_KEYINFO_HANDOFF);
						Debug.Assert(pParse.nTab > iCur + i + 1);
					}
				}
			}

			/* Top of the update loop */
			if (okOnePass)
			{
				int a1 = sqlite3VdbeAddOp1(v, OP_NotNull, regOldRowid);
				addr = sqlite3VdbeAddOp0(v, OP_Goto);
				sqlite3VdbeJumpHere(v, a1);
			}
			else
			{
				addr = sqlite3VdbeAddOp3(v, OP_RowSetRead, regRowSet, 0, regOldRowid);
			}

			/* Make cursor iCur point to the record that is being updated. If
			** this record does not exist for some reason (deleted by a trigger,
			** for example, then jump to the next iteration of the RowSet loop.  */
			sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);

			/* If the record number will change, set register regNewRowid to
			** contain the new value. If the record number is not being modified,
			** then regNewRowid is the same register as regOldRowid, which is
			** already populated.  */
			Debug.Assert(chngRowid || pTrigger != null || hasFK || regOldRowid == regNewRowid);
			if (chngRowid)
			{
				sqlite3ExprCode(pParse, pRowidExpr, regNewRowid);
				sqlite3VdbeAddOp1(v, OP_MustBeInt, regNewRowid);
			}

			/* If there are triggers on this table, populate an array of registers 
			** with the required old.* column data.  */
			if (hasFK || pTrigger != null)
			{
				u32 oldmask = (hasFK ? sqlite3FkOldmask(pParse, pTab) : 0);
				oldmask |= sqlite3TriggerColmask(pParse,
					pTrigger, pChanges, 0, TRIGGER_BEFORE | TRIGGER_AFTER, pTab, onError
				);
				for (i = 0; i < pTab.nCol; i++)
				{
					if (aXRef[i] < 0 || oldmask == 0xffffffff || (i < 32 && 0 != (oldmask & (1 << i))))
					{
						sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOld + i);
					}
					else
					{
						sqlite3VdbeAddOp2(v, OP_Null, 0, regOld + i);
					}
				}
				if (chngRowid == false)
				{
					sqlite3VdbeAddOp2(v, OP_Copy, regOldRowid, regNewRowid);
				}
			}

			/* Populate the array of registers beginning at regNew with the new
			** row data. This array is used to check constaints, create the new
			** table and index records, and as the values for any new.* references
			** made by triggers.
			**
			** If there are one or more BEFORE triggers, then do not populate the
			** registers associated with columns that are (a) not modified by
			** this UPDATE statement and (b) not accessed by new.* references. The
			** values for registers not modified by the UPDATE must be reloaded from 
			** the database after the BEFORE triggers are fired anyway (as the trigger 
			** may have modified them). So not loading those that are not going to
			** be used eliminates some redundant opcodes.
			*/
			newmask = (int)sqlite3TriggerColmask(
				pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
			);
			for (i = 0; i < pTab.nCol; i++)
			{
				if (i == pTab.iPKey)
				{
					sqlite3VdbeAddOp2(v, OP_Null, 0, regNew + i);
				}
				else
				{
					j = aXRef[i];
					if (j >= 0)
					{
						sqlite3ExprCode(pParse, pChanges.a[j].pExpr, regNew + i);
					}
					else if (0 == (tmask & TRIGGER_BEFORE) || i > 31 || (newmask & (1 << i)) != 0)
					{
						/* This branch loads the value of a column that will not be changed 
						** into a register. This is done if there are no BEFORE triggers, or
						** if there are one or more BEFORE triggers that use this value via
						** a new.* reference in a trigger program.
						*/
						testcase(i == 31);
						testcase(i == 32);
						sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew + i);
						sqlite3ColumnDefault(v, pTab, i, regNew + i);
					}
				}
			}

			/* Fire any BEFORE UPDATE triggers. This happens before constraints are
			** verified. One could argue that this is wrong.
			*/
			if ((tmask & TRIGGER_BEFORE) != 0)
			{
				sqlite3VdbeAddOp2(v, OP_Affinity, regNew, pTab.nCol);
				sqlite3TableAffinityStr(v, pTab);
				sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
					TRIGGER_BEFORE, pTab, regOldRowid, onError, addr);

				/* The row-trigger may have deleted the row being updated. In this
				** case, jump to the next row. No updates or AFTER triggers are 
				** required. This behaviour - what happens when the row being updated
				** is deleted or renamed by a BEFORE trigger - is left undefined in the
				** documentation.
				*/
				sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, regOldRowid);

				/* If it did not delete it, the row-trigger may still have modified 
				** some of the columns of the row being updated. Load the values for 
				** all columns not modified by the update statement into their 
				** registers in case this has happened.
				*/
				for (i = 0; i < pTab.nCol; i++)
				{
					if (aXRef[i] < 0 && i != pTab.iPKey)
					{
						sqlite3VdbeAddOp3(v, OP_Column, iCur, i, regNew + i);
						sqlite3ColumnDefault(v, pTab, i, regNew + i);
					}
				}
			}

			if (!isView)
			{
				int j1;                       /* Address of jump instruction */

				/* Do constraint checks. */
				int iDummy;
				sqlite3GenerateConstraintChecks(pParse, pTab, iCur, regNewRowid,
					  aRegIdx, (chngRowid ? regOldRowid : 0), true, onError, addr, out iDummy);

				/* Do FK constraint checks. */
				if (hasFK)
				{
					sqlite3FkCheck(pParse, pTab, regOldRowid, 0);
				}

				/* Delete the index entries associated with the current record.  */
				j1 = sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, regOldRowid);
				sqlite3GenerateRowIndexDelete(pParse, pTab, iCur, aRegIdx);

				/* If changing the record number, delete the old record.  */
				if (hasFK || chngRowid)
				{
					sqlite3VdbeAddOp2(v, OP_Delete, iCur, 0);
				}
				sqlite3VdbeJumpHere(v, j1);

				if (hasFK)
				{
					sqlite3FkCheck(pParse, pTab, 0, regNewRowid);
				}

				/* Insert the new index entries and the new record. */
				sqlite3CompleteInsertion(pParse, pTab, iCur, regNewRowid, aRegIdx, true, false, false);

				/* Do any ON CASCADE, SET NULL or SET DEFAULT operations required to
				** handle rows (possibly in other tables) that refer via a foreign key
				** to the row just updated. */
				if (hasFK)
				{
					sqlite3FkActions(pParse, pTab, pChanges, regOldRowid);
				}
			}

			/* Increment the row counter 
			*/
			if ((db.flags & SQLITE_CountRows) != 0 && null == pParse.pTriggerTab)
			{
				sqlite3VdbeAddOp2(v, OP_AddImm, regRowCount, 1);
			}

			sqlite3CodeRowTrigger(pParse, pTrigger, TK_UPDATE, pChanges,
				TRIGGER_AFTER, pTab, regOldRowid, onError, addr);

			/* Repeat the above with the next record to be updated, until
			** all record selected by the WHERE clause have been updated.
			*/
			sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
			sqlite3VdbeJumpHere(v, addr);

			/* Close all tables */
			for (i = 0, pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext, i++)
			{
				if (openAll || aRegIdx[i] > 0)
				{
					sqlite3VdbeAddOp2(v, OP_Close, iCur + i + 1, 0);
				}
			}
			sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);

			/* Update the sqlite_sequence table by storing the content of the
			** maximum rowid counter values recorded while inserting into
			** autoincrement tables.
			*/
			if (pParse.nested == 0 && pParse.pTriggerTab == null)
			{
				sqlite3AutoincrementEnd(pParse);
			}

			/*
			** Return the number of rows that were changed. If this routine is 
			** generating code because of a call to sqlite3NestedParse(), do not
			** invoke the callback function.
			*/
			if ((db.flags & SQLITE_CountRows) != 0 && null == pParse.pTriggerTab && 0 == pParse.nested)
			{
				sqlite3VdbeAddOp2(v, OP_ResultRow, regRowCount, 1);
				sqlite3VdbeSetNumCols(v, 1);
				sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC);
			}

		update_cleanup:
#if !SQLITE_OMIT_AUTHORIZATION
sqlite3AuthContextPop(sContext);
#endif
			sqlite3DbFree(db, ref aRegIdx);
			sqlite3DbFree(db, ref aXRef);
			sqlite3SrcListDelete(db, ref pTabList);
			sqlite3ExprListDelete(db, ref pChanges);
			sqlite3ExprDelete(db, ref pWhere);
			return;
		}
 protected virtual void RenderName(HtmlTextWriter output, string id, NameContext context)
 {
     Assert.ArgumentNotNull(output, "output");
     Assert.ArgumentNotNullOrEmpty(id, "id");
     if (!context.Editable)
     {
         output.Write("<span class='header-title'>");
         output.Write(context.Name);
         output.Write("</span>");
     }
     else
     {
         output.Write("<a href='#' class='header-title'>");
         output.Write(StringUtil.EscapeQuote(context.Name));
         output.Write("</a>");
         string str = "onkeydown='javascript:return Sitecore.CollapsiblePanel.editNameChanging(this, event);'";
         string str2 = string.IsNullOrEmpty(context.OnNameChanging)
                       	? string.Empty
                       	: ("onkeyup=\"" + context.OnNameChanging + "\"");
         string str3 = string.IsNullOrEmpty(context.OnNameChanged)
                       	? string.Empty
                       	: ("onchange=\"" + context.OnNameChanged + "\"");
         output.Write(
             "<input type='text' {0} {1} id='{2}_name' name='{2}_name' data-meta-id='{2}' data-validation-msg=\"{3}\" style='display:none' class='header-title-edit' value=\"{4}\" {5} />",
             new object[]
                 {str2, str3, id, Translate.Text("The name cannot be blank."), StringUtil.EscapeQuote(context.Name), str});
     }
 }
Esempio n. 50
0
/*
** This procedure generates VDBE code for a single invocation of either the
** sqlite_detach() or sqlite_attach() SQL user functions.
*/
static void codeAttach(
Parse pParse,       /* The parser context */
int type,           /* Either SQLITE_ATTACH or SQLITE_DETACH */
FuncDef pFunc,      /* FuncDef wrapper for detachFunc() or attachFunc() */
Expr pAuthArg,      /* Expression to pass to authorization callback */
Expr pFilename,     /* Name of database file */
Expr pDbname,       /* Name of the database to use internally */
Expr pKey           /* Database key for encryption extension */
)
{
  int rc;
  NameContext sName;
  Vdbe v;
  sqlite3 db = pParse.db;
  int regArgs;

  sName = new NameContext();// memset( &sName, 0, sizeof(NameContext));
  sName.pParse = pParse;

  if (
  SQLITE_OK != ( rc = resolveAttachExpr( sName, pFilename ) ) ||
  SQLITE_OK != ( rc = resolveAttachExpr( sName, pDbname ) ) ||
  SQLITE_OK != ( rc = resolveAttachExpr( sName, pKey ) )
  )
  {
    pParse.nErr++;
    goto attach_end;
  }

#if !SQLITE_OMIT_AUTHORIZATION
if( pAuthArg ){
char *zAuthArg;
if( pAuthArg->op==TK_STRING ){
  zAuthArg = pAuthArg->u.zToken;
}else{
  zAuthArg = 0;
}
rc = sqlite3AuthCheck(pParse, type, zAuthArg, 0, 0);
if(rc!=SQLITE_OK ){
goto attach_end;
}
}
#endif //* SQLITE_OMIT_AUTHORIZATION */

  v = sqlite3GetVdbe( pParse );
  regArgs = sqlite3GetTempRange( pParse, 4 );
  sqlite3ExprCode( pParse, pFilename, regArgs );
  sqlite3ExprCode( pParse, pDbname, regArgs + 1 );
  sqlite3ExprCode( pParse, pKey, regArgs + 2 );

  Debug.Assert( v != null /*|| db.mallocFailed != 0 */ );
  if ( v != null )
  {
    sqlite3VdbeAddOp3( v, OP_Function, 0, regArgs + 3 - pFunc.nArg, regArgs + 3 );
    Debug.Assert( pFunc.nArg == -1 || ( pFunc.nArg & 0xff ) == pFunc.nArg );
    sqlite3VdbeChangeP5( v, (u8)( pFunc.nArg ) );
    sqlite3VdbeChangeP4( v, -1, pFunc, P4_FUNCDEF );

    /* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
    ** statement only). For DETACH, set it to false (expire all existing
    ** statements).
    */
    sqlite3VdbeAddOp1( v, OP_Expire, ( type == SQLITE_ATTACH ) ? 1 : 0 );
  }

attach_end:
  sqlite3ExprDelete( db, ref pFilename );
  sqlite3ExprDelete( db, ref pDbname );
  sqlite3ExprDelete( db, ref pKey );
}
Esempio n. 51
0
    /*
    ** Generate code that will tell the VDBE the declaration types of columns
    ** in the result set.
    */
    static void generateColumnTypes(
    Parse pParse,      /* Parser context */
    SrcList pTabList,  /* List of tables */
    ExprList pEList    /* Expressions defining the result set */
    )
    {
#if !SQLITE_OMIT_DECLTYPE
      Vdbe v = pParse.pVdbe;
      int i;
      NameContext sNC = new NameContext();
      sNC.pSrcList = pTabList;
      sNC.pParse = pParse;
      for ( i = 0; i < pEList.nExpr; i++ )
      {
        Expr p = pEList.a[i].pExpr;
        string zType;
#if SQLITE_ENABLE_COLUMN_METADATA
        string zOrigDb = null;
        string zOrigTab = null;
        string zOrigCol = null;
        zType = columnType( sNC, p, ref zOrigDb, ref zOrigTab, ref zOrigCol );

        /* The vdbe must make its own copy of the column-type and other
        ** column specific strings, in case the schema is reset before this
        ** virtual machine is deleted.
        */
        sqlite3VdbeSetColName( v, i, COLNAME_DATABASE, zOrigDb, SQLITE_TRANSIENT );
        sqlite3VdbeSetColName( v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT );
        sqlite3VdbeSetColName( v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT );
#else
        string sDummy = null;
        zType = columnType( sNC, p, ref sDummy, ref sDummy, ref sDummy );
#endif
        sqlite3VdbeSetColName( v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT );
      }
#endif //* SQLITE_OMIT_DECLTYPE */
    }
Esempio n. 52
0
        static WRC ResolveSelectStep(Walker walker, Select p)
        {
            Debug.Assert(p != null);
            if ((p.SelFlags & SF.Resolved) != 0)
            {
                return(WRC.Prune);
            }
            NameContext outerNC = walker.u.NC;  // Context that contains this SELECT
            Parse       parse   = walker.Parse; // Parsing context
            Context     ctx     = parse.Ctx;    // Database connection

            // Normally sqlite3SelectExpand() will be called first and will have already expanded this SELECT.  However, if this is a subquery within
            // an expression, sqlite3ResolveExprNames() will be called without a prior call to sqlite3SelectExpand().  When that happens, let
            // sqlite3SelectPrep() do all of the processing for this SELECT. sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and
            // this routine in the correct order.
            if ((p.SelFlags & SF.Expanded) == 0)
            {
                p.Prep(parse, outerNC);
                return(parse.Errs != 0 || ctx.MallocFailed ? WRC.Abort : WRC.Prune);
            }

            bool        isCompound = (p.Prior != null); // True if p is a compound select
            int         compounds  = 0;                 // Number of compound terms processed so far
            Select      leftmost   = p;                 // Left-most of SELECT of a compound
            int         i;
            NameContext nc;                             // Name context of this SELECT

            while (p != null)
            {
                Debug.Assert((p.SelFlags & SF.Expanded) != 0);
                Debug.Assert((p.SelFlags & SF.Resolved) == 0);
                p.SelFlags |= SF.Resolved;

                // Resolve the expressions in the LIMIT and OFFSET clauses. These are not allowed to refer to any names, so pass an empty NameContext.
                nc       = new NameContext(); //: _memset(&nc, 0, sizeof(nc));
                nc.Parse = parse;
                if (Walker.ResolveExprNames(nc, ref p.Limit) || Walker.ResolveExprNames(nc, ref p.Offset))
                {
                    return(WRC.Abort);
                }

                // Recursively resolve names in all subqueries
                SrcList.SrcListItem item;
                for (i = 0; i < p.Src.Srcs; i++)
                {
                    item = p.Src.Ids[i];
                    if (item.Select != null)
                    {
                        NameContext nc2;              // Used to iterate name contexts
                        int         refs         = 0; // Refcount for pOuterNC and outer contexts
                        string      savedContext = parse.AuthContext;

                        // Count the total number of references to pOuterNC and all of its parent contexts. After resolving references to expressions in
                        // pItem->pSelect, check if this value has changed. If so, then SELECT statement pItem->pSelect must be correlated. Set the
                        // pItem->isCorrelated flag if this is the case.
                        for (nc2 = outerNC; nc2 != null; nc2 = nc2.Next)
                        {
                            refs += nc2.Refs;
                        }

                        if (item.Name != null)
                        {
                            parse.AuthContext = item.Name;
                        }
                        Walker.ResolveSelectNames(parse, item.Select, outerNC);
                        parse.AuthContext = savedContext;
                        if (parse.Errs != 0 || ctx.MallocFailed)
                        {
                            return(WRC.Abort);
                        }

                        for (nc2 = outerNC; nc2 != null; nc2 = nc2.Next)
                        {
                            refs -= nc2.Refs;
                        }
                        Debug.Assert(!item.IsCorrelated && refs <= 0);
                        item.IsCorrelated = (refs != 0);
                    }
                }

                // Set up the local name-context to pass to sqlite3ResolveExprNames() to resolve the result-set expression list.
                nc.NCFlags = NC.AllowAgg;
                nc.SrcList = p.Src;
                nc.Next    = outerNC;

                // Resolve names in the result set.
                ExprList list = p.EList; // Result set expression list
                Debug.Assert(list != null);
                for (i = 0; i < list.Exprs; i++)
                {
                    Expr expr = list.Ids[i].Expr;
                    if (Walker.ResolveExprNames(nc, ref expr))
                    {
                        return(WRC.Abort);
                    }
                }

                // If there are no aggregate functions in the result-set, and no GROUP BY expression, do not allow aggregates in any of the other expressions.
                Debug.Assert((p.SelFlags & SF.Aggregate) == 0);
                ExprList groupBy = p.GroupBy; // The GROUP BY clause
                if (groupBy != null || (nc.NCFlags & NC.HasAgg) != 0)
                {
                    p.SelFlags |= SF.Aggregate;
                }
                else
                {
                    nc.NCFlags &= ~NC.AllowAgg;
                }

                // If a HAVING clause is present, then there must be a GROUP BY clause.
                if (p.Having != null && groupBy == null)
                {
                    parse.ErrorMsg("a GROUP BY clause is required before HAVING");
                    return(WRC.Abort);
                }

                // Add the expression list to the name-context before parsing the other expressions in the SELECT statement. This is so that
                // expressions in the WHERE clause (etc.) can refer to expressions by aliases in the result set.
                //
                // Minor point: If this is the case, then the expression will be re-evaluated for each reference to it.
                nc.EList = p.EList;
                if (Walker.ResolveExprNames(nc, ref p.Where) || Walker.ResolveExprNames(nc, ref p.Having))
                {
                    return(WRC.Abort);
                }

                // The ORDER BY and GROUP BY clauses may not refer to terms in outer queries
                nc.Next     = null;
                nc.NCFlags |= NC.AllowAgg;

                // Process the ORDER BY clause for singleton SELECT statements. The ORDER BY clause for compounds SELECT statements is handled
                // below, after all of the result-sets for all of the elements of the compound have been resolved.
                if (!isCompound && Walker.ResolveOrderGroupBy(nc, p, p.OrderBy, "ORDER"))
                {
                    return(WRC.Abort);
                }
                if (ctx.MallocFailed)
                {
                    return(WRC.Abort);
                }

                // Resolve the GROUP BY clause.  At the same time, make sure the GROUP BY clause does not contain aggregate functions.
                if (groupBy != null)
                {
                    if (Walker.ResolveOrderGroupBy(nc, p, groupBy, "GROUP") || ctx.MallocFailed)
                    {
                        return(WRC.Abort);
                    }
                    ExprList.ExprListItem item2;
                    for (i = 0; i < groupBy.Exprs; i++)
                    {
                        item2 = groupBy.Ids[i];
                        if (E.ExprHasProperty(item2.Expr, EP.Agg))
                        {
                            parse.ErrorMsg("aggregate functions are not allowed in the GROUP BY clause");
                            return(WRC.Abort);
                        }
                    }
                }

                // Advance to the next term of the compound
                p = p.Prior;
                compounds++;
            }

            // Resolve the ORDER BY on a compound SELECT after all terms of the compound have been resolved.
            return(isCompound && ResolveCompoundOrderBy(parse, leftmost) != 0 ? WRC.Abort : WRC.Prune);
        }
Esempio n. 53
0
 /*
 ** This routine sets of a SELECT statement for processing.  The
 ** following is accomplished:
 **
 **     *  VDBE VdbeCursor numbers are assigned to all FROM-clause terms.
 **     *  Ephemeral Table objects are created for all FROM-clause subqueries.
 **     *  ON and USING clauses are shifted into WHERE statements
 **     *  Wildcards "*" and "TABLE.*" in result sets are expanded.
 **     *  Identifiers in expression are matched to tables.
 **
 ** This routine acts recursively on all subqueries within the SELECT.
 */
 static void sqlite3SelectPrep(
 Parse pParse,         /* The parser context */
 Select p,             /* The SELECT statement being coded. */
 NameContext pOuterNC  /* Name context for container */
 )
 {
   if ( NEVER( p == null ) )
     return;
   ////sqlite3 db = pParse.db;
   if ( ( p.selFlags & SF_HasTypeInfo ) != 0 )
     return;
   sqlite3SelectExpand( pParse, p );
   if ( pParse.nErr != 0 /*|| db.mallocFailed != 0 */ )
     return;
   sqlite3ResolveSelectNames( pParse, p, pOuterNC );
   if ( pParse.nErr != 0 /*|| db.mallocFailed != 0 */ )
     return;
   sqlite3SelectAddTypeInfo( pParse, p );
 }
Esempio n. 54
0
    static void sqlite3Insert(
    Parse pParse,        /* Parser context */
    SrcList pTabList,    /* Name of table into which we are inserting */
    ExprList pList,      /* List of values to be inserted */
    Select pSelect,      /* A SELECT statement to use as the data source */
    IdList pColumn,      /* Column names corresponding to IDLIST. */
    int onError        /* How to handle constraint errors */
    )
    {
      sqlite3 db;           /* The main database structure */
      Table pTab;           /* The table to insert into.  aka TABLE */
      string zTab;          /* Name of the table into which we are inserting */
      string zDb;           /* Name of the database holding this table */
      int i = 0;
      int j = 0;
      int idx = 0;            /* Loop counters */
      Vdbe v;               /* Generate code into this virtual machine */
      Index pIdx;           /* For looping over indices of the table */
      int nColumn;          /* Number of columns in the data */
      int nHidden = 0;      /* Number of hidden columns if TABLE is virtual */
      int baseCur = 0;      /* VDBE VdbeCursor number for pTab */
      int keyColumn = -1;   /* Column that is the INTEGER PRIMARY KEY */
      int endOfLoop = 0;      /* Label for the end of the insertion loop */
      bool useTempTable = false; /* Store SELECT results in intermediate table */
      int srcTab = 0;       /* Data comes from this temporary cursor if >=0 */
      int addrInsTop = 0;   /* Jump to label "D" */
      int addrCont = 0;     /* Top of insert loop. Label "C" in templates 3 and 4 */
      int addrSelect = 0;   /* Address of coroutine that implements the SELECT */
      SelectDest dest;      /* Destination for SELECT on rhs of INSERT */
      int iDb;              /* Index of database holding TABLE */
      Db pDb;               /* The database containing table being inserted into */
      bool appendFlag = false;   /* True if the insert is likely to be an append */

      /* Register allocations */
      int regFromSelect = 0;  /* Base register for data coming from SELECT */
      int regAutoinc = 0;   /* Register holding the AUTOINCREMENT counter */
      int regRowCount = 0;  /* Memory cell used for the row counter */
      int regIns;           /* Block of regs holding rowid+data being inserted */
      int regRowid;         /* registers holding insert rowid */
      int regData;          /* register holding first column to insert */
      int regEof = 0;       /* Register recording end of SELECT data */
      int[] aRegIdx = null; /* One register allocated to each index */


#if !SQLITE_OMIT_TRIGGER
      bool isView = false;        /* True if attempting to insert into a view */
      Trigger pTrigger;           /* List of triggers on pTab, if required */
      int tmask = 0;              /* Mask of trigger times */
#endif

      db = pParse.db;
      dest = new SelectDest();// memset( &dest, 0, sizeof( dest ) );

      if ( pParse.nErr != 0 /*|| db.mallocFailed != 0 */ )
      {
        goto insert_cleanup;
      }

      /* Locate the table into which we will be inserting new information.
      */
      Debug.Assert( pTabList.nSrc == 1 );
      zTab = pTabList.a[0].zName;
      if ( NEVER( zTab == null ) )
        goto insert_cleanup;
      pTab = sqlite3SrcListLookup( pParse, pTabList );
      if ( pTab == null )
      {
        goto insert_cleanup;
      }
      iDb = sqlite3SchemaToIndex( db, pTab.pSchema );
      Debug.Assert( iDb < db.nDb );
      pDb = db.aDb[iDb];
      zDb = pDb.zName;
#if NO_SQLITE_OMIT_AUTHORIZATION //#if !SQLITE_OMIT_AUTHORIZATION
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab.zName, 0, zDb) ){
goto insert_cleanup;
}
#endif
      /* Figure out if we have any triggers and if the table being
** inserted into is a view
*/
#if !SQLITE_OMIT_TRIGGER
      pTrigger = sqlite3TriggersExist( pParse, pTab, TK_INSERT, null, out tmask );
      isView = pTab.pSelect != null;
#else
      Trigger pTrigger = null;  //# define pTrigger 0
      int tmask = 0;            //# define tmask 0
      bool isView = false;
#endif
#if  SQLITE_OMIT_VIEW
//# undef isView
isView = false;
#endif
#if !SQLITE_OMIT_TRIGGER
      Debug.Assert( ( pTrigger != null && tmask != 0 ) || ( pTrigger == null && tmask == 0 ) );
#endif

#if !SQLITE_OMIT_VIEW
      /* If pTab is really a view, make sure it has been initialized.
      ** ViewGetColumnNames() is a no-op if pTab is not a view (or virtual
      ** module table).
      */
      if ( sqlite3ViewGetColumnNames( pParse, pTab ) != -0 )
      {
        goto insert_cleanup;
      }
#endif

      /* Ensure that:
      *  (a) the table is not read-only, 
      *  (b) that if it is a view then ON INSERT triggers exist
      */
      if ( sqlite3IsReadOnly( pParse, pTab, tmask ) )
      {
        goto insert_cleanup;
      }

      /* Allocate a VDBE
      */
      v = sqlite3GetVdbe( pParse );
      if ( v == null )
        goto insert_cleanup;
      if ( pParse.nested == 0 )
        sqlite3VdbeCountChanges( v );
      sqlite3BeginWriteOperation( pParse, ( pSelect != null || pTrigger != null ) ? 1 : 0, iDb );

#if !SQLITE_OMIT_XFER_OPT
      /* If the statement is of the form
**
**       INSERT INTO <table1> SELECT * FROM <table2>;
**
** Then special optimizations can be applied that make the transfer
** very fast and which reduce fragmentation of indices.
**
** This is the 2nd template.
*/
      if ( pColumn == null && xferOptimization( pParse, pTab, pSelect, onError, iDb ) != 0 )
      {
        Debug.Assert( null == pTrigger );
        Debug.Assert( pList == null );
        goto insert_end;
      }
#endif // * SQLITE_OMIT_XFER_OPT */

      /* If this is an AUTOINCREMENT table, look up the sequence number in the
** sqlite_sequence table and store it in memory cell regAutoinc.
*/
      regAutoinc = autoIncBegin( pParse, iDb, pTab );

      /* Figure out how many columns of data are supplied.  If the data
      ** is coming from a SELECT statement, then generate a co-routine that
      ** produces a single row of the SELECT on each invocation.  The
      ** co-routine is the common header to the 3rd and 4th templates.
      */
      if ( pSelect != null )
      {
        /* Data is coming from a SELECT.  Generate code to implement that SELECT
        ** as a co-routine.  The code is common to both the 3rd and 4th
        ** templates:
        **
        **         EOF <- 0
        **         X <- A
        **         goto B
        **      A: setup for the SELECT
        **         loop over the tables in the SELECT
        **           load value into register R..R+n
        **           yield X
        **         end loop
        **         cleanup after the SELECT
        **         EOF <- 1
        **         yield X
        **         halt-error
        **
        ** On each invocation of the co-routine, it puts a single row of the
        ** SELECT result into registers dest.iMem...dest.iMem+dest.nMem-1.
        ** (These output registers are allocated by sqlite3Select().)  When
        ** the SELECT completes, it sets the EOF flag stored in regEof.
        */
        int rc = 0, j1;

        regEof = ++pParse.nMem;
        sqlite3VdbeAddOp2( v, OP_Integer, 0, regEof );      /* EOF <- 0 */
#if SQLITE_DEBUG
        VdbeComment( v, "SELECT eof flag" );
#endif
        sqlite3SelectDestInit( dest, SRT_Coroutine, ++pParse.nMem );
        addrSelect = sqlite3VdbeCurrentAddr( v ) + 2;
        sqlite3VdbeAddOp2( v, OP_Integer, addrSelect - 1, dest.iParm );
        j1 = sqlite3VdbeAddOp2( v, OP_Goto, 0, 0 );
#if SQLITE_DEBUG
        VdbeComment( v, "Jump over SELECT coroutine" );
#endif
        /* Resolve the expressions in the SELECT statement and execute it. */
        rc = sqlite3Select( pParse, pSelect, ref dest );
        Debug.Assert( pParse.nErr == 0 || rc != 0 );
        if ( rc != 0 || NEVER( pParse.nErr != 0 ) /*|| db.mallocFailed != 0 */ )
        {
          goto insert_cleanup;
        }
        sqlite3VdbeAddOp2( v, OP_Integer, 1, regEof );         /* EOF <- 1 */
        sqlite3VdbeAddOp1( v, OP_Yield, dest.iParm );   /* yield X */
        sqlite3VdbeAddOp2( v, OP_Halt, SQLITE_INTERNAL, OE_Abort );
#if SQLITE_DEBUG
        VdbeComment( v, "End of SELECT coroutine" );
#endif
        sqlite3VdbeJumpHere( v, j1 );                          /* label B: */

        regFromSelect = dest.iMem;
        Debug.Assert( pSelect.pEList != null );
        nColumn = pSelect.pEList.nExpr;
        Debug.Assert( dest.nMem == nColumn );

        /* Set useTempTable to TRUE if the result of the SELECT statement
        ** should be written into a temporary table (template 4).  Set to
        ** FALSE if each* row of the SELECT can be written directly into
        ** the destination table (template 3).
        **
        ** A temp table must be used if the table being updated is also one
        ** of the tables being read by the SELECT statement.  Also use a
        ** temp table in the case of row triggers.
        */
        if ( pTrigger != null || readsTable( pParse, addrSelect, iDb, pTab ) )
        {
          useTempTable = true;
        }

        if ( useTempTable )
        {
          /* Invoke the coroutine to extract information from the SELECT
          ** and add it to a transient table srcTab.  The code generated
          ** here is from the 4th template:
          **
          **      B: open temp table
          **      L: yield X
          **         if EOF goto M
          **         insert row from R..R+n into temp table
          **         goto L
          **      M: ...
          */
          int regRec;      /* Register to hold packed record */
          int regTempRowid;    /* Register to hold temp table ROWID */
          int addrTop;     /* Label "L" */
          int addrIf;      /* Address of jump to M */

          srcTab = pParse.nTab++;
          regRec = sqlite3GetTempReg( pParse );
          regTempRowid = sqlite3GetTempReg( pParse );
          sqlite3VdbeAddOp2( v, OP_OpenEphemeral, srcTab, nColumn );
          addrTop = sqlite3VdbeAddOp1( v, OP_Yield, dest.iParm );
          addrIf = sqlite3VdbeAddOp1( v, OP_If, regEof );
          sqlite3VdbeAddOp3( v, OP_MakeRecord, regFromSelect, nColumn, regRec );
          sqlite3VdbeAddOp2( v, OP_NewRowid, srcTab, regTempRowid );
          sqlite3VdbeAddOp3( v, OP_Insert, srcTab, regRec, regTempRowid );
          sqlite3VdbeAddOp2( v, OP_Goto, 0, addrTop );
          sqlite3VdbeJumpHere( v, addrIf );
          sqlite3ReleaseTempReg( pParse, regRec );
          sqlite3ReleaseTempReg( pParse, regTempRowid );
        }
      }
      else
      {
        /* This is the case if the data for the INSERT is coming from a VALUES
        ** clause
        */
        NameContext sNC;
        sNC = new NameContext();// memset( &sNC, 0, sNC ).Length;
        sNC.pParse = pParse;
        srcTab = -1;
        Debug.Assert( !useTempTable );
        nColumn = pList != null ? pList.nExpr : 0;
        for ( i = 0; i < nColumn; i++ )
        {
          if ( sqlite3ResolveExprNames( sNC, ref pList.a[i].pExpr ) != 0 )
          {
            goto insert_cleanup;
          }
        }
      }

      /* Make sure the number of columns in the source data matches the number
      ** of columns to be inserted into the table.
      */
      if ( IsVirtual( pTab ) )
      {
        for ( i = 0; i < pTab.nCol; i++ )
        {
          nHidden += ( IsHiddenColumn( pTab.aCol[i] ) ? 1 : 0 );
        }
      }
      if ( pColumn == null && nColumn != 0 && nColumn != ( pTab.nCol - nHidden ) )
      {
        sqlite3ErrorMsg( pParse,
        "table %S has %d columns but %d values were supplied",
        pTabList, 0, pTab.nCol - nHidden, nColumn );
        goto insert_cleanup;
      }
      if ( pColumn != null && nColumn != pColumn.nId )
      {
        sqlite3ErrorMsg( pParse, "%d values for %d columns", nColumn, pColumn.nId );
        goto insert_cleanup;
      }

      /* If the INSERT statement included an IDLIST term, then make sure
      ** all elements of the IDLIST really are columns of the table and
      ** remember the column indices.
      **
      ** If the table has an INTEGER PRIMARY KEY column and that column
      ** is named in the IDLIST, then record in the keyColumn variable
      ** the index into IDLIST of the primary key column.  keyColumn is
      ** the index of the primary key as it appears in IDLIST, not as
      ** is appears in the original table.  (The index of the primary
      ** key in the original table is pTab.iPKey.)
      */
      if ( pColumn != null )
      {
        for ( i = 0; i < pColumn.nId; i++ )
        {
          pColumn.a[i].idx = -1;
        }
        for ( i = 0; i < pColumn.nId; i++ )
        {
          for ( j = 0; j < pTab.nCol; j++ )
          {
            if ( pColumn.a[i].zName.Equals( pTab.aCol[j].zName ,StringComparison.InvariantCultureIgnoreCase )  )
            {
              pColumn.a[i].idx = j;
              if ( j == pTab.iPKey )
              {
                keyColumn = i;
              }
              break;
            }
          }
          if ( j >= pTab.nCol )
          {
            if ( sqlite3IsRowid( pColumn.a[i].zName ) )
            {
              keyColumn = i;
            }
            else
            {
              sqlite3ErrorMsg( pParse, "table %S has no column named %s",
              pTabList, 0, pColumn.a[i].zName );
              pParse.checkSchema = 1;
              goto insert_cleanup;
            }
          }
        }
      }

      /* If there is no IDLIST term but the table has an integer primary
      ** key, the set the keyColumn variable to the primary key column index
      ** in the original table definition.
      */
      if ( pColumn == null && nColumn > 0 )
      {
        keyColumn = pTab.iPKey;
      }

      /* Initialize the count of rows to be inserted
      */
      if ( ( db.flags & SQLITE_CountRows ) != 0 )
      {
        regRowCount = ++pParse.nMem;
        sqlite3VdbeAddOp2( v, OP_Integer, 0, regRowCount );
      }

      /* If this is not a view, open the table and and all indices */
      if ( !isView )
      {
        int nIdx;

        baseCur = pParse.nTab;
        nIdx = sqlite3OpenTableAndIndices( pParse, pTab, baseCur, OP_OpenWrite );
        aRegIdx = new int[nIdx + 1];// sqlite3DbMallocRaw( db, sizeof( int ) * ( nIdx + 1 ) );
        if ( aRegIdx == null )
        {
          goto insert_cleanup;
        }
        for ( i = 0; i < nIdx; i++ )
        {
          aRegIdx[i] = ++pParse.nMem;
        }
      }

      /* This is the top of the main insertion loop */
      if ( useTempTable )
      {
        /* This block codes the top of loop only.  The complete loop is the
        ** following pseudocode (template 4):
        **
        **         rewind temp table
        **      C: loop over rows of intermediate table
        **           transfer values form intermediate table into <table>
        **         end loop
        **      D: ...
        */
        addrInsTop = sqlite3VdbeAddOp1( v, OP_Rewind, srcTab );
        addrCont = sqlite3VdbeCurrentAddr( v );
      }
      else if ( pSelect != null )
      {
        /* This block codes the top of loop only.  The complete loop is the
        ** following pseudocode (template 3):
        **
        **      C: yield X
        **         if EOF goto D
        **         insert the select result into <table> from R..R+n
        **         goto C
        **      D: ...
        */
        addrCont = sqlite3VdbeAddOp1( v, OP_Yield, dest.iParm );
        addrInsTop = sqlite3VdbeAddOp1( v, OP_If, regEof );
      }

      /* Allocate registers for holding the rowid of the new row,
      ** the content of the new row, and the assemblied row record.
      */
      regRowid = regIns = pParse.nMem + 1;
      pParse.nMem += pTab.nCol + 1;
      if ( IsVirtual( pTab ) )
      {
        regRowid++;
        pParse.nMem++;
      }
      regData = regRowid + 1;

      /* Run the BEFORE and INSTEAD OF triggers, if there are any
      */
      endOfLoop = sqlite3VdbeMakeLabel( v );
#if !SQLITE_OMIT_TRIGGER
      if ( ( tmask & TRIGGER_BEFORE ) != 0 )
      {
        int regCols = sqlite3GetTempRange( pParse, pTab.nCol + 1 );

        /* build the NEW.* reference row.  Note that if there is an INTEGER
        ** PRIMARY KEY into which a NULL is being inserted, that NULL will be
        ** translated into a unique ID for the row.  But on a BEFORE trigger,
        ** we do not know what the unique ID will be (because the insert has
        ** not happened yet) so we substitute a rowid of -1
        */
        if ( keyColumn < 0 )
        {
          sqlite3VdbeAddOp2( v, OP_Integer, -1, regCols );
        }
        else
        {
          int j1;
          if ( useTempTable )
          {
            sqlite3VdbeAddOp3( v, OP_Column, srcTab, keyColumn, regCols );
          }
          else
          {
            Debug.Assert( pSelect == null );  /* Otherwise useTempTable is true */
            sqlite3ExprCode( pParse, pList.a[keyColumn].pExpr, regCols );
          }
          j1 = sqlite3VdbeAddOp1( v, OP_NotNull, regCols );
          sqlite3VdbeAddOp2( v, OP_Integer, -1, regCols );
          sqlite3VdbeJumpHere( v, j1 );
          sqlite3VdbeAddOp1( v, OP_MustBeInt, regCols );
        }
        /* Cannot have triggers on a virtual table. If it were possible,
        ** this block would have to account for hidden column.
        */
        Debug.Assert( !IsVirtual( pTab ) );
        /* Create the new column data
        */
        for ( i = 0; i < pTab.nCol; i++ )
        {
          if ( pColumn == null )
          {
            j = i;
          }
          else
          {
            for ( j = 0; j < pColumn.nId; j++ )
            {
              if ( pColumn.a[j].idx == i )
                break;
            }
          }
          if ( ( !useTempTable && null == pList ) || ( pColumn != null && j >= pColumn.nId ) )
          {
            sqlite3ExprCode( pParse, pTab.aCol[i].pDflt, regCols + i + 1 );
          }
          else if ( useTempTable )
          {
            sqlite3VdbeAddOp3( v, OP_Column, srcTab, j, regCols + i + 1 );
          }
          else
          {
            Debug.Assert( pSelect == null ); /* Otherwise useTempTable is true */
            sqlite3ExprCodeAndCache( pParse, pList.a[j].pExpr, regCols + i + 1 );
          }
        }

        /* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
        ** do not attempt any conversions before assembling the record.
        ** If this is a real table, attempt conversions as required by the
        ** table column affinities.
        */
        if ( !isView )
        {
          sqlite3VdbeAddOp2( v, OP_Affinity, regCols + 1, pTab.nCol );
          sqlite3TableAffinityStr( v, pTab );
        }

        /* Fire BEFORE or INSTEAD OF triggers */
        sqlite3CodeRowTrigger( pParse, pTrigger, TK_INSERT, null, TRIGGER_BEFORE,
            pTab, regCols - pTab.nCol - 1, onError, endOfLoop );

        sqlite3ReleaseTempRange( pParse, regCols, pTab.nCol + 1 );
      }
#endif

      /* Push the record number for the new entry onto the stack.  The
** record number is a randomly generate integer created by NewRowid
** except when the table has an INTEGER PRIMARY KEY column, in which
** case the record number is the same as that column.
*/
      if ( !isView )
      {
        if ( IsVirtual( pTab ) )
        {
          /* The row that the VUpdate opcode will delete: none */
          sqlite3VdbeAddOp2( v, OP_Null, 0, regIns );
        }
        if ( keyColumn >= 0 )
        {
          if ( useTempTable )
          {
            sqlite3VdbeAddOp3( v, OP_Column, srcTab, keyColumn, regRowid );
          }
          else if ( pSelect != null )
          {
            sqlite3VdbeAddOp2( v, OP_SCopy, regFromSelect + keyColumn, regRowid );
          }
          else
          {
            VdbeOp pOp;
            sqlite3ExprCode( pParse, pList.a[keyColumn].pExpr, regRowid );
            pOp = sqlite3VdbeGetOp( v, -1 );
            if ( ALWAYS( pOp != null ) && pOp.opcode == OP_Null && !IsVirtual( pTab ) )
            {
              appendFlag = true;
              pOp.opcode = OP_NewRowid;
              pOp.p1 = baseCur;
              pOp.p2 = regRowid;
              pOp.p3 = regAutoinc;
            }
          }
          /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
          ** to generate a unique primary key value.
          */
          if ( !appendFlag )
          {
            int j1;
            if ( !IsVirtual( pTab ) )
            {
              j1 = sqlite3VdbeAddOp1( v, OP_NotNull, regRowid );
              sqlite3VdbeAddOp3( v, OP_NewRowid, baseCur, regRowid, regAutoinc );
              sqlite3VdbeJumpHere( v, j1 );
            }
            else
            {
              j1 = sqlite3VdbeCurrentAddr( v );
              sqlite3VdbeAddOp2( v, OP_IsNull, regRowid, j1 + 2 );
            }
            sqlite3VdbeAddOp1( v, OP_MustBeInt, regRowid );
          }
        }
        else if ( IsVirtual( pTab ) )
        {
          sqlite3VdbeAddOp2( v, OP_Null, 0, regRowid );
        }
        else
        {
          sqlite3VdbeAddOp3( v, OP_NewRowid, baseCur, regRowid, regAutoinc );
          appendFlag = true;
        }
        autoIncStep( pParse, regAutoinc, regRowid );

        /* Push onto the stack, data for all columns of the new entry, beginning
        ** with the first column.
        */
        nHidden = 0;
        for ( i = 0; i < pTab.nCol; i++ )
        {
          int iRegStore = regRowid + 1 + i;
          if ( i == pTab.iPKey )
          {
            /* The value of the INTEGER PRIMARY KEY column is always a NULL.
            ** Whenever this column is read, the record number will be substituted
            ** in its place.  So will fill this column with a NULL to avoid
            ** taking up data space with information that will never be used. */
            sqlite3VdbeAddOp2( v, OP_Null, 0, iRegStore );
            continue;
          }
          if ( pColumn == null )
          {
            if ( IsHiddenColumn( pTab.aCol[i] ) )
            {
              Debug.Assert( IsVirtual( pTab ) );
              j = -1;
              nHidden++;
            }
            else
            {
              j = i - nHidden;
            }
          }
          else
          {
            for ( j = 0; j < pColumn.nId; j++ )
            {
              if ( pColumn.a[j].idx == i )
                break;
            }
          }
          if ( j < 0 || nColumn == 0 || ( pColumn != null && j >= pColumn.nId ) )
          {
            sqlite3ExprCode( pParse, pTab.aCol[i].pDflt, iRegStore );
          }
          else if ( useTempTable )
          {
            sqlite3VdbeAddOp3( v, OP_Column, srcTab, j, iRegStore );
          }
          else if ( pSelect != null )
          {
            sqlite3VdbeAddOp2( v, OP_SCopy, regFromSelect + j, iRegStore );
          }
          else
          {
            sqlite3ExprCode( pParse, pList.a[j].pExpr, iRegStore );
          }
        }

        /* Generate code to check constraints and generate index keys and
        ** do the insertion.
        */
#if !SQLITE_OMIT_VIRTUALTABLE
        if ( IsVirtual( pTab ) )
        {
          VTable pVTab = sqlite3GetVTable( db, pTab );
          sqlite3VtabMakeWritable( pParse, pTab );
          sqlite3VdbeAddOp4( v, OP_VUpdate, 1, pTab.nCol + 2, regIns, pVTab, P4_VTAB );
          sqlite3VdbeChangeP5( v, (byte)( onError == OE_Default ? OE_Abort : onError ) );
          sqlite3MayAbort( pParse );
        }
        else
#endif
        {
          int isReplace = 0;    /* Set to true if constraints may cause a replace */
          sqlite3GenerateConstraintChecks( pParse, pTab, baseCur, regIns, aRegIdx,
            keyColumn >= 0 ? 1 : 0, false, onError, endOfLoop, out isReplace
          );
          sqlite3FkCheck( pParse, pTab, 0, regIns );
          sqlite3CompleteInsertion(
         pParse, pTab, baseCur, regIns, aRegIdx, false, appendFlag, isReplace == 0
          );
        }
      }

      /* Update the count of rows that are inserted
      */
      if ( ( db.flags & SQLITE_CountRows ) != 0 )
      {
        sqlite3VdbeAddOp2( v, OP_AddImm, regRowCount, 1 );
      }

#if !SQLITE_OMIT_TRIGGER
      if ( pTrigger != null )
      {
        /* Code AFTER triggers */
        sqlite3CodeRowTrigger( pParse, pTrigger, TK_INSERT, null, TRIGGER_AFTER,
            pTab, regData - 2 - pTab.nCol, onError, endOfLoop );
      }
#endif

      /* The bottom of the main insertion loop, if the data source
** is a SELECT statement.
*/
      sqlite3VdbeResolveLabel( v, endOfLoop );
      if ( useTempTable )
      {
        sqlite3VdbeAddOp2( v, OP_Next, srcTab, addrCont );
        sqlite3VdbeJumpHere( v, addrInsTop );
        sqlite3VdbeAddOp1( v, OP_Close, srcTab );
      }
      else if ( pSelect != null )
      {
        sqlite3VdbeAddOp2( v, OP_Goto, 0, addrCont );
        sqlite3VdbeJumpHere( v, addrInsTop );
      }

      if ( !IsVirtual( pTab ) && !isView )
      {
        /* Close all tables opened */
        sqlite3VdbeAddOp1( v, OP_Close, baseCur );
        for ( idx = 1, pIdx = pTab.pIndex; pIdx != null; pIdx = pIdx.pNext, idx++ )
        {
          sqlite3VdbeAddOp1( v, OP_Close, idx + baseCur );
        }
      }

insert_end:
      /* Update the sqlite_sequence table by storing the content of the
      ** maximum rowid counter values recorded while inserting into
      ** autoincrement tables.
      */
      if ( pParse.nested == 0 && pParse.pTriggerTab == null )
      {
        sqlite3AutoincrementEnd( pParse );
      }

      /*
      ** Return the number of rows inserted. If this routine is
      ** generating code because of a call to sqlite3NestedParse(), do not
      ** invoke the callback function.
      */
      if ( ( db.flags & SQLITE_CountRows ) != 0 && 0 == pParse.nested && null == pParse.pTriggerTab )
      {
        sqlite3VdbeAddOp2( v, OP_ResultRow, regRowCount, 1 );
        sqlite3VdbeSetNumCols( v, 1 );
        sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "rows inserted", SQLITE_STATIC );
      }

insert_cleanup:
      sqlite3SrcListDelete( db, ref pTabList );
      sqlite3ExprListDelete( db, ref pList );
      sqlite3SelectDelete( db, ref pSelect );
      sqlite3IdListDelete( db, ref pColumn );
      sqlite3DbFree( db, ref aRegIdx );
    }
Esempio n. 55
0
    /*
    ** Create and populate a new TriggerPrg object with a sub-program 
    ** implementing trigger pTrigger with ON CONFLICT policy orconf.
    */
    static TriggerPrg codeRowTrigger(
      Parse pParse,        /* Current parse context */
      Trigger pTrigger,    /* Trigger to code */
      Table pTab,          /* The table pTrigger is attached to */
      int orconf           /* ON CONFLICT policy to code trigger program with */
    )
    {
      Parse pTop = sqlite3ParseToplevel( pParse );
      sqlite3 db = pParse.db;     /* Database handle */
      TriggerPrg pPrg;            /* Value to return */
      Expr pWhen = null;          /* Duplicate of trigger WHEN expression */
      Vdbe v;                     /* Temporary VM */
      NameContext sNC;            /* Name context for sub-vdbe */
      SubProgram pProgram = null; /* Sub-vdbe for trigger program */
      Parse pSubParse;            /* Parse context for sub-vdbe */
      int iEndTrigger = 0;        /* Label to jump to if WHEN is false */

      Debug.Assert( pTrigger.zName == null || pTab == tableOfTrigger( pTrigger ) );
      Debug.Assert( pTop.pVdbe != null );

      /* Allocate the TriggerPrg and SubProgram objects. To ensure that they
      ** are freed if an error occurs, link them into the Parse.pTriggerPrg 
      ** list of the top-level Parse object sooner rather than later.  */
      pPrg = new TriggerPrg();// sqlite3DbMallocZero( db, sizeof( TriggerPrg ) );
      //if ( null == pPrg ) return 0;
      pPrg.pNext = pTop.pTriggerPrg;
      pTop.pTriggerPrg = pPrg;
      pPrg.pProgram = pProgram = new SubProgram();// sqlite3DbMallocZero( db, sizeof( SubProgram ) );
      //if( null==pProgram ) return 0;
      sqlite3VdbeLinkSubProgram( pTop.pVdbe, pProgram );
      pPrg.pTrigger = pTrigger;
      pPrg.orconf = orconf;
      pPrg.aColmask[0] = 0xffffffff;
      pPrg.aColmask[1] = 0xffffffff;


      /* Allocate and populate a new Parse context to use for coding the 
      ** trigger sub-program.  */
      pSubParse = new Parse();// sqlite3StackAllocZero( db, sizeof( Parse ) );
      //if ( null == pSubParse ) return null;
      sNC = new NameContext();// memset( &sNC, 0, sizeof( sNC ) );
      sNC.pParse = pSubParse;
      pSubParse.db = db;
      pSubParse.pTriggerTab = pTab;
      pSubParse.pToplevel = pTop;
      pSubParse.zAuthContext = pTrigger.zName;
      pSubParse.eTriggerOp = pTrigger.op;
      pSubParse.nQueryLoop = pParse.nQueryLoop;

      v = sqlite3GetVdbe( pSubParse );
      if ( v != null )
      {
#if SQLITE_DEBUG
        VdbeComment( v, "Start: %s.%s (%s %s%s%s ON %s)",
          pTrigger.zName != null ? pTrigger.zName : "", onErrorText( orconf ),
          ( pTrigger.tr_tm == TRIGGER_BEFORE ? "BEFORE" : "AFTER" ),
            ( pTrigger.op == TK_UPDATE ? "UPDATE" : "" ),
            ( pTrigger.op == TK_INSERT ? "INSERT" : "" ),
            ( pTrigger.op == TK_DELETE ? "DELETE" : "" ),
          pTab.zName
        );
#endif
#if !SQLITE_OMIT_TRACE
        sqlite3VdbeChangeP4( v, -1,
          sqlite3MPrintf( db, "-- TRIGGER %s", pTrigger.zName ), P4_DYNAMIC
        );
#endif

        /* If one was specified, code the WHEN clause. If it evaluates to false
    ** (or NULL) the sub-vdbe is immediately halted by jumping to the 
    ** OP_Halt inserted at the end of the program.  */
        if ( pTrigger.pWhen != null )
        {
          pWhen = sqlite3ExprDup( db, pTrigger.pWhen, 0 );
          if ( SQLITE_OK == sqlite3ResolveExprNames( sNC, ref pWhen )
            //&& db.mallocFailed==0 
          )
          {
            iEndTrigger = sqlite3VdbeMakeLabel( v );
            sqlite3ExprIfFalse( pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL );
          }
          sqlite3ExprDelete( db, ref pWhen );
        }

        /* Code the trigger program into the sub-vdbe. */
        codeTriggerProgram( pSubParse, pTrigger.step_list, orconf );

        /* Insert an OP_Halt at the end of the sub-program. */
        if ( iEndTrigger != 0 )
        {
          sqlite3VdbeResolveLabel( v, iEndTrigger );
        }
        sqlite3VdbeAddOp0( v, OP_Halt );
#if SQLITE_DEBUG
        VdbeComment( v, "End: %s.%s", pTrigger.zName, onErrorText( orconf ) );
#endif
        transferParseError( pParse, pSubParse );
        //if( db.mallocFailed==0 ){
        pProgram.aOp = sqlite3VdbeTakeOpArray( v, ref pProgram.nOp, ref pTop.nMaxArg );
        //}
        pProgram.nMem = pSubParse.nMem;
        pProgram.nCsr = pSubParse.nTab;
        pProgram.token = pTrigger.GetHashCode();
        pPrg.aColmask[0] = pSubParse.oldmask;
        pPrg.aColmask[1] = pSubParse.newmask;
        sqlite3VdbeDelete( ref v );
      }

      Debug.Assert( null == pSubParse.pAinc && null == pSubParse.pZombieTab );
      Debug.Assert( null == pSubParse.pTriggerPrg && 0 == pSubParse.nMaxArg );
      //sqlite3StackFree(db, pSubParse);

      return pPrg;
    }
Esempio n. 56
0
    /*
    ** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
    ** The Name context of the SELECT statement is pNC.  zType is either
    ** "ORDER" or "GROUP" depending on which type of clause pOrderBy is.
    **
    ** This routine resolves each term of the clause into an expression.
    ** If the order-by term is an integer I between 1 and N (where N is the
    ** number of columns in the result set of the SELECT) then the expression
    ** in the resolution is a copy of the I-th result-set expression.  If
    ** the order-by term is an identify that corresponds to the AS-name of
    ** a result-set expression, then the term resolves to a copy of the
    ** result-set expression.  Otherwise, the expression is resolved in
    ** the usual way - using sqlite3ResolveExprNames().
    **
    ** This routine returns the number of errors.  If errors occur, then
    ** an appropriate error message might be left in pParse.  (OOM errors
    ** excepted.)
    */
    static int resolveOrderGroupBy(
    NameContext pNC,     /* The name context of the SELECT statement */
    Select pSelect,      /* The SELECT statement holding pOrderBy */
    ExprList pOrderBy,   /* An ORDER BY or GROUP BY clause to resolve */
    string zType         /* Either "ORDER" or "GROUP", as appropriate */
    )
    {
      int i;                         /* Loop counter */
      int iCol;                      /* Column number */
      ExprList_item pItem;   /* A term of the ORDER BY clause */
      Parse pParse;                 /* Parsing context */
      int nResult;                   /* Number of terms in the result set */

      if ( pOrderBy == null )
        return 0;
      nResult = pSelect.pEList.nExpr;
      pParse = pNC.pParse;
      for ( i = 0; i < pOrderBy.nExpr; i++ )//, pItem++ )
      {
        pItem = pOrderBy.a[i];
        Expr pE = pItem.pExpr;
        iCol = resolveAsName( pParse, pSelect.pEList, pE );
        if ( iCol > 0 )
        {
          /* If an AS-name match is found, mark this ORDER BY column as being
          ** a copy of the iCol-th result-set column.  The subsequent call to
          ** sqlite3ResolveOrderGroupBy() will convert the expression to a
          ** copy of the iCol-th result-set expression. */
          pItem.iCol = (u16)iCol;
          continue;
        }
        if ( sqlite3ExprIsInteger( pE, ref iCol ) != 0 )
        {
          /* The ORDER BY term is an integer constant.  Again, set the column
          ** number so that sqlite3ResolveOrderGroupBy() will convert the
          ** order-by term to a copy of the result-set expression */
          if ( iCol < 1 )
          {
            resolveOutOfRangeError( pParse, zType, i + 1, nResult );
            return 1;
          }
          pItem.iCol = (u16)iCol;
          continue;
        }

        /* Otherwise, treat the ORDER BY term as an ordinary expression */
        pItem.iCol = 0;
        if ( sqlite3ResolveExprNames( pNC, ref pE ) != 0 )
        {
          return 1;
        }
      }
      return sqlite3ResolveOrderGroupBy( pParse, pSelect, pOrderBy, zType );
    }
Esempio n. 57
0
    /*
    ** Process an UPDATE statement.
    **
    **   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
    **          \_______/ \________/     \______/       \________________/
    *            onError   pTabList      pChanges             pWhere
    */
    static void sqlite3Update(
    Parse pParse,         /* The parser context */
    SrcList pTabList,     /* The table in which we should change things */
    ExprList pChanges,    /* Things to be changed */
    Expr pWhere,          /* The WHERE clause.  May be null */
    int onError           /* How to handle constraint errors */
    )
    {
      int i, j;                   /* Loop counters */
      Table pTab;                 /* The table to be updated */
      int addr = 0;               /* VDBE instruction address of the start of the loop */
      WhereInfo pWInfo;           /* Information about the WHERE clause */
      Vdbe v;                     /* The virtual database engine */
      Index pIdx;                 /* For looping over indices */
      int nIdx;                   /* Number of indices that need updating */
      int iCur;                   /* VDBE Cursor number of pTab */
      sqlite3 db;                 /* The database structure */
      int[] aRegIdx = null;       /* One register assigned to each index to be updated */
      int[] aXRef = null;         /* aXRef[i] is the index in pChanges.a[] of the
** an expression for the i-th column of the table.
** aXRef[i]==-1 if the i-th column is not changed. */
      bool chngRowid;             /* True if the record number is being changed */
      Expr pRowidExpr = null;     /* Expression defining the new record number */
      bool openAll = false;       /* True if all indices need to be opened */
      AuthContext sContext;       /* The authorization context */
      NameContext sNC;            /* The name-context to resolve expressions in */
      int iDb;                    /* Database containing the table being updated */
      int j1;                     /* Addresses of jump instructions */
      u8 okOnePass;               /* True for one-pass algorithm without the FIFO */

#if !SQLITE_OMIT_TRIGGER
      bool isView = false;         /* Trying to update a view */
      Trigger pTrigger;            /* List of triggers on pTab, if required */
#endif
      int iBeginAfterTrigger = 0;  /* Address of after trigger program */
      int iEndAfterTrigger = 0;    /* Exit of after trigger program */
      int iBeginBeforeTrigger = 0; /* Address of before trigger program */
      int iEndBeforeTrigger = 0;   /* Exit of before trigger program */
      u32 old_col_mask = 0;        /* Mask of OLD.* columns in use */
      u32 new_col_mask = 0;        /* Mask of NEW.* columns in use */

      int newIdx = -1;             /* index of trigger "new" temp table       */
      int oldIdx = -1;             /* index of trigger "old" temp table       */

      /* Register Allocations */
      int regRowCount = 0;         /* A count of rows changed */
      int regOldRowid;             /* The old rowid */
      int regNewRowid;             /* The new rowid */
      int regData;                 /* New data for the row */
      int regRowSet = 0;           /* Rowset of rows to be updated */

      sContext = new AuthContext(); //memset( &sContext, 0, sizeof( sContext ) );
      db = pParse.db;
      if ( pParse.nErr != 0 /*|| db.mallocFailed != 0 */ )
      {
        goto update_cleanup;
      }
      Debug.Assert( pTabList.nSrc == 1 );

      /* Locate the table which we want to update.
      */
      pTab = sqlite3SrcListLookup( pParse, pTabList );
      if ( pTab == null ) goto update_cleanup;
      iDb = sqlite3SchemaToIndex( pParse.db, pTab.pSchema );

      /* Figure out if we have any triggers and if the table being
      ** updated is a view
      */
#if !SQLITE_OMIT_TRIGGER
      int iDummy = 0;
      pTrigger = sqlite3TriggersExist( pParse, pTab, TK_UPDATE, pChanges, ref iDummy );
      isView = pTab.pSelect != null;
#else
const Trigger pTrigger = null;
#if !SQLITE_OMIT_VIEW
const bool isView = false;
#endif
#endif
#if SQLITE_OMIT_VIEW
//    # undef isView
const bool isView = false;
#endif

      if ( sqlite3ViewGetColumnNames( pParse, pTab ) != 0 )
      {
        goto update_cleanup;
      }
      if ( sqlite3IsReadOnly( pParse, pTab, ( pTrigger != null ? 1 : 0 ) ) )
      {
        goto update_cleanup;
      }
      aXRef = new int[pTab.nCol];// sqlite3DbMallocRaw(db, sizeof(int) * pTab.nCol);
      //if ( aXRef == null ) goto update_cleanup;
      for ( i = 0 ; i < pTab.nCol ; i++ ) aXRef[i] = -1;

      /* If there are FOR EACH ROW triggers, allocate cursors for the
      ** special OLD and NEW tables
      */
      if ( pTrigger != null )
      {
        newIdx = pParse.nTab++;
        oldIdx = pParse.nTab++;
      }

      /* Allocate a cursors for the main database table and for all indices.
      ** The index cursors might not be used, but if they are used they
      ** need to occur right after the database cursor.  So go ahead and
      ** allocate enough space, just in case.
      */
      pTabList.a[0].iCursor = iCur = pParse.nTab++;
      for ( pIdx = pTab.pIndex ; pIdx != null ; pIdx = pIdx.pNext )
      {
        pParse.nTab++;
      }

      /* Initialize the name-context */
      sNC = new NameContext();// memset(&sNC, 0, sNC).Length;
      sNC.pParse = pParse;
      sNC.pSrcList = pTabList;

      /* Resolve the column names in all the expressions of the
      ** of the UPDATE statement.  Also find the column index
      ** for each column to be updated in the pChanges array.  For each
      ** column to be updated, make sure we have authorization to change
      ** that column.
      */
      chngRowid = false;
      for ( i = 0 ; i < pChanges.nExpr ; i++ )
      {
        if ( sqlite3ResolveExprNames( sNC, ref pChanges.a[i].pExpr ) != 0 )
        {
          goto update_cleanup;
        }
        for ( j = 0 ; j < pTab.nCol ; j++ )
        {
          if ( sqlite3StrICmp( pTab.aCol[j].zName, pChanges.a[i].zName ) == 0 )
          {
            if ( j == pTab.iPKey )
            {
              chngRowid = true;
              pRowidExpr = pChanges.a[i].pExpr;
            }
            aXRef[j] = i;
            break;
          }
        }
        if ( j >= pTab.nCol )
        {
          if ( sqlite3IsRowid( pChanges.a[i].zName ) )
          {
            chngRowid = true;
            pRowidExpr = pChanges.a[i].pExpr;
          }
          else
          {
            sqlite3ErrorMsg( pParse, "no such column: %s", pChanges.a[i].zName );
            goto update_cleanup;
          }
        }
#if !SQLITE_OMIT_AUTHORIZATION
{
int rc;
rc = sqlite3AuthCheck(pParse, SQLITE_UPDATE, pTab.zName,
pTab.aCol[j].zName, db.aDb[iDb].zName);
if( rc==SQLITE_DENY ){
goto update_cleanup;
}else if( rc==SQLITE_IGNORE ){
aXRef[j] = -1;
}
}
#endif
      }

      /* Allocate memory for the array aRegIdx[].  There is one entry in the
      ** array for each index associated with table being updated.  Fill in
      ** the value with a register number for indices that are to be used
      ** and with zero for unused indices.
      */
      for ( nIdx = 0, pIdx = pTab.pIndex ; pIdx != null ; pIdx = pIdx.pNext, nIdx++ ) { }
      if ( nIdx > 0 )
      {
        aRegIdx = new int[nIdx]; // sqlite3DbMallocRaw(db, Index*.Length * nIdx);
        if ( aRegIdx == null ) goto update_cleanup;
      }
      for ( j = 0, pIdx = pTab.pIndex ; pIdx != null ; pIdx = pIdx.pNext, j++ )
      {
        int reg;
        if ( chngRowid )
        {
          reg = ++pParse.nMem;
        }
        else
        {
          reg = 0;
          for ( i = 0 ; i < pIdx.nColumn ; i++ )
          {
            if ( aXRef[pIdx.aiColumn[i]] >= 0 )
            {
              reg = ++pParse.nMem;
              break;
            }
          }
        }
        aRegIdx[j] = reg;
      }

      /* Allocate a block of register used to store the change record
      ** sent to sqlite3GenerateConstraintChecks().  There are either
      ** one or two registers for holding the rowid.  One rowid register
      ** is used if chngRowid is false and two are used if chngRowid is
      ** true.  Following these are pTab.nCol register holding column
      ** data.
      */
      regOldRowid = regNewRowid = pParse.nMem + 1;
      pParse.nMem += pTab.nCol + 1;
      if ( chngRowid )
      {
        regNewRowid++;
        pParse.nMem++;
      }
      regData = regNewRowid + 1;


      /* Begin generating code.
      */
      v = sqlite3GetVdbe( pParse );
      if ( v == null ) goto update_cleanup;
      if ( pParse.nested == 0 ) sqlite3VdbeCountChanges( v );
      sqlite3BeginWriteOperation( pParse, 1, iDb );

#if !SQLITE_OMIT_VIRTUALTABLE
/* Virtual tables must be handled separately */
if ( IsVirtual( pTab ) )
{
updateVirtualTable( pParse, pTabList, pTab, pChanges, pRowidExpr, aXRef, pWhere );
pWhere = null;
pTabList = null;
goto update_cleanup;
}
#endif

      /* Start the view context
*/
#if !SQLITE_OMIT_AUTHORIZATION
if( isView ){
sqlite3AuthContextPush(pParse, sContext, pTab.zName);
}
#endif
      /* Generate the code for triggers.
*/
      if ( pTrigger != null )
      {
        int iGoto;

        /* Create pseudo-tables for NEW and OLD
        */
        sqlite3VdbeAddOp3( v, OP_OpenPseudo, oldIdx, 0, pTab.nCol );
        sqlite3VdbeAddOp3( v, OP_OpenPseudo, newIdx, 0, pTab.nCol );

        iGoto = sqlite3VdbeAddOp2( v, OP_Goto, 0, 0 );
        addr = sqlite3VdbeMakeLabel( v );
        iBeginBeforeTrigger = sqlite3VdbeCurrentAddr( v );
        if ( sqlite3CodeRowTrigger( pParse, pTrigger, TK_UPDATE, pChanges,
        TRIGGER_BEFORE, pTab, newIdx, oldIdx, onError, addr,
        ref old_col_mask, ref new_col_mask ) != 0 )
        {
          goto update_cleanup;
        }
        iEndBeforeTrigger = sqlite3VdbeAddOp2( v, OP_Goto, 0, 0 );
        iBeginAfterTrigger = sqlite3VdbeCurrentAddr( v );
#if !SQLITE_OMIT_TRIGGER
        if ( sqlite3CodeRowTrigger( pParse, pTrigger, TK_UPDATE, pChanges, TRIGGER_AFTER, pTab,
        newIdx, oldIdx, onError, addr, ref old_col_mask, ref new_col_mask ) != 0 )
        {
          goto update_cleanup;
        }
#endif
        iEndAfterTrigger = sqlite3VdbeAddOp2( v, OP_Goto, 0, 0 );
        sqlite3VdbeJumpHere( v, iGoto );
      }

      /* If we are trying to update a view, realize that view into
      ** a ephemeral table.
      */
#if !(SQLITE_OMIT_VIEW) && !(SQLITE_OMIT_TRIGGER)
      if ( isView )
      {
        sqlite3MaterializeView( pParse, pTab, pWhere, iCur );
      }
#endif

      /* Resolve the column names in all the expressions in the
** WHERE clause.
*/
      if ( sqlite3ResolveExprNames( sNC, ref pWhere ) != 0 )
      {
        goto update_cleanup;
      }

      /* Begin the database scan
      */
      sqlite3VdbeAddOp2( v, OP_Null, 0, regOldRowid );
      ExprList NullOrderby = null;
      pWInfo = sqlite3WhereBegin( pParse, pTabList, pWhere, ref NullOrderby, WHERE_ONEPASS_DESIRED );
      if ( pWInfo == null ) goto update_cleanup;
      okOnePass = pWInfo.okOnePass;

      /* Remember the rowid of every item to be updated.
      */
      sqlite3VdbeAddOp2( v, OP_Rowid, iCur, regOldRowid );
      if ( 0 == okOnePass )
      {
        regRowSet = ++pParse.nMem;
        sqlite3VdbeAddOp2( v, OP_RowSetAdd, regRowSet, regOldRowid );
      }

      /* End the database scan loop.
      */
      sqlite3WhereEnd( pWInfo );

      /* Initialize the count of updated rows
      */
      if ( ( db.flags & SQLITE_CountRows ) != 0 && pParse.trigStack == null )
      {
        regRowCount = ++pParse.nMem;
        sqlite3VdbeAddOp2( v, OP_Integer, 0, regRowCount );
      }

      if ( !isView )
      {
        /*
        ** Open every index that needs updating.  Note that if any
        ** index could potentially invoke a REPLACE conflict resolution
        ** action, then we need to open all indices because we might need
        ** to be deleting some records.
        */
        if ( 0 == okOnePass ) sqlite3OpenTable( pParse, iCur, iDb, pTab, OP_OpenWrite );
        if ( onError == OE_Replace )
        {
          openAll = true;
        }
        else
        {
          openAll = false;
          for ( pIdx = pTab.pIndex ; pIdx != null ; pIdx = pIdx.pNext )
          {
            if ( pIdx.onError == OE_Replace )
            {
              openAll = true;
              break;
            }
          }
        }
        for ( i = 0, pIdx = pTab.pIndex ; pIdx != null ; pIdx = pIdx.pNext, i++ )
        {
          if ( openAll || aRegIdx[i] > 0 )
          {
            KeyInfo pKey = sqlite3IndexKeyinfo( pParse, pIdx );
            sqlite3VdbeAddOp4( v, OP_OpenWrite, iCur + i + 1, pIdx.tnum, iDb,
            pKey, P4_KEYINFO_HANDOFF );
            Debug.Assert( pParse.nTab > iCur + i + 1 );
          }
        }
      }

      /* Jump back to this point if a trigger encounters an IGNORE constraint. */
      if ( pTrigger != null )
      {
        sqlite3VdbeResolveLabel( v, addr );
      }

      /* Top of the update loop */
      if ( okOnePass != 0 )
      {
        int a1 = sqlite3VdbeAddOp1( v, OP_NotNull, regOldRowid );
        addr = sqlite3VdbeAddOp0( v, OP_Goto );
        sqlite3VdbeJumpHere( v, a1 );
      }
      else
      {
        addr = sqlite3VdbeAddOp3( v, OP_RowSetRead, regRowSet, 0, regOldRowid );
      }

      if ( pTrigger != null )
      {
        int regRowid;
        int regRow;
        int regCols;

        /* Make cursor iCur point to the record that is being updated.
        */
        sqlite3VdbeAddOp3( v, OP_NotExists, iCur, addr, regOldRowid );

        /* Generate the OLD table
        */
        regRowid = sqlite3GetTempReg( pParse );
        regRow = sqlite3GetTempReg( pParse );
        sqlite3VdbeAddOp2( v, OP_Rowid, iCur, regRowid );
        if ( old_col_mask == 0 )
        {
          sqlite3VdbeAddOp2( v, OP_Null, 0, regRow );
        }
        else
        {
          sqlite3VdbeAddOp2( v, OP_RowData, iCur, regRow );
        }
        sqlite3VdbeAddOp3( v, OP_Insert, oldIdx, regRow, regRowid );

        /* Generate the NEW table
        */
        if ( chngRowid )
        {
          sqlite3ExprCodeAndCache( pParse, pRowidExpr, regRowid );
          sqlite3VdbeAddOp1( v, OP_MustBeInt, regRowid );
        }
        else
        {
          sqlite3VdbeAddOp2( v, OP_Rowid, iCur, regRowid );
        }
        regCols = sqlite3GetTempRange( pParse, pTab.nCol );
        for ( i = 0 ; i < pTab.nCol ; i++ )
        {
          if ( i == pTab.iPKey )
          {
            sqlite3VdbeAddOp2( v, OP_Null, 0, regCols + i );
            continue;
          }
          j = aXRef[i];
          if ( ( i < 32 && ( new_col_mask & ( (u32)1 << i ) ) != 0 ) || new_col_mask == 0xffffffff )
          {
            if ( j < 0 )
            {
              sqlite3VdbeAddOp3( v, OP_Column, iCur, i, regCols + i );
              sqlite3ColumnDefault( v, pTab, i, -1 );
            }
            else
            {
              sqlite3ExprCodeAndCache( pParse, pChanges.a[j].pExpr, regCols + i );
            }
          }
          else
          {
            sqlite3VdbeAddOp2( v, OP_Null, 0, regCols + i );
          }
        }
        sqlite3VdbeAddOp3( v, OP_MakeRecord, regCols, pTab.nCol, regRow );
        if ( !isView )
        {
          sqlite3TableAffinityStr( v, pTab );
          sqlite3ExprCacheAffinityChange( pParse, regCols, pTab.nCol );
        }
        sqlite3ReleaseTempRange( pParse, regCols, pTab.nCol );
        /* if( pParse.nErr ) goto update_cleanup; */
        sqlite3VdbeAddOp3( v, OP_Insert, newIdx, regRow, regRowid );
        sqlite3ReleaseTempReg( pParse, regRowid );
        sqlite3ReleaseTempReg( pParse, regRow );

        sqlite3VdbeAddOp2( v, OP_Goto, 0, iBeginBeforeTrigger );
        sqlite3VdbeJumpHere( v, iEndBeforeTrigger );
      }

      if ( !isView )
      {

        /* Loop over every record that needs updating.  We have to load
        ** the old data for each record to be updated because some columns
        ** might not change and we will need to copy the old value.
        ** Also, the old data is needed to delete the old index entries.
        ** So make the cursor point at the old record.
        */
        sqlite3VdbeAddOp3( v, OP_NotExists, iCur, addr, regOldRowid );

        /* If the record number will change, push the record number as it
        ** will be after the update. (The old record number is currently
        ** on top of the stack.)
        */
        if ( chngRowid )
        {
          sqlite3ExprCode( pParse, pRowidExpr, regNewRowid );
          sqlite3VdbeAddOp1( v, OP_MustBeInt, regNewRowid );
        }

        /* Compute new data for this record.
        */
        for ( i = 0 ; i < pTab.nCol ; i++ )
        {
          if ( i == pTab.iPKey )
          {
            sqlite3VdbeAddOp2( v, OP_Null, 0, regData + i );
            continue;
          }
          j = aXRef[i];
          if ( j < 0 )
          {
            sqlite3VdbeAddOp3( v, OP_Column, iCur, i, regData + i );
            sqlite3ColumnDefault( v, pTab, i, regData + i );
          }
          else
          {
            sqlite3ExprCode( pParse, pChanges.a[j].pExpr, regData + i );
          }
        }

        /* Do constraint checks
        */
        iDummy = 0;
        sqlite3GenerateConstraintChecks( pParse, pTab, iCur, regNewRowid,
           aRegIdx, chngRowid, true,
           onError, addr, ref iDummy );

        /* Delete the old indices for the current record.
        */
        j1 = sqlite3VdbeAddOp3( v, OP_NotExists, iCur, 0, regOldRowid );
        sqlite3GenerateRowIndexDelete( pParse, pTab, iCur, aRegIdx );

        /* If changing the record number, delete the old record.
        */
        if ( chngRowid )
        {
          sqlite3VdbeAddOp2( v, OP_Delete, iCur, 0 );
        }
        sqlite3VdbeJumpHere( v, j1 );

        /* Create the new index entries and the new record.
        */
        sqlite3CompleteInsertion( pParse, pTab, iCur, regNewRowid,
        aRegIdx, true, -1, false, false );
      }

      /* Increment the row counter
      */
      if ( ( db.flags & SQLITE_CountRows ) != 0 && pParse.trigStack == null )
      {
        sqlite3VdbeAddOp2( v, OP_AddImm, regRowCount, 1 );
      }

      /* If there are triggers, close all the cursors after each iteration
      ** through the loop.  The fire the after triggers.
      */
      if ( pTrigger != null )
      {
        sqlite3VdbeAddOp2( v, OP_Goto, 0, iBeginAfterTrigger );
        sqlite3VdbeJumpHere( v, iEndAfterTrigger );
      }

      /* Repeat the above with the next record to be updated, until
      ** all record selected by the WHERE clause have been updated.
      */
      sqlite3VdbeAddOp2( v, OP_Goto, 0, addr );
      sqlite3VdbeJumpHere( v, addr );

      /* Close all tables */
      for ( i = 0, pIdx = pTab.pIndex ; pIdx != null ; pIdx = pIdx.pNext, i++ )
      {
        if ( openAll || aRegIdx[i] > 0 )
        {
          sqlite3VdbeAddOp2( v, OP_Close, iCur + i + 1, 0 );
        }
      }
      sqlite3VdbeAddOp2( v, OP_Close, iCur, 0 );
      if ( pTrigger != null )
      {
        sqlite3VdbeAddOp2( v, OP_Close, newIdx, 0 );
        sqlite3VdbeAddOp2( v, OP_Close, oldIdx, 0 );
      }

      /* Update the sqlite_sequence table by storing the content of the
      ** maximum rowid counter values recorded while inserting into
      ** autoincrement tables.
      */
      if ( pParse.nested == 0 && pParse.trigStack == null )
      {
        sqlite3AutoincrementEnd( pParse );
      }

      /*
      ** Return the number of rows that were changed. If this routine is
      ** generating code because of a call to sqlite3NestedParse(), do not
      ** invoke the callback function.
      */
      if ( ( db.flags & SQLITE_CountRows ) != 0 && pParse.trigStack == null && pParse.nested == 0 )
      {
        sqlite3VdbeAddOp2( v, OP_ResultRow, regRowCount, 1 );
        sqlite3VdbeSetNumCols( v, 1 );
        sqlite3VdbeSetColName( v, 0, COLNAME_NAME, "rows updated", SQLITE_STATIC );
      }

update_cleanup:
#if !SQLITE_OMIT_AUTHORIZATION
sqlite3AuthContextPop(sContext);
#endif
      //sqlite3DbFree( db, ref  aRegIdx );
      //sqlite3DbFree( db, ref  aXRef );
      sqlite3SrcListDelete( db, ref pTabList );
      sqlite3ExprListDelete( db, ref pChanges );
      sqlite3ExprDelete( db, ref pWhere );
      return;
    }
Esempio n. 58
0
    /*
    ** Resolve names in the SELECT statement p and all of its descendents.
    */
    static int resolveSelectStep( Walker pWalker, Select p )
    {
      NameContext pOuterNC;  /* Context that contains this SELECT */
      NameContext sNC;       /* Name context of this SELECT */
      bool isCompound;       /* True if p is a compound select */
      int nCompound;         /* Number of compound terms processed so far */
      Parse pParse;          /* Parsing context */
      ExprList pEList;       /* Result set expression list */
      int i;                 /* Loop counter */
      ExprList pGroupBy;     /* The GROUP BY clause */
      Select pLeftmost;      /* Left-most of SELECT of a compound */

      Debug.Assert( p != null );
      if ( ( p.selFlags & SF_Resolved ) != 0 )
      {
        return WRC_Prune;
      }
      pOuterNC = pWalker.u.pNC;
      pParse = pWalker.pParse;
      //sqlite3 db = pParse.db;

      /* Normally sqlite3SelectExpand() will be called first and will have
      ** already expanded this SELECT.  However, if this is a subquery within
      ** an expression, sqlite3ResolveExprNames() will be called without a
      ** prior call to sqlite3SelectExpand().  When that happens, let
      ** sqlite3SelectPrep() do all of the processing for this SELECT.
      ** sqlite3SelectPrep() will invoke both sqlite3SelectExpand() and
      ** this routine in the correct order.
      */
      if ( ( p.selFlags & SF_Expanded ) == 0 )
      {
        sqlite3SelectPrep( pParse, p, pOuterNC );
        return ( pParse.nErr != 0 /*|| db.mallocFailed != 0 */ ) ? WRC_Abort : WRC_Prune;
      }

      isCompound = p.pPrior != null;
      nCompound = 0;
      pLeftmost = p;
      while ( p != null )
      {
        Debug.Assert( ( p.selFlags & SF_Expanded ) != 0 );
        Debug.Assert( ( p.selFlags & SF_Resolved ) == 0 );
        p.selFlags |= SF_Resolved;

        /* Resolve the expressions in the LIMIT and OFFSET clauses. These
        ** are not allowed to refer to any names, so pass an empty NameContext.
        */
        sNC = new NameContext();// memset( &sNC, 0, sizeof( sNC ) );
        sNC.pParse = pParse;
        if ( sqlite3ResolveExprNames( sNC, ref p.pLimit ) != 0 ||
        sqlite3ResolveExprNames( sNC, ref p.pOffset ) != 0 )
        {
          return WRC_Abort;
        }

        /* Set up the local name-context to pass to sqlite3ResolveExprNames() to
        ** resolve the result-set expression list.
        */
        sNC.allowAgg = 1;
        sNC.pSrcList = p.pSrc;
        sNC.pNext = pOuterNC;

        /* Resolve names in the result set. */
        pEList = p.pEList;
        Debug.Assert( pEList != null );
        for ( i = 0; i < pEList.nExpr; i++ )
        {
          Expr pX = pEList.a[i].pExpr;
          if ( sqlite3ResolveExprNames( sNC, ref pX ) != 0 )
          {
            return WRC_Abort;
          }
        }

        /* Recursively resolve names in all subqueries
        */
        for ( i = 0; i < p.pSrc.nSrc; i++ )
        {
          SrcList_item pItem = p.pSrc.a[i];
          if ( pItem.pSelect != null )
          {
            string zSavedContext = pParse.zAuthContext;
            if ( pItem.zName != null )
              pParse.zAuthContext = pItem.zName;
            sqlite3ResolveSelectNames( pParse, pItem.pSelect, pOuterNC );
            pParse.zAuthContext = zSavedContext;
            if ( pParse.nErr != 0 /*|| db.mallocFailed != 0 */ )
              return WRC_Abort;
          }
        }

        /* If there are no aggregate functions in the result-set, and no GROUP BY
        ** expression, do not allow aggregates in any of the other expressions.
        */
        Debug.Assert( ( p.selFlags & SF_Aggregate ) == 0 );
        pGroupBy = p.pGroupBy;
        if ( pGroupBy != null || sNC.hasAgg != 0 )
        {
          p.selFlags |= SF_Aggregate;
        }
        else
        {
          sNC.allowAgg = 0;
        }

        /* If a HAVING clause is present, then there must be a GROUP BY clause.
        */
        if ( p.pHaving != null && pGroupBy == null )
        {
          sqlite3ErrorMsg( pParse, "a GROUP BY clause is required before HAVING" );
          return WRC_Abort;
        }

        /* Add the expression list to the name-context before parsing the
        ** other expressions in the SELECT statement. This is so that
        ** expressions in the WHERE clause (etc.) can refer to expressions by
        ** aliases in the result set.
        **
        ** Minor point: If this is the case, then the expression will be
        ** re-evaluated for each reference to it.
        */
        sNC.pEList = p.pEList;
        if ( sqlite3ResolveExprNames( sNC, ref p.pWhere ) != 0 ||
        sqlite3ResolveExprNames( sNC, ref p.pHaving ) != 0
        )
        {
          return WRC_Abort;
        }

        /* The ORDER BY and GROUP BY clauses may not refer to terms in
        ** outer queries
        */
        sNC.pNext = null;
        sNC.allowAgg = 1;

        /* Process the ORDER BY clause for singleton SELECT statements.
        ** The ORDER BY clause for compounds SELECT statements is handled
        ** below, after all of the result-sets for all of the elements of
        ** the compound have been resolved.
        */
        if ( !isCompound && resolveOrderGroupBy( sNC, p, p.pOrderBy, "ORDER" ) != 0 )
        {
          return WRC_Abort;
        }
        //if ( db.mallocFailed != 0 )
        //{
        //  return WRC_Abort;
        //}

        /* Resolve the GROUP BY clause.  At the same time, make sure
        ** the GROUP BY clause does not contain aggregate functions.
        */
        if ( pGroupBy != null )
        {
          ExprList_item pItem;

          if ( resolveOrderGroupBy( sNC, p, pGroupBy, "GROUP" ) != 0 /*|| db.mallocFailed != 0 */ )
          {
            return WRC_Abort;
          }
          for ( i = 0; i < pGroupBy.nExpr; i++ )//, pItem++)
          {
            pItem = pGroupBy.a[i];
            if ( ( pItem.pExpr.flags & EP_Agg ) != 0 )//HasProperty(pItem.pExpr, EP_Agg) )
            {
              sqlite3ErrorMsg( pParse, "aggregate functions are not allowed in " +
              "the GROUP BY clause" );
              return WRC_Abort;
            }
          }
        }

        /* Advance to the next term of the compound
        */
        p = p.pPrior;
        nCompound++;
      }

      /* Resolve the ORDER BY on a compound SELECT after all terms of
      ** the compound have been resolved.
      */
      if ( isCompound && resolveCompoundOrderBy( pParse, pLeftmost ) != 0 )
      {
        return WRC_Abort;
      }

      return WRC_Prune;
    }
 public DepartmentsController(NameContext context)
 {
     _context = context;
 }
Esempio n. 60
0
        static WRC ResolveExprStep(Walker walker, Expr expr)
        {
            NameContext nc = walker.u.NC;

            Debug.Assert(nc != null);
            Parse parse = nc.Parse;

            Debug.Assert(parse == walker.Parse);

            if (E.ExprHasAnyProperty(expr, EP.Resolved))
            {
                return(WRC.Prune);
            }
            E.ExprSetProperty(expr, EP.Resolved);
#if !NDEBUG
            if (nc.SrcList != null && nc.SrcList.Allocs > 0)
            {
                SrcList srcList = nc.SrcList;
                for (int i = 0; i < nc.SrcList.Srcs; i++)
                {
                    Debug.Assert(srcList.Ids[i].Cursor >= 0 && srcList.Ids[i].Cursor < parse.Tabs);
                }
            }
#endif
            switch (expr.OP)
            {
#if ENABLE_UPDATE_DELETE_LIMIT && !OMIT_SUBQUERY
            // The special operator TK_ROW means use the rowid for the first column in the FROM clause.  This is used by the LIMIT and ORDER BY
            // clause processing on UPDATE and DELETE statements.
            case TK.ROW:
            {
                SrcList srcList = nc.SrcList;
                Debug.Assert(srcList != null && srcList.Srcs == 1);
                SrcList.SrcListItem item = srcList.Ids[0];
                expr.OP        = TK.COLUMN;
                expr.Table     = item.Table;
                expr.TableId   = item.Cursor;
                expr.ColumnIdx = -1;
                expr.Aff       = AFF.INTEGER;
                break;
            }
#endif

            case TK.ID:      // A lone identifier is the name of a column.
            {
                return(LookupName(parse, null, null, expr.u.Token, nc, expr));
            }

            case TK.DOT:     // A table name and column name: ID.ID Or a database, table and column: ID.ID.ID
            {
                string columnName;
                string tableName;
                string dbName;
                // if (srcList == nullptr) break;
                Expr right = expr.Right;
                if (right.OP == TK.ID)
                {
                    dbName     = null;
                    tableName  = expr.Left.u.Token;
                    columnName = right.u.Token;
                }
                else
                {
                    Debug.Assert(right.OP == TK.DOT);
                    dbName     = expr.Left.u.Token;
                    tableName  = right.Left.u.Token;
                    columnName = right.Right.u.Token;
                }
                return(LookupName(parse, dbName, tableName, columnName, nc, expr));
            }

            case TK.CONST_FUNC:
            case TK.FUNCTION:                                              // Resolve function names
            {
                ExprList   list         = expr.x.List;                     // The argument list
                int        n            = (list != null ? list.Exprs : 0); // Number of arguments
                bool       noSuchFunc   = false;                           // True if no such function exists
                bool       wrongNumArgs = false;                           // True if wrong number of arguments
                bool       isAgg        = false;                           // True if is an aggregate function
                TEXTENCODE encode       = E.CTXENCODE(parse.Ctx);          // The database encoding

                C.ASSERTCOVERAGE(expr.OP == TK.CONST_FUNC);
                Debug.Assert(!E.ExprHasProperty(expr, EP.xIsSelect));
                string  id       = expr.u.Token;                                                     // The function name.
                int     idLength = id.Length;                                                        // Number of characters in function name
                FuncDef def      = Callback.FindFunction(parse.Ctx, id, idLength, n, encode, false); // Information about the function
                if (def == null)
                {
                    def = Callback.FindFunction(parse.Ctx, id, idLength, -2, encode, false);
                    if (def == null)
                    {
                        noSuchFunc = true;
                    }
                    else
                    {
                        wrongNumArgs = true;
                    }
                }
                else
                {
                    isAgg = (def.Func == null);
                }
#if !OMIT_AUTHORIZATION
                if (def != null)
                {
                    ARC auth = Auth.Check(parse, AUTH.FUNCTION, null, def.Name, null);         // Authorization to use the function
                    if (auth != ARC.OK)
                    {
                        if (auth == ARC.DENY)
                        {
                            parse.ErrorMsg("not authorized to use function: %s", def.Name);
                            nc.Errs++;
                        }
                        expr.OP = TK.NULL;
                        return(WRC.Prune);
                    }
                }
#endif
                if (isAgg && (nc.NCFlags & NC.AllowAgg) == 0)
                {
                    parse.ErrorMsg("misuse of aggregate function %.*s()", idLength, id);
                    nc.Errs++;
                    isAgg = false;
                }
                else if (noSuchFunc && !ctx.Init.Busy)
                {
                    parse.ErrorMsg("no such function: %.*s", idLength, id);
                    nc.Errs++;
                }
                else if (wrongNumArgs)
                {
                    parse.ErrorMsg("wrong number of arguments to function %.*s()", idLength, id);
                    nc.Errs++;
                }
                if (isAgg)
                {
                    nc.NCFlags &= ~NC.AllowAgg;
                }
                walker.WalkExprList(list);
                if (isAgg)
                {
                    NameContext nc2 = nc;
                    expr.OP  = TK.AGG_FUNCTION;
                    expr.OP2 = 0;
                    while (nc2 != null && !expr.FunctionUsesThisSrc(nc2.SrcList))
                    {
                        expr.OP2++;
                        nc2 = nc2.Next;
                    }
                    if (nc2 != null)
                    {
                        nc2.NCFlags |= NC.HasAgg;
                    }
                    nc.NCFlags |= NC.AllowAgg;
                }
                // FIX ME:  Compute pExpr->affinity based on the expected return type of the function
                return(WRC.Prune);
            }

#if !OMIT_SUBQUERY
            case TK.SELECT:
            case TK.EXISTS:
            {
                C.ASSERTCOVERAGE(expr.OP == TK.EXISTS);
                goto case TK.IN;
            }
#endif
            case TK.IN:
            {
                C.ASSERTCOVERAGE(expr.OP == TK.IN);
                if (E.ExprHasProperty(expr, EP.xIsSelect))
                {
                    int refs = nc.Refs;
#if !OMIT_CHECK
                    if ((nc.NCFlags & NC.IsCheck) != 0)
                    {
                        parse.ErrorMsg("subqueries prohibited in CHECK constraints");
                    }
#endif
                    walker.WalkSelect(expr.x.Select);
                    Debug.Assert(nc.Refs >= refs);
                    if (refs != nc.Refs)
                    {
                        E.ExprSetProperty(expr, EP.VarSelect);
                    }
                }
                break;
            }

#if !OMIT_CHECK
            case TK.VARIABLE:
            {
                if ((nc.NCFlags & NC.IsCheck) != 0)
                {
                    parse.ErrorMsg("parameters prohibited in CHECK constraints");
                }

                break;
            }
#endif
            }
            return(parse.Errs != 0 || parse.Ctx.MallocFailed ? WRC.Abort : WRC.Continue);
        }