This is an automated email from the ASF dual-hosted git repository.
lzljs3620320 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new da78eca79 [flink] Support Flink read / write data branch (#3029)
da78eca79 is described below
commit da78eca791434d01f4fe989125f125e30f2373d1
Author: Xiaojian Sun <[email protected]>
AuthorDate: Sun May 19 20:40:18 2024 +0800
[flink] Support Flink read / write data branch (#3029)
---
.../shortcodes/generated/core_configuration.html | 6 ++
.../main/java/org/apache/paimon/CoreOptions.java | 14 +++
.../java/org/apache/paimon/AbstractFileStore.java | 10 +-
.../org/apache/paimon/AppendOnlyFileStore.java | 12 +--
.../src/main/java/org/apache/paimon/FileStore.java | 4 -
.../java/org/apache/paimon/KeyValueFileStore.java | 12 +--
.../org/apache/paimon/catalog/AbstractCatalog.java | 3 +-
.../paimon/operation/AbstractFileStoreScan.java | 7 +-
.../paimon/operation/AppendOnlyFileStoreScan.java | 4 +-
.../paimon/operation/FileStoreCommitImpl.java | 10 +-
.../paimon/operation/KeyValueFileStoreScan.java | 4 +-
.../paimon/privilege/PrivilegedFileStore.java | 12 ---
.../paimon/privilege/PrivilegedFileStoreTable.java | 12 ---
.../org/apache/paimon/schema/SchemaManager.java | 54 +++++-----
.../paimon/table/AbstractFileStoreTable.java | 22 ++--
.../java/org/apache/paimon/table/DataTable.java | 2 -
.../org/apache/paimon/table/FileStoreTable.java | 2 -
.../apache/paimon/table/FileStoreTableFactory.java | 3 +-
.../apache/paimon/table/system/AuditLogTable.java | 5 -
.../apache/paimon/table/system/BucketsTable.java | 5 -
.../paimon/table/system/FileMonitorTable.java | 5 -
.../paimon/table/system/ReadOptimizedTable.java | 5 -
.../org/apache/paimon/utils/BranchManager.java | 27 +++--
.../org/apache/paimon/utils/SnapshotManager.java | 120 +++++++++------------
.../java/org/apache/paimon/utils/TagManager.java | 38 ++++---
.../paimon/table/AppendOnlyFileStoreTableTest.java | 41 +++++--
.../paimon/table/FileStoreTableTestBase.java | 49 +++++----
.../paimon/table/PrimaryKeyFileStoreTableTest.java | 44 ++++++--
.../paimon/table/SchemaEvolutionTableTestBase.java | 6 --
.../paimon/table/WritePreemptMemoryTest.java | 25 +++++
.../org/apache/paimon/flink/FlinkTableFactory.java | 5 +-
.../org/apache/paimon/flink/sink/FlinkSink.java | 1 +
.../apache/paimon/flink/AppendOnlyTableITCase.java | 16 +++
.../org/apache/paimon/flink/FileStoreITCase.java | 13 ++-
.../paimon/flink/FileStoreWithBranchITCase.java | 46 ++++----
.../flink/PrimaryKeyFileStoreTableITCase.java | 55 ++++++++++
36 files changed, 400 insertions(+), 299 deletions(-)
diff --git a/docs/layouts/shortcodes/generated/core_configuration.html
b/docs/layouts/shortcodes/generated/core_configuration.html
index 77710afab..5e7db5c55 100644
--- a/docs/layouts/shortcodes/generated/core_configuration.html
+++ b/docs/layouts/shortcodes/generated/core_configuration.html
@@ -32,6 +32,12 @@ under the License.
<td>Boolean</td>
<td>Whether to create underlying storage when reading and writing
the table.</td>
</tr>
+ <tr>
+ <td><h5>branch</h5></td>
+ <td style="word-wrap: break-word;">"main"</td>
+ <td>String</td>
+ <td>Specify branch name.</td>
+ </tr>
<tr>
<td><h5>bucket</h5></td>
<td style="word-wrap: break-word;">-1</td>
diff --git a/paimon-common/src/main/java/org/apache/paimon/CoreOptions.java
b/paimon-common/src/main/java/org/apache/paimon/CoreOptions.java
index c9f9833dc..a82166ad7 100644
--- a/paimon-common/src/main/java/org/apache/paimon/CoreOptions.java
+++ b/paimon-common/src/main/java/org/apache/paimon/CoreOptions.java
@@ -112,6 +112,9 @@ public class CoreOptions implements Serializable {
.noDefaultValue()
.withDescription("The file path of this table in the
filesystem.");
+ public static final ConfigOption<String> BRANCH =
+
key("branch").stringType().defaultValue("main").withDescription("Specify branch
name.");
+
public static final String FILE_FORMAT_ORC = "orc";
public static final String FILE_FORMAT_AVRO = "avro";
public static final String FILE_FORMAT_PARQUET = "parquet";
@@ -1178,6 +1181,17 @@ public class CoreOptions implements Serializable {
return path(options.toMap());
}
+ public String branch() {
+ return branch(options.toMap());
+ }
+
+ public static String branch(Map<String, String> options) {
+ if (options.containsKey(BRANCH.key())) {
+ return options.get(BRANCH.key());
+ }
+ return BRANCH.defaultValue();
+ }
+
public static Path path(Map<String, String> options) {
return new Path(options.get(PATH.key()));
}
diff --git a/paimon-core/src/main/java/org/apache/paimon/AbstractFileStore.java
b/paimon-core/src/main/java/org/apache/paimon/AbstractFileStore.java
index e893c0525..8cbf433f6 100644
--- a/paimon-core/src/main/java/org/apache/paimon/AbstractFileStore.java
+++ b/paimon-core/src/main/java/org/apache/paimon/AbstractFileStore.java
@@ -55,8 +55,6 @@ import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
-import static org.apache.paimon.utils.BranchManager.DEFAULT_MAIN_BRANCH;
-
/**
* Base {@link FileStore} implementation.
*
@@ -104,7 +102,7 @@ abstract class AbstractFileStore<T> implements FileStore<T>
{
@Override
public SnapshotManager snapshotManager() {
- return new SnapshotManager(fileIO, options.path());
+ return new SnapshotManager(fileIO, options.path(), options.branch());
}
@Override
@@ -175,10 +173,6 @@ abstract class AbstractFileStore<T> implements
FileStore<T> {
@Override
public FileStoreCommitImpl newCommit(String commitUser) {
- return newCommit(commitUser, DEFAULT_MAIN_BRANCH);
- }
-
- public FileStoreCommitImpl newCommit(String commitUser, String branchName)
{
return new FileStoreCommitImpl(
fileIO,
schemaManager,
@@ -196,7 +190,7 @@ abstract class AbstractFileStore<T> implements FileStore<T>
{
options.manifestMergeMinCount(),
partitionType.getFieldCount() > 0 &&
options.dynamicPartitionOverwrite(),
newKeyComparator(),
- branchName,
+ options.branch(),
newStatsFileHandler());
}
diff --git
a/paimon-core/src/main/java/org/apache/paimon/AppendOnlyFileStore.java
b/paimon-core/src/main/java/org/apache/paimon/AppendOnlyFileStore.java
index d2fefc5f9..3cd7bb3b6 100644
--- a/paimon-core/src/main/java/org/apache/paimon/AppendOnlyFileStore.java
+++ b/paimon-core/src/main/java/org/apache/paimon/AppendOnlyFileStore.java
@@ -39,7 +39,6 @@ import java.util.List;
import static org.apache.paimon.predicate.PredicateBuilder.and;
import static
org.apache.paimon.predicate.PredicateBuilder.pickTransformFieldMapping;
import static org.apache.paimon.predicate.PredicateBuilder.splitAnd;
-import static org.apache.paimon.utils.BranchManager.DEFAULT_MAIN_BRANCH;
/** {@link FileStore} for reading and writing {@link InternalRow}. */
public class AppendOnlyFileStore extends AbstractFileStore<InternalRow> {
@@ -71,11 +70,7 @@ public class AppendOnlyFileStore extends
AbstractFileStore<InternalRow> {
@Override
public AppendOnlyFileStoreScan newScan() {
- return newScan(DEFAULT_MAIN_BRANCH);
- }
-
- public AppendOnlyFileStoreScan newScan(String branchName) {
- return newScan(false, branchName);
+ return newScan(false);
}
@Override
@@ -106,12 +101,12 @@ public class AppendOnlyFileStore extends
AbstractFileStore<InternalRow> {
rowType,
pathFactory(),
snapshotManager(),
- newScan(true,
DEFAULT_MAIN_BRANCH).withManifestCacheFilter(manifestFilter),
+ newScan(true).withManifestCacheFilter(manifestFilter),
options,
tableName);
}
- private AppendOnlyFileStoreScan newScan(boolean forWrite, String
branchName) {
+ private AppendOnlyFileStoreScan newScan(boolean forWrite) {
ScanBucketFilter bucketFilter =
new ScanBucketFilter(bucketKeyType) {
@Override
@@ -146,7 +141,6 @@ public class AppendOnlyFileStore extends
AbstractFileStore<InternalRow> {
options.bucket(),
forWrite,
options.scanManifestParallelism(),
- branchName,
options.fileIndexReadEnabled());
}
diff --git a/paimon-core/src/main/java/org/apache/paimon/FileStore.java
b/paimon-core/src/main/java/org/apache/paimon/FileStore.java
index 870feffde..66bf3363d 100644
--- a/paimon-core/src/main/java/org/apache/paimon/FileStore.java
+++ b/paimon-core/src/main/java/org/apache/paimon/FileStore.java
@@ -63,8 +63,6 @@ public interface FileStore<T> extends Serializable {
FileStoreScan newScan();
- FileStoreScan newScan(String branchName);
-
ManifestList.Factory manifestListFactory();
ManifestFile.Factory manifestFileFactory();
@@ -81,8 +79,6 @@ public interface FileStore<T> extends Serializable {
FileStoreCommit newCommit(String commitUser);
- FileStoreCommit newCommit(String commitUser, String branchName);
-
SnapshotDeletion newSnapshotDeletion();
TagManager newTagManager();
diff --git a/paimon-core/src/main/java/org/apache/paimon/KeyValueFileStore.java
b/paimon-core/src/main/java/org/apache/paimon/KeyValueFileStore.java
index edd45d1c5..b1b7fc211 100644
--- a/paimon-core/src/main/java/org/apache/paimon/KeyValueFileStore.java
+++ b/paimon-core/src/main/java/org/apache/paimon/KeyValueFileStore.java
@@ -56,7 +56,6 @@ import java.util.function.Supplier;
import static org.apache.paimon.predicate.PredicateBuilder.and;
import static
org.apache.paimon.predicate.PredicateBuilder.pickTransformFieldMapping;
import static org.apache.paimon.predicate.PredicateBuilder.splitAnd;
-import static org.apache.paimon.utils.BranchManager.DEFAULT_MAIN_BRANCH;
import static org.apache.paimon.utils.Preconditions.checkArgument;
/** {@link FileStore} for querying and updating {@link KeyValue}s. */
@@ -112,11 +111,7 @@ public class KeyValueFileStore extends
AbstractFileStore<KeyValue> {
@Override
public KeyValueFileStoreScan newScan() {
- return newScan(DEFAULT_MAIN_BRANCH);
- }
-
- public KeyValueFileStoreScan newScan(String branchName) {
- return newScan(false, branchName);
+ return newScan(false);
}
@Override
@@ -185,7 +180,7 @@ public class KeyValueFileStore extends
AbstractFileStore<KeyValue> {
pathFactory(),
format2PathFactory(),
snapshotManager(),
- newScan(true,
DEFAULT_MAIN_BRANCH).withManifestCacheFilter(manifestFilter),
+ newScan(true).withManifestCacheFilter(manifestFilter),
indexFactory,
deletionVectorsMaintainerFactory,
options,
@@ -209,7 +204,7 @@ public class KeyValueFileStore extends
AbstractFileStore<KeyValue> {
return pathFactoryMap;
}
- private KeyValueFileStoreScan newScan(boolean forWrite, String branchName)
{
+ private KeyValueFileStoreScan newScan(boolean forWrite) {
ScanBucketFilter bucketFilter =
new ScanBucketFilter(bucketKeyType) {
@Override
@@ -240,7 +235,6 @@ public class KeyValueFileStore extends
AbstractFileStore<KeyValue> {
options.bucket(),
forWrite,
options.scanManifestParallelism(),
- branchName,
options.deletionVectorsEnabled(),
options.mergeEngine());
}
diff --git
a/paimon-core/src/main/java/org/apache/paimon/catalog/AbstractCatalog.java
b/paimon-core/src/main/java/org/apache/paimon/catalog/AbstractCatalog.java
index 7d26a2197..605fd14f6 100644
--- a/paimon-core/src/main/java/org/apache/paimon/catalog/AbstractCatalog.java
+++ b/paimon-core/src/main/java/org/apache/paimon/catalog/AbstractCatalog.java
@@ -335,7 +335,8 @@ public abstract class AbstractCatalog implements Catalog {
}
return table;
} else {
- return getDataTable(identifier);
+ Table table = getDataTable(identifier);
+ return table;
}
}
diff --git
a/paimon-core/src/main/java/org/apache/paimon/operation/AbstractFileStoreScan.java
b/paimon-core/src/main/java/org/apache/paimon/operation/AbstractFileStoreScan.java
index 073490694..8abf1f18b 100644
---
a/paimon-core/src/main/java/org/apache/paimon/operation/AbstractFileStoreScan.java
+++
b/paimon-core/src/main/java/org/apache/paimon/operation/AbstractFileStoreScan.java
@@ -79,7 +79,6 @@ public abstract class AbstractFileStoreScan implements
FileStoreScan {
private final SchemaManager schemaManager;
private final TableSchema schema;
protected final ScanBucketFilter bucketKeyFilter;
- private final String branchName;
private PartitionPredicate partitionFilter;
private Snapshot specifiedSnapshot = null;
@@ -102,8 +101,7 @@ public abstract class AbstractFileStoreScan implements
FileStoreScan {
ManifestList.Factory manifestListFactory,
int numOfBuckets,
boolean checkNumOfBuckets,
- Integer scanManifestParallelism,
- String branchName) {
+ Integer scanManifestParallelism) {
this.partitionType = partitionType;
this.bucketKeyFilter = bucketKeyFilter;
this.snapshotManager = snapshotManager;
@@ -115,7 +113,6 @@ public abstract class AbstractFileStoreScan implements
FileStoreScan {
this.checkNumOfBuckets = checkNumOfBuckets;
this.tableSchemas = new ConcurrentHashMap<>();
this.scanManifestParallelism = scanManifestParallelism;
- this.branchName = branchName;
}
@Override
@@ -397,7 +394,7 @@ public abstract class AbstractFileStoreScan implements
FileStoreScan {
if (manifests == null) {
snapshot =
specifiedSnapshot == null
- ? snapshotManager.latestSnapshot(branchName)
+ ? snapshotManager.latestSnapshot()
: specifiedSnapshot;
if (snapshot == null) {
manifests = Collections.emptyList();
diff --git
a/paimon-core/src/main/java/org/apache/paimon/operation/AppendOnlyFileStoreScan.java
b/paimon-core/src/main/java/org/apache/paimon/operation/AppendOnlyFileStoreScan.java
index bbc4487ca..056c82e82 100644
---
a/paimon-core/src/main/java/org/apache/paimon/operation/AppendOnlyFileStoreScan.java
+++
b/paimon-core/src/main/java/org/apache/paimon/operation/AppendOnlyFileStoreScan.java
@@ -62,7 +62,6 @@ public class AppendOnlyFileStoreScan extends
AbstractFileStoreScan {
int numOfBuckets,
boolean checkNumOfBuckets,
Integer scanManifestParallelism,
- String branchName,
boolean fileIndexReadEnabled) {
super(
partitionType,
@@ -74,8 +73,7 @@ public class AppendOnlyFileStoreScan extends
AbstractFileStoreScan {
manifestListFactory,
numOfBuckets,
checkNumOfBuckets,
- scanManifestParallelism,
- branchName);
+ scanManifestParallelism);
this.simpleStatsConverters =
new SimpleStatsConverters(sid ->
scanTableSchema(sid).fields(), schema.id());
this.fileIndexReadEnabled = fileIndexReadEnabled;
diff --git
a/paimon-core/src/main/java/org/apache/paimon/operation/FileStoreCommitImpl.java
b/paimon-core/src/main/java/org/apache/paimon/operation/FileStoreCommitImpl.java
index dab336b81..7ddf8c210 100644
---
a/paimon-core/src/main/java/org/apache/paimon/operation/FileStoreCommitImpl.java
+++
b/paimon-core/src/main/java/org/apache/paimon/operation/FileStoreCommitImpl.java
@@ -251,7 +251,7 @@ public class FileStoreCommitImpl implements FileStoreCommit
{
// we can skip conflict checking in tryCommit method.
// This optimization is mainly used to decrease the number of
times we read from
// files.
- latestSnapshot = snapshotManager.latestSnapshot(branchName);
+ latestSnapshot = snapshotManager.latestSnapshot();
if (latestSnapshot != null && checkAppendFiles) {
// it is possible that some partitions only have compact
changes,
// so we need to contain all changes
@@ -654,7 +654,7 @@ public class FileStoreCommitImpl implements FileStoreCommit
{
@Nullable String statsFileName) {
int cnt = 0;
while (true) {
- Snapshot latestSnapshot =
snapshotManager.latestSnapshot(branchName);
+ Snapshot latestSnapshot = snapshotManager.latestSnapshot();
cnt++;
if (tryCommitOnce(
tableFiles,
@@ -754,7 +754,7 @@ public class FileStoreCommitImpl implements FileStoreCommit
{
Path newSnapshotPath =
branchName.equals(DEFAULT_MAIN_BRANCH)
? snapshotManager.snapshotPath(newSnapshotId)
- : snapshotManager.branchSnapshotPath(branchName,
newSnapshotId);
+ :
snapshotManager.copyWithBranch(branchName).snapshotPath(newSnapshotId);
if (LOG.isDebugEnabled()) {
LOG.debug("Ready to commit table files to snapshot #" +
newSnapshotId);
@@ -839,7 +839,7 @@ public class FileStoreCommitImpl implements FileStoreCommit
{
newIndexManifest = indexManifest;
}
- long latestSchemaId = schemaManager.latest(branchName).get().id();
+ long latestSchemaId = schemaManager.latest().get().id();
// write new stats or inherit from the previous snapshot
String statsFileName = null;
@@ -904,7 +904,7 @@ public class FileStoreCommitImpl implements FileStoreCommit
{
boolean committed =
fileIO.writeFileUtf8(newSnapshotPath,
newSnapshot.toJson());
if (committed) {
- snapshotManager.commitLatestHint(newSnapshotId,
branchName);
+ snapshotManager.commitLatestHint(newSnapshotId);
}
return committed;
};
diff --git
a/paimon-core/src/main/java/org/apache/paimon/operation/KeyValueFileStoreScan.java
b/paimon-core/src/main/java/org/apache/paimon/operation/KeyValueFileStoreScan.java
index 5363336ea..ab19cc49f 100644
---
a/paimon-core/src/main/java/org/apache/paimon/operation/KeyValueFileStoreScan.java
+++
b/paimon-core/src/main/java/org/apache/paimon/operation/KeyValueFileStoreScan.java
@@ -62,7 +62,6 @@ public class KeyValueFileStoreScan extends
AbstractFileStoreScan {
int numOfBuckets,
boolean checkNumOfBuckets,
Integer scanManifestParallelism,
- String branchName,
boolean deletionVectorsEnabled,
MergeEngine mergeEngine) {
super(
@@ -75,8 +74,7 @@ public class KeyValueFileStoreScan extends
AbstractFileStoreScan {
manifestListFactory,
numOfBuckets,
checkNumOfBuckets,
- scanManifestParallelism,
- branchName);
+ scanManifestParallelism);
this.fieldKeyStatsConverters =
new SimpleStatsConverters(
sid ->
keyValueFieldsExtractor.keyFields(scanTableSchema(sid)),
diff --git
a/paimon-core/src/main/java/org/apache/paimon/privilege/PrivilegedFileStore.java
b/paimon-core/src/main/java/org/apache/paimon/privilege/PrivilegedFileStore.java
index cf8e4c357..e71a0cde1 100644
---
a/paimon-core/src/main/java/org/apache/paimon/privilege/PrivilegedFileStore.java
+++
b/paimon-core/src/main/java/org/apache/paimon/privilege/PrivilegedFileStore.java
@@ -94,12 +94,6 @@ public class PrivilegedFileStore<T> implements FileStore<T> {
return wrapped.newScan();
}
- @Override
- public FileStoreScan newScan(String branchName) {
- privilegeChecker.assertCanSelect(identifier);
- return wrapped.newScan(branchName);
- }
-
@Override
public ManifestList.Factory manifestListFactory() {
return wrapped.manifestListFactory();
@@ -144,12 +138,6 @@ public class PrivilegedFileStore<T> implements
FileStore<T> {
return wrapped.newCommit(commitUser);
}
- @Override
- public FileStoreCommit newCommit(String commitUser, String branchName) {
- privilegeChecker.assertCanInsert(identifier);
- return wrapped.newCommit(commitUser, branchName);
- }
-
@Override
public SnapshotDeletion newSnapshotDeletion() {
privilegeChecker.assertCanInsert(identifier);
diff --git
a/paimon-core/src/main/java/org/apache/paimon/privilege/PrivilegedFileStoreTable.java
b/paimon-core/src/main/java/org/apache/paimon/privilege/PrivilegedFileStoreTable.java
index 5820e46b4..1881c7350 100644
---
a/paimon-core/src/main/java/org/apache/paimon/privilege/PrivilegedFileStoreTable.java
+++
b/paimon-core/src/main/java/org/apache/paimon/privilege/PrivilegedFileStoreTable.java
@@ -67,12 +67,6 @@ public class PrivilegedFileStoreTable implements
FileStoreTable {
return wrapped.newSnapshotReader();
}
- @Override
- public SnapshotReader newSnapshotReader(String branchName) {
- privilegeChecker.assertCanSelect(identifier);
- return wrapped.newSnapshotReader(branchName);
- }
-
@Override
public CoreOptions coreOptions() {
return wrapped.coreOptions();
@@ -270,12 +264,6 @@ public class PrivilegedFileStoreTable implements
FileStoreTable {
return wrapped.newCommit(commitUser);
}
- @Override
- public TableCommitImpl newCommit(String commitUser, String branchName) {
- privilegeChecker.assertCanInsert(identifier);
- return wrapped.newCommit(commitUser, branchName);
- }
-
@Override
public LocalTableQuery newLocalTableQuery() {
privilegeChecker.assertCanSelect(identifier);
diff --git
a/paimon-core/src/main/java/org/apache/paimon/schema/SchemaManager.java
b/paimon-core/src/main/java/org/apache/paimon/schema/SchemaManager.java
index d94da91ef..228d30d5c 100644
--- a/paimon-core/src/main/java/org/apache/paimon/schema/SchemaManager.java
+++ b/paimon-core/src/main/java/org/apache/paimon/schema/SchemaManager.java
@@ -44,6 +44,7 @@ import org.apache.paimon.types.ReassignFieldId;
import org.apache.paimon.types.RowType;
import org.apache.paimon.utils.JsonSerdeUtil;
import org.apache.paimon.utils.Preconditions;
+import org.apache.paimon.utils.StringUtils;
import javax.annotation.Nullable;
import javax.annotation.concurrent.ThreadSafe;
@@ -67,6 +68,7 @@ import static
org.apache.paimon.catalog.AbstractCatalog.DB_SUFFIX;
import static org.apache.paimon.catalog.Identifier.UNKNOWN_DATABASE;
import static org.apache.paimon.utils.BranchManager.DEFAULT_MAIN_BRANCH;
import static org.apache.paimon.utils.BranchManager.getBranchPath;
+import static org.apache.paimon.utils.BranchManager.isMainBranch;
import static org.apache.paimon.utils.FileUtils.listVersionedFiles;
import static org.apache.paimon.utils.Preconditions.checkState;
@@ -81,9 +83,21 @@ public class SchemaManager implements Serializable {
@Nullable private transient Lock lock;
+ private final String branch;
+
public SchemaManager(FileIO fileIO, Path tableRoot) {
+ this(fileIO, tableRoot, DEFAULT_MAIN_BRANCH);
+ }
+
+ /** Specify the default branch for data writing. */
+ public SchemaManager(FileIO fileIO, Path tableRoot, String branch) {
this.fileIO = fileIO;
this.tableRoot = tableRoot;
+ this.branch = StringUtils.isBlank(branch) ? DEFAULT_MAIN_BRANCH :
branch;
+ }
+
+ public SchemaManager copyWithBranch(String branchName) {
+ return new SchemaManager(fileIO, tableRoot, branchName);
}
public SchemaManager withLock(@Nullable Lock lock) {
@@ -91,28 +105,18 @@ public class SchemaManager implements Serializable {
return this;
}
- /** @return latest schema. */
public Optional<TableSchema> latest() {
- return latest(DEFAULT_MAIN_BRANCH);
- }
-
- public Optional<TableSchema> latest(String branchName) {
- Path directoryPath =
- branchName.equals(DEFAULT_MAIN_BRANCH)
- ? schemaDirectory()
- : branchSchemaDirectory(branchName);
try {
- return listVersionedFiles(fileIO, directoryPath, SCHEMA_PREFIX)
+ return listVersionedFiles(fileIO, schemaDirectory(), SCHEMA_PREFIX)
.reduce(Math::max)
- .map(this::schema);
+ .map(id -> schema(id));
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
- /** List all schema. */
public List<TableSchema> listAll() {
- return
listAllIds().stream().map(this::schema).collect(Collectors.toList());
+ return listAllIds().stream().map(id ->
schema(id)).collect(Collectors.toList());
}
/** List all schema IDs. */
@@ -125,7 +129,6 @@ public class SchemaManager implements Serializable {
}
}
- /** Create a new schema from {@link Schema}. */
public TableSchema createTable(Schema schema) throws Exception {
return createTable(schema, false);
}
@@ -471,7 +474,6 @@ public class SchemaManager implements Serializable {
@VisibleForTesting
boolean commit(TableSchema newSchema) throws Exception {
SchemaValidation.validateTableSchema(newSchema);
-
Path schemaPath = toSchemaPath(newSchema.id());
Callable<Boolean> callable = () -> fileIO.writeFileUtf8(schemaPath,
newSchema.toString());
if (lock == null) {
@@ -497,22 +499,18 @@ public class SchemaManager implements Serializable {
}
}
- private Path schemaDirectory() {
- return new Path(tableRoot + "/schema");
+ public Path schemaDirectory() {
+ return isMainBranch(branch)
+ ? new Path(tableRoot + "/schema")
+ : new Path(getBranchPath(tableRoot, branch) + "/schema");
}
@VisibleForTesting
- public Path toSchemaPath(long id) {
- return new Path(tableRoot + "/schema/" + SCHEMA_PREFIX + id);
- }
-
- public Path branchSchemaDirectory(String branchName) {
- return new Path(getBranchPath(tableRoot, branchName) + "/schema");
- }
-
- public Path branchSchemaPath(String branchName, long schemaId) {
- return new Path(
- getBranchPath(tableRoot, branchName) + "/schema/" +
SCHEMA_PREFIX + schemaId);
+ public Path toSchemaPath(long schemaId) {
+ return isMainBranch(branch)
+ ? new Path(tableRoot + "/schema/" + SCHEMA_PREFIX + schemaId)
+ : new Path(
+ getBranchPath(tableRoot, branch) + "/schema/" +
SCHEMA_PREFIX + schemaId);
}
/**
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/AbstractFileStoreTable.java
b/paimon-core/src/main/java/org/apache/paimon/table/AbstractFileStoreTable.java
index a8241e51f..434264dbb 100644
---
a/paimon-core/src/main/java/org/apache/paimon/table/AbstractFileStoreTable.java
+++
b/paimon-core/src/main/java/org/apache/paimon/table/AbstractFileStoreTable.java
@@ -71,7 +71,6 @@ import java.util.SortedMap;
import java.util.function.BiConsumer;
import static org.apache.paimon.CoreOptions.PATH;
-import static org.apache.paimon.utils.BranchManager.DEFAULT_MAIN_BRANCH;
import static org.apache.paimon.utils.Preconditions.checkArgument;
import static org.apache.paimon.utils.Preconditions.checkNotNull;
@@ -139,13 +138,8 @@ abstract class AbstractFileStoreTable implements
FileStoreTable {
@Override
public SnapshotReader newSnapshotReader() {
- return newSnapshotReader(DEFAULT_MAIN_BRANCH);
- }
-
- @Override
- public SnapshotReader newSnapshotReader(String branchName) {
return new SnapshotReaderImpl(
- store().newScan(branchName),
+ store().newScan(),
tableSchema,
coreOptions(),
snapshotManager(),
@@ -246,7 +240,8 @@ abstract class AbstractFileStoreTable implements
FileStoreTable {
@Override
public FileStoreTable copyWithLatestSchema() {
Map<String, String> options = tableSchema.options();
- SchemaManager schemaManager = new SchemaManager(fileIO(), location());
+ SchemaManager schemaManager =
+ new SchemaManager(fileIO(), location(),
CoreOptions.branch(options()));
Optional<TableSchema> optionalLatestSchema = schemaManager.latest();
if (optionalLatestSchema.isPresent()) {
TableSchema newTableSchema = optionalLatestSchema.get();
@@ -259,7 +254,7 @@ abstract class AbstractFileStoreTable implements
FileStoreTable {
}
protected SchemaManager schemaManager() {
- return new SchemaManager(fileIO(), path);
+ return new SchemaManager(fileIO(), path,
CoreOptions.branch(options()));
}
@Override
@@ -308,11 +303,6 @@ abstract class AbstractFileStoreTable implements
FileStoreTable {
@Override
public TableCommitImpl newCommit(String commitUser) {
- // Compatibility with previous design, the main branch is written by
default
- return newCommit(commitUser, DEFAULT_MAIN_BRANCH);
- }
-
- public TableCommitImpl newCommit(String commitUser, String branchName) {
CoreOptions options = coreOptions();
Runnable snapshotExpire = null;
if (!options.writeOnly()) {
@@ -340,7 +330,7 @@ abstract class AbstractFileStoreTable implements
FileStoreTable {
}
return new TableCommitImpl(
- store().newCommit(commitUser, branchName),
+ store().newCommit(commitUser),
createCommitCallbacks(),
snapshotExpire,
options.writeOnly() ? null :
store().newPartitionExpire(commitUser),
@@ -571,7 +561,7 @@ abstract class AbstractFileStoreTable implements
FileStoreTable {
@Override
public TagManager tagManager() {
- return new TagManager(fileIO, path);
+ return new TagManager(fileIO, path, CoreOptions.branch(options()));
}
@Override
diff --git a/paimon-core/src/main/java/org/apache/paimon/table/DataTable.java
b/paimon-core/src/main/java/org/apache/paimon/table/DataTable.java
index 1d8921304..b5bebe2a7 100644
--- a/paimon-core/src/main/java/org/apache/paimon/table/DataTable.java
+++ b/paimon-core/src/main/java/org/apache/paimon/table/DataTable.java
@@ -31,8 +31,6 @@ public interface DataTable extends InnerTable {
SnapshotReader newSnapshotReader();
- SnapshotReader newSnapshotReader(String branchName);
-
CoreOptions coreOptions();
SnapshotManager snapshotManager();
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/FileStoreTable.java
b/paimon-core/src/main/java/org/apache/paimon/table/FileStoreTable.java
index b8685f329..212555d7b 100644
--- a/paimon-core/src/main/java/org/apache/paimon/table/FileStoreTable.java
+++ b/paimon-core/src/main/java/org/apache/paimon/table/FileStoreTable.java
@@ -97,8 +97,6 @@ public interface FileStoreTable extends DataTable {
@Override
TableCommitImpl newCommit(String commitUser);
- TableCommitImpl newCommit(String commitUser, String branchName);
-
LocalTableQuery newLocalTableQuery();
default SimpleStats getSchemaFieldStats(DataFileMeta dataFileMeta) {
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/FileStoreTableFactory.java
b/paimon-core/src/main/java/org/apache/paimon/table/FileStoreTableFactory.java
index 638253585..e941a89e0 100644
---
a/paimon-core/src/main/java/org/apache/paimon/table/FileStoreTableFactory.java
+++
b/paimon-core/src/main/java/org/apache/paimon/table/FileStoreTableFactory.java
@@ -53,8 +53,9 @@ public class FileStoreTableFactory {
public static FileStoreTable create(FileIO fileIO, Options options) {
Path tablePath = CoreOptions.path(options);
+ String branchName = CoreOptions.branch(options.toMap());
TableSchema tableSchema =
- new SchemaManager(fileIO, tablePath)
+ new SchemaManager(fileIO, tablePath, branchName)
.latest()
.orElseThrow(
() ->
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/system/AuditLogTable.java
b/paimon-core/src/main/java/org/apache/paimon/table/system/AuditLogTable.java
index b6cfa5c8f..7ff7f936e 100644
---
a/paimon-core/src/main/java/org/apache/paimon/table/system/AuditLogTable.java
+++
b/paimon-core/src/main/java/org/apache/paimon/table/system/AuditLogTable.java
@@ -132,11 +132,6 @@ public class AuditLogTable implements DataTable,
ReadonlyTable {
return new AuditLogDataReader(dataTable.newSnapshotReader());
}
- @Override
- public SnapshotReader newSnapshotReader(String branchName) {
- return new AuditLogDataReader(dataTable.newSnapshotReader(branchName));
- }
-
@Override
public InnerTableScan newScan() {
return new AuditLogBatchScan(dataTable.newScan());
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/system/BucketsTable.java
b/paimon-core/src/main/java/org/apache/paimon/table/system/BucketsTable.java
index 2ab88a346..4c9b9a601 100644
--- a/paimon-core/src/main/java/org/apache/paimon/table/system/BucketsTable.java
+++ b/paimon-core/src/main/java/org/apache/paimon/table/system/BucketsTable.java
@@ -148,11 +148,6 @@ public class BucketsTable implements DataTable,
ReadonlyTable {
return wrapped.newSnapshotReader();
}
- @Override
- public SnapshotReader newSnapshotReader(String branchName) {
- return wrapped.newSnapshotReader(branchName);
- }
-
@Override
public InnerTableScan newScan() {
return wrapped.newScan();
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/system/FileMonitorTable.java
b/paimon-core/src/main/java/org/apache/paimon/table/system/FileMonitorTable.java
index bedc19ac3..7825b93e4 100644
---
a/paimon-core/src/main/java/org/apache/paimon/table/system/FileMonitorTable.java
+++
b/paimon-core/src/main/java/org/apache/paimon/table/system/FileMonitorTable.java
@@ -135,11 +135,6 @@ public class FileMonitorTable implements DataTable,
ReadonlyTable {
return wrapped.newSnapshotReader();
}
- @Override
- public SnapshotReader newSnapshotReader(String branchName) {
- return wrapped.newSnapshotReader(branchName);
- }
-
@Override
public InnerTableScan newScan() {
return wrapped.newScan();
diff --git
a/paimon-core/src/main/java/org/apache/paimon/table/system/ReadOptimizedTable.java
b/paimon-core/src/main/java/org/apache/paimon/table/system/ReadOptimizedTable.java
index 3c6910fbe..0b0b0e586 100644
---
a/paimon-core/src/main/java/org/apache/paimon/table/system/ReadOptimizedTable.java
+++
b/paimon-core/src/main/java/org/apache/paimon/table/system/ReadOptimizedTable.java
@@ -97,11 +97,6 @@ public class ReadOptimizedTable implements DataTable,
ReadonlyTable {
}
}
- @Override
- public SnapshotReader newSnapshotReader(String branchName) {
- return dataTable.newSnapshotReader(branchName);
- }
-
@Override
public InnerTableScan newScan() {
return new InnerTableScanImpl(
diff --git
a/paimon-core/src/main/java/org/apache/paimon/utils/BranchManager.java
b/paimon-core/src/main/java/org/apache/paimon/utils/BranchManager.java
index f3f06f892..41099dfac 100644
--- a/paimon-core/src/main/java/org/apache/paimon/utils/BranchManager.java
+++ b/paimon-core/src/main/java/org/apache/paimon/utils/BranchManager.java
@@ -74,6 +74,10 @@ public class BranchManager {
return new Path(tablePath + "/branch");
}
+ public static boolean isMainBranch(String branch) {
+ return branch.equals(DEFAULT_MAIN_BRANCH);
+ }
+
/** Return the path string of a branch. */
public static String getBranchPath(Path tablePath, String branchName) {
return tablePath.toString() + "/branch/" + BRANCH_PREFIX + branchName;
@@ -87,7 +91,7 @@ public class BranchManager {
/** Create empty branch. */
public void createBranch(String branchName) {
checkArgument(
- !branchName.equals(DEFAULT_MAIN_BRANCH),
+ !isMainBranch(branchName),
String.format(
"Branch name '%s' is the default branch and cannot be
used.",
DEFAULT_MAIN_BRANCH));
@@ -97,11 +101,12 @@ public class BranchManager {
!branchName.chars().allMatch(Character::isDigit),
"Branch name cannot be pure numeric string but is '%s'.",
branchName);
+
try {
TableSchema latestSchema = schemaManager.latest().get();
fileIO.copyFileUtf8(
schemaManager.toSchemaPath(latestSchema.id()),
- schemaManager.branchSchemaPath(branchName,
latestSchema.id()));
+
schemaManager.copyWithBranch(branchName).toSchemaPath(latestSchema.id()));
} catch (IOException e) {
throw new RuntimeException(
String.format(
@@ -113,7 +118,7 @@ public class BranchManager {
public void createBranch(String branchName, long snapshotId) {
checkArgument(
- !branchName.equals(DEFAULT_MAIN_BRANCH),
+ !isMainBranch(branchName),
String.format(
"Branch name '%s' is the default branch and cannot be
used.",
DEFAULT_MAIN_BRANCH));
@@ -130,10 +135,10 @@ public class BranchManager {
// Copy the corresponding snapshot and schema files into the
branch directory
fileIO.copyFileUtf8(
snapshotManager.snapshotPath(snapshotId),
- snapshotManager.branchSnapshotPath(branchName,
snapshot.id()));
+
snapshotManager.copyWithBranch(branchName).snapshotPath(snapshot.id()));
fileIO.copyFileUtf8(
schemaManager.toSchemaPath(snapshot.schemaId()),
- schemaManager.branchSchemaPath(branchName,
snapshot.schemaId()));
+
schemaManager.copyWithBranch(branchName).toSchemaPath(snapshot.schemaId()));
} catch (IOException e) {
throw new RuntimeException(
String.format(
@@ -145,7 +150,7 @@ public class BranchManager {
public void createBranch(String branchName, String tagName) {
checkArgument(
- !branchName.equals(DEFAULT_MAIN_BRANCH),
+ !isMainBranch(branchName),
String.format(
"Branch name '%s' is the default branch and cannot be
used.",
DEFAULT_MAIN_BRANCH));
@@ -162,13 +167,14 @@ public class BranchManager {
try {
// Copy the corresponding tag, snapshot and schema files into the
branch directory
fileIO.copyFileUtf8(
- tagManager.tagPath(tagName),
tagManager.branchTagPath(branchName, tagName));
+ tagManager.tagPath(tagName),
+ tagManager.copyWithBranch(branchName).tagPath(tagName));
fileIO.copyFileUtf8(
snapshotManager.snapshotPath(snapshot.id()),
- snapshotManager.branchSnapshotPath(branchName,
snapshot.id()));
+
snapshotManager.copyWithBranch(branchName).snapshotPath(snapshot.id()));
fileIO.copyFileUtf8(
schemaManager.toSchemaPath(snapshot.schemaId()),
- schemaManager.branchSchemaPath(branchName,
snapshot.schemaId()));
+
schemaManager.copyWithBranch(branchName).toSchemaPath(snapshot.schemaId()));
} catch (IOException e) {
throw new RuntimeException(
String.format(
@@ -231,7 +237,8 @@ public class BranchManager {
new
PriorityQueue<>(Comparator.comparingLong(TableBranch::getCreateTime));
for (Pair<Path, Long> path : paths) {
String branchName =
path.getLeft().getName().substring(BRANCH_PREFIX.length());
- Optional<TableSchema> tableSchema =
schemaManager.latest(branchName);
+ Optional<TableSchema> tableSchema =
+ schemaManager.copyWithBranch(branchName).latest();
if (!tableSchema.isPresent()) {
// Support empty branch.
pq.add(new TableBranch(branchName, path.getValue()));
diff --git
a/paimon-core/src/main/java/org/apache/paimon/utils/SnapshotManager.java
b/paimon-core/src/main/java/org/apache/paimon/utils/SnapshotManager.java
index dbbc8fffd..63679b86a 100644
--- a/paimon-core/src/main/java/org/apache/paimon/utils/SnapshotManager.java
+++ b/paimon-core/src/main/java/org/apache/paimon/utils/SnapshotManager.java
@@ -47,6 +47,7 @@ import java.util.stream.Collectors;
import static org.apache.paimon.utils.BranchManager.DEFAULT_MAIN_BRANCH;
import static org.apache.paimon.utils.BranchManager.getBranchPath;
+import static org.apache.paimon.utils.BranchManager.isMainBranch;
import static org.apache.paimon.utils.FileUtils.listVersionedFiles;
/** Manager for {@link Snapshot}, providing utility methods related to paths
and snapshot hints. */
@@ -63,10 +64,21 @@ public class SnapshotManager implements Serializable {
private final FileIO fileIO;
private final Path tablePath;
+ private final String branch;
public SnapshotManager(FileIO fileIO, Path tablePath) {
+ this(fileIO, tablePath, DEFAULT_MAIN_BRANCH);
+ }
+
+ /** Specify the default branch for data writing. */
+ public SnapshotManager(FileIO fileIO, Path tablePath, String branchName) {
this.fileIO = fileIO;
this.tablePath = tablePath;
+ this.branch = StringUtils.isBlank(branchName) ? DEFAULT_MAIN_BRANCH :
branchName;
+ }
+
+ public SnapshotManager copyWithBranch(String branchName) {
+ return new SnapshotManager(fileIO, tablePath, branchName);
}
public FileIO fileIO() {
@@ -77,45 +89,41 @@ public class SnapshotManager implements Serializable {
return tablePath;
}
- public Path snapshotDirectory() {
- return new Path(tablePath + "/snapshot");
- }
-
public Path changelogDirectory() {
- return new Path(tablePath + "/changelog");
+ return isMainBranch(branch)
+ ? new Path(tablePath + "/changelog")
+ : new Path(getBranchPath(tablePath, branch) + "/changelog");
}
public Path longLivedChangelogPath(long snapshotId) {
- return new Path(tablePath + "/changelog/" + CHANGELOG_PREFIX +
snapshotId);
+ return isMainBranch(branch)
+ ? new Path(tablePath + "/changelog/" + CHANGELOG_PREFIX +
snapshotId)
+ : new Path(
+ getBranchPath(tablePath, branch)
+ + "/changelog/"
+ + CHANGELOG_PREFIX
+ + snapshotId);
}
public Path snapshotPath(long snapshotId) {
- return new Path(tablePath + "/snapshot/" + SNAPSHOT_PREFIX +
snapshotId);
- }
-
- public Path branchSnapshotDirectory(String branchName) {
- return new Path(getBranchPath(tablePath, branchName) + "/snapshot");
- }
-
- public Path branchSnapshotPath(String branchName, long snapshotId) {
- return new Path(
- getBranchPath(tablePath, branchName) + "/snapshot/" +
SNAPSHOT_PREFIX + snapshotId);
- }
-
- public Path snapshotPathByBranch(String branchName, long snapshotId) {
- return branchName.equals(DEFAULT_MAIN_BRANCH)
- ? snapshotPath(snapshotId)
- : branchSnapshotPath(branchName, snapshotId);
+ return isMainBranch(branch)
+ ? new Path(tablePath + "/snapshot/" + SNAPSHOT_PREFIX +
snapshotId)
+ : new Path(
+ getBranchPath(tablePath, branch)
+ + "/snapshot/"
+ + SNAPSHOT_PREFIX
+ + snapshotId);
}
- public Path snapshotDirByBranch(String branchName) {
- return branchName.equals(DEFAULT_MAIN_BRANCH)
- ? snapshotDirectory()
- : branchSnapshotDirectory(branchName);
+ public Path snapshotDirectory() {
+ return isMainBranch(branch)
+ ? new Path(tablePath + "/snapshot")
+ : new Path(getBranchPath(tablePath, branch) + "/snapshot");
}
public Snapshot snapshot(long snapshotId) {
- return snapshot(DEFAULT_MAIN_BRANCH, snapshotId);
+ Path snapshotPath = snapshotPath(snapshotId);
+ return Snapshot.fromPath(fileIO, snapshotPath);
}
public Changelog changelog(long snapshotId) {
@@ -127,11 +135,6 @@ public class SnapshotManager implements Serializable {
return Changelog.fromPath(fileIO, longLivedChangelogPath(snapshotId));
}
- public Snapshot snapshot(String branchName, long snapshotId) {
- Path snapshotPath = snapshotPathByBranch(branchName, snapshotId);
- return Snapshot.fromPath(fileIO, snapshotPath);
- }
-
public boolean snapshotExists(long snapshotId) {
Path path = snapshotPath(snapshotId);
try {
@@ -155,21 +158,13 @@ public class SnapshotManager implements Serializable {
}
public @Nullable Snapshot latestSnapshot() {
- return latestSnapshot(DEFAULT_MAIN_BRANCH);
- }
-
- public @Nullable Snapshot latestSnapshot(String branchName) {
- Long snapshotId = latestSnapshotId(branchName);
- return snapshotId == null ? null : snapshot(branchName, snapshotId);
+ Long snapshotId = latestSnapshotId();
+ return snapshotId == null ? null : snapshot(snapshotId);
}
public @Nullable Long latestSnapshotId() {
- return latestSnapshotId(DEFAULT_MAIN_BRANCH);
- }
-
- public @Nullable Long latestSnapshotId(String branchName) {
try {
- return findLatest(snapshotDirByBranch(branchName),
SNAPSHOT_PREFIX, this::snapshotPath);
+ return findLatest(snapshotDirectory(), SNAPSHOT_PREFIX,
this::snapshotPath);
} catch (IOException e) {
throw new RuntimeException("Failed to find latest snapshot id", e);
}
@@ -181,7 +176,11 @@ public class SnapshotManager implements Serializable {
}
public @Nullable Long earliestSnapshotId() {
- return earliestSnapshotId(DEFAULT_MAIN_BRANCH);
+ try {
+ return findEarliest(snapshotDirectory(), SNAPSHOT_PREFIX,
this::snapshotPath);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to find earliest snapshot id",
e);
+ }
}
public @Nullable Long earliestLongLivedChangelogId() {
@@ -205,15 +204,6 @@ public class SnapshotManager implements Serializable {
return latestSnapshotId();
}
- public @Nullable Long earliestSnapshotId(String branchName) {
- try {
- return findEarliest(
- snapshotDirByBranch(branchName), SNAPSHOT_PREFIX,
this::snapshotPath);
- } catch (IOException e) {
- throw new RuntimeException("Failed to find earliest snapshot id",
e);
- }
- }
-
public @Nullable Long pickOrLatest(Predicate<Snapshot> predicate) {
Long latestId = latestSnapshotId();
Long earliestId = earliestSnapshotId();
@@ -255,7 +245,6 @@ public class SnapshotManager implements Serializable {
earliest = earliestSnapshot;
}
Long latest = latestSnapshotId();
-
if (earliest == null || latest == null) {
return null;
}
@@ -370,14 +359,14 @@ public class SnapshotManager implements Serializable {
public Iterator<Snapshot> snapshots() throws IOException {
return listVersionedFiles(fileIO, snapshotDirectory(), SNAPSHOT_PREFIX)
- .map(this::snapshot)
+ .map(id -> snapshot(id))
.sorted(Comparator.comparingLong(Snapshot::id))
.iterator();
}
public Iterator<Changelog> changelogs() throws IOException {
return listVersionedFiles(fileIO, changelogDirectory(),
CHANGELOG_PREFIX)
- .map(this::changelog)
+ .map(snapshotId -> changelog(snapshotId))
.sorted(Comparator.comparingLong(Changelog::id))
.iterator();
}
@@ -389,7 +378,7 @@ public class SnapshotManager implements Serializable {
public List<Snapshot> safelyGetAllSnapshots() throws IOException {
List<Path> paths =
listVersionedFiles(fileIO, snapshotDirectory(),
SNAPSHOT_PREFIX)
- .map(this::snapshotPath)
+ .map(id -> snapshotPath(id))
.collect(Collectors.toList());
List<Snapshot> snapshots = new ArrayList<>();
@@ -406,7 +395,7 @@ public class SnapshotManager implements Serializable {
public List<Changelog> safelyGetAllChangelogs() throws IOException {
List<Path> paths =
listVersionedFiles(fileIO, changelogDirectory(),
CHANGELOG_PREFIX)
- .map(this::longLivedChangelogPath)
+ .map(id -> longLivedChangelogPath(id))
.collect(Collectors.toList());
List<Changelog> changelogs = new ArrayList<>();
@@ -582,7 +571,6 @@ public class SnapshotManager implements Serializable {
return snapshotId;
}
}
-
return findByListFiles(Math::max, dir, prefix);
}
@@ -602,7 +590,7 @@ public class SnapshotManager implements Serializable {
}
public Long readHint(String fileName) {
- return readHint(fileName, snapshotDirByBranch(DEFAULT_MAIN_BRANCH));
+ return readHint(fileName, snapshotDirectory());
}
public Long readHint(String fileName, Path dir) {
@@ -629,11 +617,7 @@ public class SnapshotManager implements Serializable {
}
public void commitLatestHint(long snapshotId) throws IOException {
- commitLatestHint(snapshotId, DEFAULT_MAIN_BRANCH);
- }
-
- public void commitLatestHint(long snapshotId, String branchName) throws
IOException {
- commitHint(snapshotId, LATEST, snapshotDirByBranch(branchName));
+ commitHint(snapshotId, LATEST, snapshotDirectory());
}
public void commitLongLivedChangelogLatestHint(long snapshotId) throws
IOException {
@@ -645,11 +629,7 @@ public class SnapshotManager implements Serializable {
}
public void commitEarliestHint(long snapshotId) throws IOException {
- commitEarliestHint(snapshotId, DEFAULT_MAIN_BRANCH);
- }
-
- public void commitEarliestHint(long snapshotId, String branchName) throws
IOException {
- commitHint(snapshotId, EARLIEST, snapshotDirByBranch(branchName));
+ commitHint(snapshotId, EARLIEST, snapshotDirectory());
}
private void commitHint(long snapshotId, String fileName, Path dir) throws
IOException {
diff --git a/paimon-core/src/main/java/org/apache/paimon/utils/TagManager.java
b/paimon-core/src/main/java/org/apache/paimon/utils/TagManager.java
index 8b7818fed..c96bbdd56 100644
--- a/paimon-core/src/main/java/org/apache/paimon/utils/TagManager.java
+++ b/paimon-core/src/main/java/org/apache/paimon/utils/TagManager.java
@@ -45,7 +45,9 @@ import java.util.TreeMap;
import java.util.function.Predicate;
import java.util.stream.Collectors;
+import static org.apache.paimon.utils.BranchManager.DEFAULT_MAIN_BRANCH;
import static org.apache.paimon.utils.BranchManager.getBranchPath;
+import static org.apache.paimon.utils.BranchManager.isMainBranch;
import static org.apache.paimon.utils.FileUtils.listVersionedFileStatus;
import static org.apache.paimon.utils.Preconditions.checkArgument;
@@ -58,25 +60,35 @@ public class TagManager {
private final FileIO fileIO;
private final Path tablePath;
+ private final String branch;
public TagManager(FileIO fileIO, Path tablePath) {
+ this(fileIO, tablePath, DEFAULT_MAIN_BRANCH);
+ }
+
+ /** Specify the default branch for data writing. */
+ public TagManager(FileIO fileIO, Path tablePath, String branch) {
this.fileIO = fileIO;
this.tablePath = tablePath;
+ this.branch = StringUtils.isBlank(branch) ? DEFAULT_MAIN_BRANCH :
branch;
}
- /** Return the root Directory of tags. */
- public Path tagDirectory() {
- return new Path(tablePath + "/tag");
+ public TagManager copyWithBranch(String branchName) {
+ return new TagManager(fileIO, tablePath, branchName);
}
- /** Return the path of a tag. */
- public Path tagPath(String tagName) {
- return new Path(tablePath + "/tag/" + TAG_PREFIX + tagName);
+ /** Return the root Directory of tags. */
+ public Path tagDirectory() {
+ return isMainBranch(branch)
+ ? new Path(tablePath + "/tag")
+ : new Path(getBranchPath(tablePath, branch) + "/tag");
}
/** Return the path of a tag in branch. */
- public Path branchTagPath(String branchName, String tagName) {
- return new Path(getBranchPath(tablePath, branchName) + "/tag/" +
TAG_PREFIX + tagName);
+ public Path tagPath(String tagName) {
+ return isMainBranch(branch)
+ ? new Path(tablePath + "/tag/" + TAG_PREFIX + tagName)
+ : new Path(getBranchPath(tablePath, branch) + "/tag/" +
TAG_PREFIX + tagName);
}
/** Create a tag from given snapshot and save it in the storage. */
@@ -152,14 +164,13 @@ public class TagManager {
List<Snapshot> taggedSnapshots;
// skip file deletion if snapshot exists
- if (snapshotManager.snapshotExists(taggedSnapshot.id())) {
+ if
(snapshotManager.copyWithBranch(branch).snapshotExists(taggedSnapshot.id())) {
deleteTagMetaFile(tagName, callbacks);
return;
} else {
// FileIO discovers tags by tag file, so we should read all tags
before we delete tag
SortedMap<Snapshot, List<String>> tags = tags();
deleteTagMetaFile(tagName, callbacks);
-
// skip data file clean if more than 1 tags are created based on
this snapshot
if (tags.get(taggedSnapshot).size() > 1) {
return;
@@ -196,7 +207,7 @@ public class TagManager {
skippedSnapshots.add(taggedSnapshots.get(index - 1));
}
// the nearest right neighbor
- Snapshot right = snapshotManager.earliestSnapshot();
+ Snapshot right =
snapshotManager.copyWithBranch(branch).earliestSnapshot();
if (index + 1 < taggedSnapshots.size()) {
Snapshot rightTag = taggedSnapshots.get(index + 1);
right = right.id() < rightTag.id() ? right : rightTag;
@@ -226,7 +237,7 @@ public class TagManager {
taggedSnapshot,
tagDeletion.manifestSkippingSet(skippedSnapshots));
}
- /** Check if a tag exists. */
+ /** Check if a branch tag exists. */
public boolean tagExists(String tagName) {
Path path = tagPath(tagName);
try {
@@ -242,7 +253,6 @@ public class TagManager {
/** Get the tagged snapshot by name. */
public Snapshot taggedSnapshot(String tagName) {
checkArgument(tagExists(tagName), "Tag '%s' doesn't exist.", tagName);
- // Trim to snapshot to avoid equals and compare snapshot.
return Tag.fromPath(fileIO, tagPath(tagName)).trimToSnapshot();
}
@@ -259,7 +269,7 @@ public class TagManager {
return new ArrayList<>(tags().keySet());
}
- /** Get all tagged snapshots with tag names sorted by snapshot id. */
+ /** Get all tagged snapshots with names sorted by snapshot id. */
public SortedMap<Snapshot, List<String>> tags() {
return tags(tagName -> true);
}
diff --git
a/paimon-core/src/test/java/org/apache/paimon/table/AppendOnlyFileStoreTableTest.java
b/paimon-core/src/test/java/org/apache/paimon/table/AppendOnlyFileStoreTableTest.java
index 62124a617..b569a76a8 100644
---
a/paimon-core/src/test/java/org/apache/paimon/table/AppendOnlyFileStoreTableTest.java
+++
b/paimon-core/src/test/java/org/apache/paimon/table/AppendOnlyFileStoreTableTest.java
@@ -128,9 +128,11 @@ public class AppendOnlyFileStoreTableTest extends
FileStoreTableTestBase {
public void testBranchBatchReadWrite() throws Exception {
FileStoreTable table = createFileStoreTable();
generateBranch(table);
- writeBranchData(table);
- List<Split> splits =
toSplits(table.newSnapshotReader(BRANCH_NAME).read().dataSplits());
- TableRead read = table.newRead();
+
+ FileStoreTable tableBranch = createFileStoreTable(BRANCH_NAME);
+ writeBranchData(tableBranch);
+ List<Split> splits =
toSplits(tableBranch.newSnapshotReader().read().dataSplits());
+ TableRead read = tableBranch.newRead();
assertThat(getResult(read, splits, binaryRow(1), 0,
BATCH_ROW_TO_STRING))
.hasSameElementsAs(
Arrays.asList(
@@ -308,15 +310,18 @@ public class AppendOnlyFileStoreTableTest extends
FileStoreTableTestBase {
public void testBranchStreamingReadWrite() throws Exception {
FileStoreTable table = createFileStoreTable();
generateBranch(table);
- writeBranchData(table);
+
+ FileStoreTable tableBranch = createFileStoreTable(BRANCH_NAME);
+ writeBranchData(tableBranch);
List<Split> splits =
toSplits(
- table.newSnapshotReader(BRANCH_NAME)
+ tableBranch
+ .newSnapshotReader()
.withMode(ScanMode.DELTA)
.read()
.dataSplits());
- TableRead read = table.newRead();
+ TableRead read = tableBranch.newRead();
assertThat(getResult(read, splits, binaryRow(1), 0,
STREAMING_ROW_TO_STRING))
.isEqualTo(
@@ -804,7 +809,7 @@ public class AppendOnlyFileStoreTableTest extends
FileStoreTableTestBase {
private void writeBranchData(FileStoreTable table) throws Exception {
StreamTableWrite write = table.newWrite(commitUser);
- StreamTableCommit commit = table.newCommit(commitUser, BRANCH_NAME);
+ StreamTableCommit commit = table.newCommit(commitUser);
write.write(rowData(1, 10, 100L));
write.write(rowData(2, 20, 200L));
@@ -845,6 +850,28 @@ public class AppendOnlyFileStoreTableTest extends
FileStoreTableTestBase {
return new AppendOnlyFileStoreTable(FileIOFinder.find(tablePath),
tablePath, tableSchema);
}
+ @Override
+ protected FileStoreTable createFileStoreTable(String branch,
Consumer<Options> configure)
+ throws Exception {
+ Options conf = new Options();
+ conf.set(CoreOptions.PATH, tablePath.toString());
+ conf.set(CoreOptions.BRANCH, branch);
+ configure.accept(conf);
+ if (!conf.contains(BUCKET_KEY) && conf.get(BUCKET) != -1) {
+ conf.set(BUCKET_KEY, "a");
+ }
+ TableSchema tableSchema =
+ SchemaUtils.forceCommit(
+ new SchemaManager(LocalFileIO.create(), tablePath,
branch),
+ new Schema(
+ ROW_TYPE.getFields(),
+ Collections.singletonList("pt"),
+ Collections.emptyList(),
+ conf.toMap(),
+ ""));
+ return new AppendOnlyFileStoreTable(FileIOFinder.find(tablePath),
tablePath, tableSchema);
+ }
+
@Override
protected FileStoreTable overwriteTestFileStoreTable() throws Exception {
Options conf = new Options();
diff --git
a/paimon-core/src/test/java/org/apache/paimon/table/FileStoreTableTestBase.java
b/paimon-core/src/test/java/org/apache/paimon/table/FileStoreTableTestBase.java
index 778c871f7..b30dab420 100644
---
a/paimon-core/src/test/java/org/apache/paimon/table/FileStoreTableTestBase.java
+++
b/paimon-core/src/test/java/org/apache/paimon/table/FileStoreTableTestBase.java
@@ -1019,22 +1019,22 @@ public abstract class FileStoreTableTestBase {
// verify test-tag in test-branch is equal to snapshot 2
Snapshot branchTag =
Snapshot.fromPath(
- new TraceableFileIO(),
tagManager.branchTagPath("test-branch", "test-tag"));
+ new TraceableFileIO(),
+
tagManager.copyWithBranch("test-branch").tagPath("test-tag"));
assertThat(branchTag.equals(snapshot2)).isTrue();
// verify snapshot in test-branch is equal to snapshot 2
- SnapshotManager snapshotManager = new SnapshotManager(new
TraceableFileIO(), tablePath);
+ SnapshotManager snapshotManager =
+ new SnapshotManager(new TraceableFileIO(), tablePath,
"test-branch");
Snapshot branchSnapshot =
- Snapshot.fromPath(
- new TraceableFileIO(),
- snapshotManager.branchSnapshotPath("test-branch", 2));
+ Snapshot.fromPath(new TraceableFileIO(),
snapshotManager.snapshotPath(2));
assertThat(branchSnapshot.equals(snapshot2)).isTrue();
// verify schema in test-branch is equal to schema 0
- SchemaManager schemaManager = new SchemaManager(new TraceableFileIO(),
tablePath);
+ SchemaManager schemaManager =
+ new SchemaManager(new TraceableFileIO(), tablePath,
"test-branch");
TableSchema branchSchema =
- SchemaManager.fromPath(
- new TraceableFileIO(),
schemaManager.branchSchemaPath("test-branch", 0));
+ SchemaManager.fromPath(new TraceableFileIO(),
schemaManager.toSchemaPath(0));
TableSchema schema0 = schemaManager.schema(0);
assertThat(branchSchema.equals(schema0)).isTrue();
}
@@ -1312,9 +1312,10 @@ public abstract class FileStoreTableTestBase {
generateBranch(table);
+ FileStoreTable tableBranch = createFileStoreTable(BRANCH_NAME);
// Write data to branch1
- try (StreamTableWrite write = table.newWrite(commitUser);
- StreamTableCommit commit = table.newCommit(commitUser,
BRANCH_NAME)) {
+ try (StreamTableWrite write = tableBranch.newWrite(commitUser);
+ StreamTableCommit commit = tableBranch.newCommit(commitUser)) {
write.write(rowData(2, 20, 200L));
commit.commit(1, write.prepareCommit(false, 2));
}
@@ -1330,16 +1331,16 @@ public abstract class FileStoreTableTestBase {
// Validate data in branch1
assertThat(
getResult(
- table.newRead(),
-
toSplits(table.newSnapshotReader(BRANCH_NAME).read().dataSplits()),
+ tableBranch.newRead(),
+
toSplits(tableBranch.newSnapshotReader().read().dataSplits()),
BATCH_ROW_TO_STRING))
.containsExactlyInAnyOrder(
"0|0|0|binary|varbinary|mapKey:mapVal|multiset",
"2|20|200|binary|varbinary|mapKey:mapVal|multiset");
// Write two rows data to branch1 again
- try (StreamTableWrite write = table.newWrite(commitUser);
- StreamTableCommit commit = table.newCommit(commitUser,
BRANCH_NAME)) {
+ try (StreamTableWrite write = tableBranch.newWrite(commitUser);
+ StreamTableCommit commit = tableBranch.newCommit(commitUser)) {
write.write(rowData(3, 30, 300L));
write.write(rowData(4, 40, 400L));
commit.commit(2, write.prepareCommit(false, 3));
@@ -1356,8 +1357,8 @@ public abstract class FileStoreTableTestBase {
// Verify data in branch1
assertThat(
getResult(
- table.newRead(),
-
toSplits(table.newSnapshotReader(BRANCH_NAME).read().dataSplits()),
+ tableBranch.newRead(),
+
toSplits(tableBranch.newSnapshotReader().read().dataSplits()),
BATCH_ROW_TO_STRING))
.containsExactlyInAnyOrder(
"0|0|0|binary|varbinary|mapKey:mapVal|multiset",
@@ -1446,6 +1447,14 @@ public abstract class FileStoreTableTestBase {
return createFileStoreTable(conf -> conf.set(BUCKET, numOfBucket));
}
+ protected FileStoreTable createFileStoreTable(String branch, int
numOfBucket) throws Exception {
+ return createFileStoreTable(branch, conf -> conf.set(BUCKET,
numOfBucket));
+ }
+
+ protected FileStoreTable createFileStoreTable(String branch) throws
Exception {
+ return createFileStoreTable(branch, 1);
+ }
+
protected FileStoreTable createFileStoreTable() throws Exception {
return createFileStoreTable(1);
}
@@ -1453,6 +1462,9 @@ public abstract class FileStoreTableTestBase {
protected abstract FileStoreTable createFileStoreTable(Consumer<Options>
configure)
throws Exception;
+ protected abstract FileStoreTable createFileStoreTable(
+ String branch, Consumer<Options> configure) throws Exception;
+
protected abstract FileStoreTable overwriteTestFileStoreTable() throws
Exception;
private static InternalRow overwriteRow(Object... values) {
@@ -1571,10 +1583,11 @@ public abstract class FileStoreTableTestBase {
assertThat(branchManager.branchExists(BRANCH_NAME)).isTrue();
// Verify branch1 and the main branch have the same data
+ FileStoreTable tableBranch = createFileStoreTable(BRANCH_NAME);
assertThat(
getResult(
- table.newRead(),
-
toSplits(table.newSnapshotReader(BRANCH_NAME).read().dataSplits()),
+ tableBranch.newRead(),
+
toSplits(tableBranch.newSnapshotReader().read().dataSplits()),
BATCH_ROW_TO_STRING))
.containsExactlyInAnyOrder("0|0|0|binary|varbinary|mapKey:mapVal|multiset");
}
diff --git
a/paimon-core/src/test/java/org/apache/paimon/table/PrimaryKeyFileStoreTableTest.java
b/paimon-core/src/test/java/org/apache/paimon/table/PrimaryKeyFileStoreTableTest.java
index 4c33e9893..e4a6b1d3f 100644
---
a/paimon-core/src/test/java/org/apache/paimon/table/PrimaryKeyFileStoreTableTest.java
+++
b/paimon-core/src/test/java/org/apache/paimon/table/PrimaryKeyFileStoreTableTest.java
@@ -81,6 +81,7 @@ import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
+import static org.apache.paimon.CoreOptions.BRANCH;
import static org.apache.paimon.CoreOptions.BUCKET;
import static org.apache.paimon.CoreOptions.CHANGELOG_NUM_RETAINED_MAX;
import static org.apache.paimon.CoreOptions.CHANGELOG_NUM_RETAINED_MIN;
@@ -257,9 +258,10 @@ public class PrimaryKeyFileStoreTableTest extends
FileStoreTableTestBase {
public void testBranchBatchReadWrite() throws Exception {
FileStoreTable table = createFileStoreTable();
generateBranch(table);
- writeBranchData(table);
- List<Split> splits =
toSplits(table.newSnapshotReader(BRANCH_NAME).read().dataSplits());
- TableRead read = table.newRead();
+ FileStoreTable tableBranch = createFileStoreTable(BRANCH_NAME);
+ writeBranchData(tableBranch);
+ List<Split> splits =
toSplits(tableBranch.newSnapshotReader().read().dataSplits());
+ TableRead read = tableBranch.newRead();
assertThat(getResult(read, splits, binaryRow(1), 0,
BATCH_ROW_TO_STRING))
.isEqualTo(
Collections.singletonList(
@@ -328,15 +330,18 @@ public class PrimaryKeyFileStoreTableTest extends
FileStoreTableTestBase {
public void testBranchStreamingReadWrite() throws Exception {
FileStoreTable table = createFileStoreTable();
generateBranch(table);
- writeBranchData(table);
+
+ FileStoreTable tableBranch = createFileStoreTable(BRANCH_NAME);
+ writeBranchData(tableBranch);
List<Split> splits =
toSplits(
- table.newSnapshotReader(BRANCH_NAME)
+ tableBranch
+ .newSnapshotReader()
.withMode(ScanMode.DELTA)
.read()
.dataSplits());
- TableRead read = table.newRead();
+ TableRead read = tableBranch.newRead();
assertThat(getResult(read, splits, binaryRow(1), 0,
STREAMING_ROW_TO_STRING))
.isEqualTo(
Collections.singletonList(
@@ -648,7 +653,7 @@ public class PrimaryKeyFileStoreTableTest extends
FileStoreTableTestBase {
private void writeBranchData(FileStoreTable table) throws Exception {
StreamTableWrite write = table.newWrite(commitUser);
- StreamTableCommit commit = table.newCommit(commitUser, BRANCH_NAME);
+ StreamTableCommit commit = table.newCommit(commitUser);
write.write(rowData(1, 10, 100L));
write.write(rowData(2, 20, 200L));
@@ -1645,4 +1650,29 @@ public class PrimaryKeyFileStoreTableTest extends
FileStoreTableTestBase {
""));
return new PrimaryKeyFileStoreTable(FileIOFinder.find(tablePath),
tablePath, tableSchema);
}
+
+ @Override
+ protected FileStoreTable createFileStoreTable(String branch,
Consumer<Options> configure)
+ throws Exception {
+ return createFileStoreTable(branch, configure, ROW_TYPE);
+ }
+
+ private FileStoreTable createFileStoreTable(
+ String branch, Consumer<Options> configure, RowType rowType)
throws Exception {
+ Options options = new Options();
+ options.set(CoreOptions.PATH, tablePath.toString());
+ options.set(BUCKET, 1);
+ options.set(BRANCH, branch);
+ configure.accept(options);
+ TableSchema tableSchema =
+ SchemaUtils.forceCommit(
+ new SchemaManager(LocalFileIO.create(), tablePath),
+ new Schema(
+ rowType.getFields(),
+ Collections.singletonList("pt"),
+ Arrays.asList("pt", "a"),
+ options.toMap(),
+ ""));
+ return new PrimaryKeyFileStoreTable(FileIOFinder.find(tablePath),
tablePath, tableSchema);
+ }
}
diff --git
a/paimon-core/src/test/java/org/apache/paimon/table/SchemaEvolutionTableTestBase.java
b/paimon-core/src/test/java/org/apache/paimon/table/SchemaEvolutionTableTestBase.java
index a55bda911..f5874bed7 100644
---
a/paimon-core/src/test/java/org/apache/paimon/table/SchemaEvolutionTableTestBase.java
+++
b/paimon-core/src/test/java/org/apache/paimon/table/SchemaEvolutionTableTestBase.java
@@ -502,12 +502,6 @@ public abstract class SchemaEvolutionTableTestBase {
.orElseThrow(IllegalStateException::new)));
}
- @Override
- public Optional<TableSchema> latest(String branchName) {
- // for compatibility test
- return latest();
- }
-
@Override
public List<TableSchema> listAll() {
return new ArrayList<>(tableSchemas.values());
diff --git
a/paimon-core/src/test/java/org/apache/paimon/table/WritePreemptMemoryTest.java
b/paimon-core/src/test/java/org/apache/paimon/table/WritePreemptMemoryTest.java
index 548dc7205..ee74a9e8f 100644
---
a/paimon-core/src/test/java/org/apache/paimon/table/WritePreemptMemoryTest.java
+++
b/paimon-core/src/test/java/org/apache/paimon/table/WritePreemptMemoryTest.java
@@ -110,6 +110,31 @@ public class WritePreemptMemoryTest extends
FileStoreTableTestBase {
return new PrimaryKeyFileStoreTable(FileIOFinder.find(tablePath),
tablePath, schema);
}
+ @Override
+ protected FileStoreTable createFileStoreTable(String branch,
Consumer<Options> configure)
+ throws Exception {
+ Options options = new Options();
+ options.set(CoreOptions.BUCKET, 1);
+ options.set(CoreOptions.PATH, tablePath.toString());
+ // Run with minimal memory to ensure a more intense preempt
+ // Currently a writer needs at least one page
+ int pages = 10;
+ options.set(CoreOptions.WRITE_BUFFER_SIZE, new MemorySize(pages *
1024));
+ options.set(CoreOptions.PAGE_SIZE, new MemorySize(1024));
+ options.set(CoreOptions.BRANCH, branch);
+ configure.accept(options);
+ TableSchema schema =
+ SchemaUtils.forceCommit(
+ new SchemaManager(LocalFileIO.create(), tablePath,
branch),
+ new Schema(
+ ROW_TYPE.getFields(),
+ Collections.singletonList("pt"),
+ Arrays.asList("pt", "a"),
+ options.toMap(),
+ ""));
+ return new PrimaryKeyFileStoreTable(FileIOFinder.find(tablePath),
tablePath, schema);
+ }
+
@Override
protected FileStoreTable overwriteTestFileStoreTable() throws Exception {
Options conf = new Options();
diff --git
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/FlinkTableFactory.java
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/FlinkTableFactory.java
index 4c9f8ff9b..1617b4cc3 100644
---
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/FlinkTableFactory.java
+++
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/FlinkTableFactory.java
@@ -58,9 +58,12 @@ public class FlinkTableFactory extends
AbstractFlinkTableFactory {
if (options.get(AUTO_CREATE)) {
try {
Path tablePath = CoreOptions.path(table.getOptions());
+ String branch = CoreOptions.branch(table.getOptions());
SchemaManager schemaManager =
new SchemaManager(
- FileIO.get(tablePath,
createCatalogContext(context)), tablePath);
+ FileIO.get(tablePath,
createCatalogContext(context)),
+ tablePath,
+ branch);
if (!schemaManager.latest().isPresent()) {
schemaManager.createTable(FlinkCatalog.fromCatalogTable(table));
}
diff --git
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/sink/FlinkSink.java
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/sink/FlinkSink.java
index cf9bd487a..c3460f39c 100644
---
a/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/sink/FlinkSink.java
+++
b/paimon-flink/paimon-flink-common/src/main/java/org/apache/paimon/flink/sink/FlinkSink.java
@@ -235,6 +235,7 @@ public abstract class FlinkSink<T> implements Serializable {
commitUser,
createCommitterFactory(),
createCommittableStateManager());
+
if (options.get(SINK_AUTO_TAG_FOR_SAVEPOINT)) {
committerOperator =
new AutoTagForSavepointCommitterOperator<>(
diff --git
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/AppendOnlyTableITCase.java
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/AppendOnlyTableITCase.java
index ad432d7cd..11f5b2313 100644
---
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/AppendOnlyTableITCase.java
+++
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/AppendOnlyTableITCase.java
@@ -259,6 +259,22 @@ public class AppendOnlyTableITCase extends
CatalogITCaseBase {
assertThat(iterator.collect(1)).containsExactlyInAnyOrder(Row.of(2));
}
+ @Test
+ public void testReadWriteBranch() throws Exception {
+ // create table
+ sql("CREATE TABLE T (id INT)");
+ // insert data
+ batchSql("INSERT INTO T VALUES (1)");
+ // create tag
+ paimonTable("T").createTag("tag1", 1);
+ // create branch
+ paimonTable("T").createBranch("branch1", "tag1");
+ // insert data to branch
+ batchSql("INSERT INTO T/*+ OPTIONS('branch' = 'branch1') */ VALUES
(2)");
+ List<Row> rows = batchSql("select * from T /*+ OPTIONS('branch' =
'branch1') */");
+ assertThat(rows).containsExactlyInAnyOrder(Row.of(2), Row.of(1));
+ }
+
@Override
protected List<String> ddl() {
return Arrays.asList(
diff --git
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/FileStoreITCase.java
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/FileStoreITCase.java
index 980f3fb90..225c7f63f 100644
---
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/FileStoreITCase.java
+++
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/FileStoreITCase.java
@@ -33,6 +33,7 @@ import org.apache.paimon.schema.SchemaManager;
import org.apache.paimon.table.FileStoreTable;
import org.apache.paimon.table.FileStoreTableFactory;
import org.apache.paimon.utils.BlockingIterator;
+import org.apache.paimon.utils.BranchManager;
import org.apache.paimon.utils.FailingFileIO;
import org.apache.flink.api.common.functions.MapFunction;
@@ -62,6 +63,7 @@ import
org.apache.flink.testutils.junit.extensions.parameterized.Parameters;
import org.apache.flink.types.Row;
import org.apache.flink.types.RowKind;
import org.apache.flink.util.CloseableIterator;
+import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -76,6 +78,7 @@ import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.Stream;
+import static org.apache.paimon.CoreOptions.BRANCH;
import static org.apache.paimon.CoreOptions.BUCKET;
import static org.apache.paimon.CoreOptions.BUCKET_KEY;
import static org.apache.paimon.CoreOptions.FILE_FORMAT;
@@ -125,11 +128,18 @@ public class FileStoreITCase extends AbstractTestBase {
private final StreamExecutionEnvironment env;
+ protected static String branch;
+
public FileStoreITCase(boolean isBatch) {
this.isBatch = isBatch;
this.env = isBatch ? buildBatchEnv() : buildStreamEnv();
}
+ @BeforeAll
+ public static void before() {
+ branch = BranchManager.DEFAULT_MAIN_BRANCH;
+ }
+
@Parameters(name = "isBatch-{0}")
public static List<Boolean> getVarSeg() {
return Arrays.asList(true, false);
@@ -468,7 +478,7 @@ public class FileStoreITCase extends AbstractTestBase {
"");
return retryArtificialException(
() -> {
- new SchemaManager(LocalFileIO.create(),
tablePath).createTable(schema);
+ new SchemaManager(LocalFileIO.create(), tablePath,
branch).createTable(schema);
return FileStoreTableFactory.create(LocalFileIO.create(),
options);
});
}
@@ -484,6 +494,7 @@ public class FileStoreITCase extends AbstractTestBase {
options.set(PATH, FailingFileIO.getFailingPath(failingName,
temporaryPath));
}
options.set(FILE_FORMAT, CoreOptions.FILE_FORMAT_AVRO);
+ options.set(BRANCH, branch);
return options;
}
diff --git a/paimon-core/src/main/java/org/apache/paimon/table/DataTable.java
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/FileStoreWithBranchITCase.java
similarity index 50%
copy from paimon-core/src/main/java/org/apache/paimon/table/DataTable.java
copy to
paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/FileStoreWithBranchITCase.java
index 1d8921304..8a2374b3c 100644
--- a/paimon-core/src/main/java/org/apache/paimon/table/DataTable.java
+++
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/FileStoreWithBranchITCase.java
@@ -16,32 +16,28 @@
* limitations under the License.
*/
-package org.apache.paimon.table;
+package org.apache.paimon.flink;
-import org.apache.paimon.CoreOptions;
-import org.apache.paimon.fs.FileIO;
-import org.apache.paimon.fs.Path;
-import org.apache.paimon.table.source.snapshot.SnapshotReader;
-import org.apache.paimon.utils.BranchManager;
-import org.apache.paimon.utils.SnapshotManager;
-import org.apache.paimon.utils.TagManager;
+import org.apache.paimon.flink.sink.FixedBucketSink;
+import org.apache.paimon.flink.source.ContinuousFileStoreSource;
+import org.apache.paimon.flink.source.StaticFileStoreSource;
-/** A {@link Table} for data. */
-public interface DataTable extends InnerTable {
+import
org.apache.flink.testutils.junit.extensions.parameterized.ParameterizedTestExtension;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.extension.ExtendWith;
- SnapshotReader newSnapshotReader();
-
- SnapshotReader newSnapshotReader(String branchName);
-
- CoreOptions coreOptions();
-
- SnapshotManager snapshotManager();
-
- TagManager tagManager();
-
- BranchManager branchManager();
-
- Path location();
-
- FileIO fileIO();
+/**
+ * ITCase for {@link StaticFileStoreSource}, {@link ContinuousFileStoreSource}
and {@link
+ * FixedBucketSink}.
+ */
+@ExtendWith(ParameterizedTestExtension.class)
+public class FileStoreWithBranchITCase extends FileStoreITCase {
+ public FileStoreWithBranchITCase(boolean isBatch) {
+ super(isBatch);
+ }
+
+ @BeforeAll
+ public static void before() {
+ branch = "testBranch";
+ }
}
diff --git
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/PrimaryKeyFileStoreTableITCase.java
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/PrimaryKeyFileStoreTableITCase.java
index e495ad3da..229517e76 100644
---
a/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/PrimaryKeyFileStoreTableITCase.java
+++
b/paimon-flink/paimon-flink-common/src/test/java/org/apache/paimon/flink/PrimaryKeyFileStoreTableITCase.java
@@ -168,6 +168,61 @@ public class PrimaryKeyFileStoreTableITCase extends
AbstractTestBase {
innerTestChangelogProducing(Collections.singletonList("'changelog-producer' =
'lookup'"));
}
+ @Test
+ public void testTableReadWriteBranch() throws Exception {
+ TableEnvironment sEnv =
+ tableEnvironmentBuilder()
+ .streamingMode()
+
.checkpointIntervalMs(ThreadLocalRandom.current().nextInt(900) + 100)
+ .parallelism(1)
+ .build();
+
+ sEnv.executeSql(createCatalogSql("testCatalog", path + "/warehouse"));
+ sEnv.executeSql("USE CATALOG testCatalog");
+ sEnv.executeSql(
+ "CREATE TABLE T2 ( k INT, v STRING, PRIMARY KEY (k) NOT
ENFORCED ) "
+ + "WITH ( "
+ + "'bucket' = '2'"
+ + ")");
+
+ CloseableIterator<Row> it = sEnv.executeSql("SELECT * FROM
T2").collect();
+
+ // insert data
+ sEnv.executeSql("INSERT INTO T2 VALUES (1, 'A')").await();
+ // read initial data
+ List<String> actual = new ArrayList<>();
+ for (int i = 0; i < 1; i++) {
+ actual.add(it.next().toString());
+ }
+
+ assertThat(actual).containsExactlyInAnyOrder("+I[1, A]");
+
+ // create tag
+ sEnv.executeSql(
+ String.format("CALL sys.create_tag('%s.%s', 'tag2', 1, '5
d')", "default", "T2"));
+ // create branch
+ sEnv.executeSql(
+ String.format(
+ "CALL sys.create_branch('%s.%s', 'branch1', 'tag2')",
"default", "T2"));
+ // alter table
+ sEnv.executeSql("ALTER TABLE T2 SET
('changelog-producer'='full-compaction')");
+
+ CloseableIterator<Row> branchIt =
+ sEnv.executeSql("select * from T2 /*+ OPTIONS('branch' =
'branch1') */").collect();
+ // insert data to branch
+ sEnv.executeSql(
+ "INSERT INTO T2/*+ OPTIONS('branch' = 'branch1') */
VALUES (10, 'v10'),(11, 'v11'),(12, 'v12')")
+ .await();
+
+ // read initial data
+ List<String> actualBranch = new ArrayList<>();
+ for (int i = 0; i < 4; i++) {
+ actualBranch.add(branchIt.next().toString());
+ }
+ assertThat(actualBranch)
+ .containsExactlyInAnyOrder("+I[1, A]", "+I[10, v10]", "+I[11,
v11]", "+I[12, v12]");
+ }
+
private void innerTestChangelogProducing(List<String> options) throws
Exception {
TableEnvironment sEnv =
tableEnvironmentBuilder()