1 /*
2  * Copyright 2015-2018 HuntLabs.cn
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance _with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 module hunt.sql.repository.SchemaResolveVisitorFactory;
17 
18 import hunt.sql.SQLUtils;
19 import hunt.sql.ast;
20 import hunt.sql.ast.expr;
21 import hunt.sql.ast.statement;
22 // import hunt.sql.dialect.db2.ast.DB2Object;
23 // import hunt.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;
24 // import hunt.sql.dialect.db2.visitor.DB2ASTVisitorAdapter;
25 // import hunt.sql.dialect.hive.ast.HiveInsert;
26 // import hunt.sql.dialect.hive.ast.HiveMultiInsertStatement;
27 // import hunt.sql.dialect.hive.visitor.HiveASTVisitorAdapter;
28 import hunt.sql.dialect.mysql.ast.MysqlForeignKey;
29 import hunt.sql.dialect.mysql.ast.clause.MySqlCursorDeclareStatement;
30 import hunt.sql.dialect.mysql.ast.clause.MySqlDeclareStatement;
31 import hunt.sql.dialect.mysql.ast.clause.MySqlRepeatStatement;
32 import hunt.sql.dialect.mysql.ast.statement;
33 import hunt.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;
34 // import hunt.sql.dialect.odps.ast;
35 // import hunt.sql.dialect.odps.visitor.OdpsASTVisitorAdapter;
36 // import hunt.sql.dialect.oracle.ast.stmt;
37 // import hunt.sql.dialect.oracle.visitor.OracleASTVisitorAdapter;
38 import hunt.sql.dialect.postgresql.ast.stmt;
39 import hunt.sql.dialect.postgresql.visitor.PGASTVisitorAdapter;
40 // import hunt.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
41 // import hunt.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement;
42 // import hunt.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement;
43 // import hunt.sql.dialect.sqlserver.visitor.SQLServerASTVisitorAdapter;
44 import hunt.sql.visitor.SQLASTVisitorAdapter;
45 import hunt.sql.util.FnvHash;
46 import hunt.sql.util.PGUtils;
47 import hunt.sql.repository.SchemaResolveVisitor;
48 import hunt.sql.repository.SchemaRepository;
49 import hunt.sql.repository.SchemaObject;
50 import hunt.collection;
51 // import hunt.util.Argument;
52 
53 
54 class SchemaResolveVisitorFactory {
55     static class MySqlResolveVisitor : MySqlASTVisitorAdapter , SchemaResolveVisitor {
56 
57         alias endVisit = MySqlASTVisitorAdapter.endVisit;
58         alias visit = MySqlASTVisitorAdapter.visit;
59 
60         private SchemaRepository repository;
61         private int options;
62         private SchemaResolveVisitor.Context context;
63 
64         public this(SchemaRepository repository, int options) {
65             this.repository = repository;
66             this.options = options;
67         }
68 
69         override  public bool visit(SQLSelectStatement x) {
70             resolve(this, x.getSelect());
71             return false;
72         }
73 
74         override  public bool visit(MySqlRepeatStatement x) {
75             return true;
76         }
77 
78         override public bool visit(MySqlDeclareStatement x) {
79             foreach(SQLDeclareItem declareItem ; x.getVarList()) {
80                 visit(declareItem);
81             }
82             return false;
83         }
84 
85         override public bool visit(MySqlCursorDeclareStatement x) {
86             return true;
87         }
88 
89         override public bool visit(MysqlForeignKey x) {
90             resolve(this, x);
91             return false;
92         }
93 
94         override public bool visit(SQLExprTableSource x) {
95             resolve(this, x);
96             return false;
97         }
98 
99         override public bool visit(MySqlSelectQueryBlock x) {
100             resolve(this, x);
101             return false;
102         }
103 
104         override public bool visit(SQLSelectQueryBlock x) {
105             resolve(this, x);
106             return false;
107         }
108 
109         override public bool visit(SQLSelectItem x) {
110             SQLExpr expr = x.getExpr();
111             if (cast(SQLIdentifierExpr)(expr) !is null) {
112                 resolve(this, cast(SQLIdentifierExpr) expr);
113                 return false;
114             }
115 
116             if (cast(SQLPropertyExpr)(expr) !is null) {
117                 resolve(this, cast(SQLPropertyExpr) expr);
118                 return false;
119             }
120 
121             return true;
122         }
123 
124         override public bool visit(SQLIdentifierExpr x) {
125             resolve(this, x);
126             return true;
127         }
128 
129         override public bool visit(SQLPropertyExpr x) {
130             resolve(this, x);
131             return false;
132         }
133 
134         override public bool visit(SQLAllColumnExpr x) {
135             resolve(this, x);
136             return false;
137         }
138 
139         override public bool visit(MySqlCreateTableStatement x) {
140             resolve(this, x);
141             SQLExprTableSource like = x.getLike();
142             if (like !is null) {
143                 like.accept(this);
144             }
145             return false;
146         }
147 
148         override public bool visit(MySqlUpdateStatement x) {
149             resolve(this, x);
150             return false;
151         }
152 
153         override public bool visit(MySqlDeleteStatement x) {
154             resolve(this, x);
155             return false;
156         }
157 
158         override public bool visit(SQLSelect x) {
159             resolve(this, x);
160             return false;
161         }
162 
163         override public bool visit(SQLWithSubqueryClause x) {
164             resolve(this, x);
165             return false;
166         }
167 
168         override public bool visit(SQLAlterTableStatement x) {
169             resolve(this, x);
170             return false;
171         }
172 
173         override public bool visit(MySqlInsertStatement x) {
174             resolve(this, x);
175             return false;
176         }
177 
178         override public bool visit(SQLInsertStatement x) {
179             resolve(this, x);
180             return false;
181         }
182 
183         override public bool visit(SQLReplaceStatement x) {
184             resolve(this, x);
185             return false;
186         }
187 
188         override public bool visit(SQLMergeStatement x) {
189             resolve(this, x);
190             return false;
191         }
192 
193         override public bool visit(SQLCreateProcedureStatement x) {
194             resolve(this, x);
195             return false;
196         }
197 
198         override public bool visit(SQLBlockStatement x) {
199             resolve(this, x);
200             return false;
201         }
202 
203         override public bool visit(SQLParameter x) {
204             resolve(this, x);
205             return false;
206         }
207 
208         override public bool visit(SQLDeclareItem x) {
209             resolve(this, x);
210             return false;
211         }
212 
213         override public bool visit(SQLOver x) {
214             resolve(this, x);
215             return false;
216         }
217 
218         override
219         public bool isEnabled(Option option) {
220             return (options & option.mask) != 0;
221         }
222 
223         override
224         public Context getContext() {
225             return context;
226         }
227 
228         public Context createContext(SQLObject object) {
229             return this.context = new Context(object, context);
230         }
231 
232         override
233         public void popContext() {
234             if (context !is null) {
235                 context = context.parent;
236             }
237         }
238 
239         public SchemaRepository getRepository() {
240             return repository;
241         }
242     }
243 
244     // static class DB2ResolveVisitor : DB2ASTVisitorAdapter , SchemaResolveVisitor {
245     //     private SchemaRepository repository;
246     //     private int options;
247     //     private Context context;
248 
249     //     public DB2ResolveVisitor(SchemaRepository repository, int options) {
250     //         this.repository = repository;
251     //         this.options = options;
252     //     }
253 
254     //     override public bool visit(SQLForeignKeyImpl x) {
255     //         resolve(this, x);
256     //         return false;
257     //     }
258 
259     //     override public bool visit(SQLSelectStatement x) {
260     //         resolve(this, x.getSelect());
261     //         return false;
262     //     }
263 
264     //     override public bool visit(SQLExprTableSource x) {
265     //         resolve(this, x);
266     //         return false;
267     //     }
268 
269     //     override public bool visit(SQLSelectQueryBlock x) {
270     //         resolve(this, x);
271     //         return false;
272     //     }
273 
274     //     override public bool visit(DB2SelectQueryBlock x) {
275     //         resolve(this, x);
276     //         return false;
277     //     }
278 
279     //     override public bool visit(SQLSelectItem x) {
280     //         SQLExpr expr = x.getExpr();
281     //         if (cast(SQLIdentifierExpr)(expr) !is null) {
282     //             resolve(this, (SQLIdentifierExpr) expr);
283     //             return false;
284     //         }
285 
286     //         if (cast(SQLPropertyExpr)(expr) !is null) {
287     //             resolve(this, (SQLPropertyExpr) expr);
288     //             return false;
289     //         }
290 
291     //         return true;
292     //     }
293 
294     //     override public bool visit(SQLIdentifierExpr x) {
295     //         long hash64 = x.hashCode64();
296     //         if (hash64 == DB2Object.Constants.CURRENT_DATE || hash64 == DB2Object.Constants.CURRENT_TIME) {
297     //             return false;
298     //         }
299 
300     //         resolve(this, x);
301     //         return true;
302     //     }
303 
304     //     override public bool visit(SQLPropertyExpr x) {
305     //         resolve(this, x);
306     //         return false;
307     //     }
308 
309     //     override public bool visit(SQLAllColumnExpr x) {
310     //         resolve(this, x);
311     //         return false;
312     //     }
313 
314     //     override public bool visit(SQLCreateTableStatement x) {
315     //         resolve(this, x);
316     //         return false;
317     //     }
318 
319     //     override public bool visit(SQLUpdateStatement x) {
320     //         resolve(this, x);
321     //         return false;
322     //     }
323 
324     //     override public bool visit(SQLDeleteStatement x) {
325     //         resolve(this, x);
326     //         return false;
327     //     }
328 
329     //     override public bool visit(SQLSelect x) {
330     //         resolve(this, x);
331     //         return false;
332     //     }
333 
334     //     override public bool visit(SQLWithSubqueryClause x) {
335     //         resolve(this, x);
336     //         return false;
337     //     }
338 
339     //     override public bool visit(SQLAlterTableStatement x) {
340     //         resolve(this, x);
341     //         return false;
342     //     }
343 
344     //     override public bool visit(SQLInsertStatement x) {
345     //         resolve(this, x);
346     //         return false;
347     //     }
348 
349     //     override public bool visit(SQLMergeStatement x) {
350     //         resolve(this, x);
351     //         return false;
352     //     }
353 
354     //     override public bool visit(SQLCreateProcedureStatement x) {
355     //         resolve(this, x);
356     //         return false;
357     //     }
358 
359     //     override public bool visit(SQLBlockStatement x) {
360     //         resolve(this, x);
361     //         return false;
362     //     }
363 
364     //     override public bool visit(SQLParameter x) {
365     //         resolve(this, x);
366     //         return false;
367     //     }
368 
369     //     override public bool visit(SQLDeclareItem x) {
370     //         resolve(this, x);
371     //         return false;
372     //     }
373 
374     //     override public bool visit(SQLOver x) {
375     //         resolve(this, x);
376     //         return false;
377     //     }
378 
379     //     override
380     //     public bool isEnabled(Option option) {
381     //         return (options & option.mask) != 0;
382     //     }
383 
384     //     override
385     //     public Context getContext() {
386     //         return context;
387     //     }
388 
389     //     public Context createContext(SQLObject object) {
390     //         return this.context = new Context(object, context);
391     //     }
392 
393     //     override
394     //     public void popContext() {
395     //         if (context !is null) {
396     //             context = context.parent;
397     //         }
398     //     }
399 
400     //     override
401     //     public SchemaRepository getRepository() {
402     //         return repository;
403     //     }
404     // }
405 
406     // static class OracleResolveVisitor : OracleASTVisitorAdapter , SchemaResolveVisitor {
407     //     private SchemaRepository repository;
408     //     private int options;
409     //     private Context context;
410 
411     //     public OracleResolveVisitor(SchemaRepository repository, int options) {
412     //         this.repository = repository;
413     //         this.options = options;
414     //     }
415 
416     //     override public bool visit(SQLSelectStatement x) {
417     //         resolve(this, x.getSelect());
418     //         return false;
419     //     }
420 
421     //     override public bool visit(OracleCreatePackageStatement x) {
422     //         Context ctx = createContext(x);
423 
424     //         foreach(SQLStatement stmt ; x.getStatements()) {
425     //             stmt.accept(this);
426     //         }
427 
428     //         popContext();
429     //         return false;
430     //     }
431 
432     //     override public bool visit(OracleForStatement x) {
433     //         Context ctx = createContext(x);
434 
435     //         SQLName index = x.getIndex();
436     //         SQLExpr range = x.getRange();
437 
438     //         if (index !is null) {
439     //             SQLDeclareItem declareItem = new SQLDeclareItem(index, null);
440     //             declareItem.setParent(x);
441 
442     //             if (cast(SQLIdentifierExpr)(index) !is null) {
443     //                 (cast(SQLIdentifierExpr) index).setResolvedDeclareItem(declareItem);
444     //             }
445     //             declareItem.setResolvedObject(range);
446     //             ctx.declare(declareItem);
447     //             if (cast(SQLQueryExpr)(range) !is null) {
448     //                 SQLSelect select = (cast(SQLQueryExpr) range).getSubQuery();
449     //                 SQLSubqueryTableSource tableSource = new SQLSubqueryTableSource(select);
450     //                 declareItem.setResolvedObject(tableSource);
451     //             }
452 
453     //             index.accept(this);
454     //         }
455 
456 
457     //         if (range !is null) {
458     //             range.accept(this);
459     //         }
460 
461     //         foreach(SQLStatement stmt ; x.getStatements()) {
462     //             stmt.accept(this);
463     //         }
464 
465     //         popContext();
466     //         return false;
467     //     }
468 
469     //     override public bool visit(OracleForeignKey x) {
470     //         resolve(this, x);
471     //         return false;
472     //     }
473 
474     //     override public bool visit(SQLIfStatement x) {
475     //         resolve(this, x);
476     //         return false;
477     //     }
478 
479     //     override public bool visit(SQLCreateFunctionStatement x) {
480     //         resolve(this, x);
481     //         return false;
482     //     }
483 
484     //     override public bool visit(OracleSelectTableReference x) {
485     //         resolve(this, x);
486     //         return false;
487     //     }
488 
489     //     override public bool visit(SQLExprTableSource x) {
490     //         resolve(this, x);
491     //         return false;
492     //     }
493 
494     //     override public bool visit(SQLSelectQueryBlock x) {
495     //         resolve(this, x);
496     //         return false;
497     //     }
498 
499     //     override public bool visit(OracleSelectQueryBlock x) {
500     //         resolve(this, x);
501     //         return false;
502     //     }
503 
504     //     override public bool visit(SQLSelectItem x) {
505     //         SQLExpr expr = x.getExpr();
506     //         if (cast(SQLIdentifierExpr)(expr) !is null) {
507     //             resolve(this, (SQLIdentifierExpr) expr);
508     //             return false;
509     //         }
510 
511     //         if (cast(SQLPropertyExpr)(expr) !is null) {
512     //             resolve(this, (SQLPropertyExpr) expr);
513     //             return false;
514     //         }
515 
516     //         return true;
517     //     }
518 
519     //     override public bool visit(SQLIdentifierExpr x) {
520     //         if (x.nameHashCode64() == FnvHash.Constants.ROWNUM) {
521     //             return false;
522     //         }
523 
524     //         resolve(this, x);
525     //         return true;
526     //     }
527 
528     //     override public bool visit(SQLPropertyExpr x) {
529     //         resolve(this, x);
530     //         return false;
531     //     }
532 
533     //     override public bool visit(SQLAllColumnExpr x) {
534     //         resolve(this, x);
535     //         return false;
536     //     }
537 
538     //     override public bool visit(SQLCreateTableStatement x) {
539     //         resolve(this, x);
540     //         return false;
541     //     }
542 
543     //     override public bool visit(OracleCreateTableStatement x) {
544     //         resolve(this, x);
545     //         return false;
546     //     }
547 
548     //     override public bool visit(SQLUpdateStatement x) {
549     //         resolve(this, x);
550     //         return false;
551     //     }
552 
553     //     override public bool visit(OracleUpdateStatement x) {
554     //         resolve(this, x);
555     //         return false;
556     //     }
557 
558     //     override public bool visit(SQLDeleteStatement x) {
559     //         resolve(this, x);
560     //         return false;
561     //     }
562 
563     //     override public bool visit(OracleDeleteStatement x) {
564     //         resolve(this, x);
565     //         return false;
566     //     }
567 
568     //     override public bool visit(SQLSelect x) {
569     //         resolve(this, x);
570     //         return false;
571     //     }
572 
573     //     override public bool visit(SQLWithSubqueryClause x) {
574     //         resolve(this, x);
575     //         return false;
576     //     }
577 
578     //     override public bool visit(SQLInsertStatement x) {
579     //         resolve(this, x);
580     //         return false;
581     //     }
582 
583     //     override public bool visit(OracleMultiInsertStatement x) {
584     //         Context ctx = createContext(x);
585 
586     //         SQLSelect select = x.getSubQuery();
587     //         visit(select);
588 
589     //         OracleSelectSubqueryTableSource tableSource = new OracleSelectSubqueryTableSource(select);
590     //         tableSource.setParent(x);
591     //         ctx.setTableSource(tableSource);
592 
593     //         foreach(OracleMultiInsertStatement.Entry entry ; x.getEntries()) {
594     //             entry.accept(this);
595     //         }
596 
597     //         popContext();
598     //         return false;
599     //     }
600 
601     //     override public bool visit(OracleMultiInsertStatement.InsertIntoClause x) {
602     //         foreach(SQLExpr column ; x.getColumns()) {
603     //             if (cast(SQLIdentifierExpr)(column) !is null) {
604     //                 SQLIdentifierExpr identColumn = cast(SQLIdentifierExpr) column;
605     //                 identColumn.setResolvedTableSource(x.getTableSource());
606     //             }
607     //         }
608     //         return true;
609     //     }
610 
611     //     override public bool visit(OracleInsertStatement x) {
612     //         resolve(this, x);
613     //         return false;
614     //     }
615 
616     //     override public bool visit(SQLAlterTableStatement x) {
617     //         resolve(this, x);
618     //         return false;
619     //     }
620 
621     //     override public bool visit(SQLMergeStatement x) {
622     //         resolve(this, x);
623     //         return false;
624     //     }
625 
626     //     override public bool visit(SQLCreateProcedureStatement x) {
627     //         resolve(this, x);
628     //         return false;
629     //     }
630 
631     //     override public bool visit(SQLBlockStatement x) {
632     //         resolve(this, x);
633     //         return false;
634     //     }
635 
636     //     override public bool visit(SQLParameter x) {
637     //         resolve(this, x);
638     //         return false;
639     //     }
640 
641     //     override public bool visit(SQLDeclareItem x) {
642     //         resolve(this, x);
643     //         return false;
644     //     }
645 
646     //     override public bool visit(SQLOver x) {
647     //         resolve(this, x);
648     //         return false;
649     //     }
650 
651     //     override public bool visit(SQLFetchStatement x) {
652     //         resolve(this, x);
653     //         return false;
654     //     }
655 
656     //     override
657     //     public bool isEnabled(Option option) {
658     //         return (options & option.mask) != 0;
659     //     }
660 
661     //     override
662     //     public Context getContext() {
663     //         return context;
664     //     }
665 
666     //     public Context createContext(SQLObject object) {
667     //         return this.context = new Context(object, context);
668     //     }
669 
670     //     override
671     //     public void popContext() {
672     //         if (context !is null) {
673     //             context = context.parent;
674     //         }
675     //     }
676 
677     //     public SchemaRepository getRepository() {
678     //         return repository;
679     //     }
680     // }
681 
682     // static class OdpsResolveVisitor : OdpsASTVisitorAdapter , SchemaResolveVisitor {
683     //     private int options;
684     //     private SchemaRepository repository;
685     //     private Context context;
686 
687     //     public OdpsResolveVisitor(SchemaRepository repository, int options) {
688     //         this.repository = repository;
689     //         this.options = options;
690     //     }
691 
692     //     override public bool visit(SQLForeignKeyImpl x) {
693     //         resolve(this, x);
694     //         return false;
695     //     }
696 
697     //     override public bool visit(SQLSelectStatement x) {
698     //         resolve(this, x.getSelect());
699     //         return false;
700     //     }
701 
702     //     override public bool visit(SQLExprTableSource x) {
703     //         resolve(this, x);
704     //         return false;
705     //     }
706 
707     //     override public bool visit(SQLSelectQueryBlock x) {
708     //         resolve(this, x);
709     //         return false;
710     //     }
711 
712     //     override public bool visit(OdpsSelectQueryBlock x) {
713     //         resolve(this, x);
714     //         return false;
715     //     }
716 
717     //     override public bool visit(SQLSelectItem x) {
718     //         SQLExpr expr = x.getExpr();
719     //         if (cast(SQLIdentifierExpr)(expr) !is null) {
720     //             resolve(this, (SQLIdentifierExpr) expr);
721     //             return false;
722     //         }
723 
724     //         if (cast(SQLPropertyExpr)(expr) !is null) {
725     //             resolve(this, (SQLPropertyExpr) expr);
726     //             return false;
727     //         }
728 
729     //         return true;
730     //     }
731 
732     //     override public bool visit(SQLIdentifierExpr x) {
733     //         resolve(this, x);
734     //         return true;
735     //     }
736 
737     //     override public bool visit(SQLPropertyExpr x) {
738     //         resolve(this, x);
739     //         return false;
740     //     }
741 
742     //     override public bool visit(SQLAllColumnExpr x) {
743     //         resolve(this, x);
744     //         return false;
745     //     }
746 
747     //     override public bool visit(SQLCreateTableStatement x) {
748     //         resolve(this, x);
749     //         return false;
750     //     }
751 
752     //     override public bool visit(OdpsCreateTableStatement x) {
753     //         resolve(this, x);
754     //         return false;
755     //     }
756 
757     //     override public bool visit(SQLUpdateStatement x) {
758     //         resolve(this, x);
759     //         return false;
760     //     }
761 
762     //     override public bool visit(SQLDeleteStatement x) {
763     //         resolve(this, x);
764     //         return false;
765     //     }
766 
767     //     override public bool visit(SQLSelect x) {
768     //         resolve(this, x);
769     //         return false;
770     //     }
771 
772     //     override public bool visit(SQLWithSubqueryClause x) {
773     //         resolve(this, x);
774     //         return false;
775     //     }
776 
777     //     override public bool visit(HiveInsert x) {
778     //         Context ctx = createContext(x);
779 
780     //         SQLExprTableSource tableSource = x.getTableSource();
781     //         if (tableSource !is null) {
782     //             ctx.setTableSource(x.getTableSource());
783     //             visit(tableSource);
784     //         }
785 
786     //         foreach(SQLAssignItem item ; x.getPartitions()) {
787     //             item.accept(this);
788     //         }
789 
790     //         SQLSelect select = x.getQuery();
791     //         if (select !is null) {
792     //             visit(select);
793     //         }
794 
795     //         popContext();
796     //         return false;
797     //     }
798 
799     //     override public bool visit(SQLInsertStatement x) {
800     //         resolve(this, x);
801     //         return false;
802     //     }
803 
804     //     override public bool visit(SQLAlterTableStatement x) {
805     //         resolve(this, x);
806     //         return false;
807     //     }
808 
809     //     override public bool visit(SQLMergeStatement x) {
810     //         resolve(this, x);
811     //         return false;
812     //     }
813 
814     //     override public bool visit(SQLCreateProcedureStatement x) {
815     //         resolve(this, x);
816     //         return false;
817     //     }
818 
819     //     override public bool visit(SQLBlockStatement x) {
820     //         resolve(this, x);
821     //         return false;
822     //     }
823 
824     //     override public bool visit(SQLParameter x) {
825     //         resolve(this, x);
826     //         return false;
827     //     }
828 
829     //     override public bool visit(SQLDeclareItem x) {
830     //         resolve(this, x);
831     //         return false;
832     //     }
833 
834     //     override public bool visit(SQLOver x) {
835     //         resolve(this, x);
836     //         return false;
837     //     }
838 
839     //     override
840     //     public bool isEnabled(Option option) {
841     //         return (options & option.mask) != 0;
842     //     }
843 
844     //     override
845     //     public Context getContext() {
846     //         return context;
847     //     }
848 
849     //     public Context createContext(SQLObject object) {
850     //         return this.context = new Context(object, context);
851     //     }
852 
853     //     override
854     //     public void popContext() {
855     //         if (context !is null) {
856     //             context = context.parent;
857     //         }
858     //     }
859 
860     //     public SchemaRepository getRepository() {
861     //         return repository;
862     //     }
863     // }
864 
865     // static class HiveResolveVisitor : HiveASTVisitorAdapter , SchemaResolveVisitor {
866     //     private int options;
867     //     private SchemaRepository repository;
868     //     private Context context;
869 
870     //     public HiveResolveVisitor(SchemaRepository repository, int options) {
871     //         this.repository = repository;
872     //         this.options = options;
873     //     }
874 
875     //     override public bool visit(SQLForeignKeyImpl x) {
876     //         resolve(this, x);
877     //         return false;
878     //     }
879 
880     //     override public bool visit(SQLSelectStatement x) {
881     //         resolve(this, x.getSelect());
882     //         return false;
883     //     }
884 
885     //     override public bool visit(SQLExprTableSource x) {
886     //         resolve(this, x);
887     //         return false;
888     //     }
889 
890     //     override public bool visit(SQLSelectQueryBlock x) {
891     //         resolve(this, x);
892     //         return false;
893     //     }
894 
895     //     override public bool visit(OdpsSelectQueryBlock x) {
896     //         resolve(this, x);
897     //         return false;
898     //     }
899 
900     //     override public bool visit(SQLSelectItem x) {
901     //         SQLExpr expr = x.getExpr();
902     //         if (cast(SQLIdentifierExpr)(expr) !is null) {
903     //             resolve(this, (SQLIdentifierExpr) expr);
904     //             return false;
905     //         }
906 
907     //         if (cast(SQLPropertyExpr)(expr) !is null) {
908     //             resolve(this, (SQLPropertyExpr) expr);
909     //             return false;
910     //         }
911 
912     //         return true;
913     //     }
914 
915     //     override public bool visit(SQLIdentifierExpr x) {
916     //         resolve(this, x);
917     //         return true;
918     //     }
919 
920     //     override public bool visit(SQLPropertyExpr x) {
921     //         resolve(this, x);
922     //         return false;
923     //     }
924 
925     //     override public bool visit(SQLAllColumnExpr x) {
926     //         resolve(this, x);
927     //         return false;
928     //     }
929 
930     //     override public bool visit(SQLCreateTableStatement x) {
931     //         resolve(this, x);
932     //         return false;
933     //     }
934 
935     //     override public bool visit(OdpsCreateTableStatement x) {
936     //         resolve(this, x);
937     //         return false;
938     //     }
939 
940     //     override public bool visit(SQLUpdateStatement x) {
941     //         resolve(this, x);
942     //         return false;
943     //     }
944 
945     //     override public bool visit(SQLDeleteStatement x) {
946     //         resolve(this, x);
947     //         return false;
948     //     }
949 
950     //     override public bool visit(SQLSelect x) {
951     //         resolve(this, x);
952     //         return false;
953     //     }
954 
955     //     override public bool visit(SQLWithSubqueryClause x) {
956     //         resolve(this, x);
957     //         return false;
958     //     }
959 
960     //     override public bool visit(HiveInsert x) {
961     //         Context ctx = createContext(x);
962 
963     //         SQLExprTableSource tableSource = x.getTableSource();
964     //         if (tableSource !is null) {
965     //             ctx.setTableSource(x.getTableSource());
966     //             visit(tableSource);
967     //         }
968 
969     //         foreach(SQLAssignItem item ; x.getPartitions()) {
970     //             item.accept(this);
971     //         }
972 
973     //         SQLSelect select = x.getQuery();
974     //         if (select !is null) {
975     //             visit(select);
976     //         }
977 
978     //         popContext();
979     //         return false;
980     //     }
981 
982     //     override public bool visit(SQLInsertStatement x) {
983     //         resolve(this, x);
984     //         return false;
985     //     }
986 
987     //     override public bool visit(SQLAlterTableStatement x) {
988     //         resolve(this, x);
989     //         return false;
990     //     }
991 
992     //     override public bool visit(SQLMergeStatement x) {
993     //         resolve(this, x);
994     //         return false;
995     //     }
996 
997     //     override public bool visit(SQLCreateProcedureStatement x) {
998     //         resolve(this, x);
999     //         return false;
1000     //     }
1001 
1002     //     override public bool visit(SQLBlockStatement x) {
1003     //         resolve(this, x);
1004     //         return false;
1005     //     }
1006 
1007     //     override public bool visit(SQLParameter x) {
1008     //         resolve(this, x);
1009     //         return false;
1010     //     }
1011 
1012     //     override public bool visit(SQLDeclareItem x) {
1013     //         resolve(this, x);
1014     //         return false;
1015     //     }
1016 
1017     //     override public bool visit(SQLOver x) {
1018     //         resolve(this, x);
1019     //         return false;
1020     //     }
1021 
1022     //     override
1023     //     public bool isEnabled(Option option) {
1024     //         return (options & option.mask) != 0;
1025     //     }
1026 
1027     //     override
1028     //     public Context getContext() {
1029     //         return context;
1030     //     }
1031 
1032     //     public Context createContext(SQLObject object) {
1033     //         return this.context = new Context(object, context);
1034     //     }
1035 
1036     //     override
1037     //     public void popContext() {
1038     //         if (context !is null) {
1039     //             context = context.parent;
1040     //         }
1041     //     }
1042 
1043     //     public SchemaRepository getRepository() {
1044     //         return repository;
1045     //     }
1046     // }
1047 
1048     static class PGResolveVisitor : PGASTVisitorAdapter , SchemaResolveVisitor {
1049 
1050         alias endVisit = PGASTVisitorAdapter.endVisit;
1051         alias visit = PGASTVisitorAdapter.visit; 
1052 
1053         private int options;
1054         private SchemaRepository repository;
1055         private Context context;
1056 
1057         public this(SchemaRepository repository, int options) {
1058             this.repository = repository;
1059             this.options = options;
1060         }
1061 
1062         override public bool visit(SQLForeignKeyImpl x) {
1063             resolve(this, x);
1064             return false;
1065         }
1066 
1067         override public bool visit(SQLSelectStatement x) {
1068             resolve(this, x.getSelect());
1069             return false;
1070         }
1071 
1072         override public bool visit(SQLExprTableSource x) {
1073             resolve(this, x);
1074             return false;
1075         }
1076 
1077         override public bool visit(SQLSelectQueryBlock x) {
1078             resolve(this, x);
1079             return false;
1080         }
1081 
1082         override public bool visit(PGSelectQueryBlock x) {
1083             resolve(this, x);
1084             return false;
1085         }
1086 
1087         override public bool visit(PGFunctionTableSource x) {
1088             foreach(SQLParameter parameter ; x.getParameters()) {
1089                 SQLName name = parameter.getName();
1090                 if (cast(SQLIdentifierExpr)(name) !is null) {
1091                     SQLIdentifierExpr identName = cast(SQLIdentifierExpr) name;
1092                     identName.setResolvedTableSource(x);
1093                 }
1094             }
1095 
1096             return false;
1097         }
1098 
1099         override public bool visit(SQLSelectItem x) {
1100             SQLExpr expr = x.getExpr();
1101             if (cast(SQLIdentifierExpr)(expr) !is null) {
1102                 resolve(this, cast(SQLIdentifierExpr) expr);
1103                 return false;
1104             }
1105 
1106             if (cast(SQLPropertyExpr)(expr) !is null) {
1107                 resolve(this, cast(SQLPropertyExpr) expr);
1108                 return false;
1109             }
1110 
1111             return true;
1112         }
1113 
1114         override public bool visit(SQLIdentifierExpr x) {
1115             if (PGUtils.isPseudoColumn(x.nameHashCode64())) {
1116                 return false;
1117             }
1118 
1119             resolve(this, x);
1120             return true;
1121         }
1122 
1123         override public bool visit(SQLPropertyExpr x) {
1124             resolve(this, x);
1125             return false;
1126         }
1127 
1128         override public bool visit(SQLAllColumnExpr x) {
1129             resolve(this, x);
1130             return false;
1131         }
1132 
1133         override public bool visit(SQLCreateTableStatement x) {
1134             resolve(this, x);
1135             return false;
1136         }
1137 
1138         override public bool visit(SQLUpdateStatement x) {
1139             resolve(this, x);
1140             return false;
1141         }
1142 
1143         override public bool visit(PGUpdateStatement x) {
1144             resolve(this, x);
1145             return false;
1146         }
1147 
1148         override public bool visit(SQLDeleteStatement x) {
1149             resolve(this, x);
1150             return false;
1151         }
1152 
1153         override public bool visit(PGDeleteStatement x) {
1154             resolve(this, x);
1155             return false;
1156         }
1157 
1158         override public bool visit(PGSelectStatement x) {
1159             createContext(x);
1160             visit(x.getSelect());
1161             popContext();
1162             return false;
1163         }
1164 
1165         override public bool visit(SQLSelect x) {
1166             resolve(this, x);
1167             return false;
1168         }
1169 
1170         override public bool visit(SQLWithSubqueryClause x) {
1171             resolve(this, x);
1172             return false;
1173         }
1174 
1175         override public bool visit(PGInsertStatement x) {
1176             resolve(this, x);
1177             return false;
1178         }
1179 
1180         override public bool visit(SQLInsertStatement x) {
1181             resolve(this, x);
1182             return false;
1183         }
1184 
1185         override public bool visit(SQLAlterTableStatement x) {
1186             resolve(this, x);
1187             return false;
1188         }
1189 
1190         override public bool visit(SQLMergeStatement x) {
1191             resolve(this, x);
1192             return false;
1193         }
1194 
1195         override public bool visit(SQLCreateProcedureStatement x) {
1196             resolve(this, x);
1197             return false;
1198         }
1199 
1200         override public bool visit(SQLBlockStatement x) {
1201             resolve(this, x);
1202             return false;
1203         }
1204 
1205         override public bool visit(SQLParameter x) {
1206             resolve(this, x);
1207             return false;
1208         }
1209 
1210         override public bool visit(SQLDeclareItem x) {
1211             resolve(this, x);
1212             return false;
1213         }
1214 
1215         override public bool visit(SQLOver x) {
1216             resolve(this, x);
1217             return false;
1218         }
1219 
1220         override
1221         public bool isEnabled(Option option) {
1222             return (options & option.mask) != 0;
1223         }
1224 
1225         override
1226         public Context getContext() {
1227             return context;
1228         }
1229 
1230         public Context createContext(SQLObject object) {
1231             return this.context = new Context(object, context);
1232         }
1233 
1234         override
1235         public void popContext() {
1236             if (context !is null) {
1237                 context = context.parent;
1238             }
1239         }
1240 
1241         public SchemaRepository getRepository() {
1242             return repository;
1243         }
1244     }
1245 
1246     // static class SQLServerResolveVisitor : SQLServerASTVisitorAdapter , SchemaResolveVisitor {
1247     //     private int options;
1248     //     private SchemaRepository repository;
1249     //     private Context context;
1250 
1251     //     public SQLServerResolveVisitor(SchemaRepository repository, int options) {
1252     //         this.repository = repository;
1253     //         this.options = options;
1254     //     }
1255 
1256     //     override public bool visit(SQLForeignKeyImpl x) {
1257     //         resolve(this, x);
1258     //         return false;
1259     //     }
1260 
1261     //     override public bool visit(SQLSelectStatement x) {
1262     //         resolve(this, x.getSelect());
1263     //         return false;
1264     //     }
1265 
1266     //     override public bool visit(SQLExprTableSource x) {
1267     //         resolve(this, x);
1268     //         return false;
1269     //     }
1270 
1271     //     override public bool visit(SQLSelectQueryBlock x) {
1272     //         resolve(this, x);
1273     //         return false;
1274     //     }
1275 
1276     //     override public bool visit(SQLServerSelectQueryBlock x) {
1277     //         resolve(this, x);
1278     //         return false;
1279     //     }
1280 
1281     //     override public bool visit(SQLSelectItem x) {
1282     //         SQLExpr expr = x.getExpr();
1283     //         if (cast(SQLIdentifierExpr)(expr) !is null) {
1284     //             resolve(this, (SQLIdentifierExpr) expr);
1285     //             return false;
1286     //         }
1287 
1288     //         if (cast(SQLPropertyExpr)(expr) !is null) {
1289     //             resolve(this, (SQLPropertyExpr) expr);
1290     //             return false;
1291     //         }
1292 
1293     //         return true;
1294     //     }
1295 
1296     //     override public bool visit(SQLIdentifierExpr x) {
1297     //         resolve(this, x);
1298     //         return true;
1299     //     }
1300 
1301     //     override public bool visit(SQLPropertyExpr x) {
1302     //         resolve(this, x);
1303     //         return false;
1304     //     }
1305 
1306     //     override public bool visit(SQLAllColumnExpr x) {
1307     //         resolve(this, x);
1308     //         return false;
1309     //     }
1310 
1311     //     override public bool visit(SQLCreateTableStatement x) {
1312     //         resolve(this, x);
1313     //         return false;
1314     //     }
1315 
1316     //     override public bool visit(SQLUpdateStatement x) {
1317     //         resolve(this, x);
1318     //         return false;
1319     //     }
1320 
1321     //     override public bool visit(SQLServerUpdateStatement x) {
1322     //         resolve(this, x);
1323     //         return false;
1324     //     }
1325 
1326     //     override public bool visit(SQLDeleteStatement x) {
1327     //         resolve(this, x);
1328     //         return false;
1329     //     }
1330 
1331     //     override public bool visit(SQLSelect x) {
1332     //         resolve(this, x);
1333     //         return false;
1334     //     }
1335 
1336     //     override public bool visit(SQLWithSubqueryClause x) {
1337     //         resolve(this, x);
1338     //         return false;
1339     //     }
1340 
1341     //     override public bool visit(SQLServerInsertStatement x) {
1342     //         resolve(this, x);
1343     //         return false;
1344     //     }
1345 
1346     //     override public bool visit(SQLInsertStatement x) {
1347     //         resolve(this, x);
1348     //         return false;
1349     //     }
1350 
1351     //     override public bool visit(SQLAlterTableStatement x) {
1352     //         resolve(this, x);
1353     //         return false;
1354     //     }
1355 
1356     //     override public bool visit(SQLMergeStatement x) {
1357     //         resolve(this, x);
1358     //         return false;
1359     //     }
1360 
1361     //     override public bool visit(SQLCreateProcedureStatement x) {
1362     //         resolve(this, x);
1363     //         return false;
1364     //     }
1365 
1366     //     override public bool visit(SQLBlockStatement x) {
1367     //         resolve(this, x);
1368     //         return false;
1369     //     }
1370 
1371     //     override public bool visit(SQLParameter x) {
1372     //         resolve(this, x);
1373     //         return false;
1374     //     }
1375 
1376     //     override public bool visit(SQLDeclareItem x) {
1377     //         resolve(this, x);
1378     //         return false;
1379     //     }
1380 
1381     //     override public bool visit(SQLOver x) {
1382     //         resolve(this, x);
1383     //         return false;
1384     //     }
1385 
1386     //     override
1387     //     public bool isEnabled(Option option) {
1388     //         return (options & option.mask) != 0;
1389     //     }
1390 
1391     //     override
1392     //     public Context getContext() {
1393     //         return context;
1394     //     }
1395 
1396     //     public Context createContext(SQLObject object) {
1397     //         return this.context = new Context(object, context);
1398     //     }
1399 
1400     //     override
1401     //     public void popContext() {
1402     //         if (context !is null) {
1403     //             context = context.parent;
1404     //         }
1405     //     }
1406 
1407     //     public SchemaRepository getRepository() {
1408     //         return repository;
1409     //     }
1410     // }
1411 
1412     static class SQLResolveVisitor : SQLASTVisitorAdapter , SchemaResolveVisitor {
1413         alias endVisit = SQLASTVisitorAdapter.endVisit;
1414         alias visit = SQLASTVisitorAdapter.visit; 
1415         private int options;
1416         private SchemaRepository repository;
1417         private Context context;
1418 
1419         public this(SchemaRepository repository, int options) {
1420             this.repository = repository;
1421             this.options = options;
1422         }
1423 
1424         override public bool visit(SQLForeignKeyImpl x) {
1425             resolve(this, x);
1426             return false;
1427         }
1428 
1429         override public bool visit(SQLSelectStatement x) {
1430             resolve(this, x.getSelect());
1431             return false;
1432         }
1433 
1434         override public bool visit(SQLExprTableSource x) {
1435             resolve(this, x);
1436             return false;
1437         }
1438 
1439         override public bool visit(SQLSelectQueryBlock x) {
1440             resolve(this, x);
1441             return false;
1442         }
1443 
1444         override public bool visit(SQLSelectItem x) {
1445             SQLExpr expr = x.getExpr();
1446             if (cast(SQLIdentifierExpr)(expr) !is null) {
1447                 resolve(this, cast(SQLIdentifierExpr) expr);
1448                 return false;
1449             }
1450 
1451             if (cast(SQLPropertyExpr)(expr) !is null) {
1452                 resolve(this, cast(SQLPropertyExpr) expr);
1453                 return false;
1454             }
1455 
1456             return true;
1457         }
1458 
1459         override public bool visit(SQLIdentifierExpr x) {
1460             resolve(this, x);
1461             return true;
1462         }
1463 
1464         override public bool visit(SQLPropertyExpr x) {
1465             resolve(this, x);
1466             return false;
1467         }
1468 
1469         override public bool visit(SQLAllColumnExpr x) {
1470             resolve(this, x);
1471             return false;
1472         }
1473 
1474         override public bool visit(SQLCreateTableStatement x) {
1475             resolve(this, x);
1476             return false;
1477         }
1478 
1479         override public bool visit(SQLUpdateStatement x) {
1480             resolve(this, x);
1481             return false;
1482         }
1483 
1484         override public bool visit(SQLDeleteStatement x) {
1485             resolve(this, x);
1486             return false;
1487         }
1488 
1489         override public bool visit(SQLSelect x) {
1490             resolve(this, x);
1491             return false;
1492         }
1493 
1494         override public bool visit(SQLWithSubqueryClause x) {
1495             resolve(this, x);
1496             return false;
1497         }
1498 
1499         override public bool visit(SQLInsertStatement x) {
1500             resolve(this, x);
1501             return false;
1502         }
1503 
1504         override public bool visit(SQLAlterTableStatement x) {
1505             resolve(this, x);
1506             return false;
1507         }
1508 
1509         override public bool visit(SQLMergeStatement x) {
1510             resolve(this, x);
1511             return false;
1512         }
1513 
1514         override public bool visit(SQLCreateProcedureStatement x) {
1515             resolve(this, x);
1516             return false;
1517         }
1518 
1519         override public bool visit(SQLBlockStatement x) {
1520             resolve(this, x);
1521             return false;
1522         }
1523 
1524         override public bool visit(SQLParameter x) {
1525             resolve(this, x);
1526             return false;
1527         }
1528 
1529         override public bool visit(SQLDeclareItem x) {
1530             resolve(this, x);
1531             return false;
1532         }
1533 
1534         override public bool visit(SQLOver x) {
1535             resolve(this, x);
1536             return false;
1537         }
1538 
1539         override public bool visit(SQLReplaceStatement x) {
1540             resolve(this, x);
1541             return false;
1542         }
1543 
1544         override
1545         public bool isEnabled(Option option) {
1546             return (options & option.mask) != 0;
1547         }
1548 
1549         override
1550         public Context getContext() {
1551             return context;
1552         }
1553 
1554         public Context createContext(SQLObject object) {
1555             return this.context = new Context(object, context);
1556         }
1557 
1558         override
1559         public void popContext() {
1560             if (context !is null) {
1561                 context = context.parent;
1562             }
1563         }
1564 
1565         public SchemaRepository getRepository() {
1566             return repository;
1567         }
1568     }
1569 
1570     static void resolve(SchemaResolveVisitor visitor, SQLCreateTableStatement x) {
1571         SchemaResolveVisitor.Context ctx = visitor.createContext(x);
1572 
1573         SQLExprTableSource table = x.getTableSource();
1574         ctx.setTableSource(table);
1575 
1576         table.accept(visitor);
1577 
1578         List!(SQLTableElement) elements = x.getTableElementList();
1579         for (int i = 0; i < elements.size(); i++) {
1580             SQLTableElement e = elements.get(i);
1581             if (cast(SQLColumnDefinition)(e) !is null) {
1582                 SQLColumnDefinition columnn = cast(SQLColumnDefinition) e;
1583                 SQLName columnnName = columnn.getName();
1584                 if (cast(SQLIdentifierExpr)(columnnName) !is null) {
1585                     SQLIdentifierExpr identifierExpr = cast(SQLIdentifierExpr) columnnName;
1586                     identifierExpr.setResolvedTableSource(table);
1587                     identifierExpr.setResolvedColumn(columnn);
1588                 }
1589             } else if (cast(SQLUniqueConstraint)(e) !is null) {
1590                 List!(SQLSelectOrderByItem) columns = (cast(SQLUniqueConstraint) e).getColumns();
1591                 foreach(SQLSelectOrderByItem orderByItem ; columns) {
1592                     SQLExpr orderByItemExpr = orderByItem.getExpr();
1593                     if (cast(SQLIdentifierExpr)(orderByItemExpr) !is null) {
1594                         SQLIdentifierExpr identifierExpr = cast(SQLIdentifierExpr) orderByItemExpr;
1595                         identifierExpr.setResolvedTableSource(table);
1596 
1597                         SQLColumnDefinition column = x.findColumn(identifierExpr.nameHashCode64());
1598                         if (column !is null) {
1599                             identifierExpr.setResolvedColumn(column);
1600                         }
1601                     }
1602                 }
1603             } else {
1604                 e.accept(visitor);
1605             }
1606         }
1607 
1608         SQLSelect select = x.getSelect();
1609         if (select !is null) {
1610             visitor.visit(select);
1611         }
1612 
1613         SchemaRepository repository = visitor.getRepository();
1614         if (repository !is null) {
1615             repository.acceptCreateTable(x);
1616         }
1617 
1618         visitor.popContext();
1619     }
1620 
1621     static void resolve(SchemaResolveVisitor visitor, SQLUpdateStatement x) {
1622         SchemaResolveVisitor.Context ctx = visitor.createContext(x);
1623 
1624         SQLWithSubqueryClause _with = x.getWith();
1625         if (_with !is null) {
1626             _with.accept(visitor);
1627         }
1628 
1629         SQLTableSource table = x.getTableSource();
1630         SQLTableSource from = x.getFrom();
1631 
1632         ctx.setTableSource(table);
1633         ctx.setFrom(from);
1634 
1635         table.accept(visitor);
1636         if (from !is null) {
1637             from.accept(visitor);
1638         }
1639 
1640         List!(SQLUpdateSetItem) items = x.getItems();
1641         foreach(SQLUpdateSetItem item ; items) {
1642             SQLExpr column = item.getColumn();
1643             if (cast(SQLIdentifierExpr)(column) !is null) {
1644                 SQLIdentifierExpr identifierExpr = cast(SQLIdentifierExpr) column;
1645                 identifierExpr.setResolvedTableSource(table);
1646                 visitor.visit(identifierExpr);
1647             } else if (cast(SQLListExpr)(column) !is null) {
1648                 SQLListExpr columnGroup = cast(SQLListExpr) column;
1649                 foreach(SQLExpr columnGroupItem ; columnGroup.getItems()) {
1650                     if (cast(SQLIdentifierExpr)(columnGroupItem) !is null) {
1651                         SQLIdentifierExpr identifierExpr = cast(SQLIdentifierExpr) columnGroupItem;
1652                         identifierExpr.setResolvedTableSource(table);
1653                         visitor.visit(identifierExpr);
1654                     } else {
1655                         columnGroupItem.accept(visitor);
1656                     }
1657                 }
1658             } else {
1659                 column.accept(visitor);
1660             }
1661             SQLExpr value = item.getValue();
1662             if (value !is null) {
1663                 value.accept(visitor);
1664             }
1665         }
1666 
1667         SQLExpr where = x.getWhere();
1668         if (where !is null) {
1669             where.accept(visitor);
1670         }
1671 
1672         SQLOrderBy orderBy = x.getOrderBy();
1673         if (orderBy !is null) {
1674             orderBy.accept(visitor);
1675         }
1676 
1677         foreach(SQLExpr sqlExpr ; x.getReturning()) {
1678             sqlExpr.accept(visitor);
1679         }
1680 
1681         visitor.popContext();
1682     }
1683 
1684     static void resolve(SchemaResolveVisitor visitor, SQLDeleteStatement x) {
1685         SchemaResolveVisitor.Context ctx = visitor.createContext(x);
1686 
1687         SQLWithSubqueryClause _with = x.getWith();
1688         if (_with !is null) {
1689             visitor.visit(_with);
1690         }
1691 
1692         SQLTableSource table = x.getTableSource();
1693         SQLTableSource from = x.getFrom();
1694 
1695         if (from is null) {
1696             from = x.getUsing();
1697         }
1698 
1699         if (table is null && from !is null) {
1700             table = from;
1701             from = null;
1702         }
1703 
1704         if (from !is null) {
1705             ctx.setFrom(from);
1706             from.accept(visitor);
1707         }
1708 
1709         if (table !is null) {
1710             if (from !is null && cast(SQLExprTableSource)(table) !is null) {
1711                 SQLExpr tableExpr = (cast(SQLExprTableSource) table).getExpr();
1712                 if (cast(SQLPropertyExpr)(tableExpr) !is null
1713                         && (cast(SQLPropertyExpr) tableExpr).getName() == ("*")) {
1714                     string _alias = (cast(SQLPropertyExpr) tableExpr).getOwnernName();
1715                     SQLTableSource refTableSource = from.findTableSource(_alias);
1716                     if (refTableSource !is null) {
1717                         (cast(SQLPropertyExpr) tableExpr).setResolvedTableSource(refTableSource);
1718                     }
1719                 }
1720             }
1721             table.accept(visitor);
1722             ctx.setTableSource(table);
1723         }
1724 
1725         SQLExpr where = x.getWhere();
1726         if (where !is null) {
1727             where.accept(visitor);
1728         }
1729 
1730         visitor.popContext();
1731     }
1732 
1733     static void resolve(SchemaResolveVisitor visitor, SQLInsertStatement x) {
1734         SchemaResolveVisitor.Context ctx = visitor.createContext(x);
1735 
1736         SQLWithSubqueryClause _with = x.getWith();
1737         if (_with !is null) {
1738             visitor.visit(_with);
1739         }
1740 
1741         SQLTableSource table = x.getTableSource();
1742 
1743         ctx.setTableSource(table);
1744 
1745         if (table !is null) {
1746             table.accept(visitor);
1747         }
1748 
1749         foreach(SQLExpr column ; x.getColumns()) {
1750             column.accept(visitor);
1751         }
1752 
1753         foreach(ValuesClause valuesClause ; x.getValuesList()) {
1754             valuesClause.accept(visitor);
1755         }
1756 
1757         SQLSelect query = x.getQuery();
1758         if (query !is null) {
1759             visitor.visit(query);
1760         }
1761 
1762         visitor.popContext();
1763     }
1764 
1765     static void resolve(SchemaResolveVisitor visitor, SQLIdentifierExpr x) {
1766         SchemaResolveVisitor.Context ctx = visitor.getContext();
1767         if (ctx is null) {
1768             return;
1769         }
1770 
1771         string ident = x.getName();
1772         long hash = x.nameHashCode64();
1773         SQLTableSource tableSource = null;
1774 
1775         if ((hash == FnvHash.Constants.LEVEL || hash == FnvHash.Constants.CONNECT_BY_ISCYCLE)
1776                 && cast(SQLSelectQueryBlock)(ctx.object) !is null) {
1777             SQLSelectQueryBlock queryBlock = cast(SQLSelectQueryBlock) ctx.object;
1778             if (queryBlock.getStartWith() !is null
1779                     || queryBlock.getConnectBy() !is null) {
1780                 return;
1781             }
1782         }
1783 
1784         SQLTableSource ctxTable = ctx.getTableSource();
1785 
1786         if (cast(SQLJoinTableSource)(ctxTable) !is null) {
1787             SQLJoinTableSource join = cast(SQLJoinTableSource) ctxTable;
1788             tableSource = join.findTableSourceWithColumn(hash);
1789             if (tableSource is null) {
1790                  SQLTableSource left = join.getLeft(), right = join.getRight();
1791 
1792                 if (cast(SQLSubqueryTableSource)(left) !is null
1793                         && cast(SQLExprTableSource)(right) !is null) {
1794                     SQLSelect leftSelect = (cast(SQLSubqueryTableSource) left).getSelect();
1795                     if (cast(SQLSelectQueryBlock) leftSelect.getQuery() !is null) {
1796                         bool hasAllColumn = (cast(SQLSelectQueryBlock) leftSelect.getQuery()).selectItemHasAllColumn();
1797                         if (!hasAllColumn) {
1798                             tableSource = right;
1799                         }
1800                     }
1801                 } else if (cast(SQLSubqueryTableSource)(right) !is null
1802                         && cast(SQLExprTableSource)(left) !is null) {
1803                     SQLSelect rightSelect = (cast(SQLSubqueryTableSource) right).getSelect();
1804                     if (cast(SQLSelectQueryBlock) rightSelect.getQuery() !is null) {
1805                         bool hasAllColumn = (cast(SQLSelectQueryBlock) rightSelect.getQuery()).selectItemHasAllColumn();
1806                         if (!hasAllColumn) {
1807                             tableSource = left;
1808                         }
1809                     }
1810                 } else if (cast(SQLExprTableSource)(left) !is null && cast(SQLExprTableSource)(right) !is null) {
1811                     SQLExprTableSource leftExprTableSource = cast(SQLExprTableSource) left;
1812                     SQLExprTableSource rightExprTableSource = cast(SQLExprTableSource) right;
1813 
1814                     if (leftExprTableSource.getSchemaObject() !is null
1815                             && rightExprTableSource.getSchemaObject() is null) {
1816                         tableSource = rightExprTableSource;
1817 
1818                     } else if (rightExprTableSource.getSchemaObject() !is null
1819                             && leftExprTableSource.getSchemaObject() is null) {
1820                         tableSource = leftExprTableSource;
1821                     }
1822                 }
1823             }
1824         } else if (cast(SQLSubqueryTableSource)(ctxTable) !is null) {
1825             tableSource = ctxTable.findTableSourceWithColumn(hash);
1826         } else if (cast(SQLLateralViewTableSource)(ctxTable) !is null) {
1827             tableSource = ctxTable.findTableSourceWithColumn(hash);
1828 
1829             if (tableSource is null) {
1830                 tableSource = (cast(SQLLateralViewTableSource) ctxTable).getTableSource();
1831             }
1832         } else {
1833             for (SchemaResolveVisitor.Context parentCtx = ctx;
1834                  parentCtx !is null;
1835                  parentCtx = parentCtx.parent)
1836             {
1837                 SQLDeclareItem declareItem = parentCtx.findDeclare(hash);
1838                 if (declareItem !is null) {
1839                     x.setResolvedDeclareItem(declareItem);
1840                     return;
1841                 }
1842 
1843                 if (cast(SQLBlockStatement)(parentCtx.object) !is null) {
1844                     SQLBlockStatement block = cast(SQLBlockStatement) parentCtx.object;
1845                     SQLParameter parameter = block.findParameter(hash);
1846                     if (parameter !is null) {
1847                         x.setResolvedParameter(parameter);
1848                         return;
1849                     }
1850                 } else if (cast(SQLCreateProcedureStatement)(parentCtx.object) !is null) {
1851                     SQLCreateProcedureStatement createProc = cast(SQLCreateProcedureStatement) parentCtx.object;
1852                     SQLParameter parameter = createProc.findParameter(hash);
1853                     if (parameter !is null) {
1854                         x.setResolvedParameter(parameter);
1855                         return;
1856                     }
1857                 }
1858             }
1859 
1860             tableSource = ctxTable;
1861             if (cast(SQLExprTableSource)(tableSource) !is null) {
1862                 SchemaObject table = (cast(SQLExprTableSource) tableSource).getSchemaObject();
1863                 if (table !is null) {
1864                     if (table.findColumn(hash) is null) {
1865                         SQLCreateTableStatement createStmt = null;
1866                         {
1867                             SQLStatement smt = table.getStatement();
1868                             if (cast(SQLCreateTableStatement)(smt) !is null) {
1869                                 createStmt = cast(SQLCreateTableStatement) smt;
1870                             }
1871                         }
1872 
1873                         if (createStmt !is null && createStmt.getTableElementList().size() > 0) {
1874                             tableSource = null; // maybe parent
1875                         }
1876                     }
1877                 }
1878             }
1879         }
1880 
1881         if (cast(SQLExprTableSource)(tableSource) !is null) {
1882                     SQLExpr expr = (cast(SQLExprTableSource) tableSource).getExpr();
1883             if (cast(SQLIdentifierExpr)(expr) !is null) {
1884                 SQLIdentifierExpr identExpr = cast(SQLIdentifierExpr) expr;
1885                 long identHash = identExpr.nameHashCode64();
1886 
1887                 tableSource = unwrapAlias(ctx, tableSource, identHash);
1888             }
1889         }
1890 
1891         if (tableSource !is null) {
1892             x.setResolvedTableSource(tableSource);
1893 
1894             SQLColumnDefinition column = tableSource.findColumn(hash);
1895             if (column !is null) {
1896                 x.setResolvedColumn(column);
1897             }
1898 
1899             if (cast(SQLJoinTableSource)(ctxTable) !is null) {
1900                 string _alias = tableSource.computeAlias();
1901                 if (_alias is null || cast(SQLWithSubqueryClause.Entry)(tableSource) !is null) {
1902                     return;
1903                 }
1904 
1905                 SQLPropertyExpr propertyExpr = new SQLPropertyExpr(new SQLIdentifierExpr(_alias), ident, hash);
1906                 propertyExpr.setResolvedColumn(x.getResolvedColumn());
1907                 propertyExpr.setResolvedTableSource(x.getResolvedTableSource());
1908                 SQLUtils.replaceInParent(x, propertyExpr);
1909             }
1910         }
1911 
1912         if (x.getResolvedColumn() is null
1913                 && x.getResolvedTableSource() is null) {
1914             for (SchemaResolveVisitor.Context parentCtx = ctx;
1915                  parentCtx !is null;
1916                  parentCtx = parentCtx.parent)
1917             {
1918                 SQLDeclareItem declareItem = parentCtx.findDeclare(hash);
1919                 if (declareItem !is null) {
1920                     x.setResolvedDeclareItem(declareItem);
1921                     return;
1922                 }
1923 
1924                 if (cast(SQLBlockStatement)(parentCtx.object) !is null) {
1925                     SQLBlockStatement block = cast(SQLBlockStatement) parentCtx.object;
1926                     SQLParameter parameter = block.findParameter(hash);
1927                     if (parameter !is null) {
1928                         x.setResolvedParameter(parameter);
1929                         return;
1930                     }
1931                 } else if (cast(SQLCreateProcedureStatement)(parentCtx.object) !is null) {
1932                     SQLCreateProcedureStatement createProc = cast(SQLCreateProcedureStatement) parentCtx.object;
1933                     SQLParameter parameter = createProc.findParameter(hash);
1934                     if (parameter !is null) {
1935                         x.setResolvedParameter(parameter);
1936                         return;
1937                     }
1938                 }
1939             }
1940         }
1941     }
1942 
1943     static void resolve(SchemaResolveVisitor visitor, SQLPropertyExpr x) {
1944         SchemaResolveVisitor.Context ctx = visitor.getContext();
1945         if (ctx is null) {
1946             return;
1947         }
1948 
1949         long owner_hash = 0;
1950         {
1951             SQLExpr ownerObj = x.getOwner();
1952             if (cast(SQLIdentifierExpr)(ownerObj) !is null) {
1953                 SQLIdentifierExpr owner = cast(SQLIdentifierExpr) ownerObj;
1954                 owner_hash = owner.nameHashCode64();
1955             } else if (cast(SQLPropertyExpr)(ownerObj) !is null) {
1956                 owner_hash = (cast(SQLPropertyExpr) ownerObj).hashCode64();
1957             }
1958         }
1959 
1960         SQLTableSource tableSource = null;
1961         SQLTableSource ctxTable = ctx.getTableSource();
1962 
1963         if (ctxTable !is null) {
1964             tableSource = ctxTable.findTableSource(owner_hash);
1965         }
1966 
1967         if (tableSource is null) {
1968             SQLTableSource ctxFrom = ctx.getFrom();
1969             if (ctxFrom !is null) {
1970                 tableSource = ctxFrom.findTableSource(owner_hash);
1971             }
1972         }
1973 
1974         if (tableSource is null) {
1975             for (SchemaResolveVisitor.Context parentCtx = ctx;
1976                  parentCtx !is null;
1977                  parentCtx = parentCtx.parent) {
1978 
1979                 SQLTableSource parentCtxTable = parentCtx.getTableSource();
1980 
1981                 if (parentCtxTable !is null) {
1982                     tableSource = parentCtxTable.findTableSource(owner_hash);
1983                     if (tableSource is null) {
1984                         SQLTableSource ctxFrom = parentCtx.getFrom();
1985                         if (ctxFrom !is null) {
1986                             tableSource = ctxFrom.findTableSource(owner_hash);
1987                         }
1988                     }
1989 
1990                     if (tableSource !is null) {
1991                         break;
1992                     }
1993                 } else {
1994                     if (cast(SQLBlockStatement)(parentCtx.object) !is null) {
1995                         SQLBlockStatement block = cast(SQLBlockStatement) parentCtx.object;
1996                         SQLParameter parameter = block.findParameter(owner_hash);
1997                         if (parameter !is null) {
1998                             x.setResolvedOwnerObject(parameter);
1999                             return;
2000                         }
2001                     } else if (cast(SQLMergeStatement)(parentCtx.object) !is null) {
2002                         SQLMergeStatement mergeStatement = cast(SQLMergeStatement) parentCtx.object;
2003                         SQLTableSource into = mergeStatement.getInto();
2004                         if (cast(SQLSubqueryTableSource)(into) !is null
2005                                 && into.aliasHashCode64() == owner_hash) {
2006                             x.setResolvedOwnerObject(into);
2007                         }
2008                     }
2009 
2010                     SQLDeclareItem declareItem = parentCtx.findDeclare(owner_hash);
2011                     if (declareItem !is null) {
2012                         SQLObject resolvedObject = declareItem.getResolvedObject();
2013                         if (cast(SQLCreateProcedureStatement)(resolvedObject) !is null
2014                                 || cast(SQLCreateFunctionStatement)(resolvedObject) !is null
2015                                 || cast(SQLTableSource)(resolvedObject) !is null) {
2016                             x.setResolvedOwnerObject(resolvedObject);
2017                         }
2018                         break;
2019                     }
2020                 }
2021             }
2022         }
2023 
2024         if (tableSource !is null) {
2025             x.setResolvedTableSource(tableSource);
2026             SQLColumnDefinition column = tableSource.findColumn(x.nameHashCode64());
2027             if (column !is null) {
2028                 x.setResolvedColumn(column);
2029             }
2030         }
2031     }
2032 
2033     private static SQLTableSource unwrapAlias(SchemaResolveVisitor.Context ctx, SQLTableSource tableSource, long identHash) {
2034         if (ctx is null) {
2035             return tableSource;
2036         }
2037 
2038         if (cast(SQLDeleteStatement)(ctx.object) !is null
2039                 && (ctx.getTableSource() is null || tableSource == ctx.getTableSource())
2040                 && ctx.getFrom() !is null) {
2041             SQLTableSource found = ctx.getFrom().findTableSource(identHash);
2042             if (found !is null) {
2043                 return found;
2044             }
2045         }
2046 
2047         for (SchemaResolveVisitor.Context parentCtx = ctx;
2048              parentCtx !is null;
2049              parentCtx = parentCtx.parent) {
2050 
2051             SQLWithSubqueryClause _with = null;
2052             if (cast(SQLSelect)(parentCtx.object) !is null) {
2053                 SQLSelect select = cast(SQLSelect) parentCtx.object;
2054                 _with = select.getWithSubQuery();
2055             } else if (cast(SQLDeleteStatement)(parentCtx.object) !is null) {
2056                 SQLDeleteStatement _delete = cast(SQLDeleteStatement) parentCtx.object;
2057                 _with = _delete.getWith();
2058             } else if (cast(SQLInsertStatement)(parentCtx.object) !is null) {
2059                 SQLInsertStatement insertStmt = cast(SQLInsertStatement) parentCtx.object;
2060                 _with = insertStmt.getWith();
2061             } else if (cast(SQLUpdateStatement)(parentCtx.object) !is null) {
2062                 SQLUpdateStatement updateStmt = cast(SQLUpdateStatement) parentCtx.object;
2063                 _with = updateStmt.getWith();
2064             }
2065 
2066             if (_with !is null) {
2067                 SQLWithSubqueryClause.Entry entry = _with.findEntry(identHash);
2068                 if (entry !is null) {
2069                     return entry;
2070                 }
2071             }
2072         }
2073         return tableSource;
2074     }
2075 
2076     static void resolve(SchemaResolveVisitor visitor, SQLSelectQueryBlock x) {
2077         SchemaResolveVisitor.Context ctx = visitor.createContext(x);
2078 
2079         SQLTableSource from = x.getFrom();
2080         if (from !is null) {
2081             ctx.setTableSource(from);
2082 
2083             from.accept(visitor);
2084         }// } else if (x.getParent() !is null && cast(HiveInsert)x.getParent().getParent() !is null
2085         //         && cast(HiveMultiInsertStatement)x.getParent().getParent().getParent() !is null){
2086         //     HiveMultiInsertStatement insert = cast(HiveMultiInsertStatement) x.getParent().getParent().getParent();
2087         //     if (cast(SQLExprTableSource)insert.getFrom()  !is null) {
2088         //         from = insert.getFrom();
2089         //         ctx.setTableSource(from);
2090         //     }
2091         // }
2092 
2093         List!(SQLSelectItem) selectList = x.getSelectList();
2094 
2095         List!(SQLSelectItem) columns = new ArrayList!(SQLSelectItem)();
2096         for (int i = selectList.size() - 1; i >= 0; i--) {
2097             SQLSelectItem selectItem = selectList.get(i);
2098             SQLExpr expr = selectItem.getExpr();
2099             if (cast(SQLAllColumnExpr)(expr) !is null) {
2100                 SQLAllColumnExpr allColumnExpr = cast(SQLAllColumnExpr) expr;
2101                 allColumnExpr.setResolvedTableSource(from);
2102 
2103                 visitor.visit(allColumnExpr);
2104 
2105                 if (visitor.isEnabled(SchemaResolveVisitor.Option.ResolveAllColumn)) {
2106                     extractColumns(visitor, from, columns);
2107                 }
2108             } else if (cast(SQLPropertyExpr)(expr) !is null) {
2109                 SQLPropertyExpr propertyExpr = cast(SQLPropertyExpr) expr;
2110                 visitor.visit(propertyExpr);
2111 
2112                 string ownerName = propertyExpr.getOwnernName();
2113                 if (propertyExpr.getName() == ("*")) {
2114                     if (visitor.isEnabled(SchemaResolveVisitor.Option.ResolveAllColumn)) {
2115                         SQLTableSource tableSource = x.findTableSource(ownerName);
2116                         extractColumns(visitor, tableSource, columns);
2117                     }
2118                 }
2119 
2120                 SQLColumnDefinition column = propertyExpr.getResolvedColumn();
2121                 if (column !is null) {
2122                     continue;
2123                 }
2124                 SQLTableSource tableSource = x.findTableSource(propertyExpr.getOwnernName());
2125                 if (tableSource !is null) {
2126                     column = tableSource.findColumn(propertyExpr.nameHashCode64());
2127                     if (column !is null) {
2128                         propertyExpr.setResolvedColumn(column);
2129                     }
2130                 }
2131             } else if (cast(SQLIdentifierExpr)(expr) !is null) {
2132                 SQLIdentifierExpr identExpr = cast(SQLIdentifierExpr) expr;
2133                 visitor.visit(identExpr);
2134 
2135                 long name_hash = identExpr.nameHashCode64();
2136 
2137                 SQLColumnDefinition column = identExpr.getResolvedColumn();
2138                 if (column !is null) {
2139                     continue;
2140                 }
2141                 if (from is null) {
2142                     continue;
2143                 }
2144                 column = from.findColumn(name_hash);
2145                 if (column !is null) {
2146                     identExpr.setResolvedColumn(column);
2147                 }
2148             } else {
2149                 expr.accept(visitor);
2150             }
2151 
2152             if (columns.size() > 0) {
2153                 foreach(SQLSelectItem column ; columns) {
2154                     column.setParent(x);
2155                     column.getExpr().accept(visitor);
2156                 }
2157 
2158                 selectList.removeAt(i);
2159                 // selectList.addAll(i, columns);
2160                 selectList.addAll( columns); //@gxc
2161             }
2162         }
2163 
2164         SQLExprTableSource into = x.getInto();
2165         if (into !is null) {
2166             visitor.visit(into);
2167         }
2168 
2169         SQLExpr where = x.getWhere();
2170         if (where !is null) {
2171             if (cast(SQLBinaryOpExpr)(where) !is null) {
2172                 SQLBinaryOpExpr binaryOpExpr = cast(SQLBinaryOpExpr) where;
2173                 resolveExpr(visitor, binaryOpExpr.getLeft());
2174                 resolveExpr(visitor, binaryOpExpr.getRight());
2175             } else if (cast(SQLBinaryOpExprGroup)(where) !is null) {
2176                 SQLBinaryOpExprGroup binaryOpExprGroup = cast(SQLBinaryOpExprGroup) where;
2177                 foreach(SQLExpr item ; binaryOpExprGroup.getItems()) {
2178                     if (cast(SQLBinaryOpExpr)(item) !is null) {
2179                         SQLBinaryOpExpr binaryOpExpr = cast(SQLBinaryOpExpr) item;
2180                         resolveExpr(visitor, binaryOpExpr.getLeft());
2181                         resolveExpr(visitor, binaryOpExpr.getRight());
2182                     } else {
2183                         item.accept(visitor);
2184                     }
2185                 }
2186             } else {
2187                 where.accept(visitor);
2188             }
2189         }
2190 
2191         SQLExpr startWith = x.getStartWith();
2192         if (startWith !is null) {
2193             startWith.accept(visitor);
2194         }
2195 
2196         SQLExpr connectBy = x.getConnectBy();
2197         if (connectBy !is null) {
2198             connectBy.accept(visitor);
2199         }
2200 
2201         SQLSelectGroupByClause groupBy = x.getGroupBy();
2202         if (groupBy !is null) {
2203             groupBy.accept(visitor);
2204         }
2205 
2206         SQLOrderBy orderBy = x.getOrderBy();
2207         if (orderBy !is null) {
2208             foreach(SQLSelectOrderByItem orderByItem ; orderBy.getItems()) {
2209                 SQLExpr orderByItemExpr = orderByItem.getExpr();
2210 
2211                 if (cast(SQLIdentifierExpr)(orderByItemExpr) !is null) {
2212                     SQLIdentifierExpr orderByItemIdentExpr = cast(SQLIdentifierExpr) orderByItemExpr;
2213                     long hash = orderByItemIdentExpr.nameHashCode64();
2214                     SQLSelectItem selectItem = x.findSelectItem(hash);
2215 
2216                     if (selectItem !is null) {
2217                         orderByItem.setResolvedSelectItem(selectItem);
2218 
2219                         SQLExpr selectItemExpr = selectItem.getExpr();
2220                         if (cast(SQLIdentifierExpr)(selectItemExpr) !is null) {
2221                             orderByItemIdentExpr.setResolvedTableSource((cast(SQLIdentifierExpr) selectItemExpr).getResolvedTableSource());
2222                             orderByItemIdentExpr.setResolvedColumn((cast(SQLIdentifierExpr) selectItemExpr).getResolvedColumn());
2223                         } else if (cast(SQLPropertyExpr)(selectItemExpr) !is null) {
2224                             orderByItemIdentExpr.setResolvedTableSource((cast(SQLPropertyExpr) selectItemExpr).getResolvedTableSource());
2225                             orderByItemIdentExpr.setResolvedColumn((cast(SQLPropertyExpr) selectItemExpr).getResolvedColumn());
2226                         }
2227                         continue;
2228                     }
2229                 }
2230 
2231                 orderByItemExpr.accept(visitor);
2232             }
2233         }
2234 
2235         int forUpdateOfSize = x.getForUpdateOfSize();
2236         if (forUpdateOfSize > 0) {
2237             foreach(SQLExpr sqlExpr ; x.getForUpdateOf()) {
2238                 sqlExpr.accept(visitor);
2239             }
2240         }
2241 
2242         visitor.popContext();
2243     }
2244 
2245     static void extractColumns(SchemaResolveVisitor visitor, SQLTableSource from, List!(SQLSelectItem) columns) {
2246         if (cast(SQLExprTableSource)(from) !is null) {
2247             SchemaRepository repository = visitor.getRepository();
2248             if (repository is null) {
2249                 return;
2250             }
2251 
2252             string _alias = from.getAlias();
2253 
2254             SchemaObject table = repository.findTable(cast(SQLExprTableSource) from);
2255             if (table !is null) {
2256                 SQLCreateTableStatement createTableStmt = cast(SQLCreateTableStatement) table.getStatement();
2257                 foreach(SQLTableElement e ; createTableStmt.getTableElementList()) {
2258                     if (cast(SQLColumnDefinition)(e) !is null) {
2259                         SQLColumnDefinition column = cast(SQLColumnDefinition) e;
2260 
2261                         if (_alias !is null) {
2262                             SQLPropertyExpr name = new SQLPropertyExpr(_alias, column.getName().getSimpleName());
2263                             name.setResolvedColumn(column);
2264                             columns.add(new SQLSelectItem(name));
2265                         } else {
2266                             SQLIdentifierExpr name = cast(SQLIdentifierExpr) column.getName().clone();
2267                             name.setResolvedColumn(column);
2268                             columns.add(new SQLSelectItem(name));
2269                         }
2270 
2271 
2272                     }
2273                 }
2274             }
2275             return;
2276         }
2277 
2278         if (cast(SQLJoinTableSource)(from) !is null) {
2279             SQLJoinTableSource join = cast(SQLJoinTableSource) from;
2280             extractColumns(visitor, join.getLeft(), columns);
2281             extractColumns(visitor, join.getRight(), columns);
2282         }
2283     }
2284 
2285     static void resolve(SchemaResolveVisitor visitor, SQLAllColumnExpr x) {
2286         SQLTableSource tableSource = x.getResolvedTableSource();
2287 
2288         if (tableSource is null) {
2289             SQLSelectQueryBlock queryBlock = null;
2290             for (SQLObject parent = x.getParent(); parent !is null; parent = parent.getParent()) {
2291                 if (cast(SQLTableSource)(parent) !is null) {
2292                     return;
2293                 }
2294                 if (cast(SQLSelectQueryBlock)(parent) !is null) {
2295                     queryBlock = cast(SQLSelectQueryBlock) parent;
2296                     break;
2297                 }
2298             }
2299 
2300             if (queryBlock is null) {
2301                 return;
2302             }
2303 
2304             SQLTableSource from = queryBlock.getFrom();
2305             if (from is null || cast(SQLJoinTableSource)(from) !is null) {
2306                 return;
2307             }
2308 
2309             x.setResolvedTableSource(from);
2310             tableSource = from;
2311         }
2312 
2313         if (cast(SQLExprTableSource)(tableSource) !is null) {
2314             SQLExpr expr = (cast(SQLExprTableSource) tableSource).getExpr();
2315             if (cast(SQLIdentifierExpr)(expr) !is null) {
2316                 SQLTableSource resolvedTableSource = (cast(SQLIdentifierExpr) expr).getResolvedTableSource();
2317                 if (resolvedTableSource !is null) {
2318                     x.setResolvedTableSource(resolvedTableSource);
2319                 }
2320             }
2321         }
2322     }
2323 
2324     static void resolve(SchemaResolveVisitor visitor, SQLSelect x) {
2325         SchemaResolveVisitor.Context ctx = visitor.createContext(x);
2326 
2327         SQLWithSubqueryClause _with = x.getWithSubQuery();
2328         if (_with !is null) {
2329             visitor.visit(_with);
2330         }
2331 
2332         SQLSelectQuery query = x.getQuery();
2333         if (query !is null) {
2334             query.accept(visitor);
2335         }
2336 
2337         SQLSelectQueryBlock queryBlock = x.getFirstQueryBlock();
2338 
2339         SQLOrderBy orderBy = x.getOrderBy();
2340         if (orderBy !is null) {
2341             foreach(SQLSelectOrderByItem orderByItem ; orderBy.getItems()) {
2342                 SQLExpr orderByItemExpr = orderByItem.getExpr();
2343 
2344                 if (cast(SQLIdentifierExpr)(orderByItemExpr) !is null) {
2345                     SQLIdentifierExpr orderByItemIdentExpr = cast(SQLIdentifierExpr) orderByItemExpr;
2346                     long hash = orderByItemIdentExpr.nameHashCode64();
2347 
2348                     SQLSelectItem selectItem = null;
2349                     if (queryBlock !is null) {
2350                         selectItem = queryBlock.findSelectItem(hash);
2351                     }
2352 
2353                     if (selectItem !is null) {
2354                         orderByItem.setResolvedSelectItem(selectItem);
2355 
2356                         SQLExpr selectItemExpr = selectItem.getExpr();
2357                         if (cast(SQLIdentifierExpr)(selectItemExpr) !is null) {
2358                             orderByItemIdentExpr.setResolvedTableSource((cast(SQLIdentifierExpr) selectItemExpr).getResolvedTableSource());
2359                             orderByItemIdentExpr.setResolvedColumn((cast(SQLIdentifierExpr) selectItemExpr).getResolvedColumn());
2360                         } else if (cast(SQLPropertyExpr)(selectItemExpr) !is null) {
2361                             orderByItemIdentExpr.setResolvedTableSource((cast(SQLPropertyExpr) selectItemExpr).getResolvedTableSource());
2362                             orderByItemIdentExpr.setResolvedColumn((cast(SQLPropertyExpr) selectItemExpr).getResolvedColumn());
2363                         }
2364                         continue;
2365                     }
2366                 }
2367 
2368                 orderByItemExpr.accept(visitor);
2369             }
2370         }
2371 
2372         visitor.popContext();
2373     }
2374 
2375     static void resolve(SchemaResolveVisitor visitor, SQLWithSubqueryClause x) {
2376         List!(SQLWithSubqueryClause.Entry) entries = x.getEntries();
2377         foreach(SQLWithSubqueryClause.Entry entry ; entries) {
2378             SQLSelect query = entry.getSubQuery();
2379             if (query !is null) {
2380                 visitor.visit(query);
2381             } else {
2382                 entry.getReturningStatement().accept(visitor);
2383             }
2384         }
2385     }
2386 
2387     static void resolve(SchemaResolveVisitor visitor, SQLExprTableSource x) {
2388         SQLExpr expr = x.getExpr();
2389         if (cast(SQLName)(expr) !is null) {
2390             if (x.getSchemaObject() !is null) {
2391                 return;
2392             }
2393 
2394             SchemaRepository repository = visitor.getRepository();
2395             if (repository !is null) {
2396                 SchemaObject table = repository.findTable(cast(SQLName) expr);
2397                 if (table !is null) {
2398                     x.setSchemaObject(table);
2399                 }
2400             }
2401 
2402             SQLIdentifierExpr identifierExpr = null;
2403 
2404             if (cast(SQLIdentifierExpr)(expr) !is null) {
2405                 identifierExpr = cast(SQLIdentifierExpr) expr;
2406             } else if (cast(SQLPropertyExpr)(expr) !is null) {
2407                 SQLExpr owner = (cast(SQLPropertyExpr) expr).getOwner();
2408                 if (cast(SQLIdentifierExpr)(owner) !is null) {
2409                     identifierExpr = cast(SQLIdentifierExpr) owner;
2410                 }
2411             }
2412 
2413             if (identifierExpr !is null) {
2414                 checkParameter(visitor, identifierExpr);
2415 
2416                 SQLTableSource tableSource = unwrapAlias(visitor.getContext(), null, identifierExpr.nameHashCode64());
2417                 if (tableSource !is null) {
2418                     identifierExpr.setResolvedTableSource(tableSource);
2419                 }
2420             }
2421 
2422         } else if (cast(SQLMethodInvokeExpr)(expr) !is null) {
2423             expr.accept(visitor);
2424         } else {
2425             expr.accept(visitor);
2426         }
2427     }
2428 
2429     static void resolve(SchemaResolveVisitor visitor, SQLAlterTableStatement x) {
2430         SchemaResolveVisitor.Context ctx = visitor.createContext(x);
2431 
2432         SQLTableSource tableSource = x.getTableSource();
2433         ctx.setTableSource(tableSource);
2434 
2435         foreach(SQLAlterTableItem item ; x.getItems()) {
2436             item.accept(visitor);
2437         }
2438 
2439         visitor.popContext();
2440     }
2441 
2442     static void resolve(SchemaResolveVisitor visitor, SQLMergeStatement x) {
2443         SchemaResolveVisitor.Context ctx = visitor.createContext(x);
2444 
2445         SQLTableSource into = x.getInto();
2446         if (cast(SQLExprTableSource)(into) !is null) {
2447             ctx.setTableSource(into);
2448         } else {
2449             into.accept(visitor);
2450         }
2451 
2452         SQLTableSource using = x.getUsing();
2453         if (using !is null) {
2454             using.accept(visitor);
2455             ctx.setFrom(using);
2456         }
2457 
2458         SQLExpr on = x.getOn();
2459         if (on !is null) {
2460             on.accept(visitor);
2461         }
2462 
2463         SQLMergeStatement.MergeUpdateClause updateClause  = x.getUpdateClause();
2464         if (updateClause !is null) {
2465             foreach(SQLUpdateSetItem item ; updateClause.getItems()) {
2466                 SQLExpr column = item.getColumn();
2467 
2468                 if (cast(SQLIdentifierExpr)(column) !is null) {
2469                     (cast(SQLIdentifierExpr) column).setResolvedTableSource(into);
2470                 } else if (cast(SQLPropertyExpr)(column) !is null) {
2471                     (cast(SQLPropertyExpr) column).setResolvedTableSource(into);
2472                 } else {
2473                     column.accept(visitor);
2474                 }
2475 
2476                 SQLExpr value = item.getValue();
2477                 if (value !is null) {
2478                     value.accept(visitor);
2479                 }
2480             }
2481 
2482             SQLExpr where = updateClause.getWhere();
2483             if (where !is null) {
2484                 where.accept(visitor);
2485             }
2486 
2487             SQLExpr deleteWhere = updateClause.getDeleteWhere();
2488             if (deleteWhere !is null) {
2489                 deleteWhere.accept(visitor);
2490             }
2491         }
2492 
2493         SQLMergeStatement.MergeInsertClause insertClause = x.getInsertClause();
2494         if (insertClause !is null) {
2495             foreach(SQLExpr column ; insertClause.getColumns()) {
2496                 if (cast(SQLIdentifierExpr)(column) !is null) {
2497                     (cast(SQLIdentifierExpr) column).setResolvedTableSource(into);
2498                 } else if (cast(SQLPropertyExpr)(column) !is null) {
2499                     (cast(SQLPropertyExpr) column).setResolvedTableSource(into);
2500                 }
2501                 column.accept(visitor);
2502             }
2503             foreach(SQLExpr value ; insertClause.getValues()) {
2504                 value.accept(visitor);
2505             }
2506             SQLExpr where = insertClause.getWhere();
2507             if (where !is null) {
2508                 where.accept(visitor);
2509             }
2510         }
2511 
2512         visitor.popContext();
2513     }
2514 
2515     static void resolve(SchemaResolveVisitor visitor, SQLCreateFunctionStatement x) {
2516         SchemaResolveVisitor.Context ctx = visitor.createContext(x);
2517 
2518         {
2519             SQLDeclareItem declareItem = new SQLDeclareItem(x.getName().clone(), null);
2520             declareItem.setResolvedObject(x);
2521 
2522             SchemaResolveVisitor.Context parentCtx = visitor.getContext();
2523             if (parentCtx !is null) {
2524                 parentCtx.declare(declareItem);
2525             } else {
2526                 ctx.declare(declareItem);
2527             }
2528         }
2529 
2530         foreach(SQLParameter parameter ; x.getParameters()) {
2531             parameter.accept(visitor);
2532         }
2533 
2534         SQLStatement block = x.getBlock();
2535         if (block !is null) {
2536             block.accept(visitor);
2537         }
2538 
2539         visitor.popContext();
2540     }
2541     static void resolve(SchemaResolveVisitor visitor, SQLCreateProcedureStatement x) {
2542         SchemaResolveVisitor.Context ctx = visitor.createContext(x);
2543 
2544         {
2545             SQLDeclareItem declareItem = new SQLDeclareItem(x.getName().clone(), null);
2546             declareItem.setResolvedObject(x);
2547 
2548 
2549             SchemaResolveVisitor.Context parentCtx = visitor.getContext();
2550             if (parentCtx !is null) {
2551                 parentCtx.declare(declareItem);
2552             } else {
2553                 ctx.declare(declareItem);
2554             }
2555         }
2556 
2557         foreach(SQLParameter parameter ; x.getParameters()) {
2558             parameter.accept(visitor);
2559         }
2560 
2561         SQLStatement block = x.getBlock();
2562         if (block !is null) {
2563             block.accept(visitor);
2564         }
2565 
2566         visitor.popContext();
2567     }
2568 
2569     static bool resolve(SchemaResolveVisitor visitor, SQLIfStatement x) {
2570         SchemaResolveVisitor.Context ctx = visitor.createContext(x);
2571 
2572         SQLExpr condition = x.getCondition();
2573         if (condition !is null) {
2574             condition.accept(visitor);
2575         }
2576 
2577         foreach(SQLStatement stmt ; x.getStatements()) {
2578             stmt.accept(visitor);
2579         }
2580 
2581         foreach(SQLIfStatement.ElseIf elseIf ; x.getElseIfList()) {
2582             elseIf.accept(visitor);
2583         }
2584 
2585         SQLIfStatement.Else e = x.getElseItem();
2586         if (e !is null) {
2587             e.accept(visitor);
2588         }
2589 
2590         visitor.popContext();
2591         return false;
2592     }
2593 
2594     static void resolve(SchemaResolveVisitor visitor, SQLBlockStatement x) {
2595         SchemaResolveVisitor.Context ctx = visitor.createContext(x);
2596 
2597         foreach(SQLParameter parameter ; x.getParameters()) {
2598             visitor.visit(parameter);
2599         }
2600 
2601         foreach(SQLStatement stmt ; x.getStatementList()) {
2602             stmt.accept(visitor);
2603         }
2604 
2605         SQLStatement exception = x.getException();
2606         if (exception !is null) {
2607             exception.accept(visitor);
2608         }
2609 
2610         visitor.popContext();
2611     }
2612 
2613     static void resolve(SchemaResolveVisitor visitor, SQLParameter x) {
2614         SQLName name = x.getName();
2615         if (cast(SQLIdentifierExpr)(name) !is null) {
2616             (cast(SQLIdentifierExpr) name).setResolvedParameter(x);
2617         }
2618 
2619         SQLExpr expr = x.getDefaultValue();
2620 
2621         SchemaResolveVisitor.Context ctx = null;
2622         if (expr !is null) {
2623             if (cast(SQLQueryExpr)(expr) !is null) {
2624                 ctx = visitor.createContext(x);
2625 
2626                 SQLSubqueryTableSource tableSource = new SQLSubqueryTableSource((cast(SQLQueryExpr) expr).getSubQuery());
2627                 tableSource.setParent(x);
2628                 tableSource.setAlias(x.getName().getSimpleName());
2629 
2630                 ctx.setTableSource(tableSource);
2631             }
2632 
2633             expr.accept(visitor);
2634         }
2635 
2636         if (ctx !is null) {
2637             visitor.popContext();
2638         }
2639     }
2640 
2641     static void resolve(SchemaResolveVisitor visitor, SQLDeclareItem x) {
2642         SchemaResolveVisitor.Context ctx = visitor.getContext();
2643         if (ctx !is null) {
2644             ctx.declare(x);
2645         }
2646 
2647         SQLName name = x.getName();
2648         if (cast(SQLIdentifierExpr)(name) !is null) {
2649             (cast(SQLIdentifierExpr) name).setResolvedDeclareItem(x);
2650         }
2651     }
2652 
2653     static void resolve(SchemaResolveVisitor visitor, SQLOver x) {
2654         SQLName of = x.getOf();
2655         SQLOrderBy orderBy = x.getOrderBy();
2656         List!(SQLExpr) partitionBy = x.getPartitionBy();
2657 
2658 
2659         if (of is null // skip if of is not null
2660                 && orderBy !is null) {
2661             orderBy.accept(visitor);
2662         }
2663 
2664         if (partitionBy !is null) {
2665             foreach(SQLExpr expr ; partitionBy) {
2666                 expr.accept(visitor);
2667             }
2668         }
2669     }
2670 
2671     private static bool checkParameter(SchemaResolveVisitor visitor, SQLIdentifierExpr x) {
2672         if (x.getResolvedParameter() !is null) {
2673             return true;
2674         }
2675 
2676         SchemaResolveVisitor.Context ctx = visitor.getContext();
2677         if (ctx is null) {
2678             return false;
2679         }
2680 
2681         long hash = x.hashCode64();
2682         for (SchemaResolveVisitor.Context parentCtx = ctx;
2683              parentCtx !is null;
2684              parentCtx = parentCtx.parent) {
2685 
2686             if (cast(SQLBlockStatement)(parentCtx.object) !is null) {
2687                 SQLBlockStatement block = cast(SQLBlockStatement) parentCtx.object;
2688                 SQLParameter parameter = block.findParameter(hash);
2689                 if (parameter !is null) {
2690                     x.setResolvedParameter(parameter);
2691                     return true;
2692                 }
2693             }
2694 
2695             if (cast(SQLCreateProcedureStatement)(parentCtx.object) !is null) {
2696                 SQLCreateProcedureStatement createProc = cast(SQLCreateProcedureStatement) parentCtx.object;
2697                 SQLParameter parameter = createProc.findParameter(hash);
2698                 if (parameter !is null) {
2699                     x.setResolvedParameter(parameter);
2700                     return true;
2701                 }
2702             }
2703 
2704             if (cast(SQLSelect)(parentCtx.object) !is null) {
2705                 SQLSelect select = cast(SQLSelect) parentCtx.object;
2706                 SQLWithSubqueryClause _with = select.getWithSubQuery();
2707                 if (_with !is null) {
2708                     SQLWithSubqueryClause.Entry entry = _with.findEntry(hash);
2709                     if (entry !is null) {
2710                         x.setResolvedTableSource(entry);
2711                         return true;
2712                     }
2713                 }
2714             }
2715 
2716             SQLDeclareItem declareItem = parentCtx.findDeclare(hash);
2717             if (declareItem !is null) {
2718                 x.setResolvedDeclareItem(declareItem);
2719                 break;
2720             }
2721         }
2722         return false;
2723     }
2724 
2725     static void resolve(SchemaResolveVisitor visitor, SQLReplaceStatement x) {
2726         SchemaResolveVisitor.Context ctx = visitor.createContext(x);
2727 
2728         SQLExprTableSource tableSource = x.getTableSource();
2729         ctx.setTableSource(tableSource);
2730         visitor.visit(tableSource);
2731 
2732         foreach(SQLExpr column ; x.getColumns()) {
2733             column.accept(visitor);
2734         }
2735 
2736         SQLQueryExpr queryExpr = x.getQuery();
2737         if (queryExpr !is null) {
2738             visitor.visit(queryExpr.getSubQuery());
2739         }
2740 
2741         visitor.popContext();
2742     }
2743 
2744     static void resolve(SchemaResolveVisitor visitor, SQLFetchStatement x) {
2745         resolveExpr(visitor, x.getCursorName());
2746         foreach(SQLExpr expr ; x.getInto()) {
2747             resolveExpr(visitor, expr);
2748         }
2749     }
2750 
2751     static void resolve(SchemaResolveVisitor visitor, SQLForeignKeyConstraint x) {
2752         SchemaRepository repository = visitor.getRepository();
2753         SQLObject parent = x.getParent();
2754 
2755         if (cast(SQLCreateTableStatement)(parent) !is null) {
2756             SQLCreateTableStatement createTableStmt = cast(SQLCreateTableStatement) parent;
2757             SQLTableSource table = createTableStmt.getTableSource();
2758             foreach(SQLName item ; x.getReferencingColumns()) {
2759                 SQLIdentifierExpr columnName = cast(SQLIdentifierExpr) item;
2760                 columnName.setResolvedTableSource(table);
2761 
2762                 SQLColumnDefinition column = createTableStmt.findColumn(columnName.nameHashCode64());
2763                 if (column !is null) {
2764                     columnName.setResolvedColumn(column);
2765                 }
2766             }
2767         } else if (cast(SQLAlterTableAddConstraint)(parent) !is null) {
2768             SQLAlterTableStatement stmt = cast(SQLAlterTableStatement) parent.getParent();
2769             SQLTableSource table = stmt.getTableSource();
2770             foreach(SQLName item ; x.getReferencingColumns()) {
2771                 SQLIdentifierExpr columnName = cast(SQLIdentifierExpr) item;
2772                 columnName.setResolvedTableSource(table);
2773             }
2774         }
2775 
2776 
2777         if (repository is null) {
2778             return;
2779         }
2780 
2781         SQLExprTableSource table = x.getReferencedTable();
2782         foreach(SQLName item ; x.getReferencedColumns()) {
2783             SQLIdentifierExpr columnName = cast(SQLIdentifierExpr) item;
2784             columnName.setResolvedTableSource(table);
2785         }
2786 
2787         SQLName tableName = table.getName();
2788 
2789         SchemaObject tableObject = repository.findTable(tableName);
2790         if (tableObject is null) {
2791             return;
2792         }
2793 
2794         SQLStatement tableStmt = tableObject.getStatement();
2795         if (cast(SQLCreateTableStatement)(tableStmt) !is null) {
2796             SQLCreateTableStatement refCreateTableStmt = cast(SQLCreateTableStatement) tableStmt;
2797             foreach(SQLName item ; x.getReferencedColumns()) {
2798                 SQLIdentifierExpr columnName = cast(SQLIdentifierExpr) item;
2799                 SQLColumnDefinition column = refCreateTableStmt.findColumn(columnName.nameHashCode64());
2800                 if (column !is null) {
2801                     columnName.setResolvedColumn(column);
2802                 }
2803             }
2804         }
2805     }
2806 
2807     // for performance
2808     static void resolveExpr(SchemaResolveVisitor visitor, SQLExpr x) {
2809         if (x is null) {
2810             return;
2811         }
2812 
2813         auto clazz = typeid(x);
2814         if (clazz == typeid(SQLIdentifierExpr)) {
2815             visitor.visit(cast(SQLIdentifierExpr) x);
2816             return;
2817         } else if (clazz == typeid(SQLIntegerExpr) || clazz == typeid(SQLCharExpr)) {
2818             // skip
2819             return;
2820         }
2821 
2822         x.accept(visitor);
2823     }
2824 
2825 
2826 }