HappenLee commented on code in PR #55458:
URL: https://github.com/apache/doris/pull/55458#discussion_r2335537250


##########
be/src/olap/rowset/segment_v2/ann_index/ann_topn_runtime.cpp:
##########
@@ -71,27 +71,97 @@ Status AnnTopNRuntime::prepare(RuntimeState* state, const 
RowDescriptor& row_des
             
std::dynamic_pointer_cast<vectorized::VectorizedFnCall>(vir_col_expr);
 
     if (distance_fn_call == nullptr) {
-        return Status::InternalError("Ann topn expr expect FuncationCall, 
got\n{}",
-                                     vir_col_expr->debug_string());
+        return Status::InvalidArgument("Ann topn expr expect FuncationCall, 
got\n{}",
+                                       vir_col_expr->debug_string());
     }
 
     std::shared_ptr<vectorized::VSlotRef> slot_ref =
             
std::dynamic_pointer_cast<vectorized::VSlotRef>(distance_fn_call->children()[0]);
     if (slot_ref == nullptr) {
-        return Status::InternalError("Ann topn expr expect SlotRef, got\n{}",
-                                     
distance_fn_call->children()[0]->debug_string());
+        return Status::InvalidArgument("Ann topn expr expect SlotRef, got\n{}",
+                                       
distance_fn_call->children()[0]->debug_string());
     }
 
     // slot_ref->column_id() is acutually the columnd idx in block.
     _src_column_idx = slot_ref->column_id();
 
-    std::shared_ptr<vectorized::VArrayLiteral> array_literal =
-            
std::dynamic_pointer_cast<vectorized::VArrayLiteral>(distance_fn_call->children()[1]);
-    if (array_literal == nullptr) {
-        return Status::InternalError("Ann topn expr expect ArrayLiteral, 
got\n{}",
-                                     
distance_fn_call->children()[1]->debug_string());
+    if (distance_fn_call->children()[1]->is_constant() == false) {
+        return Status::InvalidArgument("Ann topn expr expect constant 
ArrayLiteral, got\n{}",
+                                       
distance_fn_call->children()[1]->debug_string());
     }
-    _query_array = array_literal->get_column_ptr();
+
+    // Accept either ArrayLiteral([..]) or CAST('..' AS 
Nullable(Array(Nullable(Float32))))
+    // First, check the expr node type for clarity.
+    auto arg_expr = distance_fn_call->children()[1];
+    bool is_array_literal =
+            std::dynamic_pointer_cast<vectorized::VArrayLiteral>(arg_expr) != 
nullptr;
+    bool is_cast_expr = 
std::dynamic_pointer_cast<vectorized::VCastExpr>(arg_expr) != nullptr;
+    if (!is_array_literal && !is_cast_expr) {
+        return Status::InvalidArgument(
+                "Ann topn expr constant must be ArrayLiteral or CAST to array, 
got\n{}",
+                arg_expr->debug_string());
+    }
+
+    // We'll validate shape by inspecting the materialized constant column 
below.
+
+    std::shared_ptr<ColumnPtrWrapper> column_wrapper;
+    RETURN_IF_ERROR(distance_fn_call->children()[1]->get_const_col(nullptr, 
&column_wrapper));
+
+    // Execute the constant array literal and extract its float elements into 
_query_array
+    vectorized::IColumn::Ptr col_ptr =
+            column_wrapper->column_ptr->convert_to_full_column_if_const();
+
+    // The expected runtime column layout for the literal is:
+    // Nullable(ColumnArray(Nullable(ColumnFloat32))) with exactly 1 row (one 
array literal)
+    const vectorized::IColumn* top_col = col_ptr.get();
+    const vectorized::IColumn* array_holder_col = top_col;
+    // Handle outer Nullable and remember result nullability preference
+    if (auto* nullable_col =
+                
vectorized::check_and_get_column<vectorized::ColumnNullable>(*top_col)) {
+        if (nullable_col->has_null()) {
+            return Status::InvalidArgument("Ann topn query vector cannot be 
NULL");
+        }
+        array_holder_col = &nullable_col->get_nested_column();
+    }
+
+    // Must be an array column with single row
+    const auto* array_col =
+            
vectorized::check_and_get_column<vectorized::ColumnArray>(*array_holder_col);
+    if (array_col == nullptr || array_col->size() != 1) {
+        return Status::InvalidArgument(
+                "Ann topn expr constant should be an Array literal, got 
column: {}",
+                array_holder_col->get_name());
+    }
+
+    // Fetch nested data column: Nullable(ColumnFloat32) or ColumnFloat32
+    const vectorized::IColumn& nested_data_any = array_col->get_data();
+    const vectorized::IColumn* values_holder_col = &nested_data_any;
+    size_t value_count = array_col->get_offsets()[0];
+
+    if (value_count == 0) {
+        return Status::InvalidArgument("Ann topn query vector cannot be 
empty");
+    }
+
+    if (auto* value_nullable_col =
+                
vectorized::check_and_get_column<vectorized::ColumnNullable>(nested_data_any)) {
+        if (value_nullable_col->has_null(0, value_count)) {
+            return Status::InvalidArgument(
+                    "Ann topn query vector elements cannot contain NULL 
values");
+        }
+        values_holder_col = &value_nullable_col->get_nested_column();
+    }
+
+    // Now must be ColumnFloat32
+    const auto* value_col = assert_cast<const 
vectorized::ColumnFloat32*>(values_holder_col);
+
+    _query_array_size = value_count;

Review Comment:
   why here we need copy not direct use the mem of values_holder_col ?



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