Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
d2f72e5
[feat](adbc) link adbc_driver_manager into doris_be
morningman Jul 31, 2026
e0bf1b6
[feat](adbc) normalize third-party arrow variants for Doris serdes
morningman Jul 31, 2026
dec6403
[feat](adbc) add process-wide ADBC driver registry
morningman Jul 31, 2026
a9ab9c6
[feat](adbc) add adbc_params to TTableFormatFileDesc
morningman Jul 31, 2026
2b76063
[feat](adbc) add BE ADBC reader on the FileScannerV2 path
morningman Jul 31, 2026
d39b5e1
[feat](adbc) route adbc scan ranges to FileScannerV2
morningman Jul 31, 2026
13ca17a
[feat](adbc) add fe-connector-adbc module skeleton and provider
morningman Jul 31, 2026
3001cf3
[feat](adbc) wire adbc into the FE build, deployment and config
morningman Jul 31, 2026
1b3d927
[feat](adbc) add adbc catalog properties and driver path resolution
morningman Jul 31, 2026
7e0d7fd
[feat](adbc) add the adbc client on the JNI driver bridge
morningman Jul 31, 2026
64559d6
[feat](adbc) map ADBC getObjects and Arrow schemas onto Doris metadata
morningman Jul 31, 2026
3f57600
[feat](adbc) implement adbc connector metadata operations
morningman Jul 31, 2026
cb31c31
[feat](adbc) map the arrow file format to BE's arrow reader
morningman Jul 31, 2026
d24cbce
[feat](adbc) generate pushed-down SQL through a registered dialect
morningman Jul 31, 2026
6b22aad
[feat](adbc) plan a scan into one range BE can read
morningman Jul 31, 2026
3b5649d
[feat](adbc) count rows when a scan projects no columns
morningman Jul 31, 2026
701b7e8
[test](adbc) add the adbc scan regression suite
morningman Jul 31, 2026
ba6e11c
[test](adbc) add an end-to-end scan suite driven by the sqlite driver
morningman Jul 31, 2026
9f50095
[fix](adbc) materialize an all-null column whatever type the source c…
morningman Jul 31, 2026
42870b8
[test](adbc) install the prebuilt flight sql driver from thirdparty
morningman Jul 31, 2026
19a0b3a
[fix](adbc) survive a driver that leaves its stream release callback set
morningman Jul 31, 2026
07c39a1
[fix](adbc) speak Doris's identifier quoting to a Doris source
morningman Jul 31, 2026
f4b58d3
[feat](adbc) split a scan into the driver's partitions, one per backend
morningman Jul 31, 2026
d71479b
[fix](connector) tell a connector when a plan will only be explained
morningman Jul 31, 2026
a39170b
[test](adbc) check both planning paths return the same rows
morningman Jul 31, 2026
dfce7e9
[feat](adbc) read one partition instead of running a statement
morningman Jul 31, 2026
be592f2
[fix](adbc) keep the driver registry alive as long as its promise says
morningman Jul 31, 2026
cb19a08
[fix](build) build the adbc connector plugin, do not just deploy it
morningman Jul 31, 2026
53d4f26
[fix](adbc) say what the driver answered when partitioning is refused
morningman Jul 31, 2026
eb5965d
[feat](adbc) let a catalog forbid the partitioned-read downgrade
morningman Jul 31, 2026
46991f4
[fix](adbc) drop what a source calls a view from the table listing
morningman Jul 31, 2026
0845cc1
[test](adbc) pin how many partitions a scan is split into
morningman Jul 31, 2026
8eb218f
[feat](adbc) remember the source's metadata between statements
morningman Jul 31, 2026
1b94a4b
[fix](adbc) keep the listings the engine checks names against live
morningman Jul 31, 2026
de81f3e
[test](adbc) check what a catalog remembers and what forgets it
morningman Jul 31, 2026
6d9744a
[feat](adbc) verify the driver file is the build the catalog names
morningman Jul 31, 2026
87ab3f3
[fix](adbc) say which dialect wrote the statement a source rejected
morningman Jul 31, 2026
e7f33d2
[fix](connector) show the projection the scan will really ask for
morningman Aug 1, 2026
81c23d6
[fix](adbc) keep a zoned timestamp comparison out of the remote state…
morningman Aug 1, 2026
8b449fe
[test](adbc) add the end-to-end suites for a Doris Flight SQL source
morningman Aug 1, 2026
31144b0
format
morningman Aug 1, 2026
4315a84
[feat](adbc) read the driver settings from the plugin conf
morningman Aug 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .licenserc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ header:
# the file an administrator edits in plugins/connector/<dir>/. Matched by name
# rather than by a **/*.conf.template glob, so a new one is a deliberate entry
# here rather than something a wildcard silently absorbs.
- "fe/fe-connector/fe-connector-adbc/src/main/resources/adbc.conf.template"
- "fe/fe-connector/fe-connector-hive/src/main/resources/hms.conf.template"
- "fe/fe-connector/fe-connector-iceberg/src/main/resources/iceberg.conf.template"
- "fe/fe-connector/fe-connector-jdbc/src/main/resources/jdbc.conf.template"
Expand Down
1 change: 1 addition & 0 deletions be/cmake/thirdparty.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ add_thirdparty(arrow_flight LIB64)
add_thirdparty(arrow_flight_sql LIB64)
add_thirdparty(arrow_dataset LIB64)
add_thirdparty(arrow_acero LIB64)
add_thirdparty(adbc_driver_manager LIB64)
add_thirdparty(parquet LIB64)
# liblance_c.a contains compiler_builtins cbrt symbols. Place libm before it
# so the final linker resolves C math symbols from the system library first.
Expand Down
11 changes: 11 additions & 0 deletions be/src/exec/operator/file_scan_operator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ bool FileScanLocalState::TEST_should_use_file_scanner_v2(const TQueryOptions& qu
bool FileScanLocalState::_should_use_file_scanner_v2(const TQueryOptions& query_options,
bool is_load,
const TFileScanRangeParams& scan_params) {
// ADBC only has a FileScannerV2 reader, and enable_file_scanner_v2 is a session variable marked
// fuzzy=true, so the regression harness flips it to false at random. Without letting adbc
// through unconditionally, those queries land in v1, which has no "adbc" branch, and come back
// with an undiagnosable NotSupported -- showing up in CI as a random failure. This is the same
// mechanism as is_transactional_hive below, pointed the other way. Loads are left alone: there
// is no ADBC load path, so widening the rule to cover them would only route them somewhere they
// still cannot run.
if (!is_load && scan_params.__isset.table_format_params &&
scan_params.table_format_params.table_format_type == "adbc") {
return true;
}
const bool is_transactional_hive =
scan_params.__isset.table_format_params &&
scan_params.table_format_params.table_format_type == "transactional_hive";
Expand Down
6 changes: 5 additions & 1 deletion be/src/exec/scan/file_scanner_v2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include "format_v2/jni/jdbc_reader.h"
#include "format_v2/jni/max_compute_jni_reader.h"
#include "format_v2/jni/trino_connector_jni_reader.h"
#include "format_v2/table/adbc_reader.h"
#include "format_v2/table/hive_reader.h"
#include "format_v2/table/hudi_reader.h"
#include "format_v2/table/iceberg_position_delete_sys_table_reader.h"
Expand Down Expand Up @@ -103,7 +104,8 @@ bool is_supported_table_format(const TFileRangeDesc& range) {
}

bool is_supported_arrow_table_format(const TFileRangeDesc& range) {
return table_format_name(range) == "remote_doris";
const auto table_format = table_format_name(range);
return table_format == "remote_doris" || table_format == "adbc";
}

bool is_supported_jni_table_format(const TFileRangeDesc& range) {
Expand Down Expand Up @@ -619,6 +621,8 @@ Status FileScannerV2::_create_table_reader_for_format(
*reader = std::make_unique<format::trino_connector::TrinoConnectorJniReader>();
} else if (table_format == "remote_doris") {
*reader = std::make_unique<format::remote_doris::RemoteDorisReader>();
} else if (table_format == "adbc") {
*reader = std::make_unique<format::adbc::AdbcReader>();
} else {
return Status::NotSupported("FileScannerV2 does not support table format {}", table_format);
}
Expand Down
113 changes: 113 additions & 0 deletions be/src/format/arrow/arrow_array_normalizer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

#include "format/arrow/arrow_array_normalizer.h"

#include <arrow/array/array_base.h>
#include <arrow/compute/cast.h>
#include <arrow/type.h>

#include <memory>

#include "common/check.h"
#include "common/status.h"

namespace doris {

namespace {

// The accepted counterpart of an encoding-only variant. Null when there is none.
std::shared_ptr<arrow::DataType> target_type_for(const arrow::DataType& type) {
switch (type.id()) {
case arrow::Type::LARGE_STRING:
case arrow::Type::STRING_VIEW:
return arrow::utf8();
case arrow::Type::LARGE_BINARY:
case arrow::Type::BINARY_VIEW:
return arrow::binary();
case arrow::Type::DICTIONARY:
return static_cast<const arrow::DictionaryType&>(type).value_type();
case arrow::Type::RUN_END_ENCODED:
return static_cast<const arrow::RunEndEncodedType&>(type).value_type();
default:
return nullptr;
}
}

} // namespace

bool is_serde_acceptable_arrow_type(const arrow::DataType& type) {
switch (type.id()) {
// Encoding-only variants: convertible to an accepted type.
case arrow::Type::LARGE_STRING:
case arrow::Type::LARGE_BINARY:
case arrow::Type::STRING_VIEW:
case arrow::Type::BINARY_VIEW:
case arrow::Type::DICTIONARY:
case arrow::Type::RUN_END_ENCODED:
return false;
// No Doris column can hold these, so they must not reach a serde either.
case arrow::Type::INTERVAL_MONTHS:
case arrow::Type::INTERVAL_DAY_TIME:
case arrow::Type::INTERVAL_MONTH_DAY_NANO:
case arrow::Type::DURATION:
case arrow::Type::SPARSE_UNION:
case arrow::Type::DENSE_UNION:
return false;
default:
return true;
}
}

Status normalize_arrow_array(const std::shared_ptr<arrow::Array>& arr,
std::shared_ptr<arrow::Array>* out) {
DORIS_CHECK(arr != nullptr);
DORIS_CHECK(out != nullptr);

std::shared_ptr<arrow::Array> current = arr;
// dictionary<int32, large_utf8> decodes to large_utf8, which still needs converting. The bound
// stops a driver from turning a malformed type into an endless loop.
constexpr int kMaxPasses = 4;
for (int pass = 0; pass < kMaxPasses; ++pass) {
const auto& type = *current->type();
if (is_serde_acceptable_arrow_type(type)) {
*out = std::move(current);
return Status::OK();
}

auto target = target_type_for(type);
if (target == nullptr) {
return Status::NotSupported(
"ADBC: arrow type '{}' cannot be materialized into a Doris column",
type.ToString());
}

auto casted = arrow::compute::Cast(*current, target);
if (!casted.ok()) {
return Status::InternalError("ADBC: failed to normalize arrow type '{}' to '{}': {}",
type.ToString(), target->ToString(),
casted.status().ToString());
}
current = casted.MoveValueUnsafe();
}
return Status::InternalError(
"ADBC: arrow type '{}' is still not materializable after {} "
"normalization passes",
arr->type()->ToString(), kMaxPasses);
}

} // namespace doris
44 changes: 44 additions & 0 deletions be/src/format/arrow/arrow_array_normalizer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

#pragma once

#include <arrow/type_fwd.h>

#include <memory>

#include "common/status.h"

namespace doris {

/// DataTypeSerDe::read_column_from_arrow was written for the Arrow that Doris itself emits, so it
/// accepts only a subset of the Arrow type variants. Third-party ADBC drivers emit others: DuckDB
/// emits string_view, Go-based drivers may emit large_* and dictionary. This normalizes them into
/// a shape the serdes accept.
///
/// Only top-level types are normalized. A nested type whose child is an unaccepted variant (say
/// list<large_utf8>) passes through and fails inside the serde, loudly rather than silently.

/// Whether the serdes take this Arrow type as-is.
bool is_serde_acceptable_arrow_type(const arrow::DataType& type);

/// Normalizes `arr` into a serde-acceptable shape. Returns it unchanged (no copy) when it already
/// is one, and fails with the offending type named when no accepted shape exists.
Status normalize_arrow_array(const std::shared_ptr<arrow::Array>& arr,
std::shared_ptr<arrow::Array>* out);

} // namespace doris
Loading
Loading