예제 #1
0
 public static ITable If(QueryProcessor processor, Expression[] args)
 {
     SqlObject[] conditional = QueryProcessor.Result(processor.Execute(args[0]));
     // If it evaluated to true,
     bool? b = conditional[0].Value.ToBoolean();
     return b != null && b == true ? processor.Execute(args[1]) : processor.Execute(args[2]);
 }
        public ITable Evaluate(QueryProcessor processor, Expression[] args)
        {
            // 'CAST' is a special case,
            if (function.Name.Equals("@cast")) {
                // Get the value to cast, and the type to cast it to,
                SqlObject val = QueryProcessor.Result(processor.Execute(args[0]))[0];
                SqlObject castType = QueryProcessor.Result(processor.Execute(args[1]))[0];

                string castTypeString = castType.Value.ToString();
                SqlType type = SqlType.Parse(castTypeString);

                // Do the cast,
                SqlObject result = val.CastTo(type);

                // And return the result,
                return QueryProcessor.ResultTable(result);
            }

            if (function.IsAggregate)
                throw new InvalidOperationException("The function is aggregate.");

            try {
                // Execute it
                if (invokeType == 6) {
                    object[] funArgs = { function.Name, processor, args };
                    return (ITable)method.Invoke(null, funArgs);
                }
                    // The QueryProcessor, Expression[] construct
                if (invokeType == 1) {
                    object[] funArgs = { processor, args };
                    return (ITable)method.Invoke(null, funArgs);
                }
                    // The SqlObject construct
                if (invokeType == 2) {
                    int sz = args.Length;
                    // Resolve the arguments into TypedValues
                    SqlObject[] obs = new SqlObject[sz];
                    for (int i = 0; i < sz; ++i) {
                        obs[i] = QueryProcessor.Result(processor.Execute(args[i]))[0];
                    }
                    // Set up the arguments and invoke the method
                    object[] funArgs = { obs };
                    SqlObject result = (SqlObject)method.Invoke(null, funArgs);
                    // Wrap on a FunctionTable and return
                    return QueryProcessor.ResultTable(result);
                }

                throw new ApplicationException("Unknown invoke type");
            } catch (MethodAccessException e) {
                throw new ApplicationException(e.Message, e);
            } catch (TargetInvocationException e) {
                throw new ApplicationException(e.InnerException.Message, e.InnerException);
            }
        }
예제 #3
0
        public static ITable GroupConcat(QueryProcessor processor, bool distinct, ITable group, Expression[] args)
        {
            // The output string
            StringBuilder return_string = new StringBuilder();

            // Find the distinct subset of group
            if (distinct)
                group = processor.DistinctSubset(group, args);

            // Push the group table onto the processor stack
            processor.PushTable(group);

            // Iterator over the group
            IRowCursor i = group.GetRowCursor();
            bool first = true;
            while (i.MoveNext()) {
                RowId rowid = i.Current;
                processor.UpdateTableRow(rowid);
                foreach (Expression op in args) {
                    ITable val = processor.Execute(op);
                    SqlObject ob = QueryProcessor.Result(val)[0];
                    if (!ob.IsNull) {
                        if (!first) {
                            return_string.Append(", ");
                        }
                        return_string.Append(SqlValue.FromObject(ob.Value).ToString());
                        first = false;
                    }
                }
            }

            // Pop the table and return the result
            processor.PopTable();
            return QueryProcessor.ResultTable(new SqlObject(return_string.ToString()));
        }
예제 #4
0
        public static ITable Least(QueryProcessor processor, Expression[] args)
        {
            SqlObject least = null;
            for (int i = 0; i < args.Length; ++i) {
                SqlObject ob = QueryProcessor.Result(processor.Execute(args[i]))[0];
                if (ob.IsNull)
                    return QueryProcessor.ResultTable(ob);

                if (least == null || SqlObject.Compare(ob, least) < 0)
                    least = ob;
            }

            return QueryProcessor.ResultTable(least);
        }
예제 #5
0
        internal static void SetInsertRowToDefault(SystemTransaction transaction, TableName table_name, IMutableTable table, RowId rowid)
        {
            // Get all column defaults on the table
            IList<object> table_defaults = transaction.QueryTableDefaults(table_name);
            int sz = table_defaults.Count / 2;
            // Exit quickly if there's no default values
            if (sz == 0)
                return;

            // Create a query processor
            QueryProcessor processor = new QueryProcessor(transaction);
            // For each default value,
            TableRow row = table.GetRow(rowid);
            for (int i = 0; i < sz; ++i) {
                string colName = (string)table_defaults[i * 2];
                Expression colDefault = (Expression)table_defaults[(i * 2) + 1];
                // Execute the default value expression
                ITable defaultResult = processor.Execute(colDefault);
                // Turn it into a TObject
                SqlObject val = defaultResult.GetValue(0, new RowId(0));
                // The col num of the column name
                int colIndex = table.Columns.IndexOf(colName);
                if (colIndex < 0)
                    throw new ApplicationException("Column '" + colName + "' not found for DEFAULT value");

                // And insert it
                row.SetValue(colIndex, val);
            }
        }
