@@ -21,7 +21,6 @@ import (
21
21
"github.com/cockroachdb/cockroach/pkg/featureflag"
22
22
"github.com/cockroachdb/cockroach/pkg/jobs"
23
23
"github.com/cockroachdb/cockroach/pkg/jobs/jobspb"
24
- "github.com/cockroachdb/cockroach/pkg/keys"
25
24
"github.com/cockroachdb/cockroach/pkg/roachpb"
26
25
"github.com/cockroachdb/cockroach/pkg/security/username"
27
26
"github.com/cockroachdb/cockroach/pkg/server/telemetry"
@@ -33,7 +32,6 @@ import (
33
32
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descpb"
34
33
"github.com/cockroachdb/cockroach/pkg/sql/catalog/descs"
35
34
"github.com/cockroachdb/cockroach/pkg/sql/catalog/resolver"
36
- "github.com/cockroachdb/cockroach/pkg/sql/catalog/schemadesc"
37
35
"github.com/cockroachdb/cockroach/pkg/sql/catalog/schemaexpr"
38
36
"github.com/cockroachdb/cockroach/pkg/sql/catalog/tabledesc"
39
37
"github.com/cockroachdb/cockroach/pkg/sql/exprutil"
@@ -42,7 +40,6 @@ import (
42
40
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
43
41
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgnotice"
44
42
"github.com/cockroachdb/cockroach/pkg/sql/privilege"
45
- "github.com/cockroachdb/cockroach/pkg/sql/sem/catconstants"
46
43
"github.com/cockroachdb/cockroach/pkg/sql/sem/idxtype"
47
44
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
48
45
"github.com/cockroachdb/cockroach/pkg/util"
@@ -346,10 +343,6 @@ func importPlanHook(
346
343
return nil , nil , false , nil
347
344
}
348
345
349
- if ! importStmt .Bundle && ! importStmt .Into {
350
- p .BufferClientNotice (ctx , pgnotice .Newf ("IMPORT TABLE has been deprecated in 21.2, and will be removed in a future version." +
351
- " Instead, use CREATE TABLE with the desired schema, and IMPORT INTO the newly created table." ))
352
- }
353
346
switch f := strings .ToUpper (importStmt .FileFormat ); f {
354
347
case "PGDUMP" , "MYSQLDUMP" :
355
348
p .BufferClientNotice (ctx , pgnotice .Newf (
@@ -456,64 +449,30 @@ func importPlanHook(
456
449
}
457
450
}
458
451
459
- // Typically the SQL grammar means it is only possible to specifying exactly
460
- // one pgdump/mysqldump URI, but glob-expansion could have changed that.
461
- if importStmt .Bundle && len (files ) != 1 {
462
- return pgerror .New (pgcode .FeatureNotSupported , "SQL dump files must be imported individually" )
463
- }
464
-
465
452
table := importStmt .Table
466
- var db catalog.DatabaseDescriptor
467
- var sc catalog.SchemaDescriptor
468
- if table != nil {
469
- // TODO: As part of work for #34240, we should be operating on
470
- // UnresolvedObjectNames here, rather than TableNames.
471
- // We have a target table, so it might specify a DB in its name.
472
- un := table .ToUnresolvedObjectName ()
473
- found , prefix , resPrefix , err := resolver .ResolveTarget (ctx ,
474
- un , p , p .SessionData ().Database , p .SessionData ().SearchPath )
475
- if err != nil {
476
- return pgerror .Wrap (err , pgcode .UndefinedTable ,
477
- "resolving target import name" )
478
- }
479
- if ! found {
480
- // Check if database exists right now. It might not after the import is done,
481
- // but it's better to fail fast than wait until restore.
482
- return pgerror .Newf (pgcode .UndefinedObject ,
483
- "database does not exist: %q" , table )
484
- }
485
- table .ObjectNamePrefix = prefix
486
- db = resPrefix .Database
487
- sc = resPrefix .Schema
488
- // If this is a non-INTO import that will thus be making a new table, we
489
- // need the CREATE priv in the target DB.
490
- if ! importStmt .Into {
491
- if err := p .CheckPrivilege (ctx , db , privilege .CREATE ); err != nil {
492
- return err
493
- }
494
- }
453
+ // TODO: As part of work for #34240, we should be operating on
454
+ // UnresolvedObjectNames here, rather than TableNames.
455
+ // We have a target table, so it might specify a DB in its name.
456
+ un := table .ToUnresolvedObjectName ()
457
+ foundDB , prefix , resPrefix , err := resolver .ResolveTarget (ctx ,
458
+ un , p , p .SessionData ().Database , p .SessionData ().SearchPath )
459
+ if err != nil {
460
+ return pgerror .Wrap (err , pgcode .UndefinedTable ,
461
+ "resolving target import name" )
462
+ }
463
+ if ! foundDB {
464
+ // Check if database exists right now. It might not after the import is done,
465
+ // but it's better to fail fast than wait until restore.
466
+ return pgerror .Newf (pgcode .UndefinedObject ,
467
+ "database does not exist: %q" , table )
468
+ }
469
+ table .ObjectNamePrefix = prefix
470
+ db := resPrefix .Database
495
471
496
- switch sc .SchemaKind () {
497
- case catalog .SchemaVirtual :
498
- return pgerror .Newf (pgcode .InvalidSchemaName ,
499
- "cannot import into schema %q" , table .SchemaName )
500
- }
501
- } else {
502
- // No target table means we're importing whatever we find into the session
503
- // database, so it must exist.
504
- db , err = p .MustGetCurrentSessionDatabase (ctx )
505
- if err != nil {
506
- return pgerror .Wrap (err , pgcode .UndefinedObject ,
507
- "could not resolve current database" )
508
- }
509
- // If this is a non-INTO import that will thus be making a new table, we
510
- // need the CREATE priv in the target DB.
511
- if ! importStmt .Into {
512
- if err := p .CheckPrivilege (ctx , db , privilege .CREATE ); err != nil {
513
- return err
514
- }
515
- }
516
- sc = schemadesc .GetPublicSchema ()
472
+ switch resPrefix .Schema .SchemaKind () {
473
+ case catalog .SchemaVirtual :
474
+ return pgerror .Newf (pgcode .InvalidSchemaName ,
475
+ "cannot import into schema %q" , table .SchemaName )
517
476
}
518
477
519
478
format := roachpb.IOFileFormat {}
@@ -766,123 +725,92 @@ func importPlanHook(
766
725
return err
767
726
}
768
727
769
- if importStmt .Into {
770
- if _ , ok := allowedIntoFormats [importStmt .FileFormat ]; ! ok {
771
- return errors .Newf (
772
- "%s file format is currently unsupported by IMPORT INTO" ,
773
- importStmt .FileFormat )
774
- }
775
- _ , found , err := p .ResolveMutableTableDescriptor (ctx , table , true , tree .ResolveRequireTableDesc )
776
- if err != nil {
777
- return err
728
+ if _ , ok := allowedIntoFormats [importStmt .FileFormat ]; ! ok {
729
+ return errors .Newf (
730
+ "%s file format is currently unsupported by IMPORT INTO" ,
731
+ importStmt .FileFormat )
732
+ }
733
+ _ , found , err := p .ResolveMutableTableDescriptor (ctx , table , true , tree .ResolveRequireTableDesc )
734
+ if err != nil {
735
+ return err
736
+ }
737
+
738
+ err = ensureRequiredPrivileges (ctx , importIntoRequiredPrivileges , p , found )
739
+ if err != nil {
740
+ return err
741
+ }
742
+ // Check if the table has any vector indexes
743
+ for _ , idx := range found .NonDropIndexes () {
744
+ if idx .GetType () == idxtype .VECTOR {
745
+ return unimplemented .NewWithIssueDetail (145227 , "import.vector-index" ,
746
+ "IMPORT INTO is not supported for tables with vector indexes" )
778
747
}
748
+ }
749
+
750
+ if len (found .LDRJobIDs ) > 0 {
751
+ return errors .Newf ("cannot run an import on table %s which is apart of a Logical Data Replication stream" , table )
752
+ }
779
753
780
- err = ensureRequiredPrivileges (ctx , importIntoRequiredPrivileges , p , found )
754
+ // Import into an RLS table is blocked, unless this is the admin. It is
755
+ // allowed for admins since they are exempt from RLS policies and have
756
+ // unrestricted read/write access.
757
+ if found .IsRowLevelSecurityEnabled () {
758
+ admin , err := p .HasAdminRole (ctx )
781
759
if err != nil {
782
760
return err
761
+ } else if ! admin {
762
+ return pgerror .New (pgcode .FeatureNotSupported ,
763
+ "IMPORT INTO not supported with row-level security for non-admin users" )
783
764
}
784
- // Check if the table has any vector indexes
785
- for _ , idx := range found .NonDropIndexes () {
786
- if idx .GetType () == idxtype .VECTOR {
787
- return unimplemented .NewWithIssueDetail (145227 , "import.vector-index" ,
788
- "IMPORT INTO is not supported for tables with vector indexes" )
789
- }
790
- }
765
+ }
791
766
792
- if len (found .LDRJobIDs ) > 0 {
793
- return errors .Newf ("cannot run an import on table %s which is apart of a Logical Data Replication stream" , table )
767
+ // Validate target columns.
768
+ var intoCols []string
769
+ isTargetCol := make (map [string ]bool )
770
+ for _ , name := range importStmt .IntoCols {
771
+ active , err := catalog .MustFindPublicColumnsByNameList (found , tree.NameList {name })
772
+ if err != nil {
773
+ return errors .Wrap (err , "verifying target columns" )
794
774
}
795
775
796
- // Import into an RLS table is blocked, unless this is the admin. It is
797
- // allowed for admins since they are exempt from RLS policies and have
798
- // unrestricted read/write access.
799
- if found .IsRowLevelSecurityEnabled () {
800
- admin , err := p .HasAdminRole (ctx )
801
- if err != nil {
802
- return err
803
- } else if ! admin {
804
- return pgerror .New (pgcode .FeatureNotSupported ,
805
- "IMPORT INTO not supported with row-level security for non-admin users" )
806
- }
807
- }
776
+ isTargetCol [active [0 ].GetName ()] = true
777
+ intoCols = append (intoCols , active [0 ].GetName ())
778
+ }
808
779
809
- // Validate target columns.
810
- var intoCols []string
811
- isTargetCol := make (map [string ]bool )
812
- for _ , name := range importStmt .IntoCols {
813
- active , err := catalog .MustFindPublicColumnsByNameList (found , tree.NameList {name })
814
- if err != nil {
815
- return errors .Wrap (err , "verifying target columns" )
780
+ // Ensure that non-target columns that don't have default
781
+ // expressions are nullable.
782
+ if len (isTargetCol ) != 0 {
783
+ for _ , col := range found .VisibleColumns () {
784
+ if ! (isTargetCol [col .GetName ()] || col .IsNullable () || col .HasDefault () || col .IsComputed ()) {
785
+ return errors .Newf (
786
+ "all non-target columns in IMPORT INTO must be nullable " +
787
+ "or have default expressions, or have computed expressions" +
788
+ " but violated by column %q" ,
789
+ col .GetName (),
790
+ )
816
791
}
817
-
818
- isTargetCol [active [0 ].GetName ()] = true
819
- intoCols = append (intoCols , active [0 ].GetName ())
820
- }
821
-
822
- // Ensure that non-target columns that don't have default
823
- // expressions are nullable.
824
- if len (isTargetCol ) != 0 {
825
- for _ , col := range found .VisibleColumns () {
826
- if ! (isTargetCol [col .GetName ()] || col .IsNullable () || col .HasDefault () || col .IsComputed ()) {
827
- return errors .Newf (
828
- "all non-target columns in IMPORT INTO must be nullable " +
829
- "or have default expressions, or have computed expressions" +
830
- " but violated by column %q" ,
831
- col .GetName (),
832
- )
833
- }
834
- if isTargetCol [col .GetName ()] && col .IsComputed () {
835
- return schemaexpr .CannotWriteToComputedColError (col .GetName ())
836
- }
792
+ if isTargetCol [col .GetName ()] && col .IsComputed () {
793
+ return schemaexpr .CannotWriteToComputedColError (col .GetName ())
837
794
}
838
795
}
796
+ }
839
797
840
- {
841
- // Resolve the UDTs used by the table being imported into.
842
- typeDescs , err := resolveUDTsUsedByImportInto (ctx , p , found )
843
- if err != nil {
844
- return errors .Wrap (err , "resolving UDTs used by table being imported into" )
845
- }
846
- if len (typeDescs ) > 0 {
847
- typeDetails = make ([]jobspb.ImportDetails_Type , 0 , len (typeDescs ))
848
- }
849
- for _ , typeDesc := range typeDescs {
850
- typeDetails = append (typeDetails , jobspb.ImportDetails_Type {Desc : typeDesc .TypeDesc ()})
851
- }
798
+ {
799
+ // Resolve the UDTs used by the table being imported into.
800
+ typeDescs , err := resolveUDTsUsedByImportInto (ctx , p , found )
801
+ if err != nil {
802
+ return errors .Wrap (err , "resolving UDTs used by table being imported into" )
852
803
}
853
-
854
- tableDetails = []jobspb.ImportDetails_Table {{Desc : & found .TableDescriptor , IsNew : false , TargetCols : intoCols }}
855
- } else if importStmt .Bundle {
856
- // If we target a single table, populate details with one entry of tableName.
857
- if table != nil {
858
- tableDetails = make ([]jobspb.ImportDetails_Table , 1 )
859
- tableName := table .ObjectName .String ()
860
- // PGDUMP supports importing tables from non-public schemas, thus we
861
- // must prepend the target table name with the target schema name.
862
- if format .Format == roachpb .IOFileFormat_PgDump {
863
- if table .Schema () == "" {
864
- return errors .Newf ("expected schema for target table %s to be resolved" ,
865
- tableName )
866
- }
867
- tableName = fmt .Sprintf ("%s.%s" , table .SchemaName .String (),
868
- table .ObjectName .String ())
869
- }
870
- tableDetails [0 ] = jobspb.ImportDetails_Table {
871
- Name : tableName ,
872
- IsNew : true ,
873
- }
804
+ if len (typeDescs ) > 0 {
805
+ typeDetails = make ([]jobspb.ImportDetails_Type , 0 , len (typeDescs ))
874
806
}
875
-
876
- // Due to how we generate and rewrite descriptor ID's for import, we run
877
- // into problems when using user defined schemas.
878
- publicSchemaID := db .GetSchemaID (catconstants .PublicSchemaName )
879
- if sc .GetID () != publicSchemaID && sc .GetID () != keys .PublicSchemaID {
880
- err := errors .New ("cannot use IMPORT with a user defined schema" )
881
- hint := errors .WithHint (err , "create the table with CREATE TABLE and use IMPORT INTO instead" )
882
- return hint
807
+ for _ , typeDesc := range typeDescs {
808
+ typeDetails = append (typeDetails , jobspb.ImportDetails_Type {Desc : typeDesc .TypeDesc ()})
883
809
}
884
810
}
885
811
812
+ tableDetails = []jobspb.ImportDetails_Table {{Desc : & found .TableDescriptor , IsNew : false , TargetCols : intoCols }}
813
+
886
814
// Store the primary region of the database being imported into. This is
887
815
// used during job execution to evaluate certain default expressions and
888
816
// computed columns such as `gateway_region`.
@@ -919,9 +847,7 @@ func importPlanHook(
919
847
break
920
848
}
921
849
}
922
- if importStmt .Into {
923
- telemetry .Count ("import.into" )
924
- }
850
+ telemetry .Count ("import.into" )
925
851
926
852
// Here we create the job in a side transaction and then kick off the job.
927
853
// This is awful. Rather we should be disallowing this statement in an
@@ -936,7 +862,6 @@ func importPlanHook(
936
862
Tables : tableDetails ,
937
863
Types : typeDetails ,
938
864
SkipFKs : skipFKs ,
939
- ParseBundleSchema : importStmt .Bundle ,
940
865
DefaultIntSize : p .SessionData ().DefaultIntSize ,
941
866
DatabasePrimaryRegion : databasePrimaryRegion ,
942
867
}
0 commit comments