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(); }
public Expression OnAfterWalk(Expression expression) { if (expression is SelectExpression) { SelectExpression selectExp = (SelectExpression)expression; // Exiting select, we expand the select output list to a complete // form. int sz = selectExp.Output.Count; // Create a list of all forward referencable variables in the join // graph List<FetchVariableExpression> varList = new List<FetchVariableExpression>(); optimizer.PopulateVariables(varList, selectExp.Join); // The unique table name of this select TableName uniqueTableName = selectExp.UniqueName; if (uniqueTableName == null) throw new SystemException("Select must have a unique name."); List<Expression> newOutList = new List<Expression>(); for (int i = 0; i < sz; ++i) { // The Expression SelectOutput selectOut = selectExp.Output[i]; // Is this a glob type? if (selectOut.Expression is FetchGlobExpression) { // Get the glob string string str = ((FetchGlobExpression)selectOut.Expression).GlobString; // Search the referencable list for matches, bool matchFound = false; foreach(FetchVariableExpression varExp in varList) { Variable v = varExp.Variable; // Found a match, add it to the list if (optimizer.GlobMatch(str, v)) { SqlType returnType = varExp.ReturnType; Expression globExp = new FetchVariableExpression(v); globExp = new AliasVariableNameExpression(globExp, v); globExp.ReturnType = returnType; newOutList.Add(globExp); matchFound = true; } } // If we searched the whole referencable list and no matches, // we report the error. This doesn't apply to the general // glob "*" which is valid for results with no columns. if (!str.Equals("*") && !matchFound) throw new SqlParseException("'" + str + "' does not match anything", selectOut.Expression); } else { // The makes sure all other types of output from a select are // named variable references. // If this is an alias, we need to make sure we qualify it with // this table name if (selectOut.Expression is AliasVariableNameExpression) { // Rewrite this alias name with the new unique table id Variable v = selectOut.Alias; if (v.TableName != null) throw new SqlParseException("Incorrect alias format", selectOut.Expression); v = new Variable(uniqueTableName, v.Name); selectOut.Alias = v; } // If it's not a fetchvar operation, we need to assign a // unique alias name for this value else if (!(selectOut.Expression is FetchVariableExpression)) { string label = (string)selectOut.Expression.GetArgument("label"); if (label == null) label = "nolabel"; selectOut = new SelectOutput( new AliasVariableNameExpression(selectOut.Expression, new Variable(uniqueTableName, "#" + newOutList.Count + "#" + label)), selectOut.Alias); } // If it's a regular fetch variable operation, we need to // forward qualify it and label it. else { selectOut.Expression = QualifyExpression(selectOut.Expression, varList, true); Variable var = ((FetchVariableExpression)selectOut.Expression).Variable; SqlType returnType = selectOut.Expression.ReturnType; selectOut.Expression = new AliasVariableNameExpression(selectOut.Expression, var); selectOut.Expression.ReturnType = returnType; } // Add it to the new select output list newOutList.Add(selectOut.Expression); } } // new_out_list is now the new expanded select output list sz = newOutList.Count; selectExp.Output.Clear(); for (int i = 0; i < sz; ++i) { selectExp.Output.Add(new SelectOutput(newOutList[i])); } // Set the qualified flag for each select statement, selectExp.IsQualified = true; } return expression; }
private void PopulateVariables(IList<FetchVariableExpression> varList, Expression joinGraph) { // Exit early if join graph is null if (joinGraph == null) return; if (joinGraph is JoinExpression) { // Search the left and right for matching terms JoinExpression joinExp = (JoinExpression)joinGraph; PopulateVariables(varList, joinExp.Left); PopulateVariables(varList, joinExp.Right); } else if (joinGraph is FetchTableExpression) { // This must be fully qualified TableName table_name = ((FetchTableExpression)joinGraph).TableName; PopulateVariables(varList, table_name); } else if (joinGraph is AliasTableNameExpression) { AliasTableNameExpression aliasExp = (AliasTableNameExpression)joinGraph; TableName alias_name = aliasExp.Alias; // We find any that match in the child, List<FetchVariableExpression> newList = new List<FetchVariableExpression>(); PopulateVariables(newList, aliasExp.Child); // And rewrite them with this table name alias int sz = newList.Count; for (int i = 0; i < sz; ++i) { FetchVariableExpression varExp = newList[i]; Variable v = varExp.Variable; FetchVariableExpression newVarExp = (FetchVariableExpression) varExp.Clone(); newVarExp.Variable = new Variable(alias_name, v.Name); newVarExp.ReturnType = varExp.ReturnType; varList.Add(newVarExp); } } else if (joinGraph is SelectExpression) { // For nested selects, we resolve against the select output only SelectExpression selectExp = (SelectExpression)joinGraph; int sz = selectExp.Output.Count; for (int i = 0; i < sz; ++i) { Expression op = selectExp.Output[i].Expression; Variable v; SqlType varType; if (op is FetchVariableExpression) { FetchVariableExpression varExp = (FetchVariableExpression)op; v = varExp.Variable; varType = varExp.ReturnType; } else if (op is AliasVariableNameExpression) { AliasVariableNameExpression aliasExp = (AliasVariableNameExpression)op; v = aliasExp.Alias; varType = aliasExp.ReturnType; } else { throw new ApplicationException("Unknown output object in SELECT"); } if (v != null) { FetchVariableExpression varExp = new FetchVariableExpression(v); varExp.ReturnType = varType; varList.Add(varExp); } } } }
public void PopulateVariables(IList<FetchVariableExpression> varList, TableName tableName) { ITable tsource = transaction.GetTable(tableName); int sz = tsource.Columns.Count; for (int i = 0; i < sz; ++i) { TableColumn column = tsource.Columns[i]; string columnName = column.Name; // The variable name, FetchVariableExpression varExp = new FetchVariableExpression(new Variable(tableName, columnName)); // The type, SqlType returnType = column.Type; varExp.ReturnType = returnType; varList.Add(varExp); } }