protected override SqlStatement PrepareStatement(IRequest context) { var tableName = context.Access().ResolveTableName(TableName); if (tableName == null) { throw new ObjectNotFoundException(TableName); } var columns = new string[0]; if (ColumnNames != null) { columns = ColumnNames.ToArray(); } ITableQueryInfo tableQueryInfo = context.Access().GetTableQueryInfo(tableName, null); var fromTable = new FromTableDirectSource(context.Query.IgnoreIdentifiersCase(), tableQueryInfo, "INSERT_TABLE", tableName, tableName); // Get the table we are inserting to var insertTable = context.Access().GetTable(tableName); if (columns.Length == 0) { columns = new string[insertTable.TableInfo.ColumnCount]; for (int i = 0; i < columns.Length; i++) { columns[i] = insertTable.TableInfo[i].ColumnName; } } var colIndices = new int[columns.Length]; var colResolved = new ObjectName[columns.Length]; for (int i = 0; i < columns.Length; ++i) { var inVar = new ObjectName(columns[i]); var col = ResolveColumn(fromTable, inVar); int index = insertTable.FindColumn(col); if (index == -1) { throw new InvalidOperationException(String.Format("Cannot find column '{0}' in table '{1}'.", col, tableName)); } colIndices[i] = index; colResolved[i] = col; } var queryPlan = context.Context.QueryPlanner().PlanQuery(new QueryInfo(context, QueryExpression)); return(new Prepared(tableName, colResolved, colIndices, queryPlan)); }
/// <summary> /// Constructs the source. /// </summary> /// <param name="caseInsensitive"></param> /// <param name="tableQuery"></param> /// <param name="uniqueName"></param> /// <param name="givenName"></param> /// <param name="rootName"></param> public FromTableDirectSource(bool caseInsensitive, ITableQueryInfo tableQuery, string uniqueName, ObjectName givenName, ObjectName rootName) { UniqueName = uniqueName; tableInfo = tableQuery.TableInfo; RootTableName = rootName; if (givenName != null) { GivenTableName = givenName; } else { GivenTableName = rootName; } IgnoreCase = caseInsensitive; this.tableQuery = tableQuery; }
/// <summary> /// Constructs the source. /// </summary> /// <param name="caseInsensitive"></param> /// <param name="tableQuery"></param> /// <param name="uniqueName"></param> /// <param name="givenName"></param> /// <param name="rootName"></param> public FromTableDirectSource(bool caseInsensitive, ITableQueryInfo tableQuery, string uniqueName, ObjectName givenName, ObjectName rootName) { this.uniqueName = uniqueName; dataTableInfo = tableQuery.TableInfo; RootTableName = rootName; if (givenName != null) { GivenTableName = givenName; } else { GivenTableName = rootName; } // Is the database case insensitive? this.caseInsensitive = caseInsensitive; this.tableQuery = tableQuery; }
internal static TableExpressionFromSet GenerateFromSet(TableSelectExpression selectExpression, ITableSpaceContext db) { // Get the 'from_clause' from the table expression FromClause fromClause = selectExpression.From; // Create a TableExpressionFromSet for this table expression var fromSet = new TableExpressionFromSet(db.IsInCaseInsensitive); // Add all tables from the 'fromClause' foreach (FromTable fromTable in fromClause.AllTables) { string uniqueKey = fromTable.UniqueKey; ObjectName alias = fromTable.Alias; // If this is a sub-command table, if (fromTable.IsSubQueryTable) { // eg. FROM ( SELECT id FROM Part ) TableSelectExpression subQuery = fromTable.SubSelect; TableExpressionFromSet subQueryFromSet = GenerateFromSet(subQuery, db); // The aliased name of the table ObjectName aliasTableName = null; if (alias != null) { aliasTableName = alias.Clone(); } var source = new FromTableSubQuerySource(db.IsInCaseInsensitive, uniqueKey, subQuery, subQueryFromSet, aliasTableName); // Add to list of subquery tables to add to command, fromSet.AddTable(source); } else { // Else must be a standard command table, ObjectName name = fromTable.Name; // Resolve to full table name ObjectName tableName = db.ResolveTableName(name); if (!db.TableExists(tableName)) { throw new ApplicationException("Table '" + tableName + "' was not found."); } ObjectName givenName = null; if (alias != null) { givenName = alias.Clone(); } // Get the ITableQueryInfo object for this table name (aliased). ITableQueryInfo tableQueryInfo = db.GetTableQueryInfo(tableName, givenName); var source = new FromTableDirectSource(db.IsInCaseInsensitive, tableQueryInfo, uniqueKey, givenName, tableName); fromSet.AddTable(source); } } // foreach // Set up functions, aliases and exposed variables for this from set, // For each column being selected foreach (SelectColumn col in selectExpression.Columns) { // Is this a glob? (eg. Part.* ) if (col.IsGlob) { // Find the columns globbed and add to the 'selectedColumns' result. if (col.IsAll) { fromSet.ExposeAllColumns(); } else { // Otherwise the glob must be of the form '[table name].*' string tname = col.GlobPrefix; ObjectName tn = ObjectName.Parse(tname); fromSet.ExposeAllColumnsFromSource(tn); } } else { // Otherwise must be a standard column reference. Note that at this // time we aren't sure if a column expression is correlated and is // referencing an outer source. This means we can't verify if the // column expression is valid or not at this point. // If this column is aliased, add it as a function reference to the // TableExpressionFromSet. var varExpression = (VariableExpression)col.Expression; ObjectName alias = col.Alias; ObjectName v = varExpression.VariableName; bool aliasMatchV = (v != null && alias != null && fromSet.StringCompare(v.Name, alias.Name)); if (alias != null && !aliasMatchV) { fromSet.AddFunctionRef(alias.Name, col.Expression); fromSet.ExposeVariable(alias.Clone()); } else if (v != null) { ObjectName resolved = fromSet.ResolveReference(v); fromSet.ExposeVariable(resolved ?? v); } else { string funName = col.Expression.ToString(); fromSet.AddFunctionRef(funName, col.Expression); fromSet.ExposeVariable(ObjectName.Parse(funName)); } } } // for each column selected return(fromSet); }
public static QueryExpressionFrom Create(IRequest context, SqlQueryExpression expression) { // Get the 'from_clause' from the table expression var fromClause = expression.FromClause; var ignoreCase = context.Query.IgnoreIdentifiersCase(); var queryFrom = new QueryExpressionFrom(ignoreCase); foreach (var fromTable in fromClause.AllTables) { var uniqueKey = fromTable.UniqueKey; var alias = fromTable.Alias; if (fromTable.IsSubQuery) { // eg. FROM ( SELECT id FROM Part ) var subQuery = fromTable.SubQuery; var subQueryFrom = Create(context, subQuery); // The aliased name of the table ObjectName aliasTableName = null; if (alias != null) { aliasTableName = new ObjectName(alias); } // Add to list of sub-query tables to add to command, queryFrom.AddTable(new FromTableSubQuerySource(ignoreCase, uniqueKey, subQuery, subQueryFrom, aliasTableName)); } else { // Else must be a standard command table, string name = fromTable.Name; // Resolve to full table name var tableName = context.Query.ResolveTableName(name); if (!context.Query.TableExists(tableName)) { throw new InvalidOperationException(String.Format("Table '{0}' was not found.", tableName)); } ObjectName givenName = null; if (alias != null) { givenName = new ObjectName(alias); } // Get the ITableQueryInfo object for this table name (aliased). ITableQueryInfo tableQueryInfo = context.Query.GetTableQueryInfo(tableName, givenName); queryFrom.AddTable(new FromTableDirectSource(ignoreCase, tableQueryInfo, uniqueKey, givenName, tableName)); } } // Set up functions, aliases and exposed variables for this from set, foreach (var selectColumn in expression.SelectColumns) { // Is this a glob? (eg. Part.* ) if (selectColumn.IsGlob) { // Find the columns globbed and add to the 'selectedColumns' result. if (selectColumn.IsAll) { queryFrom.ExposeAllColumns(); } else { // Otherwise the glob must be of the form '[table name].*' queryFrom.ExposeColumns(selectColumn.TableName); } } else { // Otherwise must be a standard column reference. Note that at this // time we aren't sure if a column expression is correlated and is // referencing an outer source. This means we can't verify if the // column expression is valid or not at this point. // If this column is aliased, add it as a function reference to the // select expression string alias = selectColumn.Alias; var v = selectColumn.Expression.AsReferenceName(); bool aliasMatchV = (v != null && alias != null && queryFrom.CompareStrings(v.Name, alias)); if (alias != null && !aliasMatchV) { queryFrom.AddExpression(new ExpressionReference(selectColumn.Expression, alias)); queryFrom.ExposeColumn(new ObjectName(alias)); } else if (v != null) { var resolved = queryFrom.ResolveReference(v); queryFrom.ExposeColumn(resolved ?? v); } else { string funName = selectColumn.Expression.ToString(); queryFrom.AddExpression(new ExpressionReference(selectColumn.Expression, funName)); queryFrom.ExposeColumn(new ObjectName(funName)); } } } return(queryFrom); }