SqlFormatter.cs 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477
  1. using System;
  2. using System.Globalization;
  3. using System.Collections.Generic;
  4. using System.Data;
  5. using System.Text;
  6. using System.Data.Linq.Mapping;
  7. using System.Data.Linq.Provider;
  8. using System.Linq;
  9. using System.Data.SqlClient;
  10. using System.Diagnostics.CodeAnalysis;
  11. namespace System.Data.Linq.SqlClient {
  12. internal class SqlFormatter : DbFormatter {
  13. private Visitor visitor;
  14. internal SqlFormatter() {
  15. this.visitor = new Visitor();
  16. }
  17. internal override string Format(SqlNode node, bool isDebug) {
  18. return this.visitor.Format(node, isDebug);
  19. }
  20. internal string[] FormatBlock(SqlBlock block, bool isDebug) {
  21. List<string> results = new List<string>(block.Statements.Count);
  22. for (int i = 0, n = block.Statements.Count; i < n; i++) {
  23. SqlStatement stmt = block.Statements[i];
  24. SqlSelect select = stmt as SqlSelect;
  25. if (select != null && select.DoNotOutput) {
  26. continue;
  27. } else {
  28. results.Add(this.Format(stmt, isDebug));
  29. }
  30. }
  31. return results.ToArray();
  32. }
  33. internal override string Format(SqlNode node) {
  34. return this.visitor.Format(node);
  35. }
  36. internal bool ParenthesizeTop {
  37. get { return this.visitor.parenthesizeTop; }
  38. set { this.visitor.parenthesizeTop = value; }
  39. }
  40. [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.")]
  41. internal class Visitor : SqlVisitor {
  42. internal StringBuilder sb;
  43. internal bool isDebugMode;
  44. internal List<SqlSource> suppressedAliases = new List<SqlSource>();
  45. internal Dictionary<SqlNode, string> names = new Dictionary<SqlNode, string>();
  46. internal Dictionary<SqlColumn, SqlAlias> aliasMap = new Dictionary<SqlColumn, SqlAlias>();
  47. internal int depth;
  48. internal bool parenthesizeTop;
  49. internal Visitor() {
  50. }
  51. internal string Format(SqlNode node, bool isDebug) {
  52. this.sb = new StringBuilder();
  53. this.isDebugMode = isDebug;
  54. this.aliasMap.Clear();
  55. if (isDebug) {
  56. new AliasMapper(this.aliasMap).Visit(node);
  57. }
  58. this.Visit(node);
  59. return this.sb.ToString();
  60. }
  61. internal string Format(SqlNode node) {
  62. return this.Format(node, false);
  63. }
  64. [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.")]
  65. internal virtual void VisitWithParens(SqlNode node, SqlNode outer) {
  66. if (node == null)
  67. return;
  68. switch (node.NodeType) {
  69. case SqlNodeType.ColumnRef:
  70. case SqlNodeType.Value:
  71. case SqlNodeType.Member:
  72. case SqlNodeType.Parameter:
  73. case SqlNodeType.FunctionCall:
  74. case SqlNodeType.TableValuedFunctionCall:
  75. case SqlNodeType.OuterJoinedValue:
  76. this.Visit(node);
  77. break;
  78. case SqlNodeType.Add:
  79. case SqlNodeType.Mul:
  80. case SqlNodeType.And:
  81. case SqlNodeType.Or:
  82. case SqlNodeType.Not:
  83. case SqlNodeType.Not2V:
  84. case SqlNodeType.BitAnd:
  85. case SqlNodeType.BitOr:
  86. case SqlNodeType.BitXor:
  87. case SqlNodeType.BitNot:
  88. if (outer.NodeType != node.NodeType)
  89. goto default;
  90. this.Visit(node);
  91. break;
  92. default:
  93. this.sb.Append("(");
  94. this.Visit(node);
  95. this.sb.Append(")");
  96. break;
  97. }
  98. }
  99. internal override SqlExpression VisitNop(SqlNop nop) {
  100. if (!this.isDebugMode) {
  101. throw Error.InvalidFormatNode("NOP");
  102. }
  103. sb.Append("NOP()");
  104. return nop;
  105. }
  106. [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.")]
  107. internal override SqlExpression VisitUnaryOperator(SqlUnary uo) {
  108. switch (uo.NodeType) {
  109. case SqlNodeType.Not:
  110. case SqlNodeType.Not2V:
  111. this.sb.Append(GetOperator(uo.NodeType));
  112. this.sb.Append(" ");
  113. this.VisitWithParens(uo.Operand, uo);
  114. break;
  115. case SqlNodeType.Negate:
  116. case SqlNodeType.BitNot:
  117. this.sb.Append(GetOperator(uo.NodeType));
  118. this.VisitWithParens(uo.Operand, uo);
  119. break;
  120. case SqlNodeType.Count:
  121. case SqlNodeType.LongCount:
  122. case SqlNodeType.Max:
  123. case SqlNodeType.Min:
  124. case SqlNodeType.Sum:
  125. case SqlNodeType.Avg:
  126. case SqlNodeType.Stddev:
  127. case SqlNodeType.ClrLength:{
  128. this.sb.Append(GetOperator(uo.NodeType));
  129. this.sb.Append("(");
  130. if (uo.Operand == null) {
  131. this.sb.Append("*");
  132. } else {
  133. this.Visit(uo.Operand);
  134. }
  135. this.sb.Append(")");
  136. break;
  137. }
  138. case SqlNodeType.IsNull:
  139. case SqlNodeType.IsNotNull: {
  140. this.VisitWithParens(uo.Operand, uo);
  141. sb.Append(" ");
  142. sb.Append(GetOperator(uo.NodeType));
  143. break;
  144. }
  145. case SqlNodeType.Convert: {
  146. this.sb.Append("CONVERT(");
  147. QueryFormatOptions options = QueryFormatOptions.None;
  148. if(uo.Operand.SqlType.CanSuppressSizeForConversionToString) {
  149. options = QueryFormatOptions.SuppressSize;
  150. }
  151. this.sb.Append(uo.SqlType.ToQueryString(options));
  152. this.sb.Append(",");
  153. this.Visit(uo.Operand);
  154. this.sb.Append(")");
  155. break;
  156. }
  157. case SqlNodeType.ValueOf:
  158. case SqlNodeType.OuterJoinedValue:
  159. this.Visit(uo.Operand); // no op
  160. break;
  161. default:
  162. throw Error.InvalidFormatNode(uo.NodeType);
  163. }
  164. return uo;
  165. }
  166. internal override SqlRowNumber VisitRowNumber(SqlRowNumber rowNumber) {
  167. sb.Append("ROW_NUMBER() OVER (ORDER BY ");
  168. for (int i = 0, n = rowNumber.OrderBy.Count; i < n; i++) {
  169. SqlOrderExpression exp = rowNumber.OrderBy[i];
  170. if (i > 0) sb.Append(", ");
  171. this.Visit(exp.Expression);
  172. if (exp.OrderType == SqlOrderType.Descending) {
  173. sb.Append(" DESC");
  174. }
  175. }
  176. sb.Append(")");
  177. return rowNumber;
  178. }
  179. internal override SqlExpression VisitLift(SqlLift lift) {
  180. this.Visit(lift.Expression);
  181. return lift;
  182. }
  183. internal override SqlExpression VisitBinaryOperator(SqlBinary bo) {
  184. switch (bo.NodeType) {
  185. case SqlNodeType.Coalesce:
  186. sb.Append("COALESCE(");
  187. this.Visit(bo.Left);
  188. sb.Append(",");
  189. this.Visit(bo.Right);
  190. sb.Append(")");
  191. break;
  192. default:
  193. this.VisitWithParens(bo.Left, bo);
  194. sb.Append(" ");
  195. sb.Append(GetOperator(bo.NodeType));
  196. sb.Append(" ");
  197. this.VisitWithParens(bo.Right, bo);
  198. break;
  199. }
  200. return bo;
  201. }
  202. internal override SqlExpression VisitBetween(SqlBetween between) {
  203. this.VisitWithParens(between.Expression, between);
  204. sb.Append(" BETWEEN ");
  205. this.Visit(between.Start);
  206. sb.Append(" AND ");
  207. this.Visit(between.End);
  208. return between;
  209. }
  210. internal override SqlExpression VisitIn(SqlIn sin) {
  211. this.VisitWithParens(sin.Expression, sin);
  212. sb.Append(" IN (");
  213. for (int i = 0, n = sin.Values.Count; i < n; i++) {
  214. if (i > 0) {
  215. sb.Append(", ");
  216. }
  217. this.Visit(sin.Values[i]);
  218. }
  219. sb.Append(")");
  220. return sin;
  221. }
  222. internal override SqlExpression VisitLike(SqlLike like) {
  223. this.VisitWithParens(like.Expression, like);
  224. sb.Append(" LIKE ");
  225. this.Visit(like.Pattern);
  226. if (like.Escape != null) {
  227. sb.Append(" ESCAPE ");
  228. this.Visit(like.Escape);
  229. }
  230. return like;
  231. }
  232. internal override SqlExpression VisitFunctionCall(SqlFunctionCall fc) {
  233. if (fc.Name.Contains(".")) {
  234. // Assume UDF -- bracket the name.
  235. this.WriteName(fc.Name);
  236. } else {
  237. // No ".", so we assume it's a system function name and leave it alone.
  238. sb.Append(fc.Name);
  239. }
  240. sb.Append("(");
  241. for (int i = 0, n = fc.Arguments.Count; i < n; i++) {
  242. if (i > 0)
  243. sb.Append(", ");
  244. this.Visit(fc.Arguments[i]);
  245. }
  246. sb.Append(")");
  247. return fc;
  248. }
  249. internal override SqlExpression VisitTableValuedFunctionCall(SqlTableValuedFunctionCall fc) {
  250. // both scalar and table valued functions are formatted the same
  251. return VisitFunctionCall(fc);
  252. }
  253. internal override SqlExpression VisitCast(SqlUnary c) {
  254. sb.Append("CAST(");
  255. this.Visit(c.Operand);
  256. sb.Append(" AS ");
  257. QueryFormatOptions options = QueryFormatOptions.None;
  258. if (c.Operand.SqlType.CanSuppressSizeForConversionToString) {
  259. options = QueryFormatOptions.SuppressSize;
  260. }
  261. sb.Append(c.SqlType.ToQueryString(options));
  262. sb.Append(")");
  263. return c;
  264. }
  265. internal override SqlExpression VisitTreat(SqlUnary t) {
  266. sb.Append("TREAT(");
  267. this.Visit(t.Operand);
  268. sb.Append(" AS ");
  269. this.FormatType(t.SqlType);
  270. sb.Append(")");
  271. return t;
  272. }
  273. internal override SqlExpression VisitColumn(SqlColumn c) {
  274. if (!this.isDebugMode) {
  275. throw Error.InvalidFormatNode("Column");
  276. }
  277. sb.Append("COLUMN(");
  278. if (c.Expression != null) {
  279. this.Visit(c.Expression);
  280. }
  281. else {
  282. string aliasName = null;
  283. if (c.Alias != null) {
  284. if (c.Alias.Name == null) {
  285. if (!this.names.TryGetValue(c.Alias, out aliasName)) {
  286. aliasName = "A" + this.names.Count;
  287. this.names[c.Alias] = aliasName;
  288. }
  289. } else {
  290. aliasName = c.Alias.Name;
  291. }
  292. }
  293. sb.Append(aliasName);
  294. sb.Append(".");
  295. sb.Append(c.Name);
  296. }
  297. sb.Append(")");
  298. return c;
  299. }
  300. internal override SqlExpression VisitDiscriminatedType(SqlDiscriminatedType dt) {
  301. if (this.isDebugMode) {
  302. sb.Append("DTYPE(");
  303. }
  304. base.VisitDiscriminatedType(dt);
  305. if (this.isDebugMode) {
  306. sb.Append(")");
  307. }
  308. return dt;
  309. }
  310. internal override SqlExpression VisitDiscriminatorOf(SqlDiscriminatorOf dof) {
  311. if (this.isDebugMode) {
  312. sb.Append("DISCO(");
  313. }
  314. base.VisitDiscriminatorOf(dof);
  315. if (this.isDebugMode) {
  316. sb.Append(")");
  317. }
  318. return dof;
  319. }
  320. internal override SqlExpression VisitSimpleExpression(SqlSimpleExpression simple) {
  321. if (!this.isDebugMode) {
  322. throw Error.InvalidFormatNode("SIMPLE");
  323. }
  324. sb.Append("SIMPLE(");
  325. base.VisitSimpleExpression(simple);
  326. sb.Append(")");
  327. return simple;
  328. }
  329. internal override SqlExpression VisitSharedExpression(SqlSharedExpression shared) {
  330. if (!this.isDebugMode) {
  331. throw Error.InvalidFormatNode("Shared");
  332. }
  333. sb.Append("SHARED(");
  334. this.Visit(shared.Expression);
  335. sb.Append(")");
  336. return shared;
  337. }
  338. internal override SqlExpression VisitSharedExpressionRef(SqlSharedExpressionRef sref) {
  339. if (!this.isDebugMode) {
  340. throw Error.InvalidFormatNode("SharedRef");
  341. }
  342. sb.Append("SHAREDREF(");
  343. this.Visit(sref.SharedExpression.Expression);
  344. sb.Append(")");
  345. return sref;
  346. }
  347. internal override SqlExpression VisitColumnRef(SqlColumnRef cref) {
  348. string aliasName = null;
  349. SqlColumn c = cref.Column;
  350. SqlAlias alias = c.Alias;
  351. if (alias == null) {
  352. this.aliasMap.TryGetValue(c, out alias);
  353. }
  354. if (alias != null) {
  355. if (alias.Name == null) {
  356. if (!this.names.TryGetValue(alias, out aliasName)) {
  357. aliasName = "A" + this.names.Count;
  358. this.names[c.Alias] = aliasName;
  359. }
  360. } else {
  361. aliasName = c.Alias.Name;
  362. }
  363. }
  364. if (!this.suppressedAliases.Contains(c.Alias) && aliasName != null && aliasName.Length != 0) {
  365. this.WriteName(aliasName);
  366. sb.Append(".");
  367. }
  368. string name = c.Name;
  369. string inferredName = this.InferName(c.Expression, null);
  370. if (name == null)
  371. name = inferredName;
  372. if (name == null) {
  373. if (!this.names.TryGetValue(c, out name)) {
  374. name = "C" + this.names.Count;
  375. this.names[c] = name;
  376. }
  377. }
  378. this.WriteName(name);
  379. return cref;
  380. }
  381. internal virtual void WriteName(string s) {
  382. sb.Append(SqlIdentifier.QuoteCompoundIdentifier(s));
  383. }
  384. internal virtual void WriteVariableName(string s) {
  385. if (s.StartsWith("@",StringComparison.Ordinal))
  386. sb.Append(SqlIdentifier.QuoteCompoundIdentifier(s));
  387. else
  388. sb.Append(SqlIdentifier.QuoteCompoundIdentifier("@" + s));
  389. }
  390. internal override SqlExpression VisitParameter(SqlParameter p) {
  391. sb.Append(p.Name);
  392. return p;
  393. }
  394. internal override SqlExpression VisitValue(SqlValue value) {
  395. if (value.IsClientSpecified && !this.isDebugMode) {
  396. throw Error.InvalidFormatNode("Value");
  397. }
  398. else {
  399. this.FormatValue(value.Value);
  400. }
  401. return value;
  402. }
  403. internal override SqlExpression VisitClientParameter(SqlClientParameter cp) {
  404. if (!this.isDebugMode) {
  405. throw Error.InvalidFormatNode("ClientParameter");
  406. }
  407. else {
  408. sb.Append("client-parameter(");
  409. object value;
  410. try {
  411. value = cp.Accessor.Compile().DynamicInvoke(new object[] { null });
  412. } catch (System.Reflection.TargetInvocationException e) {
  413. throw e.InnerException;
  414. }
  415. sb.Append(value);
  416. sb.Append(")");
  417. }
  418. return cp;
  419. }
  420. internal override SqlExpression VisitScalarSubSelect(SqlSubSelect ss) {
  421. int saveDepth = this.depth;
  422. this.depth++;
  423. if (this.isDebugMode) {
  424. sb.Append("SCALAR");
  425. }
  426. sb.Append("(");
  427. this.NewLine();
  428. this.Visit(ss.Select);
  429. this.NewLine();
  430. sb.Append(")");
  431. this.depth = saveDepth;
  432. return ss;
  433. }
  434. internal override SqlExpression VisitElement(SqlSubSelect elem) {
  435. if (!this.isDebugMode) {
  436. throw Error.InvalidFormatNode("Element");
  437. }
  438. int saveDepth = this.depth;
  439. this.depth++;
  440. sb.Append("ELEMENT(");
  441. this.NewLine();
  442. this.Visit(elem.Select);
  443. this.NewLine();
  444. sb.Append(")");
  445. this.depth = saveDepth;
  446. return elem;
  447. }
  448. internal override SqlExpression VisitMultiset(SqlSubSelect sms) {
  449. if (!this.isDebugMode) {
  450. throw Error.InvalidFormatNode("Multiset");
  451. }
  452. int saveDepth = this.depth;
  453. this.depth++;
  454. sb.Append("MULTISET(");
  455. this.NewLine();
  456. this.Visit(sms.Select);
  457. this.NewLine();
  458. sb.Append(")");
  459. this.depth = saveDepth;
  460. return sms;
  461. }
  462. internal override SqlExpression VisitExists(SqlSubSelect sqlExpr) {
  463. int saveDepth = this.depth;
  464. this.depth++;
  465. sb.Append("EXISTS(");
  466. this.NewLine();
  467. this.Visit(sqlExpr.Select);
  468. this.NewLine();
  469. sb.Append(")");
  470. this.depth = saveDepth;
  471. return sqlExpr;
  472. }
  473. internal override SqlTable VisitTable(SqlTable tab) {
  474. string name = tab.Name;
  475. this.WriteName(name);
  476. return tab;
  477. }
  478. internal override SqlUserQuery VisitUserQuery(SqlUserQuery suq) {
  479. if (suq.Arguments.Count > 0) {
  480. // compute all the arg values...
  481. StringBuilder savesb = this.sb;
  482. this.sb = new StringBuilder();
  483. object[] args = new object[suq.Arguments.Count];
  484. for (int i = 0, n = args.Length; i < n; i++) {
  485. this.Visit(suq.Arguments[i]);
  486. args[i] = this.sb.ToString();
  487. this.sb.Length = 0;
  488. }
  489. this.sb = savesb;
  490. // append query with args...
  491. sb.Append(string.Format(CultureInfo.InvariantCulture, suq.QueryText, args));
  492. } else {
  493. sb.Append(suq.QueryText);
  494. }
  495. return suq;
  496. }
  497. internal override SqlExpression VisitUserColumn(SqlUserColumn suc) {
  498. sb.Append(suc.Name);
  499. return suc;
  500. }
  501. internal override SqlStoredProcedureCall VisitStoredProcedureCall(SqlStoredProcedureCall spc) {
  502. sb.Append("EXEC @RETURN_VALUE = ");
  503. this.WriteName(spc.Function.MappedName);
  504. sb.Append(" ");
  505. int pc = spc.Function.Parameters.Count;
  506. System.Diagnostics.Debug.Assert(spc.Arguments.Count >= pc);
  507. for (int i = 0; i < pc; i++) {
  508. MetaParameter mp = spc.Function.Parameters[i];
  509. if (i > 0) sb.Append(", ");
  510. this.WriteVariableName(mp.MappedName);
  511. sb.Append(" = ");
  512. this.Visit(spc.Arguments[i]);
  513. if (mp.Parameter.IsOut || mp.Parameter.ParameterType.IsByRef)
  514. sb.Append(" OUTPUT");
  515. }
  516. if (spc.Arguments.Count > pc) {
  517. if (pc > 0) sb.Append(", ");
  518. this.WriteVariableName(spc.Function.ReturnParameter.MappedName);
  519. sb.Append(" = ");
  520. this.Visit(spc.Arguments[pc]);
  521. sb.Append(" OUTPUT");
  522. }
  523. return spc;
  524. }
  525. internal override SqlAlias VisitAlias(SqlAlias alias) {
  526. bool isSelect = alias.Node is SqlSelect;
  527. int saveDepth = this.depth;
  528. string aliasName = null;
  529. string name = "";
  530. SqlTable table = alias.Node as SqlTable;
  531. if (table != null) {
  532. name = table.Name;
  533. }
  534. if (alias.Name == null) {
  535. if (!this.names.TryGetValue(alias, out aliasName)) {
  536. aliasName = "A" + this.names.Count;
  537. this.names[alias] = aliasName;
  538. }
  539. } else {
  540. aliasName = alias.Name;
  541. }
  542. if (isSelect) {
  543. this.depth++;
  544. sb.Append("(");
  545. this.NewLine();
  546. }
  547. this.Visit(alias.Node);
  548. if (isSelect) {
  549. this.NewLine();
  550. sb.Append(")");
  551. this.depth = saveDepth;
  552. }
  553. if (!this.suppressedAliases.Contains(alias) && aliasName != null && name != aliasName) {
  554. sb.Append(" AS ");
  555. this.WriteName(aliasName);
  556. }
  557. return alias;
  558. }
  559. internal override SqlExpression VisitAliasRef(SqlAliasRef aref) {
  560. sb.Append("AREF(");
  561. this.WriteAliasName(aref.Alias);
  562. sb.Append(")");
  563. return aref;
  564. }
  565. private void WriteAliasName(SqlAlias alias) {
  566. string aliasName = null;
  567. if (alias.Name == null) {
  568. if (!this.names.TryGetValue(alias, out aliasName)) {
  569. aliasName = "A" + this.names.Count;
  570. this.names[alias] = aliasName;
  571. }
  572. }
  573. else {
  574. aliasName = alias.Name;
  575. }
  576. this.WriteName(aliasName);
  577. }
  578. internal override SqlNode VisitUnion(SqlUnion su) {
  579. sb.Append("(");
  580. int saveDepth = this.depth;
  581. this.depth++;
  582. this.NewLine();
  583. this.Visit(su.Left);
  584. this.NewLine();
  585. sb.Append("UNION");
  586. if (su.All) {
  587. sb.Append(" ALL");
  588. }
  589. this.NewLine();
  590. this.Visit(su.Right);
  591. this.NewLine();
  592. sb.Append(")");
  593. this.depth = saveDepth;
  594. return su;
  595. }
  596. internal override SqlExpression VisitExprSet(SqlExprSet xs) {
  597. if (this.isDebugMode) {
  598. sb.Append("ES(");
  599. for (int i = 0, n = xs.Expressions.Count; i < n; i++) {
  600. if (i > 0)
  601. sb.Append(", ");
  602. this.Visit(xs.Expressions[i]);
  603. }
  604. sb.Append(")");
  605. } else {
  606. // only show the first one
  607. this.Visit(xs.GetFirstExpression());
  608. }
  609. return xs;
  610. }
  611. internal override SqlRow VisitRow(SqlRow row) {
  612. for (int i = 0, n = row.Columns.Count; i < n; i++) {
  613. SqlColumn c = row.Columns[i];
  614. if (i > 0)
  615. sb.Append(", ");
  616. this.Visit(c.Expression);
  617. string name = c.Name;
  618. string inferredName = this.InferName(c.Expression, null);
  619. if (name == null)
  620. name = inferredName;
  621. if (name == null) {
  622. if (!this.names.TryGetValue(c, out name)) {
  623. name = "C" + this.names.Count;
  624. this.names[c] = name;
  625. }
  626. }
  627. if (name != inferredName && !String.IsNullOrEmpty(name)) {
  628. sb.Append(" AS ");
  629. this.WriteName(name);
  630. }
  631. }
  632. return row;
  633. }
  634. internal override SqlExpression VisitNew(SqlNew sox) {
  635. if (!this.isDebugMode) {
  636. throw Error.InvalidFormatNode("New");
  637. }
  638. sb.Append("new ");
  639. sb.Append(sox.ClrType.Name);
  640. sb.Append("{ ");
  641. // Visit Args
  642. for (int i = 0, n = sox.Args.Count; i < n; i++)
  643. {
  644. SqlExpression argExpr = sox.Args[i];
  645. if (i > 0) sb.Append(", ");
  646. sb.Append(sox.ArgMembers[i].Name);
  647. sb.Append(" = ");
  648. this.Visit(argExpr);
  649. }
  650. // Visit Members
  651. for (int i = 0, n = sox.Members.Count; i < n; i++) {
  652. SqlMemberAssign ma = sox.Members[i];
  653. if (i > 0) sb.Append(", ");
  654. string ename = this.InferName(ma.Expression, null);
  655. if (ename != ma.Member.Name) {
  656. sb.Append(ma.Member.Name);
  657. sb.Append(" = ");
  658. }
  659. this.Visit(ma.Expression);
  660. }
  661. sb.Append(" }");
  662. return sox;
  663. }
  664. internal override SqlExpression VisitClientArray(SqlClientArray scar) {
  665. if (!this.isDebugMode) {
  666. throw Error.InvalidFormatNode("ClientArray");
  667. }
  668. sb.Append("new []{");
  669. for (int i = 0, n = scar.Expressions.Count; i < n; i++) {
  670. if (i > 0) sb.Append(", ");
  671. this.Visit(scar.Expressions[i]);
  672. }
  673. sb.Append("}");
  674. return scar;
  675. }
  676. internal override SqlNode VisitMember(SqlMember m) {
  677. this.Visit(m.Expression);
  678. sb.Append(".");
  679. sb.Append(m.Member.Name);
  680. return m;
  681. }
  682. internal virtual void NewLine() {
  683. if (sb.Length > 0) {
  684. sb.AppendLine();
  685. }
  686. for (int i = 0; i < this.depth; i++) {
  687. sb.Append(" ");
  688. }
  689. }
  690. internal override SqlSelect VisitSelect(SqlSelect ss) {
  691. if (ss.DoNotOutput) {
  692. return ss;
  693. }
  694. string from = null;
  695. if (ss.From != null) {
  696. StringBuilder savesb = this.sb;
  697. this.sb = new StringBuilder();
  698. if (this.IsSimpleCrossJoinList(ss.From)) {
  699. this.VisitCrossJoinList(ss.From);
  700. } else {
  701. this.Visit(ss.From);
  702. }
  703. from = this.sb.ToString();
  704. this.sb = savesb;
  705. }
  706. sb.Append("SELECT ");
  707. if (ss.IsDistinct) {
  708. sb.Append("DISTINCT ");
  709. }
  710. if (ss.Top != null) {
  711. sb.Append("TOP ");
  712. if (this.parenthesizeTop) {
  713. sb.Append("(");
  714. }
  715. this.Visit(ss.Top);
  716. if (this.parenthesizeTop) {
  717. sb.Append(")");
  718. }
  719. sb.Append(" ");
  720. if (ss.IsPercent) {
  721. sb.Append(" PERCENT ");
  722. }
  723. }
  724. if (ss.Row.Columns.Count > 0) {
  725. this.VisitRow(ss.Row);
  726. } else if (this.isDebugMode) {
  727. this.Visit(ss.Selection);
  728. } else {
  729. sb.Append("NULL AS [EMPTY]");
  730. }
  731. if (from != null) {
  732. this.NewLine();
  733. sb.Append("FROM ");
  734. sb.Append(from);
  735. }
  736. if (ss.Where != null) {
  737. this.NewLine();
  738. sb.Append("WHERE ");
  739. this.Visit(ss.Where);
  740. }
  741. if (ss.GroupBy.Count > 0) {
  742. this.NewLine();
  743. sb.Append("GROUP BY ");
  744. for (int i = 0, n = ss.GroupBy.Count; i < n; i++) {
  745. SqlExpression exp = ss.GroupBy[i];
  746. if (i > 0)
  747. sb.Append(", ");
  748. this.Visit(exp);
  749. }
  750. if (ss.Having != null) {
  751. this.NewLine();
  752. sb.Append("HAVING ");
  753. this.Visit(ss.Having);
  754. }
  755. }
  756. if (ss.OrderBy.Count > 0 && ss.OrderingType != SqlOrderingType.Never) {
  757. this.NewLine();
  758. sb.Append("ORDER BY ");
  759. for (int i = 0, n = ss.OrderBy.Count; i < n; i++) {
  760. SqlOrderExpression exp = ss.OrderBy[i];
  761. if (i > 0)
  762. sb.Append(", ");
  763. this.Visit(exp.Expression);
  764. if (exp.OrderType == SqlOrderType.Descending) {
  765. sb.Append(" DESC");
  766. }
  767. }
  768. }
  769. return ss;
  770. }
  771. internal virtual bool IsSimpleCrossJoinList(SqlNode node) {
  772. SqlJoin join = node as SqlJoin;
  773. if (join != null) {
  774. return join.JoinType == SqlJoinType.Cross &&
  775. this.IsSimpleCrossJoinList(join.Left) &&
  776. this.IsSimpleCrossJoinList(join.Right);
  777. }
  778. SqlAlias alias = node as SqlAlias;
  779. return (alias != null && alias.Node is SqlTable);
  780. }
  781. internal virtual void VisitCrossJoinList(SqlNode node) {
  782. SqlJoin join = node as SqlJoin;
  783. if (join != null) {
  784. this.VisitCrossJoinList(join.Left);
  785. sb.Append(", ");
  786. this.VisitCrossJoinList(join.Right);
  787. } else {
  788. this.Visit(node);
  789. }
  790. }
  791. internal void VisitJoinSource(SqlSource src) {
  792. if (src.NodeType == SqlNodeType.Join) {
  793. this.depth++;
  794. sb.Append("(");
  795. this.Visit(src);
  796. sb.Append(")");
  797. this.depth--;
  798. } else {
  799. this.Visit(src);
  800. }
  801. }
  802. internal override SqlSource VisitJoin(SqlJoin join) {
  803. this.Visit(join.Left);
  804. this.NewLine();
  805. switch (join.JoinType) {
  806. case SqlJoinType.CrossApply:
  807. sb.Append("CROSS APPLY ");
  808. break;
  809. case SqlJoinType.Cross:
  810. sb.Append("CROSS JOIN ");
  811. break;
  812. case SqlJoinType.Inner:
  813. sb.Append("INNER JOIN ");
  814. break;
  815. case SqlJoinType.LeftOuter:
  816. sb.Append("LEFT OUTER JOIN ");
  817. break;
  818. case SqlJoinType.OuterApply:
  819. sb.Append("OUTER APPLY ");
  820. break;
  821. }
  822. SqlJoin rightJoin = join.Right as SqlJoin;
  823. if (rightJoin == null ||
  824. (rightJoin.JoinType == SqlJoinType.Cross
  825. && join.JoinType != SqlJoinType.CrossApply
  826. && join.JoinType != SqlJoinType.OuterApply)) {
  827. this.Visit(join.Right);
  828. } else {
  829. this.VisitJoinSource(join.Right);
  830. }
  831. if (join.Condition != null) {
  832. sb.Append(" ON ");
  833. this.Visit(join.Condition);
  834. } else if (this.RequiresOnCondition(join.JoinType)) {
  835. sb.Append(" ON 1=1 ");
  836. }
  837. return join;
  838. }
  839. [SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification="Unknown reason.")]
  840. internal bool RequiresOnCondition(SqlJoinType joinType) {
  841. switch (joinType) {
  842. case SqlJoinType.CrossApply:
  843. case SqlJoinType.Cross:
  844. case SqlJoinType.OuterApply:
  845. return false;
  846. case SqlJoinType.Inner:
  847. case SqlJoinType.LeftOuter:
  848. return true;
  849. default:
  850. throw Error.InvalidFormatNode(joinType);
  851. }
  852. }
  853. internal override SqlBlock VisitBlock(SqlBlock block) {
  854. for (int i = 0, n = block.Statements.Count; i < n; i++) {
  855. this.Visit(block.Statements[i]);
  856. if (i < n - 1) {
  857. SqlSelect select = block.Statements[i+1] as SqlSelect;
  858. if (select == null || !select.DoNotOutput) {
  859. this.NewLine();
  860. this.NewLine();
  861. }
  862. }
  863. }
  864. return block;
  865. }
  866. internal override SqlExpression VisitClientQuery(SqlClientQuery cq) {
  867. if (!this.isDebugMode) {
  868. throw Error.InvalidFormatNode("ClientQuery");
  869. }
  870. sb.Append("client(");
  871. for (int i = 0, n = cq.Arguments.Count; i < n; i++) {
  872. if (i > 0) sb.Append(", ");
  873. this.Visit(cq.Arguments[i]);
  874. }
  875. sb.Append("; ");
  876. this.Visit(cq.Query);
  877. sb.Append(")");
  878. return cq;
  879. }
  880. internal override SqlExpression VisitJoinedCollection(SqlJoinedCollection jc) {
  881. if (!this.isDebugMode) {
  882. throw Error.InvalidFormatNode("JoinedCollection");
  883. }
  884. sb.Append("big-join(");
  885. this.Visit(jc.Expression);
  886. sb.Append(", ");
  887. this.Visit(jc.Count);
  888. sb.Append(")");
  889. return jc;
  890. }
  891. internal override SqlStatement VisitDelete(SqlDelete sd) {
  892. sb.Append("DELETE FROM ");
  893. this.suppressedAliases.Add(sd.Select.From);
  894. this.Visit(sd.Select.From);
  895. if (sd.Select.Where != null) {
  896. sb.Append(" WHERE ");
  897. this.Visit(sd.Select.Where);
  898. }
  899. this.suppressedAliases.Remove(sd.Select.From);
  900. return sd;
  901. }
  902. internal override SqlStatement VisitInsert(SqlInsert si) {
  903. if (si.OutputKey != null) {
  904. sb.Append("DECLARE @output TABLE(");
  905. this.WriteName(si.OutputKey.Name);
  906. sb.Append(" ");
  907. sb.Append(si.OutputKey.SqlType.ToQueryString());
  908. sb.Append(")");
  909. this.NewLine();
  910. if (si.OutputToLocal) {
  911. sb.Append("DECLARE @id ");
  912. sb.Append(si.OutputKey.SqlType.ToQueryString());
  913. this.NewLine();
  914. }
  915. }
  916. sb.Append("INSERT INTO ");
  917. this.Visit(si.Table);
  918. if (si.Row.Columns.Count != 0) {
  919. // INSERT INTO table (...columns...) VALUES (...values...)
  920. sb.Append("(");
  921. for (int i = 0, n = si.Row.Columns.Count; i < n; i++) {
  922. if (i > 0) sb.Append(", ");
  923. this.WriteName(si.Row.Columns[i].Name);
  924. }
  925. sb.Append(")");
  926. }
  927. if (si.OutputKey != null) {
  928. this.NewLine();
  929. sb.Append("OUTPUT INSERTED.");
  930. this.WriteName(si.OutputKey.MetaMember.MappedName);
  931. sb.Append(" INTO @output");
  932. }
  933. if (si.Row.Columns.Count == 0) {
  934. sb.Append(" DEFAULT VALUES");
  935. }
  936. else {
  937. // VALUES (...values...)
  938. this.NewLine();
  939. sb.Append("VALUES (");
  940. if (this.isDebugMode && si.Row.Columns.Count == 0) {
  941. this.Visit(si.Expression);
  942. } else {
  943. for (int i = 0, n = si.Row.Columns.Count; i < n; i++) {
  944. if (i > 0) sb.Append(", ");
  945. this.Visit( si.Row.Columns[i].Expression);
  946. }
  947. }
  948. sb.Append(")");
  949. }
  950. if (si.OutputKey != null) {
  951. this.NewLine();
  952. if (si.OutputToLocal) {
  953. sb.Append("SELECT @id = ");
  954. sb.Append(si.OutputKey.Name);
  955. sb.Append(" FROM @output");
  956. }
  957. else {
  958. sb.Append("SELECT ");
  959. this.WriteName(si.OutputKey.Name);
  960. sb.Append(" FROM @output");
  961. }
  962. }
  963. return si;
  964. }
  965. internal override SqlStatement VisitUpdate(SqlUpdate su) {
  966. sb.Append("UPDATE ");
  967. this.suppressedAliases.Add(su.Select.From);
  968. this.Visit(su.Select.From);
  969. this.NewLine();
  970. sb.Append("SET ");
  971. for (int i = 0, n = su.Assignments.Count; i < n; i++) {
  972. if (i > 0) sb.Append(", ");
  973. SqlAssign sa = su.Assignments[i];
  974. this.Visit(sa.LValue);
  975. sb.Append(" = ");
  976. this.Visit(sa.RValue);
  977. }
  978. if (su.Select.Where != null) {
  979. this.NewLine();
  980. sb.Append("WHERE ");
  981. this.Visit(su.Select.Where);
  982. }
  983. this.suppressedAliases.Remove(su.Select.From);
  984. return su;
  985. }
  986. internal override SqlStatement VisitAssign(SqlAssign sa) {
  987. sb.Append("SET ");
  988. this.Visit(sa.LValue);
  989. sb.Append(" = ");
  990. this.Visit(sa.RValue);
  991. return sa;
  992. }
  993. internal override SqlExpression VisitSearchedCase(SqlSearchedCase c) {
  994. this.depth++;
  995. this.NewLine();
  996. sb.Append("(CASE ");
  997. this.depth++;
  998. for (int i = 0, n = c.Whens.Count; i < n; i++) {
  999. SqlWhen when = c.Whens[i];
  1000. this.NewLine();
  1001. sb.Append("WHEN ");
  1002. this.Visit(when.Match);
  1003. sb.Append(" THEN ");
  1004. this.Visit(when.Value);
  1005. }
  1006. if (c.Else != null) {
  1007. this.NewLine();
  1008. sb.Append("ELSE ");
  1009. this.Visit(c.Else);
  1010. }
  1011. this.depth--;
  1012. this.NewLine();
  1013. sb.Append(" END)");
  1014. this.depth--;
  1015. return c;
  1016. }
  1017. internal override SqlExpression VisitSimpleCase(SqlSimpleCase c) {
  1018. this.depth++;
  1019. this.NewLine();
  1020. sb.Append("(CASE");
  1021. this.depth++;
  1022. if (c.Expression != null) {
  1023. sb.Append(" ");
  1024. this.Visit(c.Expression);
  1025. }
  1026. for (int i = 0, n = c.Whens.Count; i < n; i++) {
  1027. SqlWhen when = c.Whens[i];
  1028. if (i == n - 1 && when.Match == null) {
  1029. this.NewLine();
  1030. sb.Append("ELSE ");
  1031. this.Visit(when.Value);
  1032. } else {
  1033. this.NewLine();
  1034. sb.Append("WHEN ");
  1035. this.Visit(when.Match);
  1036. sb.Append(" THEN ");
  1037. this.Visit(when.Value);
  1038. }
  1039. }
  1040. this.depth--;
  1041. this.NewLine();
  1042. sb.Append(" END)");
  1043. this.depth--;
  1044. return c;
  1045. }
  1046. internal override SqlExpression VisitClientCase(SqlClientCase c) {
  1047. if (!this.isDebugMode) {
  1048. throw Error.InvalidFormatNode("ClientCase");
  1049. }
  1050. this.depth++;
  1051. this.NewLine();
  1052. sb.Append("(CASE");
  1053. this.depth++;
  1054. if (c.Expression != null) {
  1055. sb.Append(" ");
  1056. this.Visit(c.Expression);
  1057. }
  1058. for (int i = 0, n = c.Whens.Count; i < n; i++) {
  1059. SqlClientWhen when = c.Whens[i];
  1060. if (i == n - 1 && when.Match == null) {
  1061. this.NewLine();
  1062. sb.Append("ELSE ");
  1063. this.Visit(when.Value);
  1064. } else {
  1065. this.NewLine();
  1066. sb.Append("WHEN ");
  1067. this.Visit(when.Match);
  1068. sb.Append(" THEN ");
  1069. this.Visit(when.Value);
  1070. }
  1071. }
  1072. this.depth--;
  1073. this.NewLine();
  1074. sb.Append(" END)");
  1075. this.depth--;
  1076. return c;
  1077. }
  1078. internal override SqlExpression VisitTypeCase(SqlTypeCase c) {
  1079. if (!this.isDebugMode) {
  1080. throw Error.InvalidFormatNode("TypeCase");
  1081. }
  1082. this.depth++;
  1083. this.NewLine();
  1084. sb.Append("(CASE");
  1085. this.depth++;
  1086. if (c.Discriminator != null) {
  1087. sb.Append(" ");
  1088. this.Visit(c.Discriminator);
  1089. }
  1090. for (int i = 0, n = c.Whens.Count; i < n; i++) {
  1091. SqlTypeCaseWhen when = c.Whens[i];
  1092. if (i == n - 1 && when.Match == null) {
  1093. this.NewLine();
  1094. sb.Append("ELSE ");
  1095. this.Visit(when.TypeBinding);
  1096. } else {
  1097. this.NewLine();
  1098. sb.Append("WHEN ");
  1099. this.Visit(when.Match);
  1100. sb.Append(" THEN ");
  1101. this.Visit(when.TypeBinding);
  1102. }
  1103. }
  1104. this.depth--;
  1105. this.NewLine();
  1106. sb.Append(" END)");
  1107. this.depth--;
  1108. return c;
  1109. }
  1110. internal override SqlExpression VisitVariable(SqlVariable v) {
  1111. sb.Append(v.Name);
  1112. return v;
  1113. }
  1114. private string InferName(SqlExpression exp, string def) {
  1115. if (exp == null) return null;
  1116. switch (exp.NodeType) {
  1117. case SqlNodeType.Member:
  1118. return ((SqlMember)exp).Member.Name;
  1119. case SqlNodeType.Column:
  1120. return ((SqlColumn)exp).Name;
  1121. case SqlNodeType.ColumnRef:
  1122. return ((SqlColumnRef)exp).Column.Name;
  1123. case SqlNodeType.ExprSet:
  1124. return this.InferName(((SqlExprSet)exp).Expressions[0], def);
  1125. default:
  1126. return def;
  1127. }
  1128. }
  1129. private void FormatType(ProviderType type) {
  1130. sb.Append(type.ToQueryString());
  1131. }
  1132. [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.")]
  1133. internal virtual void FormatValue(object value) {
  1134. if (value == null) {
  1135. sb.Append("NULL");
  1136. } else {
  1137. Type t = value.GetType();
  1138. if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
  1139. t = t.GetGenericArguments()[0];
  1140. TypeCode tc = Type.GetTypeCode(t);
  1141. switch (tc) {
  1142. case TypeCode.Char:
  1143. case TypeCode.String:
  1144. case TypeCode.DateTime:
  1145. sb.Append("'");
  1146. sb.Append(this.EscapeSingleQuotes(value.ToString()));
  1147. sb.Append("'");
  1148. return;
  1149. case TypeCode.Boolean:
  1150. sb.Append(this.GetBoolValue((bool)value));
  1151. return;
  1152. case TypeCode.Byte:
  1153. case TypeCode.Decimal:
  1154. case TypeCode.Double:
  1155. case TypeCode.Int16:
  1156. case TypeCode.Int32:
  1157. case TypeCode.Int64:
  1158. case TypeCode.SByte:
  1159. case TypeCode.Single:
  1160. case TypeCode.UInt16:
  1161. case TypeCode.UInt32:
  1162. case TypeCode.UInt64:
  1163. sb.Append(value);
  1164. return;
  1165. case TypeCode.Object: {
  1166. if (value is Guid) {
  1167. sb.Append("'");
  1168. sb.Append(value);
  1169. sb.Append("'");
  1170. return;
  1171. }
  1172. Type valueType = value as Type;
  1173. if (valueType != null) {
  1174. if (this.isDebugMode) {
  1175. sb.Append("typeof(");
  1176. sb.Append(valueType.Name);
  1177. sb.Append(")");
  1178. } else {
  1179. this.FormatValue("");
  1180. }
  1181. return;
  1182. }
  1183. break;
  1184. }
  1185. }
  1186. if (this.isDebugMode) {
  1187. sb.Append("value(");
  1188. sb.Append(value.ToString());
  1189. sb.Append(")");
  1190. }
  1191. else {
  1192. throw Error.ValueHasNoLiteralInSql(value);
  1193. }
  1194. }
  1195. }
  1196. internal virtual string GetBoolValue(bool value) {
  1197. return value ? "1" : "0";
  1198. }
  1199. internal virtual string EscapeSingleQuotes(string str) {
  1200. if (str.IndexOf('\'') < 0) return str;
  1201. StringBuilder tempStringBuilder = new StringBuilder();
  1202. foreach (char c in str) {
  1203. if (c == '\'') {
  1204. tempStringBuilder.Append("''");
  1205. } else {
  1206. tempStringBuilder.Append("'");
  1207. }
  1208. }
  1209. return tempStringBuilder.ToString();
  1210. }
  1211. [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.")]
  1212. internal virtual string GetOperator(SqlNodeType nt) {
  1213. switch (nt) {
  1214. case SqlNodeType.Add: return "+";
  1215. case SqlNodeType.Sub: return "-";
  1216. case SqlNodeType.Mul: return "*";
  1217. case SqlNodeType.Div: return "/";
  1218. case SqlNodeType.Mod: return "%";
  1219. case SqlNodeType.Concat: return "+";
  1220. case SqlNodeType.BitAnd: return "&";
  1221. case SqlNodeType.BitOr: return "|";
  1222. case SqlNodeType.BitXor: return "^";
  1223. case SqlNodeType.And: return "AND";
  1224. case SqlNodeType.Or: return "OR";
  1225. case SqlNodeType.GE: return ">=";
  1226. case SqlNodeType.GT: return ">";
  1227. case SqlNodeType.LE: return "<=";
  1228. case SqlNodeType.LT: return "<";
  1229. case SqlNodeType.EQ: return "=";
  1230. case SqlNodeType.EQ2V: return "=";
  1231. case SqlNodeType.NE: return "<>";
  1232. case SqlNodeType.NE2V: return "<>";
  1233. case SqlNodeType.Not: return "NOT";
  1234. case SqlNodeType.Not2V: return "NOT";
  1235. case SqlNodeType.BitNot: return "~";
  1236. case SqlNodeType.Negate: return "-";
  1237. case SqlNodeType.IsNull: return "IS NULL";
  1238. case SqlNodeType.IsNotNull: return "IS NOT NULL";
  1239. case SqlNodeType.Count: return "COUNT";
  1240. case SqlNodeType.LongCount: return "COUNT_BIG";
  1241. case SqlNodeType.Min: return "MIN";
  1242. case SqlNodeType.Max: return "MAX";
  1243. case SqlNodeType.Sum: return "SUM";
  1244. case SqlNodeType.Avg: return "AVG";
  1245. case SqlNodeType.Stddev: return "STDEV";
  1246. case SqlNodeType.ClrLength: return "CLRLENGTH";
  1247. default:
  1248. throw Error.InvalidFormatNode(nt);
  1249. }
  1250. }
  1251. internal override SqlNode VisitLink(SqlLink link) {
  1252. if (!this.isDebugMode) {
  1253. throw Error.InvalidFormatNode("Link");
  1254. }
  1255. if (link.Expansion != null) {
  1256. sb.Append("LINK(");
  1257. this.Visit(link.Expansion);
  1258. sb.Append(")");
  1259. } else {
  1260. sb.Append("LINK(");
  1261. for (int i = 0, n = link.KeyExpressions.Count; i < n; i++) {
  1262. if (i > 0) sb.Append(", ");
  1263. this.Visit(link.KeyExpressions[i]);
  1264. }
  1265. sb.Append(")");
  1266. }
  1267. return link;
  1268. }
  1269. internal override SqlMemberAssign VisitMemberAssign(SqlMemberAssign ma) {
  1270. throw Error.InvalidFormatNode("MemberAssign");
  1271. }
  1272. internal override SqlExpression VisitMethodCall(SqlMethodCall mc) {
  1273. if (!this.isDebugMode) {
  1274. throw Error.InvalidFormatNode("MethodCall");
  1275. }
  1276. if (mc.Method.IsStatic) {
  1277. sb.Append(mc.Method.DeclaringType);
  1278. } else {
  1279. this.Visit(mc.Object);
  1280. }
  1281. sb.Append(".");
  1282. sb.Append(mc.Method.Name);
  1283. sb.Append("(");
  1284. for (int i = 0, n = mc.Arguments.Count; i < n; i++) {
  1285. if (i > 0) sb.Append(", ");
  1286. this.Visit(mc.Arguments[i]);
  1287. }
  1288. sb.Append(")");
  1289. return mc;
  1290. }
  1291. internal override SqlExpression VisitOptionalValue(SqlOptionalValue sov) {
  1292. if (this.isDebugMode) {
  1293. sb.Append("opt(");
  1294. this.Visit(sov.HasValue);
  1295. sb.Append(", ");
  1296. this.Visit(sov.Value);
  1297. sb.Append(")");
  1298. return sov;
  1299. } else {
  1300. throw Error.InvalidFormatNode("OptionalValue");
  1301. }
  1302. }
  1303. internal override SqlExpression VisitUserRow(SqlUserRow row) {
  1304. if (!isDebugMode) {
  1305. throw Error.InvalidFormatNode("UserRow");
  1306. }
  1307. return row;
  1308. }
  1309. internal override SqlExpression VisitGrouping(SqlGrouping g) {
  1310. if (!isDebugMode) {
  1311. throw Error.InvalidFormatNode("Grouping");
  1312. }
  1313. sb.Append("Group(");
  1314. this.Visit(g.Key);
  1315. sb.Append(", ");
  1316. this.Visit(g.Group);
  1317. sb.Append(")");
  1318. return g;
  1319. }
  1320. }
  1321. class AliasMapper : SqlVisitor {
  1322. Dictionary<SqlColumn, SqlAlias> aliasMap;
  1323. SqlAlias currentAlias;
  1324. internal AliasMapper(Dictionary<SqlColumn, SqlAlias> aliasMap) {
  1325. this.aliasMap = aliasMap;
  1326. }
  1327. internal override SqlAlias VisitAlias(SqlAlias a) {
  1328. SqlAlias save = this.currentAlias;
  1329. this.currentAlias = a;
  1330. base.VisitAlias(a);
  1331. this.currentAlias = save;
  1332. return a;
  1333. }
  1334. internal override SqlExpression VisitColumn(SqlColumn col) {
  1335. this.aliasMap[col] = this.currentAlias;
  1336. this.Visit(col.Expression);
  1337. return col;
  1338. }
  1339. internal override SqlRow VisitRow(SqlRow row) {
  1340. foreach(SqlColumn col in row.Columns) {
  1341. this.VisitColumn(col);
  1342. }
  1343. return row;
  1344. }
  1345. internal override SqlTable VisitTable(SqlTable tab) {
  1346. foreach(SqlColumn col in tab.Columns) {
  1347. this.VisitColumn(col);
  1348. }
  1349. return tab;
  1350. }
  1351. internal override SqlExpression VisitTableValuedFunctionCall(SqlTableValuedFunctionCall fc) {
  1352. foreach(SqlColumn col in fc.Columns) {
  1353. this.VisitColumn(col);
  1354. }
  1355. return fc;
  1356. }
  1357. }
  1358. }
  1359. }