public override Null Visit(FuncDef node)
    {
        // Define the function
        node.symbol = new Symbol {
            kind = SymbolKind.Func,
            isStatic = node.isStatic,
            def = node,
            type = new ErrorType()
        };
        scope.Define(node.symbol);

        // Visit the children differently than base.Visit(node) because we
        // want to define arguments in the body scope, not the parent scope.
        // Note that we don't visit the body, that's for ComputeTypesPass.
        node.returnType.Accept(this);
        if (node.block != null) {
            // Define arguments in the scope of the body
            node.block.scope = new Scope(scope, log, ScopeKind.Func);
            scope = node.block.scope;
            foreach (VarDef argDef in node.argDefs)
                argDef.Accept(this);
            scope = scope.parent;
        } else {
            // Define arguments in a temporary scope if no body is present
            scope = new Scope(scope, log, ScopeKind.Func);
            foreach (VarDef argDef in node.argDefs)
                argDef.Accept(this);
            scope = scope.parent;
        }

        return null;
    }
Example #2
0
        /*
        ** The first parameter (pDef) is a function implementation.  The
        ** second parameter (pExpr) is the first argument to this function.
        ** If pExpr is a column in a virtual table, then let the virtual
        ** table implementation have an opportunity to overload the function.
        **
        ** This routine is used to allow virtual table implementations to
        ** overload MATCH, LIKE, GLOB, and REGEXP operators.
        **
        ** Return either the pDef argument (indicating no change) or a
        ** new FuncDef structure that is marked as ephemeral using the
        ** SQLITE_FUNC_EPHEM flag.
        */
        FuncDef *sqlite3VtabOverloadFunction(
            sqlite3 *db,    /* Database connection for reporting malloc problems */
            FuncDef *pDef,  /* Function to possibly overload */
            int nArg,       /* Number of arguments to the function */
            Expr *pExpr     /* First argument to the function */
            )
        {
            Table *pTab;
              sqlite3_vtab *pVtab;
              sqlite3_module *pMod;
              void (*xFunc)(sqlite3_context*,int,sqlite3_value**) = 0;
              void *pArg = 0;
              FuncDef *pNew;
              int rc = 0;
              char *zLowerName;
              unsigned char *z;

              /* Check to see the left operand is a column in a virtual table */
              if( NEVER(pExpr==0) ) return pDef;
              if( pExpr->op!=TK_COLUMN ) return pDef;
              pTab = pExpr->pTab;
              if( NEVER(pTab==0) ) return pDef;
              if( (pTab->tabFlags & TF_Virtual)==0 ) return pDef;
              pVtab = sqlite3GetVTable(db, pTab)->pVtab;
              assert( pVtab!=0 );
              assert( pVtab->pModule!=0 );
              pMod = (sqlite3_module *)pVtab->pModule;
              if( pMod->xFindFunction==0 ) return pDef;

              /* Call the xFindFunction method on the virtual table implementation
              ** to see if the implementation wants to overload this function
              */
              zLowerName = sqlite3DbStrDup(db, pDef->zName);
              if( zLowerName ){
            for(z=(unsigned char*)zLowerName; *z; z++){
              *z = sqlite3UpperToLower[*z];
            }
            rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg);
            sqlite3DbFree(db, zLowerName);
              }
              if( rc==0 ){
            return pDef;
              }

              /* Create a new ephemeral function definition for the overloaded
              ** function */
              pNew = sqlite3DbMallocZero(db, sizeof(*pNew)
                             + sqlite3Strlen30(pDef->zName) + 1);
              if( pNew==0 ){
            return pDef;
              }
              *pNew = *pDef;
              pNew->zName = (char *)&pNew[1];
              memcpy(pNew->zName, pDef->zName, sqlite3Strlen30(pDef->zName)+1);
              pNew->xFunc = xFunc;
              pNew->pUserData = pArg;
              pNew->flags |= SQLITE_FUNC_EPHEM;
              return pNew;
        }
Example #3
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);
        }
    public override Null Visit(FuncDef node)
    {
        // Don't visit the body, that's for ComputeTypesPass
        node.returnType.Accept(this);
        foreach (VarDef argDef in node.argDefs) {
            argDef.Accept(this);
        }

        // Construct a function type from the parsed return and argument types
        node.symbol.type = new FuncType {
            returnType = GetInstanceType(node.returnType, true),
            argTypes = node.argDefs.ConvertAll(arg => GetInstanceType(arg.type, false))
        };

        return null;
    }
Example #5
0
        public override Exit visitFuncDef(FuncDef func, Environment env)
        {
            Environment funcEnv = new Environment();
            Exit        exit    = this.analyze(func.body, funcEnv);

            if (exit.HasFlag(Exit.NORMALLY))
            {
                func.exitsNormally = true;
                if (!func.symbol.type.ReturnType.IsVoid)
                {
                    log.error(func.Pos, messages.missingReturnStatement);
                }
            }

            return(0);
        }
Example #6
0
            public override object visitFuncDef(FuncDef func, WritableScope enclScope)
            {
                FuncSymbol fsym = makeFuncSymbol(func, enclScope);

                if (enclScope == symtab.topLevelSymbol.topScope && func.name == "main")
                {
                    mainFuncFound = true;
                    check.checkMainFunction(func.Pos, fsym);
                }

                if (check.checkUnique(func.Pos, fsym, enclScope))
                {
                    enclScope.enter(fsym);
                }
                return(null);
            }
Example #7
0
        /* The slow way of computing a sinc for the table. Should improve that some day */
        private static short sinc(float cutoff, float x, int N, FuncDef window_func)
        {
            /*fprintf (stderr, "%f ", x);*/
            float xx = x * cutoff;

            if (Math.Abs(x) < 1e-6f)
            {
                return(WORD2INT(32768.0f * cutoff));
            }
            else if (Math.Abs(x) > .5f * N)
            {
                return(0);
            }
            /*FIXME: Can it really be any slower than this? */
            return(WORD2INT(32768.0f * cutoff * (float)Math.Sin((float)Math.PI * xx) / ((float)Math.PI * xx) * (float)compute_func(Math.Abs(2.0f * x / N), window_func)));
        }
Example #8
0
        /*
        ** Called by the parser to compile an ATTACH statement.
        **
        **     ATTACH p AS pDbname KEY pKey
        */
        private static void sqlite3Attach(Parse pParse, Expr p, Expr pDbname, Expr pKey)
        {
            var attach_func = new FuncDef(
                3,               /* nArg */
                SQLITE_UTF8,     /* iPrefEnc */
                0,               /* flags */
                null,            /* pUserData */
                null,            /* pNext */
                attachFunc,      /* xFunc */
                null,            /* xStep */
                null,            /* xFinalize */
                "sqlite_attach", /* zName */
                null             /* pHash */
                );

            codeAttach(pParse, SQLITE_ATTACH, attach_func, p, p, pDbname, pKey);
        }
    public override Null Visit(FuncDef node)
    {
        // Forbid default arguments for the moment
        foreach (VarDef arg in node.argDefs) {
            if (arg.value != null) {
                log.ErrorDefaultArgNotAllowed(arg.location);
            }
        }

        // Validate the presence of the function body
        if (node.info.inExternal != (node.block == null)) {
            log.ErrorFunctionBody(node.location, node.info.inExternal);
        }

        base.Visit(node);
        return null;
    }
Example #10
0
        public Object Functions(string name, IEval evaluator)
        {
            Object ret = BaseFunctions != null?BaseFunctions(name, evaluator) : new StringParser.ConvertError("() not recognised");

            StringParser.ConvertError ce = ret as StringParser.ConvertError;

            if (ce != null && ce.ErrorValue.Contains("() not recognised"))
            {
                if (functions.ContainsKey(name))
                {
                    FuncDef fd = functions[name];

                    bool hasparas = fd.parameters.Length > 0;

                    if (hasparas)
                    {
                        IEvalParaListType[] plist = new IEvalParaListType[fd.parameters.Length];
                        plist = Enumerable.Repeat(IEvalParaListType.All, fd.parameters.Length).ToArray();

                        List <Object> paras = evaluator.Parameters(name, fd.parameters.Length, plist);
                        if (paras == null)              // if error, stop and return error
                        {
                            return(evaluator.Value);
                        }

                        symbols.Push();
                        for (int i = 0; i < fd.parameters.Length; i++)          // add to symbol list on next level the parameter names and values
                        {
                            System.Diagnostics.Debug.WriteLine(symbols.Levels + " " + name + " Push " + fd.parameters[i] + "=" + paras[i]);
                            symbols.Add(fd.parameters[i], paras[i]);
                        }
                    }

                    Eval   evfunc = (Eval)evaluator.Clone();                    // we need a fresh one just to evaluate this, but with the same configuration
                    Object res    = evfunc.Evaluate(fd.funcdef);                // and evaluate

                    if (hasparas)
                    {
                        symbols.Pop();                                          // clear back stack..
                    }
                    return(res);
                }
            }

            return(ret);
        }
Example #11
0
        /*
        ** Called by the parser to compile a DETACH statement.
        **
        **     DETACH pDbname
        */
        private static void sqlite3Detach(Parse pParse, Expr pDbname)
        {
            var detach_func = new FuncDef(
                1,               /* nArg */
                SQLITE_UTF8,     /* iPrefEnc */
                0,               /* flags */
                null,            /* pUserData */
                null,            /* pNext */
                detachFunc,      /* xFunc */
                null,            /* xStep */
                null,            /* xFinalize */
                "sqlite_detach", /* zName */
                null             /* pHash */
                );

            codeAttach(pParse, SQLITE_DETACH, detach_func, pDbname, null, null, pDbname);
        }
