示例#1
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);
        }
        public ITable EvaluateAggregate(QueryProcessor processor, bool distinct, ITable group, Expression[] args)
        {
            if (!function.IsAggregate)
                throw new InvalidOperationException("The function is not an aggregate.");

            try {
                // Execute it
                object[] funArgs;
                if (invokeType == 6) {
                    funArgs = new object[] { function.Name, processor, distinct, group, args };
                }
                    // The QueryProcessor, Expression[] construct
                else if (invokeType == 1) {
                    funArgs = new object[] { processor, distinct, group, args };
                } else {
                    throw new ApplicationException("Unknown invoke type");
                }

                return (ITable)method.Invoke(null, funArgs);
            } 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 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 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()));
        }
        public static ITable Avg(QueryProcessor processor, bool distinct, ITable group, Expression[] args)
        {
            // Aggregate function only can have 1 argument
            if (args.Length > 1)
                throw new ArgumentException("Only one argument permitted for SUM function.");

            return ProcessAggregate(processor, distinct, group, args, new AvgAggregateInspector());
        }
示例#6
0
        public void InitGroups(QueryProcessor processor, IIndex<long> emptyIndexContainer)
        {
            Debug.Assert(emptyIndexContainer.Count == 0);

            ITable child = BaseTable;
            // No groups, so make the entire child table the group,
            if (aggregateComposite == null || child.RowCount <= 1) {
                emptyIndexContainer.Add(0);
                emptyIndexContainer.Add(child.RowCount);
            }
                // Populate the index by the aggregate composite,
            else {
                // Create a resolver for the composite function
                IndexResolver resolver = processor.CreateResolver(child, aggregateComposite);

                // The groups state
                long groupPos = 0;
                long groupSize = 0;
                SqlObject[] lastComposite = null;
                // Scan over the child
                IRowCursor cursor = child.GetRowCursor();
                while (cursor.MoveNext()) {
                    RowId rowid = cursor.Current;
                    // Get the group term
                    SqlObject[] groupValue = resolver.GetValue(rowid);
                    if (lastComposite == null) {
                        lastComposite = groupValue;
                    } else {
                        int c = SqlObject.Compare(groupValue, lastComposite);
                        // If group_val > the last composite, we are on a new group
                        if (c > 0) {
                            // New group,
                            emptyIndexContainer.Add(groupPos);
                            emptyIndexContainer.Add(groupSize);
                            lastComposite = groupValue;
                            groupPos = groupPos + groupSize;
                            groupSize = 0;
                        } else if (c < 0) {
                            // This will happen if the child table is not sorted by the
                            // composite expression.
                            throw new ApplicationException("Aggregate child is not sorted correctly.");
                        }
                    }
                    ++groupSize;
                }
                // Final group
                // (the below check probably not necessary since we already check for the
                //  empty child so group size will always be >1 at this point).
                if (groupSize > 0) {
                    emptyIndexContainer.Add(groupPos);
                    emptyIndexContainer.Add(groupSize);
                }
            }
            // Set the group index
            childGroupsIndex = emptyIndexContainer;
            lookupCursor = BaseTable.GetRowCursor();
        }
示例#7
0
        public ExpressionTable(ITable child, QueryProcessor processor)
            : base(child)
        {
            // Make a copy of the processor
            this.processor = new QueryProcessor(processor);
            // Push the parent table onto the processor stack
            this.processor.PushTable(child);

            outputExps = new List<OutputExpression>();
            columns = new ExpressionColumnCollection(this);
        }
        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);
            }
        }
示例#9
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);
        }
示例#10
0
        public static ITable Count(QueryProcessor processor, bool distinct, ITable group, Expression[] args)
        {
            // Only 1 argument allowed
            if (args.Length > 1)
                throw new ArgumentException("Only one argument permitted for COUNT function.");

            // If the parameter is a function operation with name "star" then this is
            // a simple group size result
            Expression arg = args[0];
            if (arg.Type == ExpressionType.Function &&
                arg.GetArgument("name").Equals("star")) {
                return QueryProcessor.ResultTable(SqlObject.CastTo(group.RowCount, SqlType.Numeric));
            }

            // Otherwise, if this is a distinct,
            if (distinct) {
                group = processor.DistinctSubset(group, args);
                // The above process removes null values so we return the count,
                return QueryProcessor.ResultTable(SqlObject.CastTo(group.RowCount, SqlType.Numeric));
            }

            // Otherwise, we need to iterate through a count all none null values,
            return ProcessAggregate(processor, false, group, args, new CountAggregateInspector());
        }
示例#11
0
 internal QueryProcessor(QueryProcessor src)
 {
     transaction = src.transaction;
     tableStack = new List<ITable>(src.tableStack);
     rowIdStack = new List<RowId>(src.rowIdStack);
 }
