OIiveirra commented on code in PR #69527:
URL: https://github.com/apache/doris/pull/69527#discussion_r4366828608


##########
fe/fe-core/src/main/java/org/apache/doris/tablefunction/LocalTableValuedFunction.java:
##########
@@ -135,6 +143,38 @@ private void getFileListFromBackend() throws 
AnalysisException {
         }
     }
 
+    /** Apply LOCAL admission to sinks that select the built-in local JNI 
writer as well. */
+    public static void checkSinkEnabled(String tvfName, Map<String, String> 
properties) {
+        String writerClass = properties.getOrDefault("writer_class", "");
+        // JNI consumes a C string, and ScannerLoader accepts slash-separated 
class names.
+        int nul = writerClass.indexOf('\0');
+        if (nul >= 0) {
+            writerClass = writerClass.substring(0, nul);
+        }
+        if ("local".equalsIgnoreCase(tvfName)
+                || 
"org.apache.doris.writer.LocalFileJniWriter".equals(writerClass.replace('/', 
'.'))) {

Review Comment:
   The delegated ViewFS variant is fixed in 
46237ec1740e6c62c8fedacd84cad85876972c2a. Native admission uses the actual 
generated file's parent; FE cleanup checks its actual parent directory. The raw 
and normalized checks follow the selected mount table and path-component link, 
including trailing-source slashes, authority/default table selection, fallback 
and multiple targets. Nested targets are checked before filesystem creation. 
Unused local mounts do not block an unambiguous remote route.
   
   Runtime-overloaded, regex, cyclic, inherited or ambiguous nested delegation 
requires the existing LOCAL startup opt-in instead of assuming the inline 
configuration proves remote storage. Enabled requests retain their existing 
Hadoop behavior.
   
   All 51 selected FE tests passed with fresh XML and unchanged sources, 
including INSERT/EXPLAIN, direct binding, resource-derived mounts, off/on and 
remote controls, and a global-LOAD command entry with cleanup enabled. 
Factory/executor mocks verify no side effect before rejection. No real 
directory deletion was executed; targeted Checkstyle passed.



##########
be/src/format_v2/table/lance_reader.cpp:
##########
@@ -35,11 +39,79 @@
 #include "format_v2/lance/lance_reader_helper.h"
 #include "format_v2/lance/lance_runtime_filter_helper.h"
 #include "format_v2/lance/lance_session_manager.h"
+#include "io/fs/local_file_system.h"
 #include "runtime/file_scan_profile.h"
 #include "runtime/runtime_state.h"
 
 namespace doris::format::lance {
 
+namespace {
+std::string expand_home_path(const std::string& path) {
+    if (path != "~" && !path.starts_with("~/")) {
+        return path;
+    }
+    // Match the SDK's std::env::home_dir: HOME first, then the current user's 
passwd entry.
+    std::string home;
+    if (const char* value = std::getenv("HOME"); value != nullptr && value[0] 
!= '\0') {
+        home = value;
+    } else {
+        std::vector<char> buffer(1024);
+        struct passwd entry {};
+        struct passwd* result = nullptr;
+        int error;
+        while ((error = getpwuid_r(getuid(), &entry, buffer.data(), 
buffer.size(), &result)) ==
+               ERANGE) {
+            buffer.resize(buffer.size() * 2);
+        }
+        if (error == 0 && result != nullptr && entry.pw_dir != nullptr) {
+            home = entry.pw_dir;
+        }
+    }
+    if (home.empty()) {
+        return path;
+    }
+    return path == "~" ? home : (io::Path(home) / path.substr(2)).string();
+}
+
+Status resolve_dataset_uri(const TFileRangeDesc& range, const 
TFileScanRangeParams& scan_params,
+                           std::string* uri) {
+    const auto& requested_uri = 
range.table_format_params.lance_params.dataset_uri;
+    // Modern plans tag each range; older plans put the type in the scan 
parameters.
+    // Untagged catalog scans retain their original storage-provider selection.
+    const bool is_local = range.__isset.file_type
+                                  ? range.file_type == TFileType::FILE_LOCAL
+                                  : scan_params.__isset.file_type &&
+                                            scan_params.file_type == 
TFileType::FILE_LOCAL;
+    // LOCAL TVF uses version zero for both schema discovery and whole-dataset 
scans.
+    // Catalog scans pin a positive snapshot version, including file:// 
catalogs whose
+    // operator-configured warehouse is independent of the LOCAL TVF secure 
directory.
+    if (is_local && range.table_format_params.lance_params.version == 0) {
+        // LOCAL Lance bypasses glob because it opens a dataset directory. 
Apply the same
+        // canonical secure-root check before either schema discovery or a 
cached dataset open.
+        std::string local_input = requested_uri;
+        const auto colon = requested_uri.find(':');
+        const auto slash = requested_uri.find('/');
+        const bool bare_path =
+                colon == std::string::npos || (slash != std::string::npos && 
slash < colon);
+        if (bare_path && !requested_uri.empty() && requested_uri.find('\0') == 
std::string::npos &&
+            !config::user_files_secure_path.empty()) {
+            // Lance's PathAbs fallback resolves bare dot segments before 
following symlinks.
+            // Anchor relative TVF paths to the canonical secure root, not the 
process cwd.
+            std::string secure_root;
+            RETURN_IF_ERROR(io::global_local_filesystem()->canonicalize(
+                    config::user_files_secure_path, &secure_root));
+            local_input = (io::Path(secure_root) / 
expand_home_path(requested_uri))
+                                  .lexically_normal()
+                                  .string();
+        }
+        return io::global_local_filesystem()->canonicalize_local_file(

Review Comment:
   Fixed in 46237ec1740e6c62c8fedacd84cad85876972c2a and mirrored to the 
existing 4.1 PR. LOCAL/version-zero resolution now checks reachable dataset 
descendants before either schema discovery or dataset/session/cache opens. 
Every symlink target is canonicalized and confined to the secure root before 
traversal; failures return a generic error. Iterative canonical-directory 
identity deduplicates aliases/cycles without an arbitrary dataset-size quota.
   
   All 17 selected BE filesystem/Lance tests passed. Real fixtures reject 
external metadata/data directories, the latest manifest, a fragment file, 
deeper and dangling links. In-root directory/file links and an in-root 
directory cycle preserve schema and actual rows 1–4. This preflight scales with 
the reachable dataset tree; remote and fixed-version catalog routing are 
unchanged. No SDK or manifest-reference format change is included.



-- 
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