github-actions[bot] commented on code in PR #64878:
URL: https://github.com/apache/doris/pull/64878#discussion_r3610163485


##########
fe/fe-core/src/main/java/org/apache/doris/load/routineload/kafka/KafkaRoutineLoadJob.java:
##########
@@ -766,91 +786,95 @@ public Map<String, String> getCustomProperties() {
         return getMaskedCustomProperties("property.");
     }
 
+    @Override
+    public boolean appliesRoutineLoadDescAtomically() {
+        return true;
+    }
+
     @Override
     public void modifyProperties(AlterRoutineLoadCommand command) throws 
UserException {
-        Map<String, String> jobProperties = command.getAnalyzedJobProperties();
         KafkaDataSourceProperties dataSourceProperties = 
(KafkaDataSourceProperties) command.getDataSourceProperties();
-        if (null != dataSourceProperties) {
-            // if the partition offset is set by timestamp, convert it to real 
offset
-            convertOffset(dataSourceProperties);
-        }
 
         writeLock();
         try {
             if (getState() != JobState.PAUSED) {
                 throw new DdlException("Only supports modification of PAUSED 
jobs");
             }
+            if (command.getRoutineLoadDesc() != null && 
command.getLoadPropertyTableId() != tableId) {
+                throw new DdlException("Routine load target table changed 
while validating load properties; "
+                        + "please retry ALTER ROUTINE LOAD");
+            }
+            if (!command.hasTargetTable()) {

Review Comment:
   [P1] Revalidate the saved target against the current job state under this 
lock. A target-only ALTER can validate non-MoW B while the job is UPSERT; while 
it waits, another ALTER can change paused MoW job A to fixed partial update. 
This path then skips mutation-time validation solely because it carries a 
target and installs B, so resume later fails the partial-update/MoW planner 
check. The existing target-ID guard applies only to a command carrying a load 
clause and does not close this inverse race. Record/check a job-definition 
generation, or recompute the effective mode and revalidate B before assigning 
tableId; cover the two-ALTER interleaving.



##########
fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/AlterRoutineLoadCommand.java:
##########
@@ -315,33 +356,64 @@ private void checkJobProperties() throws UserException {
         }
     }
 
-    private void checkDataSourceProperties() throws UserException {
+    private void checkDataSourceProperties(RoutineLoadJob job) throws 
UserException {
         if (MapUtils.isEmpty(dataSourceMapProperties)) {
             return;
         }
-        RoutineLoadJob job = Env.getCurrentEnv().getRoutineLoadManager()
-                .getJob(getDbName(), getJobName());
+        String effectiveDataSourceType = dataSourceType == null ? 
job.getDataSourceType().name() : dataSourceType;
+        if 
(!effectiveDataSourceType.equalsIgnoreCase(job.getDataSourceType().name())) {
+            throw new AnalysisException("The specified job type is not: " + 
effectiveDataSourceType);
+        }
         this.dataSourceProperties = RoutineLoadDataSourcePropertyFactory
-            .createDataSource(job.getDataSourceType().name(), 
dataSourceMapProperties, job.isMultiTable());
+            .createDataSource(effectiveDataSourceType, 
dataSourceMapProperties, job.isMultiTable());
         dataSourceProperties.setAlter(true);
-        dataSourceProperties.setTimezone(job.getTimezone());
+        dataSourceProperties.setTimezone(analyzedJobProperties.getOrDefault(
+                CreateRoutineLoadInfo.TIMEZONE, job.getTimezone()));
         dataSourceProperties.analyze();
     }
 
-    private void checkPartialUpdate() throws UserException {
-        if (!isPartialUpdate) {
+    private void validateAlterJobProperties(RoutineLoadJob job,
+            TUniqueKeyUpdateMode effectiveUniqueKeyUpdateMode) throws 
UserException {
+        if (effectiveUniqueKeyUpdateMode == TUniqueKeyUpdateMode.UPSERT) {
             return;
         }
-        RoutineLoadJob job = Env.getCurrentEnv().getRoutineLoadManager()
-                .getJob(getDbName(), getDbName());
         if (job.isMultiTable()) {
-            throw new AnalysisException("load by PARTIAL_COLUMNS is not 
supported in multi-table load.");
+            throw new AnalysisException("Partial update is not supported in 
multi-table load.");
         }
         Database db = 
Env.getCurrentInternalCatalog().getDbOrAnalysisException(job.getDbFullName());
         Table table = db.getTableOrAnalysisException(job.getTableName());
-        if (isPartialUpdate && !((OlapTable) 
table).getEnableUniqueKeyMergeOnWrite()) {
-            throw new AnalysisException("load by PARTIAL_COLUMNS is only 
supported in unique table MoW");
+        job.validateAlterJobProperties((OlapTable) table, 
analyzedJobProperties, effectiveUniqueKeyUpdateMode);
+    }
+
+    private void validateTargetTable(ConnectContext ctx, RoutineLoadJob job,
+            TUniqueKeyUpdateMode effectiveUniqueKeyUpdateMode) throws 
UserException {
+        if (job.getDataSourceType() != LoadDataSourceType.KAFKA) {
+            throw new AnalysisException("ALTER ROUTINE LOAD target table 
change only supports Kafka jobs");
+        }
+        if (job.isMultiTable()) {
+            throw new AnalysisException("ALTER ROUTINE LOAD target table 
change only supports single-table job");
+        }
+        Database db = 
Env.getCurrentInternalCatalog().getDbOrAnalysisException(job.getDbFullName());
+        Table table = db.getTableOrAnalysisException(targetTableName);

Review Comment:
   [P1] Authorize before resolving the target metadata. doRun() completes 
validate() before RoutineLoadManager checks access to the current job, and this 
lookup plus the non-OLAP/temporary checks also precede the target LOAD check. A 
limited-RBAC user can therefore distinguish a missing target from an 
unauthorized ordinary table, and can classify non-OLAP or temporary targets 
from their specific errors, even without access to the current job. This 
violates the threat model's object non-discovery property. Authorize the 
current job first, then check LOAD for the requested target name before 
resolving it; unauthorized existing and nonexistent targets should follow the 
same access-denied path without metadata lookup.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to