internal Joiner(QueryPart queryPart, BuildContext buildContext, BuildArgs buildArgs) { _queryPart = queryPart; _buildContext = buildContext; _buildArgs = buildArgs; _targets = new List <TableChainer>(); }
private string BuildTop(BuildContext buildContext, BuildArgs buildArgs) { return(String.Format("{0} {1}{2} ", Text.Insert, base.BuildTop(buildContext), Text.Into)); }
private void BuildCtes(BuildContext buildContext, BuildArgs buildArgs, StringBuilder sql) { for (int i = 0; i < _defaultPart.Ctes.Count; ++i) { sql.Append(_defaultPart.Ctes[i].BuildCte(buildContext, buildArgs, i == 0)); } }
internal string BaseBuildMethod(BuildContext buildContext, BuildArgs buildArgs) { string tableSql = TableArgument.Build(buildContext, buildArgs); TryThrow(buildContext); StringBuilder sql = Text.GenerateSql(30) .NewLine(Keyword); // subquery: if (TableArgument.Original is View) { sql.S().Append(Text.LeftBracket) .Append(tableSql) .NewLine(Text.RightBracket); } // table: else { sql.S().Append(tableSql); } // table with alias if (_alias != null) { return(sql .S().Append(Text.As) .S().Append(Filter.Delimit(_alias.Name)) .ToString()); } else { return(sql.ToString()); } }
private static void BuildWhere(QueryPart part, BuildContext buildContext, BuildArgs buildArgs, StringBuilder sql) { // wheres (WHERE ... AND ... OR ...) part.Wheres.ForEach(where => { where.BuildNode(part, buildContext, buildArgs, sql); }); }
// main method for non-inliner variable processing internal bool ProcessVariable( BuildContext buildContext, BuildArgs buildArgs, out string sql) { var variable = TryGetVariable(buildContext); return(ProcessVariable(buildContext, buildArgs, out sql, variable)); }
internal string BuildConcatenator(BuildContext buildContext, BuildArgs buildArgs, Concatenator arg) { IsConcat = true; if (this is Argument) { buildContext.Current.IsConcat = true; } return(arg.Build(buildContext, buildArgs)); }
internal Column[] ProcessValueArrayInliner(BuildContext buildContext, BuildArgs buildArgs, Column[] values) { if (values.Length == 1 && values[0].Original is System.String) { var name = (System.String)values[0].Original; Variable variable = buildContext.ParamRoot.TryGetVariable(name, out chainException); if (variable.IsInliner()) { // inliner type check if (variable.DT != DT.InColumn) { buildContext.TryTakeException(variable.DT.InvalidInlinerException(GetType().Name, variable.Name, new[] { DT.InColumn })); return(null); } string arg2 = variable.Name; if (buildArgs.Executable != null) { ParameterArgument inlinerArgument = buildArgs.Executable.GetInlinerArgument(variable.Name); if (inlinerArgument.Value != null) { if (inlinerArgument.Value is System.String[]) { var args = new List <Column>(); foreach (var column in (System.String[])inlinerArgument.Value) { args.Add(column); } return(args.ToArray()); } else if (inlinerArgument.Value is Column[]) { return((Column[])inlinerArgument.Value); } } else { buildContext.TryTakeException(new QueryTalkException(this, QueryTalkExceptionType.InlinerArgumentNull, String.Format("{0} = null", arg2))); return(null); } } } } return(null); }
internal bool ProcessVariable( BuildContext buildContext, BuildArgs buildArgs, out string sql, Variable variable) { sql = null; if (variable == null) { if (Variable.Detect(Original)) { if (buildContext.Root.CompilableType.IsProcOrSnippet() || (buildContext.Root.CompilableType == Compilable.ObjectType.View && buildContext.Query.Master.Root.CompilableType.IsProc())) { buildContext.Exception = new QueryTalkException("Argument.ProcessVariable", QueryTalkExceptionType.ParamOrVariableNotDeclared, String.Format("variable = {0}", Original)); return(true); } // non-declared variables in views are valid: if (buildContext.Root.CompilableType == Compilable.ObjectType.View) { sql = (string)Original; return(true); } } return(false); } // here variable has been found: buildContext.TryTakeException(variable.DisallowedInliningException()); if (buildContext.Exception != null) { return(true); } if (variable.IsConcatenator()) { sql = BuildConcatenator(buildContext, buildArgs, variable); return(true); } buildContext.TryAddParamToConcatRoot(variable); return(false); }
private void ProcessTable( BuildContext buildContext, BuildArgs buildArgs, TableArgument table, StringBuilder sql) { sql.AppendLine() .Append(Text.Select).S() .Append(Text.Asterisk).S() .Append(Text.From).S() .Append(table.Build(buildContext, buildArgs)) .Terminate(); TryThrow(table.Exception); }
internal static string ProcessVariable( string argument, BuildContext buildContext, BuildArgs buildArgs, out QueryTalkException exception) { exception = null; var variable = buildContext.TryGetVariable(argument, out exception); if (exception != null) { return(null); } if (variable == null) { if (Variable.Detect(argument)) { if (buildContext.Root.CompilableType.IsProc() || (buildContext.Root.CompilableType == Compilable.ObjectType.View && buildContext.Query.Master.Root.CompilableType.IsProc())) { buildContext.Exception = new QueryTalkException("Variable.ProcessVariable", QueryTalkExceptionType.ParamOrVariableNotDeclared, String.Format("variable = {0}", argument)); return(null); } } return(null); } buildContext.TryTakeException(variable.DisallowedInliningException()); if (buildContext.Exception != null) { return(null); } if (variable.IsConcatenator()) { return(Argument.BuildConcatenator(buildContext, buildArgs, variable)); } buildContext.TryAddParamToConcatRoot(variable); return(null); }
// build the executable SQL code private new void Build() { // try throw the exception of the execution phase. TryThrow(); Executable.ArgumentsCriticalCheck(true); TryThrow(); var buildArgs = new BuildArgs(null); buildArgs.TestBody = _testBody; // executable is build by the context of its compilable object var execSql = Executable.Build( new BuildContext(Executable.Compilable), buildArgs); _sql = BuildOutputWrapper(execSql); }
// single-value insert private string BuildSingleValueInsert(BuildContext buildContext, BuildArgs buildArgs, Table table) { var selectable = GetPrev <ISelectable>(); // skip building the SelectChainer object ((Chainer)selectable).SkipBuild = true; var sql = BuildHeader(buildContext, buildArgs, table); // treat string column as value UseStringAsValue = true; var columns = selectable.Columns; var isDefaultValues = false; // check if there is a single column with DEFAULT VALUES insert if (columns.Length == 1) { if (columns[0].ArgType == typeof(Value)) { var value = (Value)columns[0].Original; if (value.IsSpecialValue && (string)value.Original == Text.DefaultValues) { isDefaultValues = true; } } } if (isDefaultValues) { sql.NewLine(Text.DefaultValues).S() .Terminate(); } else { sql.NewLine(Text.Values).S() .Append(Text.LeftBracket) .Append(Column.Concatenate(columns, buildContext, buildArgs, null, Text.CommaWithSpace)) .Append(Text.RightBracket) .Terminate(); } return(sql.ToString()); }
private string BuildExecProc(BuildContext buildContext, BuildArgs buildArgs) { // assign the current node of the build context buildContext.Current = _innerObject; if (ReturnVariable != null) { return(Text.GenerateSql(1000) .Append(Executable.Build(buildContext, buildArgs)) .NewLine(Text.Set).S() .Append(ReturnVariable).Append(Text._Equal_).Append(Text.Reserved.ReturnValueOuterParam) .Terminate() .ToString()); } else { return(Executable.Build(buildContext, buildArgs)); } }
private string BuildCase(BuildContext buildContext, BuildArgs buildArgs) { var sql = new StringBuilder(); Chainer node = GetPrev <CaseChainer>(); while (node != this) { object append = null; append = node.Build(buildContext, buildArgs); if (append != null) { sql.Append(append); sql.S(); } node = node.Next; } return(sql.TrimEnd().ToString()); }
// main chain build method internal string BuildChain(BuildContext buildContext, BuildArgs buildArgs) { var sql = Wall.Text.GenerateSql(250); foreach (var statement in GetRoot().Statements) { if (statement.SkipBuild) { continue; } var firstObject = statement.First; // add .Select after .OrderBy (if missing) var orderBy = firstObject.GetNext <OrderByChainer>(); if (orderBy != null && !(orderBy.Next is SelectChainer)) { var next = orderBy.Next; var cselect = new SelectChainer(orderBy, new Column[] { }, false); cselect.SetNext(next); } if (statement.Build != null) { buildContext.Current = firstObject; var append = statement.Build(buildContext, buildArgs); sql.Append(append).S(); } else { BuildSimpleStatement(buildContext, buildArgs, sql, firstObject); } } Terminate(sql); if (sql.Length == 1 && sql[0] == Text.TerminatorChar) { return(String.Empty); } return(sql.ToString()); }
private static void BuildFrom(QueryPart part, BuildContext buildContext, BuildArgs buildArgs, StringBuilder sql) { // tables part.Tables.ForEach(table => { table.BuildNode(part, buildContext, buildArgs, sql); var next = table.Next; if (next is AliasAs) { next = next.Next; } while (next is IJoinCond) { next.BuildNode(part, buildContext, buildArgs, sql); next = next.Next; } ; }); }
// builds simple statement private static void BuildSimpleStatement( BuildContext buildContext, BuildArgs buildArgs, StringBuilder sql, Chainer firstObject) { var node = firstObject; bool terminate = false; while (!terminate) { node.BuildNode(null, buildContext, buildArgs, sql); if (node.EndOfStatement) { terminate = true; } node = node.Next; } }
internal static string BuildConcatenator(BuildContext buildContext, BuildArgs buildArgs, Variable variable) { if (buildContext.Current.IsQuery) { // not allowed in writable methods where direct values are used if (buildContext.Current is IWritable) { buildContext.Current.Throw(QueryTalkExceptionType.ConcatenatorDisallowed, String.Format("concatenator = {0}", variable.Name), Text.Method.Collect); return(null); } var concatenator = new Concatenator(variable); return(concatenator.Build(buildContext, buildArgs)); } else { buildContext.Current.Throw(QueryTalkExceptionType.ConcatenatorDisallowed, String.Format("concatenator = {0}", variable.Name)); return(null); } }
internal void BuildParamAppendix(BuildArgs buildArgs) { _paramDeclaration = new StringBuilder(); _paramAssignment = new StringBuilder(); if (Admin.IsValueParameterizationOn && !buildArgs.IsTesting) { _rootCompilable.ImplicitParams.ForEach(param => { _arguments.Add(param.ParameterizedValue); }); } // return value _paramDeclaration.Append(Text.Reserved.ReturnValueInnerParam).S() .Append(Text.Free.EnclosedInt).S().Append(Text.Output); _paramAssignment.Append(Text.Reserved.ReturnValueInnerParam) .Append(Text._Equal_) .Append(Text.Reserved.ReturnValueOuterParam).S() .Append(Text.Output); // auto add arguments of optional params (if not passed) _rootCompilable.ExplicitParams.Where(param => param.IsOptional).ToList() .ForEach(param => { if (!CheckArgumentByName(param.Name)) { _arguments.Add(param.Default); } }); // exclude inline params, table variable, temp tables and bulk tables bool paramSeparator = false; _arguments.Where(argument => argument.DT.IsNotInliner() && !argument.DT.IsVTB()) .ToList() .ForEach(argument => { // param declaration _paramDeclaration.NewLine(Text.Comma); _paramDeclaration .Append(argument.ParamName) .Append(Text._As_) .Append(GetParamDeclaration(argument, true, false)); string declarationOutput = String.Empty; if (argument.IsParamOutput) { declarationOutput = Text.OneSpace + Text.Output; } _paramDeclaration.Append(declarationOutput); // marks the beginning of client params if (!paramSeparator && argument.ParamName != Text.Reserved.ReturnValueInnerParam) { _paramAssignment.NewLine() .NewLine(Text.Free.Params); paramSeparator = true; } _paramAssignment.NewLine(Text.Comma); // argument is a variable: // note: // variables can only be passed in the inner call, otherwise they are treated as string values if (argument.IsPassedVariable && _inner) { _paramAssignment.Append(argument.ParamName) .Append(Text.Equal) .Append(argument.Value); } // argument is a value: else { _paramAssignment.Append(argument.ParamName) .Append(Text.Equal); if (argument.Original is View) { // note: inner table param has the same name as outer table param _paramAssignment.Append(argument.ParamName); } else if (argument.IsOutput) { _paramAssignment.Append(argument.ParamName) .Append(Text.Underscore) .Append(Text.Output); } else { // the test value has the advantage over the regular value if (argument.TestValue != null) { Testing.AppendTestValue(_paramAssignment, argument); } else { if (argument.DataType != null) { _paramAssignment.Append(Mapping.Build(argument.Value, argument.DataType)); } else { _paramAssignment.Append(Mapping.BuildUnchecked(argument.Value)); } } } } string assignmentOutput = String.Empty; if (argument.IsOutput) { assignmentOutput = Text.OneSpace + Text.Output; } _paramAssignment.Append(assignmentOutput); }); if (chainException != null) { TryThrow(Text.Method.Pass); } }
private static void BuildSelect(QueryPart part, BuildContext buildContext, BuildArgs buildArgs, StringBuilder sql) { part.Select.BuildNode(part, buildContext, buildArgs, sql); }
private static void BuildDelete(QueryPart part, BuildContext buildContext, BuildArgs buildArgs, StringBuilder sql) { part.Delete.BuildNode(part, buildContext, buildArgs, sql); }
private void BuildUpdate(BuildContext buildContext, BuildArgs buildArgs, StringBuilder sql) { _defaultPart.Update.BuildNode(_defaultPart, buildContext, buildArgs, sql); }
private void BuildInsert(BuildContext buildContext, BuildArgs buildArgs, StringBuilder sql) { _defaultPart.Insert.BuildNode(_defaultPart, buildContext, buildArgs, sql); }
// builds the query statement private string BuildQuery(BuildContext buildContext, BuildArgs buildArgs) { // perform concatenation check // If a concatenator is found then the query is assigned the concatenation root and consecutively, // all the variables are properly concatenated and the query is executed in its own exec context. CheckConcat(this, buildContext); var sql = Text.GenerateSql(250); if (Root.CompilableType == Compilable.ObjectType.View && _defaultPart.Ctes.Count > 0) { Root.Throw(QueryTalkExceptionType.InvalidView, null, Text.Method.From); } // build clauses that belong to the default query part BuildCtes(buildContext, buildArgs, sql); BuildInsert(buildContext, buildArgs, sql); BuildUpdate(buildContext, buildArgs, sql); _parts.ForEach(part => { part.Joiner = ProcessJoiner(part, buildContext, buildArgs); BuildCollect(part, buildContext, buildArgs, sql); BuildSelect(part, buildContext, buildArgs, sql); BuildDelete(part, buildContext, buildArgs, sql); part.IntoTempTable.BuildNode(part, buildContext, buildArgs, sql); BuildFrom(part, buildContext, buildArgs, sql); BuildWhere(part, buildContext, buildArgs, sql); part.GroupBy.BuildNode(part, buildContext, buildArgs, sql); part.Having.BuildNode(part, buildContext, buildArgs, sql); part.OrderBy.BuildNode(part, buildContext, buildArgs, sql); part.Union.BuildNode(part, buildContext, buildArgs, sql); }); if (!buildContext.Root.CompilableType.IsViewOrMapper()) { sql.TerminateSingle(); } // concatenation: if (IsConcatenated && IsMaster) { string concatBody = sql.ToString(); return(Text.GenerateSql(500) .NewLine(Text.Set).S() .Append(Text.Reserved.ConcatVar).Append(Text._Equal_) .Append(Text.N).Append(Text.SingleQuote) .Append(concatBody) .Append(Text.SingleQuote).Terminate() .NewLine(Text.Free.ExecSpExecutesql).S() .Append(Text.Reserved.ConcatVar) .Append(BuildConcatParams()) .TerminateSingle() .ToString()); } else { return(sql.ToString()); } }
// multi-value insert private string BuildMultiValueInsert(BuildContext buildContext, BuildArgs buildArgs, Table table) { var sql = BuildHeader(buildContext, buildArgs, table) .NewLine(Text.Values).S(); // treat string columns as values UseStringAsValue = true; var node = (Chainer)GetPrev <ISelectable>(); while (node.Prev != null && node.Prev is ISelectable) { node = node.Prev; } var i = 0; var valueCount = ((ISelectable)node).ColumnCount; while (node is ISelectable) { // skip building the SelectChainer object node.SkipBuild = true; var selectable = (ISelectable)node; // check column-value count match if (buildArgs.Executable == null) // skip checking in case of inlining { if (selectable.ColumnCount != valueCount) { Throw(QueryTalkExceptionType.InvalidColumnCount, String.Format("previous value count = {0}{1} current value count = {2}{3} values = ({4})", valueCount, Environment.NewLine, selectable.ColumnCount, Environment.NewLine, String.Join(", ", selectable.Columns.Select(v => { if (v != null) { return(v.Build(buildContext, buildArgs)); } else { return(Text.DbNull); } } )))); } } if (i++ > 0) { sql.NewLineIndent(Text.Comma); } // append value sql.Append(Text.LeftBracket) .Append(Column.Concatenate(selectable.Columns, buildContext, buildArgs, null, Text.CommaWithSpace)) .Append(Text.RightBracket); node = node.Next; } return(sql .Terminate() .ToString()); }
private string BuildQueryInsert(BuildContext buildContext, BuildArgs buildArgs, Table table) { return(BuildHeader(buildContext, buildArgs, table).ToString()); }
private static Joiner ProcessJoiner(QueryPart queryPart, BuildContext buildContext, BuildArgs buildArgs) { var joiner = new Joiner(queryPart, buildContext, buildArgs); joiner.ProcessJoin(); return(joiner); }
private StringBuilder BuildHeader(BuildContext buildContext, BuildArgs buildArgs, Table table) { var sql = Text.GenerateSql(200); sql.NewLine(BuildTop(buildContext, buildArgs)) .Append(table.Build(buildContext, buildArgs)).S(); Column[] columns = null; var columnsObject = Prev.GetPrev <ColumnsChainer>(); if (columnsObject != null) { columnsObject.Build(buildContext, buildArgs); // Do not build the ColumnsChainer object (it has been built already) . // This is not actually not needed because the Query does not control ColumnsChainer object. // However we set this flag here to make it clear and explicit. columnsObject.SkipBuild = true; // handle column inliner in .ColumnInto method passed as collection columns = ProcessValueArrayInliner(buildContext, buildArgs, Columns); } if (columns == null) { columns = Columns; } // build inline columns if (columns != null) { sql.NewLine(Text.LeftBracket); int i = 0; foreach (var column in columns) { CheckNull(Arg(() => column, column)); if (chainException != null) { chainException.Arguments = String.Format("{0} = null{1} columns = {2}", chainException.Arguments, Environment.NewLine, ToString()); throw chainException; } if (i++ > 0) { sql.Append(Text.Comma).S(); } sql.Append(column.Build(buildContext, buildArgs)); TryThrow(buildContext); } sql.Append(Text.RightBracket) .TrimEnd(); } OutputChainer.TryAppendOutput(this, sql, buildContext, buildArgs); return(sql); }
internal static void TryAppendOutput(IOutput target, StringBuilder sql, BuildContext buildContext, BuildArgs buildArgs) { if (target.OutputColumns == null) { return; } // important: // set buildContext.IsCurrentStringAsValue as false => strings treated as identifiers buildContext.IsCurrentStringAsValue = false; sql.NewLine(Text.Output).S() .Append(Column.Concatenate(target.OutputColumns, buildContext, buildArgs, null, Text.CommaWithSpace)).S(); buildContext.ResetCurrentStringAsValueFlag(); if (target.OutputTarget != null) { sql.Append(Text.Into).S() .Append(target.OutputTarget.Build(buildContext, buildArgs)).S(); } }