1616 */
1717package com .google .edwmigration .dumper .application .dumper .connector .teradata .query ;
1818
19+ import static com .google .edwmigration .dumper .application .dumper .connector .teradata .TeradataUtils .formatQuery ;
20+ import static com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .OrderBySpec .Direction .DESC ;
21+
1922import com .google .common .collect .ImmutableList ;
2023import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .BinaryExpression ;
2124import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .Expression ;
2225import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .Identifier ;
26+ import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .InExpression ;
27+ import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .NaryExpression ;
28+ import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .OrderBySpec ;
2329import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .Projection ;
2430import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .SelectExpression ;
31+ import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .SelectSubqueryExpression ;
2532import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .SourceSpec ;
2633import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .StringLiteral ;
34+ import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .SubqueryExpression ;
35+ import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .SubquerySourceSpec ;
2736import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .TableSourceSpec ;
37+ import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .UnionExpression ;
38+ import com .google .edwmigration .dumper .application .dumper .connector .teradata .query .model .UnionSubqueryExpression ;
2839import java .util .Optional ;
2940import java .util .function .Consumer ;
3041
@@ -44,10 +55,11 @@ public static String serialize(Expression expression) {
4455 String serialize () {
4556 serializedQuery = new StringBuilder ();
4657 append (expression );
47- return serializedQuery .toString ();
58+ return formatQuery ( serializedQuery .toString () );
4859 }
4960
5061 private void append (Expression expr ) {
62+ serializedQuery .append (' ' );
5163 if (expr instanceof SelectExpression ) {
5264 append ((SelectExpression ) expression );
5365 } else if (expr instanceof StringLiteral ) {
@@ -56,22 +68,59 @@ private void append(Expression expr) {
5668 serializedQuery .append (((Identifier ) expr ).name ());
5769 } else if (expr instanceof BinaryExpression ) {
5870 append (((BinaryExpression ) expr ));
71+ } else if (expr instanceof UnionExpression ) {
72+ append (((UnionExpression ) expr ));
73+ } else if (expr instanceof SubqueryExpression ) {
74+ append (((SubqueryExpression ) expr ));
75+ } else if (expr instanceof NaryExpression ) {
76+ append (((NaryExpression ) expr ));
77+ } else if (expr instanceof InExpression ) {
78+ append (((InExpression ) expr ));
5979 } else {
6080 throw new IllegalArgumentException (String .format ("Unsupported expression type: '%s'." , expr ));
6181 }
6282 }
6383
84+ private void append (InExpression expr ) {
85+ append (expr .lhs ());
86+ serializedQuery .append (" IN (" );
87+ appendCommaSeparated (expr .items (), this ::append );
88+ serializedQuery .append (')' );
89+ }
90+
91+ private void append (NaryExpression expr ) {
92+ appendWithSeparators (expr .subexpressions (), expr .operator ().name (), this ::append );
93+ }
94+
6495 private void append (BinaryExpression expr ) {
65- appendSpaceIfNecessary ();
6696 append (expr .lhs ());
6797 serializedQuery .append (' ' );
6898 serializedQuery .append (expr .operator ());
6999 serializedQuery .append (' ' );
70100 append (expr .rhs ());
71101 }
72102
103+ private void append (SubqueryExpression expr ) {
104+ serializedQuery .append ('(' );
105+ if (expr instanceof SelectSubqueryExpression ) {
106+ append (((SelectSubqueryExpression ) expr ).selectExpression ());
107+ } else if (expr instanceof UnionSubqueryExpression ) {
108+ append (((UnionSubqueryExpression ) expr ).unionExpression ());
109+ } else {
110+ throw new IllegalStateException (String .format ("Unsupported subquery expression '%s'" , expr ));
111+ }
112+ serializedQuery .append (')' );
113+ }
114+
115+ private void append (UnionExpression expr ) {
116+ appendWithSeparators (expr .selectExpressions (), "UNION ALL" , this ::append );
117+ }
118+
73119 private void append (SelectExpression selectExpression ) {
74120 serializedQuery .append ("SELECT" );
121+ selectExpression
122+ .topRowCount ()
123+ .ifPresent (rowCount -> serializedQuery .append (" TOP " ).append (rowCount ));
75124 appendCommaSeparated (selectExpression .projections (), this ::append );
76125 selectExpression
77126 .sourceSpec ()
@@ -87,18 +136,36 @@ private void append(SelectExpression selectExpression) {
87136 serializedQuery .append (" WHERE" );
88137 append (condition );
89138 });
139+ if (!selectExpression .orderBySpecs ().isEmpty ()) {
140+ serializedQuery .append (" ORDER BY" );
141+ appendCommaSeparated (selectExpression .orderBySpecs (), this ::append );
142+ }
143+ }
144+
145+ private void append (OrderBySpec orderBySpec ) {
146+ append (orderBySpec .expression ());
147+ if (orderBySpec .direction () == DESC ) {
148+ serializedQuery .append (" DESC" );
149+ }
90150 }
91151
92152 private void append (SourceSpec sourceSpec ) {
153+ serializedQuery .append (' ' );
93154 if (sourceSpec instanceof TableSourceSpec ) {
94155 append ((TableSourceSpec ) sourceSpec );
156+ } else if (sourceSpec instanceof SubquerySourceSpec ) {
157+ append ((SubquerySourceSpec ) sourceSpec );
95158 } else {
96159 throw new IllegalStateException (String .format ("Unsupported source spec='%s'." , sourceSpec ));
97160 }
98161 }
99162
163+ private void append (SubquerySourceSpec sourceSpec ) {
164+ append (sourceSpec .subqueryExpression ());
165+ append (sourceSpec .alias ());
166+ }
167+
100168 private void append (TableSourceSpec tableSourceSpec ) {
101- serializedQuery .append (' ' );
102169 append (tableSourceSpec .tableName ());
103170 append (tableSourceSpec .alias ());
104171 }
@@ -112,19 +179,21 @@ private void append(Optional<String> aliasMaybe) {
112179 aliasMaybe .ifPresent (alias -> serializedQuery .append (" AS " ).append (alias ));
113180 }
114181
115- private void appendSpaceIfNecessary () {
116- if (serializedQuery .length () > 0 ) {
117- serializedQuery .append (' ' );
118- }
182+ private <T > void appendCommaSeparated (ImmutableList <T > list , Consumer <T > appender ) {
183+ appendWithSeparators (list , "," , appender );
119184 }
120185
121- private <T > void appendCommaSeparated (ImmutableList <T > list , Consumer <T > appender ) {
186+ private <T > void appendWithSeparators (
187+ ImmutableList <T > list , String separator , Consumer <T > appender ) {
122188 boolean first = true ;
123189 for (T element : list ) {
124190 if (first ) {
125191 first = false ;
126192 } else {
127- serializedQuery .append (',' );
193+ if (!separator .equals ("," )) {
194+ serializedQuery .append (' ' );
195+ }
196+ serializedQuery .append (separator );
128197 }
129198 serializedQuery .append (' ' );
130199 appender .accept (element );
0 commit comments