@@ -30,7 +30,7 @@ use risingwave_pb::stream_plan::stream_node::PbNodeBody;
30
30
use risingwave_pb:: stream_plan:: { ProjectNode , StreamFragmentGraph } ;
31
31
use risingwave_sqlparser:: ast:: {
32
32
AlterTableOperation , ColumnDef , ColumnOption , DataType as AstDataType , Encode ,
33
- FormatEncodeOptions , ObjectName , Statement , StructField ,
33
+ FormatEncodeOptions , Ident , ObjectName , Statement , StructField , TableConstraint ,
34
34
} ;
35
35
use risingwave_sqlparser:: parser:: Parser ;
36
36
@@ -43,34 +43,10 @@ use crate::catalog::table_catalog::TableType;
43
43
use crate :: error:: { ErrorCode , Result , RwError } ;
44
44
use crate :: expr:: { Expr , ExprImpl , InputRef , Literal } ;
45
45
use crate :: handler:: create_sink:: { fetch_incoming_sinks, insert_merger_to_union_with_project} ;
46
+ use crate :: handler:: create_table:: bind_table_constraints;
46
47
use crate :: session:: SessionImpl ;
47
48
use crate :: { Binder , TableCatalog , WithOptions } ;
48
49
49
- pub async fn replace_table_with_definition (
50
- session : & Arc < SessionImpl > ,
51
- table_name : ObjectName ,
52
- definition : Statement ,
53
- original_catalog : & Arc < TableCatalog > ,
54
- format_encode : Option < FormatEncodeOptions > ,
55
- ) -> Result < ( ) > {
56
- let ( source, table, graph, col_index_mapping, job_type) = get_replace_table_plan (
57
- session,
58
- table_name,
59
- definition,
60
- original_catalog,
61
- format_encode,
62
- None ,
63
- )
64
- . await ?;
65
-
66
- let catalog_writer = session. catalog_writer ( ) ?;
67
-
68
- catalog_writer
69
- . replace_table ( source, table, graph, col_index_mapping, job_type)
70
- . await ?;
71
- Ok ( ( ) )
72
- }
73
-
74
50
/// Used in auto schema change process
75
51
pub async fn get_new_table_definition_for_cdc_table (
76
52
session : & Arc < SessionImpl > ,
@@ -84,9 +60,11 @@ pub async fn get_new_table_definition_for_cdc_table(
84
60
. context ( "unable to parse original table definition" ) ?
85
61
. try_into ( )
86
62
. unwrap ( ) ;
63
+
87
64
let Statement :: CreateTable {
88
65
columns : original_columns,
89
66
format_encode,
67
+ constraints,
90
68
..
91
69
} = & mut definition
92
70
else {
@@ -98,6 +76,22 @@ pub async fn get_new_table_definition_for_cdc_table(
98
76
"source schema should be None for CDC table"
99
77
) ;
100
78
79
+ if bind_table_constraints ( constraints) ?. is_empty ( ) {
80
+ // For table created by `create table t (*)` the constraint is empty, we need to
81
+ // retrieve primary key names from original table catalog if available
82
+ let pk_names: Vec < _ > = original_catalog
83
+ . pk
84
+ . iter ( )
85
+ . map ( |x| original_catalog. columns [ x. column_index ] . name ( ) . to_string ( ) )
86
+ . collect ( ) ;
87
+
88
+ constraints. push ( TableConstraint :: Unique {
89
+ name : None ,
90
+ columns : pk_names. iter ( ) . map ( Ident :: new_unchecked) . collect ( ) ,
91
+ is_primary : true ,
92
+ } ) ;
93
+ }
94
+
101
95
let orig_column_catalog: HashMap < String , ColumnCatalog > = HashMap :: from_iter (
102
96
original_catalog
103
97
. columns ( )
@@ -163,9 +157,8 @@ fn to_ast_data_type(ty: &DataType) -> Result<AstDataType> {
163
157
pub async fn get_replace_table_plan (
164
158
session : & Arc < SessionImpl > ,
165
159
table_name : ObjectName ,
166
- definition : Statement ,
167
- original_catalog : & Arc < TableCatalog > ,
168
- format_encode : Option < FormatEncodeOptions > ,
160
+ new_definition : Statement ,
161
+ old_catalog : & Arc < TableCatalog > ,
169
162
new_version_columns : Option < Vec < ColumnCatalog > > , // only provided in auto schema change
170
163
) -> Result < (
171
164
Option < Source > ,
@@ -175,8 +168,8 @@ pub async fn get_replace_table_plan(
175
168
TableJobType ,
176
169
) > {
177
170
// Create handler args as if we're creating a new table with the altered definition.
178
- let handler_args = HandlerArgs :: new ( session. clone ( ) , & definition , Arc :: from ( "" ) ) ?;
179
- let col_id_gen = ColumnIdGenerator :: new_alter ( original_catalog ) ;
171
+ let handler_args = HandlerArgs :: new ( session. clone ( ) , & new_definition , Arc :: from ( "" ) ) ?;
172
+ let col_id_gen = ColumnIdGenerator :: new_alter ( old_catalog ) ;
180
173
let Statement :: CreateTable {
181
174
columns,
182
175
constraints,
@@ -186,16 +179,21 @@ pub async fn get_replace_table_plan(
186
179
with_version_column,
187
180
wildcard_idx,
188
181
cdc_table_info,
182
+ format_encode,
189
183
..
190
- } = definition
184
+ } = new_definition
191
185
else {
192
- panic ! ( "unexpected statement type: {:?}" , definition ) ;
186
+ panic ! ( "unexpected statement type: {:?}" , new_definition ) ;
193
187
} ;
194
188
189
+ let format_encode = format_encode
190
+ . clone ( )
191
+ . map ( |format_encode| format_encode. into_v2_with_warning ( ) ) ;
192
+
195
193
let ( mut graph, table, source, job_type) = generate_stream_graph_for_replace_table (
196
194
session,
197
195
table_name,
198
- original_catalog ,
196
+ old_catalog ,
199
197
format_encode,
200
198
handler_args. clone ( ) ,
201
199
col_id_gen,
@@ -213,7 +211,7 @@ pub async fn get_replace_table_plan(
213
211
214
212
// Calculate the mapping from the original columns to the new columns.
215
213
let col_index_mapping = ColIndexMapping :: new (
216
- original_catalog
214
+ old_catalog
217
215
. columns ( )
218
216
. iter ( )
219
217
. map ( |old_c| {
@@ -225,7 +223,7 @@ pub async fn get_replace_table_plan(
225
223
table. columns . len ( ) ,
226
224
) ;
227
225
228
- let incoming_sink_ids: HashSet < _ > = original_catalog . incoming_sinks . iter ( ) . copied ( ) . collect ( ) ;
226
+ let incoming_sink_ids: HashSet < _ > = old_catalog . incoming_sinks . iter ( ) . copied ( ) . collect ( ) ;
229
227
230
228
let target_columns = table
231
229
. columns
@@ -245,7 +243,7 @@ pub async fn get_replace_table_plan(
245
243
// Set some fields ourselves so that the meta service does not need to maintain them.
246
244
let mut table = table;
247
245
table. incoming_sinks = incoming_sink_ids. iter ( ) . copied ( ) . collect ( ) ;
248
- table. maybe_vnode_count = VnodeCount :: set ( original_catalog . vnode_count ( ) ) . to_protobuf ( ) ;
246
+ table. maybe_vnode_count = VnodeCount :: set ( old_catalog . vnode_count ( ) ) . to_protobuf ( ) ;
249
247
250
248
Ok ( ( source, table, graph, col_index_mapping, job_type) )
251
249
}
@@ -332,6 +330,7 @@ pub async fn handle_alter_table_column(
332
330
else {
333
331
panic ! ( "unexpected statement: {:?}" , definition) ;
334
332
} ;
333
+
335
334
let format_encode = format_encode
336
335
. clone ( )
337
336
. map ( |format_encode| format_encode. into_v2_with_warning ( ) ) ;
@@ -455,15 +454,14 @@ pub async fn handle_alter_table_column(
455
454
_ => unreachable ! ( ) ,
456
455
} ;
457
456
458
- replace_table_with_definition (
459
- & session,
460
- table_name,
461
- definition,
462
- & original_catalog,
463
- format_encode,
464
- )
465
- . await ?;
457
+ let ( source, table, graph, col_index_mapping, job_type) =
458
+ get_replace_table_plan ( & session, table_name, definition, & original_catalog, None ) . await ?;
466
459
460
+ let catalog_writer = session. catalog_writer ( ) ?;
461
+
462
+ catalog_writer
463
+ . replace_table ( source, table, graph, col_index_mapping, job_type)
464
+ . await ?;
467
465
Ok ( PgResponse :: empty_result ( StatementType :: ALTER_TABLE ) )
468
466
}
469
467
0 commit comments