Packages

An Elixir DuckDB library

Current section

Files

Jump to
exduckdb c_src duckdb src common row_operations row_external.cpp
Raw

c_src/duckdb/src/common/row_operations/row_external.cpp

//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/types/row_operations/row_external.cpp
//
//
//===----------------------------------------------------------------------===//
#include "duckdb/common/row_operations/row_operations.hpp"
#include "duckdb/common/types/row_layout.hpp"
namespace duckdb {
void RowOperations::SwizzleColumns(const RowLayout &layout, const data_ptr_t base_row_ptr, const idx_t count) {
const idx_t row_width = layout.GetRowWidth();
const idx_t heap_pointer_offset = layout.GetHeapPointerOffset();
// Swizzle the blob columns one by one
for (idx_t col_idx = 0; col_idx < layout.ColumnCount(); col_idx++) {
auto physical_type = layout.GetTypes()[col_idx].InternalType();
if (TypeIsConstantSize(physical_type)) {
continue;
}
data_ptr_t row_ptr = base_row_ptr;
const idx_t &col_offset = layout.GetOffsets()[col_idx];
if (physical_type == PhysicalType::VARCHAR) {
// Replace the pointer with the computed offset (if non-inlined)
const idx_t string_pointer_offset = sizeof(uint32_t) + string_t::PREFIX_LENGTH;
for (idx_t i = 0; i < count; i++) {
const string_t str = Load<string_t>(row_ptr + col_offset);
if (!str.IsInlined()) {
// Load the pointer to the start of the row in the heap
data_ptr_t heap_row_ptr = Load<data_ptr_t>(row_ptr + heap_pointer_offset);
// This is where the pointer that points to the heap is stored in the RowLayout
data_ptr_t col_ptr = row_ptr + col_offset + string_pointer_offset;
// Load the pointer to the data of this column in the same heap row
data_ptr_t heap_col_ptr = Load<data_ptr_t>(col_ptr);
// Overwrite the column data pointer with the within-row offset (pointer arithmetic)
Store<idx_t>(heap_col_ptr - heap_row_ptr, col_ptr);
}
row_ptr += row_width;
}
} else {
// Replace the pointer with the computed offset
for (idx_t i = 0; i < count; i++) {
// Load the pointer to the start of the row in the heap
data_ptr_t heap_row_ptr = Load<data_ptr_t>(row_ptr + heap_pointer_offset);
// This is where the pointer that points to the heap is stored in the RowLayout
data_ptr_t col_ptr = row_ptr + col_offset;
// Load the pointer to the data of this column in the same heap row
data_ptr_t heap_col_ptr = Load<data_ptr_t>(col_ptr);
// Overwrite the column data pointer with the within-row offset (pointer arithmetic)
Store<idx_t>(heap_col_ptr - heap_row_ptr, col_ptr);
row_ptr += row_width;
}
}
}
}
void RowOperations::SwizzleHeapPointer(const RowLayout &layout, data_ptr_t row_ptr, const data_ptr_t heap_base_ptr,
const idx_t count) {
const idx_t row_width = layout.GetRowWidth();
row_ptr += layout.GetHeapPointerOffset();
idx_t cumulative_offset = 0;
for (idx_t i = 0; i < count; i++) {
Store<idx_t>(cumulative_offset, row_ptr);
cumulative_offset += Load<uint32_t>(heap_base_ptr + cumulative_offset);
row_ptr += row_width;
}
}
void RowOperations::UnswizzleHeapPointer(const RowLayout &layout, data_ptr_t row_ptr, const data_ptr_t heap_base_ptr,
const idx_t count) {
const idx_t row_width = layout.GetRowWidth();
row_ptr += layout.GetHeapPointerOffset();
for (idx_t i = 0; i < count; i++) {
idx_t heap_row_offset = Load<idx_t>(row_ptr);
Store<data_ptr_t>(heap_base_ptr + heap_row_offset, row_ptr);
row_ptr += row_width;
}
}
void RowOperations::UnswizzleColumns(const RowLayout &layout, const data_ptr_t base_row_ptr, const idx_t count) {
const idx_t row_width = layout.GetRowWidth();
const idx_t heap_pointer_offset = layout.GetHeapPointerOffset();
// Unswizzle the columns one by one
for (idx_t col_idx = 0; col_idx < layout.ColumnCount(); col_idx++) {
auto physical_type = layout.GetTypes()[col_idx].InternalType();
if (TypeIsConstantSize(physical_type)) {
continue;
}
const idx_t col_offset = layout.GetOffsets()[col_idx];
data_ptr_t row_ptr = base_row_ptr;
if (physical_type == PhysicalType::VARCHAR) {
// Replace offset with the pointer (if non-inlined)
const idx_t string_pointer_offset = sizeof(uint32_t) + string_t::PREFIX_LENGTH;
for (idx_t i = 0; i < count; i++) {
const string_t str = Load<string_t>(row_ptr + col_offset);
if (!str.IsInlined()) {
// Load the pointer to the start of the row in the heap
data_ptr_t heap_row_ptr = Load<data_ptr_t>(row_ptr + heap_pointer_offset);
// This is where the pointer that points to the heap is stored in the RowLayout
data_ptr_t col_ptr = row_ptr + col_offset + string_pointer_offset;
// Load the offset to the data of this column in the same heap row
idx_t heap_col_offset = Load<idx_t>(col_ptr);
// Overwrite the column data offset with the pointer
Store<data_ptr_t>(heap_row_ptr + heap_col_offset, col_ptr);
}
row_ptr += row_width;
}
} else {
// Replace the offset with the pointer
for (idx_t i = 0; i < count; i++) {
// Load the pointer to the start of the row in the heap
data_ptr_t heap_row_ptr = Load<data_ptr_t>(row_ptr + heap_pointer_offset);
// This is where the pointer that points to the heap is stored in the RowLayout
data_ptr_t col_ptr = row_ptr + col_offset;
// Load the offset to the data of this column in the same heap row
idx_t heap_col_offset = Load<idx_t>(col_ptr);
// Overwrite the column data offset with the pointer
Store<data_ptr_t>(heap_row_ptr + heap_col_offset, col_ptr);
row_ptr += row_width;
}
}
}
}
} // namespace duckdb