Example #12
0
        public void AddFuncDef(string fname, string prms, long line)
        {
            fname       = fname.Trim();
            currentFunc = fname;

            if (funcDefs.ContainsKey(fname))
            {
                funcDefs[fname].doubleDefined = true;
                funcDefs[fname].startingLine  = line;
            }
            else
            {
                FuncDef fd = new FuncDef();
                fd.name         = fname;
                fd.paramNr      = prms.Split(',').Length;
                fd.startingLine = line;
                funcDefs.Add(fname, fd);
            }
        }
Example #13
0
        public static void FuncDefInsert(FuncDefHash hash, FuncDef def)
        {
            int     nameLength = def.Name.Length;
            int     h          = (char.ToLowerInvariant(def.Name[0]) + nameLength) % hash.data.Length;
            FuncDef other      = FunctionSearch(hash, h, def.Name, nameLength);

            if (other != null)
            {
                Debug.Assert(other != def && other.Next != def);
                def.Next   = other.Next;
                other.Next = def;
            }
            else
            {
                def.Next = null;
                def.Hash = hash[h];
                hash[h]  = def;
            }
        }
Example #14
0
            private FuncSymbol makeFuncSymbol(FuncDef func, WritableScope enclScope)
            {
                FuncSymbol fsym = new FuncSymbol(func.name, enclScope.owner, null);

                func.symbol = fsym;

                fsym.owner = enclScope.owner;

                // create scope for func parameters and local variables
                WritableScope funcScope = enclScope.subScope(fsym);

                fsym.scope = funcScope;

                fsym.parameters = new List <VarSymbol>(func.parameters.Count);
                FuncType ftype = signature(func.returnType, func.parameters, funcScope);

                ftype.symbol = fsym;
                fsym.type    = ftype;
                return(fsym);
            }
Example #15
0
        /*8,24,40,56,80,104,128,160,200,256,320*/
        private static double compute_func(float x, FuncDef func)
        {
            float  y, frac;
            double interp0, interp1, interp2, interp3;
            int    ind;

            y    = x * func.oversample;
            ind  = (int)Math.Floor(y);
            frac = (y - ind);
            /* CSE with handle the repeated powers */
            interp3 = -0.1666666667 * frac + 0.1666666667 * (frac * frac * frac);
            interp2 = frac + 0.5 * (frac * frac) - 0.5 * (frac * frac * frac);
            /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac;*/
            interp0 = -0.3333333333 * frac + 0.5 * (frac * frac) - 0.1666666667 * (frac * frac * frac);
            /* Just to make sure we don't have rounding problems */
            interp1 = 1.0f - interp3 - interp2 - interp0;

            /*sum = frac*accum[1] + (1-frac)*accum[2];*/
            return(interp0 * func.table[ind] + interp1 * func.table[ind + 1] + interp2 * func.table[ind + 2] + interp3 * func.table[ind + 3]);
        }
Example #16
0
        public override Type visitStructDef(StructDef structDef, Environment env)
        {
            Environment newEnv = new Environment {
                scope      = new CompoundScope(structDef.symbol.membersScope, env.scope),
                parent     = env,
                enclStruct = structDef.symbol
            };

            for (var i = 0; i < structDef.members.Count; i++)
            {
                Tree member = structDef.members[i];
                if (member.Tag == Tag.FUNC_DEF)
                {
                    FuncDef funcDef = (FuncDef)member;
                    visitFuncDef(funcDef, newEnv);
                }
            }

            return(null);
        }
Example #17
0
        public string CheckForErrors()
        {
            string retval = "";

            foreach (string fname in funcDefs.Keys)
            {
                FuncDef fd = funcDefs[fname];
                if (fd.doubleDefined)
                {
                    retval += "Line " + fd.startingLine + ": Function '" + fname + "' already defined\n";
                }

                foreach (string vn in fd.varsUsage.Keys)
                {
                    if (!fd.vars.ContainsKey(vn))
                    {
                        retval += "Line " + fd.startingLine + ": Using undefined variable '" + vn + "'\n";
                    }
                    else if (fd.vars[vn].line > fd.varsUsage[vn].line)
                    {
                        retval += "Line " + fd.startingLine + ": Using variable '" + vn + "' before it is actualy defined\n";
                    }
                }
            }

            foreach (FuncDef fd in funcCalls)
            {
                if (!funcDefs.ContainsKey(fd.name))
                {
                    retval += "Line " + fd.startingLine + ": Calling undefined function '" + fd.name + "'\n";
                }
                else if (fd.paramNr != funcDefs[fd.name].paramNr)
                {
                    retval += "Line " + fd.startingLine + ": Calling function '" + fd.name + "' with wrong number of parameters\n";
                }
            }

            return(retval);
        }
Example #18
0
        public static RC MemFinalize(Mem mem, FuncDef func)
        {
            RC rc = RC.OK;

            if (C._ALWAYS(func != null && func.Finalize != null))
            {
                Debug.Assert((mem.Flags & MEM.Null) != 0 || func == mem.u.Def);
                Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
                //memset(&ctx, 0, sizeof(ctx));
                FuncContext ctx = new FuncContext();
                ctx.S.Flags = MEM.Null;
                ctx.S.Ctx   = mem.Ctx;
                ctx.Mem     = mem;
                ctx.Func    = func;
                func.Finalize(ctx);              // IMP: R-24505-23230
                Debug.Assert((mem.Flags & MEM.Dyn) == 0 && mem.Del == null);
                C._tagfree(mem.Ctx, ref mem.Z_); //: mem->Malloc);
                ctx.S._memcpy(ref mem);
                rc = ctx.IsError;
            }
            return(rc);
        }
Example #19
0
        private void FuncHead(ref FuncDef function)
        {
            string first = "id int float";

            this.SkipErrors(first);

            var    lookaheadToken = this.TokenStream.Peek();
            string lookahead      = lookaheadToken.AToCCFormat();

            if (first.HasToken(lookahead))
            {
                this.ApplyDerivation("funcHead -> type optSR_AndID '(' fParams ')'");

                function.ReturnType = Type();
                var(scopeResolution, functionName) = OptSR_AndID();
                function.ScopeResolution           = scopeResolution;
                function.FunctionName = functionName;
                Match("(");
                function.Parameters = FParams();
                Match(")");
            }
        }
        public override void Visit(FuncDef funcDef)
        {
            string funcName = funcDef.FunctionName;

            if (funcDef.ScopeResolution != null)
            {
                funcName = $"{funcDef.ScopeResolution.ID}::{funcName}";
            }

            var entry = new TableEntry(funcName, Classification.Function, -1);

            entry.Link = new SymbolTable();

            if (funcDef.Parameters != null)
            {
                foreach (var param in funcDef.Parameters)
                {
                    entry.Link.Add(param.Entry, param.Location);
                }
            }

            if (funcDef.Implementation?.Table != null)
            {
                foreach (var varEntry in funcDef.Implementation.Table.GetAll())
                {
                    entry.Link.Add(varEntry, funcDef.Implementation.Location);
                }
            }

            entry.Type = funcDef.ReturnType + "-";
            if (funcDef.Parameters != null)
            {
                entry.Type += string.Join(",", funcDef.Parameters.Where(val => val.Id != string.Empty).Select(val => val.Type + "[]".Repeat(val.Dimensions.Count)));
            }
            funcDef.Entry = entry;
        }
Example #21
0
        /*
        ** Insert a new FuncDef into a FuncDefHash hash table.
        */
        static void sqlite3FuncDefInsert(
            FuncDefHash pHash, /* The hash table into which to insert */
            FuncDef pDef       /* The function definition to insert */
            )
        {
            FuncDef pOther;
            int     nName = sqlite3Strlen30(pDef.zName);
            u8      c1    = (u8)pDef.zName[0];
            int     h     = (sqlite3UpperToLower[c1] + nName) % ArraySize(pHash.a);

            pOther = functionSearch(pHash, h, pDef.zName, nName);
            if (pOther != null)
            {
                Debug.Assert(pOther != pDef && pOther.pNext != pDef);
                pDef.pNext   = pOther.pNext;
                pOther.pNext = pDef;
            }
            else
            {
                pDef.pNext = null;
                pDef.pHash = pHash.a[h];
                pHash.a[h] = pDef;
            }
        }
Example #22
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);
        }
Example #23
0
 static int sqlite3VdbeMemFinalize (MemRef pMem, FuncDef pFunc) {
     return sqlite3VdbeMemFinalize(ref pMem.inner, pFunc);
 }
