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.dialect.mysql.visitor.MySqlOutputVisitor;
17 
18 import hunt.sql.ast;
19 import hunt.sql.ast.expr;
20 import hunt.sql.ast.statement;
21 import hunt.sql.dialect.mysql.ast.MySqlForceIndexHint;
22 import hunt.sql.dialect.mysql.ast.MySqlIgnoreIndexHint;
23 import hunt.sql.dialect.mysql.ast.MySqlKey;
24 import hunt.sql.dialect.mysql.ast.MySqlPrimaryKey;
25 import hunt.sql.dialect.mysql.ast.MySqlUnique;
26 import hunt.sql.dialect.mysql.ast.MySqlUseIndexHint;
27 import hunt.sql.dialect.mysql.ast.MysqlForeignKey;
28 import hunt.sql.dialect.mysql.ast.clause.ConditionValue;
29 // import hunt.sql.dialect.mysql.ast.clause.ConditionValue.ConditionType;
30 import hunt.sql.dialect.mysql.ast.clause.MySqlCaseStatement;
31 // import hunt.sql.dialect.mysql.ast.clause.MySqlCaseStatement.MySqlWhenStatement;
32 import hunt.sql.dialect.mysql.ast.clause.MySqlCursorDeclareStatement;
33 import hunt.sql.dialect.mysql.ast.clause.MySqlDeclareConditionStatement;
34 import hunt.sql.dialect.mysql.ast.clause.MySqlDeclareHandlerStatement;
35 import hunt.sql.dialect.mysql.ast.clause.MySqlDeclareStatement;
36 import hunt.sql.dialect.mysql.ast.clause.MySqlIterateStatement;
37 import hunt.sql.dialect.mysql.ast.clause.MySqlLeaveStatement;
38 import hunt.sql.dialect.mysql.ast.clause.MySqlRepeatStatement;
39 import hunt.sql.dialect.mysql.ast.clause.MySqlSelectIntoStatement;
40 import hunt.sql.dialect.mysql.ast.expr.MySqlCharExpr;
41 import hunt.sql.dialect.mysql.ast.expr.MySqlExtractExpr;
42 import hunt.sql.dialect.mysql.ast.expr.MySqlMatchAgainstExpr;
43 import hunt.sql.dialect.mysql.ast.expr.MySqlOrderingExpr;
44 import hunt.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;
45 import hunt.sql.dialect.mysql.ast.expr.MySqlUserName;
46 import hunt.sql.dialect.mysql.ast.statement;
47 import hunt.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
48 // import hunt.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement.TableSpaceOption;
49 import hunt.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement;
50 // import hunt.sql.dialect.mysql.ast.statement.MySqlCreateUserStatement.UserSpecification;
51 import hunt.sql.visitor;
52 import hunt.sql.util.DBType;
53 import hunt.sql.dialect.mysql.visitor.MySqlASTVisitor;
54 
55 import hunt.Byte;
56 import hunt.collection;
57 import hunt.String;
58 import hunt.Boolean;
59 import hunt.text;
60 import hunt.util.Appendable;
61 import hunt.util.Common;
62 import hunt.util.StringBuilder;
63 
64 import std.string;
65 
66 public class MySqlOutputVisitor : SQLASTOutputVisitor , MySqlASTVisitor {
67     alias visit = SQLASTOutputVisitor.visit;
68     alias endVisit = SQLASTOutputVisitor.endVisit;
69 
70     private char _quotes = '`';
71 
72     this(){
73         this.dbType = DBType.MYSQL.name;
74         this.shardingSupport = true;
75     }
76 
77     public this(Appendable appender) {
78         this.dbType = DBType.MYSQL.name;
79         this.shardingSupport = true;
80         super(appender);
81     }
82 
83     public this(Appendable appender, bool parameterized) {
84         this.dbType = DBType.MYSQL.name;
85         this.shardingSupport = true;
86         super(appender, parameterized);
87 
88         // try {
89         //     configFromProperty(System.getProperties());
90         // } catch (AccessControlException e) {
91         //     // skip
92         // }
93     }
94 
95     
96 
97     // public void configFromProperty(Properties properties) {
98     //     if (this.parameterized) {
99     //         string property = properties.getProperty("druid.parameterized.shardingSupport");
100     //         if ("true" == (property)) {
101     //             this.setShardingSupport(true);
102     //         } else if ("false" == (property)) {
103     //             this.setShardingSupport(false);
104     //         }
105     //     }
106     // }
107 
108     public bool isShardingSupport() {
109         return this.parameterized
110                 && shardingSupport;
111     }
112 
113     public void setShardingSupport(bool shardingSupport) {
114         this.shardingSupport = shardingSupport;
115     }
116 
117     override
118     public bool visit(SQLSelectQueryBlock select) {
119         if (cast(MySqlSelectQueryBlock)(select) !is null) {
120             return visit(cast(MySqlSelectQueryBlock) select);
121         }
122 
123         return super.visit(select);
124     }
125 
126 
127     public bool visit(MySqlSelectQueryBlock x) {
128          bool bracket = x.isBracket();
129         if (bracket) {
130             print('(');
131         }
132 
133         if ((!isParameterized()) && isPrettyFormat() && x.hasBeforeComment()) {
134             printlnComments(x.getBeforeCommentsDirect());
135         }
136 
137         string cachedSelectList = x.getCachedSelectList();
138 
139         if (cachedSelectList !is null) {
140             if (!isEnabled(VisitorFeature.OutputSkipSelectListCacheString)) {
141                 print0(cachedSelectList);
142             }
143         } else {
144             print0(ucase ? "SELECT " : "select ");
145 
146             for (int i = 0, size = x.getHintsSize(); i < size; ++i) {
147                 SQLCommentHint hint = x.getHints().get(i);
148                 hint.accept(this);
149                 print(' ');
150             }
151 
152              int distionOption = x.getDistionOption();
153             if (SQLSetQuantifier.ALL == distionOption) {
154                 print0(ucase ? "ALL " : "all ");
155             } else if (SQLSetQuantifier.DISTINCT == distionOption) {
156                 print0(ucase ? "DISTINCT " : "distinct ");
157             } else if (SQLSetQuantifier.DISTINCTROW == distionOption) {
158                 print0(ucase ? "DISTINCTROW " : "distinctrow ");
159             }
160 
161             if (x.isHignPriority()) {
162                 print0(ucase ? "HIGH_PRIORITY " : "high_priority ");
163             }
164 
165             if (x.isStraightJoin()) {
166                 print0(ucase ? "STRAIGHT_JOIN " : "straight_join ");
167             }
168 
169             if (x.isSmallResult()) {
170                 print0(ucase ? "SQL_SMALL_RESULT " : "sql_small_result ");
171             }
172 
173             if (x.isBigResult()) {
174                 print0(ucase ? "SQL_BIG_RESULT " : "sql_big_result ");
175             }
176 
177             if (x.isBufferResult()) {
178                 print0(ucase ? "SQL_BUFFER_RESULT " : "sql_buffer_result ");
179             }
180 
181             if (x.getCache() !is null) {
182                 if (x.getCache().booleanValue()) {
183                     print0(ucase ? "SQL_CACHE " : "sql_cache ");
184                 } else {
185                     print0(ucase ? "SQL_NO_CACHE " : "sql_no_cache ");
186                 }
187             }
188 
189             if (x.isCalcFoundRows()) {
190                 print0(ucase ? "SQL_CALC_FOUND_ROWS " : "sql_calc_found_rows ");
191             }
192 
193             printSelectList(x.getSelectList());
194 
195             SQLName forcePartition = x.getForcePartition();
196             if (forcePartition !is null) {
197                 println();
198                 print0(ucase ? "FORCE PARTITION " : "force partition ");
199                 printExpr(forcePartition);
200             }
201 
202             SQLExprTableSource into = x.getInto();
203             if (into !is null) {
204                 println();
205                 print0(ucase ? "INTO " : "into ");
206                 printTableSource(into);
207             }
208         }
209 
210         SQLTableSource from = x.getFrom();
211         if (from !is null) {
212             println();
213             print0(ucase ? "FROM " : "from ");
214 
215             printTableSource(from);
216         }
217 
218         SQLExpr where = x.getWhere();
219         if (where !is null) {
220             println();
221             print0(ucase ? "WHERE " : "where ");
222             printExpr(where);
223         }
224 
225         printHierarchical(x);
226 
227         SQLSelectGroupByClause groupBy = x.getGroupBy();
228         if (groupBy !is null) {
229             println();
230             visit(groupBy);
231         }
232 
233         SQLOrderBy orderBy = x.getOrderBy();
234         if (orderBy !is null) {
235             println();
236             visit(orderBy);
237         }
238 
239         SQLLimit limit = x.getLimit();
240         if (limit !is null) {
241             println();
242             visit(limit);
243         }
244 
245         SQLName procedureName = x.getProcedureName();
246         if (procedureName !is null) {
247             print0(ucase ? " PROCEDURE " : " procedure ");
248             procedureName.accept(this);
249             if (!x.getProcedureArgumentList().isEmpty()) {
250                 print('(');
251                 printAndAccept!SQLExpr((x.getProcedureArgumentList()), ", ");
252                 print(')');
253             }
254         }
255 
256         if (x.isForUpdate()) {
257             println();
258             print0(ucase ? "FOR UPDATE" : "for update");
259             if (x.isNoWait()) {
260                 print0(ucase ? " NOWAIT" : " nowait");
261             } else if (x.getWaitTime() !is null) {
262                 print0(ucase ? " WAIT " : " wait ");
263                 x.getWaitTime().accept(this);
264             }
265         }
266 
267         if (x.isLockInShareMode()) {
268             println();
269             print0(ucase ? "LOCK IN SHARE MODE" : "lock in share mode");
270         }
271 
272         if (bracket) {
273             print(')');
274         }
275 
276         return false;
277     }
278 
279     override public bool visit(SQLColumnDefinition x) {
280         bool parameterized = this.parameterized;
281         this.parameterized = false;
282 
283         x.getName().accept(this);
284 
285         SQLDataType dataType = x.getDataType();
286         if (dataType !is null) {
287             print(' ');
288             dataType.accept(this);
289         }
290 
291          SQLExpr charsetExpr = x.getCharsetExpr();
292         if (charsetExpr !is null) {
293             print0(ucase ? " CHARSET " : " charset ");
294             charsetExpr.accept(this);
295         }
296 
297         foreach(SQLColumnConstraint item ; x.getConstraints()) {
298             print(' ');
299             item.accept(this);
300         }
301 
302          SQLExpr defaultExpr = x.getDefaultExpr();
303         if (defaultExpr !is null) {
304             print0(ucase ? " DEFAULT " : " default ");
305             defaultExpr.accept(this);
306         }
307 
308          SQLExpr storage = x.getStorage();
309         if (storage !is null) {
310             print0(ucase ? " STORAGE " : " storage ");
311             storage.accept(this);
312         }
313 
314         SQLExpr onUpdate = x.getOnUpdate();
315         if (onUpdate !is null) {
316             print0(ucase ? " ON UPDATE " : " on update ");
317 
318             onUpdate.accept(this);
319         }
320 
321         if (x.isAutoIncrement()) {
322             print0(ucase ? " AUTO_INCREMENT" : " auto_increment");
323         }
324 
325         if (x.getComment() !is null) {
326             print0(ucase ? " COMMENT " : " comment ");
327             x.getComment().accept(this);
328         }
329 
330         if (x.getAsExpr() !is null) {
331             print0(ucase ? " AS (" : " as (");
332             x.getAsExpr().accept(this);
333             print(')');
334         }
335 
336         if (x.isSorted()) {
337             print0(ucase ? " SORTED" : " sorted");
338         }
339 
340         if (x.isVirtual()) {
341             print0(ucase ? " VIRTUAL" : " virtual");
342         }
343 
344         this.parameterized = parameterized;
345         return false;
346     }
347 
348     override public bool visit(SQLDataType x) {
349         printDataType(x);
350 
351         if (cast(SQLDataTypeImpl)(x) !is null) {
352             SQLDataTypeImpl dataTypeImpl = cast(SQLDataTypeImpl) x;
353             if (dataTypeImpl.isUnsigned()) {
354                 print0(ucase ? " UNSIGNED" : " unsigned");
355             }
356 
357             if (dataTypeImpl.isZerofill()) {
358                 print0(ucase ? " ZEROFILL" : " zerofill");
359             }
360         }
361 
362         if (cast(SQLCharacterDataType)(x) !is null) {
363             SQLCharacterDataType charType = cast(SQLCharacterDataType) x;
364             if (charType.getCharSetName() !is null) {
365                 print0(ucase ? " CHARACTER SET " : " character set ");
366                 print0(charType.getCharSetName());
367 
368                 if (charType.getCollate() !is null) {
369                     print0(ucase ? " COLLATE " : " collate ");
370                     print0(charType.getCollate());
371                 }
372             }
373 
374             List!(SQLCommentHint) hints = (cast(SQLCharacterDataType) x).hints;
375             if (hints !is null) {
376                 print(' ');
377                 foreach(SQLCommentHint hint ; hints) {
378                     hint.accept(this);
379                 }
380             }
381         }
382         return false;
383     }
384 
385     override
386     public bool visit(SQLCharacterDataType x) {
387         printDataType(x);
388 
389         if (x.isHasBinary()) {
390             print0(ucase ? " BINARY " : " binary ");
391         }
392 
393         if (x.getCharSetName() !is null) {
394             print0(ucase ? " CHARACTER SET " : " character set ");
395             print0(x.getCharSetName());
396             if (x.getCollate() !is null) {
397                 print0(ucase ? " COLLATE " : " collate ");
398                 print0(x.getCollate());
399             }
400         } else if (x.getCollate() !is null) {
401             print0(ucase ? " COLLATE " : " collate ");
402             print0(x.getCollate());
403         }
404 
405         List!(SQLCommentHint) hints = (cast(SQLCharacterDataType) x).hints;
406         if (hints !is null) {
407             print(' ');
408             foreach(SQLCommentHint hint ; hints) {
409                 hint.accept(this);
410             }
411         }
412 
413         return false;
414     }
415 
416     override
417     public void endVisit(MySqlTableIndex x) {
418 
419     }
420 
421     override
422     public bool visit(MySqlTableIndex x) {
423         string indexType = x.getIndexType();
424 
425         bool indexTypePrinted = false;
426         if ("FULLTEXT".equalsIgnoreCase(indexType)) {
427             print0(ucase ? "FULLTEXT " : "fulltext ");
428             indexTypePrinted = true;
429         } else if ("SPATIAL".equalsIgnoreCase(indexType)) {
430             print0(ucase ? "SPATIAL " : "spatial ");
431             indexTypePrinted = true;
432         }
433 
434         print0(ucase ? "INDEX" : "index");
435         if (x.getName() !is null) {
436             print(' ');
437             x.getName().accept(this);
438         }
439 
440         if (indexType !is null && !indexTypePrinted) {
441             print0(ucase ? " USING " : " using ");
442             print0(indexType);
443         }
444 
445         print('(');
446         for (int i = 0, size = x.getColumns().size(); i < size; ++i) {
447             if (i != 0) {
448                 print0(", ");
449             }
450             x.getColumns().get(i).accept(this);
451         }
452         print(')');
453         return false;
454     }
455 
456     public bool visit(MySqlCreateTableStatement x) {
457         if (isPrettyFormat() && x.hasBeforeComment()) {
458             printlnComments(x.getBeforeCommentsDirect());
459         }
460 
461         print0(ucase ? "CREATE " : "create ");
462 
463         foreach(SQLCommentHint hint ; x.getHints()) {
464             hint.accept(this);
465             print(' ');
466         }
467 
468         if (SQLCreateTableStatement.Type.GLOBAL_TEMPORARY == x.getType()) {
469             print0(ucase ? "TEMPORARY TABLE " : "temporary table ");
470         } else {
471             print0(ucase ? "TABLE " : "table ");
472         }
473 
474         if (x.isIfNotExiists()) {
475             print0(ucase ? "IF NOT EXISTS " : "if not exists ");
476         }
477 
478         printTableSourceExpr(x.getName());
479 
480         if (x.getLike() !is null) {
481             print0(ucase ? " LIKE " : " like ");
482             x.getLike().accept(this);
483         }
484 
485         printTableElements(x.getTableElementList());
486 
487         foreach(string key, SQLObject v ; x.getTableOptions()) {
488             // string key = option.getKey();
489 
490             print(' ');
491             print0(ucase ? key : toLower(key));
492 
493             if ("TABLESPACE" == key) {
494                 print(' ');
495                 v.accept(this);
496                 continue;
497             } else if ("UNION" == (key)) {
498                 print0(" = (");
499                 v.accept(this);
500                 print(')');
501                 continue;
502             }
503 
504             print0(" = ");
505 
506             v.accept(this);
507         }
508 
509         SQLExpr comment = x.getComment();
510         if (comment !is null) {
511             print0(ucase ? " COMMENT " : " comment ");
512             comment.accept(this);
513         }
514 
515         SQLPartitionBy partitionBy = x.getPartitioning();
516         if (partitionBy !is null) {
517             println();
518             print0(ucase ? "PARTITION BY " : "partition by ");
519             partitionBy.accept(this);
520         }
521 
522         SQLPartitionBy dbPartitionBy = x.getDbPartitionBy();
523         if (dbPartitionBy !is null) {
524             println();
525             print0(ucase ? "DBPARTITION BY " : "dbpartition by ");
526             dbPartitionBy.accept(this);
527         }
528 
529         SQLPartitionBy tbPartitionsBy = x.getTablePartitionBy();
530         if (tbPartitionsBy !is null) {
531             println();
532             print0(ucase ? "TBPARTITION BY " : "tbpartition by ");
533             tbPartitionsBy.accept(this);
534         }
535 
536         if (x.getTbpartitions() !is null) {
537             println();
538             print0(ucase ? "TBPARTITIONS " : "tbpartitions ");
539             x.getTbpartitions().accept(this);
540         }
541 
542         if (x.getTableGroup() !is null) {
543             println();
544             print0(ucase ? "TABLEGROUP " : "tablegroup ");
545             x.getTableGroup().accept(this);
546         }
547 
548         if (x.getSelect() !is null) {
549             println();
550             print0(ucase ? "AS" : "as");
551             println();
552             x.getSelect().accept(this);
553         }
554 
555         foreach(SQLCommentHint hint ; x.getOptionHints()) {
556             print(' ');
557             hint.accept(this);
558         }
559         return false;
560     }
561 
562     override
563     public void endVisit(MySqlKey x) {
564 
565     }
566 
567     override
568     public void endVisit(MySqlPrimaryKey x) {
569 
570     }
571 
572     override
573     public void endVisit(MysqlForeignKey x) {
574 
575     }
576 
577     override
578     public bool visit(MySqlKey x) {
579         if (x.isHasConstaint()) {
580             print0(ucase ? "CONSTRAINT " : "constraint ");
581             if (x.getName() !is null) {
582                 x.getName().accept(this);
583                 print(' ');
584             }
585         }
586 
587         print0(ucase ? "KEY" : "key");
588 
589         SQLName name = x.getName();
590         if (name !is null) {
591             print(' ');
592             name.accept(this);
593         }
594 
595         if (x.getIndexType() !is null) {
596             print0(ucase ? " USING " : " using ");
597             print0(x.getIndexType());
598         }
599 
600         print0(" (");
601 
602         for (int i = 0, size = x.getColumns().size(); i < size; ++i) {
603             if (i != 0) {
604                 print0(", ");
605             }
606             x.getColumns().get(i).accept(this);
607         }
608         print(')');
609 
610         return false;
611     }
612 
613     override
614     public bool visit(MySqlPrimaryKey x) {
615         if (x.getName() !is null) {
616             print0(ucase ? "CONSTRAINT " : "constraint ");
617             x.getName().accept(this);
618             print(' ');
619         }
620 
621         print0(ucase ? "PRIMARY KEY" : "primary key");
622 
623         if (x.getIndexType() !is null) {
624             print0(ucase ? " USING " : " using ");
625             print0(x.getIndexType());
626         }
627 
628         print0(" (");
629 
630         for (int i = 0, size = x.getColumns().size(); i < size; ++i) {
631             if (i != 0) {
632                 print0(", ");
633             }
634             x.getColumns().get(i).accept(this);
635         }
636         print(')');
637 
638         return false;
639     }
640 
641     override public bool visit(SQLCharExpr x) {
642         if (this.appender is null) {
643             return false;
644         }
645 
646         try {
647             if (this.parameterized) {
648                 this.appender.append('?');
649                 incrementReplaceCunt();
650                 if (this.parameters !is null) {
651                     ExportParameterVisitorUtils.exportParameter(this.parameters, x);
652                 }
653                 return false;
654             }
655 
656             this.appender.append('\'');
657 
658             string text = x.getText().value();
659 
660             bool hasSpecial = false;
661             for (int i = 0; i < text.length; ++i) {
662                 char ch = charAt(text, i);
663                 if (ch == '\'' || ch == '\\' || ch == '\0') {
664                     hasSpecial = true;
665                     break;
666                 }
667             }
668 
669             if (hasSpecial) {
670                 for (int i = 0; i < text.length; ++i) {
671                     char ch = charAt(text, i);
672                     if (ch == '\'') {
673                         appender.append('\'');
674                         appender.append('\'');
675                     } else if (ch == '\\') {
676                         appender.append('\\');
677                         appender.append('\\');
678                     } else if (ch == '\0') {
679                         appender.append('\\');
680                         appender.append('0');
681                     } else {
682                         appender.append(ch);
683                     }
684                 }
685             } else {
686                 appender.append(text);
687             }
688 
689             appender.append('\'');
690         return false;
691         } catch (Exception e) {
692             throw new Exception("println error", e);
693         }
694     }
695 
696     override public bool visit(SQLVariantRefExpr x) {
697         {
698             int index = x.getIndex();
699 
700             if (inputParameters !is null && index < inputParameters.size()) {
701 
702                 return super.visit(x);
703             }
704         }
705 
706         if (x.isGlobal()) {
707             print0("@@global.");
708         }else if(x.isSession()){
709             print0("@@session.");
710         }
711 
712         string varName = x.getName();
713         for (int i = 0; i < varName.length; ++i) {
714             char ch = charAt(varName, i);
715             if (ch == '\'') {
716                 if (varName.startsWith("@@") && i == 2) {
717                     print(ch);
718                 } else if (varName.startsWith("@") && i == 1) {
719                     print(ch);
720                 } else if (i != 0 && i != varName.length - 1) {
721                     print0("\\'");
722                 } else {
723                     print(ch);
724                 }
725             } else {
726                 print(ch);
727             }
728         }
729 
730         String collate = cast(String) x.getAttribute("COLLATE");
731         if (collate !is null) {
732             print0(ucase ? " COLLATE " : " collate ");
733             print0(collate);
734         }
735 
736         return false;
737     }
738 
739     override
740     public bool visit(MySqlExtractExpr x) {
741         print0(ucase ? "EXTRACT(" : "extract(");
742         print0(x.getUnit().name());
743         print0(ucase ? " FROM " : " from ");
744         x.getValue().accept(this);
745         print(')');
746         return false;
747     }
748 
749     override
750     public void endVisit(MySqlExtractExpr x) {
751 
752     }
753 
754     override
755     public void endVisit(MySqlMatchAgainstExpr x) {
756 
757     }
758 
759     override
760     public bool visit(MySqlMatchAgainstExpr x) {
761         print0(ucase ? "MATCH (" : "match (");
762         printAndAccept!SQLExpr((x.getColumns()), ", ");
763         print(')');
764 
765         print0(ucase ? " AGAINST (" : " against (");
766         x.getAgainst().accept(this);
767         if (x.getSearchModifier().name.length != 0) {
768             print(' ');
769             print0(ucase ? x.getSearchModifier().name : x.getSearchModifier().name_lcase);
770         }
771         print(')');
772 
773         return false;
774     }
775 
776     override
777     public void endVisit(MySqlPrepareStatement x) {
778     }
779 
780     override
781     public bool visit(MySqlPrepareStatement x) {
782         print0(ucase ? "PREPARE " : "prepare ");
783         x.getName().accept(this);
784         print0(ucase ? " FROM " : " from ");
785         x.getFrom().accept(this);
786         return false;
787     }
788 
789     override
790     public void endVisit(MySqlExecuteStatement x) {
791 
792     }
793 
794     override
795     public bool visit(MySqlExecuteStatement x) {
796         print0(ucase ? "EXECUTE " : "execute ");
797         x.getStatementName().accept(this);
798         if (x.getParameters().size() > 0) {
799             print0(ucase ? " USING " : " using ");
800             printAndAccept!SQLExpr((x.getParameters()), ", ");
801         }
802         return false;
803     }
804 
805     override
806     public void endVisit(MysqlDeallocatePrepareStatement x) {
807 
808     }
809 
810     public bool visit(MysqlDeallocatePrepareStatement x) {
811         print0(ucase ? "DEALLOCATE PREPARE " : "deallocate prepare ");
812         x.getStatementName().accept(this);
813         return false;
814     }
815 
816     override
817     public void endVisit(MySqlDeleteStatement x) {
818 
819     }
820 
821     override
822     public bool visit(MySqlDeleteStatement x) {
823         print0(ucase ? "DELETE " : "delete ");
824 
825         for (int i = 0, size = x.getHintsSize(); i < size; ++i) {
826             SQLCommentHint hint = x.getHints().get(i);
827             hint.accept(this);
828             print(' ');
829         }
830 
831         if (x.isLowPriority()) {
832             print0(ucase ? "LOW_PRIORITY " : "low_priority ");
833         }
834 
835         if (x.isQuick()) {
836             print0(ucase ? "QUICK " : "quick ");
837         }
838 
839         if (x.isIgnore()) {
840             print0(ucase ? "IGNORE " : "ignore ");
841         }
842 
843         if (x.isForceAllPartitions()) {
844             print0(ucase ? "FORCE ALL PARTITIONS " : "force all partitions ");
845         } else {
846             SQLName partition = x.getForcePartition();
847             if (partition !is null) {
848                 print0(ucase ? "FORCE PARTITION " : "force partition ");
849                 printExpr(partition);
850                 print(' ');
851             }
852         }
853 
854         SQLTableSource from = x.getFrom();
855         if (from is null) {
856             print0(ucase ? "FROM " : "from ");
857             x.getTableSource().accept(this);
858         } else {
859             x.getTableSource().accept(this);
860             println();
861             print0(ucase ? "FROM " : "from ");
862             from.accept(this);
863         }
864 
865         SQLTableSource using = x.getUsing();
866         if (using !is null) {
867             println();
868             print0(ucase ? "USING " : "using ");
869             using.accept(this);
870         }
871 
872         SQLExpr where = x.getWhere();
873         if (where !is null) {
874             println();
875             this.indentCount++;
876             print0(ucase ? "WHERE " : "where ");
877             printExpr(where);
878             this.indentCount--;
879         }
880 
881 
882         if (x.getOrderBy() !is null) {
883             println();
884             x.getOrderBy().accept(this);
885         }
886 
887         if (x.getLimit() !is null) {
888             println();
889             x.getLimit().accept(this);
890         }
891 
892         return false;
893     }
894 
895     override
896     public void endVisit(MySqlInsertStatement x) {
897 
898     }
899 
900     override
901     public bool visit(MySqlInsertStatement x) {
902         print0(ucase ? "INSERT " : "insert ");
903 
904         if (x.isLowPriority()) {
905             print0(ucase ? "LOW_PRIORITY " : "low_priority ");
906         }
907 
908         if (x.isDelayed()) {
909             print0(ucase ? "DELAYED " : "delayed ");
910         }
911 
912         if (x.isHighPriority()) {
913             print0(ucase ? "HIGH_PRIORITY " : "high_priority ");
914         }
915 
916         if (x.isIgnore()) {
917             print0(ucase ? "IGNORE " : "ignore ");
918         }
919 
920         if (x.isRollbackOnFail()) {
921             print0(ucase ? "ROLLBACK_ON_FAIL " : "rollback_on_fail ");
922         }
923 
924         print0(ucase ? "INTO " : "into ");
925 
926         SQLExprTableSource tableSource = x.getTableSource();
927         if (typeid(tableSource) == typeid(SQLExprTableSource)) {
928             visit(tableSource);
929         } else {
930             tableSource.accept(this);
931         }
932 
933         string columnsString = x.getColumnsString();
934         if (columnsString !is null) {
935             if (!isEnabled(VisitorFeature.OutputSkipInsertColumnsString)) {
936                 print0(columnsString);
937             }
938         } else {
939             List!(SQLExpr) columns = x.getColumns();
940             if (columns.size() > 0) {
941                 this.indentCount++;
942                 print0(" (");
943                 for (int i = 0, size = columns.size(); i < size; ++i) {
944                     if (i != 0) {
945                         if (i % 5 == 0) {
946                             println();
947                         }
948                         print0(", ");
949                     }
950 
951                     SQLExpr column = columns.get(i);
952                     SQLIdentifierExpr identifierExpr = cast(SQLIdentifierExpr)(column);
953                     if (identifierExpr !is null) {
954                         string name = identifierExpr.getName();
955                         if(isEnabled(VisitorFeature.OutputQuotedIdentifier)) {
956                             print0(_quotes ~ name ~ _quotes);
957                         } else {
958                             print0(name);
959                         }
960 
961                         // print0((cast(SQLIdentifierExpr) column).getName());
962                     } else {
963                         printExpr(column);
964                     }
965                 }
966                 print(')');
967                 this.indentCount--;
968             }
969         }
970 
971         List!(ValuesClause)  valuesList = x.getValuesList();
972         if (!valuesList.isEmpty()) {
973             println();
974             printValuesList(valuesList);
975         }
976 
977         if (x.getQuery() !is null) {
978             println();
979             x.getQuery().accept(this);
980         }
981 
982         List!(SQLExpr) duplicateKeyUpdate = x.getDuplicateKeyUpdate();
983         if (duplicateKeyUpdate.size() != 0) {
984             println();
985             print0(ucase ? "ON DUPLICATE KEY UPDATE " : "on duplicate key update ");
986             for (int i = 0, size = duplicateKeyUpdate.size(); i < size; ++i) {
987                 if (i != 0) {
988                     if (i % 5 == 0) {
989                         println();
990                     }
991                     print0(", ");
992                 }
993                 duplicateKeyUpdate.get(i).accept(this);
994             }
995         }
996 
997         return false;
998     }
999 
1000     protected void printValuesList(List!(ValuesClause) valuesList) {
1001 
1002         if (this.parameterized && valuesList.size() > 0) {
1003             print0(ucase ? "VALUES " : "values ");
1004             this.indentCount++;
1005             visit(valuesList.get(0));
1006             this.indentCount--;
1007             if (valuesList.size() > 1) {
1008                 this.incrementReplaceCunt();
1009             }
1010             return;
1011         }
1012 
1013         print0(ucase ? "VALUES " : "values ");
1014         if (valuesList.size() > 1) {
1015             this.indentCount++;
1016         }
1017         for (int i = 0, size = valuesList.size(); i < size; ++i) {
1018             if (i != 0) {
1019                 print(',');
1020                 println();
1021             }
1022 
1023             ValuesClause item = valuesList.get(i);
1024             visit(item);
1025         }
1026         if (valuesList.size() > 1) {
1027             this.indentCount--;
1028         }
1029     }
1030 
1031     override
1032     public void endVisit(MySqlLoadDataInFileStatement x) {
1033 
1034     }
1035 
1036     override
1037     public bool visit(MySqlLoadDataInFileStatement x) {
1038         print0(ucase ? "LOAD DATA " : "load data ");
1039 
1040         if (x.isLowPriority()) {
1041             print0(ucase ? "LOW_PRIORITY " : "low_priority ");
1042         }
1043 
1044         if (x.isConcurrent()) {
1045             print0(ucase ? "CONCURRENT " : "concurrent ");
1046         }
1047 
1048         if (x.isLocal()) {
1049             print0(ucase ? "LOCAL " : "local ");
1050         }
1051 
1052         print0(ucase ? "INFILE " : "infile ");
1053 
1054         x.getFileName().accept(this);
1055 
1056         if (x.isReplicate()) {
1057             print0(ucase ? " REPLACE " : " replace ");
1058         }
1059 
1060         if (x.isIgnore()) {
1061             print0(ucase ? " IGNORE " : " ignore ");
1062         }
1063 
1064         print0(ucase ? " INTO TABLE " : " into table ");
1065         x.getTableName().accept(this);
1066 
1067         if (x.getColumnsTerminatedBy() !is null || x.getColumnsEnclosedBy() !is null || x.getColumnsEscaped() !is null) {
1068             print0(ucase ? " COLUMNS" : " columns");
1069             if (x.getColumnsTerminatedBy() !is null) {
1070                 print0(ucase ? " TERMINATED BY " : " terminated by ");
1071                 x.getColumnsTerminatedBy().accept(this);
1072             }
1073 
1074             if (x.getColumnsEnclosedBy() !is null) {
1075                 if (x.isColumnsEnclosedOptionally()) {
1076                     print0(ucase ? " OPTIONALLY" : " optionally");
1077                 }
1078                 print0(ucase ? " ENCLOSED BY " : " enclosed by ");
1079                 x.getColumnsEnclosedBy().accept(this);
1080             }
1081 
1082             if (x.getColumnsEscaped() !is null) {
1083                 print0(ucase ? " ESCAPED BY " : " escaped by ");
1084                 x.getColumnsEscaped().accept(this);
1085             }
1086         }
1087 
1088         if (x.getLinesStartingBy() !is null || x.getLinesTerminatedBy() !is null) {
1089             print0(ucase ? " LINES" : " lines");
1090             if (x.getLinesStartingBy() !is null) {
1091                 print0(ucase ? " STARTING BY " : " starting by ");
1092                 x.getLinesStartingBy().accept(this);
1093             }
1094 
1095             if (x.getLinesTerminatedBy() !is null) {
1096                 print0(ucase ? " TERMINATED BY " : " terminated by ");
1097                 x.getLinesTerminatedBy().accept(this);
1098             }
1099         }
1100 
1101         if (x.getIgnoreLinesNumber() !is null) {
1102             print0(ucase ? " IGNORE " : " ignore ");
1103             x.getIgnoreLinesNumber().accept(this);
1104             print0(ucase ? " LINES" : " lines");
1105         }
1106 
1107         if (x.getColumns().size() != 0) {
1108             print0(" (");
1109             printAndAccept!SQLExpr((x.getColumns()), ", ");
1110             print(')');
1111         }
1112 
1113         if (x.getSetList().size() != 0) {
1114             print0(ucase ? " SET " : " set ");
1115             printAndAccept!SQLExpr((x.getSetList()), ", ");
1116         }
1117 
1118         return false;
1119     }
1120 
1121     override public bool visit(SQLReplaceStatement x) {
1122         print0(ucase ? "REPLACE " : "replace ");
1123 
1124         if (x.isLowPriority()) {
1125             print0(ucase ? "LOW_PRIORITY " : "low_priority ");
1126         }
1127 
1128         if (x.isDelayed()) {
1129             print0(ucase ? "DELAYED " : "delayed ");
1130         }
1131 
1132         print0(ucase ? "INTO " : "into ");
1133 
1134         printTableSourceExpr(x.getTableName());
1135 
1136         List!(SQLExpr) columns = x.getColumns();
1137         if (columns.size() > 0) {
1138             print0(" (");
1139             for (int i = 0, size = columns.size(); i < size; ++i) {
1140                 if (i != 0) {
1141                     print0(", ");
1142                 }
1143 
1144                 SQLExpr columnn = columns.get(i);
1145                 printExpr(columnn);
1146             }
1147             print(')');
1148         }
1149 
1150         List!(ValuesClause) valuesClauseList = x.getValuesList();
1151         if (valuesClauseList.size() != 0) {
1152             println();
1153             print0(ucase ? "VALUES " : "values ");
1154             int size = valuesClauseList.size();
1155             if (size == 0) {
1156                 print0("()");
1157             } else {
1158                 for (int i = 0; i < size; ++i) {
1159                     if (i != 0) {
1160                         print0(", ");
1161                     }
1162                     visit(valuesClauseList.get(i));
1163                 }
1164             }
1165         }
1166 
1167         SQLQueryExpr query = x.getQuery();
1168         if (query !is null) {
1169             visit(query);
1170         }
1171 
1172         return false;
1173     }
1174 
1175     override
1176     public bool visit(SQLStartTransactionStatement x) {
1177         print0(ucase ? "START TRANSACTION" : "start transaction");
1178         if (x.isConsistentSnapshot()) {
1179             print0(ucase ? " WITH CONSISTENT SNAPSHOT" : " with consistent snapshot");
1180         }
1181 
1182         if (x.getHints() !is null && x.getHints().size() > 0) {
1183             print(' ');
1184             printAndAccept!SQLCommentHint((x.getHints()), " ");
1185         }
1186 
1187         if (x.isBegin()) {
1188             print0(ucase ? " BEGIN" : " begin");
1189         }
1190 
1191         if (x.isWork()) {
1192             print0(ucase ? " WORK" : " work");
1193         }
1194 
1195         return false;
1196     }
1197 
1198     override public bool visit(SQLRollbackStatement x) {
1199         print0(ucase ? "ROLLBACK" : "rollback");
1200 
1201         if (x.getChain() !is null) {
1202             if (x.getChain().booleanValue()) {
1203                 print0(ucase ? " AND CHAIN" : " and chain");
1204             } else {
1205                 print0(ucase ? " AND NO CHAIN" : " and no chain");
1206             }
1207         }
1208 
1209         if (x.getRelease() !is null) {
1210             if (x.getRelease().booleanValue()) {
1211                 print0(ucase ? " AND RELEASE" : " and release");
1212             } else {
1213                 print0(ucase ? " AND NO RELEASE" : " and no release");
1214             }
1215         }
1216 
1217         if (x.getTo() !is null) {
1218             print0(ucase ? " TO " : " to ");
1219             x.getTo().accept(this);
1220         }
1221 
1222         return false;
1223     }
1224 
1225     override
1226     public void endVisit(MySqlShowColumnsStatement x) {
1227 
1228     }
1229 
1230     override
1231     public bool visit(MySqlShowColumnsStatement x) {
1232         if (x.isFull()) {
1233             print0(ucase ? "SHOW FULL COLUMNS" : "show full columns");
1234         } else {
1235             print0(ucase ? "SHOW COLUMNS" : "show columns");
1236         }
1237 
1238         if (x.getTable() !is null) {
1239             print0(ucase ? " FROM " : " from ");
1240             if (x.getDatabase() !is null) {
1241                 x.getDatabase().accept(this);
1242                 print('.');
1243             }
1244             x.getTable().accept(this);
1245         }
1246 
1247         if (x.getLike() !is null) {
1248             print0(ucase ? " LIKE " : " like ");
1249             x.getLike().accept(this);
1250         }
1251 
1252         if (x.getWhere() !is null) {
1253             print0(ucase ? " WHERE " : " where ");
1254             x.getWhere().accept(this);
1255         }
1256 
1257         return false;
1258     }
1259 
1260     override
1261     public bool visit(SQLShowTablesStatement x) {
1262         if (x.isFull()) {
1263             print0(ucase ? "SHOW FULL TABLES" : "show full tables");
1264         } else {
1265             print0(ucase ? "SHOW TABLES" : "show tables");
1266         }
1267 
1268         if (x.getDatabase() !is null) {
1269             print0(ucase ? " FROM " : " from ");
1270             x.getDatabase().accept(this);
1271         }
1272 
1273         if (x.getLike() !is null) {
1274             print0(ucase ? " LIKE " : " like ");
1275             x.getLike().accept(this);
1276         }
1277 
1278         if (x.getWhere() !is null) {
1279             print0(ucase ? " WHERE " : " where ");
1280             x.getWhere().accept(this);
1281         }
1282 
1283         return false;
1284     }
1285 
1286     override
1287     public void endVisit(MySqlShowDatabasesStatement x) {
1288 
1289     }
1290 
1291     override
1292     public bool visit(MySqlShowDatabasesStatement x) {
1293         print0(ucase ? "SHOW DATABASES" : "show databases");
1294 
1295         if (x.getLike() !is null) {
1296             print0(ucase ? " LIKE " : " like ");
1297             x.getLike().accept(this);
1298         }
1299 
1300         if (x.getWhere() !is null) {
1301             print0(ucase ? " WHERE " : " where ");
1302             x.getWhere().accept(this);
1303         }
1304 
1305         return false;
1306     }
1307 
1308     override
1309     public void endVisit(MySqlShowWarningsStatement x) {
1310 
1311     }
1312 
1313     override
1314     public bool visit(MySqlShowWarningsStatement x) {
1315         if (x.isCount()) {
1316             print0(ucase ? "SHOW COUNT(*) WARNINGS" : "show count(*) warnings");
1317         } else {
1318             print0(ucase ? "SHOW WARNINGS" : "show warnings");
1319             if (x.getLimit() !is null) {
1320                 print(' ');
1321                 x.getLimit().accept(this);
1322             }
1323         }
1324 
1325         return false;
1326     }
1327 
1328     override
1329     public void endVisit(MySqlShowStatusStatement x) {
1330 
1331     }
1332 
1333     override
1334     public bool visit(MySqlShowStatusStatement x) {
1335         print0(ucase ? "SHOW " : "show ");
1336 
1337         if (x.isGlobal()) {
1338             print0(ucase ? "GLOBAL " : "global ");
1339         }
1340 
1341         if (x.isSession()) {
1342             print0(ucase ? "SESSION " : "session ");
1343         }
1344 
1345         print0(ucase ? "STATUS" : "status");
1346 
1347         if (x.getLike() !is null) {
1348             print0(ucase ? " LIKE " : " like ");
1349             x.getLike().accept(this);
1350         }
1351 
1352         if (x.getWhere() !is null) {
1353             print0(ucase ? " WHERE " : " where ");
1354             x.getWhere().accept(this);
1355         }
1356 
1357         return false;
1358     }
1359 
1360     override
1361     public void endVisit(MySqlLoadXmlStatement x) {
1362 
1363     }
1364 
1365     override
1366     public bool visit(MySqlLoadXmlStatement x) {
1367         print0(ucase ? "LOAD XML " : "load xml ");
1368 
1369         if (x.isLowPriority()) {
1370             print0(ucase ? "LOW_PRIORITY " : "low_priority ");
1371         }
1372 
1373         if (x.isConcurrent()) {
1374             print0(ucase ? "CONCURRENT " : "concurrent ");
1375         }
1376 
1377         if (x.isLocal()) {
1378             print0(ucase ? "LOCAL " : "local ");
1379         }
1380 
1381         print0(ucase ? "INFILE " : "infile ");
1382 
1383         x.getFileName().accept(this);
1384 
1385         if (x.isReplicate()) {
1386             print0(ucase ? " REPLACE " : " replace ");
1387         }
1388 
1389         if (x.isIgnore()) {
1390             print0(ucase ? " IGNORE " : " ignore ");
1391         }
1392 
1393         print0(ucase ? " INTO TABLE " : " into table ");
1394         x.getTableName().accept(this);
1395 
1396         if (x.getCharset() !is null) {
1397             print0(ucase ? " CHARSET " : " charset ");
1398             print0(x.getCharset());
1399         }
1400 
1401         if (x.getRowsIdentifiedBy() !is null) {
1402             print0(ucase ? " ROWS IDENTIFIED BY " : " rows identified by ");
1403             x.getRowsIdentifiedBy().accept(this);
1404         }
1405 
1406         if (x.getSetList().size() != 0) {
1407             print0(ucase ? " SET " : " set ");
1408             printAndAccept!SQLExpr((x.getSetList()), ", ");
1409         }
1410 
1411         return false;
1412     }
1413 
1414     override
1415     public void endVisit(CobarShowStatus x) {
1416 
1417     }
1418 
1419     override
1420     public bool visit(CobarShowStatus x) {
1421         print0(ucase ? "SHOW COBAR_STATUS" : "show cobar_status");
1422         return false;
1423     }
1424 
1425     override
1426     public void endVisit(MySqlKillStatement x) {
1427 
1428     }
1429 
1430     override
1431     public bool visit(MySqlKillStatement x) {
1432         if (MySqlKillStatement.Type.CONNECTION == (x.getType())) {
1433             print0(ucase ? "KILL CONNECTION " : "kill connection ");
1434         } else if (MySqlKillStatement.Type.QUERY == (x.getType())) {
1435             print0(ucase ? "KILL QUERY " : "kill query ");
1436         } else {
1437             print0(ucase ? "KILL " : "kill ");
1438         }
1439 
1440         printAndAccept!SQLExpr((x.getThreadIds()), ", ");
1441         return false;
1442     }
1443 
1444     override
1445     public void endVisit(MySqlBinlogStatement x) {
1446 
1447     }
1448 
1449     override
1450     public bool visit(MySqlBinlogStatement x) {
1451         print0(ucase ? "BINLOG " : "binlog ");
1452         x.getExpr().accept(this);
1453         return false;
1454     }
1455 
1456     override
1457     public void endVisit(MySqlResetStatement x) {
1458 
1459     }
1460 
1461     override
1462     public bool visit(MySqlResetStatement x) {
1463         print0(ucase ? "RESET " : "reset ");
1464         for (int i = 0; i < x.getOptions().size(); ++i) {
1465             if (i != 0) {
1466                 print0(", ");
1467             }
1468             print0(x.getOptions().get(i));
1469         }
1470         return false;
1471     }
1472 
1473     override
1474     public void endVisit(MySqlCreateUserStatement x) {
1475 
1476     }
1477 
1478     override
1479     public bool visit(MySqlCreateUserStatement x) {
1480         print0(ucase ? "CREATE USER " : "create user ");
1481         printAndAccept!(MySqlCreateUserStatement.UserSpecification)((x.getUsers()), ", ");
1482         return false;
1483     }
1484 
1485     override
1486     public void endVisit(MySqlCreateUserStatement.UserSpecification x) {
1487 
1488     }
1489 
1490     override
1491     public bool visit(MySqlCreateUserStatement.UserSpecification x) {
1492         x.getUser().accept(this);
1493 
1494         if (x.getPassword() !is null) {
1495             print0(ucase ? " IDENTIFIED BY " : " identified by ");
1496             if (x.isPasswordHash()) {
1497                 print0(ucase ? "PASSWORD " : "password ");
1498             }
1499             x.getPassword().accept(this);
1500         }
1501 
1502         if (x.getAuthPlugin() !is null) {
1503             print0(ucase ? " IDENTIFIED WITH " : " identified with ");
1504             x.getAuthPlugin().accept(this);
1505         }
1506         return false;
1507     }
1508 
1509     override
1510     public void endVisit(MySqlPartitionByKey x) {
1511 
1512     }
1513 
1514     override
1515     public bool visit(MySqlPartitionByKey x) {
1516         if (x.isLinear()) {
1517             print0(ucase ? "LINEAR KEY (" : "linear key (");
1518         } else {
1519             print0(ucase ? "KEY (" : "key (");
1520         }
1521         printAndAccept!SQLExpr((x.getColumns()), ", ");
1522         print(')');
1523 
1524         printPartitionsCountAndSubPartitions(x);
1525         return false;
1526     }
1527 
1528 
1529     //
1530 
1531     override
1532     public void endVisit(MySqlSelectQueryBlock x) {
1533 
1534     }
1535 
1536     override
1537     public bool visit(MySqlOutFileExpr x) {
1538         print0(ucase ? "OUTFILE " : "outfile ");
1539         x.getFile().accept(this);
1540 
1541         if (x.getCharset() !is null) {
1542             print0(ucase ? " CHARACTER SET " : " character set ");
1543             print0(x.getCharset());
1544         }
1545 
1546         if (x.getColumnsTerminatedBy() !is null || x.getColumnsEnclosedBy() !is null || x.getColumnsEscaped() !is null) {
1547             print0(ucase ? " COLUMNS" : " columns");
1548             if (x.getColumnsTerminatedBy() !is null) {
1549                 print0(ucase ? " TERMINATED BY " : " terminated by ");
1550                 x.getColumnsTerminatedBy().accept(this);
1551             }
1552 
1553             if (x.getColumnsEnclosedBy() !is null) {
1554                 if (x.isColumnsEnclosedOptionally()) {
1555                     print0(ucase ? " OPTIONALLY" : " optionally");
1556                 }
1557                 print0(ucase ? " ENCLOSED BY " : " enclosed by ");
1558                 x.getColumnsEnclosedBy().accept(this);
1559             }
1560 
1561             if (x.getColumnsEscaped() !is null) {
1562                 print0(ucase ? " ESCAPED BY " : " escaped by ");
1563                 x.getColumnsEscaped().accept(this);
1564             }
1565         }
1566 
1567         if (x.getLinesStartingBy() !is null || x.getLinesTerminatedBy() !is null) {
1568             print0(ucase ? " LINES" : " lines");
1569             if (x.getLinesStartingBy() !is null) {
1570                 print0(ucase ? " STARTING BY " : " starting by ");
1571                 x.getLinesStartingBy().accept(this);
1572             }
1573 
1574             if (x.getLinesTerminatedBy() !is null) {
1575                 print0(ucase ? " TERMINATED BY " : " terminated by ");
1576                 x.getLinesTerminatedBy().accept(this);
1577             }
1578         }
1579 
1580         return false;
1581     }
1582 
1583     override
1584     public void endVisit(MySqlOutFileExpr x) {
1585 
1586     }
1587 
1588     override
1589     public bool visit(MySqlExplainStatement x) {
1590         string name = x.isDescribe() ? "desc" : "explain";
1591         print0(ucase ? toUpper(name) : name);
1592         print(' ');
1593 
1594         // tbl_name [col_name | wild]
1595         if (x.getTableName() !is null) {
1596             x.getTableName().accept(this);
1597             if (x.getColumnName() !is null) {
1598                 print(' ');
1599                 x.getColumnName().accept(this);
1600             } else if (x.getWild() !is null) {
1601                 print(' ');
1602                 x.getWild().accept(this);
1603             }
1604         } else {
1605             // [explain_type]
1606             string type = x.getType();
1607             if (type !is null) {
1608                 print0(type);
1609                 print(' ');
1610                 if ("format".equalsIgnoreCase(type)) {
1611                     print0("= ");
1612                     print0(x.getFormat());
1613                     print(' ');
1614                 }
1615             }
1616 
1617             // {explainable_stmt | FOR CONNECTION connection_id}
1618             if (x.getConnectionId() !is null) {
1619                 print0(ucase ? "FOR CONNECTION " : "for connection ");
1620                 x.getConnectionId().accept(this);
1621             } else {
1622                 x.getStatement().accept(this);
1623             }
1624         }
1625 
1626         return false;
1627     }
1628 
1629     override
1630     public void endVisit(MySqlExplainStatement x) {
1631 
1632     }
1633 
1634     override
1635     public bool visit(MySqlUpdateStatement x) {
1636         List!(SQLExpr) returning = x.getReturning();
1637         if (returning !is null && returning.size() > 0) {
1638             print0(ucase ? "SELECT " : "select ");
1639             printAndAccept!SQLExpr((returning), ", ");
1640             println();
1641             print0(ucase ? "FROM " : "from ");
1642         }
1643 
1644         print0(ucase ? "UPDATE " : "update ");
1645 
1646         if (x.isLowPriority()) {
1647             print0(ucase ? "LOW_PRIORITY " : "low_priority ");
1648         }
1649 
1650         if (x.isIgnore()) {
1651             print0(ucase ? "IGNORE " : "ignore ");
1652         }
1653 
1654 
1655         if (x.getHints() !is null && x.getHints().size() > 0) {
1656             printAndAccept!SQLHint((x.getHints()), " ");
1657             print0(" ");
1658         }
1659 
1660         if (x.isCommitOnSuccess()) {
1661             print0(ucase ? "COMMIT_ON_SUCCESS " : "commit_on_success ");
1662         }
1663 
1664         if (x.isRollBackOnFail()) {
1665             print0(ucase ? "ROLLBACK_ON_FAIL " : "rollback_on_fail ");
1666         }
1667 
1668         if (x.isQueryOnPk()) {
1669             print0(ucase ? "QUEUE_ON_PK " : "queue_on_pk ");
1670         }
1671 
1672         SQLExpr targetAffectRow = x.getTargetAffectRow();
1673         if (targetAffectRow !is null) {
1674             print0(ucase ? "TARGET_AFFECT_ROW " : "target_affect_row ");
1675             printExpr(targetAffectRow);
1676             print(' ');
1677         }
1678 
1679         if (x.isForceAllPartitions()) {
1680             print0(ucase ? "FORCE ALL PARTITIONS " : "force all partitions ");
1681         } else {
1682             SQLName partition = x.getForcePartition();
1683             if (partition !is null) {
1684                 print0(ucase ? "FORCE PARTITION " : "force partition ");
1685                 printExpr(partition);
1686                 print(' ');
1687             }
1688         }
1689 
1690         printTableSource(x.getTableSource());
1691 
1692         println();
1693         print0(ucase ? "SET " : "set ");
1694         List!(SQLUpdateSetItem) items = x.getItems();
1695         for (int i = 0, size = items.size(); i < size; ++i) {
1696             if (i != 0) {
1697                 print0(", ");
1698             }
1699             SQLUpdateSetItem item = items.get(i);
1700             visit(item);
1701         }
1702 
1703         SQLExpr where = x.getWhere();
1704         if (where !is null) {
1705             println();
1706             indentCount++;
1707             print0(ucase ? "WHERE " : "where ");
1708             printExpr(where);
1709             indentCount--;
1710         }
1711 
1712         SQLOrderBy orderBy = x.getOrderBy();
1713         if (orderBy !is null) {
1714             println();
1715             visit(orderBy);
1716         }
1717 
1718         SQLLimit limit = x.getLimit();
1719         if (limit !is null) {
1720             println();
1721             visit(limit);
1722         }
1723         return false;
1724     }
1725 
1726     override
1727     public void endVisit(MySqlUpdateStatement x) {
1728 
1729     }
1730 
1731     override
1732     public bool visit(MySqlSetTransactionStatement x) {
1733         if (x.getGlobal() is null) {
1734             print0(ucase ? "SET TRANSACTION " : "set transaction ");
1735         } else if (x.getGlobal().booleanValue()) {
1736             print0(ucase ? "SET GLOBAL TRANSACTION " : "set global transaction ");
1737         } else {
1738             print0(ucase ? "SET SESSION TRANSACTION " : "set session transaction ");
1739         }
1740 
1741         if (x.getIsolationLevel() !is null) {
1742             print0(ucase ? "ISOLATION LEVEL " : "isolation level ");
1743             print0(x.getIsolationLevel());
1744         }
1745 
1746         if (x.getAccessModel() !is null) {
1747             print0(ucase ? "READ " : "read ");
1748             print0(x.getAccessModel());
1749         }
1750 
1751         return false;
1752     }
1753 
1754     override
1755     public void endVisit(MySqlSetTransactionStatement x) {
1756 
1757     }
1758 //
1759 //    override
1760 //    public bool visit(MySqlSetNamesStatement x) {
1761 //        print0(ucase ? "SET NAMES " : "set names ");
1762 //        if (x.isDefault()) {
1763 //            print0(ucase ? "DEFAULT" : "default");
1764 //        } else {
1765 //            print0(x.getCharSet());
1766 //            if (x.getCollate() !is null) {
1767 //                print0(ucase ? " COLLATE " : " collate ");
1768 //                print0(x.getCollate());
1769 //            }
1770 //        }
1771 //        return false;
1772 //    }
1773 
1774 //    public bool visit(MySqlSetCharSetStatement x) {
1775 //        print0(ucase ? "SET CHARACTER SET " : "set character set ");
1776 //        if (x.isDefault()) {
1777 //            print0(ucase ? "DEFAULT" : "default");
1778 //        } else {
1779 //            print0(x.getCharSet());
1780 //            if (x.getCollate() !is null) {
1781 //                print0(ucase ? " COLLATE " : " collate ");
1782 //                print0(x.getCollate());
1783 //            }
1784 //        }
1785 //        return false;
1786 //    }
1787 
1788     override
1789     public void endVisit(MySqlShowAuthorsStatement x) {
1790 
1791     }
1792 
1793     override
1794     public bool visit(MySqlShowAuthorsStatement x) {
1795         print0(ucase ? "SHOW AUTHORS" : "show authors");
1796         return false;
1797     }
1798 
1799     override
1800     public void endVisit(MySqlShowBinaryLogsStatement x) {
1801 
1802     }
1803 
1804     override
1805     public bool visit(MySqlShowBinaryLogsStatement x) {
1806         print0(ucase ? "SHOW BINARY LOGS" : "show binary logs");
1807         return false;
1808     }
1809 
1810     override
1811     public bool visit(MySqlShowMasterLogsStatement x) {
1812         print0(ucase ? "SHOW MASTER LOGS" : "show master logs");
1813         return false;
1814     }
1815 
1816     override
1817     public void endVisit(MySqlShowMasterLogsStatement x) {
1818 
1819     }
1820 
1821     override
1822     public bool visit(MySqlShowCollationStatement x) {
1823         print0(ucase ? "SHOW COLLATION" : "show collation");
1824         if (x.getPattern() !is null) {
1825             print0(ucase ? " LIKE " : " like ");
1826             x.getPattern().accept(this);
1827         }
1828         if (x.getWhere() !is null) {
1829             print0(ucase ? " WHERE " : " where ");
1830             x.getWhere().accept(this);
1831         }
1832         return false;
1833     }
1834 
1835     override
1836     public void endVisit(MySqlShowCollationStatement x) {
1837 
1838     }
1839 
1840     override
1841     public bool visit(MySqlShowBinLogEventsStatement x) {
1842         print0(ucase ? "SHOW BINLOG EVENTS" : "show binlog events");
1843         if (x.getIn() !is null) {
1844             print0(ucase ? " IN " : " in ");
1845             x.getIn().accept(this);
1846         }
1847         if (x.getFrom() !is null) {
1848             print0(ucase ? " FROM " : " from ");
1849             x.getFrom().accept(this);
1850         }
1851         if (x.getLimit() !is null) {
1852             print(' ');
1853             x.getLimit().accept(this);
1854         }
1855         return false;
1856     }
1857 
1858     override
1859     public void endVisit(MySqlShowBinLogEventsStatement x) {
1860 
1861     }
1862 
1863     override
1864     public bool visit(MySqlShowCharacterSetStatement x) {
1865         print0(ucase ? "SHOW CHARACTER SET" : "show character set");
1866         if (x.getPattern() !is null) {
1867             print0(ucase ? " LIKE " : " like ");
1868             x.getPattern().accept(this);
1869         }
1870         if (x.getWhere() !is null) {
1871             print0(ucase ? " WHERE " : " where ");
1872             x.getWhere().accept(this);
1873         }
1874         return false;
1875     }
1876 
1877     override
1878     public void endVisit(MySqlShowCharacterSetStatement x) {
1879 
1880     }
1881 
1882     override
1883     public bool visit(MySqlShowContributorsStatement x) {
1884         print0(ucase ? "SHOW CONTRIBUTORS" : "show contributors");
1885         return false;
1886     }
1887 
1888     override
1889     public void endVisit(MySqlShowContributorsStatement x) {
1890 
1891     }
1892 
1893     override
1894     public bool visit(MySqlShowCreateDatabaseStatement x) {
1895         print0(ucase ? "SHOW CREATE DATABASE " : "show create database ");
1896         x.getDatabase().accept(this);
1897         return false;
1898     }
1899 
1900     override
1901     public void endVisit(MySqlShowCreateDatabaseStatement x) {
1902 
1903     }
1904 
1905     override
1906     public bool visit(MySqlShowCreateEventStatement x) {
1907         print0(ucase ? "SHOW CREATE EVENT " : "show create event ");
1908         x.getEventName().accept(this);
1909         return false;
1910     }
1911 
1912     override
1913     public void endVisit(MySqlShowCreateEventStatement x) {
1914 
1915     }
1916 
1917     override
1918     public bool visit(MySqlShowCreateFunctionStatement x) {
1919         print0(ucase ? "SHOW CREATE FUNCTION " : "show create function ");
1920         x.getName().accept(this);
1921         return false;
1922     }
1923 
1924     override
1925     public void endVisit(MySqlShowCreateFunctionStatement x) {
1926 
1927     }
1928 
1929     override
1930     public bool visit(MySqlShowCreateProcedureStatement x) {
1931         print0(ucase ? "SHOW CREATE PROCEDURE " : "show create procedure ");
1932         x.getName().accept(this);
1933         return false;
1934     }
1935 
1936     override
1937     public void endVisit(MySqlShowCreateProcedureStatement x) {
1938 
1939     }
1940 
1941     override
1942     public bool visit(MySqlShowCreateTableStatement x) {
1943         print0(ucase ? "SHOW CREATE TABLE " : "show create table ");
1944         x.getName().accept(this);
1945         return false;
1946     }
1947 
1948     override
1949     public void endVisit(MySqlShowCreateTableStatement x) {
1950 
1951     }
1952 
1953     override
1954     public bool visit(MySqlShowCreateTriggerStatement x) {
1955         print0(ucase ? "SHOW CREATE TRIGGER " : "show create trigger ");
1956         x.getName().accept(this);
1957         return false;
1958     }
1959 
1960     override
1961     public void endVisit(MySqlShowCreateTriggerStatement x) {
1962 
1963     }
1964 
1965     override
1966     public bool visit(MySqlShowCreateViewStatement x) {
1967         print0(ucase ? "SHOW CREATE VIEW " : "show create view ");
1968         x.getName().accept(this);
1969         return false;
1970     }
1971 
1972     override
1973     public void endVisit(MySqlShowCreateViewStatement x) {
1974 
1975     }
1976 
1977     override
1978     public bool visit(MySqlShowEngineStatement x) {
1979         print0(ucase ? "SHOW ENGINE " : "show engine ");
1980         x.getName().accept(this);
1981         print(' ');
1982         print0(x.getOption().name());
1983         return false;
1984     }
1985 
1986     override
1987     public void endVisit(MySqlShowEngineStatement x) {
1988 
1989     }
1990 
1991     override
1992     public bool visit(MySqlShowEventsStatement x) {
1993         print0(ucase ? "SHOW EVENTS" : "show events");
1994         if (x.getSchema() !is null) {
1995             print0(ucase ? " FROM " : " from ");
1996             x.getSchema().accept(this);
1997         }
1998 
1999         if (x.getLike() !is null) {
2000             print0(ucase ? " LIKE " : " like ");
2001             x.getLike().accept(this);
2002         }
2003 
2004         if (x.getWhere() !is null) {
2005             print0(ucase ? " WHERE " : " where ");
2006             x.getWhere().accept(this);
2007         }
2008 
2009         return false;
2010     }
2011 
2012     override
2013     public void endVisit(MySqlShowEventsStatement x) {
2014 
2015     }
2016 
2017     override
2018     public bool visit(MySqlShowFunctionCodeStatement x) {
2019         print0(ucase ? "SHOW FUNCTION CODE " : "show function code ");
2020         x.getName().accept(this);
2021         return false;
2022     }
2023 
2024     override
2025     public void endVisit(MySqlShowFunctionCodeStatement x) {
2026 
2027     }
2028 
2029     override
2030     public bool visit(MySqlShowFunctionStatusStatement x) {
2031         print0(ucase ? "SHOW FUNCTION STATUS" : "show function status");
2032         if (x.getLike() !is null) {
2033             print0(ucase ? " LIKE " : " like ");
2034             x.getLike().accept(this);
2035         }
2036 
2037         if (x.getWhere() !is null) {
2038             print0(ucase ? " WHERE " : " where ");
2039             x.getWhere().accept(this);
2040         }
2041 
2042         return false;
2043     }
2044 
2045     override
2046     public void endVisit(MySqlShowFunctionStatusStatement x) {
2047 
2048     }
2049 
2050     override
2051     public bool visit(MySqlShowEnginesStatement x) {
2052         if (x.isStorage()) {
2053             print0(ucase ? "SHOW STORAGE ENGINES" : "show storage engines");
2054         } else {
2055             print0(ucase ? "SHOW ENGINES" : "show engines");
2056         }
2057         return false;
2058     }
2059 
2060     override
2061     public void endVisit(MySqlShowEnginesStatement x) {
2062 
2063     }
2064 
2065     override
2066     public bool visit(MySqlShowErrorsStatement x) {
2067         if (x.isCount()) {
2068             print0(ucase ? "SHOW COUNT(*) ERRORS" : "show count(*) errors");
2069         } else {
2070             print0(ucase ? "SHOW ERRORS" : "show errors");
2071             if (x.getLimit() !is null) {
2072                 print(' ');
2073                 x.getLimit().accept(this);
2074             }
2075         }
2076         return false;
2077     }
2078 
2079     override
2080     public void endVisit(MySqlShowErrorsStatement x) {
2081 
2082     }
2083 
2084     override
2085     public bool visit(MySqlShowGrantsStatement x) {
2086         print0(ucase ? "SHOW GRANTS" : "show grants");
2087         if (x.getUser() !is null) {
2088             print0(ucase ? " FOR " : " for ");
2089             x.getUser().accept(this);
2090         }
2091         return false;
2092     }
2093 
2094     override
2095     public void endVisit(MySqlShowGrantsStatement x) {
2096 
2097     }
2098 
2099     override
2100     public bool visit(MySqlUserName x) {
2101         print0(x.getUserName());
2102 
2103         string host = x.getHost();
2104         if (host !is null) {
2105             print('@');
2106             print0(host);
2107         }
2108 
2109         string identifiedBy = x.getIdentifiedBy();
2110         if (identifiedBy !is null) {
2111             print0(ucase ? " IDENTIFIED BY '" : " identified by '");
2112             print0(identifiedBy);
2113             print('\'');
2114         }
2115 
2116         return false;
2117     }
2118 
2119     override
2120     public void endVisit(MySqlUserName x) {
2121 
2122     }
2123 
2124     override
2125     public bool visit(MySqlShowIndexesStatement x) {
2126         print0(ucase ? "SHOW INDEX" : "show index");
2127 
2128         if (x.getTable() !is null) {
2129             print0(ucase ? " FROM " : " from ");
2130             if (x.getDatabase() !is null) {
2131                 x.getDatabase().accept(this);
2132                 print('.');
2133             }
2134             x.getTable().accept(this);
2135         }
2136 
2137         if (x.getHints() !is null && x.getHints().size() > 0) {
2138             print(' ');
2139             printAndAccept!SQLCommentHint((x.getHints()), " ");
2140         }
2141 
2142         return false;
2143     }
2144 
2145     override
2146     public void endVisit(MySqlShowIndexesStatement x) {
2147 
2148     }
2149 
2150     override
2151     public bool visit(MySqlShowKeysStatement x) {
2152         print0(ucase ? "SHOW KEYS" : "show keys");
2153 
2154         if (x.getTable() !is null) {
2155             print0(ucase ? " FROM " : " from ");
2156             if (x.getDatabase() !is null) {
2157                 x.getDatabase().accept(this);
2158                 print('.');
2159             }
2160             x.getTable().accept(this);
2161         }
2162         return false;
2163     }
2164 
2165     override
2166     public void endVisit(MySqlShowKeysStatement x) {
2167 
2168     }
2169 
2170     override
2171     public bool visit(MySqlShowMasterStatusStatement x) {
2172         print0(ucase ? "SHOW MASTER STATUS" : "show master status");
2173         return false;
2174     }
2175 
2176     override
2177     public void endVisit(MySqlShowMasterStatusStatement x) {
2178 
2179     }
2180 
2181     override
2182     public bool visit(MySqlShowOpenTablesStatement x) {
2183         print0(ucase ? "SHOW OPEN TABLES" : "show open tables");
2184 
2185         if (x.getDatabase() !is null) {
2186             print0(ucase ? " FROM " : " from ");
2187             x.getDatabase().accept(this);
2188         }
2189 
2190         if (x.getLike() !is null) {
2191             print0(ucase ? " LIKE " : " like ");
2192             x.getLike().accept(this);
2193         }
2194 
2195         if (x.getWhere() !is null) {
2196             print0(ucase ? " WHERE " : " where ");
2197             x.getWhere().accept(this);
2198         }
2199 
2200         return false;
2201     }
2202 
2203     override
2204     public void endVisit(MySqlShowOpenTablesStatement x) {
2205 
2206     }
2207 
2208     override
2209     public bool visit(MySqlShowPluginsStatement x) {
2210         print0(ucase ? "SHOW PLUGINS" : "show plugins");
2211         return false;
2212     }
2213 
2214     override
2215     public void endVisit(MySqlShowPluginsStatement x) {
2216 
2217     }
2218 
2219     override
2220     public bool visit(MySqlShowPrivilegesStatement x) {
2221         print0(ucase ? "SHOW PRIVILEGES" : "show privileges");
2222         return false;
2223     }
2224 
2225     override
2226     public void endVisit(MySqlShowPrivilegesStatement x) {
2227 
2228     }
2229 
2230     override
2231     public bool visit(MySqlShowProcedureCodeStatement x) {
2232         print0(ucase ? "SHOW PROCEDURE CODE " : "show procedure code ");
2233         x.getName().accept(this);
2234         return false;
2235     }
2236 
2237     override
2238     public void endVisit(MySqlShowProcedureCodeStatement x) {
2239 
2240     }
2241 
2242     override
2243     public bool visit(MySqlShowProcedureStatusStatement x) {
2244         print0(ucase ? "SHOW PROCEDURE STATUS" : "show procedure status");
2245         if (x.getLike() !is null) {
2246             print0(ucase ? " LIKE " : " like ");
2247             x.getLike().accept(this);
2248         }
2249 
2250         if (x.getWhere() !is null) {
2251             print0(ucase ? " WHERE " : " where ");
2252             x.getWhere().accept(this);
2253         }
2254         return false;
2255     }
2256 
2257     override
2258     public void endVisit(MySqlShowProcedureStatusStatement x) {
2259 
2260     }
2261 
2262     override
2263     public bool visit(MySqlShowProcessListStatement x) {
2264         if (x.isFull()) {
2265             print0(ucase ? "SHOW FULL PROCESSLIST" : "show full processlist");
2266         } else {
2267             print0(ucase ? "SHOW PROCESSLIST" : "show processlist");
2268         }
2269         return false;
2270     }
2271 
2272     override
2273     public void endVisit(MySqlShowProcessListStatement x) {
2274 
2275     }
2276 
2277     override
2278     public bool visit(MySqlShowProfileStatement x) {
2279         print0(ucase ? "SHOW PROFILE" : "show profile");
2280         for (int i = 0; i < x.getTypes().size(); ++i) {
2281             if (i == 0) {
2282                 print(' ');
2283             } else {
2284                 print0(", ");
2285             }
2286             print0(x.getTypes().get(i));
2287         }
2288 
2289         if (x.getForQuery() !is null) {
2290             print0(ucase ? " FOR QUERY " : " for query ");
2291             x.getForQuery().accept(this);
2292         }
2293 
2294         if (x.getLimit() !is null) {
2295             print(' ');
2296             x.getLimit().accept(this);
2297         }
2298         return false;
2299     }
2300 
2301     override
2302     public void endVisit(MySqlShowProfileStatement x) {
2303 
2304     }
2305 
2306     override
2307     public bool visit(MySqlShowProfilesStatement x) {
2308         print0(ucase ? "SHOW PROFILES" : "show profiles");
2309         return false;
2310     }
2311 
2312     override
2313     public void endVisit(MySqlShowProfilesStatement x) {
2314 
2315     }
2316 
2317     override
2318     public bool visit(MySqlShowRelayLogEventsStatement x) {
2319         print0("SHOW RELAYLOG EVENTS");
2320 
2321         if (x.getLogName() !is null) {
2322             print0(ucase ? " IN " : " in ");
2323             x.getLogName().accept(this);
2324         }
2325 
2326         if (x.getFrom() !is null) {
2327             print0(ucase ? " FROM " : " from ");
2328             x.getFrom().accept(this);
2329         }
2330 
2331         if (x.getLimit() !is null) {
2332             print(' ');
2333             x.getLimit().accept(this);
2334         }
2335 
2336         return false;
2337     }
2338 
2339     override
2340     public void endVisit(MySqlShowRelayLogEventsStatement x) {
2341 
2342     }
2343 
2344     override
2345     public bool visit(MySqlShowSlaveHostsStatement x) {
2346         print0(ucase ? "SHOW SLAVE HOSTS" : "show slave hosts");
2347         return false;
2348     }
2349 
2350     override
2351     public void endVisit(MySqlShowSlaveHostsStatement x) {
2352 
2353     }
2354 
2355     override
2356     public bool visit(MySqlShowSlaveStatusStatement x) {
2357         print0(ucase ? "SHOW SLAVE STATUS" : "show slave status");
2358         return false;
2359     }
2360 
2361     override
2362     public void endVisit(MySqlShowSlaveStatusStatement x) {
2363 
2364     }
2365 
2366     override
2367     public bool visit(MySqlShowTableStatusStatement x) {
2368         print0(ucase ? "SHOW TABLE STATUS" : "show table status");
2369         if (x.getDatabase() !is null) {
2370             print0(ucase ? " FROM " : " from ");
2371             x.getDatabase().accept(this);
2372         }
2373 
2374         if (x.getLike() !is null) {
2375             print0(ucase ? " LIKE " : " like ");
2376             x.getLike().accept(this);
2377         }
2378 
2379         if (x.getWhere() !is null) {
2380             print0(ucase ? " WHERE " : " where ");
2381             x.getWhere().accept(this);
2382         }
2383 
2384         return false;
2385     }
2386 
2387     override
2388     public void endVisit(MySqlShowTableStatusStatement x) {
2389 
2390     }
2391 
2392     override
2393     public bool visit(MySqlShowTriggersStatement x) {
2394         print0(ucase ? "SHOW TRIGGERS" : "show triggers");
2395 
2396         if (x.getDatabase() !is null) {
2397             print0(ucase ? " FROM " : " from ");
2398             x.getDatabase().accept(this);
2399         }
2400 
2401         if (x.getLike() !is null) {
2402             print0(ucase ? " LIKE " : " like ");
2403             x.getLike().accept(this);
2404         }
2405 
2406         if (x.getWhere() !is null) {
2407             print0(ucase ? " WHERE " : " where ");
2408             x.getWhere().accept(this);
2409         }
2410 
2411         return false;
2412     }
2413 
2414     override
2415     public void endVisit(MySqlShowTriggersStatement x) {
2416 
2417     }
2418 
2419     override
2420     public bool visit(MySqlShowVariantsStatement x) {
2421         print0(ucase ? "SHOW " : "show ");
2422 
2423         if (x.isGlobal()) {
2424             print0(ucase ? "GLOBAL " : "global ");
2425         }
2426 
2427         if (x.isSession()) {
2428             print0(ucase ? "SESSION " : "session ");
2429         }
2430 
2431         print0(ucase ? "VARIABLES" : "variables");
2432 
2433         if (x.getLike() !is null) {
2434             print0(ucase ? " LIKE " : " like ");
2435             x.getLike().accept(this);
2436         }
2437 
2438         if (x.getWhere() !is null) {
2439             print0(ucase ? " WHERE " : " where ");
2440             x.getWhere().accept(this);
2441         }
2442 
2443         return false;
2444     }
2445 
2446     override
2447     public void endVisit(MySqlShowVariantsStatement x) {
2448 
2449     }
2450 
2451     override
2452     public bool visit(SQLAlterTableStatement x) {
2453         if (x.isIgnore()) {
2454             print0(ucase ? "ALTER IGNORE TABLE " : "alter ignore table ");
2455         } else {
2456             print0(ucase ? "ALTER TABLE " : "alter table ");
2457         }
2458         printTableSourceExpr(x.getName());
2459         this.indentCount++;
2460         for (int i = 0; i < x.getItems().size(); ++i) {
2461             SQLAlterTableItem item = x.getItems().get(i);
2462             if (i != 0) {
2463                 print(',');
2464             }
2465             println();
2466             item.accept(this);
2467         }
2468 
2469         if (x.isRemovePatiting()) {
2470             println();
2471             print0(ucase ? "REMOVE PARTITIONING" : "remove partitioning");
2472         }
2473 
2474         if (x.isUpgradePatiting()) {
2475             println();
2476             print0(ucase ? "UPGRADE PARTITIONING" : "upgrade partitioning");
2477         }
2478 
2479         if (x.getTableOptions().size() > 0) {
2480             println();
2481         }
2482 
2483         this.indentCount--;
2484 
2485         int i = 0;
2486         foreach(string key, SQLObject v; x.getTableOptions()) {
2487             // string key = option.getKey();
2488             if (i != 0) {
2489                 print(' ');
2490             }
2491             print0(ucase ? key : toLower(key));
2492 
2493             if ("TABLESPACE" == (key)) {
2494                 print(' ');
2495                 v.accept(this);
2496                 continue;
2497             } else if ("UNION" == (key)) {
2498                 print0(" = (");
2499                 v.accept(this);
2500                 print(')');
2501                 continue;
2502             }
2503 
2504             print0(" = ");
2505 
2506             v.accept(this);
2507             i++;
2508         }
2509 
2510         return false;
2511     }
2512 
2513     override
2514     public bool visit(SQLAlterTableAddColumn x) {
2515         print0(ucase ? "ADD COLUMN " : "add column ");
2516 
2517         if (x.getColumns().size() > 1) {
2518             print('(');
2519         }
2520         printAndAccept!SQLColumnDefinition((x.getColumns()), ", ");
2521         if (x.getFirstColumn() !is null) {
2522             print0(ucase ? " FIRST " : " first ");
2523             x.getFirstColumn().accept(this);
2524         } else if (x.getAfterColumn() !is null) {
2525             print0(ucase ? " AFTER " : " after ");
2526             x.getAfterColumn().accept(this);
2527         } else if (x.isFirst()) {
2528             print0(ucase ? " FIRST" : " first");
2529         }
2530 
2531         if (x.getColumns().size() > 1) {
2532             print(')');
2533         }
2534         return false;
2535     }
2536 
2537     override
2538     public bool visit(MySqlRenameTableStatement.Item x) {
2539         x.getName().accept(this);
2540         print0(ucase ? " TO " : " to ");
2541         x.getTo().accept(this);
2542         return false;
2543     }
2544 
2545     override
2546     public void endVisit(MySqlRenameTableStatement.Item x) {
2547 
2548     }
2549 
2550     override
2551     public bool visit(MySqlRenameTableStatement x) {
2552         print0(ucase ? "RENAME TABLE " : "rename table ");
2553         printAndAccept!(MySqlRenameTableStatement.Item)((x.getItems()), ", ");
2554         return false;
2555     }
2556 
2557     override
2558     public void endVisit(MySqlRenameTableStatement x) {
2559 
2560     }
2561 
2562     override
2563     public bool visit(MySqlUseIndexHint x) {
2564         print0(ucase ? "USE INDEX " : "use index ");
2565         if (x.getOption().name.length != 0) {
2566             print0(ucase ? "FOR " : "for ");
2567             print0(x.getOption().name);
2568             print(' ');
2569         }
2570         print('(');
2571         printAndAccept!SQLName((x.getIndexList()), ", ");
2572         print(')');
2573         return false;
2574     }
2575 
2576     override
2577     public void endVisit(MySqlUseIndexHint x) {
2578 
2579     }
2580 
2581     override
2582     public bool visit(MySqlIgnoreIndexHint x) {
2583         print0(ucase ? "IGNORE INDEX " : "ignore index ");
2584         if (x.getOption().name.length != 0) {
2585             print0(ucase ? "FOR " : "for ");
2586             print0(ucase ? x.getOption().name : x.getOption().name_lcase);
2587             print(' ');
2588         }
2589         print('(');
2590         printAndAccept!SQLName((x.getIndexList()), ", ");
2591         print(')');
2592         return false;
2593     }
2594 
2595     override
2596     public void endVisit(MySqlIgnoreIndexHint x) {
2597 
2598     }
2599 
2600     override public bool visit(SQLExprTableSource x) {
2601         printTableSourceExpr(x.getExpr());
2602 
2603         string alias_p = x.getAlias();
2604         if (alias_p !is null) {
2605             print(' ');
2606             print0(alias_p);
2607         }
2608 
2609         for (int i = 0; i < x.getHintsSize(); ++i) {
2610             print(' ');
2611             x.getHints().get(i).accept(this);
2612         }
2613 
2614         if (x.getPartitionSize() > 0) {
2615             print0(ucase ? " PARTITION (" : " partition (");
2616             printlnAndAccept!(SQLName)((x.getPartitions()), ", ");
2617             print(')');
2618         }
2619 
2620         return false;
2621     }
2622 
2623     override
2624     public bool visit(MySqlLockTableStatement x) {
2625         print0(ucase ? "LOCK TABLES" : "lock tables");
2626         List!(MySqlLockTableStatement.Item) items = x.getItems();
2627         if(items.size() > 0) {
2628             print(' ');
2629             printAndAccept!(MySqlLockTableStatement.Item)((items), ", ");
2630         }
2631         return false;
2632     }
2633 
2634     override
2635     public void endVisit(MySqlLockTableStatement x) {
2636 
2637     }
2638 
2639     override
2640     public bool visit(MySqlLockTableStatement.Item x) {
2641         x.getTableSource().accept(this);
2642         if (x.getLockType().name.length != 0) {
2643             print(' ');
2644             print0(x.getLockType().name);
2645         }
2646 
2647         if (x.getHints() !is null && x.getHints().size() > 0) {
2648             print(' ');
2649             printAndAccept!SQLCommentHint((x.getHints()), " ");
2650         }
2651         return false;
2652     }
2653 
2654     override
2655     public void endVisit(MySqlLockTableStatement.Item x) {
2656 
2657     }
2658 
2659     override
2660     public bool visit(MySqlUnlockTablesStatement x) {
2661         print0(ucase ? "UNLOCK TABLES" : "unlock tables");
2662         return false;
2663     }
2664 
2665     override
2666     public void endVisit(MySqlUnlockTablesStatement x) {
2667 
2668     }
2669 
2670     override
2671     public bool visit(MySqlForceIndexHint x) {
2672         print0(ucase ? "FORCE INDEX " : "force index ");
2673         if (x.getOption().name.length != 0) {
2674             print0(ucase ? "FOR " : "for ");
2675             print0(x.getOption().name);
2676             print(' ');
2677         }
2678         print('(');
2679         printAndAccept!SQLName((x.getIndexList()), ", ");
2680         print(')');
2681         return false;
2682     }
2683 
2684     override
2685     public void endVisit(MySqlForceIndexHint x) {
2686 
2687     }
2688 
2689     override
2690     public bool visit(MySqlAlterTableChangeColumn x) {
2691         print0(ucase ? "CHANGE COLUMN " : "change column ");
2692         x.getColumnName().accept(this);
2693         print(' ');
2694         x.getNewColumnDefinition().accept(this);
2695         if (x.getFirstColumn() !is null) {
2696             print0(ucase ? " FIRST " : " first ");
2697             x.getFirstColumn().accept(this);
2698         } else if (x.getAfterColumn() !is null) {
2699             print0(ucase ? " AFTER " : " after ");
2700             x.getAfterColumn().accept(this);
2701         } else if (x.isFirst()) {
2702             print0(ucase ? " FIRST" : " first");
2703         }
2704 
2705         return false;
2706     }
2707 
2708     override
2709     public void endVisit(MySqlAlterTableChangeColumn x) {
2710 
2711     }
2712 
2713     override
2714     public bool visit(MySqlAlterTableModifyColumn x) {
2715         print0(ucase ? "MODIFY COLUMN " : "modify column ");
2716         x.getNewColumnDefinition().accept(this);
2717         if (x.getFirstColumn() !is null) {
2718             print0(ucase ? " FIRST " : " first ");
2719             x.getFirstColumn().accept(this);
2720         } else if (x.getAfterColumn() !is null) {
2721             print0(ucase ? " AFTER " : " after ");
2722             x.getAfterColumn().accept(this);
2723         } else if (x.isFirst()) {
2724             print0(ucase ? " FIRST" : " first");
2725         }
2726 
2727         return false;
2728     }
2729 
2730     override
2731     public void endVisit(MySqlAlterTableModifyColumn x) {
2732 
2733     }
2734 
2735     override
2736     public bool visit(MySqlAlterTableOption x) {
2737         print0(x.getName());
2738         print0(" = ");
2739         print0((cast(Object)(x.getValue())).toString());
2740         return false;
2741     }
2742 
2743     override
2744     public void endVisit(MySqlAlterTableOption x) {
2745 
2746     }
2747 
2748     override
2749     public void endVisit(MySqlCreateTableStatement x) {
2750 
2751     }
2752 
2753     override
2754     public bool visit(MySqlHelpStatement x) {
2755         print0(ucase ? "HELP " : "help ");
2756         x.getContent().accept(this);
2757         return false;
2758     }
2759 
2760     override
2761     public void endVisit(MySqlHelpStatement x) {
2762 
2763     }
2764 
2765     override
2766     public bool visit(MySqlCharExpr x) {
2767         if (this.parameterized) {
2768             print('?');
2769             incrementReplaceCunt();
2770             if (this.parameters !is null) {
2771                 ExportParameterVisitorUtils.exportParameter(this.parameters, x);
2772             }
2773             return false;
2774         }
2775 
2776         print0((cast(Object)(x)).toString());
2777         return false;
2778     }
2779 
2780     override
2781     public void endVisit(MySqlCharExpr x) {
2782 
2783     }
2784 
2785     override
2786     public bool visit(MySqlUnique x) {
2787         if (x.isHasConstaint()) {
2788             print0(ucase ? "CONSTRAINT " : "constraint ");
2789             if (x.getName() !is null) {
2790                 x.getName().accept(this);
2791                 print(' ');
2792             }
2793         }
2794 
2795         print0(ucase ? "UNIQUE" : "unique");
2796 
2797         SQLName name = x.getName();
2798         if (name !is null) {
2799             print(' ');
2800             name.accept(this);
2801         }
2802 
2803         if (x.getIndexType() !is null) {
2804             print0(ucase ? " USING " : " using ");
2805             print0(x.getIndexType());
2806         }
2807 
2808         print0(" (");
2809         printAndAccept!SQLSelectOrderByItem((x.getColumns()), ", ");
2810         print(')');
2811 
2812         SQLExpr keyBlockSize = x.getKeyBlockSize();
2813         if (keyBlockSize !is null) {
2814             print0(ucase ? " KEY_BLOCK_SIZE = " : " key_block_size = ");
2815             keyBlockSize.accept(this);
2816         }
2817 
2818         SQLExpr comment = x.getComment();
2819         if (comment !is null) {
2820             print0(" COMMENT ");
2821             comment.accept(this);
2822         }
2823 
2824         return false;
2825     }
2826 
2827     override
2828     public bool visit(MysqlForeignKey x) {
2829         if (x.isHasConstraint()) {
2830             print0(ucase ? "CONSTRAINT " : "constraint ");
2831             if (x.getName() !is null) {
2832                 x.getName().accept(this);
2833                 print(' ');
2834             }
2835         }
2836 
2837         print0(ucase ? "FOREIGN KEY" : "foreign key");
2838 
2839         if (x.getIndexName() !is null) {
2840             print(' ');
2841             x.getIndexName().accept(this);
2842         }
2843 
2844         print0(" (");
2845         printAndAccept!SQLName((x.getReferencingColumns()), ", ");
2846         print(')');
2847 
2848         print0(ucase ? " REFERENCES " : " references ");
2849         x.getReferencedTableName().accept(this);
2850 
2851         print0(" (");
2852         printAndAccept!SQLName((x.getReferencedColumns()), ", ");
2853         print(')');
2854 
2855         SQLForeignKeyImpl.Match match = x.getReferenceMatch();
2856         if (match.name.length != 0 ) {
2857             print0(ucase ? " MATCH " : " match ");
2858             print0(ucase ? match.name : match.name_lcase);
2859         }
2860 
2861         if (x.getOnDelete().name.length != 0 ) {
2862             print0(ucase ? " ON DELETE " : " on delete ");
2863             print0(ucase ? x.getOnDelete().name : x.getOnDelete().name_lcase);
2864         }
2865 
2866         if (x.getOnUpdate().name.length != 0 ) {
2867             print0(ucase ? " ON UPDATE " : " on update ");
2868             print0(ucase ? x.getOnUpdate().name : x.getOnUpdate().name_lcase);
2869         }
2870         return false;
2871     }
2872 
2873     override
2874     public void endVisit(MySqlUnique x) {
2875 
2876     }
2877 
2878     override
2879     public bool visit(MySqlAlterTableDiscardTablespace x) {
2880         print0(ucase ? "DISCARD TABLESPACE" : "discard tablespace");
2881         return false;
2882     }
2883 
2884     override
2885     public void endVisit(MySqlAlterTableDiscardTablespace x) {
2886 
2887     }
2888 
2889     override
2890     public bool visit(MySqlAlterTableImportTablespace x) {
2891         print0(ucase ? "IMPORT TABLESPACE" : "import tablespace");
2892         return false;
2893     }
2894 
2895     override
2896     public void endVisit(MySqlAlterTableImportTablespace x) {
2897 
2898     }
2899 
2900     override
2901     public bool visit(SQLAssignItem x) {
2902 
2903 
2904         string tagetString = (cast(Object)(x.getTarget())).toString();
2905 
2906         bool mysqlSpecial = false;
2907 
2908         if (DBType.MYSQL.opEquals(dbType)) {
2909             mysqlSpecial = "NAMES".equalsIgnoreCase(tagetString)
2910                     || "CHARACTER SET".equalsIgnoreCase(tagetString)
2911                     || "CHARSET".equalsIgnoreCase(tagetString);
2912         }
2913 
2914         if (!mysqlSpecial) {
2915             x.getTarget().accept(this);
2916             print0(" = ");
2917         } else {
2918             print0(ucase ? toUpper(tagetString) : toLower(tagetString));
2919             print(' ');
2920         }
2921         x.getValue().accept(this);
2922         return false;
2923     }
2924 
2925     override
2926     public bool visit(MySqlCreateTableStatement.TableSpaceOption x) {
2927         x.getName().accept(this);
2928 
2929         if (x.getStorage() !is null) {
2930             print(' ');
2931             x.getStorage().accept(this);
2932         }
2933         return false;
2934     }
2935 
2936     override
2937     public void endVisit(MySqlCreateTableStatement.TableSpaceOption x) {
2938 
2939     }
2940 
2941     override protected void visitAggreateRest(SQLAggregateExpr aggregateExpr) {
2942         {
2943             SQLOrderBy value = cast(SQLOrderBy) aggregateExpr.getAttribute("ORDER BY");
2944             if (value !is null) {
2945                 print(' ');
2946                 (cast(SQLObject) value).accept(this);
2947             }
2948         }
2949         {
2950             Object value = aggregateExpr.getAttribute("SEPARATOR");
2951             if (value !is null) {
2952                 print0(ucase ? " SEPARATOR " : " separator ");
2953                 (cast(SQLObject) value).accept(this);
2954             }
2955         }
2956     }
2957 
2958     override
2959     public bool visit(MySqlAnalyzeStatement x) {
2960         print0(ucase ? "ANALYZE " : "analyze ");
2961         if (x.isNoWriteToBinlog()) {
2962             print0(ucase ? "NO_WRITE_TO_BINLOG " : "no_write_to_binlog ");
2963         }
2964 
2965         if (x.isLocal()) {
2966             print0(ucase ? "LOCAL " : "local ");
2967         }
2968 
2969         print0(ucase ? "TABLE " : "table ");
2970 
2971         printAndAccept!SQLExprTableSource((x.getTableSources()), ", ");
2972         return false;
2973     }
2974 
2975     override
2976     public void endVisit(MySqlAnalyzeStatement x) {
2977 
2978     }
2979 
2980     override
2981     public bool visit(MySqlOptimizeStatement x) {
2982         print0(ucase ? "OPTIMIZE " : "optimize ");
2983         if (x.isNoWriteToBinlog()) {
2984             print0(ucase ? "NO_WRITE_TO_BINLOG " : "No_write_to_binlog ");
2985         }
2986 
2987         if (x.isLocal()) {
2988             print0(ucase ? "LOCAL " : "local ");
2989         }
2990 
2991         print0(ucase ? "TABLE " : "table ");
2992 
2993         printAndAccept!SQLExprTableSource((x.getTableSources()), ", ");
2994         return false;
2995     }
2996 
2997     override
2998     public void endVisit(MySqlOptimizeStatement x) {
2999 
3000     }
3001 
3002     override
3003     public bool visit(MySqlAlterUserStatement x) {
3004         print0(ucase ? "ALTER USER" : "alter user");
3005         foreach(SQLExpr user ; x.getUsers()) {
3006             print(' ');
3007             user.accept(this);
3008             print0(ucase ? " PASSWORD EXPIRE" : " password expire");
3009         }
3010         return false;
3011     }
3012 
3013     override
3014     public void endVisit(MySqlAlterUserStatement x) {
3015 
3016     }
3017 
3018     override
3019     public bool visit(SQLSetStatement x) {
3020         bool printSet = x.getAttribute("parser.set") == Boolean.TRUE || !DBType.ORACLE.opEquals(dbType);
3021         if (printSet) {
3022             print0(ucase ? "SET " : "set ");
3023         }
3024         SQLSetStatement.Option option = x.getOption();
3025         if (option.name.length != 0 ) {
3026             print(option.name);
3027             print(' ');
3028         }
3029 
3030         if (option == SQLSetStatement.Option.PASSWORD) {
3031             print0("FOR ");
3032         }
3033 
3034         printAndAccept!SQLAssignItem((x.getItems()), ", ");
3035 
3036         if (x.getHints() !is null && x.getHints().size() > 0) {
3037             print(' ');
3038             printAndAccept!SQLCommentHint((x.getHints()), " ");
3039         }
3040 
3041         return false;
3042     }
3043 
3044     override
3045     public bool visit(MySqlHintStatement x) {
3046         List!(SQLCommentHint) hints = x.getHints();
3047 
3048         foreach(SQLCommentHint hint ; hints) {
3049             hint.accept(this);
3050         }
3051         return false;
3052     }
3053 
3054     override
3055     public void endVisit(MySqlHintStatement x) {
3056 
3057     }
3058 
3059     override
3060     public bool visit(MySqlOrderingExpr x) {
3061         x.getExpr().accept(this);
3062         if (x.getType().name.length != 0 ) {
3063             print(' ');
3064             print0(ucase ? x.getType().name : x.getType().name_lcase);
3065         }
3066 
3067         return false;
3068     }
3069 
3070     override
3071     public void endVisit(MySqlOrderingExpr x) {
3072 
3073     }
3074 
3075     override
3076     public bool visit(SQLBlockStatement x) {
3077         SQLObject parent = x.getParent();
3078         string labelName = x.getLabelName();
3079 
3080         if (labelName !is null && !(labelName == (""))) {
3081             print0(labelName);
3082             print0(": ");
3083         }
3084 
3085         List!(SQLParameter) parameters = x.getParameters();
3086         if (parameters.size() != 0) {
3087             this.indentCount++;
3088             if (cast(SQLCreateProcedureStatement)(parent) !is null) {
3089                 printIndent();
3090             }
3091             if (!(cast(SQLCreateProcedureStatement)(parent) !is null)) {
3092                 print0(ucase ? "DECLARE" : "declare");
3093                 println();
3094             }
3095 
3096             for (int i = 0, size = parameters.size(); i < size; ++i) {
3097                 if (i != 0) {
3098                     println();
3099                 }
3100                 SQLParameter param = parameters.get(i);
3101                 visit(param);
3102                 print(';');
3103             }
3104 
3105             this.indentCount--;
3106             println();
3107         }
3108 
3109         print0(ucase ? "BEGIN" : "begin");
3110         if (!x.isEndOfCommit()) {
3111             this.indentCount++;
3112         } else {
3113             print(';');
3114         }
3115         println();
3116         List!(SQLStatement) statementList = x.getStatementList();
3117         for (int i = 0, size = statementList.size(); i < size; ++i) {
3118             if (i != 0) {
3119                 println();
3120             }
3121             SQLStatement stmt = statementList.get(i);
3122             stmt.accept(this);
3123         }
3124 
3125         if (!x.isEndOfCommit()) {
3126             this.indentCount--;
3127             println();
3128             print0(ucase ? "END" : "end");
3129             if (labelName !is null && !(labelName == (""))) {
3130                 print(' ');
3131                 print0(labelName);
3132             }
3133         }
3134 
3135         return false;
3136     }
3137 
3138     override
3139     public bool visit(SQLIfStatement x) {
3140         print0(ucase ? "IF " : "if ");
3141         x.getCondition().accept(this);
3142         print0(ucase ? " THEN" : " then");
3143         this.indentCount++;
3144         println();
3145         List!(SQLStatement) statements = x.getStatements();
3146         for (int i = 0, size = statements.size(); i < size; ++i) {
3147             SQLStatement item = statements.get(i);
3148             item.accept(this);
3149             if (i != size - 1) {
3150                 println();
3151             }
3152         }
3153         this.indentCount--;
3154         println();
3155         foreach(SQLIfStatement.ElseIf iterable_element ; x.getElseIfList()) {
3156             iterable_element.accept(this);
3157         }
3158 
3159         if (x.getElseItem() !is null) {
3160             x.getElseItem().accept(this);
3161         }
3162 
3163         print0(ucase ? "END IF" : "end if");
3164         return false;
3165     }
3166 
3167     override
3168     public bool visit(SQLIfStatement.ElseIf x) {
3169         print0(ucase ? "ELSE IF " : "else if ");
3170         x.getCondition().accept(this);
3171         print0(ucase ? " THEN" : " then");
3172         this.indentCount++;
3173         println();
3174         for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
3175             SQLStatement item = x.getStatements().get(i);
3176             item.accept(this);
3177             if (i != size - 1) {
3178                 println();
3179             }
3180         }
3181         this.indentCount--;
3182         println();
3183         return false;
3184     }
3185 
3186     override
3187     public bool visit(SQLIfStatement.Else x) {
3188         print0(ucase ? "ELSE " : "else ");
3189         this.indentCount++;
3190         println();
3191         for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
3192             SQLStatement item = x.getStatements().get(i);
3193             item.accept(this);
3194             if (i != size - 1) {
3195                 println();
3196             }
3197         }
3198         this.indentCount--;
3199         println();
3200         return false;
3201     }
3202 
3203     override
3204     public bool visit(MySqlCaseStatement x) {
3205         print0(ucase ? "CASE " : "case ");
3206         x.getCondition().accept(this);
3207         println();
3208         for (int i = 0; i < x.getWhenList().size(); i++) {
3209             x.getWhenList().get(i).accept(this);
3210         }
3211         if (x.getElseItem() !is null) x.getElseItem().accept(this);
3212         print0(ucase ? "END CASE" : "end case");
3213         return false;
3214     }
3215 
3216     override
3217     public void endVisit(MySqlCaseStatement x) {
3218 
3219     }
3220 
3221     override
3222     public bool visit(MySqlDeclareStatement x) {
3223         print0(ucase ? "DECLARE " : "declare ");
3224         printAndAccept!SQLDeclareItem((x.getVarList()), ", ");
3225         return false;
3226     }
3227 
3228     override
3229     public void endVisit(MySqlDeclareStatement x) {
3230 
3231     }
3232 
3233     override
3234     public bool visit(MySqlSelectIntoStatement x) {
3235         x.getSelect().accept(this);
3236         print0(ucase ? " INTO " : " into ");
3237         for (int i = 0; i < x.getVarList().size(); i++) {
3238             x.getVarList().get(i).accept(this);
3239             if (i != x.getVarList().size() - 1) print0(", ");
3240         }
3241         return false;
3242     }
3243 
3244     override
3245     public void endVisit(MySqlSelectIntoStatement x) {
3246 
3247     }
3248 
3249     override
3250     public bool visit(MySqlCaseStatement.MySqlWhenStatement x) {
3251         print0(ucase ? "WHEN " : "when ");
3252         x.getCondition().accept(this);
3253         print0(" THEN");
3254         println();
3255         for (int i = 0; i < x.getStatements().size(); i++) {
3256             x.getStatements().get(i).accept(this);
3257             if (i != x.getStatements().size() - 1) {
3258                 println();
3259             }
3260         }
3261         println();
3262         return false;
3263     }
3264 
3265     override
3266     public void endVisit(MySqlCaseStatement.MySqlWhenStatement x) {
3267 
3268     }
3269 
3270     override
3271     public bool visit(SQLLoopStatement x) {
3272         if (x.getLabelName() !is null && !(x.getLabelName() == (""))) {
3273             print0(x.getLabelName());
3274             print0(": ");
3275         }
3276 
3277         print0(ucase ? "LOOP " : "loop ");
3278         this.indentCount++;
3279         println();
3280         for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
3281             SQLStatement item = x.getStatements().get(i);
3282             item.accept(this);
3283             if (i != size - 1) {
3284                 println();
3285             }
3286         }
3287         this.indentCount--;
3288         println();
3289         print0(ucase ? "END LOOP" : "end loop");
3290         if (x.getLabelName() !is null && !(x.getLabelName() == (""))) {
3291             print0(" ");
3292             print0(x.getLabelName());
3293         }
3294         return false;
3295     }
3296 
3297     override
3298     public bool visit(MySqlLeaveStatement x) {
3299         print0(ucase ? "LEAVE " : "leave ");
3300         print0(x.getLabelName());
3301         return false;
3302     }
3303 
3304     override
3305     public void endVisit(MySqlLeaveStatement x) {
3306         // TODO Auto-generated method stub
3307 
3308     }
3309 
3310     override
3311     public bool visit(MySqlIterateStatement x) {
3312         print0(ucase ? "ITERATE " : "iterate ");
3313         print0(x.getLabelName());
3314         return false;
3315     }
3316 
3317     override
3318     public void endVisit(MySqlIterateStatement x) {
3319         // TODO Auto-generated method stub
3320 
3321     }
3322 
3323     override
3324     public bool visit(MySqlRepeatStatement x) {
3325         // TODO Auto-generated method stub
3326         if (x.getLabelName() !is null && !(x.getLabelName() == (""))) {
3327             print0(x.getLabelName());
3328             print0(": ");
3329         }
3330 
3331         print0(ucase ? "REPEAT " : "repeat ");
3332         this.indentCount++;
3333         println();
3334         for (int i = 0, size = x.getStatements().size(); i < size; ++i) {
3335             SQLStatement item = x.getStatements().get(i);
3336             item.accept(this);
3337             if (i != size - 1) {
3338                 println();
3339             }
3340         }
3341         this.indentCount--;
3342         println();
3343         print0(ucase ? "UNTIL " : "until ");
3344         x.getCondition().accept(this);
3345         println();
3346         print0(ucase ? "END REPEAT" : "end repeat");
3347         if (x.getLabelName() !is null && !(x.getLabelName() == (""))) {
3348             print(' ');
3349             print0(x.getLabelName());
3350         }
3351         return false;
3352     }
3353 
3354     override
3355     public void endVisit(MySqlRepeatStatement x) {
3356         // TODO Auto-generated method stub
3357 
3358     }
3359 
3360     override
3361     public bool visit(MySqlCursorDeclareStatement x) {
3362         print0(ucase ? "DECLARE " : "declare ");
3363         printExpr(x.getCursorName());
3364         print0(ucase ? " CURSOR FOR" : " cursor for");
3365         this.indentCount++;
3366         println();
3367         x.getSelect().accept(this);
3368         this.indentCount--;
3369         return false;
3370     }
3371 
3372     override
3373     public void endVisit(MySqlCursorDeclareStatement x) {
3374         // TODO Auto-generated method stub
3375 
3376     }
3377 
3378     override
3379     public bool visit(MySqlUpdateTableSource x) {
3380         MySqlUpdateStatement update = x.getUpdate();
3381         if (update !is null) {
3382             update.accept0(this);
3383         }
3384         return false;
3385     }
3386 
3387     override
3388     public void endVisit(MySqlUpdateTableSource x) {
3389 
3390     }
3391 
3392     override
3393     public bool visit(MySqlAlterTableAlterColumn x) {
3394         print0(ucase ? "ALTER COLUMN " : "alter column ");
3395         x.getColumn().accept(this);
3396         if (x.getDefaultExpr() !is null) {
3397             print0(ucase ? " SET DEFAULT " : " set default ");
3398             x.getDefaultExpr().accept(this);
3399         } else if (x.isDropDefault()) {
3400             print0(ucase ? " DROP DEFAULT" : " drop default");
3401         }
3402         return false;
3403     }
3404 
3405     override
3406     public void endVisit(MySqlAlterTableAlterColumn x) {
3407 
3408     }
3409 
3410     override
3411     public bool visit(MySqlSubPartitionByKey x) {
3412         if (x.isLinear()) {
3413             print0(ucase ? "SUBPARTITION BY LINEAR KEY (" : "subpartition by linear key (");
3414         } else {
3415             print0(ucase ? "SUBPARTITION BY KEY (" : "subpartition by key (");
3416         }
3417         printAndAccept!SQLName((x.getColumns()), ", ");
3418         print(')');
3419 
3420         if (x.getSubPartitionsCount() !is null) {
3421             print0(ucase ? " SUBPARTITIONS " : " subpartitions ");
3422             x.getSubPartitionsCount().accept(this);
3423         }
3424         return false;
3425     }
3426 
3427     override
3428     public void endVisit(MySqlSubPartitionByKey x) {
3429 
3430     }
3431 
3432     override
3433     public bool visit(MySqlSubPartitionByList x) {
3434         print0(ucase ? "SUBPARTITION BY LIST " : "subpartition by list ");
3435         if (x.getExpr() !is null) {
3436             print('(');
3437             x.getExpr().accept(this);
3438             print0(") ");
3439         } else {
3440             if (x.getColumns().size() == 1 && Boolean.TRUE.opEquals(x.getAttribute("ads.subPartitionList"))) {
3441                 print('(');
3442             } else {
3443                 print0(ucase ? "COLUMNS (" : "columns (");
3444             }
3445             printAndAccept!SQLColumnDefinition((x.getColumns()), ", ");
3446             print(")");
3447         }
3448 
3449         if (x.getOptions().size() != 0) {
3450             println();
3451             print0(ucase ? "SUBPARTITION OPTIONS (" : "subpartition options (");
3452             printAndAccept!SQLAssignItem((x.getOptions()), ", ");
3453             print(')');
3454         }
3455 
3456         return false;
3457     }
3458 
3459     override
3460     public void endVisit(MySqlSubPartitionByList x) {
3461 
3462     }
3463 
3464 
3465     override
3466     public bool visit(MySqlDeclareHandlerStatement x) {
3467         string handleType = x.getHandleType().name;
3468 
3469         print0(ucase ? "DECLARE " : "declare ");
3470         print0(ucase ? handleType : toLower(handleType));
3471         print0(ucase ? " HANDLER FOR " : " handler for ");
3472         for (int i = 0; i < x.getConditionValues().size(); i++) {
3473             ConditionValue cv = x.getConditionValues().get(i);
3474             if (cv.getType() == ConditionValue.ConditionType.SQLSTATE) {
3475                 print0(ucase ? " SQLSTATE " : " sqlstate ");
3476                 print0(cv.getValue());
3477             } else if (cv.getType() == ConditionValue.ConditionType.MYSQL_ERROR_CODE) {
3478                 print0(cv.getValue());
3479             } else if (cv.getType() == ConditionValue.ConditionType.SELF) {
3480                 print0(cv.getValue());
3481             } else if (cv.getType() == ConditionValue.ConditionType.SYSTEM) {
3482                 print0(ucase ? toUpper(cv.getValue()) : toLower(cv.getValue()));
3483             }
3484 
3485             if (i != x.getConditionValues().size() - 1) {
3486                 print0(", ");
3487             }
3488 
3489         }
3490         this.indentCount++;
3491         println();
3492         x.getSpStatement().accept(this);
3493         this.indentCount--;
3494         return false;
3495     }
3496 
3497     override
3498     public void endVisit(MySqlDeclareHandlerStatement x) {
3499 
3500     }
3501 
3502     override
3503     public bool visit(MySqlDeclareConditionStatement x) {
3504         print0(ucase ? "DECLARE " : "declare ");
3505         print0(x.getConditionName());
3506         print0(ucase ? " CONDITION FOR " : " condition for ");
3507 
3508         if (x.getConditionValue().getType() == ConditionValue.ConditionType.SQLSTATE) {
3509             print0(ucase ? "SQLSTATE " : "sqlstate ");
3510             print0(x.getConditionValue().getValue());
3511         } else {
3512             print0(x.getConditionValue().getValue());
3513         }
3514 
3515         println();
3516         return false;
3517     }
3518 
3519     override
3520     public void endVisit(MySqlDeclareConditionStatement x) {
3521 
3522     }
3523 
3524     override
3525     public bool visit(SQLAlterTableDropColumnItem x) {
3526 
3527         for (int i = 0; i < x.getColumns().size(); ++i) {
3528             if (i != 0) {
3529                 print0(", ");
3530             }
3531 
3532             SQLName columnn = x.getColumns().get(i);
3533 
3534             print0(ucase ? "DROP COLUMN " : "drop column ");
3535             columnn.accept(this);
3536 
3537             if (x.isCascade()) {
3538                 print0(ucase ? " CASCADE" : " cascade");
3539             }
3540         }
3541         return false;
3542     }
3543 
3544     /**
3545      * visit procedure create node
3546      */
3547     override
3548     public bool visit(SQLCreateProcedureStatement x) {
3549         if (x.isOrReplace()) {
3550             print0(ucase ? "CREATE OR REPLACE PROCEDURE " : "create or replace procedure ");
3551         } else {
3552             print0(ucase ? "CREATE PROCEDURE " : "create procedure ");
3553         }
3554         x.getName().accept(this);
3555 
3556         int paramSize = x.getParameters().size();
3557 
3558         print0(" (");
3559         if (paramSize > 0) {
3560             this.indentCount++;
3561             println();
3562 
3563             for (int i = 0; i < paramSize; ++i) {
3564                 if (i != 0) {
3565                     print0(", ");
3566                     println();
3567                 }
3568                 SQLParameter param = x.getParameters().get(i);
3569                 param.accept(this);
3570             }
3571 
3572             this.indentCount--;
3573             println();
3574         }
3575         print(')');
3576 
3577         if (x.isDeterministic()) {
3578             println();
3579             print(ucase ? "DETERMINISTIC" : "deterministic");
3580         }
3581 
3582         if (x.isContainsSql()) {
3583             println();
3584             print0(ucase ? "CONTAINS SQL" : "contains sql");
3585         }
3586 
3587         if (x.isNoSql()) {
3588             println();
3589             print(ucase ? "NO SQL" : "no sql");
3590         }
3591 
3592         if (x.isModifiesSqlData()) {
3593             println();
3594             print(ucase ? "MODIFIES SQL DATA" : "modifies sql data");
3595         }
3596 
3597         SQLName authid = x.getAuthid();
3598         if (authid !is null) {
3599             println();
3600             print(ucase ? "SQL SECURITY " : "sql security ");
3601             authid.accept(this);
3602         }
3603 
3604         println();
3605         x.getBlock().accept(this);
3606         return false;
3607     }
3608 
3609     override
3610     public bool visit(SQLCreateFunctionStatement x) {
3611         print0(ucase ? "CREATE FUNCTION " : "create function ");
3612         x.getName().accept(this);
3613 
3614         int paramSize = x.getParameters().size();
3615 
3616         if (paramSize > 0) {
3617             print0(" (");
3618             this.indentCount++;
3619             println();
3620 
3621             for (int i = 0; i < paramSize; ++i) {
3622                 if (i != 0) {
3623                     print0(", ");
3624                     println();
3625                 }
3626                 SQLParameter param = x.getParameters().get(i);
3627                 param.accept(this);
3628             }
3629 
3630             this.indentCount--;
3631             println();
3632             print(')');
3633         }
3634 
3635         println();
3636         print(ucase ? "RETURNS " : "returns ");
3637         x.getReturnDataType().accept(this);
3638 
3639         if (x.isDeterministic()) {
3640             print(ucase ? " DETERMINISTIC" : " deterministic");
3641         }
3642 
3643         SQLStatement block = x.getBlock();
3644 
3645         println();
3646 
3647         block.accept(this);
3648         return false;
3649     }
3650 
3651     override
3652     public bool visit(SQLCommentStatement x) {
3653         SQLCommentStatement.Type type = x.getType();
3654 
3655         SQLExprTableSource on = x.getOn();
3656         if (type == SQLCommentStatement.Type.TABLE) {
3657             print0(ucase ? "ALTER TABLE " : "alter table ");
3658             on.accept(this);
3659             print0(ucase ? " COMMENT = " : " comment = ");
3660             x.getComment().accept(this);
3661         } else {
3662             SQLPropertyExpr propertyExpr = cast(SQLPropertyExpr) on.getExpr();
3663 
3664             SQLExpr table = propertyExpr.getOwner();
3665             string column = propertyExpr.getName();
3666 
3667             print0(ucase ? "ALTER TABLE " : "alter table ");
3668             printTableSourceExpr(table);
3669             print0(ucase ? " MODIFY COLUMN " : " modify column ");
3670             print(column);
3671             print0(ucase ? " COMMENT " : " comment ");
3672             x.getComment().accept(this);
3673         }
3674 
3675         return false;
3676     }
3677 
3678     override
3679     public bool visit(MySqlFlushStatement x) {
3680         print0(ucase ? "FLUSH" : "flush");
3681 
3682         if (x.isNoWriteToBinlog()) {
3683             print0(ucase ? " NO_WRITE_TO_BINLOG" : " no_write_to_binlog");
3684         } else if (x.isLocal()) {
3685             print0(ucase ? " LOCAL" : " local");
3686         }
3687 
3688         if(x.isBinaryLogs()) {
3689             print0(ucase ? " BINARY LOGS" : " binary logs");
3690         }
3691         if (x.isDesKeyFile()) {
3692             print0(ucase ? " DES_KEY_FILE" : " des_key_file");
3693         }
3694         if (x.isEngineLogs()) {
3695             print0(ucase ? " ENGINE LOGS" : " engine logs");
3696         }
3697         if (x.isErrorLogs()) {
3698             print0(ucase ? " ERROR LOGS" : " error logs");
3699         }
3700         if (x.isGeneralLogs()) {
3701             print0(ucase ? " GENERAL LOGS" : " general logs");
3702         }
3703         if (x.isHots()) {
3704             print0(ucase ? " HOSTS" : " hosts");
3705         }
3706         if (x.isLogs()) {
3707             print0(ucase ? " LOGS" : " logs");
3708         }
3709         if (x.isPrivileges()) {
3710             print0(ucase ? " PRIVILEGES" : " privileges");
3711         }
3712         if (x.isOptimizerCosts()) {
3713             print0(ucase ? " OPTIMIZER_COSTS" : " optimizer_costs");
3714         }
3715         if (x.isQueryCache()) {
3716             print0(ucase ? " QUERY CACHE" : " query cache");
3717         }
3718         if (x.isRelayLogs()) {
3719             print0(ucase ? " RELAY LOGS" : " relay logs");
3720             SQLExpr channel = x.getRelayLogsForChannel();
3721             if (channel !is null) {
3722                 print(' ');
3723                 channel.accept(this);
3724             }
3725         }
3726         if (x.isSlowLogs()) {
3727             print0(ucase ? " SLOW LOGS" : " slow logs");
3728         }
3729         if (x.isStatus()) {
3730             print0(ucase ? " STATUS" : " status");
3731         }
3732         if (x.isUserResources()) {
3733             print0(ucase ? " USER_RESOURCES" : " user_resources");
3734         }
3735 
3736         if(x.isTableOption()){
3737             print0(ucase ? " TABLES" : " tables");
3738 
3739             List!(SQLExprTableSource) tables = x.getTables();
3740             if (tables !is null && tables.size() > 0) {
3741                 print(' ');
3742                 printAndAccept!SQLExprTableSource((tables), ", ");
3743             }
3744 
3745             if (x.isWithReadLock()) {
3746                 print0(ucase ? " WITH READ LOCK" : " with read lock");
3747             }
3748 
3749             if (x.isForExport()) {
3750                 print0(ucase ? " FOR EXPORT" : " for export");
3751             }
3752         }
3753         return false;
3754     }
3755 
3756     override
3757     public void endVisit(MySqlFlushStatement x) {
3758 
3759     }
3760 
3761     override
3762     public bool visit(MySqlEventSchedule x) {
3763         int cnt = 0;
3764         if (x.getAt() !is null) {
3765             print0(ucase ? "AT " : "at ");
3766             printExpr(x.getAt());
3767 
3768             cnt++;
3769         }
3770 
3771         if (x.getEvery() !is null) {
3772             print0(ucase ? "EVERY " : "every ");
3773             SQLIntervalExpr interval = cast(SQLIntervalExpr) x.getEvery();
3774             printExpr(interval.getValue());
3775             print(' ');
3776             print(interval.getUnit().name());
3777 
3778             cnt++;
3779         }
3780 
3781         if (x.getStarts() !is null) {
3782             if (cnt > 0) {
3783                 print(' ');
3784             }
3785 
3786             print0(ucase ? "STARTS " : "starts ");
3787             printExpr(x.getStarts());
3788 
3789             cnt++;
3790         }
3791 
3792         if (x.getEnds() !is null) {
3793             if (cnt > 0) {
3794                 print(' ');
3795             }
3796             print0(ucase ? "ENDS " : "ends ");
3797             printExpr(x.getEnds());
3798 
3799             cnt++;
3800         }
3801 
3802         return false;
3803     }
3804 
3805     override
3806     public void endVisit(MySqlEventSchedule x) {
3807 
3808     }
3809 
3810     override
3811     public bool visit(MySqlCreateEventStatement x) {
3812         print0(ucase ? "CREATE " : "create ");
3813 
3814         SQLName definer = x.getDefiner();
3815         if (definer !is null) {
3816             print0(ucase ? "DEFINER = " : "definer = ");
3817         }
3818 
3819         print0(ucase ? "EVENT " : "evnet ");
3820 
3821         if (x.isIfNotExists()) {
3822             print0(ucase ? "IF NOT EXISTS " : "if not exists ");
3823         }
3824 
3825         printExpr(x.getName());
3826 
3827         MySqlEventSchedule schedule = x.getSchedule();
3828         print0(ucase ? " ON SCHEDULE " : " on schedule ");
3829         schedule.accept(this);
3830 
3831         auto enable = x.getEnable();
3832         if (enable !is null) {
3833             if (enable.booleanValue()) {
3834                 print0(ucase ? " ENABLE" : " enable");
3835             } else {
3836                 print0(ucase ? " DISABLE" : " disable");
3837                 if (x.isDisableOnSlave()) {
3838                     print0(ucase ? " ON SLAVE" : " on slave");
3839                 }
3840             }
3841         }
3842 
3843         SQLExpr comment = x.getComment();
3844         if (comment !is null) {
3845             print0(ucase ? "COMMENT " : "comment ");
3846             comment.accept(this);
3847         }
3848 
3849         println();
3850         SQLStatement body = x.getEventBody();
3851         if (!(cast(SQLExprStatement)(body) !is null)) {
3852             print0(ucase ? "DO" : "do");
3853             println();
3854         }
3855         body.accept(this);
3856 
3857         return false;
3858     }
3859 
3860     override
3861     public void endVisit(MySqlCreateEventStatement x) {
3862 
3863     }
3864 
3865     override
3866     public bool visit(MySqlCreateAddLogFileGroupStatement x) {
3867         print0(ucase ? "CREATE LOGFILE GROUP " : "create logfile group ");
3868         x.getName().accept(this);
3869         print(' ');
3870         print0(ucase ? "ADD UNDOFILE " : "add undofile ");
3871         printExpr(x.getAddUndoFile());
3872 
3873         SQLExpr initialSize = x.getInitialSize();
3874         if (initialSize !is null) {
3875             print0(ucase ? " INITIAL_SIZE " : " initial_size ");
3876             printExpr(initialSize);
3877         }
3878 
3879         SQLExpr undoBufferSize = x.getUndoBufferSize();
3880         if (undoBufferSize !is null) {
3881             print0(ucase ? " UNDO_BUFFER_SIZE " : " undo_buffer_size ");
3882             printExpr(undoBufferSize);
3883         }
3884 
3885         SQLExpr redoBufferSize = x.getRedoBufferSize();
3886         if (redoBufferSize !is null) {
3887             print0(ucase ? " REDO_BUFFER_SIZE " : " redo_buffer_size ");
3888             printExpr(redoBufferSize);
3889         }
3890 
3891         SQLExpr nodeGroup = x.getNodeGroup();
3892         if (nodeGroup !is null) {
3893             print0(ucase ? " NODEGROUP " : " nodegroup ");
3894             printExpr(nodeGroup);
3895         }
3896 
3897         if (x.isWait()) {
3898             print0(ucase ? " WAIT" : " wait");
3899         }
3900 
3901         SQLExpr comment = x.getComment();
3902         if (comment !is null) {
3903             print0(ucase ? " COMMENT " : " comment ");
3904             printExpr(comment);
3905         }
3906 
3907         SQLExpr engine = x.getEngine();
3908         if (engine !is null) {
3909             print0(ucase ? " ENGINE " : " engine ");
3910             printExpr(engine);
3911         }
3912 
3913         return false;
3914     }
3915 
3916     override
3917     public void endVisit(MySqlCreateAddLogFileGroupStatement x) {
3918 
3919     }
3920 
3921     override
3922     public bool visit(MySqlCreateServerStatement x) {
3923         print0(ucase ? "CREATE SERVER " : "create server ");
3924         x.getName().accept(this);
3925         print0(ucase ? " FOREIGN DATA WRAPPER " : " foreign data wrapper ");
3926         printExpr(x.getForeignDataWrapper());
3927 
3928         print(" OPTIONS(");
3929         int cnt = 0;
3930         SQLExpr host = x.getHost();
3931         if (host !is null) {
3932             print0(ucase ? "HOST " : "host ");
3933             printExpr(host);
3934             cnt++;
3935         }
3936 
3937         SQLExpr database = x.getDatabase();
3938         if (database !is null) {
3939             if (cnt++ > 0) {
3940                 print(", ");
3941             }
3942             print0(ucase ? "DATABASE " : "database ");
3943             printExpr(database);
3944         }
3945 
3946         SQLExpr user = x.getUser();
3947         if (user !is null) {
3948             if (cnt++ > 0) {
3949                 print(", ");
3950             }
3951             print0(ucase ? "USER " : "user ");
3952             printExpr(user);
3953         }
3954 
3955         SQLExpr password = x.getPassword();
3956         if (password !is null) {
3957             if (cnt++ > 0) {
3958                 print(", ");
3959             }
3960             print0(ucase ? "PASSWORD " : "password ");
3961             printExpr(password);
3962         }
3963 
3964         SQLExpr socket = x.getSocket();
3965         if (socket !is null) {
3966             if (cnt++ > 0) {
3967                 print(", ");
3968             }
3969             print0(ucase ? "SOCKET " : "socket ");
3970             printExpr(socket);
3971         }
3972 
3973         SQLExpr owner = x.getOwner();
3974         if (owner !is null) {
3975             if (cnt++ > 0) {
3976                 print(", ");
3977             }
3978             print0(ucase ? "OWNER " : "owner ");
3979             printExpr(owner);
3980         }
3981 
3982         SQLExpr port = x.getPort();
3983         if (port !is null) {
3984             if (cnt++ > 0) {
3985                 print(", ");
3986             }
3987             print0(ucase ? "PORT " : "port ");
3988             printExpr(port);
3989         }
3990         print(')');
3991 
3992         return false;
3993     }
3994 
3995     override
3996     public void endVisit(MySqlCreateServerStatement x) {
3997 
3998     }
3999 
4000     override
4001     public bool visit(MySqlCreateTableSpaceStatement x) {
4002         print0(ucase ? "CREATE TABLESPACE " : "create tablespace ");
4003         x.getName().accept(this);
4004 
4005         SQLExpr addDataFile = x.getAddDataFile();
4006         if (addDataFile !is null) {
4007             print0(ucase ? " ADD DATAFILE " : " add datafile ");
4008             addDataFile.accept(this);
4009         }
4010 
4011         SQLExpr fileBlockSize = x.getFileBlockSize();
4012         if (fileBlockSize !is null) {
4013             print0(ucase ? " FILE_BLOCK_SIZE = " : " file_block_size = ");
4014             fileBlockSize.accept(this);
4015         }
4016 
4017         SQLExpr logFileGroup = x.getLogFileGroup();
4018         if (logFileGroup !is null) {
4019             print0(ucase ? " USE LOGFILE GROUP " : " use logfile group ");
4020             logFileGroup.accept(this);
4021         }
4022 
4023         SQLExpr extentSize = x.getExtentSize();
4024         if (extentSize !is null) {
4025             print0(ucase ? " EXTENT_SIZE = " : " extent_size = ");
4026             extentSize.accept(this);
4027         }
4028 
4029         SQLExpr initialSize = x.getInitialSize();
4030         if (initialSize !is null) {
4031             print0(ucase ? " INITIAL_SIZE = " : " initial_size = ");
4032             initialSize.accept(this);
4033         }
4034 
4035         SQLExpr autoExtentSize = x.getAutoExtentSize();
4036         if (autoExtentSize !is null) {
4037             print0(ucase ? " AUTOEXTEND_SIZE = " : " autoextend_size = ");
4038             autoExtentSize.accept(this);
4039         }
4040 
4041         SQLExpr maxSize = x.getMaxSize();
4042         if (autoExtentSize !is null) {
4043             print0(ucase ? " MAX_SIZE = " : " max_size = ");
4044             maxSize.accept(this);
4045         }
4046 
4047         SQLExpr nodeGroup = x.getNodeGroup();
4048         if (nodeGroup !is null) {
4049             print0(ucase ? " NODEGROUP = " : " nodegroup = ");
4050             nodeGroup.accept(this);
4051         }
4052 
4053         if (x.isWait()) {
4054             print0(ucase ? " WAIT" : " wait");
4055         }
4056 
4057         SQLExpr comment = x.getComment();
4058         if (comment !is null) {
4059             print0(ucase ? " COMMENT " : " comment ");
4060             printExpr(comment);
4061         }
4062 
4063         SQLExpr engine = x.getEngine();
4064         if (engine !is null) {
4065             print0(ucase ? " ENGINE " : " engine ");
4066             printExpr(engine);
4067         }
4068 
4069         return false;
4070     }
4071 
4072     override
4073     public void endVisit(MySqlCreateTableSpaceStatement x) {
4074 
4075     }
4076 
4077     override
4078     public bool visit(MySqlAlterEventStatement x) {
4079         print0(ucase ? "ALTER " : "alter ");
4080 
4081         SQLName definer = x.getDefiner();
4082         if (definer !is null) {
4083             print0(ucase ? "DEFINER = " : "definer = ");
4084         }
4085 
4086         print0(ucase ? "EVENT " : "evnet ");
4087         printExpr(x.getName());
4088 
4089         MySqlEventSchedule schedule = x.getSchedule();
4090         if (schedule !is null) {
4091             print0(ucase ? " ON SCHEDULE " : " on schedule ");
4092             schedule.accept(this);
4093         }
4094 
4095         auto enable = x.getEnable();
4096         if (enable !is null) {
4097             if (enable.booleanValue()) {
4098                 print0(ucase ? " ENABLE" : " enable");
4099             } else {
4100                 print0(ucase ? " DISABLE" : " disable");
4101                 if (x.isDisableOnSlave()) {
4102                     print0(ucase ? " ON SLAVE" : " on slave");
4103                 }
4104             }
4105         }
4106 
4107         SQLExpr comment = x.getComment();
4108         if (comment !is null) {
4109             print0(ucase ? "COMMENT " : "comment ");
4110             comment.accept(this);
4111         }
4112 
4113         SQLStatement body = x.getEventBody();
4114         if (body !is null) {
4115             println();
4116             if (!(cast(SQLExprStatement)(body) !is null)) {
4117                 print0(ucase ? "DO" : "do");
4118                 println();
4119             }
4120             body.accept(this);
4121         }
4122 
4123         return false;
4124     }
4125 
4126     override
4127     public void endVisit(MySqlAlterEventStatement x) {
4128 
4129     }
4130 
4131     override
4132     public bool visit(MySqlAlterLogFileGroupStatement x) {
4133         print0(ucase ? "ALTER LOGFILE GROUP " : "alter logfile group ");
4134         x.getName().accept(this);
4135         print(' ');
4136         print0(ucase ? "ADD UNDOFILE " : "add undofile ");
4137         printExpr(x.getAddUndoFile());
4138 
4139         SQLExpr initialSize = x.getInitialSize();
4140         if (initialSize !is null) {
4141             print0(ucase ? " INITIAL_SIZE " : " initial_size ");
4142             printExpr(initialSize);
4143         }
4144 
4145         if (x.isWait()) {
4146             print0(ucase ? " WAIT" : " wait");
4147         }
4148 
4149         SQLExpr engine = x.getEngine();
4150         if (engine !is null) {
4151             print0(ucase ? " ENGINE " : " engine ");
4152             printExpr(engine);
4153         }
4154 
4155         return false;
4156     }
4157 
4158     override
4159     public void endVisit(MySqlAlterLogFileGroupStatement x) {
4160 
4161     }
4162 
4163     override
4164     public bool visit(MySqlAlterServerStatement x) {
4165         print0(ucase ? "ATLER SERVER " : "alter server ");
4166         x.getName().accept(this);
4167 
4168         print(" OPTIONS(");
4169         SQLExpr user = x.getUser();
4170         if (user !is null) {
4171             print0(ucase ? "USER " : "user ");
4172             printExpr(user);
4173         }
4174 
4175         print(')');
4176 
4177         return false;
4178     }
4179 
4180     override
4181     public void endVisit(MySqlAlterServerStatement x) {
4182 
4183     }
4184 
4185     override
4186     public bool visit(MySqlAlterTablespaceStatement x) {
4187         print0(ucase ? "CREATE TABLESPACE " : "create tablespace ");
4188         x.getName().accept(this);
4189 
4190         SQLExpr addDataFile = x.getAddDataFile();
4191         if (addDataFile !is null) {
4192             print0(ucase ? " ADD DATAFILE " : " add datafile ");
4193             addDataFile.accept(this);
4194         }
4195 
4196         SQLExpr initialSize = x.getInitialSize();
4197         if (initialSize !is null) {
4198             print0(ucase ? " INITIAL_SIZE = " : " initial_size = ");
4199             initialSize.accept(this);
4200         }
4201 
4202         if (x.isWait()) {
4203             print0(ucase ? " WAIT" : " wait");
4204         }
4205 
4206         SQLExpr engine = x.getEngine();
4207         if (engine !is null) {
4208             print0(ucase ? " ENGINE " : " engine ");
4209             printExpr(engine);
4210         }
4211 
4212         return false;
4213     }
4214 
4215     override
4216     public void endVisit(MySqlAlterTablespaceStatement x) {
4217 
4218     }
4219 
4220     override
4221     public bool visit(MySqlShowDatabasePartitionStatusStatement x) {
4222         print0(ucase ? "SHOW DATABASE PARTITION STATUS FOR " : "show database partition status for ");
4223         x.getDatabase().accept(this);
4224         return false;
4225     }
4226 
4227     override
4228     public void endVisit(MySqlShowDatabasePartitionStatusStatement x) {
4229 
4230     }
4231 
4232     override protected void printQuery(SQLSelectQuery x) {
4233         auto clazz = typeid(x);
4234         if (clazz == typeid(MySqlSelectQueryBlock)) {
4235             visit(cast(MySqlSelectQueryBlock) x);
4236         } else if (clazz == typeid(SQLSelectQueryBlock)) {
4237             visit(cast(SQLSelectQueryBlock) x);
4238         } else if (clazz == typeid(SQLUnionQuery)) {
4239             visit(cast(SQLUnionQuery) x);
4240         } else {
4241             x.accept(this);
4242         }
4243     }
4244 
4245     override public void printInsertColumns(List!(SQLExpr) columns) {
4246          int size = columns.size();
4247         if (size > 0) {
4248             if (size > 5) {
4249                 this.indentCount++;
4250                 print(' ');
4251             }
4252             print('(');
4253             for (int i = 0; i < size; ++i) {
4254                 if (i != 0) {
4255                     if (i % 5 == 0) {
4256                         println();
4257                     }
4258                     print0(", ");
4259                 }
4260 
4261                 SQLExpr column = columns.get(i);
4262                 if (cast(SQLIdentifierExpr)(column) !is null) {
4263                     visit(cast(SQLIdentifierExpr) column);
4264                 } else {
4265                     printExpr(column);
4266                 }
4267 
4268                 String dataType = cast(String) column.getAttribute("dataType");
4269                 if (dataType !is null) {
4270                     print(' ');
4271                     print(dataType);
4272                 }
4273             }
4274             print(')');
4275             if (size > 5) {
4276                 this.indentCount--;
4277             }
4278         }
4279     }
4280 
4281     override
4282     public void endVisit(MySqlChecksumTableStatement x) {
4283 
4284     }
4285 
4286     override
4287     public bool visit(MySqlChecksumTableStatement x) {
4288         print0(ucase ? "CHECKSUM TABLE " : "checksum table ");
4289         printAndAccept!SQLExprTableSource((x.getTables()), ",");
4290         return false;
4291     }
4292 
4293 
4294     override bool visit(SQLBlobExpr x) {
4295         print0("\"0x");
4296         print0(x.getHex());
4297         print('"');
4298 
4299         return false;
4300     }
4301     
4302     override void endVisit(SQLBlobExpr x) {
4303         
4304     }    
4305 
4306     
4307     override protected void print0(Bytes data) {
4308         // FIXME: Needing refactor or cleanup -@zhangxueping at 4/2/2019, 5:11:53 PM
4309         // need to be checked
4310         string s = format("unhex('%(%02X%)')", data.value());
4311         print0(s);
4312     }
4313 
4314     alias print0 = SQLASTOutputVisitor.print0;
4315 } //