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 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(); }
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)); }