Example #24
0
/*
** If the input FuncDef structure is ephemeral, then free it.  If
** the FuncDef is not ephermal, then do nothing.
*/
static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
  if( ALWAYS(pDef) && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){
    sqlite3DbFree(db, pDef);
  }
}
Example #25
0
    /*
    ** Locate a user function given a name, a number of arguments and a flag
    ** indicating whether the function prefers UTF-16 over UTF-8.  Return a
    ** pointer to the FuncDef structure that defines that function, or return
    ** NULL if the function does not exist.
    **
    ** If the createFlag argument is true, then a new (blank) FuncDef
    ** structure is created and liked into the "db" structure if a
    ** no matching function previously existed.  When createFlag is true
    ** and the nArg parameter is -1, then only a function that accepts
    ** any number of arguments will be returned.
    **
    ** If createFlag is false and nArg is -1, then the first valid
    ** function found is returned.  A function is valid if either xFunc
    ** or xStep is non-zero.
    **
    ** If createFlag is false, then a function with the required name and
    ** number of arguments may be returned even if the eTextRep flag does not
    ** match that requested.
    */

    static FuncDef sqlite3FindFunction(
    sqlite3 db,           /* An open database */
    string zName,         /* Name of the function.  Not null-terminated */
    int nName,            /* Number of characters in the name */
    int nArg,             /* Number of arguments.  -1 means any number */
    u8 enc,              /* Preferred text encoding */
    u8 createFlag       /* Create new entry if true and does not otherwise exist */
    )
    {
      FuncDef p;            /* Iterator variable */
      FuncDef pBest = null; /* Best match found so far */
      int bestScore = 0;
      int h;              /* Hash value */

      Debug.Assert( enc == SQLITE_UTF8 || enc == SQLITE_UTF16LE || enc == SQLITE_UTF16BE );
      h = ( sqlite3UpperToLower[(u8)zName[0]] + nName ) % ArraySize( db.aFunc.a );


      /* First search for a match amongst the application-defined functions.
      */
      p = functionSearch( db.aFunc, h, zName, nName );
      while ( p != null )
      {
        int score = matchQuality( p, nArg, enc );
        if ( score > bestScore )
        {
          pBest = p;
          bestScore = score;

        }
        p = p.pNext;
      }


      /* If no match is found, search the built-in functions.
      **
      ** If the SQLITE_PreferBuiltin flag is set, then search the built-in
      ** functions even if a prior app-defined function was found.  And give
      ** priority to built-in functions.
      **
      ** Except, if createFlag is true, that means that we are trying to
      ** install a new function.  Whatever FuncDef structure is returned it will
      ** have fields overwritten with new information appropriate for the
      ** new function.  But the FuncDefs for built-in functions are read-only.
      ** So we must not search for built-ins when creating a new function.
      */
      if ( 0 == createFlag && ( pBest == null || ( db.flags & SQLITE_PreferBuiltin ) != 0 ) )
      {
#if SQLITE_OMIT_WSD
FuncDefHash pHash = GLOBAL( FuncDefHash, sqlite3GlobalFunctions );
#else
        FuncDefHash pHash = sqlite3GlobalFunctions;
#endif
        bestScore = 0;
        p = functionSearch( pHash, h, zName, nName );
        while ( p != null )
        {
          int score = matchQuality( p, nArg, enc );
          if ( score > bestScore )
          {
            pBest = p;
            bestScore = score;
          }
          p = p.pNext;
        }
      }

      /* If the createFlag parameter is true and the search did not reveal an
      ** exact match for the name, number of arguments and encoding, then add a
      ** new entry to the hash table and return it.
      */
      if ( createFlag != 0 && ( bestScore < 6 || pBest.nArg != nArg ) &&
      ( pBest = new FuncDef() ) != null )
      { //sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
        //pBest.zName = (char *)&pBest[1];
        pBest.nArg = (i16)nArg;
        pBest.iPrefEnc = enc;
        pBest.zName = zName; //memcpy(pBest.zName, zName, nName);
        //pBest.zName[nName] = 0;
        sqlite3FuncDefInsert( db.aFunc, pBest );
      }

      if ( pBest != null && ( pBest.xStep != null || pBest.xFunc != null || createFlag != 0 ) )
      {
        return pBest;
      }
      return null;
    }
Example #26
0
 /* During the search for the best function definition, this procedure
 ** is called to test how well the function passed as the first argument
 ** matches the request for a function with nArg arguments in a system
 ** that uses encoding enc. The value returned indicates how well the
 ** request is matched. A higher value indicates a better match.
 **
 ** The returned value is always between 0 and 6, as follows:
 **
 ** 0: Not a match, or if nArg<0 and the function is has no implementation.
 ** 1: A variable arguments function that prefers UTF-8 when a UTF-16
 **    encoding is requested, or vice versa.
 ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is
 **    requested, or vice versa.
 ** 3: A variable arguments function using the same text encoding.
 ** 4: A function with the exact number of arguments requested that
 **    prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
 ** 5: A function with the exact number of arguments requested that
 **    prefers UTF-16LE when UTF-16BE is requested, or vice versa.
 ** 6: An exact match.
 **
 */
 static int matchQuality( FuncDef p, int nArg, int enc )
 {
   int match = 0;
   if ( p.nArg == -1 || p.nArg == nArg
   || ( nArg == -1 && ( p.xFunc != null || p.xStep != null ) )
   )
   {
     match = 1;
     if ( p.nArg == nArg || nArg == -1 )
     {
       match = 4;
     }
     if ( enc == p.iPrefEnc )
     {
       match += 2;
     }
     else if ( ( enc == SQLITE_UTF16LE && p.iPrefEnc == SQLITE_UTF16BE ) ||
     ( enc == SQLITE_UTF16BE && p.iPrefEnc == SQLITE_UTF16LE ) )
     {
       match += 1;
     }
   }
   return match;
 }
 public override Null Visit(FuncDef node)
 {
     // Don't initialize arguments
     node.block.Accept(this);
     return null;
 }
Example #28
0
 /*
 ** Invoke the destructor function associated with FuncDef p, if any. Except,
 ** if this is not the last copy of the function, do not invoke it. Multiple
 ** copies of a single function are created when create_function() is called
 ** with SQLITE_ANY as the encoding.
 */
 static void functionDestroy( sqlite3 db, FuncDef p )
 {
   FuncDestructor pDestructor = p.pDestructor;
   if ( pDestructor != null )
   {
     pDestructor.nRef--;
     if ( pDestructor.nRef == 0 )
     {
       //pDestructor.xDestroy( pDestructor.pUserData );
       sqlite3DbFree( db, ref pDestructor );
     }
   }
 }
 public override Null Visit(FuncDef node)
 {
     // Make a new end node to start off the flow
     FlowNode root = new FlowNode();
     nodeMap.Add(node, root);
     next.Set(root);
     node.block.Accept(this);
     for (int i = node.argDefs.Count - 1; i >= 0; i--) {
         node.argDefs[i].Accept(this);
     }
     roots.Add(next.Get());
     return null;
 }
