@@ -518,7 +518,11 @@ impl Catalog for SqlCatalog {
518
518
{CATALOG_FIELD_TABLE_NAMESPACE}
519
519
FROM {CATALOG_TABLE_NAME}
520
520
WHERE {CATALOG_FIELD_TABLE_NAMESPACE} = ?
521
- AND {CATALOG_FIELD_CATALOG_NAME} = ?"
521
+ AND {CATALOG_FIELD_CATALOG_NAME} = ?
522
+ AND (
523
+ {CATALOG_FIELD_RECORD_TYPE} = '{CATALOG_FIELD_TABLE_RECORD_TYPE}'
524
+ OR {CATALOG_FIELD_RECORD_TYPE} IS NULL
525
+ )" ,
522
526
) ,
523
527
vec ! [ Some ( & namespace. join( "." ) ) , Some ( & self . name) ] ,
524
528
)
@@ -553,7 +557,11 @@ impl Catalog for SqlCatalog {
553
557
FROM {CATALOG_TABLE_NAME}
554
558
WHERE {CATALOG_FIELD_TABLE_NAMESPACE} = ?
555
559
AND {CATALOG_FIELD_CATALOG_NAME} = ?
556
- AND {CATALOG_FIELD_TABLE_NAME} = ?"
560
+ AND {CATALOG_FIELD_TABLE_NAME} = ?
561
+ AND (
562
+ {CATALOG_FIELD_RECORD_TYPE} = '{CATALOG_FIELD_TABLE_RECORD_TYPE}'
563
+ OR {CATALOG_FIELD_RECORD_TYPE} IS NULL
564
+ )"
557
565
) ,
558
566
vec ! [ Some ( & namespace) , Some ( & self . name) , Some ( table_name) ] ,
559
567
)
@@ -566,8 +574,32 @@ impl Catalog for SqlCatalog {
566
574
}
567
575
}
568
576
569
- async fn drop_table ( & self , _identifier : & TableIdent ) -> Result < ( ) > {
570
- todo ! ( )
577
+ async fn drop_table ( & self , identifier : & TableIdent ) -> Result < ( ) > {
578
+ if !self . table_exists ( identifier) . await ? {
579
+ return no_such_table_err ( identifier) ;
580
+ }
581
+
582
+ self . execute (
583
+ & format ! (
584
+ "DELETE FROM {CATALOG_TABLE_NAME}
585
+ WHERE {CATALOG_FIELD_CATALOG_NAME} = ?
586
+ AND {CATALOG_FIELD_TABLE_NAMESPACE} = ?
587
+ AND {CATALOG_FIELD_TABLE_NAME} = ?
588
+ AND (
589
+ {CATALOG_FIELD_RECORD_TYPE} = '{CATALOG_FIELD_TABLE_RECORD_TYPE}'
590
+ OR {CATALOG_FIELD_RECORD_TYPE} IS NULL
591
+ )"
592
+ ) ,
593
+ vec ! [
594
+ Some ( & self . name) ,
595
+ Some ( identifier. name( ) ) ,
596
+ Some ( & identifier. namespace( ) . join( "." ) ) ,
597
+ ] ,
598
+ None ,
599
+ )
600
+ . await ?;
601
+
602
+ Ok ( ( ) )
571
603
}
572
604
573
605
async fn load_table ( & self , identifier : & TableIdent ) -> Result < Table > {
@@ -674,8 +706,10 @@ impl Catalog for SqlCatalog {
674
706
. await ?;
675
707
676
708
self . execute ( & format ! (
677
- "INSERT INTO {CATALOG_TABLE_NAME} ({CATALOG_FIELD_CATALOG_NAME}, {CATALOG_FIELD_TABLE_NAMESPACE}, {CATALOG_FIELD_TABLE_NAME}, {CATALOG_FIELD_METADATA_LOCATION_PROP})
678
- VALUES (?, ?, ?, ?)" ) , vec ! [ Some ( & self . name) , Some ( & namespace. join( "." ) ) , Some ( & tbl_name. clone( ) ) , Some ( & tbl_metadata_location) ] , None ) . await ?;
709
+ "INSERT INTO {CATALOG_TABLE_NAME}
710
+ ({CATALOG_FIELD_CATALOG_NAME}, {CATALOG_FIELD_TABLE_NAMESPACE}, {CATALOG_FIELD_TABLE_NAME}, {CATALOG_FIELD_METADATA_LOCATION_PROP}, {CATALOG_FIELD_RECORD_TYPE})
711
+ VALUES (?, ?, ?, ?, ?)
712
+ " ) , vec ! [ Some ( & self . name) , Some ( & namespace. join( "." ) ) , Some ( & tbl_name. clone( ) ) , Some ( & tbl_metadata_location) , Some ( CATALOG_FIELD_TABLE_RECORD_TYPE ) ] , None ) . await ?;
679
713
680
714
Ok ( Table :: builder ( )
681
715
. file_io ( self . fileio . clone ( ) )
@@ -685,8 +719,47 @@ impl Catalog for SqlCatalog {
685
719
. build ( ) ?)
686
720
}
687
721
688
- async fn rename_table ( & self , _src : & TableIdent , _dest : & TableIdent ) -> Result < ( ) > {
689
- todo ! ( )
722
+ async fn rename_table ( & self , src : & TableIdent , dest : & TableIdent ) -> Result < ( ) > {
723
+ if src == dest {
724
+ return Ok ( ( ) ) ;
725
+ }
726
+
727
+ if !self . table_exists ( src) . await ? {
728
+ return no_such_table_err ( src) ;
729
+ }
730
+
731
+ if !self . namespace_exists ( dest. namespace ( ) ) . await ? {
732
+ return no_such_namespace_err ( dest. namespace ( ) ) ;
733
+ }
734
+
735
+ if self . table_exists ( dest) . await ? {
736
+ return table_already_exists_err ( dest) ;
737
+ }
738
+
739
+ self . execute (
740
+ & format ! (
741
+ "UPDATE {CATALOG_TABLE_NAME}
742
+ SET {CATALOG_FIELD_TABLE_NAME} = ?, {CATALOG_FIELD_TABLE_NAMESPACE} = ?
743
+ WHERE {CATALOG_FIELD_CATALOG_NAME} = ?
744
+ AND {CATALOG_FIELD_TABLE_NAME} = ?
745
+ AND {CATALOG_FIELD_TABLE_NAMESPACE} = ?
746
+ AND (
747
+ {CATALOG_FIELD_RECORD_TYPE} = '{CATALOG_FIELD_TABLE_RECORD_TYPE}'
748
+ OR {CATALOG_FIELD_RECORD_TYPE} IS NULL
749
+ )"
750
+ ) ,
751
+ vec ! [
752
+ Some ( dest. name( ) ) ,
753
+ Some ( & dest. namespace( ) . join( "." ) ) ,
754
+ Some ( & self . name) ,
755
+ Some ( src. name( ) ) ,
756
+ Some ( & src. namespace( ) . join( "." ) ) ,
757
+ ] ,
758
+ None ,
759
+ )
760
+ . await ?;
761
+
762
+ Ok ( ( ) )
690
763
}
691
764
692
765
async fn update_table ( & self , _commit : TableCommit ) -> Result < Table > {
@@ -711,6 +784,8 @@ mod tests {
711
784
use crate :: catalog:: NAMESPACE_LOCATION_PROPERTY_KEY ;
712
785
use crate :: { SqlBindStyle , SqlCatalog , SqlCatalogConfig } ;
713
786
787
+ const UUID_REGEX_STR : & str = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" ;
788
+
714
789
fn temp_path ( ) -> String {
715
790
let temp_dir = TempDir :: new ( ) . unwrap ( ) ;
716
791
temp_dir. path ( ) . to_str ( ) . unwrap ( ) . to_string ( )
@@ -778,7 +853,11 @@ mod tests {
778
853
. unwrap ( ) ;
779
854
}
780
855
781
- const UUID_REGEX_STR : & str = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" ;
856
+ async fn create_tables < C : Catalog > ( catalog : & C , table_idents : Vec < & TableIdent > ) {
857
+ for table_ident in table_idents {
858
+ create_table ( catalog, table_ident) . await ;
859
+ }
860
+ }
782
861
783
862
fn assert_table_eq ( table : & Table , expected_table_ident : & TableIdent , expected_schema : & Schema ) {
784
863
assert_eq ! ( table. identifier( ) , expected_table_ident) ;
@@ -1470,4 +1549,165 @@ mod tests {
1470
1549
)
1471
1550
) ;
1472
1551
}
1552
+
1553
+ #[ tokio:: test]
1554
+ async fn test_rename_table_in_same_namespace ( ) {
1555
+ let warehouse_loc = temp_path ( ) ;
1556
+ let catalog = new_sql_catalog ( warehouse_loc) . await ;
1557
+ let namespace_ident = NamespaceIdent :: new ( "n1" . into ( ) ) ;
1558
+ create_namespace ( & catalog, & namespace_ident) . await ;
1559
+ let src_table_ident = TableIdent :: new ( namespace_ident. clone ( ) , "tbl1" . into ( ) ) ;
1560
+ let dst_table_ident = TableIdent :: new ( namespace_ident. clone ( ) , "tbl2" . into ( ) ) ;
1561
+ create_table ( & catalog, & src_table_ident) . await ;
1562
+
1563
+ catalog
1564
+ . rename_table ( & src_table_ident, & dst_table_ident)
1565
+ . await
1566
+ . unwrap ( ) ;
1567
+
1568
+ assert_eq ! ( catalog. list_tables( & namespace_ident) . await . unwrap( ) , vec![
1569
+ dst_table_ident
1570
+ ] , ) ;
1571
+ }
1572
+
1573
+ #[ tokio:: test]
1574
+ async fn test_rename_table_across_namespaces ( ) {
1575
+ let warehouse_loc = temp_path ( ) ;
1576
+ let catalog = new_sql_catalog ( warehouse_loc) . await ;
1577
+ let src_namespace_ident = NamespaceIdent :: new ( "a" . into ( ) ) ;
1578
+ let dst_namespace_ident = NamespaceIdent :: new ( "b" . into ( ) ) ;
1579
+ create_namespaces ( & catalog, & vec ! [ & src_namespace_ident, & dst_namespace_ident] ) . await ;
1580
+ let src_table_ident = TableIdent :: new ( src_namespace_ident. clone ( ) , "tbl1" . into ( ) ) ;
1581
+ let dst_table_ident = TableIdent :: new ( dst_namespace_ident. clone ( ) , "tbl2" . into ( ) ) ;
1582
+ create_table ( & catalog, & src_table_ident) . await ;
1583
+
1584
+ catalog
1585
+ . rename_table ( & src_table_ident, & dst_table_ident)
1586
+ . await
1587
+ . unwrap ( ) ;
1588
+
1589
+ assert_eq ! (
1590
+ catalog. list_tables( & src_namespace_ident) . await . unwrap( ) ,
1591
+ vec![ ] ,
1592
+ ) ;
1593
+
1594
+ assert_eq ! (
1595
+ catalog. list_tables( & dst_namespace_ident) . await . unwrap( ) ,
1596
+ vec![ dst_table_ident] ,
1597
+ ) ;
1598
+ }
1599
+
1600
+ #[ tokio:: test]
1601
+ async fn test_rename_table_src_table_is_same_as_dst_table ( ) {
1602
+ let warehouse_loc = temp_path ( ) ;
1603
+ let catalog = new_sql_catalog ( warehouse_loc) . await ;
1604
+ let namespace_ident = NamespaceIdent :: new ( "n1" . into ( ) ) ;
1605
+ create_namespace ( & catalog, & namespace_ident) . await ;
1606
+ let table_ident = TableIdent :: new ( namespace_ident. clone ( ) , "tbl" . into ( ) ) ;
1607
+ create_table ( & catalog, & table_ident) . await ;
1608
+
1609
+ catalog
1610
+ . rename_table ( & table_ident, & table_ident)
1611
+ . await
1612
+ . unwrap ( ) ;
1613
+
1614
+ assert_eq ! ( catalog. list_tables( & namespace_ident) . await . unwrap( ) , vec![
1615
+ table_ident
1616
+ ] , ) ;
1617
+ }
1618
+
1619
+ #[ tokio:: test]
1620
+ async fn test_rename_table_across_nested_namespaces ( ) {
1621
+ let warehouse_loc = temp_path ( ) ;
1622
+ let catalog = new_sql_catalog ( warehouse_loc) . await ;
1623
+ let namespace_ident_a = NamespaceIdent :: new ( "a" . into ( ) ) ;
1624
+ let namespace_ident_a_b = NamespaceIdent :: from_strs ( vec ! [ "a" , "b" ] ) . unwrap ( ) ;
1625
+ let namespace_ident_a_b_c = NamespaceIdent :: from_strs ( vec ! [ "a" , "b" , "c" ] ) . unwrap ( ) ;
1626
+ create_namespaces ( & catalog, & vec ! [
1627
+ & namespace_ident_a,
1628
+ & namespace_ident_a_b,
1629
+ & namespace_ident_a_b_c,
1630
+ ] )
1631
+ . await ;
1632
+
1633
+ let src_table_ident = TableIdent :: new ( namespace_ident_a_b_c. clone ( ) , "tbl1" . into ( ) ) ;
1634
+ create_tables ( & catalog, vec ! [ & src_table_ident] ) . await ;
1635
+
1636
+ let dst_table_ident = TableIdent :: new ( namespace_ident_a_b. clone ( ) , "tbl1" . into ( ) ) ;
1637
+ catalog
1638
+ . rename_table ( & src_table_ident, & dst_table_ident)
1639
+ . await
1640
+ . unwrap ( ) ;
1641
+
1642
+ assert ! ( !catalog. table_exists( & src_table_ident) . await . unwrap( ) ) ;
1643
+
1644
+ assert ! ( catalog. table_exists( & dst_table_ident) . await . unwrap( ) ) ;
1645
+ }
1646
+
1647
+ #[ tokio:: test]
1648
+ async fn test_rename_table_throws_error_if_dst_namespace_doesnt_exist ( ) {
1649
+ let warehouse_loc = temp_path ( ) ;
1650
+ let catalog = new_sql_catalog ( warehouse_loc) . await ;
1651
+ let src_namespace_ident = NamespaceIdent :: new ( "n1" . into ( ) ) ;
1652
+ let src_table_ident = TableIdent :: new ( src_namespace_ident. clone ( ) , "tbl1" . into ( ) ) ;
1653
+ create_namespace ( & catalog, & src_namespace_ident) . await ;
1654
+ create_table ( & catalog, & src_table_ident) . await ;
1655
+
1656
+ let non_existent_dst_namespace_ident = NamespaceIdent :: new ( "n2" . into ( ) ) ;
1657
+ let dst_table_ident =
1658
+ TableIdent :: new ( non_existent_dst_namespace_ident. clone ( ) , "tbl1" . into ( ) ) ;
1659
+ assert_eq ! (
1660
+ catalog
1661
+ . rename_table( & src_table_ident, & dst_table_ident)
1662
+ . await
1663
+ . unwrap_err( )
1664
+ . to_string( ) ,
1665
+ format!(
1666
+ "Unexpected => No such namespace: {:?}" ,
1667
+ non_existent_dst_namespace_ident
1668
+ ) ,
1669
+ ) ;
1670
+ }
1671
+
1672
+ #[ tokio:: test]
1673
+ async fn test_rename_table_throws_error_if_src_table_doesnt_exist ( ) {
1674
+ let warehouse_loc = temp_path ( ) ;
1675
+ let catalog = new_sql_catalog ( warehouse_loc) . await ;
1676
+ let namespace_ident = NamespaceIdent :: new ( "n1" . into ( ) ) ;
1677
+ create_namespace ( & catalog, & namespace_ident) . await ;
1678
+ let src_table_ident = TableIdent :: new ( namespace_ident. clone ( ) , "tbl1" . into ( ) ) ;
1679
+ let dst_table_ident = TableIdent :: new ( namespace_ident. clone ( ) , "tbl2" . into ( ) ) ;
1680
+
1681
+ assert_eq ! (
1682
+ catalog
1683
+ . rename_table( & src_table_ident, & dst_table_ident)
1684
+ . await
1685
+ . unwrap_err( )
1686
+ . to_string( ) ,
1687
+ format!( "Unexpected => No such table: {:?}" , src_table_ident) ,
1688
+ ) ;
1689
+ }
1690
+
1691
+ #[ tokio:: test]
1692
+ async fn test_rename_table_throws_error_if_dst_table_already_exists ( ) {
1693
+ let warehouse_loc = temp_path ( ) ;
1694
+ let catalog = new_sql_catalog ( warehouse_loc) . await ;
1695
+ let namespace_ident = NamespaceIdent :: new ( "n1" . into ( ) ) ;
1696
+ create_namespace ( & catalog, & namespace_ident) . await ;
1697
+ let src_table_ident = TableIdent :: new ( namespace_ident. clone ( ) , "tbl1" . into ( ) ) ;
1698
+ let dst_table_ident = TableIdent :: new ( namespace_ident. clone ( ) , "tbl2" . into ( ) ) ;
1699
+ create_tables ( & catalog, vec ! [ & src_table_ident, & dst_table_ident] ) . await ;
1700
+
1701
+ assert_eq ! (
1702
+ catalog
1703
+ . rename_table( & src_table_ident, & dst_table_ident)
1704
+ . await
1705
+ . unwrap_err( )
1706
+ . to_string( ) ,
1707
+ format!(
1708
+ "Unexpected => Cannot create table {:? }. Table already exists." ,
1709
+ & dst_table_ident
1710
+ ) ,
1711
+ ) ;
1712
+ }
1473
1713
}
0 commit comments