private Sql.DmlDdlSqlStatement BuildStatement(string query, InputStringNormalizer stringNormalizer) { query = stringNormalizer.InputForLexer; var lexbuf = LexBuffer <char> .FromString(query); Func <LexBuffer <char>, SqlParser.token> func = (x) => SqlLexer.tokenize(x); return(SqlParser.startCT(FuncConvert.FromFunc(func), lexbuf)); }
public async Task <RowProvider> BuildExecutionTree(string queryText, ITransaction tran) { InputStringNormalizer stringNormalizer = new InputStringNormalizer(queryText); Sql.DmlDdlSqlStatement statement = BuildStatement(queryText, stringNormalizer); foreach (ISqlStatement handler in statementHandlers) { if (handler.ShouldExecute(statement)) { return(await handler.BuildTree(statement, tran, stringNormalizer)); } } throw new ArgumentException(); }
public static Func <RowHolder, bool> EvalWhere(Sql.where where, MetadataColumn[] metadataColumns, InputStringNormalizer stringNormalizer) { // TODO: This is all functional programming and nice // but I really doubt the perf. // Recursion + higher order functions is probably super slow... Func <RowHolder, bool> returnFilterFunc = null; returnFilterFunc = (rowHolder) => { if (where.IsAnd) { Sql.where.And andStmt = (Sql.where.And) where; Func <RowHolder, bool> leftOp = EvalWhere(andStmt.Item1, metadataColumns, stringNormalizer); Func <RowHolder, bool> rightOp = EvalWhere(andStmt.Item2, metadataColumns, stringNormalizer); return(leftOp(rowHolder) && rightOp(rowHolder)); } else if (where.IsOr) { Sql.where.Or orStmt = (Sql.where.Or) where; Func <RowHolder, bool> leftOp = EvalWhere(orStmt.Item1, metadataColumns, stringNormalizer); Func <RowHolder, bool> rightOp = EvalWhere(orStmt.Item2, metadataColumns, stringNormalizer); return(leftOp(rowHolder) || rightOp(rowHolder)); } else if (where.IsCond) { Sql.where.Cond condStmt = (Sql.where.Cond) where; Sql.value leftOp = stringNormalizer.ApplyReplacementTokens(condStmt.Item.Item1); Sql.op op = condStmt.Item.Item2; Sql.value rightOp = stringNormalizer.ApplyReplacementTokens(condStmt.Item.Item3); IComparable leftOpComp, rightOpComp; leftOpComp = ValToIComp(leftOp, ref metadataColumns, ref rowHolder); rightOpComp = ValToIComp(rightOp, ref metadataColumns, ref rowHolder); if (op.IsEq) { return(leftOpComp.CompareTo(rightOpComp) == 0); } else if (op.IsGe) { return(leftOpComp.CompareTo(rightOpComp) >= 0); } else if (op.IsGt) { return(leftOpComp.CompareTo(rightOpComp) > 0); } else if (op.IsLe) { return(leftOpComp.CompareTo(rightOpComp) <= 0); } else if (op.IsLt) { return(leftOpComp.CompareTo(rightOpComp) < 0); } } throw new InvalidProgramException("Invalid state."); }; return(returnFilterFunc); }
public Task <IPhysicalOperator <RowHolder> > BuildStatement(Sql.sqlStatement statement, ITransaction tran, IPhysicalOperator <RowHolder> source, InputStringNormalizer inputStringNormalizer) { if (FSharpOption <Sql.where> .get_IsSome(statement.Where)) { Sql.where whereStatement = statement.Where.Value; IPhysicalOperator <RowHolder> filterOp = new PhyOpFilter(source, FilterStatementBuilder.EvalWhere(whereStatement, source.GetOutputColumns(), inputStringNormalizer)); return(Task.FromResult(filterOp)); } else { return(Task.FromResult(source)); } }
public async Task <IPhysicalOperator <RowHolder> > BuildStatement(Sql.sqlStatement statement, ITransaction tran, IPhysicalOperator <RowHolder> source, InputStringNormalizer stringNormalizer) { if (source != null) { // For now source for scan must be null. // with subquery expression this will change. throw new ArgumentException(); } string tableName = statement.Table; MetadataTablesManager tableManager = metadataManager.GetTableManager(); MetadataTable table = await tableManager.GetByName(tableName, tran).ConfigureAwait(false); // Since we currently don't support indexes we can only build scan operation. return(new PhyOpScan(table.Collection, tran, table.Columns, table.TableName)); }
public async Task <RowProvider> BuildTree(Sql.DmlDdlSqlStatement statement, ITransaction tran, InputStringNormalizer _) { if (!statement.IsCreate) { throw new ArgumentException(); } Sql.DmlDdlSqlStatement.Create createStatement = (Sql.DmlDdlSqlStatement.Create)statement; string tableName = createStatement.Item.Table; var columns = createStatement.Item.ColumnList.ToList(); MetadataTablesManager tableManager = this.metadataManager.GetTableManager(); TableCreateDefinition tableCreateDefinition = new TableCreateDefinition(); tableCreateDefinition.TableName = tableName; tableCreateDefinition.ColumnNames = columns.Select(c => c.Item3).ToArray(); tableCreateDefinition.ColumnTypes = columns.Select(c => { if (c.Item1.IsDoubleCType) { return(new ColumnInfo(ColumnType.Double)); } else if (c.Item1.IsIntCType) { return(new ColumnInfo(ColumnType.Int)); } else if (c.Item1.IsStringCType) { if (c.Item2 > MAX_STRING_LENGTH) { throw new ArgumentException("String too big."); } return(new ColumnInfo(ColumnType.String, c.Item2)); } else { throw new ArgumentException(); } }).ToArray(); await tableManager.CreateObject(tableCreateDefinition, tran).ConfigureAwait(false); return(new RowProvider(TaskExtension.EmptyEnumerable <RowHolder>(), new MetadataColumn[0])); }
public Task <IPhysicalOperator <RowHolder> > BuildStatement(Sql.sqlStatement statement, ITransaction tran, IPhysicalOperator <RowHolder> source, InputStringNormalizer inputStringNormalizer) { Sql.columnSelect[] columns = new Sql.columnSelect[0]; Tuple <Sql.aggType, string>[] aggregates = new Tuple <Sql.aggType, string> [0]; if (!statement.Columns.IsStar) { columns = (((Sql.selectType.ColumnList)statement.Columns).Item).ToArray(); aggregates = columns .Where(c => c.IsAggregate == true) .Select(c => ((Sql.columnSelect.Aggregate)c).Item).ToArray(); } if (statement.GroupBy.Any() || aggregates.Any()) { string[] groupByColumns = statement.GroupBy.ToArray(); GroupByFunctors groupByFunctors = GroupByStatementBuilder.EvalGroupBy(groupByColumns, columns, source.GetOutputColumns()); IPhysicalOperator <RowHolder> phyOpGroupBy = new PhyOpGroupBy(source, groupByFunctors); return(Task.FromResult(phyOpGroupBy)); } else { return(Task.FromResult(source)); } }
public async Task <PhyOpTableInsert> ParseInsertStatement(Sql.insertStatement insertStatement, ITransaction tran, InputStringNormalizer stringNormalizer) { string tableName = insertStatement.Table; MetadataTablesManager tableManager = metadataManager.GetTableManager(); MetadataTable table = await tableManager.GetByName(tableName, tran).ConfigureAwait(false); ColumnInfo[] columnInfosFromTable = table.Columns.Select(mt => mt.ColumnType).ToArray(); RowHolder rowHolder = new RowHolder(columnInfosFromTable); int colNum = 0; foreach (var value in insertStatement.Values) { if (value.IsFloat) { if (columnInfosFromTable[colNum].ColumnType == ColumnType.Double) { rowHolder.SetField <double>(colNum, ((Sql.value.Float)value).Item); } else { throw new InvalidColumnTypeException(); } } else if (value.IsInt) { if (columnInfosFromTable[colNum].ColumnType == ColumnType.Int) { rowHolder.SetField <int>(colNum, ((Sql.value.Int)value).Item); } else if (columnInfosFromTable[colNum].ColumnType == ColumnType.Double) { // Int can be cast to double without data loss. rowHolder.SetField <double>(colNum, (double)((Sql.value.Int)value).Item); } else { throw new InvalidColumnTypeException(); } } else if (value.IsString) { if (columnInfosFromTable[colNum].ColumnType == ColumnType.String) { // TODO: For string heap (strings of variable length separate logic is needed. string input = ((Sql.value.String)value).Item; input = stringNormalizer.ApplyReplacementTokens(input); rowHolder.SetField(colNum, input.ToCharArray()); } else { throw new InvalidColumnTypeException(); } } else { throw new ArgumentException(); } colNum++; } PhyOpStaticRowProvider opStatic = new PhyOpStaticRowProvider(rowHolder); PhyOpTableInsert op = new PhyOpTableInsert(table.Collection, opStatic); return(op); }
public async Task <RowProvider> BuildTree(Sql.DmlDdlSqlStatement statement, ITransaction tran, InputStringNormalizer stringNormalizer) { if (!statement.IsSelect) { throw new ArgumentException(); } Sql.DmlDdlSqlStatement.Select selectStatement = ((Sql.DmlDdlSqlStatement.Select)statement); return(await this.treeBuilder.ParseSqlStatement(selectStatement.Item, tran, stringNormalizer).ConfigureAwait(false)); }
public async Task <RowProvider> ParseSqlStatement(Sql.sqlStatement sqlStatement, ITransaction tran, InputStringNormalizer stringNormalizer) { // TODO: query builder is currently manual. i.e. SCAN -> optional(JOINS) -> optional(FILTER) -> GROUP BY -> ORDER BY/PROJECT. // In future we need to build proper algebrizer, relational algebra rules and work on QO. IPhysicalOperator <RowHolder> source = null; foreach (IStatementTreeBuilder builder in this.statementBuildersList) { source = await builder.BuildStatement(sqlStatement, tran, source, stringNormalizer); } return(new RowProvider(source.Iterate(tran), source.GetOutputColumns())); }
public async Task <IPhysicalOperator <RowHolder> > BuildStatement(Sql.sqlStatement statement, ITransaction tran, IPhysicalOperator <RowHolder> source, InputStringNormalizer stringNormalizer) { if (statement.Joins.Any()) { IPhysicalOperator <RowHolder> currJoinSource = source; for (int i = 0; i < statement.Joins.Length; i++) { if (!statement.Joins[i].Item2.IsInner) { throw new NotSupportedException("Only inner join is supported at this point."); } MetadataTable joinRightTable = await this.metadataManager.GetTableManager().GetByName(statement.Joins[i].Item1, tran).ConfigureAwait(false); PhyOpScan scanOpRight = new PhyOpScan(joinRightTable.Collection, tran, joinRightTable.Columns, joinRightTable.TableName); Func <RowHolder, bool> filter = (_) => true; if (FSharpOption <Sql.where> .get_IsSome(statement.Joins[i].Item3)) { filter = FilterStatementBuilder.EvalWhere( statement.Joins[i].Item3.Value, QueryProcessingAccessors.MergeColumns(currJoinSource.GetOutputColumns(), scanOpRight.GetOutputColumns()), stringNormalizer); } currJoinSource = new PhyOpLoopInnerJoin(currJoinSource, scanOpRight, filter); } return(currJoinSource); } else { return(source); } }
public async Task <RowProvider> BuildTree(Sql.DmlDdlSqlStatement statement, ITransaction tran, InputStringNormalizer stringNormalizer) { if (!statement.IsInsert) { throw new ArgumentException(); } Sql.DmlDdlSqlStatement.Insert insertStatement = ((Sql.DmlDdlSqlStatement.Insert)statement); IPhysicalOperator <RowHolder> rootOp = await this.treeBuilder.ParseInsertStatement(insertStatement.Item, tran, stringNormalizer).ConfigureAwait(false); return(new RowProvider(rootOp.Iterate(tran), new MetadataColumn[0])); }
public Task <IPhysicalOperator <RowHolder> > BuildStatement(Sql.sqlStatement statement, ITransaction tran, IPhysicalOperator <RowHolder> source, InputStringNormalizer inputStringNormalizer) { if (statement.OrderBy.IsEmpty) { return(Task.FromResult(source)); } OrderByColumn[] orderByColumns = GetOrderByColumns(source.GetOutputColumns(), statement.OrderBy); IPhysicalOperator <RowHolder> phyOpOrderBy = new PhyOpOrderBy(source, new RowHolderOrderByComparer(orderByColumns)); return(Task.FromResult(phyOpOrderBy)); }
public Task <IPhysicalOperator <RowHolder> > BuildStatement(Sql.sqlStatement statement, ITransaction tran, IPhysicalOperator <RowHolder> source, InputStringNormalizer inputStringNormalizer) { Sql.columnSelect[] columns = new Sql.columnSelect[0]; bool isStar = false; string[] projections = new string[0]; if (statement.GroupBy.Any()) { // no job for me, this is group by. return(Task.FromResult(source)); } if (!statement.Columns.IsStar) { columns = (((Sql.selectType.ColumnList)statement.Columns).Item).ToArray(); if (columns.Any(c => c.IsAggregate == true)) { // No job for me, this is aggregation. return(Task.FromResult(source)); } projections = columns .Where(c => c.IsProjection == true) .Select(c => ((Sql.columnSelect.Projection)c).Item).ToArray(); } else { isStar = true; } int?topRows = null; if (FSharpOption <int> .get_IsSome(statement.Top)) { topRows = statement.Top.Value; if (topRows < 1) { throw new InvalidTopCountException(); } } if (isStar) { // no need for project, just return everything. IPhysicalOperator <RowHolder> projectOp = new PhyOpProject(source, topRows); return(Task.FromResult(projectOp)); } else { // Project Op. List <MetadataColumn> columnMapping = new List <MetadataColumn>(); foreach (string columnName in projections) { MetadataColumn mc = QueryProcessingAccessors.GetMetadataColumn(columnName, source.GetOutputColumns()); columnMapping.Add(mc); } IPhysicalOperator <RowHolder> projectOp = new PhyOpProject(source, columnMapping.Select(mc => mc.ColumnId).ToArray(), topRows); return(Task.FromResult(projectOp)); } }