Example #30
0
        private double EvaluateBuiltInFunction(ref int position, FuncDef kind, int nbParams, double[] param, Stack <int> returnStack, Stack <double> valueStack)
        {
            switch (kind)
            {
            // each element equal to the first
            case FuncDef.Equal:
                if (nbParams < 2)
                {
                    throw new Exception("equals ( = ) must have at least two things to compare");
                }
                return(NanTags.EncodeBool(ListEquals(param)));

            // Each element smaller than the last
            case FuncDef.GreaterThan:
                if (nbParams < 2)
                {
                    throw new Exception("greater than ( > ) must have at least two things to compare");
                }
                return(NanTags.EncodeBool(FoldGreaterThan(param)));

            // Each element larger than the last
            case FuncDef.LessThan:
                if (nbParams < 2)
                {
                    throw new Exception("less than ( < ) must have at least two things to compare");
                }
                return(NanTags.EncodeBool(FoldLessThan(param)));

            // Each element DIFFERENT TO THE FIRST (does not check set uniqueness!)
            case FuncDef.NotEqual:
                if (nbParams < 2)
                {
                    throw new Exception("not-equal ( <> ) must have at least two things to compare");
                }
                return(NanTags.EncodeBool(!ListEquals(param)));

            case FuncDef.Assert:
                if (nbParams < 1)
                {
                    return(NanTags.VoidReturn());                  // assert nothing passes
                }
                var condition = param.ElementAt(0);
                if (_memory.CastBoolean(condition) == false)
                {
                    var msg = ConcatList(param, 1);
                    throw new Exception("Assertion failed: " + msg);
                }
                return(NanTags.VoidReturn());

            case FuncDef.Random:
                if (nbParams < 1)
                {
                    return(rnd.NextDouble());                  // 0 params - any size
                }
                if (nbParams < 2)
                {
                    return(rnd.Next(_memory.CastInt(param.ElementAt(0))));                                  // 1 param  - max size
                }
                return(rnd.Next(_memory.CastInt(param.ElementAt(0)), _memory.CastInt(param.ElementAt(1)))); // 2 params - range

            case FuncDef.Eval:
                var reader      = new SourceCodeTokeniser();
                var statements  = _memory.CastString(param.ElementAt(0));
                var programTmp  = reader.Read(statements, false);
                var bin         = ToNanCodeCompiler.CompileRoot(programTmp, false);
                var interpreter = new ByteCodeInterpreter();
                interpreter.Init(new RuntimeMemoryModel(bin, _memory.Variables), _input, _output, DebugSymbols);
                return(interpreter.Execute(false, _runningVerbose, false).Result);

            case FuncDef.Call:
                NanTags.DecodePointer(param.ElementAt(0), out var target, out var type);
                if (type != DataType.PtrString && type != DataType.PtrStaticString)
                {
                    throw new Exception("Tried to call a function by name, but passed a '" + type + "' at " + position);
                }
                // this should be a string, but we need a function name hash -- so calculate it:
                var strName          = _memory.DereferenceString(target);
                var functionNameHash = NanTags.GetCrushedName(strName);
                nbParams--;
                var newParam = param.Skip(1).ToArray();
                return(EvaluateFunctionCall(ref position, functionNameHash, nbParams, newParam, returnStack, valueStack));

            case FuncDef.LogicNot:
                if (nbParams != 1)
                {
                    throw new Exception("'not' should be called with one argument");
                }
                var bval = _memory.CastBoolean(param.ElementAt(0));
                return(NanTags.EncodeBool(!bval));

            case FuncDef.LogicOr:
            {
                bool more = nbParams > 0;
                int  i    = 0;
                while (more)
                {
                    var bresult = _memory.CastBoolean(param.ElementAt(i));
                    if (bresult)
                    {
                        return(NanTags.EncodeBool(true));
                    }

                    i++;
                    more = i < nbParams;
                }

                return(NanTags.EncodeBool(false));
            }

            case FuncDef.LogicAnd:
            {
                bool more = nbParams > 0;
                int  i    = 0;
                while (more)
                {
                    var bresult = _memory.CastBoolean(param.ElementAt(i));
                    if (!bresult)
                    {
                        return(NanTags.EncodeBool(false));
                    }

                    i++;
                    more = i < nbParams;
                }

                return(NanTags.EncodeBool(true));
            }

            case FuncDef.ReadKey:
                return(_memory.StoreStringAndGetReference(((char)_input.Read()).ToString()));

            case FuncDef.ReadLine:
                return(_memory.StoreStringAndGetReference(_input.ReadLine()));

            case FuncDef.Print:
            {
                string lastStr = null;
                foreach (var v in param)
                {
                    lastStr = _memory.CastString(v);
                    _output.Write(lastStr);
                }

                if (lastStr != "")
                {
                    _output.WriteLine();
                }
            }
                return(NanTags.VoidReturn());

            case FuncDef.Substring:
                if (nbParams == 2)
                {
                    var newString = _memory.CastString(param.ElementAt(0)).Substring(_memory.CastInt(param.ElementAt(1)));
                    return(_memory.StoreStringAndGetReference(newString));
                }
                else if (nbParams == 3)
                {
                    int start  = _memory.CastInt(param.ElementAt(1));
                    int length = _memory.CastInt(param.ElementAt(2));

                    string s = _memory.CastString(param.ElementAt(0)).Substring(start, length);
                    return(_memory.StoreStringAndGetReference(s));
                }
                else
                {
                    throw new Exception("'Substring' should be called with 2 or 3 parameters");
                }

            case FuncDef.Length:
                return(_memory.CastString(param.ElementAt(0)).Length);

            case FuncDef.Replace:
                if (nbParams != 3)
                {
                    throw new Exception("'Replace' should be called with 3 parameters");
                }
                string exp      = _memory.CastString(param.ElementAt(0));
                string oldValue = _memory.CastString(param.ElementAt(1));
                string newValue = _memory.CastString(param.ElementAt(2));
                exp = exp.Replace(oldValue, newValue);
                return(_memory.StoreStringAndGetReference(exp));

            case FuncDef.Concat:
                var builder = new StringBuilder();

                foreach (var v in param)
                {
                    builder.Append(_memory.CastString(v));
                }

                return(_memory.StoreStringAndGetReference(builder.ToString()));

            case FuncDef.UnitEmpty:
            {         // valueless marker (like an empty object)
                return(NanTags.EncodeNonValue(NonValueType.Unit));
            }


            case FuncDef.MathAdd:
                if (nbParams == 1)
                {
                    return(param[0]);
                }
                return(param.ChainSum());

            case FuncDef.MathSub:
                if (nbParams == 1)
                {
                    return(-param[0]);
                }
                return(param.ChainDifference());

            case FuncDef.MathProd:
                if (nbParams == 1)
                {
                    throw new Exception("Uniary '*' is not supported");
                }
                return(param.ChainProduct());

            case FuncDef.MathDiv:
                if (nbParams == 1)
                {
                    throw new Exception("Uniary '/' is not supported");
                }
                return(param.ChainDivide());

            case FuncDef.MathMod:
                if (nbParams == 1)
                {
                    return(param[0] % 2);
                }
                return(param.ChainRemainder());

            default:
                throw new Exception("Unrecognised built-in! Type = " + ((int)kind));
            }
        }
    public override Null Visit(FuncDef node)
    {
        inFunc = true;
        base.Visit(node);
        inFunc = false;

        // Check for a return value (flow must not reach the end of non-void functions)
        if (node.block != null && !(node.symbol.type.ReturnType() is VoidType) && builder.nodeMap[node].knowledge != null) {
            log.ErrorNotAllPathsReturnValue(node.location);
        }

        return null;
    }
Example #32
0
 public static FuncInfo Create(FuncDef fd, SolverAliases aliasOf)
 {
     return(CreateWithCachingInfo(fd, aliasOf, null));
 }
Example #33
0
        FuncInfo(FuncDef fd, SolverAliases aliasOf, string cachingDomainParam = null)
        {
            name    = fd.name;
            this.fd = fd;
            if (cachingDomainParam != null && fd.cachingExpiration != TimeSpan.Zero)
            {
                nCachingInps = 1;
                inputs       = new string[fd.argsInfo.Length + nCachingInps];
                int k = 0;
                inputs[k++] = cachingDomainParam;
                foreach (var arg in fd.argsInfo)
                {
                    inputs[k++] = arg.ToString();
                }
            }
            else
            {
                inputs = new string[fd.argsInfo.Length];
                for (int i = 0; i < inputs.Length; i++)
                {
                    var s = fd.argsInfo[i].ToString();
                    inputs[i] = aliasOf.GetRealName(s);
                }
            }
            int no = fd.resultsInfo.Length;

            outputs = new string[no];
            var pureOuts = new List <string>(no);
            var inOuts   = new List <string>(no);

            for (int i = 0; i < outputs.Length; i++)
            {
                var s    = fd.resultsInfo[i].ToString();
                var real = aliasOf.GetRealName(s);
                if (real != s && !inputs.Contains(real))
                {
                    if (fd.kind != FuncKind.Macro)
                    {
                        throw new SolverException(string.Format("Name conflict between alias '{0}' and output of function '{1}'", s, name));
                    }
                }
                outputs[i] = real;
            }
            foreach (var s in outputs)
            {
                if (Array.IndexOf <string>(inputs, s) < 0)
                {
                    pureOuts.Add(s);
                }
                else
                {
                    System.Diagnostics.Debug.Assert(ValueInfo.IsID(s), $"Only _ID parameters can be 'in/out' // {name}:{s}");
                    inOuts.Add(s);
                }
            }
            var pureIns = new List <string>(no);

            for (int i = 0; i < inputs.Length; i++)
            {
                var s = inputs[i];
                if (Array.IndexOf <string>(outputs, s) < 0)
                {
                    pureIns.Add(s);
                }
            }

            this.pureIns  = pureIns.ToArray();
            this.pureOuts = pureOuts.ToArray();
            this.inOuts   = inOuts.ToArray();
        }
Example #34
0
 //FUNCDEF
 static int sqlite3VdbeAddOp4( Vdbe p, int op, int p1, int p2, int p3, FuncDef pP4, int p4type )
 {
   union_p4 _p4 = new union_p4();
   _p4.pFunc = pP4;
   int addr = sqlite3VdbeAddOp3( p, op, p1, p2, p3 );
   sqlite3VdbeChangeP4( p, addr, _p4, p4type );
   return addr;
 }
Example #35
0
 public void ChangeP4(int addr, CollSeq coll, int n) { ChangeP4(addr, new P4_t { Coll = coll }, n); } // P4_COLLSEQ 
 public void ChangeP4(int addr, FuncDef func, int n) { ChangeP4(addr, new P4_t { Func = func }, n); } // P4_FUNCDEF
Example #36
0
 /*
 ** If the input FuncDef structure is ephemeral, then free it.  If
 ** the FuncDef is not ephermal, then do nothing.
 */
 static void freeEphemeralFunction( sqlite3 db, FuncDef pDef )
 {
   if ( ALWAYS( pDef ) && ( pDef.flags & SQLITE_FUNC_EPHEM ) != 0 )
   {
     pDef = null;
     sqlite3DbFree( db, ref pDef );
   }
 }
Example #37
0
 /*
 ** Called by the parser to compile a DETACH statement.
 **
 **     DETACH pDbname
 */
 static void sqlite3Detach( Parse pParse, Expr pDbname )
 {
   FuncDef detach_func = new FuncDef(
   1,                   /* nArg */
   SQLITE_UTF8,         /* iPrefEnc */
   0,                   /* flags */
   null,                /* pUserData */
   null,                /* pNext */
   detachFunc,          /* xFunc */
   null,                /* xStep */
   null,                /* xFinalize */
   "sqlite_detach",     /* zName */
   null                 /* pHash */
   );
   codeAttach( pParse, SQLITE_DETACH, detach_func, pDbname, null, null, pDbname );
 }
