21
21
package com .dtstack .flink .sql .side ;
22
22
23
23
import com .dtstack .flink .sql .config .CalciteConfig ;
24
- import com .google .common .base .Strings ;
24
+ import com .dtstack .flink .sql .util .TableUtils ;
25
+ import com .google .common .base .Preconditions ;
25
26
import com .google .common .collect .Lists ;
26
27
import com .google .common .collect .Maps ;
27
28
import com .google .common .collect .Queues ;
@@ -73,15 +74,14 @@ public class SideSQLParser {
73
74
private static final Logger LOG = LoggerFactory .getLogger (SideSQLParser .class );
74
75
75
76
private Map <String , Table > localTableCache = Maps .newHashMap ();
76
- private final char SPLIT = '_' ;
77
77
78
- //regular joins(不带时间窗口) 不允许查询出rowtime或者proctime
79
- private final String SELECT_TEMP_SQL = "select %s from %s %s" ;
78
+ //用来构建临时的中间查询
79
+ private static final String SELECT_TEMP_SQL = "select %s from %s %s" ;
80
80
81
81
public Queue <Object > getExeQueue (String exeSql , Set <String > sideTableSet ) throws SqlParseException {
82
- System .out .println ("---exeSql ---" );
82
+ System .out .println ("----------exec original Sql------- ---" );
83
83
System .out .println (exeSql );
84
- LOG .info ("---exeSql ---" );
84
+ LOG .info ("----------exec original Sql------- ---" );
85
85
LOG .info (exeSql );
86
86
87
87
Queue <Object > queueInfo = Queues .newLinkedBlockingQueue ();
@@ -160,7 +160,7 @@ private Object parseSql(SqlNode sqlNode, Set<String> sideTableSet, Queue<Object>
160
160
if (sqlFrom .getKind () != IDENTIFIER ){
161
161
Object result = parseSql (sqlFrom , sideTableSet , queueInfo , sqlWhere , selectList );
162
162
if (result instanceof JoinInfo ){
163
- return dealSelectResultWithJoinInfo ((JoinInfo ) result , (SqlSelect ) sqlNode , queueInfo );
163
+ return TableUtils . dealSelectResultWithJoinInfo ((JoinInfo ) result , (SqlSelect ) sqlNode , queueInfo );
164
164
}else if (result instanceof AliasInfo ){
165
165
String tableName = ((AliasInfo ) result ).getName ();
166
166
if (sideTableSet .contains (tableName )){
@@ -226,11 +226,6 @@ private AliasInfo getSqlNodeAliasInfo(SqlNode sqlNode) {
226
226
private void convertSideJoinToNewQuery (SqlJoin sqlNode , Set <String > sideTableSet ) {
227
227
checkAndReplaceMultiJoin (sqlNode .getLeft (), sideTableSet );
228
228
checkAndReplaceMultiJoin (sqlNode .getRight (), sideTableSet );
229
-
230
- AliasInfo rightTableAliasInfo = getSqlNodeAliasInfo (sqlNode .getRight ());
231
- if (sideTableSet .contains (rightTableAliasInfo .getName ())){
232
- //构建新的查询
233
- }
234
229
}
235
230
236
231
private SqlBasicCall buildAsSqlNode (String internalTableName , SqlNode newSource ) {
@@ -243,6 +238,15 @@ private SqlBasicCall buildAsSqlNode(String internalTableName, SqlNode newSource)
243
238
return new SqlBasicCall (operator , sqlNodes , sqlParserPos );
244
239
}
245
240
241
+ /**
242
+ * 解析 join 操作
243
+ * @param joinNode
244
+ * @param sideTableSet
245
+ * @param queueInfo
246
+ * @param parentWhere
247
+ * @param parentSelectList
248
+ * @return
249
+ */
246
250
private JoinInfo dealJoinNode (SqlJoin joinNode , Set <String > sideTableSet , Queue <Object > queueInfo ,
247
251
SqlNode parentWhere , SqlNodeList parentSelectList ) {
248
252
SqlNode leftNode = joinNode .getLeft ();
@@ -255,35 +259,36 @@ private JoinInfo dealJoinNode(SqlJoin joinNode, Set<String> sideTableSet, Queue<
255
259
String rightTableAlias = "" ;
256
260
boolean leftTbisTmp = false ;
257
261
258
- Tuple2 <String , String > rightTableNameAndAlias = null ;
262
+ //如果是连续join 判断是否已经处理过添加到执行队列
263
+ Boolean alreadyOffer = false ;
264
+
259
265
if (leftNode .getKind () == IDENTIFIER ){
260
266
leftTbName = leftNode .toString ();
261
267
} else if (leftNode .getKind () == JOIN ) {
262
268
//处理连续join
263
- SqlBasicCall sqlBasicCall = dealNestJoin ((SqlJoin ) leftNode , sideTableSet , queueInfo , parentWhere , parentSelectList );
264
- leftTbName = sqlBasicCall .getOperands ()[0 ].toString ();
265
- leftTbAlias = sqlBasicCall .getOperands ()[1 ].toString ();
269
+ Tuple2 <Boolean , SqlBasicCall > nestJoinResult = dealNestJoin ((SqlJoin ) leftNode , sideTableSet , queueInfo , parentWhere , parentSelectList );
270
+ alreadyOffer = nestJoinResult .f0 ;
271
+ leftTbName = nestJoinResult .f1 .getOperands ()[0 ].toString ();
272
+ leftTbAlias = nestJoinResult .f1 .getOperands ()[1 ].toString ();
266
273
leftTbisTmp = true ;
267
274
} else if (leftNode .getKind () == AS ) {
268
275
AliasInfo aliasInfo = (AliasInfo ) parseSql (leftNode , sideTableSet , queueInfo , parentWhere , parentSelectList );
269
276
leftTbName = aliasInfo .getName ();
270
277
leftTbAlias = aliasInfo .getAlias ();
271
278
272
279
} else {
273
- throw new RuntimeException ("---not deal---" );
280
+ throw new RuntimeException (String . format ( "---not deal node with type %s" , leftNode . getKind (). toString ()) );
274
281
}
275
282
276
283
boolean leftIsSide = checkIsSideTable (leftTbName , sideTableSet );
277
- if (leftIsSide ){
278
- throw new RuntimeException ("side-table must be at the right of join operator" );
279
- }
284
+ Preconditions .checkState (!leftIsSide , "side-table must be at the right of join operator" );
280
285
281
- rightTableNameAndAlias = parseRightNode (rightNode , sideTableSet , queueInfo , parentWhere , parentSelectList );
286
+ Tuple2 < String , String > rightTableNameAndAlias = parseRightNode (rightNode , sideTableSet , queueInfo , parentWhere , parentSelectList );
282
287
rightTableName = rightTableNameAndAlias .f0 ;
283
288
rightTableAlias = rightTableNameAndAlias .f1 ;
284
289
285
290
boolean rightIsSide = checkIsSideTable (rightTableName , sideTableSet );
286
- if (joinType == JoinType .RIGHT ){
291
+ if (rightIsSide && joinType == JoinType .RIGHT ){
287
292
throw new RuntimeException ("side join not support join type of right[current support inner join and left join]" );
288
293
}
289
294
@@ -303,51 +308,22 @@ private JoinInfo dealJoinNode(SqlJoin joinNode, Set<String> sideTableSet, Queue<
303
308
}
304
309
305
310
tableInfo .setLeftIsTmpTable (leftTbisTmp );
306
-
307
311
tableInfo .setLeftIsSideTable (leftIsSide );
308
312
tableInfo .setRightIsSideTable (rightIsSide );
309
313
tableInfo .setLeftNode (leftNode );
310
314
tableInfo .setRightNode (rightNode );
311
315
tableInfo .setJoinType (joinType );
312
316
tableInfo .setCondition (joinNode .getCondition ());
313
317
314
- //TODO 抽取
315
- if (tableInfo .getLeftNode ().getKind () != AS ){
316
- //build 临时中间查询
317
- try {
318
- //父一级的where 条件中如果只和临时查询相关的条件都截取进来
319
- Set <String > fromTableNameSet = Sets .newHashSet ();
320
- List <SqlBasicCall > extractCondition = Lists .newArrayList ();
321
-
322
- getFromTableInfo (tableInfo .getLeftNode (), fromTableNameSet );
323
- checkAndRemoveCondition (fromTableNameSet , (SqlBasicCall ) parentWhere , extractCondition );
324
-
325
- //TODO 查询的字段需要根据最上层的字段中获取,而不是直接设置为*,当然如果上一层就是*另说
326
-
327
- List <String > extractSelectField = extractSelectList (parentSelectList , fromTableNameSet );
328
- String extractSelectFieldStr = buildSelectNode (extractSelectField );
329
- String extractConditionStr = buildCondition (extractCondition );
330
-
331
- String tmpSelectSql = String .format (SELECT_TEMP_SQL ,
332
- extractSelectFieldStr ,
333
- tableInfo .getLeftNode ().toString (),
334
- extractConditionStr );
335
-
336
- SqlParser sqlParser = SqlParser .create (tmpSelectSql , CalciteConfig .MYSQL_LEX_CONFIG );
337
- SqlNode sqlNode = sqlParser .parseStmt ();
338
- SqlBasicCall sqlBasicCall = buildAsSqlNode (tableInfo .getLeftTableAlias (), sqlNode );
339
- queueInfo .offer (sqlBasicCall );
340
-
341
- //TODO 打印合适的提示
342
- System .out .println (tmpSelectSql );
343
- }catch (Exception e ){
344
- e .printStackTrace ();
345
- throw new RuntimeException (e );
346
- }
318
+ if (!rightIsSide || alreadyOffer ){
319
+ return tableInfo ;
320
+ }
347
321
322
+ if (tableInfo .getLeftNode ().getKind () != AS ){
323
+ extractTemporaryQuery (tableInfo .getLeftNode (), tableInfo .getLeftTableAlias (), (SqlBasicCall ) parentWhere , parentSelectList , queueInfo );
348
324
}else {
349
- SqlKind asFirstKind = ((SqlBasicCall )tableInfo .getLeftNode ()).operands [0 ].getKind ();
350
- if (asFirstKind == SELECT ){
325
+ SqlKind asNodeFirstKind = ((SqlBasicCall )tableInfo .getLeftNode ()).operands [0 ].getKind ();
326
+ if (asNodeFirstKind == SELECT ){
351
327
queueInfo .offer (tableInfo .getLeftNode ());
352
328
tableInfo .setLeftNode (((SqlBasicCall )tableInfo .getLeftNode ()).operands [1 ]);
353
329
}
@@ -356,23 +332,24 @@ private JoinInfo dealJoinNode(SqlJoin joinNode, Set<String> sideTableSet, Queue<
356
332
}
357
333
358
334
//构建新的查询
359
- private SqlBasicCall dealNestJoin (SqlJoin joinNode , Set <String > sideTableSet , Queue <Object > queueInfo , SqlNode parentWhere , SqlNodeList selectList ){
335
+ private Tuple2 < Boolean , SqlBasicCall > dealNestJoin (SqlJoin joinNode , Set <String > sideTableSet , Queue <Object > queueInfo , SqlNode parentWhere , SqlNodeList selectList ){
360
336
SqlNode rightNode = joinNode .getRight ();
361
-
362
337
Tuple2 <String , String > rightTableNameAndAlias = parseRightNode (rightNode , sideTableSet , queueInfo , parentWhere , selectList );
363
-
364
338
JoinInfo joinInfo = dealJoinNode (joinNode , sideTableSet , queueInfo , parentWhere , selectList );
365
339
366
340
String rightTableName = rightTableNameAndAlias .f0 ;
367
341
boolean rightIsSide = checkIsSideTable (rightTableName , sideTableSet );
342
+ boolean alreadyOffer = false ;
343
+
368
344
if (!rightIsSide ){
369
345
//右表不是维表的情况
370
346
}else {
371
347
//右边表是维表需要重新构建左表的临时查询
372
348
queueInfo .offer (joinInfo );
349
+ alreadyOffer = true ;
373
350
}
374
351
375
- return buildAsNodeByJoinInfo (joinInfo , null , null );
352
+ return Tuple2 . of ( alreadyOffer , TableUtils . buildAsNodeByJoinInfo (joinInfo , null , null ) );
376
353
}
377
354
378
355
public boolean checkAndRemoveCondition (Set <String > fromTableNameSet , SqlBasicCall parentWhere , List <SqlBasicCall > extractContition ){
@@ -402,6 +379,40 @@ public boolean checkAndRemoveCondition(Set<String> fromTableNameSet, SqlBasicCal
402
379
}
403
380
}
404
381
382
+ private void extractTemporaryQuery (SqlNode node , String tableAlias , SqlBasicCall parentWhere ,
383
+ SqlNodeList parentSelectList , Queue <Object > queueInfo ){
384
+ try {
385
+ //父一级的where 条件中如果只和临时查询相关的条件都截取进来
386
+ Set <String > fromTableNameSet = Sets .newHashSet ();
387
+ List <SqlBasicCall > extractCondition = Lists .newArrayList ();
388
+
389
+ getFromTableInfo (node , fromTableNameSet );
390
+ checkAndRemoveCondition (fromTableNameSet , parentWhere , extractCondition );
391
+
392
+ List <String > extractSelectField = extractSelectList (parentSelectList , fromTableNameSet );
393
+ String extractSelectFieldStr = buildSelectNode (extractSelectField );
394
+ String extractConditionStr = buildCondition (extractCondition );
395
+
396
+ String tmpSelectSql = String .format (SELECT_TEMP_SQL ,
397
+ extractSelectFieldStr ,
398
+ node .toString (),
399
+ extractConditionStr );
400
+
401
+ SqlParser sqlParser = SqlParser .create (tmpSelectSql , CalciteConfig .MYSQL_LEX_CONFIG );
402
+ SqlNode sqlNode = sqlParser .parseStmt ();
403
+ SqlBasicCall sqlBasicCall = buildAsSqlNode (tableAlias , sqlNode );
404
+ queueInfo .offer (sqlBasicCall );
405
+
406
+ //TODO 打印合适的提示
407
+ System .out .println ("-------build temporary query-----------" );
408
+ System .out .println (tmpSelectSql );
409
+ System .out .println ("---------------------------------------" );
410
+ }catch (Exception e ){
411
+ e .printStackTrace ();
412
+ throw new RuntimeException (e );
413
+ }
414
+ }
415
+
405
416
/**
406
417
* 抽取上层需用使用到的字段
407
418
* 由于where字段已经抽取到上一层了所以不用查询出来
@@ -568,71 +579,6 @@ public SqlBasicCall buildDefaultCondition(){
568
579
}
569
580
570
581
571
- /**
572
- *
573
- * @param joinInfo
574
- * @param sqlNode
575
- * @param queueInfo
576
- * @return 两个边关联后的新表表名
577
- */
578
- private String dealSelectResultWithJoinInfo (JoinInfo joinInfo , SqlSelect sqlNode , Queue <Object > queueInfo ) {
579
- //SideJoinInfo rename
580
- if (joinInfo .checkIsSide ()) {
581
- joinInfo .setSelectFields (sqlNode .getSelectList ());
582
- joinInfo .setSelectNode (sqlNode );
583
- if (joinInfo .isRightIsSideTable ()) {
584
- //Analyzing left is not a simple table
585
- if (joinInfo .getLeftNode ().getKind () == SELECT ) {
586
- queueInfo .offer (joinInfo .getLeftNode ());
587
- }
588
-
589
- queueInfo .offer (joinInfo );
590
- } else {
591
- //Determining right is not a simple table
592
- if (joinInfo .getRightNode ().getKind () == SELECT ) {
593
- queueInfo .offer (joinInfo .getLeftNode ());
594
- }
595
-
596
- queueInfo .offer (joinInfo );
597
- }
598
- replaceFromNodeForJoin (joinInfo , sqlNode );
599
- return joinInfo .getNewTableName ();
600
- }
601
- return "" ;
602
- }
603
-
604
- private void replaceFromNodeForJoin (JoinInfo joinInfo , SqlSelect sqlNode ) {
605
- //Update from node
606
- SqlBasicCall sqlBasicCall = buildAsNodeByJoinInfo (joinInfo , null , null );
607
- sqlNode .setFrom (sqlBasicCall );
608
- }
609
-
610
- private SqlBasicCall buildAsNodeByJoinInfo (JoinInfo joinInfo , SqlNode sqlNode0 , String tableAlias ) {
611
- SqlOperator operator = new SqlAsOperator ();
612
-
613
- SqlParserPos sqlParserPos = new SqlParserPos (0 , 0 );
614
- String joinLeftTableName = joinInfo .getLeftTableName ();
615
- String joinLeftTableAlias = joinInfo .getLeftTableAlias ();
616
- joinLeftTableName = Strings .isNullOrEmpty (joinLeftTableName ) ? joinLeftTableAlias : joinLeftTableName ;
617
- String newTableName = buildInternalTableName (joinLeftTableName , SPLIT , joinInfo .getRightTableName ());
618
- String newTableAlias = !StringUtils .isEmpty (tableAlias ) ? tableAlias : buildInternalTableName (joinInfo .getLeftTableAlias (), SPLIT , joinInfo .getRightTableAlias ());
619
-
620
- if (null == sqlNode0 ) {
621
- sqlNode0 = new SqlIdentifier (newTableName , null , sqlParserPos );
622
- }
623
-
624
- SqlIdentifier sqlIdentifierAlias = new SqlIdentifier (newTableAlias , null , sqlParserPos );
625
- SqlNode [] sqlNodes = new SqlNode [2 ];
626
- sqlNodes [0 ] = sqlNode0 ;
627
- sqlNodes [1 ] = sqlIdentifierAlias ;
628
- return new SqlBasicCall (operator , sqlNodes , sqlParserPos );
629
- }
630
-
631
- private String buildInternalTableName (String left , char split , String right ) {
632
- StringBuilder sb = new StringBuilder ();
633
- return sb .append (left ).append (split ).append (right ).toString ();
634
- }
635
-
636
582
private boolean checkIsSideTable (String tableName , Set <String > sideTableList ){
637
583
if (sideTableList .contains (tableName )){
638
584
return true ;
0 commit comments