Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 4 additions & 3 deletions src/duckdb/src/common/arrow/appender/union_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ void ArrowUnionData::Append(ArrowAppendData &append_data, Vector &input, idx_t f
child_vectors.emplace_back(child.second, size);
}

for (idx_t input_idx = from; input_idx < to; input_idx++) {
for (idx_t i = 0; i < size; i++) {
auto input_idx = from + i;
const auto &val = input.GetValue(input_idx);

idx_t tag = 0;
Expand All @@ -40,15 +41,15 @@ void ArrowUnionData::Append(ArrowAppendData &append_data, Vector &input, idx_t f
}

for (idx_t child_idx = 0; child_idx < child_vectors.size(); child_idx++) {
child_vectors[child_idx].SetValue(input_idx, child_idx == tag ? resolved_value : Value(nullptr));
child_vectors[child_idx].SetValue(i, child_idx == tag ? resolved_value : Value(nullptr));
}
types_buffer.push_back<data_t>(NumericCast<data_t>(tag));
}

for (idx_t child_idx = 0; child_idx < child_vectors.size(); child_idx++) {
auto &child_buffer = append_data.child_data[child_idx];
auto &child = child_vectors[child_idx];
child_buffer->append_vector(*child_buffer, child, from, to, size);
child_buffer->append_vector(*child_buffer, child, 0, size, size);
}
append_data.row_count += size;
}
Expand Down
64 changes: 37 additions & 27 deletions src/duckdb/src/common/arrow/arrow_converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,37 +417,47 @@ void ArrowConverter::ToArrowSchema(ArrowSchema *out_schema, const vector<Logical
const vector<string> &names, ClientProperties &options) {
D_ASSERT(out_schema);
D_ASSERT(types.size() == names.size());
const idx_t column_count = types.size();
// Allocate as unique_ptr first to clean-up properly on error
auto root_holder = make_uniq<DuckDBArrowSchemaHolder>();
D_ASSERT(options.client_context);
auto get_schema_func = [&types, &out_schema, &names, &options]() {
const idx_t column_count = types.size();
// Allocate as unique_ptr first to clean-up properly on error
auto root_holder = make_uniq<DuckDBArrowSchemaHolder>();

// Allocate the children
root_holder->children.resize(column_count);
root_holder->children_ptrs.resize(column_count, nullptr);
for (size_t i = 0; i < column_count; ++i) {
root_holder->children_ptrs[i] = &root_holder->children[i];
}
out_schema->children = root_holder->children_ptrs.data();
out_schema->n_children = NumericCast<int64_t>(column_count);
// Allocate the children
root_holder->children.resize(column_count);
root_holder->children_ptrs.resize(column_count, nullptr);
for (size_t i = 0; i < column_count; ++i) {
root_holder->children_ptrs[i] = &root_holder->children[i];
}
out_schema->children = root_holder->children_ptrs.data();
out_schema->n_children = NumericCast<int64_t>(column_count);

// Store the schema
out_schema->format = "+s"; // struct apparently
out_schema->flags = 0;
out_schema->metadata = nullptr;
out_schema->name = "duckdb_query_result";
out_schema->dictionary = nullptr;
// Store the schema
out_schema->format = "+s"; // struct apparently
out_schema->flags = 0;
out_schema->metadata = nullptr;
out_schema->name = "duckdb_query_result";
out_schema->dictionary = nullptr;

// Configure all child schemas
for (idx_t col_idx = 0; col_idx < column_count; col_idx++) {
root_holder->owned_column_names.push_back(AddName(names[col_idx]));
auto &child = root_holder->children[col_idx];
InitializeChild(child, *root_holder, names[col_idx]);
SetArrowFormat(*root_holder, child, types[col_idx], options, *options.client_context);
}
// Configure all child schemas
for (idx_t col_idx = 0; col_idx < column_count; col_idx++) {
root_holder->owned_column_names.push_back(AddName(names[col_idx]));
auto &child = root_holder->children[col_idx];
InitializeChild(child, *root_holder, names[col_idx]);
SetArrowFormat(*root_holder, child, types[col_idx], options, *options.client_context);
}

// Release ownership to caller
out_schema->private_data = root_holder.release();
out_schema->release = ReleaseDuckDBArrowSchema;
// Release ownership to caller
out_schema->private_data = root_holder.release();
out_schema->release = ReleaseDuckDBArrowSchema;
};
auto &context = *options.client_context;
if (context.transaction.HasActiveTransaction()) {
get_schema_func();
} else {
// We need to run this in a transaction. The arrow schema callback might use the catalog to do lookups.
options.client_context->RunFunctionInTransaction(get_schema_func);
}
}

} // namespace duckdb
4 changes: 3 additions & 1 deletion src/duckdb/src/common/operator/cast_operators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1583,7 +1583,9 @@ bool TryCastBlobToUUID::Operation(string_t input, hugeint_t &result, bool strict
//===--------------------------------------------------------------------===//
template <>
bool TryCastToGeometry::Operation(string_t input, string_t &result, Vector &result_vector, CastParameters &parameters) {
return Geometry::FromString(input, result, result_vector, parameters.strict);
// Pass the query location of the cast source if available.
return Geometry::FromString(input, result, result_vector, parameters.strict,
parameters.cast_source ? parameters.cast_source->query_location : optional_idx());
}

//===--------------------------------------------------------------------===//
Expand Down
130 changes: 90 additions & 40 deletions src/duckdb/src/common/types/geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,21 @@ class TextReader {

void Match(const char *str) {
if (!TryMatch(str)) {
throw InvalidInputException("Expected '%s' but got '%c' at position %zu", str, *pos, pos - beg);
// Check if this would go EOF
if (pos + strlen(str) >= end) {
throw MakeError("Expected '%s' but got end of input", str);
}

throw MakeError("Expected '%s' but got '%c'", str, *pos);
}
}

void Match(char c) {
if (!TryMatch(c)) {
throw InvalidInputException("Expected '%c' but got '%c' at position %zu", c, *pos, pos - beg);
if (pos >= end) {
throw MakeError("Expected '%c' but got end of input", c);
}
throw MakeError("Expected '%c' but got '%c'", c, *pos);
}
}

Expand All @@ -277,7 +285,7 @@ class TextReader {
double num;
const auto res = duckdb_fast_float::from_chars(pos, end, num);
if (res.ec != std::errc()) {
throw InvalidInputException("Expected number at position %zu", pos - beg);
throw MakeError("Expected number");
}

pos = res.ptr; // update position to the end of the parsed number
Expand All @@ -294,25 +302,52 @@ class TextReader {
pos = beg;
}

private:
template <class... ARGS>
InvalidInputException MakeError(const char *raw_msg, ARGS... args) const {
const auto byte_offset = UnsafeNumericCast<idx_t>(pos - beg);
auto msg = StringUtil::Format("Failed to parse geometry: %s at offset %lu",
StringUtil::Format(raw_msg, args...), byte_offset);
if (query_location.IsValid()) {
const auto expr_offset = optional_idx(query_location.GetIndex() + byte_offset);
return InvalidInputException(Exception::InitializeExtraInfo(expr_offset), msg);
} else {
return InvalidInputException(msg);
}
}

void SetQueryLocation(optional_idx location) {
query_location = location;
}

void SkipWhitespace() {
while (pos < end && isspace(*pos)) {
pos++;
}
}

private:
const char *beg;
const char *pos;
const char *end;
optional_idx query_location;
};

void FromStringRecursive(TextReader &reader, BlobWriter &writer, uint32_t depth, bool parent_has_z, bool parent_has_m) {
if (depth == Geometry::MAX_RECURSION_DEPTH) {
throw InvalidInputException("Geometry string exceeds maximum recursion depth of %d",
Geometry::MAX_RECURSION_DEPTH);
throw reader.MakeError("Geometry string exceeds maximum recursion depth of %d", Geometry::MAX_RECURSION_DEPTH);
}

// Skip leading whitespace
reader.SkipWhitespace();

// EWKT dialect (ignore SRID if present)
if (reader.TryMatch("SRID")) {
reader.Match('=');
reader.MatchNumber();
reader.Match(';');
}

GeometryType type;
GeometryType type = GeometryType::INVALID;

if (reader.TryMatch("point")) {
type = GeometryType::POINT;
Expand All @@ -329,7 +364,7 @@ void FromStringRecursive(TextReader &reader, BlobWriter &writer, uint32_t depth,
} else if (reader.TryMatch("geometrycollection")) {
type = GeometryType::GEOMETRYCOLLECTION;
} else {
throw InvalidInputException("Unknown geometry type at position %zu", reader.GetPosition());
throw reader.MakeError("Unknown geometry type");
}

const auto has_z = reader.TryMatch("z");
Expand All @@ -338,8 +373,7 @@ void FromStringRecursive(TextReader &reader, BlobWriter &writer, uint32_t depth,
const auto is_empty = reader.TryMatch("empty");

if ((depth != 0) && ((parent_has_z != has_z) || (parent_has_m != has_m))) {
throw InvalidInputException("Geometry has inconsistent Z/M dimensions, starting at position %zu",
reader.GetPosition());
throw reader.MakeError("Geometry has inconsistent Z/M dimensions");
}

// How many dimensions does this geometry have?
Expand Down Expand Up @@ -438,6 +472,7 @@ void FromStringRecursive(TextReader &reader, BlobWriter &writer, uint32_t depth,
}
part_count.value++;
} while (reader.TryMatch(','));
reader.Match(')');
writer.Write(part_count);
} break;
case GeometryType::MULTILINESTRING: {
Expand All @@ -453,18 +488,23 @@ void FromStringRecursive(TextReader &reader, BlobWriter &writer, uint32_t depth,
writer.Write<uint8_t>(1);
writer.Write<uint32_t>(part_meta);

auto vert_count = writer.Reserve<uint32_t>();
reader.Match('(');
do {
for (uint32_t d_idx = 0; d_idx < dims; d_idx++) {
auto value = reader.MatchNumber();
writer.Write<double>(value);
}
vert_count.value++;
} while (reader.TryMatch(','));
reader.Match(')');
writer.Write(vert_count);
part_count.value++;
if (reader.TryMatch("EMPTY")) {
writer.Write<uint32_t>(0); // No vertices in empty linestring
part_count.value++;
} else {
auto vert_count = writer.Reserve<uint32_t>();
reader.Match('(');
do {
for (uint32_t d_idx = 0; d_idx < dims; d_idx++) {
auto value = reader.MatchNumber();
writer.Write<double>(value);
}
vert_count.value++;
} while (reader.TryMatch(','));
reader.Match(')');
writer.Write(vert_count);
part_count.value++;
}
} while (reader.TryMatch(','));
reader.Match(')');
writer.Write(part_count);
Expand All @@ -482,25 +522,30 @@ void FromStringRecursive(TextReader &reader, BlobWriter &writer, uint32_t depth,
writer.Write<uint8_t>(1);
writer.Write<uint32_t>(part_meta);

auto ring_count = writer.Reserve<uint32_t>();
reader.Match('(');
do {
auto vert_count = writer.Reserve<uint32_t>();
if (reader.TryMatch("EMPTY")) {
writer.Write<uint32_t>(0); // No rings in empty polygon
part_count.value++;
} else {
auto ring_count = writer.Reserve<uint32_t>();
reader.Match('(');
do {
for (uint32_t d_idx = 0; d_idx < dims; d_idx++) {
auto value = reader.MatchNumber();
writer.Write<double>(value);
}
vert_count.value++;
auto vert_count = writer.Reserve<uint32_t>();
reader.Match('(');
do {
for (uint32_t d_idx = 0; d_idx < dims; d_idx++) {
auto value = reader.MatchNumber();
writer.Write<double>(value);
}
vert_count.value++;
} while (reader.TryMatch(','));
reader.Match(')');
writer.Write(vert_count);
ring_count.value++;
} while (reader.TryMatch(','));
reader.Match(')');
writer.Write(vert_count);
ring_count.value++;
} while (reader.TryMatch(','));
reader.Match(')');
writer.Write(ring_count);
part_count.value++;
writer.Write(ring_count);
part_count.value++;
}
} while (reader.TryMatch(','));
reader.Match(')');
writer.Write(part_count);
Expand All @@ -521,8 +566,7 @@ void FromStringRecursive(TextReader &reader, BlobWriter &writer, uint32_t depth,
writer.Write(part_count);
} break;
default:
throw InvalidInputException("Unknown geometry type %d at position %zu", static_cast<int>(type),
reader.GetPosition());
throw reader.MakeError("Unknown geometry type %d", static_cast<int>(type));
}
}

Expand Down Expand Up @@ -1047,8 +1091,10 @@ void Geometry::ToBinary(Vector &source, Vector &result, idx_t count) {
result.Reinterpret(source);
}

bool Geometry::FromString(const string_t &wkt_text, string_t &result, Vector &result_vector, bool strict) {
bool Geometry::FromString(const string_t &wkt_text, string_t &result, Vector &result_vector, bool strict,
optional_idx query_location) {
TextReader reader(wkt_text.GetData(), static_cast<uint32_t>(wkt_text.GetSize()));
reader.SetQueryLocation(query_location);
BlobWriter writer;

FromStringRecursive(reader, writer, 0, false, false);
Expand All @@ -1058,6 +1104,10 @@ bool Geometry::FromString(const string_t &wkt_text, string_t &result, Vector &re
return true;
}

bool Geometry::FromString(const string_t &wkt_text, string_t &result, Vector &result_vector, bool strict) {
return FromString(wkt_text, result, result_vector, strict, optional_idx::Invalid());
}

string_t Geometry::ToString(Vector &result, const string_t &geom) {
BlobReader reader(geom.GetData(), static_cast<uint32_t>(geom.GetSize()));
TextWriter writer;
Expand Down
7 changes: 4 additions & 3 deletions src/duckdb/src/common/types/interval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@
#include "duckdb/common/operator/subtract.hpp"
#include "duckdb/common/string_util.hpp"

#include "duckdb/common/serializer/serializer.hpp"
#include "duckdb/common/serializer/deserializer.hpp"

namespace duckdb {

bool Interval::FromString(const string &str, interval_t &result) {
Expand Down Expand Up @@ -275,6 +272,10 @@ interval_parse_time : {
}
}
// invert all the values
if (result.months == NumericLimits<int32_t>::Minimum() || result.days == NumericLimits<int32_t>::Minimum()) {
throw OutOfRangeException("AGO interval value is out of range");
}

result.months = -result.months;
result.days = -result.days;
result.micros = -result.micros;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,7 @@ void ExpressionExecutor::Execute(const BoundOperatorExpression &expr, Expression
result.Reference(try_result);
return;
}
if (sel) {
VectorOperations::Copy(try_result, result, *sel, count, 0, 0, count);
} else {
VectorOperations::Copy(try_result, result, count, 0, 0);
}
VectorOperations::Copy(try_result, result, count, 0, 0);
return;
} catch (std::exception &ex) {
ErrorData error(ex);
Expand Down
2 changes: 1 addition & 1 deletion src/duckdb/src/execution/index/art/art_builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ ARTConflictType ARTBuilder::Build() {
}

reference<Node> ref(entry.node);
auto count = UnsafeNumericCast<uint8_t>(start.len - prefix_depth);
auto count = UnsafeNumericCast<idx_t>(start.len - prefix_depth);
Prefix::New(art, ref, start, prefix_depth, count);

// Inline the row ID.
Expand Down
Loading
Loading