Example #38
0
    /*
    ** The first parameter (pDef) is a function implementation.  The
    ** second parameter (pExpr) is the first argument to this function.
    ** If pExpr is a column in a virtual table, then let the virtual
    ** table implementation have an opportunity to overload the function.
    **
    ** This routine is used to allow virtual table implementations to
    ** overload MATCH, LIKE, GLOB, and REGEXP operators.
    **
    ** Return either the pDef argument (indicating no change) or a
    ** new FuncDef structure that is marked as ephemeral using the
    ** SQLITE_FUNC_EPHEM flag.
    */
    static FuncDef sqlite3VtabOverloadFunction(
      sqlite3 db,    /* Database connection for reporting malloc problems */
      FuncDef pDef,  /* Function to possibly overload */
      int nArg,      /* Number of arguments to the function */
      Expr pExpr     /* First argument to the function */
    )
    {
      Table pTab;
      sqlite3_vtab pVtab;
      sqlite3_module pMod;
      dxFunc xFunc = null;//void (*xFunc)(sqlite3_context*,int,sqlite3_value*) = 0;
      object pArg = null;
      FuncDef pNew;
      int rc = 0;
      string zLowerName;
      string z;

      /* Check to see the left operand is a column in a virtual table */
      if ( NEVER( pExpr == null ) )
        return pDef;
      if ( pExpr.op != TK_COLUMN )
        return pDef;
      pTab = pExpr.pTab;
      if ( NEVER( pTab == null ) )
        return pDef;
      if ( ( pTab.tabFlags & TF_Virtual ) == 0 )
        return pDef;
      pVtab = sqlite3GetVTable( db, pTab ).pVtab;
      Debug.Assert( pVtab != null );
      Debug.Assert( pVtab.pModule != null );
      pMod = (sqlite3_module)pVtab.pModule;
      if ( pMod.xFindFunction == null )
        return pDef;

      /* Call the xFindFunction method on the virtual table implementation
      ** to see if the implementation wants to overload this function
      */
      zLowerName = pDef.zName;//sqlite3DbStrDup(db, pDef.zName);
      if ( zLowerName != null )
      {
        //for(z=(unsigned char)zLowerName; *z; z++){
        //  *z = sqlite3UpperToLower[*z];
        //}
        rc = pMod.xFindFunction( pVtab, nArg, zLowerName.ToLowerInvariant(), ref xFunc, ref pArg );
        sqlite3DbFree( db, ref zLowerName );
      }
      if ( rc == 0 )
      {
        return pDef;
      }

      /* Create a new ephemeral function definition for the overloaded
      ** function */
      //sqlite3DbMallocZero(db, sizeof(*pNew)
      //      + sqlite3Strlen30(pDef.zName) + 1);
      //if ( pNew == null )
      //{
      //  return pDef;
      //}
      pNew = pDef.Copy();
      pNew.zName = pDef.zName;
      //pNew.zName = (char )&pNew[1];
      //memcpy(pNew.zName, pDef.zName, sqlite3Strlen30(pDef.zName)+1);
      pNew.xFunc = xFunc;
      pNew.pUserData = pArg;
      pNew.flags |= SQLITE_FUNC_EPHEM;
      return pNew;
    }
Example #39
0
 /*
 ** Called by the parser to compile an ATTACH statement.
 **
 **     ATTACH p AS pDbname KEY pKey
 */
 static void sqlite3Attach( Parse pParse, Expr p, Expr pDbname, Expr pKey )
 {
   FuncDef attach_func = new FuncDef(
   3,                /* nArg */
   SQLITE_UTF8,      /* iPrefEnc */
   0,                /* flags */
   null,             /* pUserData */
   null,             /* pNext */
   attachFunc,       /* xFunc */
   null,             /* xStep */
   null,             /* xFinalize */
   "sqlite_attach",  /* zName */
   null              /* pHash */
   );
   codeAttach( pParse, SQLITE_ATTACH, attach_func, p, p, pDbname, pKey );
 }
        public override void Visit(FuncDef funcDef)
        {
            // We don't need to handle free-functions.
            if (funcDef.ScopeResolution == null)
            {
                return;
            }

            // Make sure the class exists.
            var classScope = this.GlobalScope.Get($"{funcDef.ScopeResolution.ID}-{Classification.Class}");

            if (classScope != null)
            {
                // Make sure the function exists.
                var function = classScope.Link.Get($"{funcDef.FunctionName}-{Classification.Function}");
                if (function != null)
                {
                    // Get the return type and the parameters.
                    var types      = function.Type.Split('-');
                    var returnType = types[0];
                    var parameters = types[1].Length == 0 ? new string[0] : types[1].Split(',');

                    // Make sure the return type matches with the number of parameters
                    if (funcDef.ReturnType == returnType)
                    {
                        if (funcDef.Parameters.Count == parameters.Count())
                        {
                            bool valid = true;

                            // Make sure each parameter matches.
                            for (int i = 0; i < funcDef.Parameters.Count; i++)
                            {
                                string expectedType = parameters[i];
                                string receivedType = funcDef.Parameters[i].Type + "[]".Repeat(funcDef.Parameters[i].Dimensions.Count);

                                if (expectedType == string.Empty)
                                {
                                    expectedType = "no parameters";
                                }
                                if (receivedType == string.Empty)
                                {
                                    receivedType = "no parameters";
                                }

                                // Apply pseudo type checking.
                                if (expectedType != receivedType)
                                {
                                    ErrorManager.Add($"Invalid parameter type: Expected {expectedType}, got {receivedType}", funcDef.Parameters[i].Location);
                                    valid = false;
                                    break;
                                }
                            }

                            if (valid)
                            {
                                function.Link = funcDef.Entry.Link;
                            }
                        }
                        else
                        {
                            ErrorManager.Add($"Invalid amount of parameters. Expected {parameters.Length}. Got {funcDef.Parameters.Count}.", funcDef.Location);
                        }
                    }
                    else
                    {
                        ErrorManager.Add($"Invalid return type: Expected {returnType}, got {funcDef.ReturnType}", funcDef.Location);
                    }
                }
                else
                {
                    ErrorManager.Add($"The class {funcDef.ScopeResolution.ID} does not define a function {funcDef.FunctionName}.", funcDef.Location);
                }
            }
            else
            {
                ErrorManager.Add($"The class {funcDef.ScopeResolution.ID} could not be resolved to a type.", funcDef.ScopeResolution.Location);
            }
        }
Example #41
0
        public static BaseTree Parse(List <IElement> sourceTokens, ScriptFile sf, ScriptInfo scriptInfo)
        {
            BaseTree tree = new BaseTree(sourceTokens);

            tree._sf = sf;

            MoveInfo parser = new MoveInfo(tree, SearchTree.ChildrenBlock, 0, sf);

            ParsingInfo parsingInfo = new ParsingInfo(sf);

            // parse all groups
            MoveInfo groupInfo = new MoveInfo(tree, SearchTree.ContentTree, 0, sf);
            IElement cur       = groupInfo.Find(SearchDirection.LeftToRight, SearchVisibility.Visible);

            while (cur != null)
            {
                Group.Check(groupInfo, parsingInfo, scriptInfo);
                cur = groupInfo.FindNextBlack(SearchDirection.LeftToRight);
            }

            // parse delegate call [[delegate]]
            MoveInfo delegateInfo = new MoveInfo(tree, SearchTree.ContentTree, 0, sf);

            cur = delegateInfo.Find(SearchDirection.LeftToRight, SearchVisibility.Visible);
            while (cur != null)
            {
                DelegateCallGroup.Check(delegateInfo, parsingInfo, scriptInfo);
                cur = delegateInfo.FindNextBlack(SearchDirection.LeftToRight);
            }

            // create parse tree
            MoveInfo contentInfo = new MoveInfo(parser);

            cur = contentInfo.Current;
            while (cur != null)
            {
                if (!cur.Visible)
                {
                    XMLBlock.Check(contentInfo, parsingInfo, scriptInfo);

                    cur = contentInfo.Move(SearchDirection.LeftToRight);
                }
                else
                {
                    if (DevCode.Check(contentInfo, parsingInfo, scriptInfo) ||
                        PreProcessorInclude.Check(contentInfo, parsingInfo, scriptInfo) ||
                        PreProcessorRegion.Check(contentInfo, parsingInfo, scriptInfo) ||
                        AccessModifier.Check(contentInfo, parsingInfo, scriptInfo) ||
                        SealedModifier.Check(contentInfo, parsingInfo, scriptInfo) ||
                        UsingDef.Check(contentInfo, parsingInfo, scriptInfo) ||
                        OverwriteConstDef.Check(contentInfo, parsingInfo, scriptInfo) ||
                        FuncDef.Check(contentInfo, parsingInfo, scriptInfo) ||
                        ConstDef.Check(contentInfo, parsingInfo, scriptInfo)
                        )
                    {
                        cur = contentInfo.Move(SearchDirection.LeftToRight);
                    }
                    else
                    {
                        throw new SyntaxException("Unknown token", contentInfo.GetErrorInfo());
                    }
                }
            }

            tree.IncludeDefList        = parsingInfo.IncludeDefList;
            tree.FuncDefList           = parsingInfo.FuncDefList;
            tree.ConstDefList          = parsingInfo.ConstDefList;
            tree.UsingDefList          = parsingInfo.UsingDefList;
            tree.OverwriteConstDefList = parsingInfo.OverwriteConstDefList;

            return(tree);
        }
Example #42
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 );
}
Example #43
0
 static void FreeEphemeralFunction(Context ctx, FuncDef def)
 {
     if (C._ALWAYS(def != null) && (def.Flags & FUNC.EPHEM) != 0)
         C._tagfree(ctx, ref def);
 }
Example #44
0
 public override Null Visit(FuncDef node)
 {
     // Special-case void types for return types
     if (node.returnType is TypeExpr && ((TypeExpr)node.returnType).type is VoidType) {
         node.returnType.computedType = new MetaType { instanceType = ((TypeExpr)node.returnType).type };
     } else {
         node.returnType.Accept(this);
     }
     VisitAll(node.argDefs);
     if (node.block != null) {
         node.block.Accept(this);
     }
     return null;
 }
