@@ -30,10 +30,11 @@ use crate::planner::{
30
30
use crate :: utils:: normalize_ident;
31
31
32
32
use arrow_schema:: { DataType , Fields } ;
33
+ use datafusion_common:: error:: _plan_err;
33
34
use datafusion_common:: parsers:: CompressionTypeVariant ;
34
35
use datafusion_common:: {
35
36
exec_err, not_impl_err, plan_datafusion_err, plan_err, schema_err,
36
- unqualified_field_not_found, Column , Constraints , DFSchema , DFSchemaRef ,
37
+ unqualified_field_not_found, Column , Constraint , Constraints , DFSchema , DFSchemaRef ,
37
38
DataFusionError , Result , ScalarValue , SchemaError , SchemaReference , TableReference ,
38
39
ToDFSchema ,
39
40
} ;
@@ -427,7 +428,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
427
428
plan
428
429
} ;
429
430
430
- let constraints = Constraints :: new_from_table_constraints (
431
+ let constraints = Self :: new_constraint_from_table_constraints (
431
432
& all_constraints,
432
433
plan. schema ( ) ,
433
434
) ?;
@@ -452,7 +453,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
452
453
schema,
453
454
} ;
454
455
let plan = LogicalPlan :: EmptyRelation ( plan) ;
455
- let constraints = Constraints :: new_from_table_constraints (
456
+ let constraints = Self :: new_constraint_from_table_constraints (
456
457
& all_constraints,
457
458
plan. schema ( ) ,
458
459
) ?;
@@ -1242,7 +1243,7 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
1242
1243
1243
1244
let name = self . object_name_to_table_reference ( name) ?;
1244
1245
let constraints =
1245
- Constraints :: new_from_table_constraints ( & all_constraints, & df_schema) ?;
1246
+ Self :: new_constraint_from_table_constraints ( & all_constraints, & df_schema) ?;
1246
1247
Ok ( LogicalPlan :: Ddl ( DdlStatement :: CreateExternalTable (
1247
1248
PlanCreateExternalTable {
1248
1249
schema : df_schema,
@@ -1262,6 +1263,74 @@ impl<'a, S: ContextProvider> SqlToRel<'a, S> {
1262
1263
) ) )
1263
1264
}
1264
1265
1266
+ /// Convert each `TableConstraint` to corresponding `Constraint`
1267
+ fn new_constraint_from_table_constraints (
1268
+ constraints : & [ TableConstraint ] ,
1269
+ df_schema : & DFSchemaRef ,
1270
+ ) -> Result < Constraints > {
1271
+ let constraints = constraints
1272
+ . iter ( )
1273
+ . map ( |c : & TableConstraint | match c {
1274
+ TableConstraint :: Unique { name, columns, .. } => {
1275
+ let field_names = df_schema. field_names ( ) ;
1276
+ // Get unique constraint indices in the schema:
1277
+ let indices = columns
1278
+ . iter ( )
1279
+ . map ( |u| {
1280
+ let idx = field_names
1281
+ . iter ( )
1282
+ . position ( |item| * item == u. value )
1283
+ . ok_or_else ( || {
1284
+ let name = name
1285
+ . as_ref ( )
1286
+ . map ( |name| format ! ( "with name '{name}' " ) )
1287
+ . unwrap_or ( "" . to_string ( ) ) ;
1288
+ DataFusionError :: Execution (
1289
+ format ! ( "Column for unique constraint {}not found in schema: {}" , name, u. value)
1290
+ )
1291
+ } ) ?;
1292
+ Ok ( idx)
1293
+ } )
1294
+ . collect :: < Result < Vec < _ > > > ( ) ?;
1295
+ Ok ( Constraint :: Unique ( indices) )
1296
+ }
1297
+ TableConstraint :: PrimaryKey { columns, .. } => {
1298
+ let field_names = df_schema. field_names ( ) ;
1299
+ // Get primary key indices in the schema:
1300
+ let indices = columns
1301
+ . iter ( )
1302
+ . map ( |pk| {
1303
+ let idx = field_names
1304
+ . iter ( )
1305
+ . position ( |item| * item == pk. value )
1306
+ . ok_or_else ( || {
1307
+ DataFusionError :: Execution ( format ! (
1308
+ "Column for primary key not found in schema: {}" ,
1309
+ pk. value
1310
+ ) )
1311
+ } ) ?;
1312
+ Ok ( idx)
1313
+ } )
1314
+ . collect :: < Result < Vec < _ > > > ( ) ?;
1315
+ Ok ( Constraint :: PrimaryKey ( indices) )
1316
+ }
1317
+ TableConstraint :: ForeignKey { .. } => {
1318
+ _plan_err ! ( "Foreign key constraints are not currently supported" )
1319
+ }
1320
+ TableConstraint :: Check { .. } => {
1321
+ _plan_err ! ( "Check constraints are not currently supported" )
1322
+ }
1323
+ TableConstraint :: Index { .. } => {
1324
+ _plan_err ! ( "Indexes are not currently supported" )
1325
+ }
1326
+ TableConstraint :: FulltextOrSpatial { .. } => {
1327
+ _plan_err ! ( "Indexes are not currently supported" )
1328
+ }
1329
+ } )
1330
+ . collect :: < Result < Vec < _ > > > ( ) ?;
1331
+ Ok ( Constraints :: new_unverified ( constraints) )
1332
+ }
1333
+
1265
1334
fn parse_options_map (
1266
1335
& self ,
1267
1336
options : Vec < ( String , Value ) > ,
0 commit comments