internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { List<SqlOrderExpression> save = this.orders; this.orders = new List<SqlOrderExpression>(); base.VisitSubSelect(ss); this.orders = save; return ss; }
internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { Scope save = this.CurrentScope; this.CurrentScope = new Scope(null, this.CurrentScope); base.VisitSubSelect(ss); this.CurrentScope = save; return ss; }
internal override SqlExpression VisitMultiset(SqlSubSelect sms) { // allow one big-join per query? if ((this.options & SqlMultiplexerOptionType.EnableBigJoin) != 0 && !this.hasBigJoin && this.canJoin && this.isTopLevel && this.outerSelect != null && !MultisetChecker.HasMultiset(sms.Select.Selection) && BigJoinChecker.CanBigJoin(sms.Select)) { sms.Select = this.VisitSelect(sms.Select); SqlAlias alias = new SqlAlias(sms.Select); SqlJoin join = new SqlJoin(SqlJoinType.OuterApply, this.outerSelect.From, alias, null, sms.SourceExpression); this.outerSelect.From = @join; this.outerSelect.OrderingType = SqlOrderingType.Always; // make joined expression SqlExpression expr = (SqlExpression)SqlDuplicator.Copy(sms.Select.Selection); // make count expression SqlSelect copySelect = (SqlSelect)SqlDuplicator.Copy(sms.Select); SqlAlias copyAlias = new SqlAlias(copySelect); SqlSelect countSelect = new SqlSelect(sql.Unary(SqlNodeType.Count, null, sms.SourceExpression), copyAlias, sms.SourceExpression); countSelect.OrderingType = SqlOrderingType.Never; SqlExpression count = sql.SubSelect(SqlNodeType.ScalarSubSelect, countSelect); // make joined collection SqlJoinedCollection jc = new SqlJoinedCollection(sms.ClrType, sms.SqlType, expr, count, sms.SourceExpression); this.hasBigJoin = true; return(jc); } return(QueryExtractor.Extract(sms, this.parentParameters)); }
internal override SqlExpression VisitMultiset(SqlSubSelect sms) { // allow one big-join per query? if ((this.options & Options.EnableBigJoin) != 0 && !this.hasBigJoin && this.canJoin && this.isTopLevel && this.outerSelect != null && !MultisetChecker.HasMultiset(sms.Select.Selection) && BigJoinChecker.CanBigJoin(sms.Select)) { sms.Select = this.VisitSelect(sms.Select); SqlAlias alias = new SqlAlias(sms.Select); SqlJoin join = new SqlJoin(SqlJoinType.OuterApply, this.outerSelect.From, alias, null, sms.SourceExpression); this.outerSelect.From = join; this.outerSelect.OrderingType = SqlOrderingType.Always; // make joined expression SqlExpression expr = (SqlExpression)SqlDuplicator.Copy(sms.Select.Selection); // make count expression SqlSelect copySelect = (SqlSelect)SqlDuplicator.Copy(sms.Select); SqlAlias copyAlias = new SqlAlias(copySelect); SqlSelect countSelect = new SqlSelect(sql.Unary(SqlNodeType.Count, null, sms.SourceExpression), copyAlias, sms.SourceExpression); countSelect.OrderingType = SqlOrderingType.Never; SqlExpression count = sql.SubSelect(SqlNodeType.ScalarSubSelect, countSelect); // make joined collection SqlJoinedCollection jc = new SqlJoinedCollection(sms.ClrType, sms.SqlType, expr, count, sms.SourceExpression); this.hasBigJoin = true; return jc; } else { return QueryExtractor.Extract(sms, this.parentParameters); } }
protected override SqlSelect GenerateSkipTake(SqlSelect sequence, SqlExpression skipExp, SqlExpression takeExp) { //return base.GenerateSkipTake(sequence, skipExp, takeExp); SqlSelect node = LockSelect(sequence); var value2 = skipExp as SqlValue; if ((skipExp == null) || ((value2 != null) && (((int)value2.Value) <= 0))) { skipExp = sql.ValueFromObject(0, dominatingExpression); } var alias = new SqlAlias(node); var selection = new SqlAliasRef(alias); if (UseConverterStrategy(ConverterStrategy.SkipWithRowNumber)) { var col = new SqlColumn("ROW_NUMBER", this.sql.RowNumber(new List <SqlOrderExpression>(), this.dominatingExpression)); var expr = new SqlColumnRef(col); node.Row.Columns.Add(col); var select2 = new SqlSelect(selection, alias, this.dominatingExpression); if (takeExp != null) { select2.Where = this.sql.Between(expr, this.sql.Add(skipExp, 1), this.sql.Binary(SqlNodeType.Add, (SqlExpression)SqlDuplicator.Copy(skipExp), takeExp), this.dominatingExpression); return(select2); } select2.Where = this.sql.Binary(SqlNodeType.GT, expr, skipExp); return(select2); } if (!this.CanSkipOnSelection(node.Selection)) { throw SqlClient.Error.SkipNotSupportedForSequenceTypes(); } var visitor = new SingleTableQueryVisitor(); visitor.Visit(node); if (!visitor.IsValid) { throw ALinq.SqlClient.Error.SkipRequiresSingleTableQueryWithPKs(); } var select3 = (SqlSelect)SqlDuplicator.Copy(node); select3.Top = skipExp; var alias2 = new SqlAlias(select3); var ref4 = new SqlAliasRef(alias2); var select = new SqlSelect(ref4, alias2, this.dominatingExpression); select.Where = this.sql.Binary(SqlNodeType.EQ2V, selection, ref4); SqlSubSelect expression = this.sql.SubSelect(SqlNodeType.Exists, select); var select6 = new SqlSelect(selection, alias, this.dominatingExpression); select6.Where = this.sql.Unary(SqlNodeType.Not, expression, this.dominatingExpression); select6.Top = takeExp; return(select6); }
internal virtual SqlExpression VisitSubSelect(SqlSubSelect ss) { switch(ss.NodeType) { case SqlNodeType.ScalarSubSelect: return this.VisitScalarSubSelect(ss); case SqlNodeType.Multiset: return this.VisitMultiset(ss); case SqlNodeType.Element: return this.VisitElement(ss); case SqlNodeType.Exists: return this.VisitExists(ss); } throw Error.UnexpectedNode(ss.NodeType); }
internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { bool saveIsTopLevel = this.isTopLevel; try { return base.VisitSubSelect(ss); } finally { this.isTopLevel = saveIsTopLevel; } }
internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { SqlScope save = this.CurrentScope; this.CurrentScope = new SqlScope(null, this.CurrentScope); base.VisitSubSelect(ss); this.CurrentScope = save; return(ss); }
internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { List <SqlOrderExpression> save = this.orders; this.orders = new List <SqlOrderExpression>(); base.VisitSubSelect(ss); this.orders = save; return(ss); }
internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { base.VisitScalarSubSelect(ss); if (ss.Select.Row.Columns.Count > 0) { System.Diagnostics.Debug.Assert(ss != null && ss.Select != null && ss.Select.Row != null && ss.Select.Row.Columns.Count == 1); // make sure these scalar subselects don't get redundantly named ss.Select.Row.Columns[0].Name = ""; } return ss; }
internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { SqlSelect innerSelect = this.VisitSelect(ss.Select); if (!this.aggregateChecker.HasAggregates(innerSelect)) { innerSelect.Top = this.sql.ValueFromObject(1, ss.SourceExpression); } innerSelect.OrderingType = SqlOrderingType.Blocked; SqlAlias alias = new SqlAlias(innerSelect); this.currentSelect.From = new SqlJoin(SqlJoinType.OuterApply, this.currentSelect.From, alias, null, ss.SourceExpression); return new SqlColumnRef(innerSelect.Row.Columns[0]); }
internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { base.VisitScalarSubSelect(ss); if (ss.Select.Row.Columns.Count > 0) { Diagnostics.Debug.Assert(ss != null && ss.Select != null && ss.Select.Row != null && ss.Select.Row.Columns.Count == 1); // make sure these scalar subselects don't get redundantly named ss.Select.Row.Columns[0].Name = ""; } return(ss); }
internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { // block where clauses from being lifted out of a sub-query Scope save = this.current; this.current = null; SqlExpression result = base.VisitSubSelect(ss); this.current = save; return(result); }
internal static SqlClientQuery Extract(SqlSubSelect subquery, IEnumerable <SqlParameter> parentParameters) { SqlClientQuery cq = new SqlClientQuery(subquery); if (parentParameters != null) { cq.Parameters.AddRange(parentParameters); } SubSelectDuplicator v = new SubSelectDuplicator(cq.Arguments, cq.Parameters); cq.Query = (SqlSubSelect)v.Visit(subquery); return(cq); }
protected override SqlSubSelect VisitSqlSubSelect(SqlSubSelect sqlSelectRef) { _sql.Append("("); _sql.AppendLine(); this.Indent++; this.Visit(sqlSelectRef.Select); this.Indent--; _sql.AppendLine(); _sql.Append(") AS "); _sql.Append(sqlSelectRef.Alias); return(sqlSelectRef); }
internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { bool saveIsTopLevel = _isTopLevel; try { return(base.VisitSubSelect(ss)); } finally { _isTopLevel = saveIsTopLevel; } }
internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { bool saveIsTopLevel = this.isTopLevel; this.isTopLevel = false; bool saveCanJoin = this.canJoin; this.canJoin = false; try { return base.VisitScalarSubSelect(ss); } finally { this.isTopLevel = saveIsTopLevel; this.canJoin = saveCanJoin; } }
internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { SqlSelect innerSelect = this.VisitSelect(ss.Select); if (!this.aggregateChecker.HasAggregates(innerSelect)) { innerSelect.Top = this.sql.ValueFromObject(1, ss.SourceExpression); } innerSelect.OrderingType = SqlOrderingType.Blocked; SqlAlias alias = new SqlAlias(innerSelect); this.currentSelect.From = new SqlJoin(SqlJoinType.OuterApply, this.currentSelect.From, alias, null, ss.SourceExpression); return(new SqlColumnRef(innerSelect.Row.Columns[0])); }
internal SqlNode TranslateLink(SqlLink link, List <SqlExpression> keyExpressions, bool asExpression) { MetaDataMember mm = link.Member; if (mm.IsAssociation) { // Create the row source. MetaType otherType = mm.Association.OtherType; Type tableType = otherType.InheritanceRoot.Type; ITable table = this.services.Context.GetTable(tableType); Expression source = new LinkedTableExpression(link, table, typeof(IQueryable <>).MakeGenericType(otherType.Type)); // Build key expression nodes. Expression[] keyExprs = new Expression[keyExpressions.Count]; for (int i = 0; i < keyExpressions.Count; ++i) { MetaDataMember metaMember = mm.Association.OtherKey[i]; Type memberType = TypeSystem.GetMemberType(metaMember.Member); keyExprs[i] = InternalExpression.Known(keyExpressions[i], memberType); } Expression lex = link.Expression != null ? (Expression)InternalExpression.Known(link.Expression) : (Expression)Expression.Constant(null, link.Member.Member.DeclaringType); Expression expr = TranslateAssociation(this.services.Context, mm.Association, source, keyExprs, lex); // Convert QueryConverter qc = new QueryConverter(this.services, this.typeProvider, this, this.sql); SqlSelect sel = (SqlSelect)qc.ConvertInner(expr, link.SourceExpression); // Turn it into an expression is necessary SqlNode result = sel; if (asExpression) { if (mm.Association.IsMany) { result = new SqlSubSelect(SqlNodeType.Multiset, link.ClrType, link.SqlType, sel); } else { result = new SqlSubSelect(SqlNodeType.Element, link.ClrType, link.SqlType, sel); } } return(result); } else { System.Diagnostics.Debug.Assert(link.Expansion != null); System.Diagnostics.Debug.Assert(link.KeyExpressions == keyExpressions); // deferred expression already defined... return(link.Expansion); } }
internal override SqlExpression VisitClientQuery(SqlClientQuery cq) { SqlSubSelect query = (SqlSubSelect)this.VisitExpression(cq.Query); SqlClientQuery nq = new SqlClientQuery(query); for (int i = 0, n = cq.Arguments.Count; i < n; i++) { nq.Arguments.Add(this.VisitExpression(cq.Arguments[i])); } for (int i = 0, n = cq.Parameters.Count; i < n; i++) { nq.Parameters.Add((SqlParameter)this.VisitExpression(cq.Parameters[i])); } return(nq); }
internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { bool saveIsTopLevel = _isTopLevel; _isTopLevel = false; bool saveForceReferenceAll = _forceReferenceAll; _forceReferenceAll = true; try { return(base.VisitScalarSubSelect(ss)); } finally { _isTopLevel = saveIsTopLevel; _forceReferenceAll = saveForceReferenceAll; } }
internal override SqlExpression VisitExists(SqlSubSelect ss) { bool saveIsTopLevel = this.isTopLevel; this.isTopLevel = false; bool saveCanJoin = this.canJoin; this.canJoin = false; try { return(base.VisitExists(ss)); } finally { this.isTopLevel = saveIsTopLevel; this.canJoin = saveCanJoin; } }
internal virtual SqlExpression VisitExists(SqlSubSelect sqlExpr) { sqlExpr.Select = this.VisitSequence(sqlExpr.Select); return sqlExpr; }
internal override SqlExpression VisitMultiset(SqlSubSelect sms) { return(new SqlSubSelect(sms.NodeType, sms.ClrType, sms.SqlType, (SqlSelect)this.Visit(sms.Select))); }
internal virtual SqlExpression VisitMultiset(SqlSubSelect sms) { sms.Select = this.VisitSequence(sms.Select); return sms; }
internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { return ss; }
internal override SqlExpression VisitElement(SqlSubSelect elem) { return QueryExtractor.Extract(elem, this.parentParameters); }
internal override SqlExpression VisitElement(SqlSubSelect elem) { this.FoundHierarchy = true; return(elem); }
internal override SqlExpression VisitElement(SqlSubSelect elem) { return elem; }
internal override SqlExpression VisitExists(SqlSubSelect sqlExpr) { int saveDepth = this.depth; this.depth++; sb.Append("EXISTS("); this.NewLine(); this.Visit(sqlExpr.Select); this.NewLine(); sb.Append(")"); this.depth = saveDepth; return sqlExpr; }
/// <summary> /// 为指定的原始查询生成指定分页效果的新查询。 /// </summary> /// <param name="raw">原始查询</param> /// <param name="pagingInfo">分页信息。</param> /// <returns></returns> /// <exception cref="System.ArgumentNullException">pagingInfo</exception> /// <exception cref="System.InvalidProgramException">必须排序后才能使用分页功能。</exception> protected virtual ISqlSelect ModifyToPagingTree(SqlSelect raw, PagingInfo pagingInfo) { if (PagingInfo.IsNullOrEmpty(pagingInfo)) { throw new ArgumentNullException("pagingInfo"); } if (!raw.HasOrdered()) { throw new InvalidProgramException("必须排序后才能使用分页功能。"); } /*********************** 代码块解释 ********************************* * * 使用 ROW_NUMBER() 函数,此函数 SqlServer、Oracle 都可使用。 * 注意,这个方法只支持不太复杂 SQL 的转换。 * * 源格式: * select ...... from ...... order by xxxx asc, yyyy desc * 不限于以上格式,只要满足没有复杂的嵌套查询,最外层是一个 Select 和 From 语句即可。 * * 目标格式: * select * from (select ......, row_number() over(order by xxxx asc, yyyy desc) _rowNumber from ......) x where x._rowNumber<10 and x._rowNumber>5; **********************************************************************/ var startRow = pagingInfo.PageSize * (pagingInfo.PageNumber - 1) + 1; var endRow = startRow + pagingInfo.PageSize - 1; var innerSelect = new SqlSelect(); var selection = new SqlArray(); if (raw.Selection != null) { selection.Items.Add(raw.Selection); } selection.Items.Add(new SqlNodeList { new SqlLiteral { FormattedSql = "row_number() over (" }, raw.OrderBy, new SqlLiteral { FormattedSql = ") _rowNumber" } }); innerSelect.Selection = selection; var subSelect = new SqlSubSelect { Select = innerSelect, Alias = "x" }; var rowNumberColumn = new SqlTree.SqlColumn { Table = subSelect, ColumnName = "_rowNumber" }; var pagingSelect = new SqlSelect(); pagingSelect.From = subSelect; pagingSelect.Where = new SqlTree.SqlBinaryConstraint { Left = new SqlTree.SqlColumnConstraint { Column = rowNumberColumn, Operator = SqlColumnConstraintOperator.GreaterEqual, Value = startRow }, Opeartor = SqlBinaryConstraintType.And, Right = new SqlTree.SqlColumnConstraint { Column = rowNumberColumn, Operator = SqlColumnConstraintOperator.LessEqual, Value = endRow } }; return(pagingSelect); }
internal override SqlExpression VisitElement(SqlSubSelect elem) { return(QueryExtractor.Extract(elem, this.parentParameters)); }
internal virtual SqlExpression VisitElement(SqlSubSelect elem) { elem.Select = this.VisitSequence(elem.Select); return elem; }
internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { return (SqlExpression)new SqlDuplicator().Duplicate(ss); }
internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { return(ss); }
private SqlExpression FoldSubquery(SqlSubSelect ss) { // convert ELEMENT(SELECT MULTISET(SELECT xxx FROM t1 WHERE p1) FROM t2 WHERE p2) // into MULTISET(SELECT xxx FROM t2 CA (SELECT xxx FROM t1 WHERE p1) WHERE p2)) while (true) { if (ss.NodeType == SqlNodeType.Element && ss.Select.Selection.NodeType == SqlNodeType.Multiset) { SqlSubSelect msub = (SqlSubSelect)ss.Select.Selection; SqlAlias alias = new SqlAlias(msub.Select); SqlAliasRef aref = new SqlAliasRef(alias); SqlSelect sel = ss.Select; sel.Selection = this.ConvertLinks(this.VisitExpression(aref)); sel.From = new SqlJoin(SqlJoinType.CrossApply, sel.From, alias, null, ss.SourceExpression); SqlSubSelect newss = sql.SubSelect(SqlNodeType.Multiset, sel, ss.ClrType); ss = newss; } else if (ss.NodeType == SqlNodeType.Element && ss.Select.Selection.NodeType == SqlNodeType.Element) { SqlSubSelect msub = (SqlSubSelect)ss.Select.Selection; SqlAlias alias = new SqlAlias(msub.Select); SqlAliasRef aref = new SqlAliasRef(alias); SqlSelect sel = ss.Select; sel.Selection = this.ConvertLinks(this.VisitExpression(aref)); sel.From = new SqlJoin(SqlJoinType.CrossApply, sel.From, alias, null, ss.SourceExpression); SqlSubSelect newss = sql.SubSelect(SqlNodeType.Element, sel); ss = newss; } else { break; } } return ss; }
internal override SqlExpression VisitElement(SqlSubSelect elem) { if (!this.isDebugMode) { throw Error.InvalidFormatNode("Element"); } int saveDepth = this.depth; this.depth++; sb.Append("ELEMENT("); this.NewLine(); this.Visit(elem.Select); this.NewLine(); sb.Append(")"); this.depth = saveDepth; return elem; }
internal override SqlExpression VisitElement(SqlSubSelect elem) { return(elem); }
internal override SqlExpression VisitMultiset(SqlSubSelect sms) { return sms; }
internal override SqlExpression VisitElement(SqlSubSelect elem) { return this.VisitMultiset(elem); }
internal override SqlExpression VisitExists(SqlSubSelect ss) { return ss; }
internal override SqlExpression VisitExists(SqlSubSelect sqlExpr) { return new SqlSubSelect(sqlExpr.NodeType, sqlExpr.ClrType, sqlExpr.SqlType, (SqlSelect)this.Visit(sqlExpr.Select)); }
internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { return((SqlExpression) new SqlDuplicator().Duplicate(ss)); }
internal override SqlExpression VisitMultiset(SqlSubSelect sms) { return new SqlSubSelect(sms.NodeType, sms.ClrType, sms.SqlType, (SqlSelect)this.Visit(sms.Select)); }
internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { return(new SqlSubSelect(SqlNodeType.ScalarSubSelect, ss.ClrType, ss.SqlType, this.VisitSequence(ss.Select))); }
internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { return new SqlSubSelect(SqlNodeType.ScalarSubSelect, ss.ClrType, ss.SqlType, this.VisitSequence(ss.Select)); }
internal virtual SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { ss.Select = this.VisitSequence(ss.Select); return ss; }
internal override SqlExpression VisitMultiset(SqlSubSelect sms) { return(sms); }
internal static SqlClientQuery Extract(SqlSubSelect subquery, IEnumerable<System.Data.Linq.SqlClient.SqlParameter> parentParameters) { SqlClientQuery cq = new SqlClientQuery(subquery); if (parentParameters != null) { cq.Parameters.AddRange(parentParameters); } Visitor v = new Visitor(cq.Arguments, cq.Parameters); cq.Query = (SqlSubSelect)v.Visit(subquery); return cq; }
internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { base.VisitScalarSubSelect(ss); ss.SetSqlType(ss.Select.Selection.SqlType); return(ss); }
internal override SqlExpression VisitElement(SqlSubSelect elem) { this.foundHierarchy = true; return elem; }
internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { int saveDepth = this.depth; this.depth++; if (this.isDebugMode) { sb.Append("SCALAR"); } sb.Append("("); this.NewLine(); this.Visit(ss.Select); this.NewLine(); sb.Append(")"); this.depth = saveDepth; return ss; }
internal override SqlExpression VisitMultiset(SqlSubSelect sms) { this.foundMultiset = true; return sms; }
internal override SqlExpression VisitMultiset(SqlSubSelect sms) { if (!this.isDebugMode) { throw Error.InvalidFormatNode("Multiset"); } int saveDepth = this.depth; this.depth++; sb.Append("MULTISET("); this.NewLine(); this.Visit(sms.Select); this.NewLine(); sb.Append(")"); this.depth = saveDepth; return sms; }
internal override SqlExpression VisitMultiset(SqlSubSelect sms) { this.FoundHierarchy = true; return(sms); }
internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) { base.VisitScalarSubSelect(ss); ss.SetSqlType(ss.Select.Selection.SqlType); return ss; }
internal override SqlExpression VisitSubSelect(SqlSubSelect ss) { // don't preserve any link optimizations across sub-queries LinkOptimizationScope saveScope = this.linkMap; SqlSelect saveSelect = this.currentSelect; try { this.linkMap = new LinkOptimizationScope(this.linkMap); this.currentSelect = null; return base.VisitSubSelect(ss); } finally { this.linkMap = saveScope; this.currentSelect = saveSelect; } }