Skip to content

Instantly share code, notes, and snippets.

@chilarai

chilarai/duckdb.hpp Secret

Created Dec 12, 2020
Embed
What would you like to do?
duckdb.hpp
/*
Copyright 2018 DuckDB Contributors (see https://github.com/cwida/duckdb/graphs/contributors)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#define DUCKDB_AMALGAMATION 1
#define DUCKDB_SOURCE_ID "3222accba"
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/main/connection.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/main/materialized_query_result.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/types/chunk_collection.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/enums/order_type.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/constants.hpp
//
//
//===----------------------------------------------------------------------===//
#include <memory>
#include <cstdint>
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/string.hpp
//
//
//===----------------------------------------------------------------------===//
#include <string>
#include <sstream>
namespace duckdb {
using std::string;
}
namespace duckdb {
//! inline std directives that we use frequently
using std::move;
using std::shared_ptr;
using std::unique_ptr;
using data_ptr = unique_ptr<char[]>;
using std::make_shared;
// NOTE: there is a copy of this in the Postgres' parser grammar (gram.y)
#define DEFAULT_SCHEMA "main"
#define TEMP_SCHEMA "temp"
#define INVALID_SCHEMA ""
//! a saner size_t for loop indices etc
typedef uint64_t idx_t;
//! The type used for row identifiers
typedef int64_t row_t;
//! The type used for hashes
typedef uint64_t hash_t;
//! The value used to signify an invalid index entry
extern const idx_t INVALID_INDEX;
//! data pointers
typedef uint8_t data_t;
typedef data_t *data_ptr_t;
typedef const data_t *const_data_ptr_t;
//! Type used to represent dates
typedef int32_t date_t;
//! Type used to represent time
typedef int32_t dtime_t;
//! Type used to represent timestamps
typedef int64_t timestamp_t;
//! Type used for the selection vector
typedef uint16_t sel_t;
//! Type used for transaction timestamps
typedef idx_t transaction_t;
//! Type used for column identifiers
typedef idx_t column_t;
//! Special value used to signify the ROW ID of a table
extern const column_t COLUMN_IDENTIFIER_ROW_ID;
//! The maximum row identifier used in tables
extern const row_t MAX_ROW_ID;
extern const transaction_t TRANSACTION_ID_START;
extern const transaction_t MAXIMUM_QUERY_ID;
extern const transaction_t NOT_DELETED_ID;
extern const double PI;
struct Storage {
//! The size of a hard disk sector, only really needed for Direct IO
constexpr static int SECTOR_SIZE = 4096;
//! Block header size for blocks written to the storage
constexpr static int BLOCK_HEADER_SIZE = sizeof(uint64_t);
// Size of a memory slot managed by the StorageManager. This is the quantum of allocation for Blocks on DuckDB. We
// default to 256KB. (1 << 18)
constexpr static int BLOCK_ALLOC_SIZE = 262144;
//! The actual memory space that is available within the blocks
constexpr static int BLOCK_SIZE = BLOCK_ALLOC_SIZE - BLOCK_HEADER_SIZE;
//! The size of the headers. This should be small and written more or less atomically by the hard disk. We default
//! to the page size, which is 4KB. (1 << 12)
constexpr static int FILE_HEADER_SIZE = 4096;
};
uint64_t NextPowerOfTwo(uint64_t v);
} // namespace duckdb
namespace duckdb {
enum class OrderType : uint8_t { INVALID = 0, ORDER_DEFAULT = 1, ASCENDING = 2, DESCENDING = 3 };
enum class OrderByNullType : uint8_t { INVALID = 0, ORDER_DEFAULT = 1, NULLS_FIRST = 2, NULLS_LAST = 3 };
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/types/data_chunk.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/common.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/helper.hpp
//
//
//===----------------------------------------------------------------------===//
#include <string.h>
#ifdef _MSC_VER
#define suint64_t int64_t
#endif
namespace duckdb {
#if !defined(_MSC_VER) && (__cplusplus < 201402L)
template <typename T, typename... Args> unique_ptr<T> make_unique(Args &&... args) {
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
#else // Visual Studio has make_unique
using std::make_unique;
#endif
template <typename S, typename T, typename... Args> unique_ptr<S> make_unique_base(Args &&... args) {
return unique_ptr<S>(new T(std::forward<Args>(args)...));
}
template <typename T, typename S> unique_ptr<S> unique_ptr_cast(unique_ptr<T> src) {
return unique_ptr<S>(static_cast<S *>(src.release()));
}
template <typename T> T MaxValue(T a, T b) {
return a > b ? a : b;
}
template <typename T> T MinValue(T a, T b) {
return a < b ? a : b;
}
template <typename T> const T Load(const_data_ptr_t ptr) {
T ret;
memcpy(&ret, ptr, sizeof(ret));
return ret;
}
template <typename T> void Store(const T val, data_ptr_t ptr) {
memcpy(ptr, (void *)&val, sizeof(val));
}
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/types/vector.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/bitset.hpp
//
//
//===----------------------------------------------------------------------===//
#include <bitset>
namespace duckdb {
using std::bitset;
}
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/types/selection_vector.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/types.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/assert.hpp
//
//
//===----------------------------------------------------------------------===//
#include <assert.h>
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/vector.hpp
//
//
//===----------------------------------------------------------------------===//
#include <vector>
namespace duckdb {
using std::vector;
}
namespace duckdb {
class Serializer;
class Deserializer;
struct blob_t {
data_ptr_t data;
idx_t size;
};
struct interval_t {
int32_t months;
int32_t days;
int64_t msecs;
};
struct hugeint_t {
public:
uint64_t lower;
int64_t upper;
public:
hugeint_t() = default;
hugeint_t(int64_t value);
hugeint_t(const hugeint_t &rhs) = default;
hugeint_t(hugeint_t &&rhs) = default;
hugeint_t &operator=(const hugeint_t &rhs) = default;
hugeint_t &operator=(hugeint_t &&rhs) = default;
string ToString() const;
// comparison operators
bool operator==(const hugeint_t &rhs) const;
bool operator!=(const hugeint_t &rhs) const;
bool operator<=(const hugeint_t &rhs) const;
bool operator<(const hugeint_t &rhs) const;
bool operator>(const hugeint_t &rhs) const;
bool operator>=(const hugeint_t &rhs) const;
// arithmetic operators
hugeint_t operator+(const hugeint_t &rhs) const;
hugeint_t operator-(const hugeint_t &rhs) const;
hugeint_t operator*(const hugeint_t &rhs) const;
hugeint_t operator/(const hugeint_t &rhs) const;
hugeint_t operator%(const hugeint_t &rhs) const;
hugeint_t operator-() const;
// bitwise operators
hugeint_t operator>>(const hugeint_t &rhs) const;
hugeint_t operator<<(const hugeint_t &rhs) const;
hugeint_t operator&(const hugeint_t &rhs) const;
hugeint_t operator|(const hugeint_t &rhs) const;
hugeint_t operator^(const hugeint_t &rhs) const;
hugeint_t operator~() const;
// in-place operators
hugeint_t &operator+=(const hugeint_t &rhs);
hugeint_t &operator-=(const hugeint_t &rhs);
hugeint_t &operator*=(const hugeint_t &rhs);
hugeint_t &operator/=(const hugeint_t &rhs);
hugeint_t &operator%=(const hugeint_t &rhs);
hugeint_t &operator>>=(const hugeint_t &rhs);
hugeint_t &operator<<=(const hugeint_t &rhs);
hugeint_t &operator&=(const hugeint_t &rhs);
hugeint_t &operator|=(const hugeint_t &rhs);
hugeint_t &operator^=(const hugeint_t &rhs);
};
struct string_t;
template <class T> using child_list_t = std::vector<std::pair<std::string, T>>;
template <class T> using buffer_ptr = std::shared_ptr<T>;
template <class T, typename... Args> buffer_ptr<T> make_buffer(Args &&... args) {
return std::make_shared<T>(std::forward<Args>(args)...);
}
struct list_entry_t {
list_entry_t() = default;
list_entry_t(uint64_t offset, uint64_t length) : offset(offset), length(length) {
}
uint64_t offset;
uint64_t length;
};
//===--------------------------------------------------------------------===//
// Internal Types
//===--------------------------------------------------------------------===//
// taken from arrow's type.h
enum class PhysicalType : uint8_t {
/// A NULL type having no physical storage
NA = 0,
/// Boolean as 1 bit, LSB bit-packed ordering
BOOL = 1,
/// Unsigned 8-bit little-endian integer
UINT8 = 2,
/// Signed 8-bit little-endian integer
INT8 = 3,
/// Unsigned 16-bit little-endian integer
UINT16 = 4,
/// Signed 16-bit little-endian integer
INT16 = 5,
/// Unsigned 32-bit little-endian integer
UINT32 = 6,
/// Signed 32-bit little-endian integer
INT32 = 7,
/// Unsigned 64-bit little-endian integer
UINT64 = 8,
/// Signed 64-bit little-endian integer
INT64 = 9,
/// 2-byte floating point value
HALF_FLOAT = 10,
/// 4-byte floating point value
FLOAT = 11,
/// 8-byte floating point value
DOUBLE = 12,
/// UTF8 variable-length string as List<Char>
STRING = 13,
/// Variable-length bytes (no guarantee of UTF8-ness)
BINARY = 14,
/// Fixed-size binary. Each value occupies the same number of bytes
FIXED_SIZE_BINARY = 15,
/// int32_t days since the UNIX epoch
DATE32 = 16,
/// int64_t milliseconds since the UNIX epoch
DATE64 = 17,
/// Exact timestamp encoded with int64 since UNIX epoch
/// Default unit millisecond
TIMESTAMP = 18,
/// Time as signed 32-bit integer, representing either seconds or
/// milliseconds since midnight
TIME32 = 19,
/// Time as signed 64-bit integer, representing either microseconds or
/// nanoseconds since midnight
TIME64 = 20,
/// YEAR_MONTH or DAY_TIME interval in SQL style
INTERVAL = 21,
/// Precision- and scale-based decimal type. Storage type depends on the
/// parameters.
// DECIMAL = 22,
/// A list of some logical data type
LIST = 23,
/// Struct of logical types
STRUCT = 24,
/// Unions of logical types
UNION = 25,
/// Dictionary-encoded type, also called "categorical" or "factor"
/// in other programming languages. Holds the dictionary value
/// type but not the dictionary itself, which is part of the
/// ArrayData struct
DICTIONARY = 26,
/// Map, a repeated struct logical type
MAP = 27,
/// Custom data type, implemented by user
EXTENSION = 28,
/// Fixed size list of some logical type
FIXED_SIZE_LIST = 29,
/// Measure of elapsed time in either seconds, milliseconds, microseconds
/// or nanoseconds.
DURATION = 30,
/// Like STRING, but with 64-bit offsets
LARGE_STRING = 31,
/// Like BINARY, but with 64-bit offsets
LARGE_BINARY = 32,
/// Like LIST, but with 64-bit offsets
LARGE_LIST = 33,
// DuckDB Extensions
VARCHAR = 200, // our own string representation, different from STRING and LARGE_STRING above
VARBINARY = 201,
POINTER = 202,
HASH = 203,
INT128 = 204, // 128-bit integers
INVALID = 255
};
//===--------------------------------------------------------------------===//
// SQL Types
//===--------------------------------------------------------------------===//
enum class LogicalTypeId : uint8_t {
INVALID = 0,
SQLNULL = 1, /* NULL type, used for constant NULL */
UNKNOWN = 2, /* unknown type, used for parameter expressions */
ANY = 3, /* ANY type, used for functions that accept any type as parameter */
BOOLEAN = 10,
TINYINT = 11,
SMALLINT = 12,
INTEGER = 13,
BIGINT = 14,
DATE = 15,
TIME = 16,
TIMESTAMP = 17,
DECIMAL = 18,
FLOAT = 19,
DOUBLE = 20,
CHAR = 21,
VARCHAR = 22,
VARBINARY = 23,
BLOB = 24,
INTERVAL = 25,
HUGEINT = 50,
POINTER = 51,
HASH = 52,
STRUCT = 100,
LIST = 101
};
struct LogicalType {
LogicalType();
LogicalType(LogicalTypeId id);
LogicalType(LogicalTypeId id, string collation);
LogicalType(LogicalTypeId id, uint8_t width, uint8_t scale);
LogicalType(LogicalTypeId id, child_list_t<LogicalType> child_types);
LogicalType(LogicalTypeId id, uint8_t width, uint8_t scale, string collation,
child_list_t<LogicalType> child_types);
LogicalTypeId id() const {
return id_;
}
uint8_t width() const {
return width_;
}
uint8_t scale() const {
return scale_;
}
const string &collation() const {
return collation_;
}
const child_list_t<LogicalType> &child_types() const {
return child_types_;
}
PhysicalType InternalType() const {
return physical_type_;
}
bool operator==(const LogicalType &rhs) const {
return id_ == rhs.id_ && width_ == rhs.width_ && scale_ == rhs.scale_;
}
bool operator!=(const LogicalType &rhs) const {
return !(*this == rhs);
}
//! Serializes a LogicalType to a stand-alone binary blob
void Serialize(Serializer &serializer);
//! Deserializes a blob back into an LogicalType
static LogicalType Deserialize(Deserializer &source);
string ToString() const;
bool IsIntegral() const;
bool IsNumeric() const;
bool IsMoreGenericThan(LogicalType &other) const;
hash_t Hash() const;
static LogicalType MaxLogicalType(LogicalType left, LogicalType right);
//! Gets the decimal properties of a numeric type. Fails if the type is not numeric.
bool GetDecimalProperties(int &width, int &scale) const;
void Verify() const;
private:
LogicalTypeId id_;
uint8_t width_;
uint8_t scale_;
string collation_;
child_list_t<LogicalType> child_types_;
PhysicalType physical_type_;
private:
PhysicalType GetInternalType();
public:
static const LogicalType SQLNULL;
static const LogicalType BOOLEAN;
static const LogicalType TINYINT;
static const LogicalType SMALLINT;
static const LogicalType INTEGER;
static const LogicalType BIGINT;
static const LogicalType FLOAT;
static const LogicalType DOUBLE;
static const LogicalType DECIMAL;
static const LogicalType DATE;
static const LogicalType TIMESTAMP;
static const LogicalType TIME;
static const LogicalType VARCHAR;
static const LogicalType VARBINARY;
static const LogicalType STRUCT;
static const LogicalType LIST;
static const LogicalType ANY;
static const LogicalType BLOB;
static const LogicalType INTERVAL;
static const LogicalType HUGEINT;
static const LogicalType HASH;
static const LogicalType POINTER;
static const LogicalType INVALID;
//! A list of all NUMERIC types (integral and floating point types)
static const vector<LogicalType> NUMERIC;
//! A list of all INTEGRAL types
static const vector<LogicalType> INTEGRAL;
//! A list of ALL SQL types
static const vector<LogicalType> ALL_TYPES;
};
string LogicalTypeIdToString(LogicalTypeId type);
LogicalType TransformStringToLogicalType(string str);
//! Returns the PhysicalType for the given type
template <class T> PhysicalType GetTypeId() {
if (std::is_same<T, bool>()) {
return PhysicalType::BOOL;
} else if (std::is_same<T, int8_t>()) {
return PhysicalType::INT8;
} else if (std::is_same<T, int16_t>()) {
return PhysicalType::INT16;
} else if (std::is_same<T, int32_t>()) {
return PhysicalType::INT32;
} else if (std::is_same<T, int64_t>()) {
return PhysicalType::INT64;
} else if (std::is_same<T, hugeint_t>()) {
return PhysicalType::INT128;
} else if (std::is_same<T, uint64_t>()) {
return PhysicalType::HASH;
} else if (std::is_same<T, uintptr_t>()) {
return PhysicalType::POINTER;
} else if (std::is_same<T, float>()) {
return PhysicalType::FLOAT;
} else if (std::is_same<T, double>()) {
return PhysicalType::DOUBLE;
} else if (std::is_same<T, const char *>() || std::is_same<T, char *>()) {
return PhysicalType::VARCHAR;
} else if (std::is_same<T, interval_t>()) {
return PhysicalType::INTERVAL;
} else {
return PhysicalType::INVALID;
}
}
template <class T> bool IsValidType() {
return GetTypeId<T>() != PhysicalType::INVALID;
}
//! The PhysicalType used by the row identifiers column
extern const LogicalType LOGICAL_ROW_TYPE;
extern const PhysicalType ROW_TYPE;
string TypeIdToString(PhysicalType type);
idx_t GetTypeIdSize(PhysicalType type);
bool TypeIsConstantSize(PhysicalType type);
bool TypeIsIntegral(PhysicalType type);
bool TypeIsNumeric(PhysicalType type);
bool TypeIsInteger(PhysicalType type);
template <class T> bool IsIntegerType() {
return TypeIsIntegral(GetTypeId<T>());
}
bool ApproxEqual(float l, float r);
bool ApproxEqual(double l, double r);
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/vector_size.hpp
//
//
//===----------------------------------------------------------------------===//
namespace duckdb {
//! The vector size used in the execution engine
#ifndef STANDARD_VECTOR_SIZE
#define STANDARD_VECTOR_SIZE 1024
#endif
#if ((STANDARD_VECTOR_SIZE & (STANDARD_VECTOR_SIZE - 1)) != 0)
#error Vector size should be a power of two
#endif
//! Zero selection vector: completely filled with the value 0 [READ ONLY]
extern const sel_t ZERO_VECTOR[STANDARD_VECTOR_SIZE];
}
namespace duckdb {
class VectorBuffer;
struct SelectionData {
SelectionData(idx_t count) {
owned_data = unique_ptr<sel_t[]>(new sel_t[count]);
}
unique_ptr<sel_t[]> owned_data;
};
struct SelectionVector {
SelectionVector() : sel_vector(nullptr) {
}
SelectionVector(sel_t *sel) {
Initialize(sel);
}
SelectionVector(idx_t count) {
Initialize(count);
}
SelectionVector(idx_t start, idx_t count) {
Initialize(STANDARD_VECTOR_SIZE);
for (idx_t i = 0; i < count; i++) {
set_index(i, start + i);
}
}
SelectionVector(const SelectionVector &sel_vector) {
Initialize(sel_vector);
}
SelectionVector(buffer_ptr<SelectionData> data) {
Initialize(move(data));
}
public:
void Initialize(sel_t *sel) {
selection_data.reset();
sel_vector = sel;
}
void Initialize(idx_t count = STANDARD_VECTOR_SIZE) {
selection_data = make_buffer<SelectionData>(count);
sel_vector = selection_data->owned_data.get();
}
void Initialize(buffer_ptr<SelectionData> data) {
selection_data = move(data);
sel_vector = selection_data->owned_data.get();
}
void Initialize(const SelectionVector &other) {
selection_data = other.selection_data;
sel_vector = other.sel_vector;
}
bool empty() const {
return !sel_vector;
}
void set_index(idx_t idx, idx_t loc) {
sel_vector[idx] = loc;
}
void swap(idx_t i, idx_t j) {
sel_t tmp = sel_vector[i];
sel_vector[i] = sel_vector[j];
sel_vector[j] = tmp;
}
idx_t get_index(idx_t idx) const {
return sel_vector[idx];
}
sel_t *data() {
return sel_vector;
}
buffer_ptr<SelectionData> sel_data() {
return selection_data;
}
buffer_ptr<SelectionData> Slice(const SelectionVector &sel, idx_t count);
string ToString(idx_t count = 0) const;
void Print(idx_t count = 0) const;
private:
sel_t *sel_vector;
buffer_ptr<SelectionData> selection_data;
};
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/types/value.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/exception.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/exception_format_value.hpp
//
//
//===----------------------------------------------------------------------===//
namespace duckdb {
enum class ExceptionFormatValueType : uint8_t {
FORMAT_VALUE_TYPE_DOUBLE,
FORMAT_VALUE_TYPE_INTEGER,
FORMAT_VALUE_TYPE_STRING
};
struct ExceptionFormatValue {
ExceptionFormatValue(double dbl_val) : type(ExceptionFormatValueType::FORMAT_VALUE_TYPE_DOUBLE), dbl_val(dbl_val) {
}
ExceptionFormatValue(int64_t int_val)
: type(ExceptionFormatValueType::FORMAT_VALUE_TYPE_INTEGER), int_val(int_val) {
}
ExceptionFormatValue(string str_val) : type(ExceptionFormatValueType::FORMAT_VALUE_TYPE_STRING), str_val(str_val) {
}
ExceptionFormatValueType type;
double dbl_val;
int64_t int_val;
string str_val;
public:
template <class T> static ExceptionFormatValue CreateFormatValue(T value) {
return int64_t(value);
}
static string Format(string msg, vector<ExceptionFormatValue> &values);
};
template <> ExceptionFormatValue ExceptionFormatValue::CreateFormatValue(PhysicalType value);
template <> ExceptionFormatValue ExceptionFormatValue::CreateFormatValue(LogicalType value);
template <> ExceptionFormatValue ExceptionFormatValue::CreateFormatValue(float value);
template <> ExceptionFormatValue ExceptionFormatValue::CreateFormatValue(double value);
template <> ExceptionFormatValue ExceptionFormatValue::CreateFormatValue(string value);
template <> ExceptionFormatValue ExceptionFormatValue::CreateFormatValue(const char *value);
template <> ExceptionFormatValue ExceptionFormatValue::CreateFormatValue(char *value);
} // namespace duckdb
#include <stdexcept>
namespace duckdb {
enum class PhysicalType : uint8_t;
struct LogicalType;
struct hugeint_t;
inline void assert_restrict_function(void *left_start, void *left_end, void *right_start, void *right_end,
const char *fname, int linenr) {
// assert that the two pointers do not overlap
#ifdef DEBUG
if (!(left_end <= right_start || right_end <= left_start)) {
printf("ASSERT RESTRICT FAILED: %s:%d\n", fname, linenr);
assert(0);
}
#endif
}
#define ASSERT_RESTRICT(left_start, left_end, right_start, right_end) \
assert_restrict_function(left_start, left_end, right_start, right_end, __FILE__, __LINE__)
//===--------------------------------------------------------------------===//
// Exception Types
//===--------------------------------------------------------------------===//
enum class ExceptionType {
INVALID = 0, // invalid type
OUT_OF_RANGE = 1, // value out of range error
CONVERSION = 2, // conversion/casting error
UNKNOWN_TYPE = 3, // unknown type
DECIMAL = 4, // decimal related
MISMATCH_TYPE = 5, // type mismatch
DIVIDE_BY_ZERO = 6, // divide by 0
OBJECT_SIZE = 7, // object size exceeded
INVALID_TYPE = 8, // incompatible for operation
SERIALIZATION = 9, // serialization
TRANSACTION = 10, // transaction management
NOT_IMPLEMENTED = 11, // method not implemented
EXPRESSION = 12, // expression parsing
CATALOG = 13, // catalog related
PARSER = 14, // parser related
PLANNER = 15, // planner related
SCHEDULER = 16, // scheduler related
EXECUTOR = 17, // executor related
CONSTRAINT = 18, // constraint related
INDEX = 19, // index related
STAT = 20, // stat related
CONNECTION = 21, // connection related
SYNTAX = 22, // syntax related
SETTINGS = 23, // settings related
BINDER = 24, // binder related
NETWORK = 25, // network related
OPTIMIZER = 26, // optimizer related
NULL_POINTER = 27, // nullptr exception
IO = 28, // IO exception
INTERRUPT = 29, // interrupt
FATAL = 30, // Fatal exception: fatal exceptions are non-recoverable, and render the entire DB in an unusable state
INTERNAL =
31, // Internal exception: exception that indicates something went wrong internally (i.e. bug in the code base)
INVALID_INPUT = 32 // Input or arguments error
};
class Exception : public std::exception {
public:
Exception(string message);
Exception(ExceptionType exception_type, string message);
ExceptionType type;
public:
const char *what() const noexcept override;
string ExceptionTypeToString(ExceptionType type);
template <typename... Args> static string ConstructMessage(string msg, Args... params) {
vector<ExceptionFormatValue> values;
return ConstructMessageRecursive(msg, values, params...);
}
static string ConstructMessageRecursive(string msg, vector<ExceptionFormatValue> &values);
template <class T, typename... Args>
static string ConstructMessageRecursive(string msg, vector<ExceptionFormatValue> &values, T param, Args... params) {
values.push_back(ExceptionFormatValue::CreateFormatValue<T>(param));
return ConstructMessageRecursive(msg, values, params...);
}
private:
string exception_message_;
};
//===--------------------------------------------------------------------===//
// Exception derived classes
//===--------------------------------------------------------------------===//
//! Exceptions that are StandardExceptions do NOT invalidate the current transaction when thrown
class StandardException : public Exception {
public:
StandardException(ExceptionType exception_type, string message) : Exception(exception_type, message) {
}
};
class CatalogException : public StandardException {
public:
CatalogException(string msg);
template <typename... Args>
CatalogException(string msg, Args... params) : CatalogException(ConstructMessage(msg, params...)) {
}
};
class ParserException : public StandardException {
public:
ParserException(string msg);
template <typename... Args>
ParserException(string msg, Args... params) : ParserException(ConstructMessage(msg, params...)) {
}
};
class BinderException : public StandardException {
public:
BinderException(string msg);
template <typename... Args>
BinderException(string msg, Args... params) : BinderException(ConstructMessage(msg, params...)) {
}
};
class ConversionException : public Exception {
public:
ConversionException(string msg);
template <typename... Args>
ConversionException(string msg, Args... params) : ConversionException(ConstructMessage(msg, params...)) {
}
};
class TransactionException : public Exception {
public:
TransactionException(string msg);
template <typename... Args>
TransactionException(string msg, Args... params) : TransactionException(ConstructMessage(msg, params...)) {
}
};
class NotImplementedException : public Exception {
public:
NotImplementedException(string msg);
template <typename... Args>
NotImplementedException(string msg, Args... params) : NotImplementedException(ConstructMessage(msg, params...)) {
}
};
class OutOfRangeException : public Exception {
public:
OutOfRangeException(string msg);
template <typename... Args>
OutOfRangeException(string msg, Args... params) : OutOfRangeException(ConstructMessage(msg, params...)) {
}
};
class SyntaxException : public Exception {
public:
SyntaxException(string msg);
template <typename... Args>
SyntaxException(string msg, Args... params) : SyntaxException(ConstructMessage(msg, params...)) {
}
};
class ConstraintException : public Exception {
public:
ConstraintException(string msg);
template <typename... Args>
ConstraintException(string msg, Args... params) : ConstraintException(ConstructMessage(msg, params...)) {
}
};
class IOException : public Exception {
public:
IOException(string msg);
template <typename... Args>
IOException(string msg, Args... params) : IOException(ConstructMessage(msg, params...)) {
}
};
class SerializationException : public Exception {
public:
SerializationException(string msg);
template <typename... Args>
SerializationException(string msg, Args... params) : SerializationException(ConstructMessage(msg, params...)) {
}
};
class SequenceException : public Exception {
public:
SequenceException(string msg);
template <typename... Args>
SequenceException(string msg, Args... params) : SequenceException(ConstructMessage(msg, params...)) {
}
};
class InterruptException : public Exception {
public:
InterruptException();
};
class FatalException : public Exception {
public:
FatalException(string msg);
template <typename... Args>
FatalException(string msg, Args... params) : FatalException(ConstructMessage(msg, params...)) {
}
};
class InternalException : public Exception {
public:
InternalException(string msg);
template <typename... Args>
InternalException(string msg, Args... params) : InternalException(ConstructMessage(msg, params...)) {
}
};
class InvalidInputException : public Exception {
public:
InvalidInputException(string msg);
template <typename... Args>
InvalidInputException(string msg, Args... params) : InvalidInputException(ConstructMessage(msg, params...)) {
}
};
class CastException : public Exception {
public:
CastException(const PhysicalType origType, const PhysicalType newType);
CastException(const LogicalType origType, const LogicalType newType);
};
class InvalidTypeException : public Exception {
public:
InvalidTypeException(PhysicalType type, string msg);
InvalidTypeException(LogicalType type, string msg);
};
class TypeMismatchException : public Exception {
public:
TypeMismatchException(const PhysicalType type_1, const PhysicalType type_2, string msg);
TypeMismatchException(const LogicalType type_1, const LogicalType type_2, string msg);
};
class ValueOutOfRangeException : public Exception {
public:
ValueOutOfRangeException(const int64_t value, const PhysicalType origType, const PhysicalType newType);
ValueOutOfRangeException(const hugeint_t value, const PhysicalType origType, const PhysicalType newType);
ValueOutOfRangeException(const double value, const PhysicalType origType, const PhysicalType newType);
ValueOutOfRangeException(const PhysicalType varType, const idx_t length);
};
} // namespace duckdb
namespace duckdb {
class Deserializer;
class Serializer;
//! The Value object holds a single arbitrary value of any type that can be
//! stored in the database.
class Value {
friend class Vector;
public:
//! Create an empty NULL value of the specified type
explicit Value(LogicalType type = LogicalType::SQLNULL) : type_(type), is_null(true) {
}
//! Create a BIGINT value
Value(int32_t val) : type_(LogicalType::INTEGER), is_null(false) {
value_.integer = val;
}
//! Create a BIGINT value
Value(int64_t val) : type_(LogicalType::BIGINT), is_null(false) {
value_.bigint = val;
}
//! Create a FLOAT value
Value(float val) : type_(LogicalType::FLOAT), is_null(false) {
value_.float_ = val;
}
//! Create a DOUBLE value
Value(double val) : type_(LogicalType::DOUBLE), is_null(false) {
value_.double_ = val;
}
//! Create a VARCHAR value
Value(const char *val) : Value(val ? string(val) : string()) {
}
Value(string_t val);
//! Create a VARCHAR value
Value(string val);
LogicalType type() const {
return type_;
}
//! Create the lowest possible value of a given type (numeric only)
static Value MinimumValue(PhysicalType type);
//! Create the highest possible value of a given type (numeric only)
static Value MaximumValue(PhysicalType type);
//! Create a Numeric value of the specified type with the specified value
static Value Numeric(LogicalType type, int64_t value);
static Value Numeric(LogicalType type, hugeint_t value);
//! Create a tinyint Value from a specified value
static Value BOOLEAN(int8_t value);
//! Create a tinyint Value from a specified value
static Value TINYINT(int8_t value);
//! Create a smallint Value from a specified value
static Value SMALLINT(int16_t value);
//! Create an integer Value from a specified value
static Value INTEGER(int32_t value);
//! Create a bigint Value from a specified value
static Value BIGINT(int64_t value);
//! Create a hugeint Value from a specified value
static Value HUGEINT(hugeint_t value);
//! Create a hash Value from a specified value
static Value HASH(hash_t value);
//! Create a pointer Value from a specified value
static Value POINTER(uintptr_t value);
//! Create a date Value from a specified date
static Value DATE(date_t date);
//! Create a date Value from a specified date
static Value DATE(int32_t year, int32_t month, int32_t day);
//! Create a time Value from a specified time
static Value TIME(dtime_t time);
//! Create a time Value from a specified time
static Value TIME(int32_t hour, int32_t min, int32_t sec, int32_t msec);
//! Create a timestamp Value from a specified date/time combination
static Value TIMESTAMP(date_t date, dtime_t time);
//! Create a timestamp Value from a specified timestamp
static Value TIMESTAMP(timestamp_t timestamp);
//! Create a timestamp Value from a specified timestamp in separate values
static Value TIMESTAMP(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec,
int32_t msec);
static Value INTERVAL(int32_t months, int32_t days, int64_t msecs);
static Value INTERVAL(interval_t interval);
// Decimal values
static Value DECIMAL(int16_t value, uint8_t width, uint8_t scale);
static Value DECIMAL(int32_t value, uint8_t width, uint8_t scale);
static Value DECIMAL(int64_t value, uint8_t width, uint8_t scale);
static Value DECIMAL(hugeint_t value, uint8_t width, uint8_t scale);
//! Create a float Value from a specified value
static Value FLOAT(float value);
//! Create a double Value from a specified value
static Value DOUBLE(double value);
//! Create a struct value with given list of entries
static Value STRUCT(child_list_t<Value> values);
//! Create a list value with the given entries
static Value LIST(std::vector<Value> values);
//! Create a blob Value from a specified value
static Value BLOB(string data, bool must_cast = true);
template <class T> T GetValue() const {
throw NotImplementedException("Unimplemented template type for Value::GetValue");
}
template <class T> static Value CreateValue(T value) {
throw NotImplementedException("Unimplemented template type for Value::CreateValue");
}
//! Return a copy of this value
Value Copy() const {
return Value(*this);
}
//! Convert this value to a string
string ToString() const;
//! Cast this value to another type
Value CastAs(LogicalType target_type, bool strict = false) const;
//! Tries to cast value to another type, throws exception if its not possible
bool TryCastAs(LogicalType target_type, bool strict = false);
//! Serializes a Value to a stand-alone binary blob
void Serialize(Serializer &serializer);
//! Deserializes a Value from a blob
static Value Deserialize(Deserializer &source);
//===--------------------------------------------------------------------===//
// Numeric Operators
//===--------------------------------------------------------------------===//
Value operator+(const Value &rhs) const;
Value operator-(const Value &rhs) const;
Value operator*(const Value &rhs) const;
Value operator/(const Value &rhs) const;
Value operator%(const Value &rhs) const;
//===--------------------------------------------------------------------===//
// Comparison Operators
//===--------------------------------------------------------------------===//
bool operator==(const Value &rhs) const;
bool operator!=(const Value &rhs) const;
bool operator<(const Value &rhs) const;
bool operator>(const Value &rhs) const;
bool operator<=(const Value &rhs) const;
bool operator>=(const Value &rhs) const;
bool operator==(const int64_t &rhs) const;
bool operator!=(const int64_t &rhs) const;
bool operator<(const int64_t &rhs) const;
bool operator>(const int64_t &rhs) const;
bool operator<=(const int64_t &rhs) const;
bool operator>=(const int64_t &rhs) const;
static bool FloatIsValid(float value);
static bool DoubleIsValid(double value);
//! Returns true if the values are (approximately) equivalent. Note this is NOT the SQL equivalence. For this
//! function, NULL values are equivalent and floating point values that are close are equivalent.
static bool ValuesAreEqual(Value result_value, Value value);
friend std::ostream &operator<<(std::ostream &out, const Value &val) {
out << val.ToString();
return out;
}
void Print();
private:
//! The logical of the value
LogicalType type_;
public:
//! Whether or not the value is NULL
bool is_null;
//! The value of the object, if it is of a constant size Type
union Val {
int8_t boolean;
int8_t tinyint;
int16_t smallint;
int32_t integer;
int64_t bigint;
hugeint_t hugeint;
float float_;
double double_;
uintptr_t pointer;
uint64_t hash;
interval_t interval;
} value_;
//! The value of the object, if it is of a variable size type
string str_value;
child_list_t<Value> struct_value;
std::vector<Value> list_value;
private:
template <class T> T GetValueInternal() const;
//! Templated helper function for casting
template <class DST, class OP> static DST _cast(const Value &v);
//! Templated helper function for binary operations
template <class OP>
static void _templated_binary_operation(const Value &left, const Value &right, Value &result, bool ignore_null);
//! Templated helper function for boolean operations
template <class OP> static bool _templated_boolean_operation(const Value &left, const Value &right);
};
template <> Value Value::CreateValue(bool value);
template <> Value Value::CreateValue(int8_t value);
template <> Value Value::CreateValue(int16_t value);
template <> Value Value::CreateValue(int32_t value);
template <> Value Value::CreateValue(int64_t value);
template <> Value Value::CreateValue(hugeint_t value);
template <> Value Value::CreateValue(const char *value);
template <> Value Value::CreateValue(string value);
template <> Value Value::CreateValue(string_t value);
template <> Value Value::CreateValue(float value);
template <> Value Value::CreateValue(double value);
template <> Value Value::CreateValue(Value value);
template <> bool Value::GetValue() const;
template <> int8_t Value::GetValue() const;
template <> int16_t Value::GetValue() const;
template <> int32_t Value::GetValue() const;
template <> int64_t Value::GetValue() const;
template <> hugeint_t Value::GetValue() const;
template <> string Value::GetValue() const;
template <> float Value::GetValue() const;
template <> double Value::GetValue() const;
template <> uintptr_t Value::GetValue() const;
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/enums/vector_type.hpp
//
//
//===----------------------------------------------------------------------===//
namespace duckdb {
enum class VectorType : uint8_t {
FLAT_VECTOR, // Flat vectors represent a standard uncompressed vector
CONSTANT_VECTOR, // Constant vector represents a single constant
DICTIONARY_VECTOR, // Dictionary vector represents a selection vector on top of another vector
SEQUENCE_VECTOR // Sequence vector represents a sequence with a start point and an increment
};
string VectorTypeToString(VectorType type);
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/types/vector_buffer.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/types/string_heap.hpp
//
//
//===----------------------------------------------------------------------===//
namespace duckdb {
//! A string heap is the owner of a set of strings, strings can be inserted into
//! it On every insert, a pointer to the inserted string is returned The
//! returned pointer will remain valid until the StringHeap is destroyed
class StringHeap {
public:
StringHeap();
void Destroy() {
tail = nullptr;
chunk = nullptr;
}
void Move(StringHeap &other) {
assert(!other.chunk);
other.tail = tail;
other.chunk = move(chunk);
tail = nullptr;
}
//! Add a string to the string heap, returns a pointer to the string
string_t AddString(const char *data, idx_t len);
//! Add a string to the string heap, returns a pointer to the string
string_t AddString(const char *data);
//! Add a string to the string heap, returns a pointer to the string
string_t AddString(const string &data);
//! Add a string to the string heap, returns a pointer to the string
string_t AddString(const string_t &data);
//! Add a blob to the string heap; blobs can be non-valid UTF8
string_t AddBlob(const char *data, idx_t len);
//! Allocates space for an empty string of size "len" on the heap
string_t EmptyString(idx_t len);
//! Add all strings from a different string heap to this string heap
void MergeHeap(StringHeap &heap);
private:
struct StringChunk {
StringChunk(idx_t size) : current_position(0), maximum_size(size) {
data = unique_ptr<char[]>(new char[maximum_size]);
}
~StringChunk() {
if (prev) {
auto current_prev = move(prev);
while (current_prev) {
current_prev = move(current_prev->prev);
}
}
}
unique_ptr<char[]> data;
idx_t current_position;
idx_t maximum_size;
unique_ptr<StringChunk> prev;
};
StringChunk *tail;
unique_ptr<StringChunk> chunk;
};
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/types/string_type.hpp
//
//
//===----------------------------------------------------------------------===//
#include <cstring>
#include <cassert>
namespace duckdb {
struct string_t {
friend struct StringComparisonOperators;
friend class StringSegment;
public:
static constexpr idx_t PREFIX_LENGTH = 4 * sizeof(char);
static constexpr idx_t INLINE_LENGTH = 12;
string_t() = default;
string_t(uint32_t len) {
value.inlined.length = len;
memset(value.inlined.inlined, 0, INLINE_LENGTH);
}
string_t(const char *data, uint32_t len) {
value.inlined.length = len;
assert(data || GetSize() == 0);
if (IsInlined()) {
// zero initialize the prefix first
// this makes sure that strings with length smaller than 4 still have an equal prefix
memset(value.inlined.inlined, 0, PREFIX_LENGTH);
if (GetSize() == 0) {
return;
}
// small string: inlined
/* Note: this appears to write out-of bounds on `prefix` if `length` > `PREFIX_LENGTH`
but this is not the case because the `value_` union `inlined` char array directly
follows it with 8 more chars to use for the string value.
*/
memcpy(value.inlined.inlined, data, GetSize());
value.inlined.inlined[GetSize()] = '\0';
} else {
// large string: store pointer
memcpy(value.pointer.prefix, data, PREFIX_LENGTH);
value.pointer.ptr = (char *)data;
}
}
string_t(const char *data) : string_t(data, strlen(data)) {
}
string_t(const string &value) : string_t(value.c_str(), value.size()) {
}
bool IsInlined() const {
return GetSize() < INLINE_LENGTH;
}
char *GetData() {
return IsInlined() ? (char *)value.inlined.inlined : value.pointer.ptr;
}
const char *GetData() const {
return IsInlined() ? (const char *)value.inlined.inlined : value.pointer.ptr;
}
const char *GetPrefix() const {
return value.pointer.prefix;
}
idx_t GetSize() const {
return value.inlined.length;
}
string GetString() const {
return string(GetData(), GetSize());
}
void Finalize() {
// set trailing NULL byte
auto dataptr = (char *)GetData();
dataptr[GetSize()] = '\0';
if (GetSize() < INLINE_LENGTH) {
// fill prefix with zeros if the length is smaller than the prefix length
for (idx_t i = GetSize(); i < PREFIX_LENGTH; i++) {
value.inlined.inlined[i] = '\0';
}
} else {
// copy the data into the prefix
memcpy(value.pointer.prefix, dataptr, PREFIX_LENGTH);
}
}
void Verify();
private:
union {
struct {
uint32_t length;
char prefix[4];
char *ptr;
} pointer;
struct {
uint32_t length;
char inlined[12];
} inlined;
} value;
};
} // namespace duckdb
namespace duckdb {
class VectorBuffer;
class Vector;
class ChunkCollection;
enum class VectorBufferType : uint8_t {
STANDARD_BUFFER, // standard buffer, holds a single array of data
DICTIONARY_BUFFER, // dictionary buffer, holds a selection vector
VECTOR_CHILD_BUFFER, // vector child buffer: holds another vector
STRING_BUFFER, // string buffer, holds a string heap
STRUCT_BUFFER, // struct buffer, holds a ordered mapping from name to child vector
LIST_BUFFER // list buffer, holds a single flatvector child
};
//! The VectorBuffer is a class used by the vector to hold its data
class VectorBuffer {
public:
VectorBuffer(VectorBufferType type) : type(type) {
}
VectorBuffer(idx_t data_size);
virtual ~VectorBuffer() {
}
VectorBufferType type;
public:
data_ptr_t GetData() {
return data.get();
}
static buffer_ptr<VectorBuffer> CreateStandardVector(PhysicalType type);
static buffer_ptr<VectorBuffer> CreateConstantVector(PhysicalType type);
protected:
unique_ptr<data_t[]> data;
};
//! The DictionaryBuffer holds a selection vector
class DictionaryBuffer : public VectorBuffer {
public:
DictionaryBuffer(const SelectionVector &sel) : VectorBuffer(VectorBufferType::DICTIONARY_BUFFER), sel_vector(sel) {
}
DictionaryBuffer(buffer_ptr<SelectionData> data)
: VectorBuffer(VectorBufferType::DICTIONARY_BUFFER), sel_vector(move(data)) {
}
DictionaryBuffer(idx_t count = STANDARD_VECTOR_SIZE)
: VectorBuffer(VectorBufferType::DICTIONARY_BUFFER), sel_vector(count) {
}
public:
SelectionVector &GetSelVector() {
return sel_vector;
}
private:
SelectionVector sel_vector;
};
class VectorStringBuffer : public VectorBuffer {
public:
VectorStringBuffer();
public:
string_t AddString(const char *data, idx_t len) {
return heap.AddString(data, len);
}
string_t AddString(string_t data) {
return heap.AddString(data);
}
string_t AddBlob(string_t data) {
return heap.AddBlob(data.GetData(), data.GetSize());
}
string_t EmptyString(idx_t len) {
return heap.EmptyString(len);
}
void AddHeapReference(buffer_ptr<VectorBuffer> heap) {
references.push_back(move(heap));
}
private:
//! The string heap of this buffer
StringHeap heap;
// References to additional vector buffers referenced by this string buffer
vector<buffer_ptr<VectorBuffer>> references;
};
class VectorStructBuffer : public VectorBuffer {
public:
VectorStructBuffer();
~VectorStructBuffer();
public:
child_list_t<unique_ptr<Vector>> &GetChildren() {
return children;
}
void AddChild(string name, unique_ptr<Vector> vector) {
children.push_back(std::make_pair(name, move(vector)));
}
private:
//! child vectors used for nested data
child_list_t<unique_ptr<Vector>> children;
};
class VectorListBuffer : public VectorBuffer {
public:
VectorListBuffer();
~VectorListBuffer();
public:
ChunkCollection &GetChild() {
return *child;
}
void SetChild(unique_ptr<ChunkCollection> new_child);
private:
//! child vectors used for nested data
unique_ptr<ChunkCollection> child;
};
} // namespace duckdb
namespace duckdb {
//! Type used for nullmasks
typedef bitset<STANDARD_VECTOR_SIZE> nullmask_t;
//! Zero NULL mask: filled with the value 0 [READ ONLY]
extern nullmask_t ZERO_MASK;
struct VectorData {
const SelectionVector *sel;
data_ptr_t data;
nullmask_t *nullmask;
};
class VectorStructBuffer;
class VectorListBuffer;
class ChunkCollection;
struct SelCache;
//! Vector of values of a specified PhysicalType.
class Vector {
friend struct ConstantVector;
friend struct DictionaryVector;
friend struct FlatVector;
friend struct ListVector;
friend struct StringVector;
friend struct StructVector;
friend struct SequenceVector;
friend class DataChunk;
public:
Vector();
//! Create a vector of size one holding the passed on value
Vector(Value value);
//! Create an empty standard vector with a type, equivalent to calling Vector(type, true, false)
Vector(LogicalType type);
//! Create a non-owning vector that references the specified data
Vector(LogicalType type, data_ptr_t dataptr);
//! Create an owning vector that holds at most STANDARD_VECTOR_SIZE entries.
/*!
Create a new vector
If create_data is true, the vector will be an owning empty vector.
If zero_data is true, the allocated data will be zero-initialized.
*/
Vector(LogicalType type, bool create_data, bool zero_data);
// implicit copying of Vectors is not allowed
Vector(const Vector &) = delete;
// but moving of vectors is allowed
Vector(Vector &&other) noexcept;
//! The vector type specifies how the data of the vector is physically stored (i.e. if it is a single repeated
//! constant, if it is compressed)
VectorType vector_type;
//! The type of the elements stored in the vector (e.g. integer, float)
LogicalType type;
public:
//! Create a vector that references the specified value.
void Reference(const Value &value);
//! Causes this vector to reference the data held by the other vector.
void Reference(Vector &other);
//! Creates a reference to a slice of the other vector
void Slice(Vector &other, idx_t offset);
//! Creates a reference to a slice of the other vector
void Slice(Vector &other, const SelectionVector &sel, idx_t count);
//! Turns the vector into a dictionary vector with the specified dictionary
void Slice(const SelectionVector &sel, idx_t count);
//! Slice the vector, keeping the result around in a cache or potentially using the cache instead of slicing
void Slice(const SelectionVector &sel, idx_t count, SelCache &cache);
//! Creates the data of this vector with the specified type. Any data that
//! is currently in the vector is destroyed.
void Initialize(LogicalType new_type = LogicalType::INVALID, bool zero_data = false);
//! Converts this Vector to a printable string representation
string ToString(idx_t count) const;
void Print(idx_t count);
string ToString() const;
void Print();
//! Flatten the vector, removing any compression and turning it into a FLAT_VECTOR
void Normalify(idx_t count);
void Normalify(const SelectionVector &sel, idx_t count);
//! Obtains a selection vector and data pointer through which the data of this vector can be accessed
void Orrify(idx_t count, VectorData &data);
//! Turn the vector into a sequence vector
void Sequence(int64_t start, int64_t increment);
//! Verify that the Vector is in a consistent, not corrupt state. DEBUG
//! FUNCTION ONLY!
void Verify(idx_t count);
void Verify(const SelectionVector &sel, idx_t count);
void UTFVerify(idx_t count);
void UTFVerify(const SelectionVector &sel, idx_t count);
//! Returns the [index] element of the Vector as a Value.
Value GetValue(idx_t index) const;
//! Sets the [index] element of the Vector to the specified Value.
void SetValue(idx_t index, Value val);
//! Serializes a Vector to a stand-alone binary blob
void Serialize(idx_t count, Serializer &serializer);
//! Deserializes a blob back into a Vector
void Deserialize(idx_t count, Deserializer &source);
bool nullmask_all_set(){
return nullmask.all();
}
protected:
//! A pointer to the data.
data_ptr_t data;
//! The nullmask of the vector
nullmask_t nullmask;
//! The main buffer holding the data of the vector
buffer_ptr<VectorBuffer> buffer;
//! The buffer holding auxiliary data of the vector
//! e.g. a string vector uses this to store strings
buffer_ptr<VectorBuffer> auxiliary;
};
//! The DictionaryBuffer holds a selection vector
class VectorChildBuffer : public VectorBuffer {
public:
VectorChildBuffer() : VectorBuffer(VectorBufferType::VECTOR_CHILD_BUFFER), data() {
}
public:
Vector data;
};
struct ConstantVector {
static inline data_ptr_t GetData(Vector &vector) {
assert(vector.vector_type == VectorType::CONSTANT_VECTOR || vector.vector_type == VectorType::FLAT_VECTOR);
return vector.data;
}
template <class T> static inline T *GetData(Vector &vector) {
return (T *)ConstantVector::GetData(vector);
}
static inline bool IsNull(const Vector &vector) {
assert(vector.vector_type == VectorType::CONSTANT_VECTOR);
return vector.nullmask[0];
}
static inline void SetNull(Vector &vector, bool is_null) {
assert(vector.vector_type == VectorType::CONSTANT_VECTOR);
vector.nullmask[0] = is_null;
}
static inline nullmask_t &Nullmask(Vector &vector) {
assert(vector.vector_type == VectorType::CONSTANT_VECTOR);
return vector.nullmask;
}
static const sel_t zero_vector[STANDARD_VECTOR_SIZE];
static const SelectionVector ZeroSelectionVector;
};
struct DictionaryVector {
static inline SelectionVector &SelVector(const Vector &vector) {
assert(vector.vector_type == VectorType::DICTIONARY_VECTOR);
return ((DictionaryBuffer &)*vector.buffer).GetSelVector();
}
static inline Vector &Child(const Vector &vector) {
assert(vector.vector_type == VectorType::DICTIONARY_VECTOR);
return ((VectorChildBuffer &)*vector.auxiliary).data;
}
};
struct FlatVector {
static inline data_ptr_t GetData(Vector &vector) {
return ConstantVector::GetData(vector);
}
template <class T> static inline T *GetData(Vector &vector) {
return ConstantVector::GetData<T>(vector);
}
static inline void SetData(Vector &vector, data_ptr_t data) {
assert(vector.vector_type == VectorType::FLAT_VECTOR);
vector.data = data;
}
template <class T> static inline T GetValue(Vector &vector, idx_t idx) {
assert(vector.vector_type == VectorType::FLAT_VECTOR);
return FlatVector::GetData<T>(vector)[idx];
}
static inline nullmask_t &Nullmask(Vector &vector) {
assert(vector.vector_type == VectorType::FLAT_VECTOR);
return vector.nullmask;
}
static inline void SetNullmask(Vector &vector, nullmask_t new_mask) {
assert(vector.vector_type == VectorType::FLAT_VECTOR);
vector.nullmask = move(new_mask);
}
static inline void SetNull(Vector &vector, idx_t idx, bool value) {
assert(vector.vector_type == VectorType::FLAT_VECTOR);
vector.nullmask[idx] = value;
}
static inline bool IsNull(const Vector &vector, idx_t idx) {
assert(vector.vector_type == VectorType::FLAT_VECTOR);
return vector.nullmask[idx];
}
static const sel_t incremental_vector[STANDARD_VECTOR_SIZE];
static const SelectionVector IncrementalSelectionVector;
};
struct ListVector {
static ChunkCollection &GetEntry(const Vector &vector);
static bool HasEntry(const Vector &vector);
static void SetEntry(Vector &vector, unique_ptr<ChunkCollection> entry);
};
struct StringVector {
//! Add a string to the string heap of the vector (auxiliary data)
static string_t AddString(Vector &vector, const char *data, idx_t len);
//! Add a string to the string heap of the vector (auxiliary data)
static string_t AddString(Vector &vector, const char *data);
//! Add a string to the string heap of the vector (auxiliary data)
static string_t AddString(Vector &vector, string_t data);
//! Add a string to the string heap of the vector (auxiliary data)
static string_t AddString(Vector &vector, const string &data);
//! Add a string or a blob to the string heap of the vector (auxiliary data)
//! This function is the same as ::AddString, except the added data does not need to be valid UTF8
static string_t AddStringOrBlob(Vector &vector, string_t data);
//! Allocates an empty string of the specified size, and returns a writable pointer that can be used to store the
//! result of an operation
static string_t EmptyString(Vector &vector, idx_t len);
//! Add a reference from this vector to the string heap of the provided vector
static void AddHeapReference(Vector &vector, Vector &other);
};
struct StructVector {
static bool HasEntries(const Vector &vector);
static child_list_t<unique_ptr<Vector>> &GetEntries(const Vector &vector);
static void AddEntry(Vector &vector, string name, unique_ptr<Vector> entry);
};
struct SequenceVector {
static void GetSequence(const Vector &vector, int64_t &start, int64_t &increment) {
assert(vector.vector_type == VectorType::SEQUENCE_VECTOR);
auto data = (int64_t *)vector.buffer->GetData();
start = data[0];
increment = data[1];
}
};
} // namespace duckdb
struct ArrowArray;
namespace duckdb {
//! A Data Chunk represents a set of vectors.
/*!
The data chunk class is the intermediate representation used by the
execution engine of DuckDB. It effectively represents a subset of a relation.
It holds a set of vectors that all have the same length.
DataChunk is initialized using the DataChunk::Initialize function by
providing it with a vector of TypeIds for the Vector members. By default,
this function will also allocate a chunk of memory in the DataChunk for the
vectors and all the vectors will be referencing vectors to the data owned by
the chunk. The reason for this behavior is that the underlying vectors can
become referencing vectors to other chunks as well (i.e. in the case an
operator does not alter the data, such as a Filter operator which only adds a
selection vector).
In addition to holding the data of the vectors, the DataChunk also owns the
selection vector that underlying vectors can point to.
*/
class DataChunk {
public:
//! Creates an empty DataChunk
DataChunk();
//! The vectors owned by the DataChunk.
vector<Vector> data;
public:
idx_t size() const {
return count;
}
idx_t column_count() const {
return data.size();
}
void SetCardinality(idx_t count) {
assert(count <= STANDARD_VECTOR_SIZE);
this->count = count;
}
void SetCardinality(const DataChunk &other) {
this->count = other.size();
}
Value GetValue(idx_t col_idx, idx_t index) const;
void SetValue(idx_t col_idx, idx_t index, Value val);
//! Set the DataChunk to reference another data chunk
void Reference(DataChunk &chunk);
//! Initializes the DataChunk with the specified types to an empty DataChunk
//! This will create one vector of the specified type for each LogicalType in the
//! types list. The vector will be referencing vector to the data owned by
//! the DataChunk.
void Initialize(vector<LogicalType> &types);
//! Initializes an empty DataChunk with the given types. The vectors will *not* have any data allocated for them.
void InitializeEmpty(vector<LogicalType> &types);
//! Append the other DataChunk to this one. The column count and types of
//! the two DataChunks have to match exactly. Throws an exception if there
//! is not enough space in the chunk.
void Append(DataChunk &other);
//! Destroy all data and columns owned by this DataChunk
void Destroy();
//! Copies the data from this vector to another vector.
void Copy(DataChunk &other, idx_t offset = 0);
//! Turn all the vectors from the chunk into flat vectors
void Normalify();
unique_ptr<VectorData[]> Orrify();
void Slice(const SelectionVector &sel_vector, idx_t count);
void Slice(DataChunk &other, const SelectionVector &sel, idx_t count, idx_t col_offset = 0);
//! Resets the DataChunk to its state right after the DataChunk::Initialize
//! function was called. This sets the count to 0, and resets each member
//! Vector to point back to the data owned by this DataChunk.
void Reset();
//! Serializes a DataChunk to a stand-alone binary blob
void Serialize(Serializer &serializer);
//! Deserializes a blob back into a DataChunk
void Deserialize(Deserializer &source);
//! Hashes the DataChunk to the target vector
void Hash(Vector &result);
//! Returns a list of types of the vectors of this data chunk
vector<LogicalType> GetTypes();
//! Converts this DataChunk to a printable string representation
string ToString() const;
void Print();
DataChunk(const DataChunk &) = delete;
//! Verify that the DataChunk is in a consistent, not corrupt state. DEBUG
//! FUNCTION ONLY!
void Verify();
//! export data chunk as a arrow struct array that can be imported as arrow record batch
void ToArrowArray(ArrowArray *out_array);
private:
idx_t count;
};
} // namespace duckdb
namespace duckdb {
//! A ChunkCollection represents a set of DataChunks that all have the same
//! types
/*!
A ChunkCollection represents a set of DataChunks concatenated together in a
list. Individual values of the collection can be iterated over using the
iterator. It is also possible to iterate directly over the chunks for more
direct access.
*/
class ChunkCollection {
public:
ChunkCollection() : count(0) {
}
//! The total amount of elements in the collection
idx_t count;
//! The set of data chunks in the collection
vector<unique_ptr<DataChunk>> chunks;
//! The types of the ChunkCollection
vector<LogicalType> types;
//! The amount of columns in the ChunkCollection
idx_t column_count() {
return types.size();
}
//! Append a new DataChunk directly to this ChunkCollection
void Append(DataChunk &new_chunk);
//! Append another ChunkCollection directly to this ChunkCollection
void Append(ChunkCollection &other);
void Verify();
//! Gets the value of the column at the specified index
Value GetValue(idx_t column, idx_t index);
//! Sets the value of the column at the specified index
void SetValue(idx_t column, idx_t index, Value value);
vector<Value> GetRow(idx_t index);
string ToString() const {
return chunks.size() == 0 ? "ChunkCollection [ 0 ]"
: "ChunkCollection [ " + std::to_string(count) + " ]: \n" + chunks[0]->ToString();
}
void Print();
//! Gets a reference to the chunk at the given index
DataChunk &GetChunk(idx_t index) {
return *chunks[LocateChunk(index)];
}
void Sort(vector<OrderType> &desc, vector<OrderByNullType> &null_order, idx_t result[]);
//! Reorders the rows in the collection according to the given indices. NB: order is changed!
void Reorder(idx_t order[]);
void MaterializeSortedChunk(DataChunk &target, idx_t order[], idx_t start_offset);
//! Returns true if the ChunkCollections are equivalent
bool Equals(ChunkCollection &other);
//! Locates the chunk that belongs to the specific index
idx_t LocateChunk(idx_t index) {
idx_t result = index / STANDARD_VECTOR_SIZE;
assert(result < chunks.size());
return result;
}
void Heap(vector<OrderType> &desc, vector<OrderByNullType> &null_order, idx_t heap[], idx_t heap_size);
idx_t MaterializeHeapChunk(DataChunk &target, idx_t order[], idx_t start_offset, idx_t heap_size);
};
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/main/query_result.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/enums/statement_type.hpp
//
//
//===----------------------------------------------------------------------===//
namespace duckdb {
//===--------------------------------------------------------------------===//
// Statement Types
//===--------------------------------------------------------------------===//
enum class StatementType : uint8_t {
INVALID_STATEMENT, // invalid statement type
SELECT_STATEMENT, // select statement type
INSERT_STATEMENT, // insert statement type
UPDATE_STATEMENT, // update statement type
CREATE_STATEMENT, // create statement type
DELETE_STATEMENT, // delete statement type
PREPARE_STATEMENT, // prepare statement type
EXECUTE_STATEMENT, // execute statement type
ALTER_STATEMENT, // alter statement type
TRANSACTION_STATEMENT, // transaction statement type,
COPY_STATEMENT, // copy type
ANALYZE_STATEMENT, // analyze type
VARIABLE_SET_STATEMENT, // variable set statement type
CREATE_FUNC_STATEMENT, // create func statement type
EXPLAIN_STATEMENT, // explain statement type
DROP_STATEMENT, // DROP statement type
EXPORT_STATEMENT, // EXPORT statement type
PRAGMA_STATEMENT, // PRAGMA statement type
VACUUM_STATEMENT, // VACUUM statement type
CALL_STATEMENT, // CALL statement type
RELATION_STATEMENT
};
string StatementTypeToString(StatementType type);
} // namespace duckdb
struct ArrowSchema;
namespace duckdb {
enum class QueryResultType : uint8_t { MATERIALIZED_RESULT, STREAM_RESULT };
//! The QueryResult object holds the result of a query. It can either be a MaterializedQueryResult, in which case the
//! result contains the entire result set, or a StreamQueryResult in which case the Fetch method can be called to
//! incrementally fetch data from the database.
class QueryResult {
public:
//! Creates an successful empty query result
QueryResult(QueryResultType type, StatementType statement_type);
//! Creates a successful query result with the specified names and types
QueryResult(QueryResultType type, StatementType statement_type, vector<LogicalType> types, vector<string> names);
//! Creates an unsuccessful query result with error condition
QueryResult(QueryResultType type, string error);
virtual ~QueryResult() {
}
//! The type of the result (MATERIALIZED or STREAMING)
QueryResultType type;
//! The type of the statement that created this result
StatementType statement_type;
//! The SQL types of the result
vector<LogicalType> types;
//! The names of the result
vector<string> names;
//! Whether or not execution was successful
bool success;
//! The error string (in case execution was not successful)
string error;
//! The next result (if any)
unique_ptr<QueryResult> next;
public:
//! Fetches a DataChunk from the query result. Returns an empty chunk if the result is empty, or nullptr on failure.
virtual unique_ptr<DataChunk> Fetch() = 0;
// Converts the QueryResult to a string
virtual string ToString() = 0;
//! Prints the QueryResult to the console
void Print();
//! Returns true if the two results are identical; false otherwise. Note that this method is destructive; it calls
//! Fetch() until both results are exhausted. The data in the results will be lost.
bool Equals(QueryResult &other);
idx_t column_count() {
return types.size();
}
void ToArrowSchema(ArrowSchema *out_array);
private:
//! The current chunk used by the iterator
unique_ptr<DataChunk> iterator_chunk;
class QueryResultIterator;
class QueryResultRow {
public:
QueryResultRow(QueryResultIterator &iterator) : iterator(iterator), row(0) {
}
QueryResultIterator &iterator;
idx_t row;
template <class T> T GetValue(idx_t col_idx) const {
return iterator.result->iterator_chunk->GetValue(col_idx, iterator.row_idx).GetValue<T>();
}
};
//! The row-based query result iterator. Invoking the
class QueryResultIterator {
public:
QueryResultIterator(QueryResult *result) : current_row(*this), result(result), row_idx(0) {
if (result) {
result->iterator_chunk = result->Fetch();
}
}
QueryResultRow current_row;
QueryResult *result;
idx_t row_idx;
public:
void Next() {
if (!result->iterator_chunk) {
return;
}
current_row.row++;
row_idx++;
if (row_idx >= result->iterator_chunk->size()) {
result->iterator_chunk = result->Fetch();
row_idx = 0;
}
}
QueryResultIterator &operator++() {
Next();
return *this;
}
bool operator!=(const QueryResultIterator &other) const {
return result->iterator_chunk && result->iterator_chunk->column_count() > 0;
}
const QueryResultRow &operator*() const {
return current_row;
}
};
public:
QueryResultIterator begin() {
return QueryResultIterator(this);
}
QueryResultIterator end() {
return QueryResultIterator(nullptr);
}
protected:
string HeaderToString();
private:
QueryResult(const QueryResult &) = delete;
};
} // namespace duckdb
namespace duckdb {
class MaterializedQueryResult : public QueryResult {
public:
//! Creates an empty successful query result
MaterializedQueryResult(StatementType statement_type);
//! Creates a successful query result with the specified names and types
MaterializedQueryResult(StatementType statement_type, vector<LogicalType> types, vector<string> names);
//! Creates an unsuccessful query result with error condition
MaterializedQueryResult(string error);
//! Fetches a DataChunk from the query result. Returns an empty chunk if the result is empty, or nullptr on failure.
//! This will consume the result (i.e. the chunks are taken directly from the ChunkCollection).
unique_ptr<DataChunk> Fetch() override;
//! Converts the QueryResult to a string
string ToString() override;
//! Gets the (index) value of the (column index) column
Value GetValue(idx_t column, idx_t index);
template <class T> T GetValue(idx_t column, idx_t index) {
auto value = GetValue(column, index);
return (T)value.GetValue<int64_t>();
}
ChunkCollection collection;
};
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/main/stream_query_result.hpp
//
//
//===----------------------------------------------------------------------===//
namespace duckdb {
class ClientContext;
class MaterializedQueryResult;
class StreamQueryResult : public QueryResult {
public:
//! Create a successful StreamQueryResult. StreamQueryResults should always be successful initially (it makes no
//! sense to stream an error).
StreamQueryResult(StatementType statement_type, ClientContext &context, vector<LogicalType> types,
vector<string> names);
~StreamQueryResult() override;
//! Fetches a DataChunk from the query result. Returns an empty chunk if the result is empty, or nullptr on error.
unique_ptr<DataChunk> Fetch() override;
//! Converts the QueryResult to a string
string ToString() override;
//! Materializes the query result and turns it into a materialized query result
unique_ptr<MaterializedQueryResult> Materialize();
//! Closes the StreamQueryResult
void Close();
//! Whether or not the StreamQueryResult is still open
bool is_open;
private:
//! The client context this StreamQueryResult belongs to
ClientContext &context;
};
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/main/prepared_statement.hpp
//
//
//===----------------------------------------------------------------------===//
namespace duckdb {
class ClientContext;
class PreparedStatementData;
//! A prepared statement
class PreparedStatement {
public:
//! Create a successfully prepared prepared statement object with the given name
PreparedStatement(ClientContext *context, string name, string query, PreparedStatementData &data,
idx_t n_param = 0);
//! Create a prepared statement that was not successfully prepared
PreparedStatement(string error);
~PreparedStatement();
public:
StatementType type;
//! The client context this prepared statement belongs to
ClientContext *context;
//! The internal name of the prepared statement
string name;
//! The query that is being prepared
string query;
//! Whether or not the statement was successfully prepared
bool success;
//! The error message (if success = false)
string error;
//! Whether or not the prepared statement has been invalidated because the underlying connection has been destroyed
bool is_invalidated;
//! The amount of bound parameters
idx_t n_param;
//! The result SQL types of the prepared statement
vector<LogicalType> types;
//! The result names of the prepared statement
vector<string> names;
public:
//! Execute the prepared statement with the given set of arguments
template <typename... Args> unique_ptr<QueryResult> Execute(Args... args) {
vector<Value> values;
return ExecuteRecursive(values, args...);
}
//! Execute the prepared statement with the given set of values
unique_ptr<QueryResult> Execute(vector<Value> &values, bool allow_stream_result = true);
private:
unique_ptr<QueryResult> ExecuteRecursive(vector<Value> &values) {
return Execute(values);
}
template <typename T, typename... Args>
unique_ptr<QueryResult> ExecuteRecursive(vector<Value> &values, T value, Args... args) {
values.push_back(Value::CreateValue<T>(value));
return ExecuteRecursive(values, args...);
}
};
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/main/table_description.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/parser/column_definition.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/parser/parsed_expression.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/parser/base_expression.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/enums/expression_type.hpp
//
//
//===----------------------------------------------------------------------===//
namespace duckdb {
//===--------------------------------------------------------------------===//
// Predicate Expression Operation Types
//===--------------------------------------------------------------------===//
enum class ExpressionType : uint8_t {
INVALID = 0,
// explicitly cast left as right (right is integer in ValueType enum)
OPERATOR_CAST = 12,
// logical not operator
OPERATOR_NOT = 13,
// is null operator
OPERATOR_IS_NULL = 14,
// is not null operator
OPERATOR_IS_NOT_NULL = 15,
// -----------------------------
// Comparison Operators
// -----------------------------
// equal operator between left and right
COMPARE_EQUAL = 25,
// compare initial boundary
COMPARE_BOUNDARY_START = COMPARE_EQUAL,
// inequal operator between left and right
COMPARE_NOTEQUAL = 26,
// less than operator between left and right
COMPARE_LESSTHAN = 27,
// greater than operator between left and right
COMPARE_GREATERTHAN = 28,
// less than equal operator between left and right
COMPARE_LESSTHANOREQUALTO = 29,
// greater than equal operator between left and right
COMPARE_GREATERTHANOREQUALTO = 30,
// IN operator [left IN (right1, right2, ...)]
COMPARE_IN = 35,
// NOT IN operator [left NOT IN (right1, right2, ...)]
COMPARE_NOT_IN = 36,
// IS DISTINCT FROM operator
COMPARE_DISTINCT_FROM = 37,
// compare final boundary
COMPARE_BETWEEN = 38,
COMPARE_NOT_BETWEEN = 39,
COMPARE_BOUNDARY_END = COMPARE_NOT_BETWEEN,
// -----------------------------
// Conjunction Operators
// -----------------------------
CONJUNCTION_AND = 50,
CONJUNCTION_OR = 51,
// -----------------------------
// Values
// -----------------------------
VALUE_CONSTANT = 75,
VALUE_PARAMETER = 76,
VALUE_TUPLE = 77,
VALUE_TUPLE_ADDRESS = 78,
VALUE_NULL = 79,
VALUE_VECTOR = 80,
VALUE_SCALAR = 81,
VALUE_DEFAULT = 82,
// -----------------------------
// Aggregates
// -----------------------------
AGGREGATE = 100,
BOUND_AGGREGATE = 101,
// -----------------------------
// Window Functions
// -----------------------------
WINDOW_AGGREGATE = 110,
WINDOW_RANK = 120,
WINDOW_RANK_DENSE = 121,
WINDOW_NTILE = 122,
WINDOW_PERCENT_RANK = 123,
WINDOW_CUME_DIST = 124,
WINDOW_ROW_NUMBER = 125,
WINDOW_FIRST_VALUE = 130,
WINDOW_LAST_VALUE = 131,
WINDOW_LEAD = 132,
WINDOW_LAG = 133,
// -----------------------------
// Functions
// -----------------------------
FUNCTION = 140,
BOUND_FUNCTION = 141,
// -----------------------------
// Operators
// -----------------------------
CASE_EXPR = 150,
OPERATOR_NULLIF = 151,
OPERATOR_COALESCE = 152,
// -----------------------------
// Subquery IN/EXISTS
// -----------------------------
SUBQUERY = 175,
// -----------------------------
// Parser
// -----------------------------
STAR = 200,
TABLE_STAR = 201,
PLACEHOLDER = 202,
COLUMN_REF = 203,
FUNCTION_REF = 204,
TABLE_REF = 205,
// -----------------------------
// Miscellaneous
// -----------------------------
CAST = 225,
COMMON_SUBEXPRESSION = 226,
BOUND_REF = 227,
BOUND_COLUMN_REF = 228,
BOUND_UNNEST = 229,
COLLATE = 230
};
//===--------------------------------------------------------------------===//
// Expression Class
//===--------------------------------------------------------------------===//
enum class ExpressionClass : uint8_t {
INVALID = 0,
//===--------------------------------------------------------------------===//
// Parsed Expressions
//===--------------------------------------------------------------------===//
AGGREGATE = 1,
CASE = 2,
CAST = 3,
COLUMN_REF = 4,
COMPARISON = 5,
CONJUNCTION = 6,
CONSTANT = 7,
DEFAULT = 8,
FUNCTION = 9,
OPERATOR = 10,
STAR = 11,
TABLE_STAR = 12,
SUBQUERY = 13,
WINDOW = 14,
PARAMETER = 15,
COLLATE = 16,
//===--------------------------------------------------------------------===//
// Bound Expressions
//===--------------------------------------------------------------------===//
BOUND_AGGREGATE = 25,
BOUND_CASE = 26,
BOUND_CAST = 27,
BOUND_COLUMN_REF = 28,
BOUND_COMPARISON = 29,
BOUND_CONJUNCTION = 30,
BOUND_CONSTANT = 31,
BOUND_DEFAULT = 32,
BOUND_FUNCTION = 33,
BOUND_OPERATOR = 34,
BOUND_PARAMETER = 35,
BOUND_REF = 36,
BOUND_SUBQUERY = 37,
BOUND_WINDOW = 38,
BOUND_BETWEEN = 39,
BOUND_UNNEST = 40,
//===--------------------------------------------------------------------===//
// Miscellaneous
//===--------------------------------------------------------------------===//
BOUND_EXPRESSION = 50,
COMMON_SUBEXPRESSION = 51
};
string ExpressionTypeToString(ExpressionType type);
string ExpressionTypeToOperator(ExpressionType type);
//! Negate a comparison expression, turning e.g. = into !=, or < into >=
ExpressionType NegateComparisionExpression(ExpressionType type);
//! Flip a comparison expression, turning e.g. < into >, or = into =
ExpressionType FlipComparisionExpression(ExpressionType type);
} // namespace duckdb
namespace duckdb {
//! The BaseExpression class is a base class that can represent any expression
//! part of a SQL statement.
class BaseExpression {
public:
//! Create an Expression
BaseExpression(ExpressionType type, ExpressionClass expression_class)
: type(type), expression_class(expression_class) {
}
virtual ~BaseExpression() {
}
//! Returns the type of the expression
ExpressionType GetExpressionType() {
return type;
}
//! Returns the class of the expression
ExpressionClass GetExpressionClass() {
return expression_class;
}
//! Type of the expression
ExpressionType type;
//! The expression class of the node
ExpressionClass expression_class;
//! The alias of the expression,
string alias;
public:
//! Returns true if this expression is an aggregate or not.
/*!
Examples:
(1) SUM(a) + 1 -- True
(2) a + 1 -- False
*/
virtual bool IsAggregate() const = 0;
//! Returns true if the expression has a window function or not
virtual bool IsWindow() const = 0;
//! Returns true if the query contains a subquery
virtual bool HasSubquery() const = 0;
//! Returns true if expression does not contain a group ref or col ref or parameter
virtual bool IsScalar() const = 0;
//! Returns true if the expression has a parameter
virtual bool HasParameter() const = 0;
//! Get the name of the expression
virtual string GetName() const {
return !alias.empty() ? alias : ToString();
}
//! Convert the Expression to a String
virtual string ToString() const = 0;
//! Print the expression to stdout
void Print();
//! Creates a hash value of this expression. It is important that if two expressions are identical (i.e.
//! Expression::Equals() returns true), that their hash value is identical as well.
virtual hash_t Hash() const = 0;
//! Returns true if this expression is equal to another expression
virtual bool Equals(const BaseExpression *other) const;
static bool Equals(BaseExpression *left, BaseExpression *right) {
if (left == right) {
return true;
}
if (!left || !right) {
return false;
}
return left->Equals(right);
}
bool operator==(const BaseExpression &rhs) {
return this->Equals(&rhs);
}
};
} // namespace duckdb
namespace duckdb {
class Serializer;
class Deserializer;
//! The ParsedExpression class is a base class that can represent any expression
//! part of a SQL statement.
/*!
The ParsedExpression class is a base class that can represent any expression
part of a SQL statement. This is, for example, a column reference in a SELECT
clause, but also operators, aggregates or filters. The Expression is emitted by the parser and does not contain any
information about bindings to the catalog or to the types. ParsedExpressions are transformed into regular Expressions
in the Binder.
*/
class ParsedExpression : public BaseExpression {
public:
//! Create an Expression
ParsedExpression(ExpressionType type, ExpressionClass expression_class) : BaseExpression(type, expression_class) {
}
//! The location in the query (if any)
idx_t query_location = INVALID_INDEX;
public:
bool IsAggregate() const override;
bool IsWindow() const override;
bool HasSubquery() const override;
bool IsScalar() const override;
bool HasParameter() const override;
bool Equals(const BaseExpression *other) const override;
hash_t Hash() const override;
//! Create a copy of this expression
virtual unique_ptr<ParsedExpression> Copy() const = 0;
//! Serializes an Expression to a stand-alone binary blob
virtual void Serialize(Serializer &serializer);
//! Deserializes a blob back into an Expression [CAN THROW:
//! SerializationException]
static unique_ptr<ParsedExpression> Deserialize(Deserializer &source);
protected:
//! Copy base Expression properties from another expression to this one,
//! used in Copy method
void CopyProperties(const ParsedExpression &other) {
type = other.type;
expression_class = other.expression_class;
alias = other.alias;
}
};
} // namespace duckdb
namespace duckdb {
//! A column of a table.
class ColumnDefinition {
public:
ColumnDefinition(string name, LogicalType type) : name(name), type(type) {
}
ColumnDefinition(string name, LogicalType type, unique_ptr<ParsedExpression> default_value)
: name(name), type(type), default_value(move(default_value)) {
}
//! The name of the entry
string name;
//! The index of the column in the table
idx_t oid;
//! The type of the column
LogicalType type;
//! The default value of the column (if any)
unique_ptr<ParsedExpression> default_value;
public:
ColumnDefinition Copy();
void Serialize(Serializer &serializer);
static ColumnDefinition Deserialize(Deserializer &source);
};
} // namespace duckdb
namespace duckdb {
struct TableDescription {
//! The schema of the table
string schema;
//! The table name of the table
string table;
//! The columns of the table
vector<ColumnDefinition> columns;
};
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/main/relation.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/enums/relation_type.hpp
//
//
//===----------------------------------------------------------------------===//
namespace duckdb {
//===--------------------------------------------------------------------===//
// Catalog Types
//===--------------------------------------------------------------------===//
enum class RelationType : uint8_t {
INVALID_RELATION,
TABLE_RELATION,
PROJECTION_RELATION,
FILTER_RELATION,
EXPLAIN_RELATION,
CROSS_PRODUCT_RELATION,
JOIN_RELATION,
AGGREGATE_RELATION,
SET_OPERATION_RELATION,
DISTINCT_RELATION,
LIMIT_RELATION,
ORDER_RELATION,
CREATE_VIEW_RELATION,
CREATE_TABLE_RELATION,
INSERT_RELATION,
VALUE_LIST_RELATION,
DELETE_RELATION,
UPDATE_RELATION,
WRITE_CSV_RELATION,
READ_CSV_RELATION,
SUBQUERY_RELATION,
TABLE_FUNCTION_RELATION,
VIEW_RELATION
};
string RelationTypeToString(RelationType type);
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/enums/join_type.hpp
//
//
//===----------------------------------------------------------------------===//
namespace duckdb {
//===--------------------------------------------------------------------===//
// Join Types
//===--------------------------------------------------------------------===//
enum class JoinType : uint8_t {
INVALID = 0, // invalid join type
LEFT = 1, // left
RIGHT = 2, // right
INNER = 3, // inner
OUTER = 4, // outer
SEMI = 5, // SEMI join returns left side row ONLY if it has a join partner, no duplicates
ANTI = 6, // ANTI join returns left side row ONLY if it has NO join partner, no duplicates
MARK = 7, // MARK join returns marker indicating whether or not there is a join partner (true), there is no join
// partner (false)
SINGLE = 8 // SINGLE join is like LEFT OUTER JOIN, BUT returns at most one join partner per entry on the LEFT side
// (and NULL if no partner is found)
};
string JoinTypeToString(JoinType type);
} // namespace duckdb
#include <memory>
namespace duckdb {
struct BoundStatement;
class ClientContext;
class Binder;
class LogicalOperator;
class QueryNode;
class TableRef;
class Relation : public std::enable_shared_from_this<Relation> {
public:
Relation(ClientContext &context, RelationType type) : context(context), type(type) {
}
virtual ~Relation() {
}
ClientContext &context;
RelationType type;
public:
virtual const vector<ColumnDefinition> &Columns() = 0;
virtual unique_ptr<QueryNode> GetQueryNode() = 0;
virtual BoundStatement Bind(Binder &binder);
virtual string GetAlias();
unique_ptr<QueryResult> Execute();
string ToString();
virtual string ToString(idx_t depth) = 0;
void Print();
void Head(idx_t limit = 10);
shared_ptr<Relation> CreateView(string name, bool replace = true);
unique_ptr<QueryResult> Query(string sql);
unique_ptr<QueryResult> Query(string name, string sql);
//! Explain the query plan of this relation
unique_ptr<QueryResult> Explain();
virtual unique_ptr<TableRef> GetTableRef();
virtual bool IsReadOnly() {
return true;
}
public:
// PROJECT
shared_ptr<Relation> Project(string select_list);
shared_ptr<Relation> Project(string expression, string alias);
shared_ptr<Relation> Project(string select_list, vector<string> aliases);
shared_ptr<Relation> Project(vector<string> expressions);
shared_ptr<Relation> Project(vector<string> expressions, vector<string> aliases);
// FILTER
shared_ptr<Relation> Filter(string expression);
shared_ptr<Relation> Filter(vector<string> expressions);
// LIMIT
shared_ptr<Relation> Limit(int64_t n, int64_t offset = 0);
// ORDER
shared_ptr<Relation> Order(string expression);
shared_ptr<Relation> Order(vector<string> expressions);
// JOIN operation
shared_ptr<Relation> Join(shared_ptr<Relation> other, string condition, JoinType type = JoinType::INNER);
// SET operations
shared_ptr<Relation> Union(shared_ptr<Relation> other);
shared_ptr<Relation> Except(shared_ptr<Relation> other);
shared_ptr<Relation> Intersect(shared_ptr<Relation> other);
// DISTINCT operation
shared_ptr<Relation> Distinct();
// AGGREGATES
shared_ptr<Relation> Aggregate(string aggregate_list);
shared_ptr<Relation> Aggregate(vector<string> aggregates);
shared_ptr<Relation> Aggregate(string aggregate_list, string group_list);
shared_ptr<Relation> Aggregate(vector<string> aggregates, vector<string> groups);
// ALIAS
shared_ptr<Relation> Alias(string alias);
//! Insert the data from this relation into a table
void Insert(string table_name);
void Insert(string schema_name, string table_name);
//! Insert a row (i.e.,list of values) into a table
void Insert(vector<vector<Value>> values);
//! Create a table and insert the data from this relation into that table
void Create(string table_name);
void Create(string schema_name, string table_name);
//! Write a relation to a CSV file
void WriteCSV(string csv_file);
//! Update a table, can only be used on a TableRelation
virtual void Update(string update, string condition = string());
//! Delete from a table, can only be used on a TableRelation
virtual void Delete(string condition = string());
public:
//! Whether or not the relation inherits column bindings from its child or not, only relevant for binding
virtual bool InheritsColumnBindings() {
return false;
}
virtual Relation *ChildRelation() {
return nullptr;
}
protected:
string RenderWhitespace(idx_t depth);
};
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/enums/profiler_format.hpp
//
//
//===----------------------------------------------------------------------===//
namespace duckdb {
enum class ProfilerPrintFormat : uint8_t { NONE, QUERY_TREE, JSON, QUERY_TREE_OPTIMIZER };
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/parser/sql_statement.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/printer.hpp
//
//
//===----------------------------------------------------------------------===//
namespace duckdb {
//! Printer is a static class that allows printing to logs or stdout/stderr
class Printer {
public:
//! Print the object to stderr
static void Print(string str);
};
} // namespace duckdb
namespace duckdb {
//! SQLStatement is the base class of any type of SQL statement.
class SQLStatement {
public:
SQLStatement(StatementType type) : type(type){};
virtual ~SQLStatement() {
}
StatementType type;
idx_t stmt_location;
idx_t stmt_length;
string query;
};
} // namespace duckdb
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/function/udf_function.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/function/scalar_function.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/vector_operations/binary_executor.hpp
//
//
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/common/vector_operations/vector_operations.hpp
//
//
//===----------------------------------------------------------------------===//
#include <functional>
namespace duckdb {
// VectorOperations contains a set of operations that operate on sets of
// vectors. In general, the operators must all have the same type, otherwise an
// exception is thrown. Note that the functions underneath use restrict
// pointers, hence the data that the vectors point to (and hence the vector
// themselves) should not be equal! For example, if you call the function Add(A,
// B, A) then ASSERT_RESTRICT will be triggered. Instead call AddInPlace(A, B)
// or Add(A, B, C)
struct VectorOperations {
//===--------------------------------------------------------------------===//
// In-Place Operators
//===--------------------------------------------------------------------===//
//! A += B
static void AddInPlace(Vector &A, int64_t B, idx_t count);
//===--------------------------------------------------------------------===//
// NULL Operators
//===--------------------------------------------------------------------===//
//! result = IS NOT NULL(A)
static void IsNotNull(Vector &A, Vector &result, idx_t count);
//! result = IS NULL (A)
static void IsNull(Vector &A, Vector &result, idx_t count);
// Returns whether or not a vector has a NULL value
static bool HasNull(Vector &A, idx_t count);
static bool HasNotNull(Vector &A, idx_t count);
//===--------------------------------------------------------------------===//
// Boolean Operations
//===--------------------------------------------------------------------===//
// result = A && B
static void And(Vector &A, Vector &B, Vector &result, idx_t count);
// result = A || B
static void Or(Vector &A, Vector &B, Vector &result, idx_t count);
// result = NOT(A)
static void Not(Vector &A, Vector &result, idx_t count);
//===--------------------------------------------------------------------===//
// Comparison Operations
//===--------------------------------------------------------------------===//
// result = A == B
static void Equals(Vector &A, Vector &B, Vector &result, idx_t count);
// result = A != B
static void NotEquals(Vector &A, Vector &B, Vector &result, idx_t count);
// result = A > B
static void GreaterThan(Vector &A, Vector &B, Vector &result, idx_t count);
// result = A >= B
static void GreaterThanEquals(Vector &A, Vector &B, Vector &result, idx_t count);
// result = A < B
static void LessThan(Vector &A, Vector &B, Vector &result, idx_t count);
// result = A <= B
static void LessThanEquals(Vector &A, Vector &B, Vector &result, idx_t count);
//===--------------------------------------------------------------------===//
// Scatter methods
//===--------------------------------------------------------------------===//
// make sure dest.count is set for gather methods!
struct Gather {
//! dest.data[i] = ptr[i]. NullValue<T> is checked for and converted to the nullmask in dest. The source
//! addresses are incremented by the size of the type.
static void Set(Vector &source, Vector &dest, idx_t count);
};
//===--------------------------------------------------------------------===//
// Hash functions
//===--------------------------------------------------------------------===//
// result = HASH(A)
static void Hash(Vector &input, Vector &hashes, idx_t count);
static void Hash(Vector &input, Vector &hashes, const SelectionVector &rsel, idx_t count);
// A ^= HASH(B)
static void CombineHash(Vector &hashes, Vector &B, idx_t count);
static void CombineHash(Vector &hashes, Vector &B, const SelectionVector &rsel, idx_t count);
//===--------------------------------------------------------------------===//
// Generate functions
//===--------------------------------------------------------------------===//
static void GenerateSequence(Vector &result, idx_t count, int64_t start = 0, int64_t increment = 1);
static void GenerateSequence(Vector &result, idx_t count, const SelectionVector &sel, int64_t start = 0,
int64_t increment = 1);
//===--------------------------------------------------------------------===//
// Helpers
//===--------------------------------------------------------------------===//
// Cast the data from the source type to the target type
static void Cast(Vector &source, Vector &result, idx_t count, bool strict = false);
// Copy the data of <source> to the target vector
static void Copy(Vector &source, Vector &target, idx_t source_count, idx_t source_offset, idx_t target_offset);
static void Copy(Vector &source, Vector &target, const SelectionVector &sel, idx_t source_count,
idx_t source_offset, idx_t target_offset);
// Copy the data of <source> to the target location, setting null values to
// NullValue<T>. Used to store data without separate NULL mask.
static void WriteToStorage(Vector &source, idx_t count, data_ptr_t target);
// Reads the data of <source> to the target vector, setting the nullmask
// for any NullValue<T> of source. Used to go back from storage to a proper vector
static void ReadFromStorage(data_ptr_t source, idx_t count, Vector &result);
};
} // namespace duckdb
#include <functional>
namespace duckdb {
struct DefaultNullCheckOperator {
template <class LEFT_TYPE, class RIGHT_TYPE> static inline bool Operation(LEFT_TYPE left, RIGHT_TYPE right) {
return false;
}
};
struct BinaryStandardOperatorWrapper {
template <class FUNC, class OP, class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE>
static inline RESULT_TYPE Operation(FUNC fun, LEFT_TYPE left, RIGHT_TYPE right, nullmask_t &nullmask, idx_t idx) {
return OP::template Operation<LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE>(left, right);
}
};
struct BinarySingleArgumentOperatorWrapper {
template <class FUNC, class OP, class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE>
static inline RESULT_TYPE Operation(FUNC fun, LEFT_TYPE left, RIGHT_TYPE right, nullmask_t &nullmask, idx_t idx) {
return OP::template Operation<LEFT_TYPE>(left, right);
}
};
struct BinaryLambdaWrapper {
template <class FUNC, class OP, class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE>
static inline RESULT_TYPE Operation(FUNC fun, LEFT_TYPE left, RIGHT_TYPE right, nullmask_t &nullmask, idx_t idx) {
return fun(left, right);
}
};
struct BinaryExecutor {
template <class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE, class OPWRAPPER, class OP, class FUNC,
bool IGNORE_NULL, bool LEFT_CONSTANT, bool RIGHT_CONSTANT>
static void ExecuteFlatLoop(LEFT_TYPE *__restrict ldata, RIGHT_TYPE *__restrict rdata,
RESULT_TYPE *__restrict result_data, idx_t count, nullmask_t &nullmask, FUNC fun) {
if (!LEFT_CONSTANT) {
ASSERT_RESTRICT(ldata, ldata + count, result_data, result_data + count);
}
if (!RIGHT_CONSTANT) {
ASSERT_RESTRICT(rdata, rdata + count, result_data, result_data + count);
}
if (
#ifdef DUCKDB_ALLOW_UNDEFINED
IGNORE_NULL &&
#endif
nullmask.any()) {
for (idx_t i = 0; i < count; i++) {
if (!nullmask[i]) {
auto lentry = ldata[LEFT_CONSTANT ? 0 : i];
auto rentry = rdata[RIGHT_CONSTANT ? 0 : i];
result_data[i] = OPWRAPPER::template Operation<FUNC, OP, LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE>(
fun, lentry, rentry, nullmask, i);
}
}
} else {
for (idx_t i = 0; i < count; i++) {
auto lentry = ldata[LEFT_CONSTANT ? 0 : i];
auto rentry = rdata[RIGHT_CONSTANT ? 0 : i];
result_data[i] = OPWRAPPER::template Operation<FUNC, OP, LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE>(
fun, lentry, rentry, nullmask, i);
}
}
}
template <class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE, class OPWRAPPER, class OP, class FUNC,
bool IGNORE_NULL>
static void ExecuteConstant(Vector &left, Vector &right, Vector &result, FUNC fun) {
result.vector_type = VectorType::CONSTANT_VECTOR;
auto ldata = ConstantVector::GetData<LEFT_TYPE>(left);
auto rdata = ConstantVector::GetData<RIGHT_TYPE>(right);
auto result_data = ConstantVector::GetData<RESULT_TYPE>(result);
if (ConstantVector::IsNull(left) || ConstantVector::IsNull(right)) {
ConstantVector::SetNull(result, true);
return;
}
*result_data = OPWRAPPER::template Operation<FUNC, OP, LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE>(
fun, *ldata, *rdata, ConstantVector::Nullmask(result), 0);
}
template <class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE, class OPWRAPPER, class OP, class FUNC,
bool IGNORE_NULL, bool LEFT_CONSTANT, bool RIGHT_CONSTANT>
static void ExecuteFlat(Vector &left, Vector &right, Vector &result, idx_t count, FUNC fun) {
auto ldata = FlatVector::GetData<LEFT_TYPE>(left);
auto rdata = FlatVector::GetData<RIGHT_TYPE>(right);
if ((LEFT_CONSTANT && ConstantVector::IsNull(left)) || (RIGHT_CONSTANT && ConstantVector::IsNull(right))) {
// either left or right is constant NULL: result is constant NULL
result.vector_type = VectorType::CONSTANT_VECTOR;
ConstantVector::SetNull(result, true);
return;
}
result.vector_type = VectorType::FLAT_VECTOR;
auto result_data = FlatVector::GetData<RESULT_TYPE>(result);
if (LEFT_CONSTANT) {
FlatVector::SetNullmask(result, FlatVector::Nullmask(right));
} else if (RIGHT_CONSTANT) {
FlatVector::SetNullmask(result, FlatVector::Nullmask(left));
} else {