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