001package gudusoft.gsqlparser.stmt;
002
003import gudusoft.gsqlparser.*;
004import gudusoft.gsqlparser.nodes.*;
005import gudusoft.gsqlparser.nodes.EHiveInsertType;
006import gudusoft.gsqlparser.nodes.EOnConflictActionType;
007import gudusoft.gsqlparser.nodes.oracle.TErrorLoggingClause;
008import gudusoft.gsqlparser.stmt.mssql.TMssqlExecute;
009
010import java.util.ArrayList;
011
012/**
013 * SQL insert statement.
014 * <br>
015 * <br> {@link #getTargetTable} returns the table or view that receive the data.
016 * <br> {@link #getColumnList()} returns the list of columns in target table if specified.
017 * <br> Usually, the data comes from a value clause, you can get those values from {@link #getValues()}.
018 * <br> Always checking {@link #getInsertSource} before fetch the data source which may various from value clause
019 * to subquery and other forms. Below are some data source types:
020 * <ul>
021 *     <li>{@link EInsertSource#values} -&gt; {@link #getValues()}</li>
022 *     <li>{@link EInsertSource#subquery} -&gt; {@link #getSubQuery()}</li>
023 * </ul>
024 *
025 * <br>Examples:
026 * <pre>
027 * INSERT INTO Production.UnitMeasure (Name, UnitMeasureCode,ModifiedDate)
028 * VALUES (N'Square Yards', N'Y2', GETDATE());
029 * </pre>
030 * Table name: Production.UnitMeasure. Fetched from {@link #getTargetTable} or the first element of {@link #tables}
031 * <br>column list: (Name, UnitMeasureCode,ModifiedDate). Fetch from {@link #getColumnList}
032 * <br>value list: (N'Square Yards', N'Y2', GETDATE()). Fetch from {@link #getValues}
033 * <br>
034 * <pre>
035 * INSERT INTO dbo.EmployeeSales
036 * SELECT 'SELECT', sp.BusinessEntityID, c.LastName, sp.SalesYTD
037 * FROM Sales.SalesPerson AS sp
038 * INNER JOIN Person.Person AS c
039 * ON sp.BusinessEntityID = c.BusinessEntityID
040 * WHERE sp.BusinessEntityID LIKE '2%'
041 * ORDER BY sp.BusinessEntityID, c.LastName;
042 * </pre>
043 * select query in above insert statement can be fetched from {@link #getSubQuery}
044 *
045 * @see TCustomSqlStatement#cteList
046 * @see TCustomSqlStatement#targetTable
047 * @see TCustomSqlStatement#outputClause
048 * @see TCustomSqlStatement#returningClause
049 *
050 */
051public class TInsertSqlStatement extends TCustomSqlStatement {
052
053    private ArrayList<TInsertSqlStatement> multiInsertStatements;
054
055    /**
056     * Hive, from table insert..., insert ...
057     * @return
058     */
059    public ArrayList<TInsertSqlStatement> getMultiInsertStatements() {
060        if (this.multiInsertStatements == null){
061            this.multiInsertStatements = new ArrayList<>();
062        }
063        return multiInsertStatements;
064    }
065
066    private String fileFormat;
067    private String fileOptions = null;
068
069    public String getFileFormat() {
070        return fileFormat;
071    }
072
073    public String getFileOptions() {
074        return fileOptions;
075    }
076
077    private TObjectName sourceValueTable;
078
079    public TObjectName getSourceValueTable() {
080        return sourceValueTable;
081    }
082
083    private boolean insertAll = false;
084    private boolean insertFirst = false;
085
086    public void setInsertAll(boolean insertAll) {
087        this.insertAll = insertAll;
088    }
089
090    public void setInsertFirst(boolean insertFirst) {
091        this.insertFirst = insertFirst;
092    }
093
094    /**
095     * Oracle insert all
096     * @return Oracle insert all
097     */
098    public boolean isInsertAll() {
099
100        return insertAll;
101    }
102
103    /**
104     * Oracle insert first
105     * @return Oracle insert first
106     */
107    public boolean isInsertFirst() {
108        return insertFirst;
109    }
110
111    /**
112     * Whether this is a multi-table insert, {@code INSERT ALL} or {@code INSERT FIRST}: the VALUES of its INTO
113     * clauses read the select list of its subquery. The two forms differ only in which WHEN branch receives a
114     * row, so a rule about what a VALUES name reads must test this, not {@link #isInsertAll()} alone.
115     *
116     * @return true for {@code INSERT ALL} and {@code INSERT FIRST}
117     */
118    public boolean isMultiTableInsert() {
119        return insertAll || insertFirst;
120    }
121
122    private TErrorLoggingClause errorLoggingClause;
123
124    /**
125     * Oracle error logging clause
126     * @return Oracle error logging clause
127     */
128    public TErrorLoggingClause getErrorLoggingClause() {
129        return errorLoggingClause;
130    }
131
132    /**
133     * Hive insert type
134     * @return Hive insert type
135     */
136    public EHiveInsertType getHiveInsertType() {
137        return hiveInsertType;
138    }
139
140    /**
141     * Hive directory name
142     * @return directory name
143     */
144    public TObjectName getDirectoryName() {
145        if( (directoryName == null)&&(fileOptions != null)){
146            String a[] = fileOptions.split("[,]");
147            for(String s:a){
148                if (s.trim().startsWith("\'path\'")){
149                    directoryName = TObjectName.createObjectName (this.dbvendor, EDbObjectType.directory_path, new TSourceToken(s.split("[ ]")[1]));
150                    break;
151                }
152            }
153        }
154        return directoryName;
155    }
156
157
158    private EHiveInsertType hiveInsertType = EHiveInsertType.intoUnknown;
159    private TObjectName directoryName = null;
160
161    private TPTNodeList<TInsertCondition>  insertConditions;
162    private TPTNodeList<TInsertIntoValue> insertIntoValues;
163
164    /**
165     * Oracle insert condition
166     * @return Oracle insert condition
167     */
168    public TPTNodeList<TInsertCondition> getInsertConditions() {
169        return insertConditions;
170    }
171
172    /**
173     * Oracle insert into values used after insert all/first clause
174     * @return Oracle insert into values used after insert all/first clause
175     */
176    public TPTNodeList<TInsertIntoValue> getInsertIntoValues() {
177        return insertIntoValues;
178    }
179
180    public void setInsertToken(TSourceToken insertToken) {
181        this.insertToken = insertToken;
182    }
183
184    /**
185     * INSERT keyword
186     * @return INSERT keyword
187     */
188    public TSourceToken getInsertToken() {
189
190        return insertToken;
191    }
192
193    private TSourceToken insertToken = null;
194    
195    /**
196     * value clause valid when {@link #getInsertSource} is {@link gudusoft.gsqlparser.EInsertSource#subquery}.
197     * @return {@link gudusoft.gsqlparser.stmt.TSelectSqlStatement sub-query}
198     */
199    public TSelectSqlStatement getSubQuery() {
200        return subQuery;
201    }
202
203    private TSelectSqlStatement subQuery = null;
204
205    private TFunctionCall functionCall = null;
206
207    private TMssqlExecute executeStmt = null;
208
209    /**
210     * value clause valid when {@link #getInsertSource} is {@link gudusoft.gsqlparser.EInsertSource#values_function}.
211     * @return row value was constructed by a function.
212     */
213    public TFunctionCall getFunctionCall() {
214        return functionCall;
215    }
216
217    /**
218     * Oracle PLSQL record name in values clause, {@link #getInsertSource} returns {@link  EInsertSource#values_oracle_record}
219     * @return record name in plsql.
220     */
221    public TObjectName getRecordName() {
222        return recordName;
223    }
224
225    private  TObjectName recordName = null;
226
227    /**
228     * Type of the source from where the data is coming for this insert statement.
229     * @return Type of the data source
230     */
231    public EInsertSource getInsertSource() {
232        return insertSource;
233    }
234
235    private EInsertSource insertSource = EInsertSource.values;
236
237    /**
238     * @deprecated As of v1.6.4.9, use {@link #getInsertSource} instead.
239     *
240     * @return how rows was insert into table. value can be one of
241     * <p>vt_values,  {@link #getValues}
242     * <p>vt_values_empty, syntax like: value ()
243     * <p>vt_query,   {@link #getSubQuery}
244     * <p>vt_default_values,
245     * <p>vt_execute,
246     * <p>vt_values_function, {@link #getFunctionCall} 
247     */
248    public int getValueType() {
249        return valueType;
250    }
251
252    /**
253     * value clause, valid when {@link #getInsertSource} is {@link EInsertSource#values}.
254     * represents in format like this: ((1,2,3),(4,5),(6,7,8)),
255     * if even value clause is (1,2,3), it will be saved in {@link TMultiTargetList} like ((1,2,3))
256     * <br>
257     * @return a single row value, or multi row values returned by query or value constructor.
258     */
259    public TMultiTargetList getValues() {
260        return values;
261    }
262
263    private TMultiTargetList values = null;
264
265    private int valueType = TBaseType.vt_values;
266
267    private TResultColumnList setColumnValues = null;
268
269    private TSourceToken ignore;
270    private TSourceToken priority_delayed;
271
272    private TResultColumnList onDuplicateKeyUpdate = null;
273
274    /**
275     * MySQL on duplicate key update column list.
276     * @return MySQL on duplicate key update column list
277     */
278    public TResultColumnList getOnDuplicateKeyUpdate() {
279        return onDuplicateKeyUpdate;
280    }
281
282    /**
283     * MySQL 8.0.20+ row alias for INSERT ... ON DUPLICATE KEY UPDATE.
284     * Allows referencing the inserted row values without using VALUES() function.
285     * Example: INSERT INTO t1 (a,b,c) VALUES (1,2,3) AS new ON DUPLICATE KEY UPDATE c = new.a+new.b;
286     */
287    private TObjectName insertRowAlias = null;
288
289    /**
290     * MySQL 8.0.20+ optional column aliases for the row alias.
291     * Example: INSERT INTO t1 (a,b,c) VALUES (1,2,3) AS new(m,n,p) ON DUPLICATE KEY UPDATE c = m+n;
292     */
293    private TObjectNameList insertRowAliasColumnList = null;
294
295    /**
296     * Get MySQL 8.0.20+ row alias for INSERT ... ON DUPLICATE KEY UPDATE.
297     * @return the row alias name, or null if not specified
298     */
299    public TObjectName getInsertRowAlias() {
300        return insertRowAlias;
301    }
302
303    /**
304     * Get MySQL 8.0.20+ optional column aliases for the row alias.
305     * @return the column alias list, or null if not specified
306     */
307    public TObjectNameList getInsertRowAliasColumnList() {
308        return insertRowAliasColumnList;
309    }
310
311    private TOnConflictClause onConflictClause;
312
313    /**
314     * PostgreSQL ON CONFLICT clause (UPSERT).
315     * <p>Provides access to the conflict target (columns or constraint name),
316     * the action type (DO NOTHING or DO UPDATE), and the SET/WHERE clauses
317     * for DO UPDATE actions.
318     *
319     * <p>Example:
320     * <pre>
321     * INSERT INTO tbl VALUES (1, 2) ON CONFLICT (id) DO UPDATE SET col = EXCLUDED.col;
322     * </pre>
323     *
324     * @return the ON CONFLICT clause, or null if not present
325     */
326    public TOnConflictClause getOnConflictClause() {
327        return onConflictClause;
328    }
329
330    /**
331     * IGNORE keyword used in the insert statement.
332     * @return IGNORE keyword if used, otherwise, returns null.
333     */
334    public TSourceToken getIgnore() {
335
336        return ignore;
337    }
338
339    /**
340     * DELAY, LOW_PRIORITY, HIGH_PRIORITY keyword used in insert statement.
341     * @return null if none of those keywords is used: DELAY, LOW_PRIORITY, HIGH_PRIORITY
342     */
343    public TSourceToken getPriority_delayed() {
344        return priority_delayed;
345    }
346
347    /**
348     * set column value clauses in MySQL insert statement.
349     * @return MySQL specific column value list.
350     */
351    public TResultColumnList getSetColumnValues() {
352        return setColumnValues;
353    }
354
355    public TInsertSqlStatement(EDbVendor dbvendor) {
356        super(dbvendor);
357        sqlstatementtype = ESqlStatementType.sstinsert;
358    }
359
360    void buildsql() {
361    }
362
363    void clear() {
364    }
365
366    String getasprettytext() {
367        return "";
368    }
369
370    void iterate(TVisitorAbs pvisitor) {
371    }
372
373    /**
374     * columns of the target table.
375     * @return column name list in insert into clause.
376     */
377    public TObjectNameList getColumnList() {
378        return columnList;
379    }
380
381    private TObjectNameList columnList = null;
382
383    public void setValues(TMultiTargetList values) {
384        this.values = values;
385    }
386
387    public void setColumnList(TObjectNameList columnList) {
388        this.columnList = columnList;
389    }
390
391    public void setSubQuery(TSelectSqlStatement subQuery) {
392        insertSource = EInsertSource.subquery;
393        this.subQuery = subQuery;
394    }
395
396    /**
397     * SQL Server, execute statement used in the insert statement.
398     * {@link #getInsertSource()} returns {@link EInsertSource#execute}
399     *
400     * @return SQL Server, execute statement
401     */
402    public TMssqlExecute getExecuteStmt() {
403        return executeStmt;
404    }
405
406    private TPTNodeList<TInsertIntoValue> elseIntoValues;
407
408    /**
409     * Oracle,  values in else clause
410     * @return values in else clause
411     */
412    public TPTNodeList<TInsertIntoValue> getElseIntoValues() {
413        return elseIntoValues;
414    }
415
416    public int doParseStatement(TCustomSqlStatement psql) {
417        if (rootNode == null) return -1;
418        TInsertSqlNode insertNode = (TInsertSqlNode)rootNode;
419
420        if (this.sourcetokenlist.size() == 0){
421            // subquery nested in other statements.
422            this.setStartToken(insertNode.getStartToken());
423            this.setEndToken(insertNode.getEndToken());
424        }
425
426        super.doParseStatement(psql);
427
428        if (insertNode.hasInvalidColumnList()) {
429            TSourceToken errorToken = insertNode.getInsertToken();
430            if (errorToken != null) {
431                parseerrormessagehandle(new TSyntaxError(errorToken,
432                        "invalid INSERT column list", EErrorType.sperror,
433                        TBaseType.MSG_ERROR_SYNTAX_ERROR, this));
434            } else {
435                parseerrormessagehandle(new TSyntaxError("INSERT", 0, 0,
436                        "invalid INSERT column list", EErrorType.sperror,
437                        TBaseType.MSG_ERROR_SYNTAX_ERROR, this, -1));
438            }
439            return TBaseType.MSG_ERROR_SYNTAX_ERROR;
440        }
441
442        this.insertToken = insertNode.getInsertToken();
443        this.ignore = insertNode.getIgnore();
444        this.priority_delayed = insertNode.getPriority_delayed();
445        this.insertAll = insertNode.isInsertAll();
446        this.insertFirst = insertNode.isInsertFirst();
447        this.hiveInsertType = insertNode.getHiveInsertType();
448
449        this.valueType = insertNode.getValueType();
450
451        // Databricks supports INSERT OVERWRITE [LOCAL] DIRECTORY as well (Mantis 4646)
452        if((dbvendor == EDbVendor.dbvhive)||(dbvendor == EDbVendor.dbvsparksql)||(dbvendor == EDbVendor.dbvdatabricks)){
453
454            this.hiveInsertType = insertNode.getHiveInsertType();
455            this.directoryName = insertNode.getDirectoryName();
456            this.fileFormat = insertNode.getFileFormat();
457            this.fileOptions = insertNode.getFileOptions();
458            if (insertNode.getInsertSqlNodes() != null){
459                for(int i=1;i<insertNode.getInsertSqlNodes().size();i++){
460                    // i=1, start from the second insert statement, the first is this insert statement itself.
461                    TInsertSqlStatement newInsert = new TInsertSqlStatement(this.dbvendor);
462                    newInsert.rootNode = insertNode.getInsertSqlNodes().get(i);
463                    newInsert.setFrameStack(this.getFrameStack());
464                    newInsert.doParseStatement(psql);
465                    this.getMultiInsertStatements().add(newInsert);
466                }
467            }
468        }
469
470        if (insertNode.cteList != null){
471            this.setCteList( insertNode.cteList);
472            this.getCteList().doParse(this, ESqlClause.cte);
473        }
474
475
476        if (insertNode.getTopClause() != null){
477           insertNode.getTopClause().doParse(this,ESqlClause.top);
478           this.setTopClause(insertNode.getTopClause());
479        }
480
481        if ((this.valueType != TBaseType.vt_values_multi_table)
482                &&(insertNode.getTargetTable() != null)
483            )
484        {
485           // System.out.println(insertNode.getTargetTable().toString());
486           TTable lcTable = analyzeFromTable(insertNode.getTargetTable(),true);
487           lcTable.setEffectType(ETableEffectType.tetInsert);
488           unbindCteTarget(lcTable);
489           setTargetTable(lcTable);
490           this.getRelations().add(lcTable);
491        }
492
493        if (insertNode.getColumnList() != null){
494            this.columnList = insertNode.getColumnList(); 
495            TObjectName crf ;
496            for (int i=0;i< insertNode.getColumnList().size();i++){
497                crf =insertNode.getColumnList().getObjectName(i);
498                // link this column to last 2 tables
499                crf.setLocation(ESqlClause.insertColumn);
500                crf.columnToPropertyIfQualifiedByTable(getTargetTable()); // Mantis #4747
501                getTargetTable().getObjectNameReferences().addObjectName(crf);
502                getTargetTable().getLinkedColumns().addObjectName(crf);
503                crf.setSourceTable(getTargetTable());
504            }
505
506            //insertNode.getColumnList().doParse(this,TBaseType.insertColumnClause);
507        }
508
509        if (insertNode.getOutputClause() != null){
510            insertNode.getOutputClause().doParse(this,ESqlClause.output);
511            this.setOutputClause(insertNode.getOutputClause());
512        }
513
514        switch(valueType){
515            case TBaseType.vt_values:
516                insertSource = EInsertSource.values;
517                insertNode.getValues().doParse(this,ESqlClause.insertValues);
518                this.values = insertNode.getValues();
519                // check is count of value list is the same as column list
520                if (columnList != null){
521                    TMultiTarget mt;
522                    TSourceToken st1;
523                    // Hive/Impala INSERT ... (cols) PARTITION (p1, p2=v) VALUES (...):
524                    // each dynamic partition column (no '=value') is supplied by the
525                    // VALUES row, so it raises the expected value count by one.
526                    // Scoped to the Hive family, where dynamic partition columns are
527                    // part of the row; Oracle-style PARTITION (name) does not add values.
528                    int dynamicPartitionCols = 0;
529                    if ((this.dbvendor == EDbVendor.dbvimpala || this.dbvendor == EDbVendor.dbvhive
530                            || this.dbvendor == EDbVendor.dbvsparksql)
531                            && (getTargetTable() != null)
532                            && (getTargetTable().getPartitionExtensionClause() != null)
533                            && (getTargetTable().getPartitionExtensionClause().getKeyValues() != null)){
534                        TExpressionList lcPartitionVals = getTargetTable().getPartitionExtensionClause().getKeyValues();
535                        for(int k=0;k<lcPartitionVals.size();k++){
536                            if (lcPartitionVals.getExpression(k).getExpressionType() != EExpressionType.assignment_t){
537                                dynamicPartitionCols++;
538                            }
539                        }
540                    }
541                    for(int k=0;k<values.size();k++){
542                        mt = values.getMultiTarget(k);
543                        if (mt.getColumnList() == null) continue;
544                        if (mt.getColumnList().size() == 0) continue;
545                        if (mt.getColumnList().getResultColumn(0).getExpr() == null) continue;
546                        if (mt.getColumnList().getResultColumn(0).getExpr().getExpressionType() == EExpressionType.subquery_t) continue;
547                        if (mt.getColumnList().size() == columnList.size() + dynamicPartitionCols) continue;
548                        if (mt.getColumnList().size() != columnList.size()){
549                            st1 = mt.getColumnList().getStartToken();
550                            TSyntaxError err = new TSyntaxError(st1.toString()
551                                    ,st1.lineNo,st1.columnNo
552                                    ,String.format("value count(%d) is not the same as column list(%d)",mt.getColumnList().size(),columnList.size())
553                                    ,EErrorType.sperror ,TBaseType.MSG_ERROR_INSERT_VALUE_COLUMN_NUMBER_NOT_MATCH,this,st1.posinlist);
554                            this.parseerrormessagehandle( err);
555                        }
556                    }
557                }
558                break;
559            case TBaseType.vt_values_empty:
560                insertSource = EInsertSource.values_empty;
561                break;
562            case TBaseType.vt_values_multi_table:
563                insertSource = EInsertSource.values_multi_table;
564                if (subQuery == null){
565                    subQuery = new TSelectSqlStatement(this.dbvendor);
566                    subQuery.rootNode = insertNode.getSubQueryNode();
567                }
568                subQuery.doParseStatement(this);
569
570                break;
571            case TBaseType.vt_query:
572                insertSource = EInsertSource.subquery;
573                if (subQuery == null){
574                    subQuery = new TSelectSqlStatement(this.dbvendor);
575                    subQuery.rootNode = insertNode.getSubQueryNode();
576                }
577                subQuery.doParseStatement(this);
578                break;
579            case TBaseType.vt_hive_query:
580                insertSource = EInsertSource.hive_query;
581                if (subQuery == null){
582                    subQuery = new TSelectSqlStatement(this.dbvendor);
583                    subQuery.rootNode = insertNode.getSubQueryNode();
584                }
585                subQuery.doParseStatement(this);
586                break;
587            case TBaseType.vt_default_values:
588                insertSource = EInsertSource.default_values;
589                break;
590            case TBaseType.vt_execute:
591                insertSource = EInsertSource.execute;
592                executeStmt = new TMssqlExecute(EDbVendor.dbvmssql);
593                executeStmt.rootNode = insertNode.getExecuteSqlNode();
594                executeStmt.doParseStatement(this);
595                break;
596            case TBaseType.vt_values_function:
597                insertSource = EInsertSource.values_function;
598                insertNode.getFunctionCall().doParse(this,ESqlClause.insertValues);
599
600                this.functionCall = insertNode.getFunctionCall(); 
601                break;
602            case TBaseType.vt_values_oracle_record:
603                insertSource = EInsertSource.values_oracle_record;
604                insertNode.getRecordName().doParse(this,ESqlClause.insertValues);
605                this.recordName = insertNode.getRecordName();
606                break;
607            case TBaseType.vt_set_column_value:
608                insertSource = EInsertSource.set_column_value;
609                this.setColumnValues = insertNode.getSetColumnValues();
610                this.setColumnValues.doParse(this,ESqlClause.insertValues);
611                break;
612            case TBaseType.vt_table:
613                insertSource = EInsertSource.value_table;
614                this.sourceValueTable = insertNode.getSourceValueTable();
615                break;
616        }
617
618        if (insertNode.getInsertConditions() != null){
619            this.valueType = TBaseType.vt_values_multi_table;
620            this.insertConditions = insertNode.getInsertConditions();
621            this.insertConditions.doParse(this,ESqlClause.insertValues);
622            setTargetTable(insertConditions.getElement(0).getInsertIntoValues().getElement(0).getTable() );
623        }
624
625        if (insertNode.getInsertIntoValues() != null){
626            this.valueType = TBaseType.vt_values_multi_table;
627            this.insertIntoValues = insertNode.getInsertIntoValues();
628            this.insertIntoValues.doParse(this,ESqlClause.insertValues);
629            setTargetTable(insertIntoValues.getElement(0).getTable());
630        }
631
632        if (insertNode.getElseIntoValues() != null){
633            this.valueType = TBaseType.vt_values_multi_table;
634            this.elseIntoValues = insertNode.getElseIntoValues();
635            this.elseIntoValues.doParse(this,ESqlClause.insertValues);
636            setTargetTable(elseIntoValues.getElement(0).getTable());
637        }
638
639        if (insertNode.getReturningClause() != null){
640            insertNode.getReturningClause().doParse(this,ESqlClause.returning);
641            this.setReturningClause(insertNode.getReturningClause());
642        }
643
644        if (insertNode.getOnDuplicateKeyUpdate() != null){
645            this.onDuplicateKeyUpdate = insertNode.getOnDuplicateKeyUpdate();
646            onDuplicateKeyUpdate.doParse(this,ESqlClause.unknown);
647        }
648
649        // MySQL 8.0.20+ row alias for INSERT ... ON DUPLICATE KEY UPDATE
650        this.insertRowAlias = insertNode.getInsertRowAlias();
651        this.insertRowAliasColumnList = insertNode.getInsertRowAliasColumnList();
652
653        // PostgreSQL ON CONFLICT clause
654        if (insertNode.getOnConflictClause() != null){
655            this.onConflictClause = insertNode.getOnConflictClause();
656            onConflictClause.doParse(this, ESqlClause.unknown);
657        }
658
659        errorLoggingClause = insertNode.getErrorLoggingClause();
660        return 0;
661    }
662
663    public void accept(TParseTreeVisitor v){
664        v.preVisit(this);
665
666        v.postVisit(this);
667    }
668
669    public void acceptChildren(TParseTreeVisitor v){
670        v.preVisit(this);
671
672        if (this.getCteList() != null){
673            this.getCteList().acceptChildren(v);
674        }
675
676        if (this.getTopClause() != null){
677            this.getTopClause().acceptChildren(v);
678        }
679
680        if (this.getTargetTable() != null){
681            this.getTargetTable().acceptChildren(v);
682        }
683
684        if (this.getColumnList() != null){
685            this.getColumnList().acceptChildren(v);
686        }
687
688        if (this.getOutputClause() != null){
689            this.getOutputClause().acceptChildren(v);
690        }
691
692        switch(this.getValueType()){
693            case TBaseType.vt_values:
694                if (this.getValues() != null) {
695                    this.getValues().acceptChildren(v);
696                }
697                break;
698            case TBaseType.vt_values_empty:
699                break;
700            case TBaseType.vt_query:
701                if (this.getSubQuery() != null) {
702                    this.getSubQuery().acceptChildren(v);
703                }
704                break;
705            case TBaseType.vt_values_function:
706                if (this.getFunctionCall() != null) {
707                    this.getFunctionCall().acceptChildren(v);
708                }
709                break;
710            case TBaseType.vt_values_oracle_record:
711                if (this.getRecordName() != null) {
712                    this.getRecordName().acceptChildren(v);
713                }
714                break;
715            case TBaseType.vt_set_column_value:
716                if (this.getSetColumnValues() != null) {
717                    this.getSetColumnValues().acceptChildren(v);
718                }
719                break;
720            case TBaseType.vt_values_multi_table:
721                // Oracle INSERT ALL/FIRST: traverse conditional inserts, unconditional inserts, else clause, and source subquery
722                if (this.getInsertConditions() != null) {
723                    this.getInsertConditions().acceptChildren(v);
724                }
725                if (this.getInsertIntoValues() != null) {
726                    this.getInsertIntoValues().acceptChildren(v);
727                }
728                if (this.getElseIntoValues() != null) {
729                    this.getElseIntoValues().acceptChildren(v);
730                }
731                if (this.getSubQuery() != null) {
732                    this.getSubQuery().acceptChildren(v);
733                }
734                break;
735            default:
736                break;
737        }
738
739        if (this.onConflictClause != null){
740            this.onConflictClause.acceptChildren(v);
741        }
742
743        if (this.getReturningClause() != null){
744            this.getReturningClause().acceptChildren(v);
745        }
746
747        v.postVisit(this);
748    }
749
750    public void setErrorLoggingClause(TErrorLoggingClause errorLoggingClause) {
751        this.errorLoggingClause = errorLoggingClause;
752    }
753
754    public void setHiveInsertType(EHiveInsertType hiveInsertType) {
755        this.hiveInsertType = hiveInsertType;
756    }
757
758    public void setDirectoryName(TObjectName directoryName) {
759        this.directoryName = directoryName;
760    }
761
762    public void setInsertConditions(TPTNodeList<TInsertCondition> insertConditions) {
763        this.insertConditions = insertConditions;
764    }
765
766    public void setInsertIntoValues(TPTNodeList<TInsertIntoValue> insertIntoValues) {
767        this.insertIntoValues = insertIntoValues;
768    }
769
770    public void setFunctionCall(TFunctionCall functionCall) {
771        this.functionCall = functionCall;
772    }
773
774    public void setExecuteStmt(TMssqlExecute executeStmt) {
775        this.executeStmt = executeStmt;
776    }
777
778    public void setRecordName(TObjectName recordName) {
779        this.recordName = recordName;
780    }
781
782    public void setInsertSource(EInsertSource insertSource) {
783        this.insertSource = insertSource;
784    }
785
786    public void setValueType(int valueType) {
787        this.valueType = valueType;
788    }
789
790    public void setSetColumnValues(TResultColumnList setColumnValues) {
791        this.setColumnValues = setColumnValues;
792    }
793
794    public void setOnDuplicateKeyUpdate(TResultColumnList onDuplicateKeyUpdate) {
795        this.onDuplicateKeyUpdate = onDuplicateKeyUpdate;
796    }
797}