|
18 | 18 |
|
19 | 19 | package org.apache.paimon.rest; |
20 | 20 |
|
| 21 | +import org.apache.paimon.CoreOptions; |
21 | 22 | import org.apache.paimon.PagedList; |
22 | 23 | import org.apache.paimon.Snapshot; |
23 | 24 | import org.apache.paimon.TableType; |
@@ -2686,66 +2687,102 @@ public void testCreateExternalTable(@TempDir java.nio.file.Path path) throws Exc |
2686 | 2687 | Table tableAgain = catalog.getTable(identifier); |
2687 | 2688 | assertThat(tableAgain).isNotNull(); |
2688 | 2689 | assertThat(tableAgain.comment()).isEqualTo(Optional.of("External table for testing")); |
| 2690 | + } |
| 2691 | + |
| 2692 | + @Test |
| 2693 | + public void testCreateExternalTableWithSchemaInference(@TempDir java.nio.file.Path path) |
| 2694 | + throws Exception { |
| 2695 | + Path externalTablePath = new Path(path.toString(), "external_table_inference_location"); |
| 2696 | + DEFAULT_TABLE_SCHEMA.options().put(CoreOptions.PATH.key(), externalTablePath.toString()); |
| 2697 | + restCatalog.createDatabase("test_schema_inference_db", true); |
| 2698 | + Identifier identifier = |
| 2699 | + Identifier.create("test_schema_inference_db", "external_inference_table"); |
| 2700 | + try { |
| 2701 | + catalog.dropTable(identifier, true); |
| 2702 | + } catch (Exception e) { |
| 2703 | + // Ignore drop errors |
| 2704 | + } |
| 2705 | + |
| 2706 | + createExternalTableDirectory(externalTablePath, DEFAULT_TABLE_SCHEMA); |
| 2707 | + Schema emptySchema = |
| 2708 | + new Schema( |
| 2709 | + Lists.newArrayList(), |
| 2710 | + Collections.emptyList(), |
| 2711 | + Collections.emptyList(), |
| 2712 | + DEFAULT_TABLE_SCHEMA.options(), |
| 2713 | + ""); |
| 2714 | + catalog.createTable(identifier, emptySchema, false); |
2689 | 2715 |
|
2690 | | - testReadSystemTables(); |
| 2716 | + Table table = catalog.getTable(identifier); |
| 2717 | + assertThat(table).isNotNull(); |
| 2718 | + assertThat(table.rowType().getFieldCount()).isEqualTo(3); |
| 2719 | + assertThat(table.rowType().getFieldNames()).containsExactly("pk", "col1", "col2"); |
2691 | 2720 |
|
2692 | | - // Verify external table path still exists after operations |
2693 | | - assertTrue( |
2694 | | - fileIO.exists(externalTablePath), |
2695 | | - "External table path should still exist after operations"); |
| 2721 | + Schema clientProvidedSchema = |
| 2722 | + new Schema( |
| 2723 | + Lists.newArrayList( |
| 2724 | + new DataField(0, "pk", DataTypes.INT()), |
| 2725 | + new DataField(1, "col1", DataTypes.STRING())), |
| 2726 | + Collections.emptyList(), |
| 2727 | + Collections.emptyList(), |
| 2728 | + DEFAULT_TABLE_SCHEMA.options(), |
| 2729 | + ""); |
| 2730 | + // schema mismatch should throw an exception |
| 2731 | + Assertions.assertThrows( |
| 2732 | + RuntimeException.class, |
| 2733 | + () -> catalog.createTable(identifier, clientProvidedSchema, false)); |
| 2734 | + DEFAULT_TABLE_SCHEMA.options().remove(CoreOptions.PATH.key()); |
| 2735 | + } |
2696 | 2736 |
|
2697 | | - // Test dropping external table - data should remain |
2698 | | - catalog.dropTable(identifier, false); |
| 2737 | + @Test |
| 2738 | + public void testReadSystemTablesWithExternalTable(@TempDir java.nio.file.Path path) |
| 2739 | + throws Exception { |
| 2740 | + // Create an external table |
| 2741 | + Path externalTablePath = new Path(path.toString(), "external_sys_table_location"); |
| 2742 | + DEFAULT_TABLE_SCHEMA.options().put(CoreOptions.PATH.key(), externalTablePath.toString()); |
2699 | 2743 |
|
2700 | | - // Verify external table path still exists after drop (external table behavior) |
2701 | | - assertTrue( |
2702 | | - fileIO.exists(externalTablePath), |
2703 | | - "External table path should still exist after drop"); |
| 2744 | + restCatalog.createDatabase("test_sys_table_db", true); |
| 2745 | + Identifier identifier = Identifier.create("test_sys_table_db", "external_sys_table"); |
2704 | 2746 |
|
2705 | | - // Clean up |
2706 | 2747 | try { |
2707 | | - fileIO.deleteQuietly(externalTablePath); |
| 2748 | + catalog.dropTable(identifier, true); |
2708 | 2749 | } catch (Exception e) { |
2709 | | - // Ignore cleanup errors |
| 2750 | + // Ignore drop errors |
2710 | 2751 | } |
2711 | | - } |
2712 | 2752 |
|
2713 | | - private void testReadSystemTables() throws IOException, Catalog.TableNotExistException { |
| 2753 | + createExternalTableDirectory(externalTablePath, DEFAULT_TABLE_SCHEMA); |
| 2754 | + catalog.createTable(identifier, DEFAULT_TABLE_SCHEMA, false); |
| 2755 | + |
| 2756 | + // Test reading system table with external table |
2714 | 2757 | Identifier allTablesIdentifier = Identifier.create("sys", "tables"); |
2715 | 2758 | Table allTablesTable = catalog.getTable(allTablesIdentifier); |
| 2759 | + assertThat(allTablesTable).isNotNull(); |
2716 | 2760 |
|
2717 | | - if (allTablesTable != null) { |
2718 | | - ReadBuilder allTablesReadBuilder = allTablesTable.newReadBuilder(); |
2719 | | - TableRead allTablesRead = allTablesReadBuilder.newRead(); |
2720 | | - List<Split> allTablesSplits = allTablesReadBuilder.newScan().plan().splits(); |
| 2761 | + ReadBuilder readBuilder = allTablesTable.newReadBuilder(); |
| 2762 | + TableRead read = readBuilder.newRead(); |
| 2763 | + List<Split> splits = readBuilder.newScan().plan().splits(); |
2721 | 2764 |
|
2722 | | - List<InternalRow> allTablesResults = new ArrayList<>(); |
2723 | | - for (Split split : allTablesSplits) { |
2724 | | - try (RecordReader<InternalRow> reader = allTablesRead.createReader(split)) { |
2725 | | - reader.forEachRemaining(allTablesResults::add); |
2726 | | - } |
| 2765 | + List<InternalRow> results = new ArrayList<>(); |
| 2766 | + for (Split split : splits) { |
| 2767 | + try (RecordReader<InternalRow> reader = read.createReader(split)) { |
| 2768 | + reader.forEachRemaining(results::add); |
2727 | 2769 | } |
| 2770 | + } |
2728 | 2771 |
|
2729 | | - // Verify that our external table appears in ALL_TABLES |
2730 | | - assertThat(allTablesResults).isNotEmpty(); |
2731 | | - |
2732 | | - // Find our external table in the results |
2733 | | - boolean foundExternalTable = false; |
2734 | | - for (InternalRow row : allTablesResults) { |
2735 | | - String tableName = row.getString(1).toString(); // table_name column |
2736 | | - String databaseName = row.getString(0).toString(); // database_name column |
2737 | | - if ("external_test_table".equals(tableName) |
2738 | | - && "test_external_table_db".equals(databaseName)) { |
2739 | | - foundExternalTable = true; |
2740 | | - // Verify table properties |
2741 | | - String tableType = row.getString(2).toString(); // table_type column |
2742 | | - assertThat(tableType) |
2743 | | - .isEqualTo("table"); // External tables are still MANAGED type |
2744 | | - break; |
2745 | | - } |
| 2772 | + // Verify external table appears in system table |
| 2773 | + assertThat(results).isNotEmpty(); |
| 2774 | + boolean foundExternalTable = false; |
| 2775 | + for (InternalRow row : results) { |
| 2776 | + String databaseName = row.getString(0).toString(); |
| 2777 | + String tableName = row.getString(1).toString(); |
| 2778 | + if ("test_sys_table_db".equals(databaseName) |
| 2779 | + && "external_sys_table".equals(tableName)) { |
| 2780 | + foundExternalTable = true; |
| 2781 | + break; |
2746 | 2782 | } |
2747 | | - assertThat(foundExternalTable).isTrue(); |
2748 | 2783 | } |
| 2784 | + assertThat(foundExternalTable).isTrue(); |
| 2785 | + DEFAULT_TABLE_SCHEMA.options().remove(CoreOptions.PATH.key()); |
2749 | 2786 | } |
2750 | 2787 |
|
2751 | 2788 | protected void createTable( |
|
0 commit comments