Skip to content

Commit d201732

Browse files
authored
feat: SHOW CREATE TABLE add quote for ident (#17505)
Signed-off-by: Kould <[email protected]>
1 parent 8794ca5 commit d201732

File tree

14 files changed

+120
-15
lines changed

14 files changed

+120
-15
lines changed

Diff for: src/query/ast/src/ast/quote.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,16 @@ pub fn ident_needs_quote(ident: &str) -> bool {
5050
false
5151
}
5252

53-
pub fn display_ident(name: &str, quoted_ident_case_sensitive: bool, dialect: Dialect) -> String {
53+
pub fn display_ident(
54+
name: &str,
55+
force_quoted_ident: bool,
56+
quoted_ident_case_sensitive: bool,
57+
dialect: Dialect,
58+
) -> String {
5459
// Db-s -> "Db-s" ; dbs -> dbs
5560
if name.chars().any(|c| c.is_ascii_uppercase()) && quoted_ident_case_sensitive
5661
|| ident_needs_quote(name)
62+
|| force_quoted_ident
5763
{
5864
QuotedIdent(name, dialect.default_ident_quote()).to_string()
5965
} else {

Diff for: src/query/ast/src/ast/statements/table.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ pub struct ShowCreateTableStmt {
7373
pub catalog: Option<Identifier>,
7474
pub database: Option<Identifier>,
7575
pub table: Identifier,
76+
pub with_quoted_ident: bool,
7677
}
7778

7879
impl Display for ShowCreateTableStmt {
@@ -84,7 +85,11 @@ impl Display for ShowCreateTableStmt {
8485
.iter()
8586
.chain(&self.database)
8687
.chain(Some(&self.table)),
87-
)
88+
)?;
89+
if self.with_quoted_ident {
90+
write!(f, " WITH QUOTED_IDENTIFIERS")?
91+
}
92+
Ok(())
8893
}
8994
}
9095

Diff for: src/query/ast/src/parser/statement.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -823,13 +823,14 @@ pub fn statement_body(i: Input) -> IResult<Statement> {
823823
);
824824
let show_create_table = map(
825825
rule! {
826-
SHOW ~ CREATE ~ TABLE ~ #dot_separated_idents_1_to_3
826+
SHOW ~ CREATE ~ TABLE ~ #dot_separated_idents_1_to_3 ~ ( WITH ~ ^QUOTED_IDENTIFIERS )?
827827
},
828-
|(_, _, _, (catalog, database, table))| {
828+
|(_, _, _, (catalog, database, table), comment_opt)| {
829829
Statement::ShowCreateTable(ShowCreateTableStmt {
830830
catalog,
831831
database,
832832
table,
833+
with_quoted_ident: comment_opt.is_some(),
833834
})
834835
},
835836
);

Diff for: src/query/ast/src/parser/token.rs

+2
Original file line numberDiff line numberDiff line change
@@ -942,6 +942,8 @@ pub enum TokenKind {
942942
QUERY,
943943
#[token("QUOTE", ignore(ascii_case))]
944944
QUOTE,
945+
#[token("QUOTED_IDENTIFIERS", ignore(ascii_case))]
946+
QUOTED_IDENTIFIERS,
945947
#[token("RANGE", ignore(ascii_case))]
946948
RANGE,
947949
#[token("RAWDEFLATE", ignore(ascii_case))]

Diff for: src/query/ast/tests/it/parser.rs

+1
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ fn test_statement() {
107107
r#"show processlist like 't%' limit 2;"#,
108108
r#"show processlist where database='default' limit 2;"#,
109109
r#"show create table a.b;"#,
110+
r#"show create table a.b with quoted_identifiers;"#,
110111
r#"show create table a.b format TabSeparatedWithNamesAndTypes;"#,
111112
r#"replace into test on(c) select sum(c) as c from source group by v;"#,
112113
r#"explain pipeline select a from b;"#,

Diff for: src/query/ast/tests/it/testdata/stmt.txt

+33
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,38 @@ ShowCreateTable(
505505
quote: None,
506506
ident_type: None,
507507
},
508+
with_quoted_ident: false,
509+
},
510+
)
511+
512+
513+
---------- Input ----------
514+
show create table a.b with quoted_identifiers;
515+
---------- Output ---------
516+
SHOW CREATE TABLE a.b WITH QUOTED_IDENTIFIERS
517+
---------- AST ------------
518+
ShowCreateTable(
519+
ShowCreateTableStmt {
520+
catalog: None,
521+
database: Some(
522+
Identifier {
523+
span: Some(
524+
18..19,
525+
),
526+
name: "a",
527+
quote: None,
528+
ident_type: None,
529+
},
530+
),
531+
table: Identifier {
532+
span: Some(
533+
20..21,
534+
),
535+
name: "b",
536+
quote: None,
537+
ident_type: None,
538+
},
539+
with_quoted_ident: true,
508540
},
509541
)
510542

@@ -535,6 +567,7 @@ ShowCreateTable(
535567
quote: None,
536568
ident_type: None,
537569
},
570+
with_quoted_ident: false,
538571
},
539572
)
540573

Diff for: src/query/expression/src/utils/display.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1077,5 +1077,5 @@ fn display_f64(num: f64) -> String {
10771077

10781078
/// Display a tuple field name, if it contains uppercase letters or special characters, add quotes.
10791079
pub fn display_tuple_field_name(field_name: &str) -> String {
1080-
display_ident(field_name, true, Dialect::PostgreSQL)
1080+
display_ident(field_name, false, true, Dialect::PostgreSQL)
10811081
}

Diff for: src/query/service/src/interpreters/interpreter_dictionary_show_create.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ impl ShowCreateDictionaryInterpreter {
119119

120120
let mut dict_create_sql = format!(
121121
"CREATE DICTIONARY {}\n(\n",
122-
display_ident(dict_name, quoted_ident_case_sensitive, sql_dialect)
122+
display_ident(dict_name, false, quoted_ident_case_sensitive, sql_dialect)
123123
);
124124

125125
// Append columns and indexes.
@@ -132,7 +132,12 @@ impl ShowCreateDictionaryInterpreter {
132132
.and_then(|c| format!(" COMMENT '{}'", c).into())
133133
.unwrap_or_default();
134134

135-
let ident = display_ident(field.name(), quoted_ident_case_sensitive, sql_dialect);
135+
let ident = display_ident(
136+
field.name(),
137+
false,
138+
quoted_ident_case_sensitive,
139+
sql_dialect,
140+
);
136141
let data_type = field.data_type().sql_name_explicit_null();
137142
let column_str = format!(" {ident} {data_type}{comment}",);
138143

Diff for: src/query/service/src/interpreters/interpreter_table_show_create.rs

+33-5
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ pub struct ShowCreateTableInterpreter {
5252

5353
pub struct ShowCreateQuerySettings {
5454
pub sql_dialect: Dialect,
55+
pub force_quoted_ident: bool,
5556
pub quoted_ident_case_sensitive: bool,
5657
pub hide_options_in_show_create_table: bool,
5758
}
@@ -85,6 +86,7 @@ impl Interpreter for ShowCreateTableInterpreter {
8586

8687
let settings = ShowCreateQuerySettings {
8788
sql_dialect: settings.get_sql_dialect()?,
89+
force_quoted_ident: self.plan.with_quoted_ident,
8890
quoted_ident_case_sensitive: settings.get_quoted_ident_case_sensitive()?,
8991
hide_options_in_show_create_table: settings
9092
.get_hide_options_in_show_create_table()
@@ -144,24 +146,40 @@ impl ShowCreateTableInterpreter {
144146
let field_comments = table.field_comments();
145147
let n_fields = schema.fields().len();
146148
let sql_dialect = settings.sql_dialect;
149+
let force_quoted_ident = settings.force_quoted_ident;
147150
let quoted_ident_case_sensitive = settings.quoted_ident_case_sensitive;
148151
let hide_options_in_show_create_table = settings.hide_options_in_show_create_table;
149152

150153
let mut table_create_sql = format!(
151154
"CREATE TABLE {} (\n",
152-
display_ident(name, quoted_ident_case_sensitive, sql_dialect)
155+
display_ident(
156+
name,
157+
force_quoted_ident,
158+
quoted_ident_case_sensitive,
159+
sql_dialect
160+
)
153161
);
154162
if table.options().contains_key("TRANSIENT") {
155163
table_create_sql = format!(
156164
"CREATE TRANSIENT TABLE {} (\n",
157-
display_ident(name, quoted_ident_case_sensitive, sql_dialect)
165+
display_ident(
166+
name,
167+
force_quoted_ident,
168+
quoted_ident_case_sensitive,
169+
sql_dialect
170+
)
158171
)
159172
}
160173

161174
if table.options().contains_key(OPT_KEY_TEMP_PREFIX) {
162175
table_create_sql = format!(
163176
"CREATE TEMP TABLE {} (\n",
164-
display_ident(name, quoted_ident_case_sensitive, sql_dialect)
177+
display_ident(
178+
name,
179+
force_quoted_ident,
180+
quoted_ident_case_sensitive,
181+
sql_dialect
182+
)
165183
)
166184
}
167185

@@ -198,7 +216,12 @@ impl ShowCreateTableInterpreter {
198216
} else {
199217
"".to_string()
200218
};
201-
let ident = display_ident(field.name(), quoted_ident_case_sensitive, sql_dialect);
219+
let ident = display_ident(
220+
field.name(),
221+
force_quoted_ident,
222+
quoted_ident_case_sensitive,
223+
sql_dialect,
224+
);
202225
let data_type = field.data_type().sql_name_explicit_null();
203226
let column_str =
204227
format!(" {ident} {data_type}{default_expr}{computed_expr}{comment}");
@@ -226,7 +249,12 @@ impl ShowCreateTableInterpreter {
226249
let mut index_str = format!(
227250
" {} INVERTED INDEX {} ({})",
228251
sync,
229-
display_ident(&index_field.name, quoted_ident_case_sensitive, sql_dialect),
252+
display_ident(
253+
&index_field.name,
254+
force_quoted_ident,
255+
quoted_ident_case_sensitive,
256+
sql_dialect
257+
),
230258
column_names_str
231259
);
232260
if !options.is_empty() {

Diff for: src/query/service/src/servers/admin/v1/tenant_tables.rs

+1
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ async fn load_tenant_tables(tenant: &Tenant) -> Result<TenantTablesResponse> {
6666

6767
let settings = ShowCreateQuerySettings {
6868
sql_dialect: Dialect::PostgreSQL,
69+
force_quoted_ident: false,
6970
quoted_ident_case_sensitive: true,
7071
hide_options_in_show_create_table: false,
7172
};

Diff for: src/query/sql/src/planner/binder/copy_into_location.rs

+18-3
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,24 @@ impl Binder {
6969
self.ctx.get_settings().get_quoted_ident_case_sensitive()?;
7070
let subquery = format!(
7171
"SELECT * FROM {}.{}.{}{with_options_str}",
72-
display_ident(&catalog_name, quoted_ident_case_sensitive, self.dialect),
73-
display_ident(&database_name, quoted_ident_case_sensitive, self.dialect),
74-
display_ident(&table_name, quoted_ident_case_sensitive, self.dialect),
72+
display_ident(
73+
&catalog_name,
74+
false,
75+
quoted_ident_case_sensitive,
76+
self.dialect
77+
),
78+
display_ident(
79+
&database_name,
80+
false,
81+
quoted_ident_case_sensitive,
82+
self.dialect
83+
),
84+
display_ident(
85+
&table_name,
86+
false,
87+
quoted_ident_case_sensitive,
88+
self.dialect
89+
),
7590
);
7691
let tokens = tokenize_sql(&subquery)?;
7792
let sub_stmt_msg = parse_sql(&tokens, self.dialect)?;

Diff for: src/query/sql/src/planner/binder/ddl/table.rs

+2
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ impl Binder {
252252
catalog,
253253
database,
254254
table,
255+
with_quoted_ident,
255256
} = stmt;
256257

257258
let (catalog, database, table) =
@@ -266,6 +267,7 @@ impl Binder {
266267
database,
267268
table,
268269
schema,
270+
with_quoted_ident: *with_quoted_ident,
269271
})))
270272
}
271273

Diff for: src/query/sql/src/planner/plans/ddl/table.rs

+1
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ pub struct ShowCreateTablePlan {
383383
pub table: String,
384384
/// The table schema
385385
pub schema: DataSchemaRef,
386+
pub with_quoted_ident: bool,
386387
}
387388

388389
impl ShowCreateTablePlan {

Diff for: tests/sqllogictests/suites/base/06_show/06_0001_show_create_table.test

+5
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ SHOW CREATE TABLE `test`.`a`
1212
----
1313
a CREATE TABLE a ( a BIGINT NOT NULL, b INT NOT NULL DEFAULT 3, c VARCHAR NOT NULL DEFAULT 'x', d SMALLINT NULL, e DATE NOT NULL ) ENGINE=NULL
1414

15+
query TT
16+
SHOW CREATE TABLE `test`.`a` WITH QUOTED_IDENTIFIERS
17+
----
18+
a CREATE TABLE "a" ( "a" BIGINT NOT NULL, "b" INT NOT NULL DEFAULT 3, "c" VARCHAR NOT NULL DEFAULT 'x', "d" SMALLINT NULL, "e" DATE NOT NULL ) ENGINE=NULL
19+
1520
statement ok
1621
CREATE TABLE `test`.`b` ( a bigint not null, b int null default null, c varchar(255) not null, d smallint unsigned null) Engine = Null COMMENT = 'test b'
1722

0 commit comments

Comments
 (0)