| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477 |
- using System;
- using System.Globalization;
- using System.Collections.Generic;
- using System.Data;
- using System.Text;
- using System.Data.Linq.Mapping;
- using System.Data.Linq.Provider;
- using System.Linq;
- using System.Data.SqlClient;
- using System.Diagnostics.CodeAnalysis;
- namespace System.Data.Linq.SqlClient {
- internal class SqlFormatter : DbFormatter {
- private Visitor visitor;
- internal SqlFormatter() {
- this.visitor = new Visitor();
- }
- internal override string Format(SqlNode node, bool isDebug) {
- return this.visitor.Format(node, isDebug);
- }
- internal string[] FormatBlock(SqlBlock block, bool isDebug) {
- List<string> results = new List<string>(block.Statements.Count);
- for (int i = 0, n = block.Statements.Count; i < n; i++) {
- SqlStatement stmt = block.Statements[i];
- SqlSelect select = stmt as SqlSelect;
- if (select != null && select.DoNotOutput) {
- continue;
- } else {
- results.Add(this.Format(stmt, isDebug));
- }
- }
- return results.ToArray();
- }
- internal override string Format(SqlNode node) {
- return this.visitor.Format(node);
- }
- internal bool ParenthesizeTop {
- get { return this.visitor.parenthesizeTop; }
- set { this.visitor.parenthesizeTop = value; }
- }
- [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification="These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
- internal class Visitor : SqlVisitor {
- internal StringBuilder sb;
- internal bool isDebugMode;
- internal List<SqlSource> suppressedAliases = new List<SqlSource>();
- internal Dictionary<SqlNode, string> names = new Dictionary<SqlNode, string>();
- internal Dictionary<SqlColumn, SqlAlias> aliasMap = new Dictionary<SqlColumn, SqlAlias>();
- internal int depth;
- internal bool parenthesizeTop;
- internal Visitor() {
- }
- internal string Format(SqlNode node, bool isDebug) {
- this.sb = new StringBuilder();
- this.isDebugMode = isDebug;
- this.aliasMap.Clear();
- if (isDebug) {
- new AliasMapper(this.aliasMap).Visit(node);
- }
- this.Visit(node);
- return this.sb.ToString();
- }
- internal string Format(SqlNode node) {
- return this.Format(node, false);
- }
- [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification="These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
- internal virtual void VisitWithParens(SqlNode node, SqlNode outer) {
- if (node == null)
- return;
- switch (node.NodeType) {
- case SqlNodeType.ColumnRef:
- case SqlNodeType.Value:
- case SqlNodeType.Member:
- case SqlNodeType.Parameter:
- case SqlNodeType.FunctionCall:
- case SqlNodeType.TableValuedFunctionCall:
- case SqlNodeType.OuterJoinedValue:
- this.Visit(node);
- break;
- case SqlNodeType.Add:
- case SqlNodeType.Mul:
- case SqlNodeType.And:
- case SqlNodeType.Or:
- case SqlNodeType.Not:
- case SqlNodeType.Not2V:
- case SqlNodeType.BitAnd:
- case SqlNodeType.BitOr:
- case SqlNodeType.BitXor:
- case SqlNodeType.BitNot:
- if (outer.NodeType != node.NodeType)
- goto default;
- this.Visit(node);
- break;
- default:
- this.sb.Append("(");
- this.Visit(node);
- this.sb.Append(")");
- break;
- }
- }
- internal override SqlExpression VisitNop(SqlNop nop) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("NOP");
- }
- sb.Append("NOP()");
- return nop;
- }
- [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification="These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
- internal override SqlExpression VisitUnaryOperator(SqlUnary uo) {
- switch (uo.NodeType) {
- case SqlNodeType.Not:
- case SqlNodeType.Not2V:
- this.sb.Append(GetOperator(uo.NodeType));
- this.sb.Append(" ");
- this.VisitWithParens(uo.Operand, uo);
- break;
- case SqlNodeType.Negate:
- case SqlNodeType.BitNot:
- this.sb.Append(GetOperator(uo.NodeType));
- this.VisitWithParens(uo.Operand, uo);
- break;
- case SqlNodeType.Count:
- case SqlNodeType.LongCount:
- case SqlNodeType.Max:
- case SqlNodeType.Min:
- case SqlNodeType.Sum:
- case SqlNodeType.Avg:
- case SqlNodeType.Stddev:
- case SqlNodeType.ClrLength:{
- this.sb.Append(GetOperator(uo.NodeType));
- this.sb.Append("(");
- if (uo.Operand == null) {
- this.sb.Append("*");
- } else {
- this.Visit(uo.Operand);
- }
- this.sb.Append(")");
- break;
- }
- case SqlNodeType.IsNull:
- case SqlNodeType.IsNotNull: {
- this.VisitWithParens(uo.Operand, uo);
- sb.Append(" ");
- sb.Append(GetOperator(uo.NodeType));
- break;
- }
- case SqlNodeType.Convert: {
- this.sb.Append("CONVERT(");
- QueryFormatOptions options = QueryFormatOptions.None;
- if(uo.Operand.SqlType.CanSuppressSizeForConversionToString) {
- options = QueryFormatOptions.SuppressSize;
- }
- this.sb.Append(uo.SqlType.ToQueryString(options));
- this.sb.Append(",");
- this.Visit(uo.Operand);
- this.sb.Append(")");
- break;
- }
- case SqlNodeType.ValueOf:
- case SqlNodeType.OuterJoinedValue:
- this.Visit(uo.Operand); // no op
- break;
- default:
- throw Error.InvalidFormatNode(uo.NodeType);
- }
- return uo;
- }
- internal override SqlRowNumber VisitRowNumber(SqlRowNumber rowNumber) {
- sb.Append("ROW_NUMBER() OVER (ORDER BY ");
- for (int i = 0, n = rowNumber.OrderBy.Count; i < n; i++) {
- SqlOrderExpression exp = rowNumber.OrderBy[i];
- if (i > 0) sb.Append(", ");
- this.Visit(exp.Expression);
- if (exp.OrderType == SqlOrderType.Descending) {
- sb.Append(" DESC");
- }
- }
- sb.Append(")");
- return rowNumber;
- }
- internal override SqlExpression VisitLift(SqlLift lift) {
- this.Visit(lift.Expression);
- return lift;
- }
- internal override SqlExpression VisitBinaryOperator(SqlBinary bo) {
- switch (bo.NodeType) {
- case SqlNodeType.Coalesce:
- sb.Append("COALESCE(");
- this.Visit(bo.Left);
- sb.Append(",");
- this.Visit(bo.Right);
- sb.Append(")");
- break;
- default:
- this.VisitWithParens(bo.Left, bo);
- sb.Append(" ");
- sb.Append(GetOperator(bo.NodeType));
- sb.Append(" ");
- this.VisitWithParens(bo.Right, bo);
- break;
- }
- return bo;
- }
- internal override SqlExpression VisitBetween(SqlBetween between) {
- this.VisitWithParens(between.Expression, between);
- sb.Append(" BETWEEN ");
- this.Visit(between.Start);
- sb.Append(" AND ");
- this.Visit(between.End);
- return between;
- }
- internal override SqlExpression VisitIn(SqlIn sin) {
- this.VisitWithParens(sin.Expression, sin);
- sb.Append(" IN (");
- for (int i = 0, n = sin.Values.Count; i < n; i++) {
- if (i > 0) {
- sb.Append(", ");
- }
- this.Visit(sin.Values[i]);
- }
- sb.Append(")");
- return sin;
- }
- internal override SqlExpression VisitLike(SqlLike like) {
- this.VisitWithParens(like.Expression, like);
- sb.Append(" LIKE ");
- this.Visit(like.Pattern);
- if (like.Escape != null) {
- sb.Append(" ESCAPE ");
- this.Visit(like.Escape);
- }
- return like;
- }
- internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc) {
- if (fc.Name.Contains(".")) {
- // Assume UDF -- bracket the name.
- this.WriteName(fc.Name);
- } else {
- // No ".", so we assume it's a system function name and leave it alone.
- sb.Append(fc.Name);
- }
-
- sb.Append("(");
- for (int i = 0, n = fc.Arguments.Count; i < n; i++) {
- if (i > 0)
- sb.Append(", ");
- this.Visit(fc.Arguments[i]);
- }
- sb.Append(")");
- return fc;
- }
- internal override SqlExpression VisitTableValuedFunctionCall(SqlTableValuedFunctionCall fc) {
- // both scalar and table valued functions are formatted the same
- return VisitFunctionCall(fc);
- }
- internal override SqlExpression VisitCast(SqlUnary c) {
- sb.Append("CAST(");
- this.Visit(c.Operand);
- sb.Append(" AS ");
- QueryFormatOptions options = QueryFormatOptions.None;
- if (c.Operand.SqlType.CanSuppressSizeForConversionToString) {
- options = QueryFormatOptions.SuppressSize;
- }
- sb.Append(c.SqlType.ToQueryString(options));
- sb.Append(")");
- return c;
- }
- internal override SqlExpression VisitTreat(SqlUnary t) {
- sb.Append("TREAT(");
- this.Visit(t.Operand);
- sb.Append(" AS ");
- this.FormatType(t.SqlType);
- sb.Append(")");
- return t;
- }
- internal override SqlExpression VisitColumn(SqlColumn c) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("Column");
- }
- sb.Append("COLUMN(");
- if (c.Expression != null) {
- this.Visit(c.Expression);
- }
- else {
- string aliasName = null;
- if (c.Alias != null) {
- if (c.Alias.Name == null) {
- if (!this.names.TryGetValue(c.Alias, out aliasName)) {
- aliasName = "A" + this.names.Count;
- this.names[c.Alias] = aliasName;
- }
- } else {
- aliasName = c.Alias.Name;
- }
- }
- sb.Append(aliasName);
- sb.Append(".");
- sb.Append(c.Name);
- }
- sb.Append(")");
- return c;
- }
- internal override SqlExpression VisitDiscriminatedType(SqlDiscriminatedType dt) {
- if (this.isDebugMode) {
- sb.Append("DTYPE(");
- }
- base.VisitDiscriminatedType(dt);
- if (this.isDebugMode) {
- sb.Append(")");
- }
- return dt;
- }
- internal override SqlExpression VisitDiscriminatorOf(SqlDiscriminatorOf dof) {
- if (this.isDebugMode) {
- sb.Append("DISCO(");
- }
- base.VisitDiscriminatorOf(dof);
- if (this.isDebugMode) {
- sb.Append(")");
- }
- return dof;
- }
- internal override SqlExpression VisitSimpleExpression(SqlSimpleExpression simple) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("SIMPLE");
- }
- sb.Append("SIMPLE(");
- base.VisitSimpleExpression(simple);
- sb.Append(")");
- return simple;
- }
- internal override SqlExpression VisitSharedExpression(SqlSharedExpression shared) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("Shared");
- }
- sb.Append("SHARED(");
- this.Visit(shared.Expression);
- sb.Append(")");
- return shared;
- }
- internal override SqlExpression VisitSharedExpressionRef(SqlSharedExpressionRef sref) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("SharedRef");
- }
- sb.Append("SHAREDREF(");
- this.Visit(sref.SharedExpression.Expression);
- sb.Append(")");
- return sref;
- }
- internal override SqlExpression VisitColumnRef(SqlColumnRef cref) {
- string aliasName = null;
- SqlColumn c = cref.Column;
- SqlAlias alias = c.Alias;
- if (alias == null) {
- this.aliasMap.TryGetValue(c, out alias);
- }
- if (alias != null) {
- if (alias.Name == null) {
- if (!this.names.TryGetValue(alias, out aliasName)) {
- aliasName = "A" + this.names.Count;
- this.names[c.Alias] = aliasName;
- }
- } else {
- aliasName = c.Alias.Name;
- }
- }
- if (!this.suppressedAliases.Contains(c.Alias) && aliasName != null && aliasName.Length != 0) {
- this.WriteName(aliasName);
- sb.Append(".");
- }
- string name = c.Name;
- string inferredName = this.InferName(c.Expression, null);
- if (name == null)
- name = inferredName;
- if (name == null) {
- if (!this.names.TryGetValue(c, out name)) {
- name = "C" + this.names.Count;
- this.names[c] = name;
- }
- }
- this.WriteName(name);
- return cref;
- }
- internal virtual void WriteName(string s) {
- sb.Append(SqlIdentifier.QuoteCompoundIdentifier(s));
- }
- internal virtual void WriteVariableName(string s) {
- if (s.StartsWith("@",StringComparison.Ordinal))
- sb.Append(SqlIdentifier.QuoteCompoundIdentifier(s));
- else
- sb.Append(SqlIdentifier.QuoteCompoundIdentifier("@" + s));
- }
- internal override SqlExpression VisitParameter(SqlParameter p) {
- sb.Append(p.Name);
- return p;
- }
- internal override SqlExpression VisitValue(SqlValue value) {
- if (value.IsClientSpecified && !this.isDebugMode) {
- throw Error.InvalidFormatNode("Value");
- }
- else {
- this.FormatValue(value.Value);
- }
- return value;
- }
- internal override SqlExpression VisitClientParameter(SqlClientParameter cp) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("ClientParameter");
- }
- else {
- sb.Append("client-parameter(");
- object value;
- try {
- value = cp.Accessor.Compile().DynamicInvoke(new object[] { null });
- } catch (System.Reflection.TargetInvocationException e) {
- throw e.InnerException;
- }
- sb.Append(value);
- sb.Append(")");
- }
- return cp;
- }
- 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 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 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 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;
- }
- internal override SqlTable VisitTable(SqlTable tab) {
- string name = tab.Name;
- this.WriteName(name);
- return tab;
- }
- internal override SqlUserQuery VisitUserQuery(SqlUserQuery suq) {
- if (suq.Arguments.Count > 0) {
- // compute all the arg values...
- StringBuilder savesb = this.sb;
- this.sb = new StringBuilder();
- object[] args = new object[suq.Arguments.Count];
- for (int i = 0, n = args.Length; i < n; i++) {
- this.Visit(suq.Arguments[i]);
- args[i] = this.sb.ToString();
- this.sb.Length = 0;
- }
- this.sb = savesb;
- // append query with args...
- sb.Append(string.Format(CultureInfo.InvariantCulture, suq.QueryText, args));
- } else {
- sb.Append(suq.QueryText);
- }
- return suq;
- }
- internal override SqlExpression VisitUserColumn(SqlUserColumn suc) {
- sb.Append(suc.Name);
- return suc;
- }
- internal override SqlStoredProcedureCall VisitStoredProcedureCall(SqlStoredProcedureCall spc) {
- sb.Append("EXEC @RETURN_VALUE = ");
- this.WriteName(spc.Function.MappedName);
- sb.Append(" ");
- int pc = spc.Function.Parameters.Count;
- System.Diagnostics.Debug.Assert(spc.Arguments.Count >= pc);
- for (int i = 0; i < pc; i++) {
- MetaParameter mp = spc.Function.Parameters[i];
- if (i > 0) sb.Append(", ");
- this.WriteVariableName(mp.MappedName);
- sb.Append(" = ");
- this.Visit(spc.Arguments[i]);
- if (mp.Parameter.IsOut || mp.Parameter.ParameterType.IsByRef)
- sb.Append(" OUTPUT");
- }
- if (spc.Arguments.Count > pc) {
- if (pc > 0) sb.Append(", ");
- this.WriteVariableName(spc.Function.ReturnParameter.MappedName);
- sb.Append(" = ");
- this.Visit(spc.Arguments[pc]);
- sb.Append(" OUTPUT");
- }
- return spc;
- }
- internal override SqlAlias VisitAlias(SqlAlias alias) {
- bool isSelect = alias.Node is SqlSelect;
- int saveDepth = this.depth;
- string aliasName = null;
- string name = "";
- SqlTable table = alias.Node as SqlTable;
- if (table != null) {
- name = table.Name;
- }
- if (alias.Name == null) {
- if (!this.names.TryGetValue(alias, out aliasName)) {
- aliasName = "A" + this.names.Count;
- this.names[alias] = aliasName;
- }
- } else {
- aliasName = alias.Name;
- }
- if (isSelect) {
- this.depth++;
- sb.Append("(");
- this.NewLine();
- }
- this.Visit(alias.Node);
- if (isSelect) {
- this.NewLine();
- sb.Append(")");
- this.depth = saveDepth;
- }
- if (!this.suppressedAliases.Contains(alias) && aliasName != null && name != aliasName) {
- sb.Append(" AS ");
- this.WriteName(aliasName);
- }
- return alias;
- }
- internal override SqlExpression VisitAliasRef(SqlAliasRef aref) {
- sb.Append("AREF(");
- this.WriteAliasName(aref.Alias);
- sb.Append(")");
- return aref;
- }
- private void WriteAliasName(SqlAlias alias) {
- string aliasName = null;
- if (alias.Name == null) {
- if (!this.names.TryGetValue(alias, out aliasName)) {
- aliasName = "A" + this.names.Count;
- this.names[alias] = aliasName;
- }
- }
- else {
- aliasName = alias.Name;
- }
- this.WriteName(aliasName);
- }
- internal override SqlNode VisitUnion(SqlUnion su) {
- sb.Append("(");
- int saveDepth = this.depth;
- this.depth++;
- this.NewLine();
- this.Visit(su.Left);
- this.NewLine();
- sb.Append("UNION");
- if (su.All) {
- sb.Append(" ALL");
- }
- this.NewLine();
- this.Visit(su.Right);
- this.NewLine();
- sb.Append(")");
- this.depth = saveDepth;
- return su;
- }
- internal override SqlExpression VisitExprSet(SqlExprSet xs) {
- if (this.isDebugMode) {
- sb.Append("ES(");
- for (int i = 0, n = xs.Expressions.Count; i < n; i++) {
- if (i > 0)
- sb.Append(", ");
- this.Visit(xs.Expressions[i]);
- }
- sb.Append(")");
- } else {
- // only show the first one
- this.Visit(xs.GetFirstExpression());
- }
- return xs;
- }
- internal override SqlRow VisitRow(SqlRow row) {
- for (int i = 0, n = row.Columns.Count; i < n; i++) {
- SqlColumn c = row.Columns[i];
- if (i > 0)
- sb.Append(", ");
- this.Visit(c.Expression);
- string name = c.Name;
- string inferredName = this.InferName(c.Expression, null);
- if (name == null)
- name = inferredName;
- if (name == null) {
- if (!this.names.TryGetValue(c, out name)) {
- name = "C" + this.names.Count;
- this.names[c] = name;
- }
- }
- if (name != inferredName && !String.IsNullOrEmpty(name)) {
- sb.Append(" AS ");
- this.WriteName(name);
- }
- }
- return row;
- }
- internal override SqlExpression VisitNew(SqlNew sox) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("New");
- }
- sb.Append("new ");
- sb.Append(sox.ClrType.Name);
- sb.Append("{ ");
- // Visit Args
- for (int i = 0, n = sox.Args.Count; i < n; i++)
- {
- SqlExpression argExpr = sox.Args[i];
- if (i > 0) sb.Append(", ");
- sb.Append(sox.ArgMembers[i].Name);
- sb.Append(" = ");
- this.Visit(argExpr);
- }
- // Visit Members
- for (int i = 0, n = sox.Members.Count; i < n; i++) {
- SqlMemberAssign ma = sox.Members[i];
- if (i > 0) sb.Append(", ");
- string ename = this.InferName(ma.Expression, null);
- if (ename != ma.Member.Name) {
- sb.Append(ma.Member.Name);
- sb.Append(" = ");
- }
- this.Visit(ma.Expression);
- }
- sb.Append(" }");
- return sox;
- }
- internal override SqlExpression VisitClientArray(SqlClientArray scar) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("ClientArray");
- }
- sb.Append("new []{");
- for (int i = 0, n = scar.Expressions.Count; i < n; i++) {
- if (i > 0) sb.Append(", ");
- this.Visit(scar.Expressions[i]);
- }
- sb.Append("}");
- return scar;
- }
- internal override SqlNode VisitMember(SqlMember m) {
- this.Visit(m.Expression);
- sb.Append(".");
- sb.Append(m.Member.Name);
- return m;
- }
- internal virtual void NewLine() {
- if (sb.Length > 0) {
- sb.AppendLine();
- }
- for (int i = 0; i < this.depth; i++) {
- sb.Append(" ");
- }
- }
- internal override SqlSelect VisitSelect(SqlSelect ss) {
- if (ss.DoNotOutput) {
- return ss;
- }
- string from = null;
- if (ss.From != null) {
- StringBuilder savesb = this.sb;
- this.sb = new StringBuilder();
- if (this.IsSimpleCrossJoinList(ss.From)) {
- this.VisitCrossJoinList(ss.From);
- } else {
- this.Visit(ss.From);
- }
- from = this.sb.ToString();
- this.sb = savesb;
- }
- sb.Append("SELECT ");
- if (ss.IsDistinct) {
- sb.Append("DISTINCT ");
- }
- if (ss.Top != null) {
- sb.Append("TOP ");
- if (this.parenthesizeTop) {
- sb.Append("(");
- }
- this.Visit(ss.Top);
- if (this.parenthesizeTop) {
- sb.Append(")");
- }
- sb.Append(" ");
- if (ss.IsPercent) {
- sb.Append(" PERCENT ");
- }
- }
- if (ss.Row.Columns.Count > 0) {
- this.VisitRow(ss.Row);
- } else if (this.isDebugMode) {
- this.Visit(ss.Selection);
- } else {
- sb.Append("NULL AS [EMPTY]");
- }
- if (from != null) {
- this.NewLine();
- sb.Append("FROM ");
- sb.Append(from);
- }
- if (ss.Where != null) {
- this.NewLine();
- sb.Append("WHERE ");
- this.Visit(ss.Where);
- }
- if (ss.GroupBy.Count > 0) {
- this.NewLine();
- sb.Append("GROUP BY ");
- for (int i = 0, n = ss.GroupBy.Count; i < n; i++) {
- SqlExpression exp = ss.GroupBy[i];
- if (i > 0)
- sb.Append(", ");
- this.Visit(exp);
- }
- if (ss.Having != null) {
- this.NewLine();
- sb.Append("HAVING ");
- this.Visit(ss.Having);
- }
- }
- if (ss.OrderBy.Count > 0 && ss.OrderingType != SqlOrderingType.Never) {
- this.NewLine();
- sb.Append("ORDER BY ");
- for (int i = 0, n = ss.OrderBy.Count; i < n; i++) {
- SqlOrderExpression exp = ss.OrderBy[i];
- if (i > 0)
- sb.Append(", ");
- this.Visit(exp.Expression);
- if (exp.OrderType == SqlOrderType.Descending) {
- sb.Append(" DESC");
- }
- }
- }
- return ss;
- }
- internal virtual bool IsSimpleCrossJoinList(SqlNode node) {
- SqlJoin join = node as SqlJoin;
- if (join != null) {
- return join.JoinType == SqlJoinType.Cross &&
- this.IsSimpleCrossJoinList(join.Left) &&
- this.IsSimpleCrossJoinList(join.Right);
- }
- SqlAlias alias = node as SqlAlias;
- return (alias != null && alias.Node is SqlTable);
- }
- internal virtual void VisitCrossJoinList(SqlNode node) {
- SqlJoin join = node as SqlJoin;
- if (join != null) {
- this.VisitCrossJoinList(join.Left);
- sb.Append(", ");
- this.VisitCrossJoinList(join.Right);
- } else {
- this.Visit(node);
- }
- }
- internal void VisitJoinSource(SqlSource src) {
- if (src.NodeType == SqlNodeType.Join) {
- this.depth++;
- sb.Append("(");
- this.Visit(src);
- sb.Append(")");
- this.depth--;
- } else {
- this.Visit(src);
- }
- }
- internal override SqlSource VisitJoin(SqlJoin join) {
- this.Visit(join.Left);
- this.NewLine();
- switch (join.JoinType) {
- case SqlJoinType.CrossApply:
- sb.Append("CROSS APPLY ");
- break;
- case SqlJoinType.Cross:
- sb.Append("CROSS JOIN ");
- break;
- case SqlJoinType.Inner:
- sb.Append("INNER JOIN ");
- break;
- case SqlJoinType.LeftOuter:
- sb.Append("LEFT OUTER JOIN ");
- break;
- case SqlJoinType.OuterApply:
- sb.Append("OUTER APPLY ");
- break;
- }
- SqlJoin rightJoin = join.Right as SqlJoin;
- if (rightJoin == null ||
- (rightJoin.JoinType == SqlJoinType.Cross
- && join.JoinType != SqlJoinType.CrossApply
- && join.JoinType != SqlJoinType.OuterApply)) {
- this.Visit(join.Right);
- } else {
- this.VisitJoinSource(join.Right);
- }
- if (join.Condition != null) {
- sb.Append(" ON ");
- this.Visit(join.Condition);
- } else if (this.RequiresOnCondition(join.JoinType)) {
- sb.Append(" ON 1=1 ");
- }
- return join;
- }
- [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")]
- internal bool RequiresOnCondition(SqlJoinType joinType) {
- switch (joinType) {
- case SqlJoinType.CrossApply:
- case SqlJoinType.Cross:
- case SqlJoinType.OuterApply:
- return false;
- case SqlJoinType.Inner:
- case SqlJoinType.LeftOuter:
- return true;
- default:
- throw Error.InvalidFormatNode(joinType);
- }
- }
- internal override SqlBlock VisitBlock(SqlBlock block) {
- for (int i = 0, n = block.Statements.Count; i < n; i++) {
- this.Visit(block.Statements[i]);
- if (i < n - 1) {
- SqlSelect select = block.Statements[i+1] as SqlSelect;
- if (select == null || !select.DoNotOutput) {
- this.NewLine();
- this.NewLine();
- }
- }
- }
- return block;
- }
- internal override SqlExpression VisitClientQuery(SqlClientQuery cq) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("ClientQuery");
- }
- sb.Append("client(");
- for (int i = 0, n = cq.Arguments.Count; i < n; i++) {
- if (i > 0) sb.Append(", ");
- this.Visit(cq.Arguments[i]);
- }
- sb.Append("; ");
- this.Visit(cq.Query);
- sb.Append(")");
- return cq;
- }
- internal override SqlExpression VisitJoinedCollection(SqlJoinedCollection jc) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("JoinedCollection");
- }
- sb.Append("big-join(");
- this.Visit(jc.Expression);
- sb.Append(", ");
- this.Visit(jc.Count);
- sb.Append(")");
- return jc;
- }
- internal override SqlStatement VisitDelete(SqlDelete sd) {
- sb.Append("DELETE FROM ");
- this.suppressedAliases.Add(sd.Select.From);
- this.Visit(sd.Select.From);
- if (sd.Select.Where != null) {
- sb.Append(" WHERE ");
- this.Visit(sd.Select.Where);
- }
- this.suppressedAliases.Remove(sd.Select.From);
- return sd;
- }
- internal override SqlStatement VisitInsert(SqlInsert si) {
- if (si.OutputKey != null) {
- sb.Append("DECLARE @output TABLE(");
- this.WriteName(si.OutputKey.Name);
- sb.Append(" ");
- sb.Append(si.OutputKey.SqlType.ToQueryString());
- sb.Append(")");
- this.NewLine();
- if (si.OutputToLocal) {
- sb.Append("DECLARE @id ");
- sb.Append(si.OutputKey.SqlType.ToQueryString());
- this.NewLine();
- }
- }
- sb.Append("INSERT INTO ");
- this.Visit(si.Table);
- if (si.Row.Columns.Count != 0) {
- // INSERT INTO table (...columns...) VALUES (...values...)
- sb.Append("(");
- for (int i = 0, n = si.Row.Columns.Count; i < n; i++) {
- if (i > 0) sb.Append(", ");
- this.WriteName(si.Row.Columns[i].Name);
- }
- sb.Append(")");
- }
- if (si.OutputKey != null) {
- this.NewLine();
- sb.Append("OUTPUT INSERTED.");
- this.WriteName(si.OutputKey.MetaMember.MappedName);
- sb.Append(" INTO @output");
- }
- if (si.Row.Columns.Count == 0) {
- sb.Append(" DEFAULT VALUES");
- }
- else {
- // VALUES (...values...)
- this.NewLine();
- sb.Append("VALUES (");
- if (this.isDebugMode && si.Row.Columns.Count == 0) {
- this.Visit(si.Expression);
- } else {
- for (int i = 0, n = si.Row.Columns.Count; i < n; i++) {
- if (i > 0) sb.Append(", ");
- this.Visit( si.Row.Columns[i].Expression);
- }
- }
- sb.Append(")");
- }
- if (si.OutputKey != null) {
- this.NewLine();
- if (si.OutputToLocal) {
- sb.Append("SELECT @id = ");
- sb.Append(si.OutputKey.Name);
- sb.Append(" FROM @output");
- }
- else {
- sb.Append("SELECT ");
- this.WriteName(si.OutputKey.Name);
- sb.Append(" FROM @output");
- }
- }
- return si;
- }
- internal override SqlStatement VisitUpdate(SqlUpdate su) {
- sb.Append("UPDATE ");
- this.suppressedAliases.Add(su.Select.From);
- this.Visit(su.Select.From);
- this.NewLine();
- sb.Append("SET ");
- for (int i = 0, n = su.Assignments.Count; i < n; i++) {
- if (i > 0) sb.Append(", ");
- SqlAssign sa = su.Assignments[i];
- this.Visit(sa.LValue);
- sb.Append(" = ");
- this.Visit(sa.RValue);
- }
- if (su.Select.Where != null) {
- this.NewLine();
- sb.Append("WHERE ");
- this.Visit(su.Select.Where);
- }
- this.suppressedAliases.Remove(su.Select.From);
- return su;
- }
- internal override SqlStatement VisitAssign(SqlAssign sa) {
- sb.Append("SET ");
- this.Visit(sa.LValue);
- sb.Append(" = ");
- this.Visit(sa.RValue);
- return sa;
- }
- internal override SqlExpression VisitSearchedCase(SqlSearchedCase c) {
- this.depth++;
- this.NewLine();
- sb.Append("(CASE ");
- this.depth++;
- for (int i = 0, n = c.Whens.Count; i < n; i++) {
- SqlWhen when = c.Whens[i];
- this.NewLine();
- sb.Append("WHEN ");
- this.Visit(when.Match);
- sb.Append(" THEN ");
- this.Visit(when.Value);
- }
- if (c.Else != null) {
- this.NewLine();
- sb.Append("ELSE ");
- this.Visit(c.Else);
- }
- this.depth--;
- this.NewLine();
- sb.Append(" END)");
- this.depth--;
- return c;
- }
- internal override SqlExpression VisitSimpleCase(SqlSimpleCase c) {
- this.depth++;
- this.NewLine();
- sb.Append("(CASE");
- this.depth++;
- if (c.Expression != null) {
- sb.Append(" ");
- this.Visit(c.Expression);
- }
- for (int i = 0, n = c.Whens.Count; i < n; i++) {
- SqlWhen when = c.Whens[i];
- if (i == n - 1 && when.Match == null) {
- this.NewLine();
- sb.Append("ELSE ");
- this.Visit(when.Value);
- } else {
- this.NewLine();
- sb.Append("WHEN ");
- this.Visit(when.Match);
- sb.Append(" THEN ");
- this.Visit(when.Value);
- }
- }
- this.depth--;
- this.NewLine();
- sb.Append(" END)");
- this.depth--;
- return c;
- }
- internal override SqlExpression VisitClientCase(SqlClientCase c) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("ClientCase");
- }
- this.depth++;
- this.NewLine();
- sb.Append("(CASE");
- this.depth++;
- if (c.Expression != null) {
- sb.Append(" ");
- this.Visit(c.Expression);
- }
- for (int i = 0, n = c.Whens.Count; i < n; i++) {
- SqlClientWhen when = c.Whens[i];
- if (i == n - 1 && when.Match == null) {
- this.NewLine();
- sb.Append("ELSE ");
- this.Visit(when.Value);
- } else {
- this.NewLine();
- sb.Append("WHEN ");
- this.Visit(when.Match);
- sb.Append(" THEN ");
- this.Visit(when.Value);
- }
- }
- this.depth--;
- this.NewLine();
- sb.Append(" END)");
- this.depth--;
- return c;
- }
- internal override SqlExpression VisitTypeCase(SqlTypeCase c) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("TypeCase");
- }
- this.depth++;
- this.NewLine();
- sb.Append("(CASE");
- this.depth++;
- if (c.Discriminator != null) {
- sb.Append(" ");
- this.Visit(c.Discriminator);
- }
- for (int i = 0, n = c.Whens.Count; i < n; i++) {
- SqlTypeCaseWhen when = c.Whens[i];
- if (i == n - 1 && when.Match == null) {
- this.NewLine();
- sb.Append("ELSE ");
- this.Visit(when.TypeBinding);
- } else {
- this.NewLine();
- sb.Append("WHEN ");
- this.Visit(when.Match);
- sb.Append(" THEN ");
- this.Visit(when.TypeBinding);
- }
- }
- this.depth--;
- this.NewLine();
- sb.Append(" END)");
- this.depth--;
- return c;
- }
- internal override SqlExpression VisitVariable(SqlVariable v) {
- sb.Append(v.Name);
- return v;
- }
- private string InferName(SqlExpression exp, string def) {
- if (exp == null) return null;
- switch (exp.NodeType) {
- case SqlNodeType.Member:
- return ((SqlMember)exp).Member.Name;
- case SqlNodeType.Column:
- return ((SqlColumn)exp).Name;
- case SqlNodeType.ColumnRef:
- return ((SqlColumnRef)exp).Column.Name;
- case SqlNodeType.ExprSet:
- return this.InferName(((SqlExprSet)exp).Expressions[0], def);
- default:
- return def;
- }
- }
- private void FormatType(ProviderType type) {
- sb.Append(type.ToQueryString());
- }
- [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification="These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
- internal virtual void FormatValue(object value) {
- if (value == null) {
- sb.Append("NULL");
- } else {
- Type t = value.GetType();
- if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
- t = t.GetGenericArguments()[0];
- TypeCode tc = Type.GetTypeCode(t);
- switch (tc) {
- case TypeCode.Char:
- case TypeCode.String:
- case TypeCode.DateTime:
- sb.Append("'");
- sb.Append(this.EscapeSingleQuotes(value.ToString()));
- sb.Append("'");
- return;
- case TypeCode.Boolean:
- sb.Append(this.GetBoolValue((bool)value));
- return;
- case TypeCode.Byte:
- case TypeCode.Decimal:
- case TypeCode.Double:
- case TypeCode.Int16:
- case TypeCode.Int32:
- case TypeCode.Int64:
- case TypeCode.SByte:
- case TypeCode.Single:
- case TypeCode.UInt16:
- case TypeCode.UInt32:
- case TypeCode.UInt64:
- sb.Append(value);
- return;
- case TypeCode.Object: {
- if (value is Guid) {
- sb.Append("'");
- sb.Append(value);
- sb.Append("'");
- return;
- }
- Type valueType = value as Type;
- if (valueType != null) {
- if (this.isDebugMode) {
- sb.Append("typeof(");
- sb.Append(valueType.Name);
- sb.Append(")");
- } else {
- this.FormatValue("");
- }
- return;
- }
- break;
- }
- }
- if (this.isDebugMode) {
- sb.Append("value(");
- sb.Append(value.ToString());
- sb.Append(")");
- }
- else {
- throw Error.ValueHasNoLiteralInSql(value);
- }
- }
- }
- internal virtual string GetBoolValue(bool value) {
- return value ? "1" : "0";
- }
- internal virtual string EscapeSingleQuotes(string str) {
- if (str.IndexOf('\'') < 0) return str;
- StringBuilder tempStringBuilder = new StringBuilder();
- foreach (char c in str) {
- if (c == '\'') {
- tempStringBuilder.Append("''");
- } else {
- tempStringBuilder.Append("'");
- }
- }
- return tempStringBuilder.ToString();
- }
- [SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity", Justification="These issues are related to our use of if-then and case statements for node types, which adds to the complexity count however when reviewed they are easy to navigate and understand.")]
- internal virtual string GetOperator(SqlNodeType nt) {
- switch (nt) {
- case SqlNodeType.Add: return "+";
- case SqlNodeType.Sub: return "-";
- case SqlNodeType.Mul: return "*";
- case SqlNodeType.Div: return "/";
- case SqlNodeType.Mod: return "%";
- case SqlNodeType.Concat: return "+";
- case SqlNodeType.BitAnd: return "&";
- case SqlNodeType.BitOr: return "|";
- case SqlNodeType.BitXor: return "^";
- case SqlNodeType.And: return "AND";
- case SqlNodeType.Or: return "OR";
- case SqlNodeType.GE: return ">=";
- case SqlNodeType.GT: return ">";
- case SqlNodeType.LE: return "<=";
- case SqlNodeType.LT: return "<";
- case SqlNodeType.EQ: return "=";
- case SqlNodeType.EQ2V: return "=";
- case SqlNodeType.NE: return "<>";
- case SqlNodeType.NE2V: return "<>";
- case SqlNodeType.Not: return "NOT";
- case SqlNodeType.Not2V: return "NOT";
- case SqlNodeType.BitNot: return "~";
- case SqlNodeType.Negate: return "-";
- case SqlNodeType.IsNull: return "IS NULL";
- case SqlNodeType.IsNotNull: return "IS NOT NULL";
- case SqlNodeType.Count: return "COUNT";
- case SqlNodeType.LongCount: return "COUNT_BIG";
- case SqlNodeType.Min: return "MIN";
- case SqlNodeType.Max: return "MAX";
- case SqlNodeType.Sum: return "SUM";
- case SqlNodeType.Avg: return "AVG";
- case SqlNodeType.Stddev: return "STDEV";
- case SqlNodeType.ClrLength: return "CLRLENGTH";
- default:
- throw Error.InvalidFormatNode(nt);
- }
- }
- internal override SqlNode VisitLink(SqlLink link) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("Link");
- }
- if (link.Expansion != null) {
- sb.Append("LINK(");
- this.Visit(link.Expansion);
- sb.Append(")");
- } else {
- sb.Append("LINK(");
- for (int i = 0, n = link.KeyExpressions.Count; i < n; i++) {
- if (i > 0) sb.Append(", ");
- this.Visit(link.KeyExpressions[i]);
- }
- sb.Append(")");
- }
- return link;
- }
- internal override SqlMemberAssign VisitMemberAssign(SqlMemberAssign ma) {
- throw Error.InvalidFormatNode("MemberAssign");
- }
- internal override SqlExpression VisitMethodCall(SqlMethodCall mc) {
- if (!this.isDebugMode) {
- throw Error.InvalidFormatNode("MethodCall");
- }
- if (mc.Method.IsStatic) {
- sb.Append(mc.Method.DeclaringType);
- } else {
- this.Visit(mc.Object);
- }
- sb.Append(".");
- sb.Append(mc.Method.Name);
- sb.Append("(");
- for (int i = 0, n = mc.Arguments.Count; i < n; i++) {
- if (i > 0) sb.Append(", ");
- this.Visit(mc.Arguments[i]);
- }
- sb.Append(")");
- return mc;
- }
- internal override SqlExpression VisitOptionalValue(SqlOptionalValue sov) {
- if (this.isDebugMode) {
- sb.Append("opt(");
- this.Visit(sov.HasValue);
- sb.Append(", ");
- this.Visit(sov.Value);
- sb.Append(")");
- return sov;
- } else {
- throw Error.InvalidFormatNode("OptionalValue");
- }
- }
- internal override SqlExpression VisitUserRow(SqlUserRow row) {
- if (!isDebugMode) {
- throw Error.InvalidFormatNode("UserRow");
- }
- return row;
- }
- internal override SqlExpression VisitGrouping(SqlGrouping g) {
- if (!isDebugMode) {
- throw Error.InvalidFormatNode("Grouping");
- }
- sb.Append("Group(");
- this.Visit(g.Key);
- sb.Append(", ");
- this.Visit(g.Group);
- sb.Append(")");
- return g;
- }
- }
- class AliasMapper : SqlVisitor {
- Dictionary<SqlColumn, SqlAlias> aliasMap;
- SqlAlias currentAlias;
- internal AliasMapper(Dictionary<SqlColumn, SqlAlias> aliasMap) {
- this.aliasMap = aliasMap;
- }
- internal override SqlAlias VisitAlias(SqlAlias a) {
- SqlAlias save = this.currentAlias;
- this.currentAlias = a;
- base.VisitAlias(a);
- this.currentAlias = save;
- return a;
- }
- internal override SqlExpression VisitColumn(SqlColumn col) {
- this.aliasMap[col] = this.currentAlias;
- this.Visit(col.Expression);
- return col;
- }
- internal override SqlRow VisitRow(SqlRow row) {
- foreach(SqlColumn col in row.Columns) {
- this.VisitColumn(col);
- }
- return row;
- }
- internal override SqlTable VisitTable(SqlTable tab) {
- foreach(SqlColumn col in tab.Columns) {
- this.VisitColumn(col);
- }
- return tab;
- }
- internal override SqlExpression VisitTableValuedFunctionCall(SqlTableValuedFunctionCall fc) {
- foreach(SqlColumn col in fc.Columns) {
- this.VisitColumn(col);
- }
- return fc;
- }
- }
- }
- }
|