2121package com .spotify .dbeam .args ;
2222
2323import com .google .common .collect .ImmutableList ;
24+ import com .google .common .collect .ImmutableSet ;
2425import java .io .Serializable ;
2526import java .util .List ;
2627import java .util .Optional ;
@@ -117,18 +118,24 @@ public int hashCode() {
117118 private final QueryBase base ;
118119 private final List <String > whereConditions ;
119120 private final Optional <String > limitStr ;
121+ private final Optional <ImmutableSet <String >> excludedColumns ;
120122
121123 private QueryBuilder (final QueryBase base ) {
122124 this .base = base ;
123125 this .limitStr = Optional .empty ();
124126 this .whereConditions = ImmutableList .of ();
127+ this .excludedColumns = Optional .empty ();
125128 }
126129
127130 private QueryBuilder (
128- final QueryBase base , final List <String > whereConditions , final Optional <String > limitStr ) {
131+ final QueryBase base ,
132+ final List <String > whereConditions ,
133+ final Optional <String > limitStr ,
134+ final Optional <ImmutableSet <String >> excludedColumns ) {
129135 this .base = base ;
130136 this .whereConditions = whereConditions ;
131137 this .limitStr = limitStr ;
138+ this .excludedColumns = excludedColumns ;
132139 }
133140
134141 public static QueryBuilder fromTablename (final String tableName ) {
@@ -148,7 +155,22 @@ public QueryBuilder withPartitionCondition(
148155 Stream .of (
149156 createSqlPartitionCondition (partitionColumn , startPointIncl , endPointExcl )))
150157 .collect (Collectors .toList ()),
151- this .limitStr );
158+ this .limitStr ,
159+ this .excludedColumns );
160+ }
161+
162+ public QueryBuilder withExcludedColumns (final Optional <ImmutableSet <String >> excludedColumns ) {
163+ if (excludedColumns .isPresent () && this .base instanceof UserQueryBase ) {
164+ UserQueryBase userQueryBase = (UserQueryBase ) this .base ;
165+ String newSqlQuery = rebuildSelectClause (userQueryBase .userSqlQuery , excludedColumns .get ());
166+ return new QueryBuilder (
167+ new UserQueryBase (newSqlQuery , userQueryBase .selectClause ),
168+ this .whereConditions ,
169+ this .limitStr ,
170+ excludedColumns );
171+ } else {
172+ return new QueryBuilder (this .base , this .whereConditions , this .limitStr , excludedColumns );
173+ }
152174 }
153175
154176 private static String createSqlPartitionCondition (
@@ -171,7 +193,8 @@ public QueryBuilder withParallelizationCondition(
171193 createSqlSplitCondition (
172194 partitionColumn , startPointIncl , endPoint , isEndPointExcl )))
173195 .collect (Collectors .toList ()),
174- this .limitStr );
196+ this .limitStr ,
197+ this .excludedColumns );
175198 }
176199
177200 private static String createSqlSplitCondition (
@@ -205,9 +228,38 @@ private static String removeTrailingSymbols(String sqlQuery) {
205228 return sqlQuery .replaceAll (regex , "$1" );
206229 }
207230
231+ private static String rebuildSelectClause (
232+ String sqlQuery , ImmutableSet <String > excludedColumns ) {
233+ String lowerCaseQuery = sqlQuery .toLowerCase ();
234+ int selectIdx = lowerCaseQuery .indexOf ("select" );
235+ int fromIdx = lowerCaseQuery .indexOf ("from" );
236+
237+ if (selectIdx == -1 || fromIdx == -1 || selectIdx > fromIdx ) {
238+ // Cannot parse, return original query
239+ return sqlQuery ;
240+ }
241+
242+ String selectClause = sqlQuery .substring (selectIdx + "select" .length (), fromIdx ).trim ();
243+ String [] columns = selectClause .split ("," );
244+ List <String > newColumns =
245+ Stream .of (columns )
246+ .map (String ::trim )
247+ .filter (column -> !excludedColumns .contains (column ))
248+ .collect (Collectors .toList ());
249+
250+ if (newColumns .isEmpty ()) {
251+ return "SELECT * " + sqlQuery .substring (fromIdx );
252+ } else {
253+ return "SELECT " + String .join (", " , newColumns ) + " " + sqlQuery .substring (fromIdx );
254+ }
255+ }
256+
208257 public QueryBuilder withLimit (long limit ) {
209258 return new QueryBuilder (
210- this .base , this .whereConditions , Optional .of (String .format (" LIMIT %d" , limit )));
259+ this .base ,
260+ this .whereConditions ,
261+ Optional .of (String .format (" LIMIT %d" , limit )),
262+ this .excludedColumns );
211263 }
212264
213265 @ Override
@@ -248,6 +300,11 @@ public QueryBuilder generateQueryToGetLimitsOfSplitColumn(
248300 "SELECT MIN(%s) as %s, MAX(%s) as %s" ,
249301 splitColumn , minSplitColumnName , splitColumn , maxSplitColumnName );
250302
251- return new QueryBuilder (base .withSelect (selectMinMax ), this .whereConditions , this .limitStr );
303+ return new QueryBuilder (
304+ base .withSelect (selectMinMax ),
305+ this .whereConditions ,
306+ this .limitStr ,
307+ this .excludedColumns );
252308 }
253309}
310+
0 commit comments