2121import org .apache .flink .annotation .Internal ;
2222import org .apache .flink .table .api .TableException ;
2323import org .apache .flink .table .catalog .CatalogBaseTable ;
24+ import org .apache .flink .table .catalog .CatalogBaseTable .TableKind ;
2425import org .apache .flink .table .catalog .CatalogDescriptor ;
2526import org .apache .flink .table .catalog .CatalogView ;
2627import org .apache .flink .table .catalog .Column ;
28+ import org .apache .flink .table .catalog .IntervalFreshness ;
2729import org .apache .flink .table .catalog .ObjectIdentifier ;
2830import org .apache .flink .table .catalog .QueryOperationCatalogView ;
2931import org .apache .flink .table .catalog .ResolvedCatalogBaseTable ;
32+ import org .apache .flink .table .catalog .ResolvedCatalogMaterializedTable ;
3033import org .apache .flink .table .catalog .ResolvedCatalogModel ;
3134import org .apache .flink .table .catalog .ResolvedCatalogTable ;
3235import org .apache .flink .table .catalog .ResolvedSchema ;
3841import org .apache .commons .lang3 .StringUtils ;
3942
4043import java .util .List ;
44+ import java .util .Locale ;
4145import java .util .Map ;
4246import java .util .Objects ;
4347import java .util .Optional ;
@@ -82,12 +86,7 @@ public static String buildShowCreateTableRow(
8286 ObjectIdentifier tableIdentifier ,
8387 boolean isTemporary ,
8488 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 );
9190 StringBuilder sb =
9291 new StringBuilder ()
9392 .append (buildCreateFormattedPrefix ("TABLE" , isTemporary , tableIdentifier ));
@@ -110,17 +109,40 @@ public static String buildShowCreateTableRow(
110109 return sb .toString ();
111110 }
112111
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+
113140 /** Show create view statement only for views. */
114141 public static String buildShowCreateViewRow (
115142 ResolvedCatalogBaseTable <?> view ,
116143 ObjectIdentifier viewIdentifier ,
117144 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 );
124146 final CatalogBaseTable origin = view .getOrigin ();
125147 if (origin instanceof QueryOperationCatalogView
126148 && !((QueryOperationCatalogView ) origin ).supportsShowCreateView ()) {
@@ -243,6 +265,10 @@ private static String formatComment(String comment) {
243265 return String .format ("COMMENT '%s'" , EncodingUtils .escapeSingleQuotes (comment ));
244266 }
245267
268+ private static String formatPartitionedBy (String partitionedByColumns ) {
269+ return String .format ("PARTITION BY (%s)\n " , partitionedByColumns );
270+ }
271+
246272 static Optional <String > extractComment (ResolvedCatalogBaseTable <?> table ) {
247273 return StringUtils .isEmpty (table .getComment ())
248274 ? Optional .empty ()
@@ -263,10 +289,32 @@ static Optional<String> extractFormattedPartitionedInfo(ResolvedCatalogTable cat
263289 if (!catalogTable .isPartitioned ()) {
264290 return Optional .empty ();
265291 }
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 ());
270318 }
271319
272320 static Optional <String > extractFormattedOptions (Map <String , String > conf , String printIndent ) {
@@ -297,4 +345,42 @@ static String extractFormattedColumnNames(
297345 EncodingUtils .escapeIdentifier (column .getName ())))
298346 .collect (Collectors .joining (",\n " ));
299347 }
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+ }
300386}
0 commit comments