Example #45
0
        static RantFuncs()
        {
            F = new Dictionary <string, FuncDef>(StringComparer.InvariantCultureIgnoreCase);

            // Repeaters, probability, and block attributes
            F["rep"]      = F["r"] = new FuncSig(Repeat, ParamFlags.None);
            F["sep"]      = F["s"] = new FuncSig(Separator, ParamFlags.Code);
            F["before"]   = new FuncSig(Before, ParamFlags.Code);
            F["after"]    = new FuncSig(After, ParamFlags.Code);
            F["chance"]   = new FuncSig(Chance, ParamFlags.None);
            F["break"]    = new FuncSig(Break);
            F["repnum"]   = F["rn"] = new FuncSig(RepNum);
            F["repindex"] = F["ri"] = new FuncSig(RepIndex);
            F["repcount"] = F["rc"] = new FuncSig(RepCount);

            // Synchronizers
            F["sync"] = F["x"] = new FuncDef(
                new FuncSig(SyncCreateApply, ParamFlags.None, ParamFlags.None),
                new FuncSig(SyncApply, ParamFlags.None)
                );
            F["xreset"] = new FuncSig(SyncReset, ParamFlags.None);
            F["xseed"]  = new FuncSig(SyncReseed, ParamFlags.None, ParamFlags.None);
            F["xnone"]  = new FuncSig(Desync);
            F["xnew"]   = new FuncSig(SyncCreate, ParamFlags.None, ParamFlags.None);
            F["xpin"]   = new FuncSig(Pin, ParamFlags.None);
            F["xunpin"] = new FuncSig(Unpin, ParamFlags.None);
            F["xstep"]  = new FuncSig(Step, ParamFlags.None);

            // RNG manipulation
            F["branch"] = F["b"] = new FuncDef(
                new FuncSig(Branch, ParamFlags.None),
                new FuncSig(BranchScope, ParamFlags.None, ParamFlags.Code)
                );
            F["merge"]      = F["m"] = new FuncSig(Merge);
            F["generation"] = F["g"] = new FuncDef(new FuncSig(Generation), new FuncSig(GenerationSet, ParamFlags.None));

            // Repeater conditionals
            F["first"]     = new FuncSig(First, ParamFlags.Code);
            F["last"]      = new FuncSig(Last, ParamFlags.Code);
            F["middle"]    = new FuncSig(Middle, ParamFlags.Code);
            F["notfirst"]  = new FuncSig(NotFirst, ParamFlags.Code);
            F["notlast"]   = new FuncSig(NotLast, ParamFlags.Code);
            F["notmiddle"] = new FuncSig(NotMiddle, ParamFlags.Code);
            F["odd"]       = new FuncSig(Odd, ParamFlags.Code);
            F["even"]      = new FuncSig(Even, ParamFlags.Code);
            F["nth"]       = new FuncDef(
                new FuncSig(Nth, ParamFlags.None, ParamFlags.None, ParamFlags.Code),
                new FuncSig(NthSimple, ParamFlags.None, ParamFlags.Code)
                );

            // Quantifier conditionals
            F["alt"] = new FuncSig(Alt, ParamFlags.Code, ParamFlags.Code);
            F["any"] = new FuncSig(Any, ParamFlags.Code, ParamFlags.Code);

            // Replacers
            F["match"] = new FuncSig(ReplaceMatch);
            F["group"] = new FuncSig(ReplaceGroup, ParamFlags.None);

            // Subrotuine interaction
            F["arg"] = new FuncSig(Arg, ParamFlags.None);

            // Formatting
            F["numfmt"]    = new FuncSig(NumFmt, ParamFlags.None);
            F["caps"]      = F["case"] = new FuncSig(Caps, ParamFlags.None); // TODO: [caps] is deprecated. Remove it eventually.
            F["capsinfer"] = new FuncSig(CapsInfer, ParamFlags.None);

            // Channels
            F["out"]   = new FuncSig(Out, ParamFlags.None, ParamFlags.None);
            F["close"] = new FuncSig(Close, ParamFlags.None);

            // External interaction
            F["extern"] = F["ext"] = new FuncSig(Extern, ParamFlags.None, ParamFlags.Multi);

            // Markers and targets
            F["mark"]  = new FuncSig(Mark, ParamFlags.None);
            F["dist"]  = new FuncSig(Dist, ParamFlags.None, ParamFlags.None);
            F["get"]   = new FuncSig(Get, ParamFlags.None);
            F["send"]  = new FuncSig(Send, ParamFlags.None, ParamFlags.None);
            F["osend"] = new FuncSig(SendOverwrite, ParamFlags.None, ParamFlags.None);
            F["clrt"]  = new FuncSig(ClearTarget, ParamFlags.None);

            // String generation, manipulation, and analysis
            F["len"]  = new FuncSig(Length, ParamFlags.None);
            F["char"] = new FuncDef(
                new FuncSig(Character, ParamFlags.None),
                new FuncSig(CharacterMulti, ParamFlags.None, ParamFlags.None));
            F["num"] = F["n"] = new FuncSig(Number, ParamFlags.None, ParamFlags.None);
            F["dec"] = new FuncSig(NumberDec);

            // Flags
            F["define"] = new FuncSig(DefineFlag, ParamFlags.None | ParamFlags.Multi);
            F["undef"]  = new FuncSig(UndefineFlag, ParamFlags.None | ParamFlags.Multi);
            F["ifdef"]  = new FuncSig(IfDef, ParamFlags.None, ParamFlags.Code);
            F["ifndef"] = new FuncSig(IfNDef, ParamFlags.None, ParamFlags.Code);
            F["else"]   = new FuncSig(Else, ParamFlags.Code);

            // Comparisons
            F["cmp"] = new FuncSig(Compare, ParamFlags.None, ParamFlags.None, ParamFlags.Code);
            F["is"]  = new FuncSig(CmpIs, ParamFlags.None, ParamFlags.Code);

            // Misc
            F["src"] = new FuncSig(Src);
        }
Example #46
0
 /*
 ** Insert a new FuncDef into a FuncDefHash hash table.
 */
 static void sqlite3FuncDefInsert(
 FuncDefHash pHash,  /* The hash table into which to insert */
 FuncDef pDef        /* The function definition to insert */
 )
 {
   FuncDef pOther;
   int nName = sqlite3Strlen30( pDef.zName );
   u8 c1 = (u8)pDef.zName[0];
   int h = ( sqlite3UpperToLower[c1] + nName ) % ArraySize( pHash.a );
   pOther = functionSearch( pHash, h, pDef.zName, nName );
   if ( pOther != null )
   {
     Debug.Assert( pOther != pDef && pOther.pNext != pDef );
     pDef.pNext = pOther.pNext;
     pOther.pNext = pDef;
   }
   else
   {
     pDef.pNext = null;
     pDef.pHash = pHash.a[h];
     pHash.a[h] = pDef;
   }
 }
Example #47
0
 public void Add(string name, string[] plist, string f)
 {
     functions[name] = new FuncDef(name, plist, f);
 }
Example #48
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 = pAuthArg->u.zToken;
                if (NEVER(zAuthArg == 0))
                {
                    goto attach_end;
                }
                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);
        }
