diff --git a/docker/thirdparties/docker-compose/iceberg/scripts/create_preinstalled_scripts/paimon/run10.sql b/docker/thirdparties/docker-compose/iceberg/scripts/create_preinstalled_scripts/paimon/run10.sql new file mode 100644 index 00000000000000..c5106e943b91fb --- /dev/null +++ b/docker/thirdparties/docker-compose/iceberg/scripts/create_preinstalled_scripts/paimon/run10.sql @@ -0,0 +1,18 @@ +use paimon; + +create database if not exists test_paimon_ro_read_db; + +use test_paimon_ro_read_db; + +CREATE TABLE if not exists paimon_pk_for_ro ( + id INT, + name STRING, + age INT +) USING paimon +TBLPROPERTIES ('primary-key' = 'id', 'bucket' = '1'); + +INSERT INTO paimon_pk_for_ro (id, name, age) VALUES (1, 'Alice', 30),(2, 'Bob', 25),(3, 'Charlie', 28); + +CALL sys.compact(table => 'test_paimon_ro_read_db.paimon_pk_for_ro'); + +INSERT INTO paimon_pk_for_ro (id, name, age) VALUES (1, 'AliceNew', 33); diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 index d916626420678f..04f7e9592fb362 100644 --- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 +++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 @@ -1404,7 +1404,7 @@ identifierSeq ; optScanParams - : ATSIGN funcName=identifier LEFT_PAREN (mapParams=propertyItemList | listParams=identifierSeq)? RIGHT_PAREN + : ATSIGN funcName=identifier (LEFT_PAREN (mapParams=propertyItemList | listParams=identifierSeq)? RIGHT_PAREN)? ; relationPrimary diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/TableScanParams.java b/fe/fe-core/src/main/java/org/apache/doris/analysis/TableScanParams.java index a73b208a6112a7..83b730615429d0 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/analysis/TableScanParams.java +++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/TableScanParams.java @@ -29,17 +29,22 @@ public class TableScanParams { public static final String INCREMENTAL_READ = "incr"; public static final String BRANCH = "branch"; public static final String TAG = "tag"; + // for paimon read-optimized system table + public static final String RO = "ro"; private static final ImmutableSet VALID_PARAM_TYPES = ImmutableSet.of( INCREMENTAL_READ, BRANCH, - TAG); + TAG, + RO); private final String paramType; - // There are two ways to pass parameters to a function. + // There are three ways to pass parameters to a function. // - One is in map form, where the data is stored in `mapParams`. // such as: @func_name('param1'='value1', 'param2'='value2', 'param3'='value3') - // - The other is in list form, where the data is stored in `listParams`. + // - Another one is in list form, where the data is stored in `listParams`. // such as: `listParams` is used for @func_name('value1', 'value2', 'value3') + // - The third one is in short form, now only used for paimon 'ro' table. + // such as: @ro private final Map mapParams; private final List listParams; @@ -47,6 +52,10 @@ private void validate() { if (!VALID_PARAM_TYPES.contains(paramType)) { throw new IllegalArgumentException("Invalid param type: " + paramType); } + if (isRo() && (!mapParams.isEmpty() || !listParams.isEmpty())) { + throw new IllegalArgumentException( + "The '@ro' parameter for Paimon read-optimized tables must be used without arguments"); + } // TODO: validate mapParams and listParams for different param types } @@ -80,4 +89,8 @@ public boolean isBranch() { public boolean isTag() { return TAG.equals(paramType); } + + public boolean isRo() { + return RO.equals(paramType); + } } diff --git a/fe/fe-core/src/main/java/org/apache/doris/datasource/paimon/PaimonExternalTable.java b/fe/fe-core/src/main/java/org/apache/doris/datasource/paimon/PaimonExternalTable.java index 6b39413d1d4161..20056d3f083fdd 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/datasource/paimon/PaimonExternalTable.java +++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/paimon/PaimonExternalTable.java @@ -124,11 +124,8 @@ private PaimonSnapshotCacheValue getPaimonSnapshotCacheValue(Optional latestSnapshot = table.latestSnapshot(); - long latestSnapshotId = PaimonSnapshot.INVALID_SNAPSHOT_ID; - if (latestSnapshot.isPresent()) { - latestSnapshotId = latestSnapshot.get().id(); - } + long latestSnapshotId = table.latestSnapshot().map(Snapshot::id) + .orElse(PaimonSnapshot.INVALID_SNAPSHOT_ID); // Branches in Paimon can have independent schemas and snapshots. // TODO: Add time travel support for paimon branch tables. DataTable dataTable = (DataTable) table; @@ -141,6 +138,21 @@ private PaimonSnapshotCacheValue getPaimonSnapshotCacheValue(Optional