示例#12
0
        private static IRowCursor QueryAllMatches(SystemTransaction transaction, TableName tableName, SystemTable table,
            IList<string> columns, SqlObject val)
        {
            // Try and find an index on these columns
            SystemIndexSetDataSource indexSet = transaction.FindIndexOn(tableName, columns);

            // If index found
            if (indexSet != null)
                // Query the index and find all matches
                return indexSet.Select(SelectableRange.Is(val));

            // Otherwise no index, so scan the table for matches

            // Make an Expression for the operation;
            //  (column1, column2, ...columnn) = val
            Expression compExp;
            int sz = columns.Count;
            if (sz > 1) {
                FunctionExpression cfunExp = new FunctionExpression("composite_fetch");
                for (int i = 0; i < sz; ++i) {
                    Expression varRef = new FetchVariableExpression(new Variable(tableName, columns[i]));
                    cfunExp.Parameters.Add(varRef);
                }
                compExp = cfunExp;
            } else if (sz == 1) {
                compExp = new FetchVariableExpression(new Variable(tableName, columns[0]));
            } else {
                throw new ApplicationException("Invalid columns list size");
            }

            // Equality test
            FunctionExpression funExp = new FunctionExpression("@is_sql");
            funExp.Parameters.Add(compExp);
            funExp.Parameters.Add(new FetchStaticExpression(val));

            // Create a query processor and perform the scan operation
            QueryProcessor processor = new QueryProcessor(transaction);
            ITable result = processor.FilterByScan(table, funExp);
            // Return the row cursor
            return result.GetRowCursor();
        }
示例#13
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);
            }
        }
示例#14
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();
        }
示例#15
0
 public static ITable AllLesserOrEqualThan(QueryProcessor processor, Expression[] args)
 {
     return NestedAllScan(processor, args[0], args[1], LesserOrEqualThan);
 }
示例#16
0
        public ITable EvaluateAggregate(QueryProcessor processor, bool distinct, ITable group, Expression[] args)
        {
            if (evalContext == null)
                throw new InvalidOperationException("Evaluation context was not set");

            return evalContext.EvaluateAggregate(processor, distinct, group, args);
        }
示例#17
0
 public static ITable CharLength(QueryProcessor processor, Expression[] args)
 {
     return Length(processor, args);
 }
示例#18
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));
        }
示例#19
0
 public QueryPlanner(SystemTransaction transaction)
 {
     this.transaction = transaction;
     random = new Random();
     simpleProcessor = new QueryProcessor(transaction);
 }
示例#20
0
 public static ITable AnyNotEqual(QueryProcessor processor, Expression[] args)
 {
     return NestedAnyScan(processor, args[0], args[1], NotEqual);
 }
示例#21
0
 public static ITable AnyLesserThan(QueryProcessor processor, Expression[] args)
 {
     return NestedAnyScan(processor, args[0], args[1], LesserThan);
 }
示例#22
0
 public static ITable AnyGreaterOrEqualThan(QueryProcessor processor, Expression[] args)
 {
     return NestedAnyScan(processor, args[0], args[1], GreaterOrEqualThan);
 }
示例#23
0
 public ExpressionIndexResolver(QueryProcessor processor, ITable table, 
     SqlType[] type, bool[] ascending_type, Expression[] column_ops)
 {
     this.processor = new QueryProcessor(processor);
     this.table = table;
     this.columnExps = column_ops;
     this.collationType = type;
     this.ascending = ascending_type;
     // Push the table onto the top of the processor
     this.processor.PushTable(this.table);
     // NOTE: we don't need to pop the table since we are using a processor
     //   that isn't shared with anything else.
 }
示例#24
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));
        }
示例#25
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);
 }
示例#26
0
        public ITable Evaluate(QueryProcessor processor, Expression[] args)
        {
            if (evalContext == null)
                throw new InvalidOperationException("Evaluation context was not set");

            return evalContext.Evaluate(processor, args);
        }
示例#27
0
 public QueryCostModel(SystemTransaction transaction)
 {
     this.transaction = transaction;
     processor = new QueryProcessor(transaction);
 }
示例#28
0
 public static ITable BitLength(QueryProcessor processor, Expression[] args)
 {
     SqlObject ob = QueryProcessor.Result(Length(processor, args))[0];
     SqlObject eight = new SqlObject(8L);
     return QueryProcessor.ResultTable(Add(new SqlObject[] { ob, eight }));
 }
示例#29
0
 public static ITable AllGreaterThan(QueryProcessor processor, Expression[] args)
 {
     return NestedAllScan(processor, args[0], args[1], GreaterThan);
 }