Example #49
0
        /// <summary>
        /// This procedure generates VDBE code for a single invocation of either the
        /// sqlite_detach() or sqlite_attach() SQL user functions.
        /// </summary>
        /// <param name='pParse'>
        /// The parser context
        /// </param>
        /// <param name='type'>
        /// Either SQLITE_ATTACH or SQLITE_DETACH
        /// </param>
        /// <param name='pFunc'>
        /// FuncDef wrapper for detachFunc() or attachFunc()
        /// </param>
        /// <param name='pAuthArg'>
        /// Expression to pass to authorization callback 
        /// </param>
        /// <param name='pFilename'>
        /// Name of database file
        /// </param>
        /// <param name='pDbname'>
        /// Name of the database to use internally
        /// </param>
        /// <param name='pKey'>
        /// Database key for encryption extension
        /// </param>
        static void codeAttach(
		Parse pParse,
		int type,
		FuncDef pFunc,
		Expr pAuthArg,
		Expr pFilename,
		Expr pDbname,
		Expr pKey
		)
        {
            NameContext sName;
            Vdbe v;
            sqlite3 db = pParse.db;
            int regArgs;

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

            if (
            SQLITE_OK != (resolveAttachExpr(sName, pFilename)) ||
            SQLITE_OK != (resolveAttachExpr(sName, pDbname)) ||
            SQLITE_OK != (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);
        }
Example #50
0
        /*
        ** The first parameter (pDef) is a function implementation.  The
        ** second parameter (pExpr) is the first argument to this function.
        ** If pExpr is a column in a virtual table, then let the virtual
        ** table implementation have an opportunity to overload the function.
        **
        ** This routine is used to allow virtual table implementations to
        ** overload MATCH, LIKE, GLOB, and REGEXP operators.
        **
        ** Return either the pDef argument (indicating no change) or a
        ** new FuncDef structure that is marked as ephemeral using the
        ** SQLITE_FUNC_EPHEM flag.
        */
        static FuncDef sqlite3VtabOverloadFunction(
            sqlite3 db,   /* Database connection for reporting malloc problems */
            FuncDef pDef, /* Function to possibly overload */
            int nArg,     /* Number of arguments to the function */
            Expr pExpr    /* First argument to the function */
            )
        {
            Table          pTab;
            sqlite3_vtab   pVtab;
            sqlite3_module pMod;
            dxFunc         xFunc = null;//void (*xFunc)(sqlite3_context*,int,sqlite3_value*) = 0;
            object         pArg  = null;
            FuncDef        pNew;
            int            rc = 0;
            string         zLowerName;
            string         z;

            /* Check to see the left operand is a column in a virtual table */
            if (NEVER(pExpr == null))
            {
                return(pDef);
            }
            if (pExpr.op != TK_COLUMN)
            {
                return(pDef);
            }
            pTab = pExpr.pTab;
            if (NEVER(pTab == null))
            {
                return(pDef);
            }
            if ((pTab.tabFlags & TF_Virtual) == 0)
            {
                return(pDef);
            }
            pVtab = sqlite3GetVTable(db, pTab).pVtab;
            Debug.Assert(pVtab != null);
            Debug.Assert(pVtab.pModule != null);
            pMod = (sqlite3_module)pVtab.pModule;
            if (pMod.xFindFunction == null)
            {
                return(pDef);
            }

            /* Call the xFindFunction method on the virtual table implementation
            ** to see if the implementation wants to overload this function
            */
            zLowerName = pDef.zName;//sqlite3DbStrDup(db, pDef.zName);
            if (zLowerName != null)
            {
                //for(z=(unsigned char)zLowerName; *z; z++){
                //  *z = sqlite3UpperToLower[*z];
                //}
                rc = pMod.xFindFunction(pVtab, nArg, zLowerName.ToLowerInvariant(), ref xFunc, ref pArg);
                sqlite3DbFree(db, ref zLowerName);
            }
            if (rc == 0)
            {
                return(pDef);
            }

            /* Create a new ephemeral function definition for the overloaded
            ** function */
            //sqlite3DbMallocZero(db, sizeof(*pNew)
            //      + sqlite3Strlen30(pDef.zName) + 1);
            //if ( pNew == null )
            //{
            //  return pDef;
            //}
            pNew       = pDef.Copy();
            pNew.zName = pDef.zName;
            //pNew.zName = (char )&pNew[1];
            //memcpy(pNew.zName, pDef.zName, sqlite3Strlen30(pDef.zName)+1);
            pNew.xFunc     = xFunc;
            pNew.pUserData = pArg;
            pNew.flags    |= SQLITE_FUNC_EPHEM;
            return(pNew);
        }
Example #51
0
 public void Defun(FuncBase func)
 {
     FuncDef def;
     if (!m_func.TryGetValue(func.Name.ID, out def))
     {
         def = new FuncDef(func);
         m_func.Add(def.ID, def);
     }
     else
         def.Overload(func);
 }        
Example #52
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);
        }
Example #53
0
 //P4_FUNCDEF
 static void sqlite3VdbeChangeP4( Vdbe p, int addr, FuncDef pFunc, int n )
 {
   union_p4 _p4 = new union_p4();
   _p4.pFunc = pFunc;
   sqlite3VdbeChangeP4( p, addr, _p4, n );
 }
Example #54
0
 public static RC MemFinalize(Mem mem, FuncDef func)
 {
     RC rc = RC.OK;
     if (C._ALWAYS(func != null && func.Finalize != null))
     {
         Debug.Assert((mem.Flags & MEM.Null) != 0 || func == mem.u.Def);
         Debug.Assert(mem.Ctx == null || MutexEx.Held(mem.Ctx.Mutex));
         //memset(&ctx, 0, sizeof(ctx));
         FuncContext ctx = new FuncContext();
         ctx.S.Flags = MEM.Null;
         ctx.S.Ctx = mem.Ctx;
         ctx.Mem = mem;
         ctx.Func = func;
         func.Finalize(ctx); // IMP: R-24505-23230
         Debug.Assert((mem.Flags & MEM.Dyn) == 0 && mem.Del == null);
         C._tagfree(mem.Ctx, ref mem.Z_); //: mem->Malloc);
         ctx.S._memcpy(ref mem);
         rc = ctx.IsError;
     }
     return rc;
 }
Example #55
0
        public static FuncDef OverloadFunction(Context ctx, FuncDef def, int argsLength, Expr expr)
        {
            // Check to see the left operand is a column in a virtual table
            if (C._NEVER(expr == null))
            {
                return(def);
            }
            if (expr.OP != TK.COLUMN)
            {
                return(def);
            }
            Table table = expr.Table;

            if (C._NEVER(table == null))
            {
                return(def);
            }
            if ((table.TabFlags & TF.Virtual) == 0)
            {
                return(def);
            }
            IVTable ivtable = GetVTable(ctx, table).IVTable;

            Debug.Assert(ivtable != null);
            Debug.Assert(ivtable.IModule != null);
            ITableModule imodule = (ITableModule)ivtable.IModule;

            if (imodule.FindFunction == null)
            {
                return(def);
            }

            // Call the xFindFunction method on the virtual table implementation to see if the implementation wants to overload this function
            string lowerName = def.Name;
            RC     rc        = RC.OK;
            Action <FuncContext, int, Mem[]> func = null;

            object[] args = null;
            if (lowerName != null)
            {
                lowerName = lowerName.ToLowerInvariant();
                rc        = imodule.FindFunction(ivtable, argsLength, lowerName, func, args);
                C._tagfree(ctx, ref lowerName);
            }
            if (rc == RC.OK)
            {
                return(def);
            }

            // Create a new ephemeral function definition for the overloaded function
            FuncDef newFunc = new FuncDef();//: (FuncDef*)_tagalloc(ctx, sizeof(FuncDef) + _strlen30(def->Name) + 1, true);

            if (newFunc == null)
            {
                return(def);
            }
            newFunc          = def._memcpy();
            newFunc.Name     = def.Name;
            newFunc.Func     = func;
            newFunc.UserData = args;
            newFunc.Flags   |= FUNC.EPHEM;
            return(newFunc);
        }
Example #56
0
        /*
        ** Locate a user function given a name, a number of arguments and a flag
        ** indicating whether the function prefers UTF-16 over UTF-8.  Return a
        ** pointer to the FuncDef structure that defines that function, or return
        ** NULL if the function does not exist.
        **
        ** If the createFlag argument is true, then a new (blank) FuncDef
        ** structure is created and liked into the "db" structure if a
        ** no matching function previously existed.  When createFlag is true
        ** and the nArg parameter is -1, then only a function that accepts
        ** any number of arguments will be returned.
        **
        ** If createFlag is false and nArg is -1, then the first valid
        ** function found is returned.  A function is valid if either xFunc
        ** or xStep is non-zero.
        **
        ** If createFlag is false, then a function with the required name and
        ** number of arguments may be returned even if the eTextRep flag does not
        ** match that requested.
        */

        static FuncDef sqlite3FindFunction(
            sqlite3 db,   /* An open database */
            string zName, /* Name of the function.  Not null-terminated */
            int nName,    /* Number of characters in the name */
            int nArg,     /* Number of arguments.  -1 means any number */
            u8 enc,       /* Preferred text encoding */
            u8 createFlag /* Create new entry if true and does not otherwise exist */
            )
        {
            FuncDef p;                /* Iterator variable */
            FuncDef pBest     = null; /* Best match found so far */
            int     bestScore = 0;
            int     h;                /* Hash value */

            Debug.Assert(enc == SQLITE_UTF8 || enc == SQLITE_UTF16LE || enc == SQLITE_UTF16BE);
            h = (sqlite3UpperToLower[(u8)zName[0]] + nName) % ArraySize(db.aFunc.a);


            /* First search for a match amongst the application-defined functions.
             */
            p = functionSearch(db.aFunc, h, zName, nName);
            while (p != null)
            {
                int score = matchQuality(p, nArg, enc);
                if (score > bestScore)
                {
                    pBest     = p;
                    bestScore = score;
                }
                p = p.pNext;
            }


            /* If no match is found, search the built-in functions.
            **
            ** If the SQLITE_PreferBuiltin flag is set, then search the built-in
            ** functions even if a prior app-defined function was found.  And give
            ** priority to built-in functions.
            **
            ** Except, if createFlag is true, that means that we are trying to
            ** install a new function.  Whatever FuncDef structure is returned it will
            ** have fields overwritten with new information appropriate for the
            ** new function.  But the FuncDefs for built-in functions are read-only.
            ** So we must not search for built-ins when creating a new function.
            */
            if (0 == createFlag && (pBest == null || (db.flags & SQLITE_PreferBuiltin) != 0))
            {
#if SQLITE_OMIT_WSD
                FuncDefHash pHash = GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
#else
                FuncDefHash pHash = sqlite3GlobalFunctions;
#endif
                bestScore = 0;
                p         = functionSearch(pHash, h, zName, nName);
                while (p != null)
                {
                    int score = matchQuality(p, nArg, enc);
                    if (score > bestScore)
                    {
                        pBest     = p;
                        bestScore = score;
                    }
                    p = p.pNext;
                }
            }

            /* If the createFlag parameter is true and the search did not reveal an
            ** exact match for the name, number of arguments and encoding, then add a
            ** new entry to the hash table and return it.
            */
            if (createFlag != 0 && (bestScore < 6 || pBest.nArg != nArg) &&
                (pBest = new FuncDef()) != null)
            { //sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
              //pBest.zName = (char *)&pBest[1];
                pBest.nArg     = (i16)nArg;
                pBest.iPrefEnc = enc;
                pBest.zName    = zName; //memcpy(pBest.zName, zName, nName);
                //pBest.zName[nName] = 0;
                sqlite3FuncDefInsert(db.aFunc, pBest);
            }

            if (pBest != null && (pBest.xStep != null || pBest.xFunc != null || createFlag != 0))
            {
                return(pBest);
            }
            return(null);
        }
