示例#1
0
        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));
        }
示例#2
0
        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();
        }
示例#3
0
        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);
        }
示例#4
0
 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));
     }
 }
示例#5
0
        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));
        }
示例#6
0
        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]));
        }
示例#7
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));
            }
        }
示例#8
0
        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);
        }
示例#9
0
        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));
        }
示例#10
0
        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()));
        }
示例#11
0
        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);
            }
        }
示例#12
0
        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]));
        }
示例#13
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));
        }
示例#14
0
        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));
            }
        }