21
21
import org .apache .flink .annotation .Internal ;
22
22
import org .apache .flink .table .api .TableException ;
23
23
import org .apache .flink .table .catalog .CatalogBaseTable ;
24
+ import org .apache .flink .table .catalog .CatalogBaseTable .TableKind ;
24
25
import org .apache .flink .table .catalog .CatalogDescriptor ;
25
26
import org .apache .flink .table .catalog .CatalogView ;
26
27
import org .apache .flink .table .catalog .Column ;
28
+ import org .apache .flink .table .catalog .IntervalFreshness ;
27
29
import org .apache .flink .table .catalog .ObjectIdentifier ;
28
30
import org .apache .flink .table .catalog .QueryOperationCatalogView ;
29
31
import org .apache .flink .table .catalog .ResolvedCatalogBaseTable ;
32
+ import org .apache .flink .table .catalog .ResolvedCatalogMaterializedTable ;
30
33
import org .apache .flink .table .catalog .ResolvedCatalogModel ;
31
34
import org .apache .flink .table .catalog .ResolvedCatalogTable ;
32
35
import org .apache .flink .table .catalog .ResolvedSchema ;
38
41
import org .apache .commons .lang3 .StringUtils ;
39
42
40
43
import java .util .List ;
44
+ import java .util .Locale ;
41
45
import java .util .Map ;
42
46
import java .util .Objects ;
43
47
import java .util .Optional ;
@@ -82,12 +86,7 @@ public static String buildShowCreateTableRow(
82
86
ObjectIdentifier tableIdentifier ,
83
87
boolean isTemporary ,
84
88
SqlFactory sqlFactory ) {
85
- if (table .getTableKind () == CatalogBaseTable .TableKind .VIEW ) {
86
- throw new TableException (
87
- String .format (
88
- "SHOW CREATE TABLE is only supported for tables, but %s is a view. Please use SHOW CREATE VIEW instead." ,
89
- tableIdentifier .asSerializableString ()));
90
- }
89
+ validateTableKind (table , tableIdentifier , TableKind .TABLE );
91
90
StringBuilder sb =
92
91
new StringBuilder ()
93
92
.append (buildCreateFormattedPrefix ("TABLE" , isTemporary , tableIdentifier ));
@@ -110,17 +109,40 @@ public static String buildShowCreateTableRow(
110
109
return sb .toString ();
111
110
}
112
111
112
+ /** Show create materialized table statement only for materialized tables. */
113
+ public static String buildShowCreateMaterializedTableRow (
114
+ ResolvedCatalogMaterializedTable table ,
115
+ ObjectIdentifier tableIdentifier ,
116
+ boolean isTemporary ) {
117
+ validateTableKind (table , tableIdentifier , TableKind .MATERIALIZED_TABLE );
118
+ StringBuilder sb =
119
+ new StringBuilder ()
120
+ .append (
121
+ buildCreateFormattedPrefix (
122
+ "MATERIALIZED TABLE" , isTemporary , tableIdentifier ));
123
+ sb .append (extractFormattedColumns (table , PRINT_INDENT ));
124
+ extractFormattedPrimaryKey (table , PRINT_INDENT )
125
+ .ifPresent (pk -> sb .append (",\n " ).append (pk ));
126
+ sb .append ("\n )\n " );
127
+ extractComment (table ).ifPresent (c -> sb .append (formatComment (c )).append ("\n " ));
128
+ extractFormattedPartitionedInfo (table )
129
+ .ifPresent (partitionedBy -> sb .append (formatPartitionedBy (partitionedBy )));
130
+ extractFormattedOptions (table .getOptions (), PRINT_INDENT )
131
+ .ifPresent (v -> sb .append ("WITH (\n " ).append (v ).append ("\n )\n " ));
132
+ sb .append (extractFreshness (table ))
133
+ .append ("\n " )
134
+ .append (extractRefreshMode (table ))
135
+ .append ("\n " );
136
+ sb .append ("AS " ).append (table .getDefinitionQuery ()).append ('\n' );
137
+ return sb .toString ();
138
+ }
139
+
113
140
/** Show create view statement only for views. */
114
141
public static String buildShowCreateViewRow (
115
142
ResolvedCatalogBaseTable <?> view ,
116
143
ObjectIdentifier viewIdentifier ,
117
144
boolean isTemporary ) {
118
- if (view .getTableKind () != CatalogBaseTable .TableKind .VIEW ) {
119
- throw new TableException (
120
- String .format (
121
- "SHOW CREATE VIEW is only supported for views, but %s is a table. Please use SHOW CREATE TABLE instead." ,
122
- viewIdentifier .asSerializableString ()));
123
- }
145
+ validateTableKind (view , viewIdentifier , TableKind .VIEW );
124
146
final CatalogBaseTable origin = view .getOrigin ();
125
147
if (origin instanceof QueryOperationCatalogView
126
148
&& !((QueryOperationCatalogView ) origin ).supportsShowCreateView ()) {
@@ -243,6 +265,10 @@ private static String formatComment(String comment) {
243
265
return String .format ("COMMENT '%s'" , EncodingUtils .escapeSingleQuotes (comment ));
244
266
}
245
267
268
+ private static String formatPartitionedBy (String partitionedByColumns ) {
269
+ return String .format ("PARTITION BY (%s)\n " , partitionedByColumns );
270
+ }
271
+
246
272
static Optional <String > extractComment (ResolvedCatalogBaseTable <?> table ) {
247
273
return StringUtils .isEmpty (table .getComment ())
248
274
? Optional .empty ()
@@ -263,10 +289,32 @@ static Optional<String> extractFormattedPartitionedInfo(ResolvedCatalogTable cat
263
289
if (!catalogTable .isPartitioned ()) {
264
290
return Optional .empty ();
265
291
}
266
- return Optional .of (
267
- catalogTable .getPartitionKeys ().stream ()
268
- .map (EncodingUtils ::escapeIdentifier )
269
- .collect (Collectors .joining (", " )));
292
+ return Optional .of (extractPartitionKeys (catalogTable .getPartitionKeys ()));
293
+ }
294
+
295
+ static Optional <String > extractFormattedPartitionedInfo (
296
+ ResolvedCatalogMaterializedTable catalogMaterializedTable ) {
297
+ if (!catalogMaterializedTable .isPartitioned ()) {
298
+ return Optional .empty ();
299
+ }
300
+ return Optional .of (extractPartitionKeys (catalogMaterializedTable .getPartitionKeys ()));
301
+ }
302
+
303
+ private static String extractPartitionKeys (List <String > partitionKeys ) {
304
+ return partitionKeys .stream ()
305
+ .map (EncodingUtils ::escapeIdentifier )
306
+ .collect (Collectors .joining (", " ));
307
+ }
308
+
309
+ static String extractFreshness (ResolvedCatalogMaterializedTable materializedTable ) {
310
+ final IntervalFreshness definitionFreshness = materializedTable .getDefinitionFreshness ();
311
+ return String .format (
312
+ "FRESHNESS = INTERVAL '%s' %s" ,
313
+ definitionFreshness .getInterval (), definitionFreshness .getTimeUnit ());
314
+ }
315
+
316
+ static String extractRefreshMode (ResolvedCatalogMaterializedTable materializedTable ) {
317
+ return String .format ("REFRESH_MODE = %s" , materializedTable .getRefreshMode ());
270
318
}
271
319
272
320
static Optional <String > extractFormattedOptions (Map <String , String > conf , String printIndent ) {
@@ -297,4 +345,42 @@ static String extractFormattedColumnNames(
297
345
EncodingUtils .escapeIdentifier (column .getName ())))
298
346
.collect (Collectors .joining (",\n " ));
299
347
}
348
+
349
+ private static void validateTableKind (
350
+ ResolvedCatalogBaseTable <?> table ,
351
+ ObjectIdentifier tableIdentifier ,
352
+ TableKind expectedTableKind ) {
353
+ if (table .getTableKind () == expectedTableKind ) {
354
+ return ;
355
+ }
356
+
357
+ final String tableKindName = table .getTableKind ().name ().replace ('_' , ' ' );
358
+ final String commandToUse = showCreateCommandToUse (table .getTableKind ());
359
+ final String expectedTableKindName = expectedTableKind .name ().replace ('_' , ' ' );
360
+ final String currentCommand = "SHOW CREATE " + expectedTableKindName ;
361
+
362
+ throw new TableException (
363
+ String .format (
364
+ "%s is only supported for %ss, but %s is a %s. Please use %s instead." ,
365
+ currentCommand ,
366
+ expectedTableKindName .toLowerCase (Locale .ROOT ),
367
+ tableIdentifier .asSerializableString (),
368
+ tableKindName .toLowerCase (Locale .ROOT ),
369
+ commandToUse ));
370
+ }
371
+
372
+ private static String showCreateCommandToUse (TableKind tableKind ) {
373
+ switch (tableKind ) {
374
+ case MATERIALIZED_TABLE :
375
+ return "SHOW CREATE MATERIALIZED TABLE" ;
376
+ case TABLE :
377
+ return "SHOW CREATE TABLE" ;
378
+ case VIEW :
379
+ return "SHOW CREATE VIEW" ;
380
+ default :
381
+ throw new TableException (
382
+ String .format (
383
+ "SHOW CREATE is not implemented for %s yet." , tableKind .name ()));
384
+ }
385
+ }
300
386
}
0 commit comments