예제 #6
0
        public ITable Execute(Query query, Expression expression)
        {
            // Create the QueryProcessor
            QueryProcessor processor = new QueryProcessor(transaction);

            // If it's a select,
            if (expression is SelectExpression) {
                QueryOptimizer optimizer = new QueryOptimizer(transaction);
                expression = optimizer.SubstituteParameters(expression, query);
                expression = optimizer.Qualify(expression);
                expression = optimizer.Optimize(expression);

                // Execute the query,
                return processor.Execute(expression);
            }

            // Set the parameter as the base table, and the base rowid (the
            // parameters table only has 1 row).
            processor.PushTable(new QueryParametersTable(query));
            processor.UpdateTableRow(new RowId(0));

            // Otherwise it must be an interpretable function

            if (expression is FunctionExpression) {
                string fun_name = (string)expression.GetArgument("name");

                if (fun_name.Equals("create_table"))
                    return CreateTable(expression);
                /*
                TODO:
                if (fun_name.Equals("drop_table"))
                    return DropTable(processor, expression);
                if (fun_name.Equals("create_index"))
                    return CreateIndex(processor, expression);
                if (fun_name.Equals("drop_index"))
                    return DropIndex(processor, expression);
                if (fun_name.Equals("explain_expression"))
                    return ExplainExpression(expression);
                */
            }

            throw new NotSupportedException();
        }
예제 #7
0
        private static ITable ProcessAggregate(QueryProcessor processor, bool distinct, ITable group, Expression[] args, IAggregateInspector aggregator)
        {
            // Qualify the return type of the parameter
            SqlType type = processor.GetExpressionType(group, args[0]);

            // If an empty group
            if (group.RowCount == 0) {
                // Null return type if group is empty,
                return QueryProcessor.ResultTable(SqlObject.MakeNull(type));
            }

            // Find the distinct subset of group
            if (distinct)
                group = processor.DistinctSubset(group, args);

            // Push the group table onto the processor stack
            processor.PushTable(group);

            // Scan the group table, returning null on a null value
            IRowCursor i = group.GetRowCursor();

            while (i.MoveNext()) {
                RowId rowid = i.Current;
                processor.UpdateTableRow(rowid);
                ITable val = processor.Execute(args[0]);
                SqlObject ob = QueryProcessor.Result(val)[0];
                // If we hit a null value, we ignore it.  SQL-92 apparently says we
                // should generate a warning for nulls that are eliminated by set
                // functions.
                if (!ob.IsNull) {
                    aggregator.Accumulate(ob);
                }
            }

            // Pop the table and return the result
            processor.PopTable();
            SqlObject result = aggregator.Result();
            return QueryProcessor.ResultTable(result ?? SqlObject.MakeNull(type));
        }
예제 #8
0
        private static ITable NestedAnyScan(QueryProcessor processor, Expression leftExp, Expression rightExp, NestedEvaluate evaluate)
        {
            // Evaluate the left and right side of the operation
            ITable left = processor.Execute(leftExp);
            ITable right = processor.Execute(rightExp);
            // Turn left into a SqlObject
            SqlObject leftOb = QueryProcessor.Result(left)[0];
            // Scan right, return true on the first that's equal
            IRowCursor i = right.GetRowCursor();
            try {
                while (i.MoveNext()) {
                    RowId rowid = i.Current;
                    SqlObject scanVal = right.GetValue(0, rowid);
                    SqlObject[] args = new SqlObject[] { leftOb, scanVal };
                    SqlObject r = evaluate(args);
                    if (Equals(r, new SqlObject(true))) {
                        return QueryProcessor.ResultTable(new SqlObject(true));
                    }
                }
            } catch (AccessViolationException e) {
                throw new ApplicationException(e.Message, e);
            } catch (TargetInvocationException e) {
                throw new ApplicationException(e.InnerException.Message, e.InnerException);
            }

            return QueryProcessor.ResultTable(new SqlObject(false));
        }
예제 #9
0
 public static ITable Exists(QueryProcessor processor, Expression[] args)
 {
     // The nested expression to evaluate
     Expression nested_op = args[0];
     // Execute the nested operation,
     ITable result = processor.Execute(nested_op);
     // If there are elements, then 'exists' is true
     return QueryProcessor.ResultTable(result.RowCount > 0 ? SqlObject.True : SqlObject.False);
 }
예제 #10
0
        public static ITable Length(QueryProcessor processor, Expression[] args)
        {
            if (args.Length != 1)
                throw new ArgumentException("The function LENGTH accepts only 1 argument.");

            Expression arg = args[0];

            SqlObject resultLength;
            SqlObject obj = QueryProcessor.Result(processor.Execute(arg))[0];
            if (obj.IsNull) {
                resultLength = SqlObject.MakeNull(SqlType.Numeric);
            } else {
                int length;
                SqlType obType = obj.Type;
                SqlValue obValue = obj.Value;
                // If it's a string,
                if (obType.IsString) {
                    length = obValue.ToString().Length;
                }
                    // If it's a binary,
                else if (obType.IsBinary) {
                    length = obValue.Length - 1;
                }
                    // Otherwise, return null,
                else {
                    length = -1;
                }

                resultLength = length == -1 ? SqlObject.MakeNull(SqlType.Numeric) : new SqlObject((long) length);
            }

            return QueryProcessor.ResultTable(resultLength);
        }