public NonQueryLinqCommandData(LinqCommand baseLinqCommand, SelectExpression baseSelect, TableExpression targetTable, bool isSingleTable) { BaseLinqCommand = baseLinqCommand; BaseSelect = baseSelect; TargetTable = targetTable; IsSingleTableCommand = isSingleTable; }
public override SqlStatement ReviewSelectSql(SelectExpression select, SqlStatement sql) { const string ReadLockTemplate = "{0} \r\n FOR SHARE;"; const string WriteLockTemplate = "{0} \r\n FOR UPDATE;"; var flags = select.CommandInfo.Flags; if (flags.IsSet(LinqCommandFlags.ReadLock)) return string.Format(ReadLockTemplate, sql); if (flags.IsSet(LinqCommandFlags.WriteLock)) return string.Format(WriteLockTemplate, sql); return sql; }
public SelectExpression(SelectExpression parentSelectExpression) : base(SqlExpressionType.Select, null, null) { Parent = parentSelectExpression; // Tables and columns are empty, since the table/column lookup recurses to parentScopePiece Tables = new List<TableExpression>(); Columns = new List<ColumnExpression>(); // Local clauses Where = new List<Expression>(); OrderBy = new List<OrderByExpression>(); Group = new List<GroupExpression>(); }
public SubSelectExpression(SelectExpression select, Type type, string alias, Vita.Data.Model.DbTableInfo tableInfo) : base(type, alias, tableInfo) { this.Select = select; this.Alias = alias; }
public override SelectExpression PreviewSelect(SelectExpression e) { base.PreviewSelect(e); // SQL CE doesn't support 'ORDER BY' for 'SELECT COUNT(*)' if (e.HasOrderBy() && e.HasOutAggregates()) e.OrderBy.Clear(); return e; }
public override SqlStatement ReviewSelectSql(SelectExpression select, SqlStatement sql) { const string NoLockTemplate = @"SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; {0}; COMMIT ; "; const string ReadLockTemplate = "{0} \r\n LOCK IN SHARE MODE;"; const string WriteLockTemplate = "{0} \r\n FOR UPDATE;"; var flags = select.CommandInfo.Flags; if (flags.IsSet(LinqCommandFlags.NoLock)) return string.Format(NoLockTemplate, sql); if (flags.IsSet(LinqCommandFlags.ReadLock)) return string.Format(ReadLockTemplate, sql); if (flags.IsSet(LinqCommandFlags.WriteLock)) return string.Format(WriteLockTemplate, sql); return sql; }
/// <summary> /// Find the common ancestor between two ScopeExpressions /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> protected virtual SelectExpression FindCommonScope(SelectExpression a, SelectExpression b) { for (var aScope = a; aScope != null; aScope = aScope.Parent) { for (var bScope = b; bScope != null; bScope = bScope.Parent) { if (aScope == bScope) return aScope; } } return null; }
/// <summary> /// Creates a new rewriterContext with a new query scope which is parent of the current one /// </summary> /// <returns></returns> public void NewParentSelect() { SelectExpression currentSelect = this.CurrentSelect; SelectExpression newParentSelect = new SelectExpression(currentSelect.Parent); while (currentSelect != null) { currentSelect.Parent = newParentSelect; currentSelect = currentSelect.NextSelectExpression; } this._currentScopeIndex = SelectExpressions.Count; SelectExpressions.Add(newParentSelect); }
/// <summary> /// Returns a list of sorted tables, given a select expression. /// The tables are sorted by dependency: independent tables first, dependent tables next /// </summary> /// <param name="selectExpression"></param> /// <returns></returns> protected IList<TableExpression> GetSortedTables(SelectExpression selectExpression) { //RI: I have rewritten this if(selectExpression.Tables.Count < 2) return selectExpression.Tables; var tables = new List<TableExpression>(selectExpression.Tables); foreach(var table in tables) table.SortIndex = 0; for(int i = 0; i < tables.Count * 2; i++) { bool updated = false; //make one round of updates foreach(var t in tables) if(t.JoinedTable != null && t.JoinedTable.SortIndex <= t.SortIndex) { t.JoinedTable.SortIndex = t.SortIndex + 1; updated = true; } if(!updated) { tables.Sort((x, y) => y.SortIndex.CompareTo(x.SortIndex)); return tables; } } //for i Util.Throw("Internal LINQ engine error - failed to sort joined tables."); return tables; }
private SqlStatement BuildSelectSql(SelectExpression selectExpression) { selectExpression = _sqlProvider.PreviewSelect(selectExpression); // A scope usually has: // - a SELECT: the operation creating a CLR object with data coming from SQL tier // - a FROM: list of tables // - a WHERE: list of conditions // - a GROUP BY: grouping by selected columns // - a ORDER BY: sort var select = BuildSelectClause(selectExpression); if (select.ToString() == string.Empty) { SubSelectExpression subselect = null; if (selectExpression.Tables.Count == 1) subselect = selectExpression.Tables[0] as SubSelectExpression; if(subselect != null) return _sqlProvider.GetParenthesis(BuildSelectSql(subselect.Select)); } // TODO: the following might be wrong (at least this might be the wrong place to do this if (select.ToString() == string.Empty) select = new SqlStatement("SELECT " + _sqlProvider.GetLiteral(null) + " AS " + _sqlProvider.GetSafeName("Empty")); var tables = GetSortedTables(selectExpression); var from = BuildFrom(tables); var join = BuildJoin(tables); var where = BuildWhere(tables, selectExpression.Where); var groupBy = BuildGroupBy(selectExpression.Group); var having = BuildHaving(selectExpression.Where); var orderBy = BuildOrderBy(selectExpression.OrderBy); select = Join(select, from, join, where, groupBy, having, orderBy); select = BuildLimit(selectExpression, select); if (selectExpression.NextSelectExpression != null) { var nextLiteralSelect = BuildSelectSql(selectExpression.NextSelectExpression); select = _sqlProvider.GetLiteral( selectExpression.NextSelectExpressionOperator, select, nextLiteralSelect); } return select; }
public SqlStatement BuildSelect(SelectExpression selectExpression) { var stmt = BuildSelectSql(selectExpression); stmt = _sqlProvider.ReviewSelectSql(selectExpression, stmt); return stmt; }
protected virtual SqlStatement BuildLimit(SelectExpression select, SqlStatement literalSelect) { if (select.Limit == null) return literalSelect; var literalLimit = BuildExpression(select.Limit); var literalOffset = BuildExpression(select.Offset); var literalOffsetAndLimit = BuildExpression(select.OffsetAndLimit); return _sqlProvider.GetLiteralLimit(literalSelect, literalLimit, literalOffset, literalOffsetAndLimit); }
public SelectExpression(SelectExpression parentSelectExpression, LinqCommand queryInfo) : base(SqlExpressionType.Select, null, null) { Parent = parentSelectExpression; Command = queryInfo; }
/// <summary> Previews and changes if necessary the entire (outermost) expression. </summary> /// <param name="e"></param> /// <remarks> /// <para> /// Derived classes can override this method to manipulate the entire expression prior to SQL generation. /// </para> /// </remarks> public virtual SelectExpression PreviewSelect(SelectExpression e) { //None of the servers support in one query COUNT and Limit (FETCH NEXT for MS SQL) if (e.HasLimit() && e.HasOutAggregates()) Util.Throw("Invalid LINQ expression: Server does not support COUNT(*) and LIMIT (MS SQL: FETCH NEXT) in one query."); return e; }
private ColumnExpression FindAnyColumnForFakeOrderBy(SelectExpression select, TranslationContext context) { var col = select.Operands.OfType<ColumnExpression>().FirstOrDefault(); if (col != null) return col; if (select.Columns.Count > 0) return select.Columns[0]; //register column var tbl0 = select.Tables[0]; col = _translator.RegisterColumn(tbl0, tbl0.TableInfo.PrimaryKey.KeyColumns[0].Column.ColumnName, context); return col; }
public virtual SqlStatement ReviewSelectSql(SelectExpression select, SqlStatement sql) { return sql; }
protected override Expression Mutate2(IList<Expression> newOperands) { Type type; if (newOperands.Count > 0) type = newOperands[0].Type; else type = Type; var scopeExpression = new SelectExpression(type, newOperands); scopeExpression.Tables = Tables; scopeExpression.Columns = Columns; scopeExpression.Where = Where; scopeExpression.OrderBy = OrderBy; scopeExpression.Group = Group; scopeExpression.Parent = Parent; scopeExpression.ResultsProcessor = ResultsProcessor; scopeExpression.Reader = Reader; scopeExpression.Limit = Limit; scopeExpression.Offset = Offset; scopeExpression.OffsetAndLimit = OffsetAndLimit; scopeExpression.NextSelectExpression = NextSelectExpression; scopeExpression.NextSelectExpressionOperator = NextSelectExpressionOperator; return scopeExpression; }