Example #57
0
        /// <summary>
        /// Create definitions of loading functions from specified SQL query
        /// </summary>
        /// <param name="funcNamesPrefix">Optional prefix for functions names. If null or empty, first table from 'FROM' clause is used</param>
        /// <param name="actualityInDays">Used to restrict the minimum queried timestamp // :MIN_TIME = :BEG_TIME-actualityInDays</param>
        /// <param name="queryText">SQL query text. Only some subset of SQL is supported
        /// (all sources in FROM cluase must have aliases, all fields in SELECT must be specified with source aliases, subqueries is not tested, etc)</param>
        /// <returns>Enumeration of pairs (func_name, loading function definition)</returns>
        internal static IEnumerable <FuncDef> FuncDefsForSql(Preprocessing.SqlFuncPreprocessingCtx c)
        {
            var sql = SqlParse.Do(c.queryText, SqlExpr.Options.EmptyFromPossible);

            sql = c.PostProc(sql);

            if (sql == null)
            {
                yield break;
            }

            var actuality = TimeSpan.FromDays((c.actualityInDays < 0) ? Attr.defaultActualityDays : c.actualityInDays);

            if (string.IsNullOrEmpty(c.funcNamesPrefix))
            {
                c.funcNamesPrefix = sql.sources[0].expr.ToString();
            }
            // generate list of results
            bool timedQuery    = false;
            bool withSeparator = false;

            ValueInfo[] resultsInfo;
            {
                int n   = sql.results.Length;
                var lst = new List <ValueInfo>(n);
                for (int i = 0; i < n; i++)
                {
                    var d = sql.results[i].alias;//.ToUpperInvariant();
                    if (d == nameof(START_TIME))
                    {
                        timedQuery = timedQuery || i == 1;
                    }
                    else if (d == nameof(END_TIME) || d == nameof(END_TIME__DT))
                    {
                        //if (d.Length == nameof(END_TIME).Length)
                        //	timedQuery = timedQuery || i == 2;
                    }
                    else if (d == nameof(INS_OUTS_SEPARATOR))
                    {
                        withSeparator = true;
                    }
                    else
                    {
                        //if (d.Length > 30)
                        //    throw new Generator.Exception($"SQL identifier too long (max 30, but {d.Length} chars in \"{d}\")");
                        var vi = ValueInfo.Create(d, defaultLocation: c.DefaultLocationForValueInfo);
                        int DL = vi.DescriptorLength();
                        if (DL > 30)
                        {
                            throw new Generator.Exception($"SQL identifier too long (max 30, but {DL} chars in \"{vi}\")");
                        }
                        lst.Add(vi);
                    }
                }
                resultsInfo = lst.ToArray();
            }

            var dbConnName = c.tblAttrs.GetString(Attr.Tbl.DbConnName) ?? c.ldr.dbConnValueName;

            #region Some query with INS_OUTS_SEPARATOR column
            if (withSeparator || !timedQuery || (c.ldr.forKinds & DbFuncType.Raw) != 0)
            {   // separator column present
                string[] inputs, outputs;
                var      qt        = SqlQueryNonTimed(sql, c.arrayResults, dbConnName, out inputs, out outputs);
                Fn       func      = FuncNonTimedQuery(qt);
                var      colsNames = qt.colsNames.Where(s => s != nameof(START_TIME) && s != nameof(END_TIME) && s != nameof(END_TIME__DT)).ToList();
                for (int i = inputs.Length - 1; i >= 0; i--)
                {
                    if (!ValueInfo.IsID(inputs[i]))
                    {
                        colsNames.RemoveAt(i);
                    }
                }
                var fd = new FuncDef(func, c.funcNamesPrefix /* + "_Values"*/, inputs.Length, inputs.Length,
                                     ValueInfo.CreateMany(inputs),
                                     ValueInfo.CreateMany(colsNames.ToArray()),
                                     FuncFlags.Defaults, 0, 0, c.ldr.cachingExpiration, c.ldr.cacheSubdomain,
                                     c.tblAttrs.ToDictionary(p => p.Key.ToString(), p => p.Value)
                                     );
                fd.xtraAttrs.Add(nameof(QueryTemplate), qt);
                yield return(fd);

                yield break;
            }
            #endregion
            #region Range
            if ((c.ldr.forKinds & DbFuncType.TimeInterval) != 0)
            {
                var qt   = SqlQueryTimed(sql, DbFuncType.TimeInterval, c.arrayResults, dbConnName);
                Fn  func = FuncTimedRangeQuery(actuality, qt);
                var fd   = new FuncDef(func, c.funcNamesPrefix + "_Range", 3, 3,
                                       ValueInfo.CreateMany(qt.colsNames[0], nameof(ValueInfo.A_TIME__XT), nameof(ValueInfo.B_TIME__XT)),
                                       resultsInfo, FuncFlags.Defaults, 0, 0, c.ldr.cachingExpiration, c.ldr.cacheSubdomain,
                                       c.tblAttrs.ToDictionary(p => p.Key.ToString(), p => p.Value)
                                       );
                fd.xtraAttrs.Add(nameof(QueryTemplate), qt);
                yield return(fd);
            }
            #endregion
            #region Slice at AT_TIME
            if ((c.ldr.forKinds & DbFuncType.TimeSlice) != 0)
            {
                var qt   = SqlQueryTimed(sql, DbFuncType.TimeSlice, c.arrayResults, dbConnName);
                Fn  func = FuncTimedSliceQuery(actuality, qt);
                var fd   = new FuncDef(func, c.funcNamesPrefix + "_Slice", 2, 2,
                                       ValueInfo.CreateMany(qt.colsNames[0], nameof(ValueInfo.At_TIME__XT)),
                                       resultsInfo, FuncFlags.Defaults, 0, 0, c.ldr.cachingExpiration, c.ldr.cacheSubdomain,
                                       c.tblAttrs.ToDictionary(p => p.Key.ToString(), p => p.Value)
                                       );
                fd.xtraAttrs.Add(nameof(QueryTemplate), qt);
                yield return(fd);
            }
            #endregion
            #region Raw interval // START_TIME in range MIN_TIME .. MAX_TIME
            if ((c.ldr.forKinds & DbFuncType.TimeRawInterval) != 0)
            {
                var qt   = SqlQueryTimed(sql, DbFuncType.TimeRawInterval, c.arrayResults, dbConnName);
                Fn  func = FuncRawIntervalQuery(qt);
                var fd   = new FuncDef(func, c.funcNamesPrefix + "_Raw", 3, 3,
                                       ValueInfo.CreateMany(qt.colsNames[0], "MIN_TIME__XT", "MAX_TIME__XT"),
                                       resultsInfo, FuncFlags.Defaults, 0, 0, c.ldr.cachingExpiration, c.ldr.cacheSubdomain,
                                       c.tblAttrs.ToDictionary(p => p.Key.ToString(), p => p.Value)
                                       );
                fd.xtraAttrs.Add(nameof(QueryTemplate), qt);
                yield return(fd);
            }
            #endregion
            #region Insert rows function
            if ((c.ldr.forKinds & DbFuncType.Insert) != 0)
            {
                var qt = SqlCommandInsert(sql, dbConnName, c.DefaultLocationForValueInfo, out var outputs);
                //todo: Sql insert
                //Fn func = FuncInsert(qt);
            }
            #endregion
        }
Example #58
0
		/*
		** Memory cell pMem contains the context of an aggregate function.
		** This routine calls the finalize method for that function.  The
		** result of the aggregate is stored back into pMem.
		**
		** Return SQLITE_ERROR if the finalizer reports an error.  SQLITE_OK
		** otherwise.
		*/

		private static int sqlite3VdbeMemFinalize(Mem pMem, FuncDef pFunc)
		{
			int rc = SQLITE_OK;
			if (ALWAYS(pFunc != null && pFunc.xFinalize != null))
			{
				sqlite3_context ctx = new sqlite3_context();
				Debug.Assert((pMem.flags & MEM_Null) != 0 || pFunc == pMem.u.pDef);
				Debug.Assert(pMem.db == null || sqlite3_mutex_held(pMem.db.mutex));
				//memset(&ctx, 0, sizeof(ctx));
				ctx.s.flags = MEM_Null;
				ctx.s.db = pMem.db;
				ctx.pMem = pMem;
				ctx.pFunc = pFunc;
				pFunc.xFinalize(ctx); /* IMP: R-24505-23230 */
				Debug.Assert(0 == (pMem.flags & MEM_Dyn) && pMem.xDel == null);
				sqlite3DbFree(pMem.db, ref pMem.zBLOB);//zMalloc );
				ctx.s.CopyTo(ref pMem);//memcpy(pMem, &ctx.s, sizeof(ctx.s));
				rc = ctx.isError;
			}
			return rc;
		}
Example #59
0
 public int AddOp4(OP op, int p1, int p2, int p3, FuncDef p4, Vdbe.P4T p4t) // FUNCDEF
 {
     int addr = AddOp3(op, p1, p2, p3);
     ChangeP4(addr, new P4_t { Func = p4 }, p4t);
     return addr;
 }