コード例 #1
0
 internal Joiner(QueryPart queryPart, BuildContext buildContext, BuildArgs buildArgs)
 {
     _queryPart    = queryPart;
     _buildContext = buildContext;
     _buildArgs    = buildArgs;
     _targets      = new List <TableChainer>();
 }
コード例 #2
0
ファイル: InsertChainer.cs プロジェクト: amosvoron/querytalk
 private string BuildTop(BuildContext buildContext, BuildArgs buildArgs)
 {
     return(String.Format("{0} {1}{2} ",
                          Text.Insert,
                          base.BuildTop(buildContext),
                          Text.Into));
 }
コード例 #3
0
 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));
     }
 }
コード例 #4
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());
            }
        }
コード例 #5
0
 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);
     });
 }
コード例 #6
0
        // 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));
        }
コード例 #7
0
ファイル: Chainer.cs プロジェクト: amosvoron/querytalk
        internal string BuildConcatenator(BuildContext buildContext, BuildArgs buildArgs, Concatenator arg)
        {
            IsConcat = true;

            if (this is Argument)
            {
                buildContext.Current.IsConcat = true;
            }

            return(arg.Build(buildContext, buildArgs));
        }
コード例 #8
0
ファイル: WriteChainer.cs プロジェクト: amosvoron/querytalk
        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);
        }
コード例 #9
0
        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);
        }
コード例 #10
0
        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);
        }
コード例 #11
0
ファイル: Variable.cs プロジェクト: amosvoron/querytalk
        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);
        }
コード例 #12
0
ファイル: Connectable.cs プロジェクト: amosvoron/querytalk
        // 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);
        }
コード例 #13
0
ファイル: InsertChainer.cs プロジェクト: amosvoron/querytalk
        // 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());
        }
コード例 #14
0
ファイル: ExecChainer.cs プロジェクト: amosvoron/querytalk
        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));
            }
        }
コード例 #15
0
        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());
        }
コード例 #16
0
        // 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());
        }
コード例 #17
0
        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;
                }
                ;
            });
        }
コード例 #18
0
        // 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;
            }
        }
コード例 #19
0
        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);
            }
        }
コード例 #20
0
ファイル: Executable.cs プロジェクト: amosvoron/querytalk
        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);
            }
        }
コード例 #21
0
 private static void BuildSelect(QueryPart part, BuildContext buildContext, BuildArgs buildArgs, StringBuilder sql)
 {
     part.Select.BuildNode(part, buildContext, buildArgs, sql);
 }
コード例 #22
0
 private static void BuildDelete(QueryPart part, BuildContext buildContext, BuildArgs buildArgs, StringBuilder sql)
 {
     part.Delete.BuildNode(part, buildContext, buildArgs, sql);
 }
コード例 #23
0
 private void BuildUpdate(BuildContext buildContext, BuildArgs buildArgs, StringBuilder sql)
 {
     _defaultPart.Update.BuildNode(_defaultPart, buildContext, buildArgs, sql);
 }
コード例 #24
0
 private void BuildInsert(BuildContext buildContext, BuildArgs buildArgs, StringBuilder sql)
 {
     _defaultPart.Insert.BuildNode(_defaultPart, buildContext, buildArgs, sql);
 }
コード例 #25
0
        // 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());
            }
        }
コード例 #26
0
ファイル: InsertChainer.cs プロジェクト: amosvoron/querytalk
        // 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());
        }
コード例 #27
0
ファイル: InsertChainer.cs プロジェクト: amosvoron/querytalk
 private string BuildQueryInsert(BuildContext buildContext, BuildArgs buildArgs, Table table)
 {
     return(BuildHeader(buildContext, buildArgs, table).ToString());
 }
コード例 #28
0
        private static Joiner ProcessJoiner(QueryPart queryPart, BuildContext buildContext, BuildArgs buildArgs)
        {
            var joiner = new Joiner(queryPart, buildContext, buildArgs);

            joiner.ProcessJoin();
            return(joiner);
        }
コード例 #29
0
ファイル: InsertChainer.cs プロジェクト: amosvoron/querytalk
        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);
        }
コード例 #30
0
        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();
            }
        }