#pragma once
#define DUCKDB_AMALGAMATION 1
#define DUCKDB_SOURCE_ID "71f1c7a7e"
#define DUCKDB_VERSION "0.2.9-dev462"
#include <memory>
#include <cstdint>
#include <string>
#include <sstream>
namespace duckdb {
using std::string;
}
namespace duckdb {
using std::move;
using std::shared_ptr;
using std::unique_ptr;
using std::weak_ptr;
using data_ptr = unique_ptr<char[]>;
using std::make_shared;
#define DEFAULT_SCHEMA "main"
#define TEMP_SCHEMA "temp"
#define INVALID_SCHEMA ""
typedef uint64_t idx_t;
typedef int64_t row_t;
typedef uint64_t hash_t;
extern const idx_t INVALID_INDEX;
typedef uint8_t data_t;
typedef data_t *data_ptr_t;
typedef const data_t *const_data_ptr_t;
typedef uint32_t sel_t;
typedef idx_t transaction_t;
typedef idx_t column_t;
extern const column_t COLUMN_IDENTIFIER_ROW_ID;
extern const row_t MAX_ROW_ID;
extern const transaction_t TRANSACTION_ID_START;
extern const transaction_t MAX_TRANSACTION_ID;
extern const transaction_t MAXIMUM_QUERY_ID;
extern const transaction_t NOT_DELETED_ID;
extern const double PI;
struct Storage {
constexpr static int SECTOR_SIZE = 4096;
constexpr static int BLOCK_HEADER_SIZE = sizeof(uint64_t);
constexpr static int BLOCK_ALLOC_SIZE = 262144;
constexpr static int BLOCK_SIZE = BLOCK_ALLOC_SIZE - BLOCK_HEADER_SIZE;
constexpr static int FILE_HEADER_SIZE = 4096;
};
uint64_t NextPowerOfTwo(uint64_t v);
}
namespace duckdb {
enum class ProfilerPrintFormat : uint8_t { NONE, QUERY_TREE, JSON, QUERY_TREE_OPTIMIZER };
}
#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
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()));
}
struct SharedConstructor {
template <class T, typename... ARGS>
static shared_ptr<T> Create(ARGS &&...args) {
return make_shared<T>(std::forward<ARGS>(args)...);
}
};
struct UniqueConstructor {
template <class T, typename... ARGS>
static unique_ptr<T> Create(ARGS &&...args) {
return make_unique<T>(std::forward<ARGS>(args)...);
}
};
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>
T AbsValue(T a) {
return a < 0 ? -a : a;
}
template<class T, T val=8>
static inline T AlignValue(T n) {
return ((n + (val - 1)) / val) * val;
}
template<class T, T val=8>
static inline bool ValueIsAligned(T n) {
return (n % val) == 0;
}
template <typename T>
T SignValue(T a) {
return a < 0 ? -1 : 1;
}
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));
}
template<class T>
void AssignSharedPointer(shared_ptr<T> &target, const shared_ptr<T> &source) {
if (target.get() != source.get()) {
target = source;
}
}
}
#if (defined(DUCKDB_USE_STANDARD_ASSERT) || !defined(DEBUG)) && !defined(DUCKDB_FORCE_ASSERT)
#include <assert.h>
#define D_ASSERT assert
#else
namespace duckdb {
void DuckDBAssertInternal(bool condition, const char *condition_name, const char *file, int linenr);
}
#define D_ASSERT(condition) duckdb::DuckDBAssertInternal(bool(condition), #condition, __FILE__, __LINE__)
#endif
class RefCounter {
public:
uint32_t pn;
RefCounter() : pn(1) {
}
void inc() {
++pn;
}
void dec() {
--pn;
}
uint32_t getPn() const {
return pn;
}
virtual ~RefCounter() {
}
};
namespace duckdb {
template <typename T>
class single_thread_ptr {
public:
T *ptr; RefCounter *ref_count;
public:
constexpr single_thread_ptr() : ptr(nullptr), ref_count(nullptr) {
}
constexpr single_thread_ptr(std::nullptr_t) : ptr(nullptr), ref_count(nullptr) {
}
single_thread_ptr(RefCounter *r, T *p) {
ptr = p;
ref_count = r;
}
template <class U>
single_thread_ptr(RefCounter *r, U *p) {
ptr = p;
ref_count = r;
}
single_thread_ptr(const single_thread_ptr &sp) : ptr(nullptr), ref_count(nullptr) {
if (sp.ptr) {
ptr = sp.ptr;
ref_count = sp.ref_count;
ref_count->inc();
}
}
template <typename U>
single_thread_ptr(const single_thread_ptr<U> &sp) : ptr(nullptr), ref_count(nullptr) {
if (sp.ptr) {
ptr = sp.ptr;
ref_count = sp.ref_count;
ref_count->inc();
}
}
single_thread_ptr(single_thread_ptr &&sp) noexcept : ptr {sp.ptr}, ref_count {sp.ref_count} {
sp.ptr = nullptr;
sp.ref_count = nullptr;
}
template <class U>
single_thread_ptr(single_thread_ptr<U> &&sp) noexcept : ptr {sp.ptr}, ref_count {sp.ref_count} {
sp.ptr = nullptr;
sp.ref_count = nullptr;
}
~single_thread_ptr() {
release();
}
void release() {
if (ptr && ref_count) {
ref_count->dec();
if ((ref_count->getPn()) == 0) {
delete ref_count;
}
}
ref_count = nullptr;
ptr = nullptr;
}
single_thread_ptr &operator=(single_thread_ptr sp) noexcept {
std::swap(this->ptr, sp.ptr);
std::swap(this->ref_count, sp.ref_count);
return *this;
}
T &operator*() const noexcept {
return *ptr;
}
T *operator->() const noexcept {
return ptr;
}
T *get() const noexcept {
return ptr;
}
long use_count() const noexcept {
if (ptr)
return ref_count->getPn();
else
return 0;
}
explicit operator bool() const noexcept {
return (ptr);
}
void reset() noexcept {
release();
}
};
template <class T>
struct _object_and_block : public RefCounter {
T object;
template <class... Args>
explicit _object_and_block(Args &&... args) : object(std::forward<Args>(args)...) {
}
};
template <typename T, typename U>
inline bool operator==(const single_thread_ptr<T> &sp1, const single_thread_ptr<U> &sp2) {
return sp1.get() == sp2.get();
}
template <typename T>
inline bool operator==(const single_thread_ptr<T> &sp, std::nullptr_t) noexcept {
return !sp;
}
template <typename T, typename U>
inline bool operator!=(const single_thread_ptr<T> &sp1, const single_thread_ptr<U> &sp2) {
return sp1.get() != sp2.get();
}
template <typename T>
inline bool operator!=(const single_thread_ptr<T> &sp, std::nullptr_t) noexcept {
return sp.get();
}
template <typename T>
inline bool operator!=(std::nullptr_t, const single_thread_ptr<T> &sp) noexcept {
return sp.get();
}
template <class T, class... Args>
single_thread_ptr<T> single_thread_make_shared(Args &&... args) {
auto tmp_object = new _object_and_block<T>(std::forward<Args>(args)...);
return single_thread_ptr<T>(tmp_object, &(tmp_object->object));
}
}
#include <vector>
namespace duckdb {
using std::vector;
}
#ifndef DUCKDB_API
#ifdef _WIN32
#if defined(DUCKDB_BUILD_LIBRARY) && !defined(DUCKDB_BUILD_LOADABLE_EXTENSION)
#define DUCKDB_API __declspec(dllexport)
#else
#define DUCKDB_API __declspec(dllimport)
#endif
#else
#define DUCKDB_API
#endif
#endif
#ifdef DUCKDB_BUILD_LOADABLE_EXTENSION
#ifdef _WIN32
#define DUCKDB_EXTENSION_API __declspec(dllexport)
#else
#define DUCKDB_EXTENSION_API
#endif
#endif
namespace duckdb {
class Serializer;
class Deserializer;
struct date_t {
int32_t days;
date_t() = default;
explicit inline date_t(int32_t days_p) : days(days_p) {}
explicit inline operator int32_t() const {return days;}
inline bool operator==(const date_t &rhs) const {return days == rhs.days;};
inline bool operator!=(const date_t &rhs) const {return days != rhs.days;};
inline bool operator<=(const date_t &rhs) const {return days <= rhs.days;};
inline bool operator<(const date_t &rhs) const {return days < rhs.days;};
inline bool operator>(const date_t &rhs) const {return days > rhs.days;};
inline bool operator>=(const date_t &rhs) const {return days >= rhs.days;};
inline date_t operator+(const int32_t &days) const {return date_t(this->days + days);};
inline date_t operator-(const int32_t &days) const {return date_t(this->days - days);};
inline date_t &operator+=(const int32_t &days) {this->days += days; return *this;};
inline date_t &operator-=(const int32_t &days) {this->days -= days; return *this;};
};
struct dtime_t {
int64_t micros;
dtime_t() = default;
explicit inline dtime_t(int64_t micros_p) : micros(micros_p) {}
inline dtime_t& operator=(int64_t micros_p) {micros = micros_p; return *this;}
explicit inline operator int64_t() const {return micros;}
explicit inline operator double() const {return micros;}
inline bool operator==(const dtime_t &rhs) const {return micros == rhs.micros;};
inline bool operator!=(const dtime_t &rhs) const {return micros != rhs.micros;};
inline bool operator<=(const dtime_t &rhs) const {return micros <= rhs.micros;};
inline bool operator<(const dtime_t &rhs) const {return micros < rhs.micros;};
inline bool operator>(const dtime_t &rhs) const {return micros > rhs.micros;};
inline bool operator>=(const dtime_t &rhs) const {return micros >= rhs.micros;};
inline dtime_t operator+(const int64_t µs) const {return dtime_t(this->micros + micros);};
inline dtime_t operator+(const double µs) const {return dtime_t(this->micros + int64_t(micros));};
inline dtime_t operator-(const int64_t µs) const {return dtime_t(this->micros - micros);};
inline dtime_t operator*(const idx_t &copies) const {return dtime_t(this->micros * copies);};
inline dtime_t operator/(const idx_t &copies) const {return dtime_t(this->micros / copies);};
inline int64_t operator-(const dtime_t &other) const {return this->micros - other.micros;};
inline dtime_t &operator+=(const int64_t µs) {this->micros += micros; return *this;};
inline dtime_t &operator-=(const int64_t µs) {this->micros -= micros; return *this;};
inline dtime_t &operator+=(const dtime_t &other) {this->micros += other.micros; return *this;};
};
struct timestamp_t {
int64_t value;
timestamp_t() = default;
explicit inline timestamp_t(int64_t value_p) : value(value_p) {}
inline timestamp_t& operator=(int64_t value_p) {value = value_p; return *this;}
explicit inline operator int64_t() const {return value;}
inline bool operator==(const timestamp_t &rhs) const {return value == rhs.value;};
inline bool operator!=(const timestamp_t &rhs) const {return value != rhs.value;};
inline bool operator<=(const timestamp_t &rhs) const {return value <= rhs.value;};
inline bool operator<(const timestamp_t &rhs) const {return value < rhs.value;};
inline bool operator>(const timestamp_t &rhs) const {return value > rhs.value;};
inline bool operator>=(const timestamp_t &rhs) const {return value >= rhs.value;};
inline timestamp_t operator+(const double &value) const {return timestamp_t(this->value + int64_t(value));};
inline int64_t operator-(const timestamp_t &other) const {return this->value - other.value;};
inline timestamp_t &operator+=(const int64_t &value) {this->value += value; return *this;};
inline timestamp_t &operator-=(const int64_t &value) {this->value -= value; return *this;};
};
struct interval_t {
int32_t months;
int32_t days;
int64_t micros;
inline bool operator==(const interval_t &rhs) const {
return this->days == rhs.days && this->months == rhs.months && this->micros == rhs.micros;
}
};
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;
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;
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;
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;
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 = shared_ptr<T>;
template <class T, typename... Args>
buffer_ptr<T> make_buffer(Args &&...args) {
return 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;
};
enum class PhysicalType : uint8_t {
NA = 0,
BOOL = 1,
UINT8 = 2,
INT8 = 3,
UINT16 = 4,
INT16 = 5,
UINT32 = 6,
INT32 = 7,
UINT64 = 8,
INT64 = 9,
HALF_FLOAT = 10,
FLOAT = 11,
DOUBLE = 12,
STRING = 13,
BINARY = 14,
FIXED_SIZE_BINARY = 15,
DATE32 = 16,
DATE64 = 17,
TIMESTAMP = 18,
TIME32 = 19,
TIME64 = 20,
INTERVAL = 21,
LIST = 23,
STRUCT = 24,
UNION = 25,
DICTIONARY = 26,
MAP = 27,
EXTENSION = 28,
FIXED_SIZE_LIST = 29,
DURATION = 30,
LARGE_STRING = 31,
LARGE_BINARY = 32,
LARGE_LIST = 33,
VARCHAR = 200, INT128 = 204,
BIT = 205,
INVALID = 255
};
enum class LogicalTypeId : uint8_t {
INVALID = 0,
SQLNULL = 1,
UNKNOWN = 2,
ANY = 3,
BOOLEAN = 10,
TINYINT = 11,
SMALLINT = 12,
INTEGER = 13,
BIGINT = 14,
DATE = 15,
TIME = 16,
TIMESTAMP_SEC = 17,
TIMESTAMP_MS = 18,
TIMESTAMP = 19, TIMESTAMP_NS = 20,
DECIMAL = 21,
FLOAT = 22,
DOUBLE = 23,
CHAR = 24,
VARCHAR = 25,
BLOB = 26,
INTERVAL = 27,
UTINYINT = 28,
USMALLINT = 29,
UINTEGER = 30,
UBIGINT = 31,
HUGEINT = 50,
POINTER = 51,
HASH = 52,
VALIDITY = 53,
STRUCT = 100,
LIST = 101,
MAP = 102,
TABLE = 103
};
struct ExtraTypeInfo;
struct LogicalType {
DUCKDB_API LogicalType();
DUCKDB_API LogicalType(LogicalTypeId id); DUCKDB_API LogicalType(LogicalTypeId id, shared_ptr<ExtraTypeInfo> type_info);
DUCKDB_API LogicalType(const LogicalType &other) :
id_(other.id_), physical_type_(other.physical_type_), type_info_(other.type_info_) {}
DUCKDB_API LogicalType(LogicalType &&other) :
id_(other.id_), physical_type_(other.physical_type_), type_info_(move(other.type_info_)) {}
DUCKDB_API ~LogicalType();
LogicalTypeId id() const {
return id_;
}
PhysicalType InternalType() const {
return physical_type_;
}
const ExtraTypeInfo *AuxInfo() const {
return type_info_.get();
}
LogicalType& operator=(const LogicalType &other) {
id_ = other.id_;
physical_type_ = other.physical_type_;
type_info_ = other.type_info_;
return *this;
}
LogicalType& operator=(LogicalType&& other) {
id_ = other.id_;
physical_type_ = other.physical_type_;
type_info_ = move(other.type_info_);
return *this;
}
bool operator==(const LogicalType &rhs) const;
bool operator!=(const LogicalType &rhs) const {
return !(*this == rhs);
}
DUCKDB_API void Serialize(Serializer &serializer) const;
DUCKDB_API static LogicalType Deserialize(Deserializer &source);
DUCKDB_API string ToString() const;
DUCKDB_API bool IsIntegral() const;
DUCKDB_API bool IsNumeric() const;
DUCKDB_API hash_t Hash() const;
DUCKDB_API static LogicalType MaxLogicalType(const LogicalType &left, const LogicalType &right);
DUCKDB_API bool GetDecimalProperties(uint8_t &width, uint8_t &scale) const;
DUCKDB_API void Verify() const;
private:
LogicalTypeId id_;
PhysicalType physical_type_;
shared_ptr<ExtraTypeInfo> type_info_;
private:
PhysicalType GetInternalType();
public:
DUCKDB_API static const LogicalType SQLNULL;
DUCKDB_API static const LogicalType BOOLEAN;
DUCKDB_API static const LogicalType TINYINT;
DUCKDB_API static const LogicalType UTINYINT;
DUCKDB_API static const LogicalType SMALLINT;
DUCKDB_API static const LogicalType USMALLINT;
DUCKDB_API static const LogicalType INTEGER;
DUCKDB_API static const LogicalType UINTEGER;
DUCKDB_API static const LogicalType BIGINT;
DUCKDB_API static const LogicalType UBIGINT;
DUCKDB_API static const LogicalType FLOAT;
DUCKDB_API static const LogicalType DOUBLE;
DUCKDB_API static const LogicalType DATE;
DUCKDB_API static const LogicalType TIMESTAMP;
DUCKDB_API static const LogicalType TIMESTAMP_S;
DUCKDB_API static const LogicalType TIMESTAMP_MS;
DUCKDB_API static const LogicalType TIMESTAMP_NS;
DUCKDB_API static const LogicalType TIME;
DUCKDB_API static const LogicalType VARCHAR;
DUCKDB_API static const LogicalType ANY;
DUCKDB_API static const LogicalType BLOB;
DUCKDB_API static const LogicalType INTERVAL;
DUCKDB_API static const LogicalType HUGEINT;
DUCKDB_API static const LogicalType HASH;
DUCKDB_API static const LogicalType POINTER;
DUCKDB_API static const LogicalType TABLE;
DUCKDB_API static const LogicalType INVALID;
DUCKDB_API static LogicalType DECIMAL(int width, int scale); DUCKDB_API static LogicalType VARCHAR_COLLATION(string collation); DUCKDB_API static LogicalType LIST(LogicalType child); DUCKDB_API static LogicalType STRUCT(child_list_t<LogicalType> children); DUCKDB_API static LogicalType MAP(child_list_t<LogicalType> children);
DUCKDB_API static const vector<LogicalType> NUMERIC;
DUCKDB_API static const vector<LogicalType> INTEGRAL;
DUCKDB_API static const vector<LogicalType> ALL_TYPES;
};
struct DecimalType {
DUCKDB_API static uint8_t GetWidth(const LogicalType &type);
DUCKDB_API static uint8_t GetScale(const LogicalType &type);
};
struct StringType {
DUCKDB_API static string GetCollation(const LogicalType &type);
};
struct ListType {
DUCKDB_API static const LogicalType &GetChildType(const LogicalType &type);
};
struct StructType {
DUCKDB_API static const child_list_t<LogicalType> &GetChildTypes(const LogicalType &type);
DUCKDB_API static const LogicalType &GetChildType(const LogicalType &type, idx_t index);
DUCKDB_API static const string &GetChildName(const LogicalType &type, idx_t index);
DUCKDB_API static idx_t GetChildCount(const LogicalType &type);
};
string LogicalTypeIdToString(LogicalTypeId type);
LogicalTypeId TransformStringToLogicalType(const string &str);
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, uint8_t>()) {
return PhysicalType::UINT8;
} else if (std::is_same<T, uint16_t>()) {
return PhysicalType::UINT16;
} else if (std::is_same<T, uint32_t>()) {
return PhysicalType::UINT32;
} else if (std::is_same<T, uint64_t>()) {
return PhysicalType::UINT64;
} else if (std::is_same<T, hugeint_t>()) {
return PhysicalType::INT128;
} else if (std::is_same<T, date_t>()) {
return PhysicalType::DATE32;
} else if (std::is_same<T, dtime_t>()) {
return PhysicalType::TIME32;
} else if (std::is_same<T, timestamp_t>()) {
return PhysicalType::TIMESTAMP;
} 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 *>() || std::is_same<T, string_t>()) {
return PhysicalType::VARCHAR;
} else if (std::is_same<T, interval_t>()) {
return PhysicalType::INTERVAL;
} else {
return PhysicalType::INVALID;
}
}
template<class T>
bool TypeIsNumber() {
return std::is_integral<T>() || std::is_floating_point<T>() || std::is_same<T, hugeint_t>();
}
template <class T>
bool IsValidType() {
return GetTypeId<T>() != PhysicalType::INVALID;
}
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 {
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(move(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(const 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);
}
#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) {
#ifdef DEBUG
if (!(left_end <= right_start || right_end <= left_start)) {
printf("ASSERT RESTRICT FAILED: %s:%d\n", fname, linenr);
D_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__)
enum class ExceptionType {
INVALID = 0, OUT_OF_RANGE = 1, CONVERSION = 2, UNKNOWN_TYPE = 3, DECIMAL = 4, MISMATCH_TYPE = 5, DIVIDE_BY_ZERO = 6, OBJECT_SIZE = 7, INVALID_TYPE = 8, SERIALIZATION = 9, TRANSACTION = 10, NOT_IMPLEMENTED = 11, EXPRESSION = 12, CATALOG = 13, PARSER = 14, PLANNER = 15, SCHEDULER = 16, EXECUTOR = 17, CONSTRAINT = 18, INDEX = 19, STAT = 20, CONNECTION = 21, SYNTAX = 22, SETTINGS = 23, BINDER = 24, NETWORK = 25, OPTIMIZER = 26, NULL_POINTER = 27, IO = 28, INTERRUPT = 29, FATAL = 30, INTERNAL =
31, INVALID_INPUT = 32, OUT_OF_MEMORY = 33 };
class Exception : public std::exception {
public:
explicit Exception(const string &msg);
Exception(ExceptionType exception_type, const string &message);
ExceptionType type;
public:
const char *what() const noexcept override;
string ExceptionTypeToString(ExceptionType type);
template <typename... Args>
static string ConstructMessage(const string &msg, Args... params) {
vector<ExceptionFormatValue> values;
return ConstructMessageRecursive(msg, values, params...);
}
static string ConstructMessageRecursive(const string &msg, vector<ExceptionFormatValue> &values);
template <class T, typename... Args>
static string ConstructMessageRecursive(const 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_;
};
class StandardException : public Exception {
public:
StandardException(ExceptionType exception_type, string message) : Exception(exception_type, message) {
}
};
class CatalogException : public StandardException {
public:
explicit CatalogException(const string &msg);
template <typename... Args>
explicit CatalogException(const string &msg, Args... params) : CatalogException(ConstructMessage(msg, params...)) {
}
};
class ParserException : public StandardException {
public:
explicit ParserException(const string &msg);
template <typename... Args>
explicit ParserException(const string &msg, Args... params) : ParserException(ConstructMessage(msg, params...)) {
}
};
class BinderException : public StandardException {
public:
explicit BinderException(const string &msg);
template <typename... Args>
explicit BinderException(const string &msg, Args... params) : BinderException(ConstructMessage(msg, params...)) {
}
};
class ConversionException : public Exception {
public:
explicit ConversionException(const string &msg);
template <typename... Args>
explicit ConversionException(const string &msg, Args... params)
: ConversionException(ConstructMessage(msg, params...)) {
}
};
class TransactionException : public Exception {
public:
explicit TransactionException(const string &msg);
template <typename... Args>
explicit TransactionException(const string &msg, Args... params)
: TransactionException(ConstructMessage(msg, params...)) {
}
};
class NotImplementedException : public Exception {
public:
explicit NotImplementedException(const string &msg);
template <typename... Args>
explicit NotImplementedException(const string &msg, Args... params)
: NotImplementedException(ConstructMessage(msg, params...)) {
}
};
class OutOfRangeException : public Exception {
public:
explicit OutOfRangeException(const string &msg);
template <typename... Args>
explicit OutOfRangeException(const string &msg, Args... params)
: OutOfRangeException(ConstructMessage(msg, params...)) {
}
};
class OutOfMemoryException : public Exception {
public:
explicit OutOfMemoryException(const string &msg);
template <typename... Args>
explicit OutOfMemoryException(const string &msg, Args... params)
: OutOfMemoryException(ConstructMessage(msg, params...)) {
}
};
class SyntaxException : public Exception {
public:
explicit SyntaxException(const string &msg);
template <typename... Args>
explicit SyntaxException(const string &msg, Args... params) : SyntaxException(ConstructMessage(msg, params...)) {
}
};
class ConstraintException : public Exception {
public:
explicit ConstraintException(const string &msg);
template <typename... Args>
explicit ConstraintException(const string &msg, Args... params)
: ConstraintException(ConstructMessage(msg, params...)) {
}
};
class IOException : public Exception {
public:
explicit IOException(const string &msg);
template <typename... Args>
explicit IOException(const string &msg, Args... params) : IOException(ConstructMessage(msg, params...)) {
}
};
class SerializationException : public Exception {
public:
explicit SerializationException(const string &msg);
template <typename... Args>
explicit SerializationException(const string &msg, Args... params)
: SerializationException(ConstructMessage(msg, params...)) {
}
};
class SequenceException : public Exception {
public:
explicit SequenceException(const string &msg);
template <typename... Args>
explicit SequenceException(const string &msg, Args... params)
: SequenceException(ConstructMessage(msg, params...)) {
}
};
class InterruptException : public Exception {
public:
InterruptException();
};
class FatalException : public Exception {
public:
explicit FatalException(const string &msg);
template <typename... Args>
explicit FatalException(const string &msg, Args... params) : FatalException(ConstructMessage(msg, params...)) {
}
};
class InternalException : public Exception {
public:
explicit InternalException(const string &msg);
template <typename... Args>
explicit InternalException(const string &msg, Args... params)
: InternalException(ConstructMessage(msg, params...)) {
}
};
class InvalidInputException : public Exception {
public:
explicit InvalidInputException(const string &msg);
template <typename... Args>
explicit InvalidInputException(const 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, const string &msg);
InvalidTypeException(const LogicalType &type, const string &msg);
};
class TypeMismatchException : public Exception {
public:
TypeMismatchException(const PhysicalType type_1, const PhysicalType type_2, const string &msg);
TypeMismatchException(const LogicalType &type_1, const LogicalType &type_2, const 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 {
class Serializer {
public:
virtual ~Serializer() {
}
virtual void WriteData(const_data_ptr_t buffer, idx_t write_size) = 0;
template <class T>
void Write(T element) {
WriteData((const_data_ptr_t)&element, sizeof(T));
}
void WriteBufferData(const string &str) {
WriteData((const_data_ptr_t)str.c_str(), str.size());
}
void WriteString(const string &val) {
Write<uint32_t>((uint32_t)val.size());
if (val.size() > 0) {
WriteData((const_data_ptr_t)val.c_str(), val.size());
}
}
void WriteStringLen(const_data_ptr_t val, idx_t len) {
Write<uint32_t>((uint32_t)len);
if (len > 0) {
WriteData(val, len);
}
}
template <class T>
void WriteList(vector<unique_ptr<T>> &list) {
Write<uint32_t>((uint32_t)list.size());
for (auto &child : list) {
child->Serialize(*this);
}
}
void WriteStringVector(const vector<string> &list) {
Write<uint32_t>((uint32_t)list.size());
for (auto &child : list) {
WriteString(child);
}
}
template <class T>
void WriteOptional(const unique_ptr<T> &element) {
Write<bool>(element ? true : false);
if (element) {
element->Serialize(*this);
}
}
};
class Deserializer {
public:
virtual ~Deserializer() {
}
virtual void ReadData(data_ptr_t buffer, idx_t read_size) = 0;
template <class T>
T Read() {
T value;
ReadData((data_ptr_t)&value, sizeof(T));
return value;
}
template <class T>
void ReadList(vector<unique_ptr<T>> &list) {
auto select_count = Read<uint32_t>();
for (uint32_t i = 0; i < select_count; i++) {
auto child = T::Deserialize(*this);
list.push_back(move(child));
}
}
template <class T, class RETURN_TYPE = T>
unique_ptr<RETURN_TYPE> ReadOptional() {
auto has_entry = Read<bool>();
if (has_entry) {
return T::Deserialize(*this);
}
return nullptr;
}
void ReadStringVector(vector<string> &list);
};
template <>
string Deserializer::Read();
}
namespace duckdb {
class Allocator;
struct FileHandle;
enum class FileBufferType : uint8_t { BLOCK = 1, MANAGED_BUFFER = 2 };
class FileBuffer {
public:
FileBuffer(Allocator &allocator, FileBufferType type, uint64_t bufsiz);
FileBuffer(FileBuffer &source, FileBufferType type);
virtual ~FileBuffer();
Allocator &allocator;
FileBufferType type;
data_ptr_t buffer;
uint64_t size;
public:
void Read(FileHandle &handle, uint64_t location);
void ReadAndChecksum(FileHandle &handle, uint64_t location);
void Write(FileHandle &handle, uint64_t location);
void ChecksumAndWrite(FileHandle &handle, uint64_t location);
void Clear();
void Resize(uint64_t bufsiz);
uint64_t AllocSize() {
return internal_size;
}
protected:
data_ptr_t internal_buffer;
uint64_t internal_size;
private:
data_ptr_t malloced_buffer;
uint64_t malloced_size;
protected:
uint64_t GetMallocedSize() {
return malloced_size;
}
void SetMallocedSize(uint64_t &bufsiz);
void Construct(uint64_t bufsiz);
};
}
#include <unordered_map>
namespace duckdb {
using std::unordered_map;
}
namespace duckdb {
enum class FileCompressionType : uint8_t { AUTO_DETECT = 0, UNCOMPRESSED = 1, GZIP = 2 };
}
#include <functional>
#undef CreateDirectory
#undef MoveFile
#undef RemoveDirectory
namespace duckdb {
class ClientContext;
class DatabaseInstance;
class FileSystem;
enum class FileType {
FILE_TYPE_REGULAR,
FILE_TYPE_DIR,
FILE_TYPE_FIFO,
FILE_TYPE_SOCKET,
FILE_TYPE_LINK,
FILE_TYPE_BLOCKDEV,
FILE_TYPE_CHARDEV,
FILE_TYPE_INVALID,
};
struct FileHandle {
public:
FileHandle(FileSystem &file_system, string path) : file_system(file_system), path(path) {
}
FileHandle(const FileHandle &) = delete;
virtual ~FileHandle() {
}
int64_t Read(void *buffer, idx_t nr_bytes);
int64_t Write(void *buffer, idx_t nr_bytes);
void Read(void *buffer, idx_t nr_bytes, idx_t location);
void Write(void *buffer, idx_t nr_bytes, idx_t location);
void Seek(idx_t location);
void Reset();
idx_t SeekPosition();
void Sync();
void Truncate(int64_t new_size);
string ReadLine();
bool CanSeek();
bool OnDiskFile();
idx_t GetFileSize();
FileType GetType();
protected:
virtual void Close() = 0;
public:
FileSystem &file_system;
string path;
};
enum class FileLockType : uint8_t { NO_LOCK = 0, READ_LOCK = 1, WRITE_LOCK = 2 };
class FileFlags {
public:
static constexpr uint8_t FILE_FLAGS_READ = 1 << 0;
static constexpr uint8_t FILE_FLAGS_WRITE = 1 << 1;
static constexpr uint8_t FILE_FLAGS_DIRECT_IO = 1 << 2;
static constexpr uint8_t FILE_FLAGS_FILE_CREATE = 1 << 3;
static constexpr uint8_t FILE_FLAGS_FILE_CREATE_NEW = 1 << 4;
static constexpr uint8_t FILE_FLAGS_APPEND = 1 << 5;
};
class FileSystem {
public:
virtual ~FileSystem() {
}
public:
static FileSystem &GetFileSystem(ClientContext &context);
static FileSystem &GetFileSystem(DatabaseInstance &db);
virtual unique_ptr<FileHandle> OpenFile(const string &path, uint8_t flags,
FileLockType lock = FileLockType::NO_LOCK,
FileCompressionType compression = FileCompressionType::UNCOMPRESSED);
virtual void Read(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location);
virtual void Write(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location);
virtual int64_t Read(FileHandle &handle, void *buffer, int64_t nr_bytes);
virtual int64_t Write(FileHandle &handle, void *buffer, int64_t nr_bytes);
virtual int64_t GetFileSize(FileHandle &handle);
virtual time_t GetLastModifiedTime(FileHandle &handle);
virtual FileType GetFileType(FileHandle &handle);
virtual void Truncate(FileHandle &handle, int64_t new_size);
virtual bool DirectoryExists(const string &directory);
virtual void CreateDirectory(const string &directory);
virtual void RemoveDirectory(const string &directory);
virtual bool ListFiles(const string &directory, const std::function<void(string, bool)> &callback);
virtual void MoveFile(const string &source, const string &target);
virtual bool FileExists(const string &filename);
virtual void RemoveFile(const string &filename);
virtual string PathSeparator();
virtual string JoinPath(const string &a, const string &path);
virtual string ConvertSeparators(const string &path);
virtual string ExtractBaseName(const string &path);
virtual void FileSync(FileHandle &handle);
virtual void SetWorkingDirectory(const string &path);
virtual string GetWorkingDirectory();
virtual string GetHomeDirectory();
virtual vector<string> Glob(const string &path);
virtual idx_t GetAvailableMemory();
virtual void RegisterSubSystem(unique_ptr<FileSystem> sub_fs) {
throw NotImplementedException("Can't register a sub system on a non-virtual file system");
}
virtual bool CanHandleFile(const string &fpath) {
return false;
}
virtual void Seek(FileHandle &handle, idx_t location);
virtual void Reset(FileHandle &handle);
virtual idx_t SeekPosition(FileHandle &handle);
virtual bool CanSeek();
virtual bool OnDiskFile(FileHandle &handle);
private:
void SetFilePointer(FileHandle &handle, idx_t location);
virtual idx_t GetFilePointer(FileHandle &handle);
};
class VirtualFileSystem : public FileSystem {
public:
unique_ptr<FileHandle> OpenFile(const string &path, uint8_t flags, FileLockType lock = FileLockType::NO_LOCK,
FileCompressionType compression = FileCompressionType::UNCOMPRESSED) override;
virtual void Read(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) override {
handle.file_system.Read(handle, buffer, nr_bytes, location);
};
virtual void Write(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) override {
handle.file_system.Write(handle, buffer, nr_bytes, location);
}
int64_t Read(FileHandle &handle, void *buffer, int64_t nr_bytes) override {
return handle.file_system.Read(handle, buffer, nr_bytes);
}
int64_t Write(FileHandle &handle, void *buffer, int64_t nr_bytes) override {
return handle.file_system.Write(handle, buffer, nr_bytes);
}
int64_t GetFileSize(FileHandle &handle) override {
return handle.file_system.GetFileSize(handle);
}
time_t GetLastModifiedTime(FileHandle &handle) override {
return handle.file_system.GetLastModifiedTime(handle);
}
FileType GetFileType(FileHandle &handle) override {
return handle.file_system.GetFileType(handle);
}
void Truncate(FileHandle &handle, int64_t new_size) override {
handle.file_system.Truncate(handle, new_size);
}
void FileSync(FileHandle &handle) override {
handle.file_system.FileSync(handle);
}
bool DirectoryExists(const string &directory) override {
return FindFileSystem(directory)->DirectoryExists(directory);
}
void CreateDirectory(const string &directory) override {
FindFileSystem(directory)->CreateDirectory(directory);
}
void RemoveDirectory(const string &directory) override {
FindFileSystem(directory)->RemoveDirectory(directory);
}
bool ListFiles(const string &directory, const std::function<void(string, bool)> &callback) override {
return FindFileSystem(directory)->ListFiles(directory, callback);
}
void MoveFile(const string &source, const string &target) override {
FindFileSystem(source)->MoveFile(source, target);
}
bool FileExists(const string &filename) override {
return FindFileSystem(filename)->FileExists(filename);
}
virtual void RemoveFile(const string &filename) override {
FindFileSystem(filename)->RemoveFile(filename);
}
vector<string> Glob(const string &path) override {
return FindFileSystem(path)->Glob(path);
}
void SetWorkingDirectory(const string &path) override {
default_fs.SetWorkingDirectory(path);
}
string GetWorkingDirectory() override {
return default_fs.GetWorkingDirectory();
}
string GetHomeDirectory() override {
return default_fs.GetWorkingDirectory();
}
idx_t GetAvailableMemory() override {
return default_fs.GetAvailableMemory();
}
void RegisterSubSystem(unique_ptr<FileSystem> fs) override {
sub_systems.push_back(move(fs));
}
private:
FileSystem *FindFileSystem(const string &path) {
for (auto &sub_system : sub_systems) {
if (sub_system->CanHandleFile(path)) {
return sub_system.get();
}
}
return &default_fs;
}
private:
vector<unique_ptr<FileSystem>> sub_systems;
FileSystem default_fs;
};
}
namespace duckdb {
#define FILE_BUFFER_SIZE 4096
class BufferedFileWriter : public Serializer {
public:
BufferedFileWriter(FileSystem &fs, const string &path,
uint8_t open_flags = FileFlags::FILE_FLAGS_WRITE | FileFlags::FILE_FLAGS_FILE_CREATE);
FileSystem &fs;
unique_ptr<data_t[]> data;
idx_t offset;
idx_t total_written;
unique_ptr<FileHandle> handle;
public:
void WriteData(const_data_ptr_t buffer, uint64_t write_size) override;
void Sync();
void Flush();
int64_t GetFileSize();
void Truncate(int64_t size);
idx_t GetTotalWritten();
};
}
#include <bitset>
namespace duckdb {
using std::bitset;
}
namespace duckdb {
enum class VectorType : uint8_t {
FLAT_VECTOR, CONSTANT_VECTOR, DICTIONARY_VECTOR, SEQUENCE_VECTOR };
string VectorTypeToString(VectorType type);
}
namespace duckdb {
#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
extern const sel_t ZERO_VECTOR[STANDARD_VECTOR_SIZE];
}
namespace duckdb {
class VectorBuffer;
struct SelectionData {
explicit 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) {
}
explicit SelectionVector(sel_t *sel) {
Initialize(sel);
}
explicit 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);
}
explicit 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;
}
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 ? sel_vector[idx] : 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) const;
string ToString(idx_t count = 0) const;
void Print(idx_t count = 0) const;
sel_t &operator[](idx_t index) {
return sel_vector[index];
}
private:
sel_t *sel_vector;
buffer_ptr<SelectionData> selection_data;
};
class OptionalSelection {
public:
explicit inline OptionalSelection(SelectionVector *sel_p) : sel(sel_p) {
if (sel) {
vec.Initialize(sel->data());
sel = &vec;
}
}
inline operator SelectionVector *() {
return sel;
}
inline void Append(idx_t &count, const idx_t idx) {
if (sel) {
sel->set_index(count, idx);
}
++count;
}
inline void Advance(idx_t completed) {
if (sel) {
sel->Initialize(sel->data() + completed);
}
}
private:
SelectionVector *sel;
SelectionVector vec;
};
}
namespace duckdb {
using std::to_string;
}
namespace duckdb {
struct ValidityMask;
template <typename V>
struct TemplatedValidityData {
static constexpr const int BITS_PER_VALUE = sizeof(V) * 8;
static constexpr const V MAX_ENTRY = ~V(0);
public:
explicit TemplatedValidityData(idx_t count) {
auto entry_count = EntryCount(count);
owned_data = unique_ptr<V[]>(new V[entry_count]);
for (idx_t entry_idx = 0; entry_idx < entry_count; entry_idx++) {
owned_data[entry_idx] = MAX_ENTRY;
}
}
TemplatedValidityData(const V *validity_mask, idx_t count) {
D_ASSERT(validity_mask);
auto entry_count = EntryCount(count);
owned_data = unique_ptr<V[]>(new V[entry_count]);
for (idx_t entry_idx = 0; entry_idx < entry_count; entry_idx++) {
owned_data[entry_idx] = validity_mask[entry_idx];
}
}
unique_ptr<V[]> owned_data;
public:
static inline idx_t EntryCount(idx_t count) {
return (count + (BITS_PER_VALUE - 1)) / BITS_PER_VALUE;
}
};
using validity_t = uint64_t;
struct ValidityData : TemplatedValidityData<validity_t> {
public:
DUCKDB_API explicit ValidityData(idx_t count);
DUCKDB_API ValidityData(const ValidityMask &original, idx_t count);
};
template <typename V>
struct TemplatedValidityMask {
using ValidityBuffer = TemplatedValidityData<V>;
public:
static constexpr const int BITS_PER_VALUE = ValidityBuffer::BITS_PER_VALUE;
static constexpr const int STANDARD_ENTRY_COUNT = (STANDARD_VECTOR_SIZE + (BITS_PER_VALUE - 1)) / BITS_PER_VALUE;
static constexpr const int STANDARD_MASK_SIZE = STANDARD_ENTRY_COUNT * sizeof(validity_t);
public:
TemplatedValidityMask() : validity_mask(nullptr) {
}
explicit TemplatedValidityMask(idx_t max_count) {
Initialize(max_count);
}
explicit TemplatedValidityMask(V *ptr) : validity_mask(ptr) {
}
TemplatedValidityMask(const TemplatedValidityMask &original, idx_t count) {
Copy(original, count);
}
static inline idx_t ValidityMaskSize(idx_t count = STANDARD_VECTOR_SIZE) {
return ValidityBuffer::EntryCount(count) * sizeof(V);
}
inline bool AllValid() const {
return !validity_mask;
}
bool CheckAllValid(idx_t count) const {
if (AllValid()) {
return true;
}
idx_t entry_count = ValidityBuffer::EntryCount(count);
idx_t valid_count = 0;
for (idx_t i = 0; i < entry_count; i++) {
valid_count += validity_mask[i] == ValidityBuffer::MAX_ENTRY;
}
return valid_count == entry_count;
}
bool CheckAllValid(idx_t to, idx_t from) const {
if (AllValid()) {
return true;
}
for (idx_t i = from; i < to; i++) {
if (!RowIsValid(i)) {
return false;
}
}
return true;
}
inline V *GetData() const {
return validity_mask;
}
void Reset() {
validity_mask = nullptr;
validity_data.reset();
}
static inline idx_t EntryCount(idx_t count) {
return ValidityBuffer::EntryCount(count);
}
inline V GetValidityEntry(idx_t entry_idx) const {
if (!validity_mask) {
return ValidityBuffer::MAX_ENTRY;
}
return validity_mask[entry_idx];
}
static inline bool AllValid(V entry) {
return entry == ValidityBuffer::MAX_ENTRY;
}
static inline bool NoneValid(V entry) {
return entry == 0;
}
static inline bool RowIsValid(V entry, idx_t idx_in_entry) {
return entry & (V(1) << V(idx_in_entry));
}
static inline void GetEntryIndex(idx_t row_idx, idx_t &entry_idx, idx_t &idx_in_entry) {
entry_idx = row_idx / BITS_PER_VALUE;
idx_in_entry = row_idx % BITS_PER_VALUE;
}
inline bool RowIsValidUnsafe(idx_t row_idx) const {
D_ASSERT(validity_mask);
idx_t entry_idx, idx_in_entry;
GetEntryIndex(row_idx, entry_idx, idx_in_entry);
auto entry = GetValidityEntry(entry_idx);
return RowIsValid(entry, idx_in_entry);
}
inline bool RowIsValid(idx_t row_idx) const {
if (!validity_mask) {
return true;
}
return RowIsValidUnsafe(row_idx);
}
inline void SetValidUnsafe(idx_t row_idx) {
D_ASSERT(validity_mask);
idx_t entry_idx, idx_in_entry;
GetEntryIndex(row_idx, entry_idx, idx_in_entry);
validity_mask[entry_idx] |= (V(1) << V(idx_in_entry));
}
inline void SetValid(idx_t row_idx) {
if (!validity_mask) {
return;
}
SetValidUnsafe(row_idx);
}
inline void SetInvalidUnsafe(idx_t entry_idx, idx_t idx_in_entry) {
D_ASSERT(validity_mask);
validity_mask[entry_idx] &= ~(V(1) << V(idx_in_entry));
}
inline void SetInvalidUnsafe(idx_t row_idx) {
idx_t entry_idx, idx_in_entry;
GetEntryIndex(row_idx, entry_idx, idx_in_entry);
SetInvalidUnsafe(entry_idx, idx_in_entry);
}
inline void SetInvalid(idx_t row_idx) {
if (!validity_mask) {
D_ASSERT(row_idx <= STANDARD_VECTOR_SIZE);
Initialize(STANDARD_VECTOR_SIZE);
}
SetInvalidUnsafe(row_idx);
}
inline void Set(idx_t row_idx, bool valid) {
if (valid) {
SetValid(row_idx);
} else {
SetInvalid(row_idx);
}
}
inline void EnsureWritable() {
if (!validity_mask) {
Initialize();
}
}
inline void SetAllInvalid(idx_t count) {
EnsureWritable();
for (idx_t i = 0; i < ValidityBuffer::EntryCount(count); i++) {
validity_mask[i] = 0;
}
}
inline void SetAllValid(idx_t count) {
EnsureWritable();
for (idx_t i = 0; i < ValidityBuffer::EntryCount(count); i++) {
validity_mask[i] = ValidityBuffer::MAX_ENTRY;
}
}
inline bool IsMaskSet() const {
if (validity_mask) {
return true;
}
return false;
}
public:
void Initialize(validity_t *validity) {
validity_data.reset();
validity_mask = validity;
}
void Initialize(const TemplatedValidityMask &other) {
validity_mask = other.validity_mask;
validity_data = other.validity_data;
}
void Initialize(idx_t count = STANDARD_VECTOR_SIZE) {
validity_data = make_buffer<ValidityBuffer>(count);
validity_mask = validity_data->owned_data.get();
}
void Copy(const TemplatedValidityMask &other, idx_t count) {
if (other.AllValid()) {
validity_data = nullptr;
validity_mask = nullptr;
} else {
validity_data = make_buffer<ValidityBuffer>(other.validity_mask, count);
validity_mask = validity_data->owned_data.get();
}
}
protected:
V *validity_mask;
buffer_ptr<ValidityBuffer> validity_data;
};
struct ValidityMask : public TemplatedValidityMask<validity_t> {
public:
ValidityMask() : TemplatedValidityMask(nullptr) {
}
explicit ValidityMask(idx_t max_count) : TemplatedValidityMask(max_count) {
}
explicit ValidityMask(validity_t *ptr) : TemplatedValidityMask(ptr) {
}
ValidityMask(const ValidityMask &original, idx_t count) : TemplatedValidityMask(original, count) {
}
public:
void Resize(idx_t old_size, idx_t new_size);
void Slice(const ValidityMask &other, idx_t offset);
void Combine(const ValidityMask &other, idx_t count);
string ToString(idx_t count) const;
};
}
namespace duckdb {
class Deserializer;
class Serializer;
class Value {
friend class Vector;
public:
explicit Value(LogicalType type = LogicalType::SQLNULL);
Value(int32_t val); Value(int64_t val); Value(float val); Value(double val); Value(const char *val); Value(std::nullptr_t val); Value(string_t val); Value(string val);
const LogicalType &type() const {
return type_;
}
DUCKDB_API static Value MinimumValue(const LogicalType &type);
DUCKDB_API static Value MaximumValue(const LogicalType &type);
DUCKDB_API static Value Numeric(const LogicalType &type, int64_t value);
DUCKDB_API static Value Numeric(const LogicalType &type, hugeint_t value);
DUCKDB_API static Value BOOLEAN(int8_t value);
DUCKDB_API static Value TINYINT(int8_t value);
DUCKDB_API static Value SMALLINT(int16_t value);
DUCKDB_API static Value INTEGER(int32_t value);
DUCKDB_API static Value BIGINT(int64_t value);
DUCKDB_API static Value UTINYINT(uint8_t value);
DUCKDB_API static Value USMALLINT(uint16_t value);
DUCKDB_API static Value UINTEGER(uint32_t value);
DUCKDB_API static Value UBIGINT(uint64_t value);
DUCKDB_API static Value HUGEINT(hugeint_t value);
DUCKDB_API static Value HASH(hash_t value);
DUCKDB_API static Value POINTER(uintptr_t value);
DUCKDB_API static Value DATE(date_t date);
DUCKDB_API static Value DATE(int32_t year, int32_t month, int32_t day);
DUCKDB_API static Value TIME(dtime_t time);
DUCKDB_API static Value TIME(int32_t hour, int32_t min, int32_t sec, int32_t micros);
DUCKDB_API static Value TIMESTAMP(date_t date, dtime_t time);
DUCKDB_API static Value TIMESTAMP(timestamp_t timestamp);
DUCKDB_API static Value TimestampNs(timestamp_t timestamp);
DUCKDB_API static Value TimestampMs(timestamp_t timestamp);
DUCKDB_API static Value TimestampSec(timestamp_t timestamp);
DUCKDB_API static Value TIMESTAMP(int32_t year, int32_t month, int32_t day, int32_t hour, int32_t min, int32_t sec,
int32_t micros);
DUCKDB_API static Value INTERVAL(int32_t months, int32_t days, int64_t micros);
DUCKDB_API static Value INTERVAL(interval_t interval);
DUCKDB_API static Value DECIMAL(int16_t value, uint8_t width, uint8_t scale);
DUCKDB_API static Value DECIMAL(int32_t value, uint8_t width, uint8_t scale);
DUCKDB_API static Value DECIMAL(int64_t value, uint8_t width, uint8_t scale);
DUCKDB_API static Value DECIMAL(hugeint_t value, uint8_t width, uint8_t scale);
DUCKDB_API static Value FLOAT(float value);
DUCKDB_API static Value DOUBLE(double value);
DUCKDB_API static Value STRUCT(child_list_t<Value> values);
DUCKDB_API static Value LIST(vector<Value> values);
DUCKDB_API static Value EMPTYLIST(LogicalType child_type);
DUCKDB_API static Value MAP(Value key, Value value);
DUCKDB_API static Value BLOB(const_data_ptr_t data, idx_t len);
DUCKDB_API static Value BLOB_RAW(const string &data) {
return Value::BLOB((const_data_ptr_t)data.c_str(), data.size());
}
DUCKDB_API static Value BLOB(const string &data);
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");
}
template <class T>
T &GetValueUnsafe() {
throw NotImplementedException("Unimplemented template type for Value::GetValueUnsafe");
}
Value Copy() const {
return Value(*this);
}
DUCKDB_API string ToString() const;
DUCKDB_API uintptr_t GetPointer() const;
DUCKDB_API Value CastAs(const LogicalType &target_type, bool strict = false) const;
DUCKDB_API bool TryCastAs(const LogicalType &target_type, Value &new_value, string *error_message,
bool strict = false) const;
DUCKDB_API bool TryCastAs(const LogicalType &target_type, bool strict = false);
DUCKDB_API void Serialize(Serializer &serializer);
DUCKDB_API static Value Deserialize(Deserializer &source);
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;
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);
static bool StringIsValid(const char *str, idx_t length);
static bool StringIsValid(const string &str) {
return StringIsValid(str.c_str(), str.size());
}
template <class T>
static bool IsValid(T value) {
return true;
}
static bool ValuesAreEqual(const Value &result_value, const Value &value);
friend std::ostream &operator<<(std::ostream &out, const Value &val) {
out << val.ToString();
return out;
}
void Print() const;
private:
LogicalType type_;
public:
bool is_null;
union Val {
int8_t boolean;
int8_t tinyint;
int16_t smallint;
int32_t integer;
int64_t bigint;
uint8_t utinyint;
uint16_t usmallint;
uint32_t uinteger;
uint64_t ubigint;
hugeint_t hugeint;
float float_;
double double_;
uintptr_t pointer;
uint64_t hash;
date_t date;
dtime_t time;
timestamp_t timestamp;
interval_t interval;
} value_;
string str_value;
vector<Value> struct_value;
vector<Value> list_value;
private:
template <class T>
T GetValueInternal() const;
template <class DST, class OP>
static DST _cast(const Value &v);
template <class OP>
static void _templated_binary_operation(const Value &left, const Value &right, Value &result, bool ignore_null);
template <class OP>
static bool _templated_boolean_operation(const Value &left, const Value &right);
};
template <>
Value DUCKDB_API Value::CreateValue(bool value);
template <>
Value DUCKDB_API Value::CreateValue(uint8_t value);
template <>
Value DUCKDB_API Value::CreateValue(uint16_t value);
template <>
Value DUCKDB_API Value::CreateValue(uint32_t value);
template <>
Value DUCKDB_API Value::CreateValue(uint64_t value);
template <>
Value DUCKDB_API Value::CreateValue(int8_t value);
template <>
Value DUCKDB_API Value::CreateValue(int16_t value);
template <>
Value DUCKDB_API Value::CreateValue(int32_t value);
template <>
Value DUCKDB_API Value::CreateValue(int64_t value);
template <>
Value DUCKDB_API Value::CreateValue(hugeint_t value);
template <>
Value DUCKDB_API Value::CreateValue(date_t value);
template <>
Value DUCKDB_API Value::CreateValue(dtime_t value);
template <>
Value DUCKDB_API Value::CreateValue(timestamp_t value);
template <>
Value DUCKDB_API Value::CreateValue(const char *value);
template <>
Value DUCKDB_API Value::CreateValue(string value);
template <>
Value DUCKDB_API Value::CreateValue(string_t value);
template <>
Value DUCKDB_API Value::CreateValue(float value);
template <>
Value DUCKDB_API Value::CreateValue(double value);
template <>
Value DUCKDB_API Value::CreateValue(interval_t value);
template <>
Value DUCKDB_API Value::CreateValue(Value value);
template <>
DUCKDB_API bool Value::GetValue() const;
template <>
DUCKDB_API int8_t Value::GetValue() const;
template <>
DUCKDB_API int16_t Value::GetValue() const;
template <>
DUCKDB_API int32_t Value::GetValue() const;
template <>
DUCKDB_API int64_t Value::GetValue() const;
template <>
DUCKDB_API uint8_t Value::GetValue() const;
template <>
DUCKDB_API uint16_t Value::GetValue() const;
template <>
DUCKDB_API uint32_t Value::GetValue() const;
template <>
DUCKDB_API uint64_t Value::GetValue() const;
template <>
DUCKDB_API hugeint_t Value::GetValue() const;
template <>
DUCKDB_API string Value::GetValue() const;
template <>
DUCKDB_API float Value::GetValue() const;
template <>
DUCKDB_API double Value::GetValue() const;
template <>
DUCKDB_API date_t Value::GetValue() const;
template <>
DUCKDB_API dtime_t Value::GetValue() const;
template <>
DUCKDB_API timestamp_t Value::GetValue() const;
template <>
DUCKDB_API interval_t Value::GetValue() const;
template <>
DUCKDB_API int8_t &Value::GetValueUnsafe();
template <>
DUCKDB_API int16_t &Value::GetValueUnsafe();
template <>
DUCKDB_API int32_t &Value::GetValueUnsafe();
template <>
DUCKDB_API int64_t &Value::GetValueUnsafe();
template <>
DUCKDB_API hugeint_t &Value::GetValueUnsafe();
template <>
DUCKDB_API uint8_t &Value::GetValueUnsafe();
template <>
DUCKDB_API uint16_t &Value::GetValueUnsafe();
template <>
DUCKDB_API uint32_t &Value::GetValueUnsafe();
template <>
DUCKDB_API uint64_t &Value::GetValueUnsafe();
template <>
DUCKDB_API string &Value::GetValueUnsafe();
template <>
DUCKDB_API float &Value::GetValueUnsafe();
template <>
DUCKDB_API double &Value::GetValueUnsafe();
template <>
DUCKDB_API date_t &Value::GetValueUnsafe();
template <>
DUCKDB_API dtime_t &Value::GetValueUnsafe();
template <>
DUCKDB_API timestamp_t &Value::GetValueUnsafe();
template <>
DUCKDB_API interval_t &Value::GetValueUnsafe();
template <>
DUCKDB_API bool Value::IsValid(float value);
template <>
DUCKDB_API bool Value::IsValid(double value);
}
namespace duckdb {
class StringHeap {
public:
StringHeap();
void Destroy() {
tail = nullptr;
chunk = nullptr;
}
void Move(StringHeap &other) {
D_ASSERT(!other.chunk);
other.tail = tail;
other.chunk = move(chunk);
tail = nullptr;
}
string_t AddString(const char *data, idx_t len);
string_t AddString(const char *data);
string_t AddString(const string &data);
string_t AddString(const string_t &data);
string_t AddBlob(const char *data, idx_t len);
string_t EmptyString(idx_t len);
private:
struct StringChunk {
explicit 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;
};
}
#include <cstring>
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;
explicit string_t(uint32_t len) {
value.inlined.length = len;
}
string_t(const char *data, uint32_t len) {
value.inlined.length = len;
D_ASSERT(data || GetSize() == 0);
if (IsInlined()) {
memset(value.inlined.inlined, 0, INLINE_LENGTH);
if (GetSize() == 0) {
return;
}
memcpy(value.inlined.inlined, data, GetSize());
} else {
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;
}
const char *GetDataUnsafe() const {
return IsInlined() ? (const char *)value.inlined.inlined : value.pointer.ptr;
}
char *GetDataWriteable() const {
return IsInlined() ? (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(GetDataUnsafe(), GetSize());
}
explicit operator string() const {
return GetString();
}
void Finalize() {
auto dataptr = (char *)GetDataUnsafe();
if (GetSize() <= INLINE_LENGTH) {
for (idx_t i = GetSize(); i < INLINE_LENGTH; i++) {
value.inlined.inlined[i] = '\0';
}
} else {
memcpy(value.pointer.prefix, dataptr, PREFIX_LENGTH);
}
}
void Verify();
void VerifyNull();
bool operator<(const string_t &r) const {
auto this_str = this->GetString();
auto r_str = r.GetString();
return this_str < r_str;
}
private:
union {
struct {
uint32_t length;
char prefix[4];
char *ptr;
} pointer;
struct {
uint32_t length;
char inlined[12];
} inlined;
} value;
};
}
namespace duckdb {
class BufferHandle;
class VectorBuffer;
class Vector;
class ChunkCollection;
enum class VectorBufferType : uint8_t {
STANDARD_BUFFER, DICTIONARY_BUFFER, VECTOR_CHILD_BUFFER, STRING_BUFFER, STRUCT_BUFFER, LIST_BUFFER, MANAGED_BUFFER, OPAQUE_BUFFER };
class VectorBuffer {
public:
explicit VectorBuffer(VectorBufferType type) : buffer_type(type) {
}
explicit VectorBuffer(idx_t data_size) : buffer_type(VectorBufferType::STANDARD_BUFFER) {
if (data_size > 0) {
data = unique_ptr<data_t[]>(new data_t[data_size]);
}
}
explicit VectorBuffer(unique_ptr<data_t[]> data_p)
: buffer_type(VectorBufferType::STANDARD_BUFFER), data(move(data_p)) {
}
virtual ~VectorBuffer() {
}
VectorBuffer() {
}
public:
data_ptr_t GetData() {
return data.get();
}
void SetData(unique_ptr<data_t[]> new_data) {
data = move(new_data);
}
static buffer_ptr<VectorBuffer> CreateStandardVector(PhysicalType type, idx_t capacity = STANDARD_VECTOR_SIZE);
static buffer_ptr<VectorBuffer> CreateConstantVector(PhysicalType type);
static buffer_ptr<VectorBuffer> CreateConstantVector(const LogicalType &logical_type);
static buffer_ptr<VectorBuffer> CreateStandardVector(const LogicalType &logical_type,
idx_t capacity = STANDARD_VECTOR_SIZE);
inline VectorBufferType GetBufferType() const {
return buffer_type;
}
protected:
VectorBufferType buffer_type;
unique_ptr<data_t[]> data;
};
class DictionaryBuffer : public VectorBuffer {
public:
explicit DictionaryBuffer(const SelectionVector &sel)
: VectorBuffer(VectorBufferType::DICTIONARY_BUFFER), sel_vector(sel) {
}
explicit DictionaryBuffer(buffer_ptr<SelectionData> data)
: VectorBuffer(VectorBufferType::DICTIONARY_BUFFER), sel_vector(move(data)) {
}
explicit DictionaryBuffer(idx_t count = STANDARD_VECTOR_SIZE)
: VectorBuffer(VectorBufferType::DICTIONARY_BUFFER), sel_vector(count) {
}
public:
const SelectionVector &GetSelVector() const {
return sel_vector;
}
SelectionVector &GetSelVector() {
return sel_vector;
}
void SetSelVector(const SelectionVector &vector) {
this->sel_vector.Initialize(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.GetDataUnsafe(), data.GetSize());
}
string_t EmptyString(idx_t len) {
return heap.EmptyString(len);
}
void AddHeapReference(buffer_ptr<VectorBuffer> heap) {
references.push_back(move(heap));
}
private:
StringHeap heap;
vector<buffer_ptr<VectorBuffer>> references;
};
class VectorStructBuffer : public VectorBuffer {
public:
VectorStructBuffer();
VectorStructBuffer(const LogicalType &struct_type, idx_t capacity = STANDARD_VECTOR_SIZE);
~VectorStructBuffer() override;
public:
const vector<unique_ptr<Vector>> &GetChildren() const {
return children;
}
vector<unique_ptr<Vector>> &GetChildren() {
return children;
}
private:
vector<unique_ptr<Vector>> children;
};
class VectorListBuffer : public VectorBuffer {
public:
VectorListBuffer(unique_ptr<Vector> vector, idx_t initial_capacity = STANDARD_VECTOR_SIZE);
VectorListBuffer(const LogicalType &list_type, idx_t initial_capacity = STANDARD_VECTOR_SIZE);
~VectorListBuffer() override;
public:
Vector &GetChild() {
return *child;
}
void Reserve(idx_t to_reserve);
void Append(const Vector &to_append, idx_t to_append_size, idx_t source_offset = 0);
void Append(const Vector &to_append, const SelectionVector &sel, idx_t to_append_size, idx_t source_offset = 0);
void PushBack(Value &insert);
idx_t capacity = 0;
idx_t size = 0;
private:
unique_ptr<Vector> child;
};
class ManagedVectorBuffer : public VectorBuffer {
public:
explicit ManagedVectorBuffer(unique_ptr<BufferHandle> handle);
~ManagedVectorBuffer() override;
private:
unique_ptr<BufferHandle> handle;
};
}
namespace duckdb {
struct VectorData {
const SelectionVector *sel;
data_ptr_t data;
ValidityMask validity;
SelectionVector owned_sel;
};
class VectorCache;
class VectorStructBuffer;
class VectorListBuffer;
class ChunkCollection;
struct SelCache;
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;
friend class VectorCacheBuffer;
public:
explicit Vector(Vector &other);
explicit Vector(Vector &other, const SelectionVector &sel, idx_t count);
explicit Vector(Vector &other, idx_t offset);
explicit Vector(const Value &value);
explicit Vector(LogicalType type, idx_t capacity = STANDARD_VECTOR_SIZE);
explicit Vector(const VectorCache &cache);
Vector(LogicalType type, data_ptr_t dataptr);
Vector(LogicalType type, bool create_data, bool zero_data, idx_t capacity = STANDARD_VECTOR_SIZE);
Vector(const Vector &) = delete;
Vector(Vector &&other) noexcept;
public:
void Reference(const Value &value);
void Reference(Vector &other);
void Reinterpret(Vector &other);
void ResetFromCache(const VectorCache &cache);
void Slice(Vector &other, idx_t offset);
void Slice(Vector &other, const SelectionVector &sel, idx_t count);
void Slice(const SelectionVector &sel, idx_t count);
void Slice(const SelectionVector &sel, idx_t count, SelCache &cache);
void Initialize(bool zero_data = false, idx_t capacity = STANDARD_VECTOR_SIZE);
string ToString(idx_t count) const;
void Print(idx_t count);
string ToString() const;
void Print();
DUCKDB_API void Normalify(idx_t count);
DUCKDB_API void Normalify(const SelectionVector &sel, idx_t count);
DUCKDB_API void Orrify(idx_t count, VectorData &data);
void Sequence(int64_t start, int64_t increment);
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);
Value GetValue(idx_t index) const;
void SetValue(idx_t index, const Value &val);
void SetAuxiliary(buffer_ptr<VectorBuffer> new_buffer) {
auxiliary = std::move(new_buffer);
};
void Resize(idx_t cur_size, idx_t new_size);
void Serialize(idx_t count, Serializer &serializer);
void Deserialize(idx_t count, Deserializer &source);
inline VectorType GetVectorType() const {
return vector_type;
}
inline const LogicalType &GetType() const {
return type;
}
inline data_ptr_t GetData() {
return data;
}
buffer_ptr<VectorBuffer> GetAuxiliary() {
return auxiliary;
}
buffer_ptr<VectorBuffer> GetBuffer() {
return buffer;
}
DUCKDB_API void SetVectorType(VectorType vector_type);
protected:
VectorType vector_type;
LogicalType type;
data_ptr_t data;
ValidityMask validity;
buffer_ptr<VectorBuffer> buffer;
buffer_ptr<VectorBuffer> auxiliary;
};
class VectorChildBuffer : public VectorBuffer {
public:
VectorChildBuffer(Vector vector) : VectorBuffer(VectorBufferType::VECTOR_CHILD_BUFFER), data(move(vector)) {
}
public:
Vector data;
};
struct ConstantVector {
static inline const_data_ptr_t GetData(const Vector &vector) {
D_ASSERT(vector.GetVectorType() == VectorType::CONSTANT_VECTOR ||
vector.GetVectorType() == VectorType::FLAT_VECTOR);
return vector.data;
}
static inline data_ptr_t GetData(Vector &vector) {
D_ASSERT(vector.GetVectorType() == VectorType::CONSTANT_VECTOR ||
vector.GetVectorType() == VectorType::FLAT_VECTOR);
return vector.data;
}
template <class T>
static inline const T *GetData(const Vector &vector) {
return (const T *)ConstantVector::GetData(vector);
}
template <class T>
static inline T *GetData(Vector &vector) {
return (T *)ConstantVector::GetData(vector);
}
static inline bool IsNull(const Vector &vector) {
D_ASSERT(vector.GetVectorType() == VectorType::CONSTANT_VECTOR);
return !vector.validity.RowIsValid(0);
}
DUCKDB_API static void SetNull(Vector &vector, bool is_null);
static inline ValidityMask &Validity(Vector &vector) {
D_ASSERT(vector.GetVectorType() == VectorType::CONSTANT_VECTOR);
return vector.validity;
}
DUCKDB_API static const SelectionVector *ZeroSelectionVector(idx_t count, SelectionVector &owned_sel);
DUCKDB_API static void Reference(Vector &vector, Vector &source, idx_t position, idx_t count);
static const sel_t ZERO_VECTOR[STANDARD_VECTOR_SIZE];
static const SelectionVector ZERO_SELECTION_VECTOR;
};
struct DictionaryVector {
static inline const SelectionVector &SelVector(const Vector &vector) {
D_ASSERT(vector.GetVectorType() == VectorType::DICTIONARY_VECTOR);
return ((const DictionaryBuffer &)*vector.buffer).GetSelVector();
}
static inline SelectionVector &SelVector(Vector &vector) {
D_ASSERT(vector.GetVectorType() == VectorType::DICTIONARY_VECTOR);
return ((DictionaryBuffer &)*vector.buffer).GetSelVector();
}
static inline const Vector &Child(const Vector &vector) {
D_ASSERT(vector.GetVectorType() == VectorType::DICTIONARY_VECTOR);
return ((const VectorChildBuffer &)*vector.auxiliary).data;
}
static inline Vector &Child(Vector &vector) {
D_ASSERT(vector.GetVectorType() == 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 const T *GetData(const Vector &vector) {
return ConstantVector::GetData<T>(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) {
D_ASSERT(vector.GetVectorType() == VectorType::FLAT_VECTOR);
vector.data = data;
}
template <class T>
static inline T GetValue(Vector &vector, idx_t idx) {
D_ASSERT(vector.GetVectorType() == VectorType::FLAT_VECTOR);
return FlatVector::GetData<T>(vector)[idx];
}
static inline const ValidityMask &Validity(const Vector &vector) {
D_ASSERT(vector.GetVectorType() == VectorType::FLAT_VECTOR);
return vector.validity;
}
static inline ValidityMask &Validity(Vector &vector) {
D_ASSERT(vector.GetVectorType() == VectorType::FLAT_VECTOR);
return vector.validity;
}
static inline void SetValidity(Vector &vector, ValidityMask &new_validity) {
D_ASSERT(vector.GetVectorType() == VectorType::FLAT_VECTOR);
vector.validity.Initialize(new_validity);
}
static void SetNull(Vector &vector, idx_t idx, bool is_null);
static inline bool IsNull(const Vector &vector, idx_t idx) {
D_ASSERT(vector.GetVectorType() == VectorType::FLAT_VECTOR);
return !vector.validity.RowIsValid(idx);
}
static const sel_t INCREMENTAL_VECTOR[STANDARD_VECTOR_SIZE];
static const SelectionVector INCREMENTAL_SELECTION_VECTOR;
};
struct ListVector {
static inline list_entry_t *GetData(Vector &v) {
if (v.GetVectorType() == VectorType::DICTIONARY_VECTOR) {
auto &child = DictionaryVector::Child(v);
return GetData(child);
}
return FlatVector::GetData<list_entry_t>(v);
}
DUCKDB_API static const Vector &GetEntry(const Vector &vector);
DUCKDB_API static Vector &GetEntry(Vector &vector);
DUCKDB_API static idx_t GetListSize(const Vector &vector);
DUCKDB_API static void SetListSize(Vector &vec, idx_t size);
DUCKDB_API static void Reserve(Vector &vec, idx_t required_capacity);
DUCKDB_API static void Append(Vector &target, const Vector &source, idx_t source_size, idx_t source_offset = 0);
DUCKDB_API static void Append(Vector &target, const Vector &source, const SelectionVector &sel, idx_t source_size,
idx_t source_offset = 0);
DUCKDB_API static void PushBack(Vector &target, Value &insert);
DUCKDB_API static vector<idx_t> Search(Vector &list, Value &key, idx_t row);
DUCKDB_API static Value GetValuesFromOffsets(Vector &list, vector<idx_t> &offsets);
DUCKDB_API static void ReferenceEntry(Vector &vector, Vector &other);
};
struct StringVector {
DUCKDB_API static string_t AddString(Vector &vector, const char *data, idx_t len);
DUCKDB_API static string_t AddStringOrBlob(Vector &vector, const char *data, idx_t len);
DUCKDB_API static string_t AddString(Vector &vector, const char *data);
DUCKDB_API static string_t AddString(Vector &vector, string_t data);
DUCKDB_API static string_t AddString(Vector &vector, const string &data);
DUCKDB_API static string_t AddStringOrBlob(Vector &vector, string_t data);
DUCKDB_API static string_t EmptyString(Vector &vector, idx_t len);
DUCKDB_API static void AddHandle(Vector &vector, unique_ptr<BufferHandle> handle);
DUCKDB_API static void AddBuffer(Vector &vector, buffer_ptr<VectorBuffer> buffer);
DUCKDB_API static void AddHeapReference(Vector &vector, Vector &other);
};
struct StructVector {
DUCKDB_API static const vector<unique_ptr<Vector>> &GetEntries(const Vector &vector);
DUCKDB_API static vector<unique_ptr<Vector>> &GetEntries(Vector &vector);
};
struct SequenceVector {
static void GetSequence(const Vector &vector, int64_t &start, int64_t &increment) {
D_ASSERT(vector.GetVectorType() == VectorType::SEQUENCE_VECTOR);
auto data = (int64_t *)vector.buffer->GetData();
start = data[0];
increment = data[1];
}
};
}
struct ArrowArray;
namespace duckdb {
class VectorCache;
class DataChunk {
public:
DataChunk();
~DataChunk();
vector<Vector> data;
public:
DUCKDB_API idx_t size() const {
return count;
}
DUCKDB_API idx_t ColumnCount() const {
return data.size();
}
void SetCardinality(idx_t count_p) {
D_ASSERT(count <= STANDARD_VECTOR_SIZE);
this->count = count_p;
}
void SetCardinality(const DataChunk &other) {
this->count = other.size();
}
DUCKDB_API Value GetValue(idx_t col_idx, idx_t index) const;
DUCKDB_API void SetValue(idx_t col_idx, idx_t index, const Value &val);
DUCKDB_API void Reference(DataChunk &chunk);
DUCKDB_API void Move(DataChunk &chunk);
void Initialize(const vector<LogicalType> &types);
void InitializeEmpty(const vector<LogicalType> &types);
DUCKDB_API void Append(const DataChunk &other);
DUCKDB_API void Destroy();
DUCKDB_API void Copy(DataChunk &other, idx_t offset = 0) const;
DUCKDB_API void Copy(DataChunk &other, const SelectionVector &sel, const idx_t source_count,
const idx_t offset = 0) const;
DUCKDB_API void Normalify();
DUCKDB_API unique_ptr<VectorData[]> Orrify();
DUCKDB_API void Slice(const SelectionVector &sel_vector, idx_t count);
DUCKDB_API void Slice(DataChunk &other, const SelectionVector &sel, idx_t count, idx_t col_offset = 0);
DUCKDB_API void Reset();
DUCKDB_API void Serialize(Serializer &serializer);
DUCKDB_API void Deserialize(Deserializer &source);
DUCKDB_API void Hash(Vector &result);
DUCKDB_API vector<LogicalType> GetTypes();
DUCKDB_API string ToString() const;
DUCKDB_API void Print();
DataChunk(const DataChunk &) = delete;
DUCKDB_API void Verify();
DUCKDB_API void ToArrowArray(ArrowArray *out_array);
private:
idx_t count;
vector<VectorCache> vector_caches;
};
}
#include <functional>
namespace duckdb {
struct VectorOperations {
static void AddInPlace(Vector &A, int64_t B, idx_t count);
static void IsNotNull(Vector &A, Vector &result, idx_t count);
static void IsNull(Vector &A, Vector &result, idx_t count);
static bool HasNull(Vector &A, idx_t count);
static bool HasNotNull(Vector &A, idx_t count);
static void And(Vector &A, Vector &B, Vector &result, idx_t count);
static void Or(Vector &A, Vector &B, Vector &result, idx_t count);
static void Not(Vector &A, Vector &result, idx_t count);
static void Equals(Vector &A, Vector &B, Vector &result, idx_t count);
static void NotEquals(Vector &A, Vector &B, Vector &result, idx_t count);
static void GreaterThan(Vector &A, Vector &B, Vector &result, idx_t count);
static void GreaterThanEquals(Vector &A, Vector &B, Vector &result, idx_t count);
static void LessThan(Vector &A, Vector &B, Vector &result, idx_t count);
static void LessThanEquals(Vector &A, Vector &B, Vector &result, idx_t count);
static void DistinctFrom(Vector &left, Vector &right, Vector &result, idx_t count);
static void NotDistinctFrom(Vector &left, Vector &right, Vector &result, idx_t count);
static void DistinctGreaterThan(Vector &left, Vector &right, Vector &result, idx_t count);
static void DistinctGreaterThanEquals(Vector &left, Vector &right, Vector &result, idx_t count);
static void DistinctLessThan(Vector &left, Vector &right, Vector &result, idx_t count);
static void DistinctLessThanEquals(Vector &left, Vector &right, Vector &result, idx_t count);
static idx_t Equals(Vector &left, Vector &right, const SelectionVector *sel, idx_t count, SelectionVector *true_sel,
SelectionVector *false_sel);
static idx_t NotEquals(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t GreaterThan(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t GreaterThanEquals(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t LessThan(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t LessThanEquals(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t DistinctFrom(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t NotDistinctFrom(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t DistinctGreaterThan(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t DistinctGreaterThanEquals(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t DistinctLessThan(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t DistinctLessThanEquals(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t NestedNotEquals(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t NestedEquals(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t NestedGreaterThan(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t NestedGreaterThanEquals(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel,
idx_t count, SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t NestedLessThan(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel);
static idx_t NestedLessThanEquals(Vector &left, Vector &right, idx_t vcount, const SelectionVector &sel,
idx_t count, SelectionVector *true_sel, SelectionVector *false_sel);
static void Hash(Vector &input, Vector &hashes, idx_t count);
static void Hash(Vector &input, Vector &hashes, const SelectionVector &rsel, idx_t count);
static void CombineHash(Vector &hashes, Vector &B, idx_t count);
static void CombineHash(Vector &hashes, Vector &B, const SelectionVector &rsel, idx_t count);
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);
static bool TryCast(Vector &source, Vector &result, idx_t count, string *error_message, bool strict = false);
static void Cast(Vector &source, Vector &result, idx_t count, bool strict = false);
static void Copy(const Vector &source, Vector &target, idx_t source_count, idx_t source_offset,
idx_t target_offset);
static void Copy(const Vector &source, Vector &target, const SelectionVector &sel, idx_t source_count,
idx_t source_offset, idx_t target_offset);
static void WriteToStorage(Vector &source, idx_t count, data_ptr_t target);
static void ReadFromStorage(data_ptr_t source, idx_t count, Vector &result);
};
}
#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, ValidityMask &mask, idx_t idx) {
return OP::template Operation<LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE>(left, right);
}
static bool AddsNulls() {
return false;
}
};
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, ValidityMask &mask, idx_t idx) {
return OP::template Operation<LEFT_TYPE>(left, right);
}
static bool AddsNulls() {
return false;
}
};
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, ValidityMask &mask, idx_t idx) {
return fun(left, right);
}
static bool AddsNulls() {
return false;
}
};
struct BinaryExecutor {
template <class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE, class OPWRAPPER, class OP, class FUNC,
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, ValidityMask &mask, 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 (!mask.AllValid()) {
idx_t base_idx = 0;
auto entry_count = ValidityMask::EntryCount(count);
for (idx_t entry_idx = 0; entry_idx < entry_count; entry_idx++) {
auto validity_entry = mask.GetValidityEntry(entry_idx);
idx_t next = MinValue<idx_t>(base_idx + ValidityMask::BITS_PER_VALUE, count);
if (ValidityMask::AllValid(validity_entry)) {
for (; base_idx < next; base_idx++) {
auto lentry = ldata[LEFT_CONSTANT ? 0 : base_idx];
auto rentry = rdata[RIGHT_CONSTANT ? 0 : base_idx];
result_data[base_idx] =
OPWRAPPER::template Operation<FUNC, OP, LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE>(
fun, lentry, rentry, mask, base_idx);
}
} else if (ValidityMask::NoneValid(validity_entry)) {
base_idx = next;
continue;
} else {
idx_t start = base_idx;
for (; base_idx < next; base_idx++) {
if (ValidityMask::RowIsValid(validity_entry, base_idx - start)) {
auto lentry = ldata[LEFT_CONSTANT ? 0 : base_idx];
auto rentry = rdata[RIGHT_CONSTANT ? 0 : base_idx];
result_data[base_idx] =
OPWRAPPER::template Operation<FUNC, OP, LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE>(
fun, lentry, rentry, mask, base_idx);
}
}
}
}
} 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, mask, i);
}
}
}
template <class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE, class OPWRAPPER, class OP, class FUNC>
static void ExecuteConstant(Vector &left, Vector &right, Vector &result, FUNC fun) {
result.SetVectorType(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::Validity(result), 0);
}
template <class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE, class OPWRAPPER, class OP, class FUNC,
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))) {
result.SetVectorType(VectorType::CONSTANT_VECTOR);
ConstantVector::SetNull(result, true);
return;
}
result.SetVectorType(VectorType::FLAT_VECTOR);
auto result_data = FlatVector::GetData<RESULT_TYPE>(result);
auto &result_validity = FlatVector::Validity(result);
if (LEFT_CONSTANT) {
if (OPWRAPPER::AddsNulls()) {
result_validity.Copy(FlatVector::Validity(right), count);
} else {
FlatVector::SetValidity(result, FlatVector::Validity(right));
}
} else if (RIGHT_CONSTANT) {
if (OPWRAPPER::AddsNulls()) {
result_validity.Copy(FlatVector::Validity(left), count);
} else {
FlatVector::SetValidity(result, FlatVector::Validity(left));
}
} else {
if (OPWRAPPER::AddsNulls()) {
result_validity.Copy(FlatVector::Validity(left), count);
if (result_validity.AllValid()) {
result_validity.Copy(FlatVector::Validity(right), count);
} else {
result_validity.Combine(FlatVector::Validity(right), count);
}
} else {
FlatVector::SetValidity(result, FlatVector::Validity(left));
result_validity.Combine(FlatVector::Validity(right), count);
}
}
ExecuteFlatLoop<LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE, OPWRAPPER, OP, FUNC, LEFT_CONSTANT, RIGHT_CONSTANT>(
ldata, rdata, result_data, count, result_validity, fun);
}
template <class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE, class OPWRAPPER, class OP, class FUNC>
static void ExecuteGenericLoop(LEFT_TYPE *__restrict ldata, RIGHT_TYPE *__restrict rdata,
RESULT_TYPE *__restrict result_data, const SelectionVector *__restrict lsel,
const SelectionVector *__restrict rsel, idx_t count, ValidityMask &lvalidity,
ValidityMask &rvalidity, ValidityMask &result_validity, FUNC fun) {
if (!lvalidity.AllValid() || !rvalidity.AllValid()) {
for (idx_t i = 0; i < count; i++) {
auto lindex = lsel->get_index(i);
auto rindex = rsel->get_index(i);
if (lvalidity.RowIsValid(lindex) && rvalidity.RowIsValid(rindex)) {
auto lentry = ldata[lindex];
auto rentry = rdata[rindex];
result_data[i] = OPWRAPPER::template Operation<FUNC, OP, LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE>(
fun, lentry, rentry, result_validity, i);
} else {
result_validity.SetInvalid(i);
}
}
} else {
for (idx_t i = 0; i < count; i++) {
auto lentry = ldata[lsel->get_index(i)];
auto rentry = rdata[rsel->get_index(i)];
result_data[i] = OPWRAPPER::template Operation<FUNC, OP, LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE>(
fun, lentry, rentry, result_validity, i);
}
}
}
template <class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE, class OPWRAPPER, class OP, class FUNC>
static void ExecuteGeneric(Vector &left, Vector &right, Vector &result, idx_t count, FUNC fun) {
VectorData ldata, rdata;
left.Orrify(count, ldata);
right.Orrify(count, rdata);
result.SetVectorType(VectorType::FLAT_VECTOR);
auto result_data = FlatVector::GetData<RESULT_TYPE>(result);
ExecuteGenericLoop<LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE, OPWRAPPER, OP, FUNC>(
(LEFT_TYPE *)ldata.data, (RIGHT_TYPE *)rdata.data, result_data, ldata.sel, rdata.sel, count, ldata.validity,
rdata.validity, FlatVector::Validity(result), fun);
}
template <class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE, class OPWRAPPER, class OP, class FUNC>
static void ExecuteSwitch(Vector &left, Vector &right, Vector &result, idx_t count, FUNC fun) {
auto left_vector_type = left.GetVectorType();
auto right_vector_type = right.GetVectorType();
if (left_vector_type == VectorType::CONSTANT_VECTOR && right_vector_type == VectorType::CONSTANT_VECTOR) {
ExecuteConstant<LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE, OPWRAPPER, OP, FUNC>(left, right, result, fun);
} else if (left_vector_type == VectorType::FLAT_VECTOR && right_vector_type == VectorType::CONSTANT_VECTOR) {
ExecuteFlat<LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE, OPWRAPPER, OP, FUNC, false, true>(left, right, result,
count, fun);
} else if (left_vector_type == VectorType::CONSTANT_VECTOR && right_vector_type == VectorType::FLAT_VECTOR) {
ExecuteFlat<LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE, OPWRAPPER, OP, FUNC, true, false>(left, right, result,
count, fun);
} else if (left_vector_type == VectorType::FLAT_VECTOR && right_vector_type == VectorType::FLAT_VECTOR) {
ExecuteFlat<LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE, OPWRAPPER, OP, FUNC, false, false>(left, right, result,
count, fun);
} else {
ExecuteGeneric<LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE, OPWRAPPER, OP, FUNC>(left, right, result, count, fun);
}
}
public:
template <class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE,
class FUNC = std::function<RESULT_TYPE(LEFT_TYPE, RIGHT_TYPE)>>
static void Execute(Vector &left, Vector &right, Vector &result, idx_t count, FUNC fun) {
ExecuteSwitch<LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE, BinaryLambdaWrapper, bool, FUNC>(left, right, result, count,
fun);
}
template <class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE, class OP,
class OPWRAPPER = BinarySingleArgumentOperatorWrapper>
static void Execute(Vector &left, Vector &right, Vector &result, idx_t count) {
ExecuteSwitch<LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE, OPWRAPPER, OP, bool>(left, right, result, count, false);
}
template <class LEFT_TYPE, class RIGHT_TYPE, class RESULT_TYPE, class OP>
static void ExecuteStandard(Vector &left, Vector &right, Vector &result, idx_t count) {
ExecuteSwitch<LEFT_TYPE, RIGHT_TYPE, RESULT_TYPE, BinaryStandardOperatorWrapper, OP, bool>(left, right, result,
count, false);
}
public:
template <class LEFT_TYPE, class RIGHT_TYPE, class OP>
static idx_t SelectConstant(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel) {
auto ldata = ConstantVector::GetData<LEFT_TYPE>(left);
auto rdata = ConstantVector::GetData<RIGHT_TYPE>(right);
if (ConstantVector::IsNull(left) || ConstantVector::IsNull(right) || !OP::Operation(*ldata, *rdata)) {
if (false_sel) {
for (idx_t i = 0; i < count; i++) {
false_sel->set_index(i, sel->get_index(i));
}
}
return 0;
} else {
if (true_sel) {
for (idx_t i = 0; i < count; i++) {
true_sel->set_index(i, sel->get_index(i));
}
}
return count;
}
}
template <class LEFT_TYPE, class RIGHT_TYPE, class OP, bool LEFT_CONSTANT, bool RIGHT_CONSTANT, bool HAS_TRUE_SEL,
bool HAS_FALSE_SEL>
static inline idx_t SelectFlatLoop(LEFT_TYPE *__restrict ldata, RIGHT_TYPE *__restrict rdata,
const SelectionVector *sel, idx_t count, ValidityMask &validity_mask,
SelectionVector *true_sel, SelectionVector *false_sel) {
idx_t true_count = 0, false_count = 0;
idx_t base_idx = 0;
auto entry_count = ValidityMask::EntryCount(count);
for (idx_t entry_idx = 0; entry_idx < entry_count; entry_idx++) {
auto validity_entry = validity_mask.GetValidityEntry(entry_idx);
idx_t next = MinValue<idx_t>(base_idx + ValidityMask::BITS_PER_VALUE, count);
if (ValidityMask::AllValid(validity_entry)) {
for (; base_idx < next; base_idx++) {
idx_t result_idx = sel->get_index(base_idx);
idx_t lidx = LEFT_CONSTANT ? 0 : base_idx;
idx_t ridx = RIGHT_CONSTANT ? 0 : base_idx;
bool comparison_result = OP::Operation(ldata[lidx], rdata[ridx]);
if (HAS_TRUE_SEL) {
true_sel->set_index(true_count, result_idx);
true_count += comparison_result;
}
if (HAS_FALSE_SEL) {
false_sel->set_index(false_count, result_idx);
false_count += !comparison_result;
}
}
} else if (ValidityMask::NoneValid(validity_entry)) {
if (HAS_FALSE_SEL) {
for (; base_idx < next; base_idx++) {
idx_t result_idx = sel->get_index(base_idx);
false_sel->set_index(false_count, result_idx);
false_count++;
}
}
base_idx = next;
continue;
} else {
idx_t start = base_idx;
for (; base_idx < next; base_idx++) {
idx_t result_idx = sel->get_index(base_idx);
idx_t lidx = LEFT_CONSTANT ? 0 : base_idx;
idx_t ridx = RIGHT_CONSTANT ? 0 : base_idx;
bool comparison_result = ValidityMask::RowIsValid(validity_entry, base_idx - start) &&
OP::Operation(ldata[lidx], rdata[ridx]);
if (HAS_TRUE_SEL) {
true_sel->set_index(true_count, result_idx);
true_count += comparison_result;
}
if (HAS_FALSE_SEL) {
false_sel->set_index(false_count, result_idx);
false_count += !comparison_result;
}
}
}
}
if (HAS_TRUE_SEL) {
return true_count;
} else {
return count - false_count;
}
}
template <class LEFT_TYPE, class RIGHT_TYPE, class OP, bool LEFT_CONSTANT, bool RIGHT_CONSTANT>
static inline idx_t SelectFlatLoopSwitch(LEFT_TYPE *__restrict ldata, RIGHT_TYPE *__restrict rdata,
const SelectionVector *sel, idx_t count, ValidityMask &mask,
SelectionVector *true_sel, SelectionVector *false_sel) {
if (true_sel && false_sel) {
return SelectFlatLoop<LEFT_TYPE, RIGHT_TYPE, OP, LEFT_CONSTANT, RIGHT_CONSTANT, true, true>(
ldata, rdata, sel, count, mask, true_sel, false_sel);
} else if (true_sel) {
return SelectFlatLoop<LEFT_TYPE, RIGHT_TYPE, OP, LEFT_CONSTANT, RIGHT_CONSTANT, true, false>(
ldata, rdata, sel, count, mask, true_sel, false_sel);
} else {
D_ASSERT(false_sel);
return SelectFlatLoop<LEFT_TYPE, RIGHT_TYPE, OP, LEFT_CONSTANT, RIGHT_CONSTANT, false, true>(
ldata, rdata, sel, count, mask, true_sel, false_sel);
}
}
template <class LEFT_TYPE, class RIGHT_TYPE, class OP, bool LEFT_CONSTANT, bool RIGHT_CONSTANT>
static idx_t SelectFlat(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel) {
auto ldata = FlatVector::GetData<LEFT_TYPE>(left);
auto rdata = FlatVector::GetData<RIGHT_TYPE>(right);
if (LEFT_CONSTANT && ConstantVector::IsNull(left)) {
return 0;
}
if (RIGHT_CONSTANT && ConstantVector::IsNull(right)) {
return 0;
}
if (LEFT_CONSTANT) {
return SelectFlatLoopSwitch<LEFT_TYPE, RIGHT_TYPE, OP, LEFT_CONSTANT, RIGHT_CONSTANT>(
ldata, rdata, sel, count, FlatVector::Validity(right), true_sel, false_sel);
} else if (RIGHT_CONSTANT) {
return SelectFlatLoopSwitch<LEFT_TYPE, RIGHT_TYPE, OP, LEFT_CONSTANT, RIGHT_CONSTANT>(
ldata, rdata, sel, count, FlatVector::Validity(left), true_sel, false_sel);
} else {
ValidityMask combined_mask = FlatVector::Validity(left);
combined_mask.Combine(FlatVector::Validity(right), count);
return SelectFlatLoopSwitch<LEFT_TYPE, RIGHT_TYPE, OP, LEFT_CONSTANT, RIGHT_CONSTANT>(
ldata, rdata, sel, count, combined_mask, true_sel, false_sel);
}
}
template <class LEFT_TYPE, class RIGHT_TYPE, class OP, bool NO_NULL, bool HAS_TRUE_SEL, bool HAS_FALSE_SEL>
static inline idx_t
SelectGenericLoop(LEFT_TYPE *__restrict ldata, RIGHT_TYPE *__restrict rdata, const SelectionVector *__restrict lsel,
const SelectionVector *__restrict rsel, const SelectionVector *__restrict result_sel, idx_t count,
ValidityMask &lvalidity, ValidityMask &rvalidity, SelectionVector *true_sel,
SelectionVector *false_sel) {
idx_t true_count = 0, false_count = 0;
for (idx_t i = 0; i < count; i++) {
auto result_idx = result_sel->get_index(i);
auto lindex = lsel->get_index(i);
auto rindex = rsel->get_index(i);
if ((NO_NULL || (lvalidity.RowIsValid(lindex) && rvalidity.RowIsValid(rindex))) &&
OP::Operation(ldata[lindex], rdata[rindex])) {
if (HAS_TRUE_SEL) {
true_sel->set_index(true_count++, result_idx);
}
} else {
if (HAS_FALSE_SEL) {
false_sel->set_index(false_count++, result_idx);
}
}
}
if (HAS_TRUE_SEL) {
return true_count;
} else {
return count - false_count;
}
}
template <class LEFT_TYPE, class RIGHT_TYPE, class OP, bool NO_NULL>
static inline idx_t
SelectGenericLoopSelSwitch(LEFT_TYPE *__restrict ldata, RIGHT_TYPE *__restrict rdata,
const SelectionVector *__restrict lsel, const SelectionVector *__restrict rsel,
const SelectionVector *__restrict result_sel, idx_t count, ValidityMask &lvalidity,
ValidityMask &rvalidity, SelectionVector *true_sel, SelectionVector *false_sel) {
if (true_sel && false_sel) {
return SelectGenericLoop<LEFT_TYPE, RIGHT_TYPE, OP, NO_NULL, true, true>(
ldata, rdata, lsel, rsel, result_sel, count, lvalidity, rvalidity, true_sel, false_sel);
} else if (true_sel) {
return SelectGenericLoop<LEFT_TYPE, RIGHT_TYPE, OP, NO_NULL, true, false>(
ldata, rdata, lsel, rsel, result_sel, count, lvalidity, rvalidity, true_sel, false_sel);
} else {
D_ASSERT(false_sel);
return SelectGenericLoop<LEFT_TYPE, RIGHT_TYPE, OP, NO_NULL, false, true>(
ldata, rdata, lsel, rsel, result_sel, count, lvalidity, rvalidity, true_sel, false_sel);
}
}
template <class LEFT_TYPE, class RIGHT_TYPE, class OP>
static inline idx_t
SelectGenericLoopSwitch(LEFT_TYPE *__restrict ldata, RIGHT_TYPE *__restrict rdata,
const SelectionVector *__restrict lsel, const SelectionVector *__restrict rsel,
const SelectionVector *__restrict result_sel, idx_t count, ValidityMask &lvalidity,
ValidityMask &rvalidity, SelectionVector *true_sel, SelectionVector *false_sel) {
if (!lvalidity.AllValid() || !rvalidity.AllValid()) {
return SelectGenericLoopSelSwitch<LEFT_TYPE, RIGHT_TYPE, OP, false>(
ldata, rdata, lsel, rsel, result_sel, count, lvalidity, rvalidity, true_sel, false_sel);
} else {
return SelectGenericLoopSelSwitch<LEFT_TYPE, RIGHT_TYPE, OP, true>(
ldata, rdata, lsel, rsel, result_sel, count, lvalidity, rvalidity, true_sel, false_sel);
}
}
template <class LEFT_TYPE, class RIGHT_TYPE, class OP>
static idx_t SelectGeneric(Vector &left, Vector &right, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel) {
VectorData ldata, rdata;
left.Orrify(count, ldata);
right.Orrify(count, rdata);
return SelectGenericLoopSwitch<LEFT_TYPE, RIGHT_TYPE, OP>((LEFT_TYPE *)ldata.data, (RIGHT_TYPE *)rdata.data,
ldata.sel, rdata.sel, sel, count, ldata.validity,
rdata.validity, true_sel, false_sel);
}
template <class LEFT_TYPE, class RIGHT_TYPE, class OP>
static idx_t Select(Vector &left, Vector &right, const SelectionVector *sel, idx_t count, SelectionVector *true_sel,
SelectionVector *false_sel) {
if (!sel) {
sel = &FlatVector::INCREMENTAL_SELECTION_VECTOR;
}
if (left.GetVectorType() == VectorType::CONSTANT_VECTOR &&
right.GetVectorType() == VectorType::CONSTANT_VECTOR) {
return SelectConstant<LEFT_TYPE, RIGHT_TYPE, OP>(left, right, sel, count, true_sel, false_sel);
} else if (left.GetVectorType() == VectorType::CONSTANT_VECTOR &&
right.GetVectorType() == VectorType::FLAT_VECTOR) {
return SelectFlat<LEFT_TYPE, RIGHT_TYPE, OP, true, false>(left, right, sel, count, true_sel, false_sel);
} else if (left.GetVectorType() == VectorType::FLAT_VECTOR &&
right.GetVectorType() == VectorType::CONSTANT_VECTOR) {
return SelectFlat<LEFT_TYPE, RIGHT_TYPE, OP, false, true>(left, right, sel, count, true_sel, false_sel);
} else if (left.GetVectorType() == VectorType::FLAT_VECTOR &&
right.GetVectorType() == VectorType::FLAT_VECTOR) {
return SelectFlat<LEFT_TYPE, RIGHT_TYPE, OP, false, false>(left, right, sel, count, true_sel, false_sel);
} else {
return SelectGeneric<LEFT_TYPE, RIGHT_TYPE, OP>(left, right, sel, count, true_sel, false_sel);
}
}
};
}
#include <functional>
namespace duckdb {
struct TernaryExecutor {
private:
template <class A_TYPE, class B_TYPE, class C_TYPE, class RESULT_TYPE, class FUN>
static inline void ExecuteLoop(A_TYPE *__restrict adata, B_TYPE *__restrict bdata, C_TYPE *__restrict cdata,
RESULT_TYPE *__restrict result_data, idx_t count, const SelectionVector &asel,
const SelectionVector &bsel, const SelectionVector &csel, ValidityMask &avalidity,
ValidityMask &bvalidity, ValidityMask &cvalidity, ValidityMask &result_validity,
FUN fun) {
if (!avalidity.AllValid() || !bvalidity.AllValid() || !cvalidity.AllValid()) {
for (idx_t i = 0; i < count; i++) {
auto aidx = asel.get_index(i);
auto bidx = bsel.get_index(i);
auto cidx = csel.get_index(i);
if (avalidity.RowIsValid(aidx) && bvalidity.RowIsValid(bidx) && cvalidity.RowIsValid(cidx)) {
result_data[i] = fun(adata[aidx], bdata[bidx], cdata[cidx]);
} else {
result_validity.SetInvalid(i);
}
}
} else {
for (idx_t i = 0; i < count; i++) {
auto aidx = asel.get_index(i);
auto bidx = bsel.get_index(i);
auto cidx = csel.get_index(i);
result_data[i] = fun(adata[aidx], bdata[bidx], cdata[cidx]);
}
}
}
public:
template <class A_TYPE, class B_TYPE, class C_TYPE, class RESULT_TYPE,
class FUN = std::function<RESULT_TYPE(A_TYPE, B_TYPE, C_TYPE)>>
static void Execute(Vector &a, Vector &b, Vector &c, Vector &result, idx_t count, FUN fun) {
if (a.GetVectorType() == VectorType::CONSTANT_VECTOR && b.GetVectorType() == VectorType::CONSTANT_VECTOR &&
c.GetVectorType() == VectorType::CONSTANT_VECTOR) {
result.SetVectorType(VectorType::CONSTANT_VECTOR);
if (ConstantVector::IsNull(a) || ConstantVector::IsNull(b) || ConstantVector::IsNull(c)) {
ConstantVector::SetNull(result, true);
} else {
auto adata = ConstantVector::GetData<A_TYPE>(a);
auto bdata = ConstantVector::GetData<B_TYPE>(b);
auto cdata = ConstantVector::GetData<C_TYPE>(c);
auto result_data = ConstantVector::GetData<RESULT_TYPE>(result);
result_data[0] = fun(*adata, *bdata, *cdata);
}
} else {
result.SetVectorType(VectorType::FLAT_VECTOR);
VectorData adata, bdata, cdata;
a.Orrify(count, adata);
b.Orrify(count, bdata);
c.Orrify(count, cdata);
ExecuteLoop<A_TYPE, B_TYPE, C_TYPE, RESULT_TYPE>(
(A_TYPE *)adata.data, (B_TYPE *)bdata.data, (C_TYPE *)cdata.data,
FlatVector::GetData<RESULT_TYPE>(result), count, *adata.sel, *bdata.sel, *cdata.sel, adata.validity,
bdata.validity, cdata.validity, FlatVector::Validity(result), fun);
}
}
private:
template <class A_TYPE, class B_TYPE, class C_TYPE, class OP, bool NO_NULL, bool HAS_TRUE_SEL, bool HAS_FALSE_SEL>
static inline idx_t SelectLoop(A_TYPE *__restrict adata, B_TYPE *__restrict bdata, C_TYPE *__restrict cdata,
const SelectionVector *result_sel, idx_t count, const SelectionVector &asel,
const SelectionVector &bsel, const SelectionVector &csel, ValidityMask &avalidity,
ValidityMask &bvalidity, ValidityMask &cvalidity, SelectionVector *true_sel,
SelectionVector *false_sel) {
idx_t true_count = 0, false_count = 0;
for (idx_t i = 0; i < count; i++) {
auto result_idx = result_sel->get_index(i);
auto aidx = asel.get_index(i);
auto bidx = bsel.get_index(i);
auto cidx = csel.get_index(i);
bool comparison_result =
(NO_NULL || (avalidity.RowIsValid(aidx) && bvalidity.RowIsValid(bidx) && cvalidity.RowIsValid(cidx))) &&
OP::Operation(adata[aidx], bdata[bidx], cdata[cidx]);
if (HAS_TRUE_SEL) {
true_sel->set_index(true_count, result_idx);
true_count += comparison_result;
}
if (HAS_FALSE_SEL) {
false_sel->set_index(false_count, result_idx);
false_count += !comparison_result;
}
}
if (HAS_TRUE_SEL) {
return true_count;
} else {
return count - false_count;
}
}
template <class A_TYPE, class B_TYPE, class C_TYPE, class OP, bool NO_NULL>
static inline idx_t SelectLoopSelSwitch(VectorData &adata, VectorData &bdata, VectorData &cdata,
const SelectionVector *sel, idx_t count, SelectionVector *true_sel,
SelectionVector *false_sel) {
if (true_sel && false_sel) {
return SelectLoop<A_TYPE, B_TYPE, C_TYPE, OP, NO_NULL, true, true>(
(A_TYPE *)adata.data, (B_TYPE *)bdata.data, (C_TYPE *)cdata.data, sel, count, *adata.sel, *bdata.sel,
*cdata.sel, adata.validity, bdata.validity, cdata.validity, true_sel, false_sel);
} else if (true_sel) {
return SelectLoop<A_TYPE, B_TYPE, C_TYPE, OP, NO_NULL, true, false>(
(A_TYPE *)adata.data, (B_TYPE *)bdata.data, (C_TYPE *)cdata.data, sel, count, *adata.sel, *bdata.sel,
*cdata.sel, adata.validity, bdata.validity, cdata.validity, true_sel, false_sel);
} else {
D_ASSERT(false_sel);
return SelectLoop<A_TYPE, B_TYPE, C_TYPE, OP, NO_NULL, false, true>(
(A_TYPE *)adata.data, (B_TYPE *)bdata.data, (C_TYPE *)cdata.data, sel, count, *adata.sel, *bdata.sel,
*cdata.sel, adata.validity, bdata.validity, cdata.validity, true_sel, false_sel);
}
}
template <class A_TYPE, class B_TYPE, class C_TYPE, class OP>
static inline idx_t SelectLoopSwitch(VectorData &adata, VectorData &bdata, VectorData &cdata,
const SelectionVector *sel, idx_t count, SelectionVector *true_sel,
SelectionVector *false_sel) {
if (!adata.validity.AllValid() || !bdata.validity.AllValid() || !cdata.validity.AllValid()) {
return SelectLoopSelSwitch<A_TYPE, B_TYPE, C_TYPE, OP, false>(adata, bdata, cdata, sel, count, true_sel,
false_sel);
} else {
return SelectLoopSelSwitch<A_TYPE, B_TYPE, C_TYPE, OP, true>(adata, bdata, cdata, sel, count, true_sel,
false_sel);
}
}
public:
template <class A_TYPE, class B_TYPE, class C_TYPE, class OP>
static idx_t Select(Vector &a, Vector &b, Vector &c, const SelectionVector *sel, idx_t count,
SelectionVector *true_sel, SelectionVector *false_sel) {
if (!sel) {
sel = &FlatVector::INCREMENTAL_SELECTION_VECTOR;
}
VectorData adata, bdata, cdata;
a.Orrify(count, adata);
b.Orrify(count, bdata);
c.Orrify(count, cdata);
return SelectLoopSwitch<A_TYPE, B_TYPE, C_TYPE, OP>(adata, bdata, cdata, sel, count, true_sel, false_sel);
}
};
}
#include <functional>
namespace duckdb {
struct UnaryOperatorWrapper {
template <class OP, class INPUT_TYPE, class RESULT_TYPE>
static inline RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) {
return OP::template Operation<INPUT_TYPE, RESULT_TYPE>(input);
}
};
struct UnaryLambdaWrapper {
template <class FUNC, class INPUT_TYPE, class RESULT_TYPE>
static inline RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) {
auto fun = (FUNC *)dataptr;
return (*fun)(input);
}
};
struct GenericUnaryWrapper {
template <class OP, class INPUT_TYPE, class RESULT_TYPE>
static inline RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) {
return OP::template Operation<INPUT_TYPE, RESULT_TYPE>(input, mask, idx, dataptr);
}
};
template <class OP>
struct UnaryStringOperator {
template <class INPUT_TYPE, class RESULT_TYPE>
static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) {
auto vector = (Vector *)dataptr;
return OP::template Operation<INPUT_TYPE, RESULT_TYPE>(input, *vector);
}
};
struct UnaryExecutor {
private:
template <class INPUT_TYPE, class RESULT_TYPE, class OPWRAPPER, class OP>
static inline void ExecuteLoop(INPUT_TYPE *__restrict ldata, RESULT_TYPE *__restrict result_data, idx_t count,
const SelectionVector *__restrict sel_vector, ValidityMask &mask,
ValidityMask &result_mask, void *dataptr, bool adds_nulls) {
ASSERT_RESTRICT(ldata, ldata + count, result_data, result_data + count);
if (!mask.AllValid()) {
result_mask.EnsureWritable();
for (idx_t i = 0; i < count; i++) {
auto idx = sel_vector->get_index(i);
if (mask.RowIsValidUnsafe(idx)) {
result_data[i] =
OPWRAPPER::template Operation<OP, INPUT_TYPE, RESULT_TYPE>(ldata[idx], result_mask, i, dataptr);
} else {
result_mask.SetInvalid(i);
}
}
} else {
if (adds_nulls) {
result_mask.EnsureWritable();
}
for (idx_t i = 0; i < count; i++) {
auto idx = sel_vector->get_index(i);
result_data[i] =
OPWRAPPER::template Operation<OP, INPUT_TYPE, RESULT_TYPE>(ldata[idx], result_mask, i, dataptr);
}
}
}
template <class INPUT_TYPE, class RESULT_TYPE, class OPWRAPPER, class OP>
static inline void ExecuteFlat(INPUT_TYPE *__restrict ldata, RESULT_TYPE *__restrict result_data, idx_t count,
ValidityMask &mask, ValidityMask &result_mask, void *dataptr, bool adds_nulls) {
ASSERT_RESTRICT(ldata, ldata + count, result_data, result_data + count);
if (!mask.AllValid()) {
if (!adds_nulls) {
result_mask.Initialize(mask);
} else {
result_mask.Copy(mask, count);
}
idx_t base_idx = 0;
auto entry_count = ValidityMask::EntryCount(count);
for (idx_t entry_idx = 0; entry_idx < entry_count; entry_idx++) {
auto validity_entry = mask.GetValidityEntry(entry_idx);
idx_t next = MinValue<idx_t>(base_idx + ValidityMask::BITS_PER_VALUE, count);
if (ValidityMask::AllValid(validity_entry)) {
for (; base_idx < next; base_idx++) {
result_data[base_idx] = OPWRAPPER::template Operation<OP, INPUT_TYPE, RESULT_TYPE>(
ldata[base_idx], result_mask, base_idx, dataptr);
}
} else if (ValidityMask::NoneValid(validity_entry)) {
base_idx = next;
continue;
} else {
idx_t start = base_idx;
for (; base_idx < next; base_idx++) {
if (ValidityMask::RowIsValid(validity_entry, base_idx - start)) {
D_ASSERT(mask.RowIsValid(base_idx));
result_data[base_idx] = OPWRAPPER::template Operation<OP, INPUT_TYPE, RESULT_TYPE>(
ldata[base_idx], result_mask, base_idx, dataptr);
}
}
}
}
} else {
if (adds_nulls) {
result_mask.EnsureWritable();
}
for (idx_t i = 0; i < count; i++) {
result_data[i] =
OPWRAPPER::template Operation<OP, INPUT_TYPE, RESULT_TYPE>(ldata[i], result_mask, i, dataptr);
}
}
}
template <class INPUT_TYPE, class RESULT_TYPE, class OPWRAPPER, class OP>
static inline void ExecuteStandard(Vector &input, Vector &result, idx_t count, void *dataptr, bool adds_nulls) {
switch (input.GetVectorType()) {
case VectorType::CONSTANT_VECTOR: {
result.SetVectorType(VectorType::CONSTANT_VECTOR);
auto result_data = ConstantVector::GetData<RESULT_TYPE>(result);
auto ldata = ConstantVector::GetData<INPUT_TYPE>(input);
if (ConstantVector::IsNull(input)) {
ConstantVector::SetNull(result, true);
} else {
ConstantVector::SetNull(result, false);
*result_data = OPWRAPPER::template Operation<OP, INPUT_TYPE, RESULT_TYPE>(
*ldata, ConstantVector::Validity(result), 0, dataptr);
}
break;
}
case VectorType::FLAT_VECTOR: {
result.SetVectorType(VectorType::FLAT_VECTOR);
auto result_data = FlatVector::GetData<RESULT_TYPE>(result);
auto ldata = FlatVector::GetData<INPUT_TYPE>(input);
ExecuteFlat<INPUT_TYPE, RESULT_TYPE, OPWRAPPER, OP>(ldata, result_data, count, FlatVector::Validity(input),
FlatVector::Validity(result), dataptr, adds_nulls);
break;
}
default: {
VectorData vdata;
input.Orrify(count, vdata);
result.SetVectorType(VectorType::FLAT_VECTOR);
auto result_data = FlatVector::GetData<RESULT_TYPE>(result);
auto ldata = (INPUT_TYPE *)vdata.data;
ExecuteLoop<INPUT_TYPE, RESULT_TYPE, OPWRAPPER, OP>(ldata, result_data, count, vdata.sel, vdata.validity,
FlatVector::Validity(result), dataptr, adds_nulls);
break;
}
}
}
public:
template <class INPUT_TYPE, class RESULT_TYPE, class OP>
static void Execute(Vector &input, Vector &result, idx_t count) {
ExecuteStandard<INPUT_TYPE, RESULT_TYPE, UnaryOperatorWrapper, OP>(input, result, count, nullptr, false);
}
template <class INPUT_TYPE, class RESULT_TYPE, class FUNC = std::function<RESULT_TYPE(INPUT_TYPE)>>
static void Execute(Vector &input, Vector &result, idx_t count, FUNC fun) {
ExecuteStandard<INPUT_TYPE, RESULT_TYPE, UnaryLambdaWrapper, FUNC>(input, result, count, (void *)&fun, false);
}
template <class INPUT_TYPE, class RESULT_TYPE, class OP>
static void GenericExecute(Vector &input, Vector &result, idx_t count, void *dataptr, bool adds_nulls = false) {
ExecuteStandard<INPUT_TYPE, RESULT_TYPE, GenericUnaryWrapper, OP>(input, result, count, dataptr, adds_nulls);
}
template <class INPUT_TYPE, class RESULT_TYPE, class OP>
static void ExecuteString(Vector &input, Vector &result, idx_t count) {
UnaryExecutor::GenericExecute<string_t, string_t, UnaryStringOperator<OP>>(input, result, count,
(void *)&result);
}
};
}
#include <chrono>
namespace duckdb {
using std::chrono::duration;
using std::chrono::duration_cast;
using std::chrono::high_resolution_clock;
using std::chrono::system_clock;
using std::chrono::time_point;
}
namespace duckdb {
template <class T>
struct NumericLimits {
static T Minimum();
static T Maximum();
static bool IsSigned();
static idx_t Digits();
};
template <>
struct NumericLimits<int8_t> {
static int8_t Minimum();
static int8_t Maximum();
static bool IsSigned() {
return true;
}
static idx_t Digits() {
return 3;
}
};
template <>
struct NumericLimits<int16_t> {
static int16_t Minimum();
static int16_t Maximum();
static bool IsSigned() {
return true;
}
static idx_t Digits() {
return 5;
}
};
template <>
struct NumericLimits<int32_t> {
static int32_t Minimum();
static int32_t Maximum();
static bool IsSigned() {
return true;
}
static idx_t Digits() {
return 10;
}
};
template <>
struct NumericLimits<int64_t> {
static int64_t Minimum();
static int64_t Maximum();
static bool IsSigned() {
return true;
}
static idx_t Digits() {
return 19;
}
};
template <>
struct NumericLimits<hugeint_t> {
static hugeint_t Minimum();
static hugeint_t Maximum();
static bool IsSigned() {
return true;
}
static idx_t Digits() {
return 39;
}
};
template <>
struct NumericLimits<uint8_t> {
static uint8_t Minimum();
static uint8_t Maximum();
static bool IsSigned() {
return false;
}
static idx_t Digits() {
return 3;
}
};
template <>
struct NumericLimits<uint16_t> {
static uint16_t Minimum();
static uint16_t Maximum();
static bool IsSigned() {
return false;
}
static idx_t Digits() {
return 5;
}
};
template <>
struct NumericLimits<uint32_t> {
static uint32_t Minimum();
static uint32_t Maximum();
static bool IsSigned() {
return false;
}
static idx_t Digits() {
return 10;
}
};
template <>
struct NumericLimits<uint64_t> {
static uint64_t Minimum();
static uint64_t Maximum();
static bool IsSigned() {
return false;
}
static idx_t Digits() {
return 20;
}
};
template <>
struct NumericLimits<float> {
static float Minimum();
static float Maximum();
static bool IsSigned() {
return true;
}
static idx_t Digits() {
return 127;
}
};
template <>
struct NumericLimits<double> {
static double Minimum();
static double Maximum();
static bool IsSigned() {
return true;
}
static idx_t Digits() {
return 250;
}
};
}
#include <random>
namespace duckdb {
struct RandomEngine {
std::mt19937 random_engine;
RandomEngine(int64_t seed = -1) {
if (seed < 0) {
std::random_device rd;
random_engine.seed(rd());
} else {
random_engine.seed(seed);
}
}
double NextRandom(double min, double max) {
std::uniform_real_distribution<double> dist(min, max);
return dist(random_engine);
}
double NextRandom() {
return NextRandom(0, 1);
}
uint32_t NextRandomInteger() {
std::uniform_int_distribution<uint32_t> dist(0, NumericLimits<uint32_t>::Maximum());
return dist(random_engine);
}
};
}
namespace duckdb {
class CycleCounter {
friend struct ExpressionInfo;
friend struct ExpressionRootInfo;
static constexpr int SAMPLING_RATE = 50;
static constexpr int SAMPLING_VARIANCE = 100;
public:
CycleCounter() : random(-1) {
}
void BeginSample() {
if (current_count >= next_sample) {
tmp = Tick();
}
}
void EndSample(int chunk_size) {
if (current_count >= next_sample) {
time += Tick() - tmp;
}
if (current_count >= next_sample) {
next_sample = SAMPLING_RATE + random.NextRandomInteger() % SAMPLING_VARIANCE;
++sample_count;
sample_tuples_count += chunk_size;
current_count = 0;
} else {
++current_count;
}
tuples_count += chunk_size;
}
private:
uint64_t Tick() const;
uint64_t tmp;
uint64_t time = 0;
uint64_t current_count = 0;
uint64_t next_sample = 0;
uint64_t sample_count = 0;
uint64_t sample_tuples_count = 0;
uint64_t tuples_count = 0;
RandomEngine random;
};
}
namespace duckdb {
class Expression;
class ExpressionExecutor;
struct ExpressionExecutorState;
struct ExpressionState {
ExpressionState(const Expression &expr, ExpressionExecutorState &root);
virtual ~ExpressionState() {
}
const Expression &expr;
ExpressionExecutorState &root;
vector<unique_ptr<ExpressionState>> child_states;
vector<LogicalType> types;
DataChunk intermediate_chunk;
string name;
CycleCounter profiler;
public:
void AddChild(Expression *expr);
void Finalize();
};
struct ExpressionExecutorState {
explicit ExpressionExecutorState(const string &name);
unique_ptr<ExpressionState> root_state;
ExpressionExecutor *executor;
CycleCounter profiler;
string name;
};
}
#include <unordered_set>
namespace duckdb {
using std::unordered_set;
}
namespace duckdb {
enum class ExpressionType : uint8_t {
INVALID = 0,
OPERATOR_CAST = 12,
OPERATOR_NOT = 13,
OPERATOR_IS_NULL = 14,
OPERATOR_IS_NOT_NULL = 15,
COMPARE_EQUAL = 25,
COMPARE_BOUNDARY_START = COMPARE_EQUAL,
COMPARE_NOTEQUAL = 26,
COMPARE_LESSTHAN = 27,
COMPARE_GREATERTHAN = 28,
COMPARE_LESSTHANOREQUALTO = 29,
COMPARE_GREATERTHANOREQUALTO = 30,
COMPARE_IN = 35,
COMPARE_NOT_IN = 36,
COMPARE_DISTINCT_FROM = 37,
COMPARE_BETWEEN = 38,
COMPARE_NOT_BETWEEN = 39,
COMPARE_NOT_DISTINCT_FROM = 40,
COMPARE_BOUNDARY_END = COMPARE_NOT_DISTINCT_FROM,
CONJUNCTION_AND = 50,
CONJUNCTION_OR = 51,
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,
AGGREGATE = 100,
BOUND_AGGREGATE = 101,
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,
WINDOW_NTH_VALUE = 134,
FUNCTION = 140,
BOUND_FUNCTION = 141,
CASE_EXPR = 150,
OPERATOR_NULLIF = 151,
OPERATOR_COALESCE = 152,
ARRAY_EXTRACT = 153,
ARRAY_SLICE = 154,
STRUCT_EXTRACT = 155,
ARRAY_CONSTRUCTOR = 156,
SUBQUERY = 175,
STAR = 200,
TABLE_STAR = 201,
PLACEHOLDER = 202,
COLUMN_REF = 203,
FUNCTION_REF = 204,
TABLE_REF = 205,
CAST = 225,
BOUND_REF = 227,
BOUND_COLUMN_REF = 228,
BOUND_UNNEST = 229,
COLLATE = 230,
LAMBDA = 231,
POSITIONAL_REFERENCE = 232
};
enum class ExpressionClass : uint8_t {
INVALID = 0,
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,
LAMBDA = 17,
POSITIONAL_REFERENCE = 18,
BETWEEN = 19,
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,
BOUND_EXPRESSION = 50
};
string ExpressionTypeToString(ExpressionType type);
string ExpressionTypeToOperator(ExpressionType type);
ExpressionType NegateComparisionExpression(ExpressionType type);
ExpressionType FlipComparisionExpression(ExpressionType type);
}
namespace duckdb {
class BaseExpression {
public:
BaseExpression(ExpressionType type, ExpressionClass expression_class)
: type(type), expression_class(expression_class) {
}
virtual ~BaseExpression() {
}
ExpressionType GetExpressionType() {
return type;
}
ExpressionClass GetExpressionClass() {
return expression_class;
}
ExpressionType type;
ExpressionClass expression_class;
string alias;
public:
virtual bool IsAggregate() const = 0;
virtual bool IsWindow() const = 0;
virtual bool HasSubquery() const = 0;
virtual bool IsScalar() const = 0;
virtual bool HasParameter() const = 0;
virtual string GetName() const;
virtual string ToString() const = 0;
void Print();
virtual hash_t Hash() const = 0;
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 {
class Serializer;
class Deserializer;
class ParsedExpression : public BaseExpression {
public:
ParsedExpression(ExpressionType type, ExpressionClass expression_class) : BaseExpression(type, expression_class) {
}
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;
virtual unique_ptr<ParsedExpression> Copy() const = 0;
virtual void Serialize(Serializer &serializer);
static unique_ptr<ParsedExpression> Deserialize(Deserializer &source);
protected:
void CopyProperties(const ParsedExpression &other) {
type = other.type;
expression_class = other.expression_class;
alias = other.alias;
}
};
}
namespace duckdb {
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)) {
}
string name;
idx_t oid;
LogicalType type;
unique_ptr<ParsedExpression> default_value;
public:
ColumnDefinition Copy() const;
void Serialize(Serializer &serializer) const;
static ColumnDefinition Deserialize(Deserializer &source);
};
}
namespace duckdb {
class CatalogEntry;
class Catalog;
class ClientContext;
class Expression;
class ExpressionExecutor;
class Transaction;
class AggregateFunction;
class AggregateFunctionSet;
class CopyFunction;
class PragmaFunction;
class ScalarFunctionSet;
class ScalarFunction;
class TableFunctionSet;
class TableFunction;
struct PragmaInfo;
struct FunctionData {
virtual ~FunctionData() {
}
virtual unique_ptr<FunctionData> Copy() {
throw InternalException("Unimplemented copy for FunctionData");
};
virtual bool Equals(FunctionData &other) {
return true;
}
static bool Equals(FunctionData *left, FunctionData *right) {
if (left == right) {
return true;
}
if (!left || !right) {
return false;
}
return left->Equals(*right);
}
};
struct TableFunctionData : public FunctionData {
vector<idx_t> column_ids;
};
struct FunctionParameters {
vector<Value> values;
unordered_map<string, Value> named_parameters;
};
class Function {
public:
explicit Function(string name) : name(name) {
}
virtual ~Function() {
}
string name;
public:
DUCKDB_API static string CallToString(const string &name, const vector<LogicalType> &arguments);
DUCKDB_API static string CallToString(const string &name, const vector<LogicalType> &arguments,
const LogicalType &return_type);
DUCKDB_API static string CallToString(const string &name, const vector<LogicalType> &arguments,
const unordered_map<string, LogicalType> &named_parameters);
static idx_t BindFunction(const string &name, vector<ScalarFunction> &functions, vector<LogicalType> &arguments,
string &error);
static idx_t BindFunction(const string &name, vector<ScalarFunction> &functions,
vector<unique_ptr<Expression>> &arguments, string &error);
static idx_t BindFunction(const string &name, vector<AggregateFunction> &functions, vector<LogicalType> &arguments,
string &error);
static idx_t BindFunction(const string &name, vector<AggregateFunction> &functions,
vector<unique_ptr<Expression>> &arguments, string &error);
static idx_t BindFunction(const string &name, vector<TableFunction> &functions, vector<LogicalType> &arguments,
string &error);
static idx_t BindFunction(const string &name, vector<TableFunction> &functions,
vector<unique_ptr<Expression>> &arguments, string &error);
static idx_t BindFunction(const string &name, vector<PragmaFunction> &functions, PragmaInfo &info, string &error);
};
class SimpleFunction : public Function {
public:
SimpleFunction(string name, vector<LogicalType> arguments,
LogicalType varargs = LogicalType(LogicalTypeId::INVALID))
: Function(name), arguments(move(arguments)), varargs(varargs) {
}
~SimpleFunction() override {
}
vector<LogicalType> arguments;
LogicalType varargs;
public:
virtual string ToString() {
return Function::CallToString(name, arguments);
}
bool HasVarArgs() const {
return varargs.id() != LogicalTypeId::INVALID;
}
};
class SimpleNamedParameterFunction : public SimpleFunction {
public:
SimpleNamedParameterFunction(string name, vector<LogicalType> arguments,
LogicalType varargs = LogicalType(LogicalTypeId::INVALID))
: SimpleFunction(name, move(arguments), varargs) {
}
~SimpleNamedParameterFunction() override {
}
unordered_map<string, LogicalType> named_parameters;
public:
string ToString() override {
return Function::CallToString(name, arguments, named_parameters);
}
bool HasNamedParameters() {
return named_parameters.size() != 0;
}
void EvaluateInputParameters(vector<LogicalType> &arguments, vector<Value> ¶meters,
unordered_map<string, Value> &named_parameters,
vector<unique_ptr<ParsedExpression>> &children);
};
class BaseScalarFunction : public SimpleFunction {
public:
BaseScalarFunction(string name, vector<LogicalType> arguments, LogicalType return_type, bool has_side_effects,
LogicalType varargs = LogicalType(LogicalTypeId::INVALID))
: SimpleFunction(move(name), move(arguments), move(varargs)), return_type(return_type),
has_side_effects(has_side_effects) {
}
~BaseScalarFunction() override {
}
LogicalType return_type;
bool has_side_effects;
public:
hash_t Hash() const;
void CastToFunctionArguments(vector<unique_ptr<Expression>> &children);
string ToString() override {
return Function::CallToString(name, arguments, return_type);
}
};
class BuiltinFunctions {
public:
BuiltinFunctions(ClientContext &transaction, Catalog &catalog);
void Initialize();
public:
void AddFunction(AggregateFunctionSet set);
void AddFunction(AggregateFunction function);
void AddFunction(ScalarFunctionSet set);
void AddFunction(PragmaFunction function);
void AddFunction(const string &name, vector<PragmaFunction> functions);
void AddFunction(ScalarFunction function);
void AddFunction(const vector<string> &names, ScalarFunction function);
void AddFunction(TableFunctionSet set);
void AddFunction(TableFunction function);
void AddFunction(CopyFunction function);
void AddCollation(string name, ScalarFunction function, bool combinable = false,
bool not_required_for_equality = false);
private:
ClientContext &context;
Catalog &catalog;
private:
template <class T>
void Register() {
T::RegisterFunction(*this);
}
void RegisterSQLiteFunctions();
void RegisterReadFunctions();
void RegisterTableFunctions();
void RegisterArrowFunctions();
void RegisterAlgebraicAggregates();
void RegisterDistributiveAggregates();
void RegisterNestedAggregates();
void RegisterHolisticAggregates();
void RegisterRegressiveAggregates();
void RegisterDateFunctions();
void RegisterGenericFunctions();
void RegisterMathFunctions();
void RegisterOperators();
void RegisterStringFunctions();
void RegisterNestedFunctions();
void RegisterSequenceFunctions();
void RegisterTrigonometricsFunctions();
void RegisterPragmaFunctions();
};
}
namespace duckdb {
class Hugeint {
public:
static bool FromString(string str, hugeint_t &result);
static bool FromCString(const char *str, idx_t len, hugeint_t &result);
static string ToString(hugeint_t input);
static hugeint_t FromString(string str) {
hugeint_t result;
FromString(str, result);
return result;
}
template <class T>
static bool TryCast(hugeint_t input, T &result);
template <class T>
static T Cast(hugeint_t input) {
T value;
TryCast(input, value);
return value;
}
template <class T>
static bool TryConvert(T value, hugeint_t &result);
template <class T>
static hugeint_t Convert(T value) {
hugeint_t result;
if (!TryConvert(value, result)) { throw ValueOutOfRangeException(double(value), GetTypeId<T>(), GetTypeId<hugeint_t>());
} return result;
}
static void NegateInPlace(hugeint_t &input) {
input.lower = NumericLimits<uint64_t>::Maximum() - input.lower + 1;
input.upper = -1 - input.upper + (input.lower == 0);
}
static hugeint_t Negate(hugeint_t input) {
NegateInPlace(input);
return input;
}
static bool TryMultiply(hugeint_t lhs, hugeint_t rhs, hugeint_t &result);
static hugeint_t Add(hugeint_t lhs, hugeint_t rhs);
static hugeint_t Subtract(hugeint_t lhs, hugeint_t rhs);
static hugeint_t Multiply(hugeint_t lhs, hugeint_t rhs);
static hugeint_t Divide(hugeint_t lhs, hugeint_t rhs);
static hugeint_t Modulo(hugeint_t lhs, hugeint_t rhs);
static hugeint_t DivMod(hugeint_t lhs, hugeint_t rhs, hugeint_t &remainder);
static hugeint_t DivModPositive(hugeint_t lhs, uint64_t rhs, uint64_t &remainder);
static bool AddInPlace(hugeint_t &lhs, hugeint_t rhs);
static bool SubtractInPlace(hugeint_t &lhs, hugeint_t rhs);
static bool Equals(hugeint_t lhs, hugeint_t rhs) {
int lower_equals = lhs.lower == rhs.lower;
int upper_equals = lhs.upper == rhs.upper;
return lower_equals & upper_equals;
}
static bool NotEquals(hugeint_t lhs, hugeint_t rhs) {
int lower_not_equals = lhs.lower != rhs.lower;
int upper_not_equals = lhs.upper != rhs.upper;
return lower_not_equals | upper_not_equals;
}
static bool GreaterThan(hugeint_t lhs, hugeint_t rhs) {
int upper_bigger = lhs.upper > rhs.upper;
int upper_equal = lhs.upper == rhs.upper;
int lower_bigger = lhs.lower > rhs.lower;
return upper_bigger | (upper_equal & lower_bigger);
}
static bool GreaterThanEquals(hugeint_t lhs, hugeint_t rhs) {
int upper_bigger = lhs.upper > rhs.upper;
int upper_equal = lhs.upper == rhs.upper;
int lower_bigger_equals = lhs.lower >= rhs.lower;
return upper_bigger | (upper_equal & lower_bigger_equals);
}
static bool LessThan(hugeint_t lhs, hugeint_t rhs) {
int upper_smaller = lhs.upper < rhs.upper;
int upper_equal = lhs.upper == rhs.upper;
int lower_smaller = lhs.lower < rhs.lower;
return upper_smaller | (upper_equal & lower_smaller);
}
static bool LessThanEquals(hugeint_t lhs, hugeint_t rhs) {
int upper_smaller = lhs.upper < rhs.upper;
int upper_equal = lhs.upper == rhs.upper;
int lower_smaller_equals = lhs.lower <= rhs.lower;
return upper_smaller | (upper_equal & lower_smaller_equals);
}
static const hugeint_t POWERS_OF_TEN[40];
};
template <>
bool Hugeint::TryCast(hugeint_t input, int8_t &result);
template <>
bool Hugeint::TryCast(hugeint_t input, int16_t &result);
template <>
bool Hugeint::TryCast(hugeint_t input, int32_t &result);
template <>
bool Hugeint::TryCast(hugeint_t input, int64_t &result);
template <>
bool Hugeint::TryCast(hugeint_t input, uint8_t &result);
template <>
bool Hugeint::TryCast(hugeint_t input, uint16_t &result);
template <>
bool Hugeint::TryCast(hugeint_t input, uint32_t &result);
template <>
bool Hugeint::TryCast(hugeint_t input, uint64_t &result);
template <>
bool Hugeint::TryCast(hugeint_t input, hugeint_t &result);
template <>
bool Hugeint::TryCast(hugeint_t input, float &result);
template <>
bool Hugeint::TryCast(hugeint_t input, double &result);
template <>
bool Hugeint::TryConvert(int8_t value, hugeint_t &result);
template <>
bool Hugeint::TryConvert(int16_t value, hugeint_t &result);
template <>
bool Hugeint::TryConvert(int32_t value, hugeint_t &result);
template <>
bool Hugeint::TryConvert(int64_t value, hugeint_t &result);
template <>
bool Hugeint::TryConvert(uint8_t value, hugeint_t &result);
template <>
bool Hugeint::TryConvert(uint16_t value, hugeint_t &result);
template <>
bool Hugeint::TryConvert(uint32_t value, hugeint_t &result);
template <>
bool Hugeint::TryConvert(uint64_t value, hugeint_t &result);
template <>
bool Hugeint::TryConvert(float value, hugeint_t &result);
template <>
bool Hugeint::TryConvert(double value, hugeint_t &result);
}
namespace duckdb {
class Interval {
public:
static constexpr const int32_t MONTHS_PER_MILLENIUM = 12000;
static constexpr const int32_t MONTHS_PER_CENTURY = 1200;
static constexpr const int32_t MONTHS_PER_DECADE = 120;
static constexpr const int32_t MONTHS_PER_YEAR = 12;
static constexpr const int32_t MONTHS_PER_QUARTER = 3;
static constexpr const int32_t DAYS_PER_WEEK = 7;
static constexpr const int64_t DAYS_PER_MONTH =
30; static constexpr const int64_t MSECS_PER_SEC = 1000;
static constexpr const int32_t SECS_PER_MINUTE = 60;
static constexpr const int32_t MINS_PER_HOUR = 60;
static constexpr const int32_t HOURS_PER_DAY = 24;
static constexpr const int32_t SECS_PER_HOUR = SECS_PER_MINUTE * MINS_PER_HOUR;
static constexpr const int32_t SECS_PER_DAY = SECS_PER_HOUR * HOURS_PER_DAY;
static constexpr const int32_t SECS_PER_WEEK = SECS_PER_DAY * DAYS_PER_WEEK;
static constexpr const int64_t MICROS_PER_MSEC = 1000;
static constexpr const int64_t MICROS_PER_SEC = MICROS_PER_MSEC * MSECS_PER_SEC;
static constexpr const int64_t MICROS_PER_MINUTE = MICROS_PER_SEC * SECS_PER_MINUTE;
static constexpr const int64_t MICROS_PER_HOUR = MICROS_PER_MINUTE * MINS_PER_HOUR;
static constexpr const int64_t MICROS_PER_DAY = MICROS_PER_HOUR * HOURS_PER_DAY;
static constexpr const int64_t MICROS_PER_WEEK = MICROS_PER_DAY * DAYS_PER_WEEK;
static constexpr const int64_t MICROS_PER_MONTH = MICROS_PER_DAY * DAYS_PER_MONTH;
static constexpr const int64_t NANOS_PER_MICRO = 1000;
static constexpr const int64_t NANOS_PER_MSEC = NANOS_PER_MICRO * MICROS_PER_MSEC;
static constexpr const int64_t NANOS_PER_SEC = NANOS_PER_MSEC * MSECS_PER_SEC;
static constexpr const int64_t NANOS_PER_MINUTE = NANOS_PER_SEC * SECS_PER_MINUTE;
static constexpr const int64_t NANOS_PER_HOUR = NANOS_PER_MINUTE * MINS_PER_HOUR;
static constexpr const int64_t NANOS_PER_DAY = NANOS_PER_HOUR * HOURS_PER_DAY;
static constexpr const int64_t NANOS_PER_WEEK = NANOS_PER_DAY * DAYS_PER_WEEK;
public:
static bool FromString(const string &str, interval_t &result);
static bool FromCString(const char *str, idx_t len, interval_t &result, string *error_message, bool strict);
static string ToString(interval_t date);
static int64_t GetMilli(interval_t val);
static int64_t GetNanoseconds(interval_t val);
static interval_t GetDifference(timestamp_t timestamp_1, timestamp_t timestamp_2);
static bool Equals(interval_t left, interval_t right);
static bool GreaterThan(interval_t left, interval_t right);
static bool GreaterThanEquals(interval_t left, interval_t right);
};
}
#include <cstring>
namespace duckdb {
struct Equals {
template <class T>
static inline bool Operation(T left, T right) {
return left == right;
}
};
struct NotEquals {
template <class T>
static inline bool Operation(T left, T right) {
return left != right;
}
};
struct GreaterThan {
template <class T>
static inline bool Operation(T left, T right) {
return left > right;
}
};
struct GreaterThanEquals {
template <class T>
static inline bool Operation(T left, T right) {
return left >= right;
}
};
struct LessThan {
template <class T>
static inline bool Operation(T left, T right) {
return left < right;
}
};
struct LessThanEquals {
template <class T>
static inline bool Operation(T left, T right) {
return left <= right;
}
};
struct DistinctFrom {
template <class T>
static inline bool Operation(T left, T right, bool left_null, bool right_null) {
return (left_null != right_null) || (!left_null && !right_null && (left != right));
}
};
struct NotDistinctFrom {
template <class T>
static inline bool Operation(T left, T right, bool left_null, bool right_null) {
return (left_null && right_null) || (!left_null && !right_null && (left == right));
}
};
struct DistinctGreaterThan {
template <class T>
static inline bool Operation(T left, T right, bool left_null, bool right_null) {
return GreaterThan::Operation(left_null, right_null) ||
(!left_null && !right_null && GreaterThan::Operation(left, right));
}
};
struct DistinctGreaterThanEquals {
template <class T>
static inline bool Operation(T left, T right, bool left_null, bool right_null) {
return left_null || (!left_null && !right_null && GreaterThanEquals::Operation(left, right));
}
};
struct DistinctLessThan {
template <class T>
static inline bool Operation(T left, T right, bool left_null, bool right_null) {
return LessThan::Operation(left_null, right_null) ||
(!left_null && !right_null && LessThan::Operation(left, right));
}
};
struct DistinctLessThanEquals {
template <class T>
static inline bool Operation(T left, T right, bool left_null, bool right_null) {
return right_null || (!left_null && !right_null && LessThanEquals::Operation(left, right));
}
};
template <>
inline bool GreaterThan::Operation(bool left, bool right) {
return !right && left;
}
template <>
inline bool LessThan::Operation(bool left, bool right) {
return !left && right;
}
struct StringComparisonOperators {
template <bool INVERSE>
static inline bool EqualsOrNot(const string_t a, const string_t b) {
if (a.IsInlined()) {
if (memcmp(&a, &b, sizeof(string_t)) == 0) {
return INVERSE ? false : true;
}
} else {
if (memcmp(&a, &b, sizeof(uint32_t) + string_t::PREFIX_LENGTH) == 0) {
if (memcmp(a.value.pointer.ptr, b.value.pointer.ptr, a.GetSize()) == 0) {
return INVERSE ? false : true;
}
}
}
return INVERSE ? true : false;
}
};
template <>
inline bool Equals::Operation(string_t left, string_t right) {
return StringComparisonOperators::EqualsOrNot<false>(left, right);
}
template <>
inline bool NotEquals::Operation(string_t left, string_t right) {
return StringComparisonOperators::EqualsOrNot<true>(left, right);
}
template <>
inline bool NotDistinctFrom::Operation(string_t left, string_t right, bool left_null, bool right_null) {
return (left_null && right_null) ||
(!left_null && !right_null && StringComparisonOperators::EqualsOrNot<false>(left, right));
}
template <>
inline bool DistinctFrom::Operation(string_t left, string_t right, bool left_null, bool right_null) {
return (left_null != right_null) ||
(!left_null && !right_null && StringComparisonOperators::EqualsOrNot<true>(left, right));
}
template <class OP>
static bool templated_string_compare_op(string_t left, string_t right) {
auto memcmp_res =
memcmp(left.GetDataUnsafe(), right.GetDataUnsafe(), MinValue<idx_t>(left.GetSize(), right.GetSize()));
auto final_res = memcmp_res == 0 ? OP::Operation(left.GetSize(), right.GetSize()) : OP::Operation(memcmp_res, 0);
return final_res;
}
template <>
inline bool GreaterThan::Operation(string_t left, string_t right) {
return templated_string_compare_op<GreaterThan>(left, right);
}
template <>
inline bool GreaterThanEquals::Operation(string_t left, string_t right) {
return templated_string_compare_op<GreaterThanEquals>(left, right);
}
template <>
inline bool LessThan::Operation(string_t left, string_t right) {
return templated_string_compare_op<LessThan>(left, right);
}
template <>
inline bool LessThanEquals::Operation(string_t left, string_t right) {
return templated_string_compare_op<LessThanEquals>(left, right);
}
template <>
inline bool Equals::Operation(interval_t left, interval_t right) {
return Interval::Equals(left, right);
}
template <>
inline bool NotEquals::Operation(interval_t left, interval_t right) {
return !Equals::Operation(left, right);
}
template <>
inline bool GreaterThan::Operation(interval_t left, interval_t right) {
return Interval::GreaterThan(left, right);
}
template <>
inline bool GreaterThanEquals::Operation(interval_t left, interval_t right) {
return Interval::GreaterThanEquals(left, right);
}
template <>
inline bool LessThan::Operation(interval_t left, interval_t right) {
return GreaterThan::Operation(right, left);
}
template <>
inline bool LessThanEquals::Operation(interval_t left, interval_t right) {
return GreaterThanEquals::Operation(right, left);
}
template <>
inline bool NotDistinctFrom::Operation(interval_t left, interval_t right, bool left_null, bool right_null) {
return (left_null && right_null) || (!left_null && !right_null && Interval::Equals(left, right));
}
template <>
inline bool DistinctFrom::Operation(interval_t left, interval_t right, bool left_null, bool right_null) {
return (left_null != right_null) || (!left_null && !right_null && !Equals::Operation(left, right));
}
inline bool operator<(const interval_t &lhs, const interval_t &rhs) {
return LessThan::Operation(lhs, rhs);
}
template <>
inline bool Equals::Operation(hugeint_t left, hugeint_t right) {
return Hugeint::Equals(left, right);
}
template <>
inline bool NotEquals::Operation(hugeint_t left, hugeint_t right) {
return Hugeint::NotEquals(left, right);
}
template <>
inline bool GreaterThan::Operation(hugeint_t left, hugeint_t right) {
return Hugeint::GreaterThan(left, right);
}
template <>
inline bool GreaterThanEquals::Operation(hugeint_t left, hugeint_t right) {
return Hugeint::GreaterThanEquals(left, right);
}
template <>
inline bool LessThan::Operation(hugeint_t left, hugeint_t right) {
return Hugeint::LessThan(left, right);
}
template <>
inline bool LessThanEquals::Operation(hugeint_t left, hugeint_t right) {
return Hugeint::LessThanEquals(left, right);
}
}
namespace duckdb {
struct SelectionVector;
class Serializer;
class Deserializer;
class Vector;
class ValidityStatistics;
class BaseStatistics {
public:
explicit BaseStatistics(LogicalType type);
virtual ~BaseStatistics();
LogicalType type;
unique_ptr<BaseStatistics> validity_stats;
public:
bool CanHaveNull();
bool CanHaveNoNull();
virtual bool IsConstant() {
return false;
}
static unique_ptr<BaseStatistics> CreateEmpty(LogicalType type);
virtual void Merge(const BaseStatistics &other);
virtual unique_ptr<BaseStatistics> Copy();
virtual void Serialize(Serializer &serializer);
static unique_ptr<BaseStatistics> Deserialize(Deserializer &source, LogicalType type);
virtual void Verify(Vector &vector, const SelectionVector &sel, idx_t count);
void Verify(Vector &vector, idx_t count);
virtual string ToString();
};
}
namespace duckdb {
class BoundFunctionExpression;
class ScalarFunctionCatalogEntry;
typedef std::function<void(DataChunk &, ExpressionState &, Vector &)> scalar_function_t;
typedef unique_ptr<FunctionData> (*bind_scalar_function_t)(ClientContext &context, ScalarFunction &bound_function,
vector<unique_ptr<Expression>> &arguments);
typedef unique_ptr<BaseStatistics> (*function_statistics_t)(ClientContext &context, BoundFunctionExpression &expr,
FunctionData *bind_data,
vector<unique_ptr<BaseStatistics>> &child_stats);
typedef void (*dependency_function_t)(BoundFunctionExpression &expr, unordered_set<CatalogEntry *> &dependencies);
class ScalarFunction : public BaseScalarFunction {
public:
ScalarFunction(string name, vector<LogicalType> arguments, LogicalType return_type, scalar_function_t function,
bool has_side_effects = false, bind_scalar_function_t bind = nullptr,
dependency_function_t dependency = nullptr, function_statistics_t statistics = nullptr,
LogicalType varargs = LogicalType(LogicalTypeId::INVALID))
: BaseScalarFunction(name, arguments, return_type, has_side_effects, varargs), function(function), bind(bind),
dependency(dependency), statistics(statistics) {
}
ScalarFunction(vector<LogicalType> arguments, LogicalType return_type, scalar_function_t function,
bool has_side_effects = false, bind_scalar_function_t bind = nullptr,
dependency_function_t dependency = nullptr, function_statistics_t statistics = nullptr,
LogicalType varargs = LogicalType(LogicalTypeId::INVALID))
: ScalarFunction(string(), arguments, return_type, function, has_side_effects, bind, dependency, statistics,
varargs) {
}
scalar_function_t function;
bind_scalar_function_t bind;
dependency_function_t dependency;
function_statistics_t statistics;
static unique_ptr<BoundFunctionExpression> BindScalarFunction(ClientContext &context, const string &schema,
const string &name,
vector<unique_ptr<Expression>> children,
string &error, bool is_operator = false);
static unique_ptr<BoundFunctionExpression> BindScalarFunction(ClientContext &context,
ScalarFunctionCatalogEntry &function,
vector<unique_ptr<Expression>> children,
string &error, bool is_operator = false);
static unique_ptr<BoundFunctionExpression> BindScalarFunction(ClientContext &context, ScalarFunction bound_function,
vector<unique_ptr<Expression>> children,
bool is_operator = false);
bool operator==(const ScalarFunction &rhs) const {
return CompareScalarFunctionT(rhs.function) && bind == rhs.bind && dependency == rhs.dependency &&
statistics == rhs.statistics;
}
bool operator!=(const ScalarFunction &rhs) const {
return !(*this == rhs);
}
bool Equal(const ScalarFunction &rhs) const {
if (this->arguments.size() != rhs.arguments.size()) {
return false;
}
for (idx_t i = 0; i < this->arguments.size(); ++i) {
if (this->arguments[i] != rhs.arguments[i]) {
return false;
}
}
if (this->return_type != rhs.return_type) {
return false;
}
if (this->varargs != rhs.varargs) {
return false;
}
return true; }
private:
bool CompareScalarFunctionT(const scalar_function_t other) const {
typedef void(scalar_function_ptr_t)(DataChunk &, ExpressionState &, Vector &);
auto func_ptr = (scalar_function_ptr_t **)function.template target<scalar_function_ptr_t *>();
auto other_ptr = (scalar_function_ptr_t **)other.template target<scalar_function_ptr_t *>();
if (!func_ptr && !other_ptr) {
return true;
}
if (func_ptr == nullptr || other_ptr == nullptr) {
return false;
}
return ((size_t)*func_ptr == (size_t)*other_ptr);
}
public:
static void NopFunction(DataChunk &input, ExpressionState &state, Vector &result) {
D_ASSERT(input.ColumnCount() >= 1);
result.Reference(input.data[0]);
}
template <class TA, class TR, class OP>
static void UnaryFunction(DataChunk &input, ExpressionState &state, Vector &result) {
D_ASSERT(input.ColumnCount() >= 1);
UnaryExecutor::Execute<TA, TR, OP>(input.data[0], result, input.size());
}
template <class TA, class TB, class TR, class OP>
static void BinaryFunction(DataChunk &input, ExpressionState &state, Vector &result) {
D_ASSERT(input.ColumnCount() == 2);
BinaryExecutor::ExecuteStandard<TA, TB, TR, OP>(input.data[0], input.data[1], result, input.size());
}
public:
template <class OP>
static scalar_function_t GetScalarUnaryFunction(LogicalType type) {
scalar_function_t function;
switch (type.id()) {
case LogicalTypeId::TINYINT:
function = &ScalarFunction::UnaryFunction<int8_t, int8_t, OP>;
break;
case LogicalTypeId::SMALLINT:
function = &ScalarFunction::UnaryFunction<int16_t, int16_t, OP>;
break;
case LogicalTypeId::INTEGER:
function = &ScalarFunction::UnaryFunction<int32_t, int32_t, OP>;
break;
case LogicalTypeId::BIGINT:
function = &ScalarFunction::UnaryFunction<int64_t, int64_t, OP>;
break;
case LogicalTypeId::UTINYINT:
function = &ScalarFunction::UnaryFunction<uint8_t, uint8_t, OP>;
break;
case LogicalTypeId::USMALLINT:
function = &ScalarFunction::UnaryFunction<uint16_t, uint16_t, OP>;
break;
case LogicalTypeId::UINTEGER:
function = &ScalarFunction::UnaryFunction<uint32_t, uint32_t, OP>;
break;
case LogicalTypeId::UBIGINT:
function = &ScalarFunction::UnaryFunction<uint64_t, uint64_t, OP>;
break;
case LogicalTypeId::HUGEINT:
function = &ScalarFunction::UnaryFunction<hugeint_t, hugeint_t, OP>;
break;
case LogicalTypeId::FLOAT:
function = &ScalarFunction::UnaryFunction<float, float, OP>;
break;
case LogicalTypeId::DOUBLE:
function = &ScalarFunction::UnaryFunction<double, double, OP>;
break;
default:
throw InternalException("Unimplemented type for GetScalarUnaryFunction");
}
return function;
}
template <class TR, class OP>
static scalar_function_t GetScalarUnaryFunctionFixedReturn(LogicalType type) {
scalar_function_t function;
switch (type.id()) {
case LogicalTypeId::TINYINT:
function = &ScalarFunction::UnaryFunction<int8_t, TR, OP>;
break;
case LogicalTypeId::SMALLINT:
function = &ScalarFunction::UnaryFunction<int16_t, TR, OP>;
break;
case LogicalTypeId::INTEGER:
function = &ScalarFunction::UnaryFunction<int32_t, TR, OP>;
break;
case LogicalTypeId::BIGINT:
function = &ScalarFunction::UnaryFunction<int64_t, TR, OP>;
break;
case LogicalTypeId::UTINYINT:
function = &ScalarFunction::UnaryFunction<uint8_t, TR, OP>;
break;
case LogicalTypeId::USMALLINT:
function = &ScalarFunction::UnaryFunction<uint16_t, TR, OP>;
break;
case LogicalTypeId::UINTEGER:
function = &ScalarFunction::UnaryFunction<uint32_t, TR, OP>;
break;
case LogicalTypeId::UBIGINT:
function = &ScalarFunction::UnaryFunction<uint64_t, TR, OP>;
break;
case LogicalTypeId::HUGEINT:
function = &ScalarFunction::UnaryFunction<hugeint_t, TR, OP>;
break;
case LogicalTypeId::FLOAT:
function = &ScalarFunction::UnaryFunction<float, TR, OP>;
break;
case LogicalTypeId::DOUBLE:
function = &ScalarFunction::UnaryFunction<double, TR, OP>;
break;
default:
throw InternalException("Unimplemented type for GetScalarUnaryFunctionFixedReturn");
}
return function;
}
};
}
namespace duckdb {
struct FunctionData;
typedef std::pair<idx_t, idx_t> FrameBounds;
class AggregateExecutor {
private:
template <class STATE_TYPE, class OP>
static inline void NullaryFlatLoop(STATE_TYPE **__restrict states, FunctionData *bind_data, idx_t count) {
for (idx_t i = 0; i < count; i++) {
OP::template Operation<STATE_TYPE, OP>(states[i], bind_data, i);
}
}
template <class STATE_TYPE, class OP>
static inline void NullaryScatterLoop(STATE_TYPE **__restrict states, FunctionData *bind_data,
const SelectionVector &ssel, idx_t count) {
for (idx_t i = 0; i < count; i++) {
auto sidx = ssel.get_index(i);
OP::template Operation<STATE_TYPE, OP>(states[sidx], bind_data, sidx);
}
}
template <class STATE_TYPE, class INPUT_TYPE, class OP>
static inline void UnaryFlatLoop(INPUT_TYPE *__restrict idata, FunctionData *bind_data,
STATE_TYPE **__restrict states, ValidityMask &mask, idx_t count) {
if (!mask.AllValid()) {
idx_t base_idx = 0;
auto entry_count = ValidityMask::EntryCount(count);
for (idx_t entry_idx = 0; entry_idx < entry_count; entry_idx++) {
auto validity_entry = mask.GetValidityEntry(entry_idx);
idx_t next = MinValue<idx_t>(base_idx + ValidityMask::BITS_PER_VALUE, count);
if (!OP::IgnoreNull() || ValidityMask::AllValid(validity_entry)) {
for (; base_idx < next; base_idx++) {
OP::template Operation<INPUT_TYPE, STATE_TYPE, OP>(states[base_idx], bind_data, idata, mask,
base_idx);
}
} else if (ValidityMask::NoneValid(validity_entry)) {
base_idx = next;
continue;
} else {
idx_t start = base_idx;
for (; base_idx < next; base_idx++) {
if (ValidityMask::RowIsValid(validity_entry, base_idx - start)) {
OP::template Operation<INPUT_TYPE, STATE_TYPE, OP>(states[base_idx], bind_data, idata, mask,
base_idx);
}
}
}
}
} else {
for (idx_t i = 0; i < count; i++) {
OP::template Operation<INPUT_TYPE, STATE_TYPE, OP>(states[i], bind_data, idata, mask, i);
}
}
}
template <class STATE_TYPE, class INPUT_TYPE, class OP>
static inline void UnaryScatterLoop(INPUT_TYPE *__restrict idata, FunctionData *bind_data,
STATE_TYPE **__restrict states, const SelectionVector &isel,
const SelectionVector &ssel, ValidityMask &mask, idx_t count) {
if (OP::IgnoreNull() && !mask.AllValid()) {
for (idx_t i = 0; i < count; i++) {
auto idx = isel.get_index(i);
auto sidx = ssel.get_index(i);
if (mask.RowIsValid(idx)) {
OP::template Operation<INPUT_TYPE, STATE_TYPE, OP>(states[sidx], bind_data, idata, mask, idx);
}
}
} else {
for (idx_t i = 0; i < count; i++) {
auto idx = isel.get_index(i);
auto sidx = ssel.get_index(i);
OP::template Operation<INPUT_TYPE, STATE_TYPE, OP>(states[sidx], bind_data, idata, mask, idx);
}
}
}
template <class STATE_TYPE, class INPUT_TYPE, class OP>
static inline void UnaryFlatUpdateLoop(INPUT_TYPE *__restrict idata, FunctionData *bind_data,
STATE_TYPE *__restrict state, idx_t count, ValidityMask &mask) {
idx_t base_idx = 0;
auto entry_count = ValidityMask::EntryCount(count);
for (idx_t entry_idx = 0; entry_idx < entry_count; entry_idx++) {
auto validity_entry = mask.GetValidityEntry(entry_idx);
idx_t next = MinValue<idx_t>(base_idx + ValidityMask::BITS_PER_VALUE, count);
if (!OP::IgnoreNull() || ValidityMask::AllValid(validity_entry)) {
for (; base_idx < next; base_idx++) {
OP::template Operation<INPUT_TYPE, STATE_TYPE, OP>(state, bind_data, idata, mask, base_idx);
}
} else if (ValidityMask::NoneValid(validity_entry)) {
base_idx = next;
continue;
} else {
idx_t start = base_idx;
for (; base_idx < next; base_idx++) {
if (ValidityMask::RowIsValid(validity_entry, base_idx - start)) {
OP::template Operation<INPUT_TYPE, STATE_TYPE, OP>(state, bind_data, idata, mask, base_idx);
}
}
}
}
}
template <class STATE_TYPE, class INPUT_TYPE, class OP>
static inline void UnaryUpdateLoop(INPUT_TYPE *__restrict idata, FunctionData *bind_data,
STATE_TYPE *__restrict state, idx_t count, ValidityMask &mask,
const SelectionVector &__restrict sel_vector) {
if (OP::IgnoreNull() && !mask.AllValid()) {
for (idx_t i = 0; i < count; i++) {
auto idx = sel_vector.get_index(i);
if (mask.RowIsValid(idx)) {
OP::template Operation<INPUT_TYPE, STATE_TYPE, OP>(state, bind_data, idata, mask, idx);
}
}
} else {
for (idx_t i = 0; i < count; i++) {
auto idx = sel_vector.get_index(i);
OP::template Operation<INPUT_TYPE, STATE_TYPE, OP>(state, bind_data, idata, mask, idx);
}
}
}
template <class STATE_TYPE, class A_TYPE, class B_TYPE, class OP>
static inline void BinaryScatterLoop(A_TYPE *__restrict adata, FunctionData *bind_data, B_TYPE *__restrict bdata,
STATE_TYPE **__restrict states, idx_t count, const SelectionVector &asel,
const SelectionVector &bsel, const SelectionVector &ssel,
ValidityMask &avalidity, ValidityMask &bvalidity) {
if (OP::IgnoreNull() && (!avalidity.AllValid() || !bvalidity.AllValid())) {
for (idx_t i = 0; i < count; i++) {
auto aidx = asel.get_index(i);
auto bidx = bsel.get_index(i);
auto sidx = ssel.get_index(i);
if (avalidity.RowIsValid(aidx) && bvalidity.RowIsValid(bidx)) {
OP::template Operation<A_TYPE, B_TYPE, STATE_TYPE, OP>(states[sidx], bind_data, adata, bdata,
avalidity, bvalidity, aidx, bidx);
}
}
} else {
for (idx_t i = 0; i < count; i++) {
auto aidx = asel.get_index(i);
auto bidx = bsel.get_index(i);
auto sidx = ssel.get_index(i);
OP::template Operation<A_TYPE, B_TYPE, STATE_TYPE, OP>(states[sidx], bind_data, adata, bdata, avalidity,
bvalidity, aidx, bidx);
}
}
}
template <class STATE_TYPE, class A_TYPE, class B_TYPE, class OP>
static inline void BinaryUpdateLoop(A_TYPE *__restrict adata, FunctionData *bind_data, B_TYPE *__restrict bdata,
STATE_TYPE *__restrict state, idx_t count, const SelectionVector &asel,
const SelectionVector &bsel, ValidityMask &avalidity, ValidityMask &bvalidity) {
if (OP::IgnoreNull() && (!avalidity.AllValid() || !bvalidity.AllValid())) {
for (idx_t i = 0; i < count; i++) {
auto aidx = asel.get_index(i);
auto bidx = bsel.get_index(i);
if (avalidity.RowIsValid(aidx) && bvalidity.RowIsValid(bidx)) {
OP::template Operation<A_TYPE, B_TYPE, STATE_TYPE, OP>(state, bind_data, adata, bdata, avalidity,
bvalidity, aidx, bidx);
}
}
} else {
for (idx_t i = 0; i < count; i++) {
auto aidx = asel.get_index(i);
auto bidx = bsel.get_index(i);
OP::template Operation<A_TYPE, B_TYPE, STATE_TYPE, OP>(state, bind_data, adata, bdata, avalidity,
bvalidity, aidx, bidx);
}
}
}
public:
template <class STATE_TYPE, class OP>
static void NullaryScatter(Vector &states, FunctionData *bind_data, idx_t count) {
if (states.GetVectorType() == VectorType::CONSTANT_VECTOR) {
auto sdata = ConstantVector::GetData<STATE_TYPE *>(states);
OP::template ConstantOperation<STATE_TYPE, OP>(*sdata, bind_data, count);
} else if (states.GetVectorType() == VectorType::FLAT_VECTOR) {
auto sdata = FlatVector::GetData<STATE_TYPE *>(states);
NullaryFlatLoop<STATE_TYPE, OP>(sdata, bind_data, count);
} else {
VectorData sdata;
states.Orrify(count, sdata);
NullaryScatterLoop<STATE_TYPE, OP>((STATE_TYPE **)sdata.data, bind_data, *sdata.sel, count);
}
}
template <class STATE_TYPE, class OP>
static void NullaryUpdate(data_ptr_t state, FunctionData *bind_data, idx_t count) {
OP::template ConstantOperation<STATE_TYPE, OP>((STATE_TYPE *)state, bind_data, count);
}
template <class STATE_TYPE, class INPUT_TYPE, class OP>
static void UnaryScatter(Vector &input, Vector &states, FunctionData *bind_data, idx_t count) {
if (input.GetVectorType() == VectorType::CONSTANT_VECTOR &&
states.GetVectorType() == VectorType::CONSTANT_VECTOR) {
if (OP::IgnoreNull() && ConstantVector::IsNull(input)) {
return;
}
auto idata = ConstantVector::GetData<INPUT_TYPE>(input);
auto sdata = ConstantVector::GetData<STATE_TYPE *>(states);
OP::template ConstantOperation<INPUT_TYPE, STATE_TYPE, OP>(*sdata, bind_data, idata,
ConstantVector::Validity(input), count);
} else if (input.GetVectorType() == VectorType::FLAT_VECTOR &&
states.GetVectorType() == VectorType::FLAT_VECTOR) {
auto idata = FlatVector::GetData<INPUT_TYPE>(input);
auto sdata = FlatVector::GetData<STATE_TYPE *>(states);
UnaryFlatLoop<STATE_TYPE, INPUT_TYPE, OP>(idata, bind_data, sdata, FlatVector::Validity(input), count);
} else {
VectorData idata, sdata;
input.Orrify(count, idata);
states.Orrify(count, sdata);
UnaryScatterLoop<STATE_TYPE, INPUT_TYPE, OP>((INPUT_TYPE *)idata.data, bind_data, (STATE_TYPE **)sdata.data,
*idata.sel, *sdata.sel, idata.validity, count);
}
}
template <class STATE_TYPE, class INPUT_TYPE, class OP>
static void UnaryUpdate(Vector &input, FunctionData *bind_data, data_ptr_t state, idx_t count) {
switch (input.GetVectorType()) {
case VectorType::CONSTANT_VECTOR: {
if (OP::IgnoreNull() && ConstantVector::IsNull(input)) {
return;
}
auto idata = ConstantVector::GetData<INPUT_TYPE>(input);
OP::template ConstantOperation<INPUT_TYPE, STATE_TYPE, OP>((STATE_TYPE *)state, bind_data, idata,
ConstantVector::Validity(input), count);
break;
}
case VectorType::FLAT_VECTOR: {
auto idata = FlatVector::GetData<INPUT_TYPE>(input);
UnaryFlatUpdateLoop<STATE_TYPE, INPUT_TYPE, OP>(idata, bind_data, (STATE_TYPE *)state, count,
FlatVector::Validity(input));
break;
}
default: {
VectorData idata;
input.Orrify(count, idata);
UnaryUpdateLoop<STATE_TYPE, INPUT_TYPE, OP>((INPUT_TYPE *)idata.data, bind_data, (STATE_TYPE *)state, count,
idata.validity, *idata.sel);
break;
}
}
}
template <class STATE_TYPE, class A_TYPE, class B_TYPE, class OP>
static void BinaryScatter(FunctionData *bind_data, Vector &a, Vector &b, Vector &states, idx_t count) {
VectorData adata, bdata, sdata;
a.Orrify(count, adata);
b.Orrify(count, bdata);
states.Orrify(count, sdata);
BinaryScatterLoop<STATE_TYPE, A_TYPE, B_TYPE, OP>((A_TYPE *)adata.data, bind_data, (B_TYPE *)bdata.data,
(STATE_TYPE **)sdata.data, count, *adata.sel, *bdata.sel,
*sdata.sel, adata.validity, bdata.validity);
}
template <class STATE_TYPE, class A_TYPE, class B_TYPE, class OP>
static void BinaryUpdate(FunctionData *bind_data, Vector &a, Vector &b, data_ptr_t state, idx_t count) {
VectorData adata, bdata;
a.Orrify(count, adata);
b.Orrify(count, bdata);
BinaryUpdateLoop<STATE_TYPE, A_TYPE, B_TYPE, OP>((A_TYPE *)adata.data, bind_data, (B_TYPE *)bdata.data,
(STATE_TYPE *)state, count, *adata.sel, *bdata.sel,
adata.validity, bdata.validity);
}
template <class STATE_TYPE, class OP>
static void Combine(Vector &source, Vector &target, idx_t count) {
D_ASSERT(source.GetType().id() == LogicalTypeId::POINTER && target.GetType().id() == LogicalTypeId::POINTER);
auto sdata = FlatVector::GetData<const STATE_TYPE *>(source);
auto tdata = FlatVector::GetData<STATE_TYPE *>(target);
for (idx_t i = 0; i < count; i++) {
OP::template Combine<STATE_TYPE, OP>(*sdata[i], tdata[i]);
}
}
template <class STATE_TYPE, class RESULT_TYPE, class OP>
static void Finalize(Vector &states, FunctionData *bind_data, Vector &result, idx_t count, idx_t offset) {
if (states.GetVectorType() == VectorType::CONSTANT_VECTOR) {
result.SetVectorType(VectorType::CONSTANT_VECTOR);
auto sdata = ConstantVector::GetData<STATE_TYPE *>(states);
auto rdata = ConstantVector::GetData<RESULT_TYPE>(result);
OP::template Finalize<RESULT_TYPE, STATE_TYPE>(result, bind_data, *sdata, rdata,
ConstantVector::Validity(result), 0);
} else {
D_ASSERT(states.GetVectorType() == VectorType::FLAT_VECTOR);
result.SetVectorType(VectorType::FLAT_VECTOR);
auto sdata = FlatVector::GetData<STATE_TYPE *>(states);
auto rdata = FlatVector::GetData<RESULT_TYPE>(result);
for (idx_t i = 0; i < count; i++) {
OP::template Finalize<RESULT_TYPE, STATE_TYPE>(result, bind_data, sdata[i], rdata,
FlatVector::Validity(result), i + offset);
}
}
}
template <class STATE, class INPUT_TYPE, class RESULT_TYPE, class OP>
static void UnaryWindow(Vector &input, FunctionData *bind_data, data_ptr_t state, const FrameBounds &frame,
const FrameBounds &prev, Vector &result, idx_t rid) {
auto idata = FlatVector::GetData<const INPUT_TYPE>(input) - MinValue(frame.first, prev.first);
const auto &ivalid = FlatVector::Validity(input);
OP::template Window<STATE, INPUT_TYPE, RESULT_TYPE>(idata, ivalid, bind_data, (STATE *)state, frame, prev,
result, rid);
}
template <class STATE_TYPE, class OP>
static void Destroy(Vector &states, idx_t count) {
auto sdata = FlatVector::GetData<STATE_TYPE *>(states);
for (idx_t i = 0; i < count; i++) {
OP::template Destroy<STATE_TYPE>(sdata[i]);
}
}
};
}
namespace duckdb {
class NodeStatistics {
public:
NodeStatistics() : has_estimated_cardinality(false), has_max_cardinality(false) {
}
explicit NodeStatistics(idx_t estimated_cardinality)
: has_estimated_cardinality(true), estimated_cardinality(estimated_cardinality), has_max_cardinality(false) {
}
NodeStatistics(idx_t estimated_cardinality, idx_t max_cardinality)
: has_estimated_cardinality(true), estimated_cardinality(estimated_cardinality), has_max_cardinality(true),
max_cardinality(max_cardinality) {
}
bool has_estimated_cardinality;
idx_t estimated_cardinality;
bool has_max_cardinality;
idx_t max_cardinality;
};
}
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 {
enum ResultModifierType : uint8_t { LIMIT_MODIFIER = 1, ORDER_MODIFIER = 2, DISTINCT_MODIFIER = 3 };
class ResultModifier {
public:
explicit ResultModifier(ResultModifierType type) : type(type) {
}
virtual ~ResultModifier() {
}
ResultModifierType type;
public:
virtual bool Equals(const ResultModifier *other) const;
virtual unique_ptr<ResultModifier> Copy() = 0;
virtual void Serialize(Serializer &serializer);
static unique_ptr<ResultModifier> Deserialize(Deserializer &source);
};
struct OrderByNode {
OrderByNode(OrderType type, OrderByNullType null_order, unique_ptr<ParsedExpression> expression)
: type(type), null_order(null_order), expression(move(expression)) {
}
OrderType type;
OrderByNullType null_order;
unique_ptr<ParsedExpression> expression;
public:
void Serialize(Serializer &serializer);
string ToString() const;
static OrderByNode Deserialize(Deserializer &source);
};
class LimitModifier : public ResultModifier {
public:
LimitModifier() : ResultModifier(ResultModifierType::LIMIT_MODIFIER) {
}
unique_ptr<ParsedExpression> limit;
unique_ptr<ParsedExpression> offset;
public:
bool Equals(const ResultModifier *other) const override;
unique_ptr<ResultModifier> Copy() override;
void Serialize(Serializer &serializer) override;
static unique_ptr<ResultModifier> Deserialize(Deserializer &source);
};
class OrderModifier : public ResultModifier {
public:
OrderModifier() : ResultModifier(ResultModifierType::ORDER_MODIFIER) {
}
vector<OrderByNode> orders;
public:
bool Equals(const ResultModifier *other) const override;
unique_ptr<ResultModifier> Copy() override;
void Serialize(Serializer &serializer) override;
static unique_ptr<ResultModifier> Deserialize(Deserializer &source);
};
class DistinctModifier : public ResultModifier {
public:
DistinctModifier() : ResultModifier(ResultModifierType::DISTINCT_MODIFIER) {
}
vector<unique_ptr<ParsedExpression>> distinct_on_targets;
public:
bool Equals(const ResultModifier *other) const override;
unique_ptr<ResultModifier> Copy() override;
void Serialize(Serializer &serializer) override;
static unique_ptr<ResultModifier> Deserialize(Deserializer &source);
};
}
namespace duckdb {
enum class CatalogType : uint8_t {
INVALID = 0,
TABLE_ENTRY = 1,
SCHEMA_ENTRY = 2,
VIEW_ENTRY = 3,
INDEX_ENTRY = 4,
PREPARED_STATEMENT = 5,
SEQUENCE_ENTRY = 6,
COLLATION_ENTRY = 7,
TABLE_FUNCTION_ENTRY = 25,
SCALAR_FUNCTION_ENTRY = 26,
AGGREGATE_FUNCTION_ENTRY = 27,
PRAGMA_FUNCTION_ENTRY = 28,
COPY_FUNCTION_ENTRY = 29,
MACRO_ENTRY = 30,
UPDATED_ENTRY = 50,
DELETED_ENTRY = 51,
};
string CatalogTypeToString(CatalogType type);
}
#include <atomic>
namespace duckdb {
using std::atomic;
}
#include <memory>
namespace duckdb {
struct AlterInfo;
class Catalog;
class CatalogSet;
class ClientContext;
class CatalogEntry {
public:
CatalogEntry(CatalogType type, Catalog *catalog, string name);
virtual ~CatalogEntry();
idx_t oid;
CatalogType type;
Catalog *catalog;
CatalogSet *set;
string name;
bool deleted;
bool temporary;
bool internal;
atomic<transaction_t> timestamp;
unique_ptr<CatalogEntry> child;
CatalogEntry *parent;
public:
virtual unique_ptr<CatalogEntry> AlterEntry(ClientContext &context, AlterInfo *info);
virtual unique_ptr<CatalogEntry> Copy(ClientContext &context);
virtual void SetAsRoot();
virtual string ToSQL();
};
}
#include <mutex>
namespace duckdb {
using std::lock_guard;
using std::mutex;
using std::unique_lock;
}
namespace duckdb {
class SQLStatement;
class QueryErrorContext {
public:
explicit QueryErrorContext(SQLStatement *statement_ = nullptr, idx_t query_location_ = INVALID_INDEX)
: statement(statement_), query_location(query_location_) {
}
SQLStatement *statement;
idx_t query_location;
public:
static string Format(const string &query, const string &error_message, int error_location);
string FormatErrorRecursive(const string &msg, vector<ExceptionFormatValue> &values);
template <class T, typename... Args>
string FormatErrorRecursive(const string &msg, vector<ExceptionFormatValue> &values, T param, Args... params) {
values.push_back(ExceptionFormatValue::CreateFormatValue<T>(param));
return FormatErrorRecursive(msg, values, params...);
}
template <typename... Args>
string FormatError(const string &msg, Args... params) {
vector<ExceptionFormatValue> values;
return FormatErrorRecursive(msg, values, params...);
}
};
}
#include <functional>
namespace duckdb {
struct CreateSchemaInfo;
struct DropInfo;
struct BoundCreateTableInfo;
struct AlterTableInfo;
struct CreateTableFunctionInfo;
struct CreateCopyFunctionInfo;
struct CreatePragmaFunctionInfo;
struct CreateFunctionInfo;
struct CreateViewInfo;
struct CreateSequenceInfo;
struct CreateCollationInfo;
class ClientContext;
class Transaction;
class AggregateFunctionCatalogEntry;
class CollateCatalogEntry;
class SchemaCatalogEntry;
class TableCatalogEntry;
class ViewCatalogEntry;
class SequenceCatalogEntry;
class TableFunctionCatalogEntry;
class CopyFunctionCatalogEntry;
class PragmaFunctionCatalogEntry;
class CatalogSet;
class DatabaseInstance;
class DependencyManager;
class Catalog {
public:
explicit Catalog(DatabaseInstance &db);
~Catalog();
DatabaseInstance &db;
unique_ptr<CatalogSet> schemas;
unique_ptr<DependencyManager> dependency_manager;
mutex write_lock;
public:
static Catalog &GetCatalog(ClientContext &context);
static Catalog &GetCatalog(DatabaseInstance &db);
DependencyManager &GetDependencyManager() {
return *dependency_manager;
}
idx_t GetCatalogVersion();
idx_t ModifyCatalog();
CatalogEntry *CreateSchema(ClientContext &context, CreateSchemaInfo *info);
CatalogEntry *CreateTable(ClientContext &context, BoundCreateTableInfo *info);
CatalogEntry *CreateTableFunction(ClientContext &context, CreateTableFunctionInfo *info);
CatalogEntry *CreateCopyFunction(ClientContext &context, CreateCopyFunctionInfo *info);
CatalogEntry *CreatePragmaFunction(ClientContext &context, CreatePragmaFunctionInfo *info);
CatalogEntry *CreateFunction(ClientContext &context, CreateFunctionInfo *info);
CatalogEntry *CreateView(ClientContext &context, CreateViewInfo *info);
CatalogEntry *CreateSequence(ClientContext &context, CreateSequenceInfo *info);
CatalogEntry *CreateCollation(ClientContext &context, CreateCollationInfo *info);
CatalogEntry *CreateTable(ClientContext &context, SchemaCatalogEntry *schema, BoundCreateTableInfo *info);
CatalogEntry *CreateTableFunction(ClientContext &context, SchemaCatalogEntry *schema,
CreateTableFunctionInfo *info);
CatalogEntry *CreateCopyFunction(ClientContext &context, SchemaCatalogEntry *schema, CreateCopyFunctionInfo *info);
CatalogEntry *CreatePragmaFunction(ClientContext &context, SchemaCatalogEntry *schema,
CreatePragmaFunctionInfo *info);
CatalogEntry *CreateFunction(ClientContext &context, SchemaCatalogEntry *schema, CreateFunctionInfo *info);
CatalogEntry *CreateView(ClientContext &context, SchemaCatalogEntry *schema, CreateViewInfo *info);
CatalogEntry *CreateSequence(ClientContext &context, SchemaCatalogEntry *schema, CreateSequenceInfo *info);
CatalogEntry *CreateCollation(ClientContext &context, SchemaCatalogEntry *schema, CreateCollationInfo *info);
void DropEntry(ClientContext &context, DropInfo *info);
SchemaCatalogEntry *GetSchema(ClientContext &context, const string &name = DEFAULT_SCHEMA,
QueryErrorContext error_context = QueryErrorContext());
void ScanSchemas(ClientContext &context, std::function<void(CatalogEntry *)> callback);
CatalogEntry *GetEntry(ClientContext &context, CatalogType type, string schema, const string &name,
bool if_exists = false, QueryErrorContext error_context = QueryErrorContext());
template <class T>
T *GetEntry(ClientContext &context, string schema_name, const string &name, bool if_exists = false,
QueryErrorContext error_context = QueryErrorContext());
void Alter(ClientContext &context, AlterInfo *info);
private:
atomic<idx_t> catalog_version;
private:
void DropSchema(ClientContext &context, DropInfo *info);
};
template <>
TableCatalogEntry *Catalog::GetEntry(ClientContext &context, string schema_name, const string &name, bool if_exists,
QueryErrorContext error_context);
template <>
SequenceCatalogEntry *Catalog::GetEntry(ClientContext &context, string schema_name, const string &name, bool if_exists,
QueryErrorContext error_context);
template <>
TableFunctionCatalogEntry *Catalog::GetEntry(ClientContext &context, string schema_name, const string &name,
bool if_exists, QueryErrorContext error_context);
template <>
CopyFunctionCatalogEntry *Catalog::GetEntry(ClientContext &context, string schema_name, const string &name,
bool if_exists, QueryErrorContext error_context);
template <>
PragmaFunctionCatalogEntry *Catalog::GetEntry(ClientContext &context, string schema_name, const string &name,
bool if_exists, QueryErrorContext error_context);
template <>
AggregateFunctionCatalogEntry *Catalog::GetEntry(ClientContext &context, string schema_name, const string &name,
bool if_exists, QueryErrorContext error_context);
template <>
CollateCatalogEntry *Catalog::GetEntry(ClientContext &context, string schema_name, const string &name, bool if_exists,
QueryErrorContext error_context);
}
namespace duckdb {
enum class LogicalOperatorType : uint8_t {
LOGICAL_INVALID = 0,
LOGICAL_PROJECTION = 1,
LOGICAL_FILTER = 2,
LOGICAL_AGGREGATE_AND_GROUP_BY = 3,
LOGICAL_WINDOW = 4,
LOGICAL_UNNEST = 5,
LOGICAL_LIMIT = 6,
LOGICAL_ORDER_BY = 7,
LOGICAL_TOP_N = 8,
LOGICAL_COPY_TO_FILE = 10,
LOGICAL_DISTINCT = 11,
LOGICAL_SAMPLE = 12,
LOGICAL_GET = 25,
LOGICAL_CHUNK_GET = 26,
LOGICAL_DELIM_GET = 27,
LOGICAL_EXPRESSION_GET = 28,
LOGICAL_DUMMY_SCAN = 29,
LOGICAL_EMPTY_RESULT = 30,
LOGICAL_CTE_REF = 31,
LOGICAL_JOIN = 50,
LOGICAL_DELIM_JOIN = 51,
LOGICAL_COMPARISON_JOIN = 52,
LOGICAL_ANY_JOIN = 53,
LOGICAL_CROSS_PRODUCT = 54,
LOGICAL_UNION = 75,
LOGICAL_EXCEPT = 76,
LOGICAL_INTERSECT = 77,
LOGICAL_RECURSIVE_CTE = 78,
LOGICAL_INSERT = 100,
LOGICAL_DELETE = 101,
LOGICAL_UPDATE = 102,
LOGICAL_ALTER = 125,
LOGICAL_CREATE_TABLE = 126,
LOGICAL_CREATE_INDEX = 127,
LOGICAL_CREATE_SEQUENCE = 128,
LOGICAL_CREATE_VIEW = 129,
LOGICAL_CREATE_SCHEMA = 130,
LOGICAL_CREATE_MACRO = 131,
LOGICAL_DROP = 132,
LOGICAL_PRAGMA = 133,
LOGICAL_TRANSACTION = 134,
LOGICAL_EXPLAIN = 150,
LOGICAL_SHOW = 160,
LOGICAL_PREPARE = 175,
LOGICAL_EXECUTE = 176,
LOGICAL_EXPORT = 177,
LOGICAL_VACUUM = 178,
LOGICAL_SET = 179,
LOGICAL_LOAD = 180
};
string LogicalOperatorToString(LogicalOperatorType type);
}
namespace duckdb {
class BaseStatistics;
class Expression : public BaseExpression {
public:
Expression(ExpressionType type, ExpressionClass expression_class, LogicalType return_type);
~Expression() override;
LogicalType return_type;
unique_ptr<BaseStatistics> stats;
public:
bool IsAggregate() const override;
bool IsWindow() const override;
bool HasSubquery() const override;
bool IsScalar() const override;
bool HasParameter() const override;
virtual bool HasSideEffects() const;
virtual bool IsFoldable() const;
hash_t Hash() const override;
bool Equals(const BaseExpression *other) const override {
if (!BaseExpression::Equals(other)) {
return false;
}
return return_type == ((Expression *)other)->return_type;
}
static bool Equals(Expression *left, Expression *right) {
return BaseExpression::Equals((BaseExpression *)left, (BaseExpression *)right);
}
virtual unique_ptr<Expression> Copy() = 0;
protected:
void CopyProperties(Expression &other) {
type = other.type;
expression_class = other.expression_class;
alias = other.alias;
return_type = other.return_type;
}
};
}
namespace duckdb {
class BoundQueryNode;
class BoundSelectNode;
class BoundSetOperationNode;
class BoundRecursiveCTENode;
class Expression;
class BoundAggregateExpression;
class BoundBetweenExpression;
class BoundCaseExpression;
class BoundCastExpression;
class BoundColumnRefExpression;
class BoundComparisonExpression;
class BoundConjunctionExpression;
class BoundConstantExpression;
class BoundDefaultExpression;
class BoundFunctionExpression;
class BoundOperatorExpression;
class BoundParameterExpression;
class BoundReferenceExpression;
class BoundSubqueryExpression;
class BoundUnnestExpression;
class BoundWindowExpression;
class BoundTableRef;
class BoundBaseTableRef;
class BoundCrossProductRef;
class BoundJoinRef;
class BoundSubqueryRef;
class BoundTableFunction;
class BoundEmptyTableRef;
class BoundExpressionListRef;
class BoundCTERef;
}
namespace duckdb {
class LogicalOperator;
class LogicalAggregate;
class LogicalAnyJoin;
class LogicalChunkGet;
class LogicalComparisonJoin;
class LogicalCopyToFile;
class LogicalCreate;
class LogicalCreateTable;
class LogicalCreateIndex;
class LogicalCreateTable;
class LogicalCrossProduct;
class LogicalCTERef;
class LogicalDelete;
class LogicalDelimGet;
class LogicalDelimJoin;
class LogicalDistinct;
class LogicalDummyScan;
class LogicalEmptyResult;
class LogicalExecute;
class LogicalExplain;
class LogicalExport;
class LogicalExpressionGet;
class LogicalFilter;
class LogicalGet;
class LogicalInsert;
class LogicalJoin;
class LogicalLimit;
class LogicalOrder;
class LogicalPragma;
class LogicalPrepare;
class LogicalProjection;
class LogicalRecursiveCTE;
class LogicalSetOperation;
class LogicalSample;
class LogicalShow;
class LogicalSimple;
class LogicalSet;
class LogicalTopN;
class LogicalUnnest;
class LogicalUpdate;
class LogicalWindow;
}
#include <functional>
namespace duckdb {
class LogicalOperatorVisitor {
public:
virtual ~LogicalOperatorVisitor() {};
virtual void VisitOperator(LogicalOperator &op);
virtual void VisitExpression(unique_ptr<Expression> *expression);
static void EnumerateExpressions(LogicalOperator &op,
const std::function<void(unique_ptr<Expression> *child)> &callback);
protected:
void VisitOperatorChildren(LogicalOperator &op);
void VisitOperatorExpressions(LogicalOperator &op);
virtual void VisitExpressionChildren(Expression &expression);
virtual unique_ptr<Expression> VisitReplace(BoundAggregateExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundBetweenExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundCaseExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundCastExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundColumnRefExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundComparisonExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundConjunctionExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundConstantExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundDefaultExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundFunctionExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundOperatorExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundReferenceExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundSubqueryExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundParameterExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundWindowExpression &expr, unique_ptr<Expression> *expr_ptr);
virtual unique_ptr<Expression> VisitReplace(BoundUnnestExpression &expr, unique_ptr<Expression> *expr_ptr);
};
}
#include <functional>
namespace duckdb {
struct ColumnBinding {
idx_t table_index;
idx_t column_index;
ColumnBinding() : table_index(INVALID_INDEX), column_index(INVALID_INDEX) {
}
ColumnBinding(idx_t table, idx_t column) : table_index(table), column_index(column) {
}
bool operator==(const ColumnBinding &rhs) const {
return table_index == rhs.table_index && column_index == rhs.column_index;
}
};
}
#include <functional>
#include <algorithm>
namespace duckdb {
class LogicalOperator {
public:
explicit LogicalOperator(LogicalOperatorType type) : type(type) {
}
LogicalOperator(LogicalOperatorType type, vector<unique_ptr<Expression>> expressions)
: type(type), expressions(move(expressions)) {
}
virtual ~LogicalOperator() {
}
LogicalOperatorType type;
vector<unique_ptr<LogicalOperator>> children;
vector<unique_ptr<Expression>> expressions;
vector<LogicalType> types;
idx_t estimated_cardinality = 0;
public:
virtual vector<ColumnBinding> GetColumnBindings() {
return {ColumnBinding(0, 0)};
}
static vector<ColumnBinding> GenerateColumnBindings(idx_t table_idx, idx_t column_count);
static vector<LogicalType> MapTypes(const vector<LogicalType> &types, const vector<idx_t> &projection_map);
static vector<ColumnBinding> MapBindings(const vector<ColumnBinding> &types, const vector<idx_t> &projection_map);
void ResolveOperatorTypes();
virtual string GetName() const;
virtual string ParamsToString() const;
virtual string ToString(idx_t depth = 0) const;
void Print();
virtual void Verify();
void AddChild(unique_ptr<LogicalOperator> child) {
children.push_back(move(child));
}
virtual idx_t EstimateCardinality(ClientContext &context) {
idx_t max_cardinality = 0;
for (auto &child : children) {
max_cardinality = MaxValue(child->EstimateCardinality(context), max_cardinality);
}
return max_cardinality;
}
protected:
virtual void ResolveTypes() = 0;
};
}
namespace duckdb {
struct BoundStatement {
unique_ptr<LogicalOperator> plan;
vector<LogicalType> types;
vector<string> names;
};
}
namespace duckdb {
class BoundResultModifier {
public:
explicit BoundResultModifier(ResultModifierType type) : type(type) {
}
virtual ~BoundResultModifier() {
}
ResultModifierType type;
};
struct BoundOrderByNode {
BoundOrderByNode(OrderType type, OrderByNullType null_order, unique_ptr<Expression> expression)
: type(type), null_order(null_order), expression(move(expression)) {
}
OrderType type;
OrderByNullType null_order;
unique_ptr<Expression> expression;
};
class BoundLimitModifier : public BoundResultModifier {
public:
BoundLimitModifier() : BoundResultModifier(ResultModifierType::LIMIT_MODIFIER) {
}
int64_t limit_val = NumericLimits<int64_t>::Maximum();
int64_t offset_val = 0;
unique_ptr<Expression> limit;
unique_ptr<Expression> offset;
};
class BoundOrderModifier : public BoundResultModifier {
public:
BoundOrderModifier() : BoundResultModifier(ResultModifierType::ORDER_MODIFIER) {
}
vector<BoundOrderByNode> orders;
};
class BoundDistinctModifier : public BoundResultModifier {
public:
BoundDistinctModifier() : BoundResultModifier(ResultModifierType::DISTINCT_MODIFIER) {
}
vector<unique_ptr<Expression>> target_distincts;
};
}
namespace duckdb {
class BoundAggregateExpression;
typedef idx_t (*aggregate_size_t)();
typedef void (*aggregate_initialize_t)(data_ptr_t state);
typedef void (*aggregate_update_t)(Vector inputs[], FunctionData *bind_data, idx_t input_count, Vector &state,
idx_t count);
typedef void (*aggregate_combine_t)(Vector &state, Vector &combined, idx_t count);
typedef void (*aggregate_finalize_t)(Vector &state, FunctionData *bind_data, Vector &result, idx_t count, idx_t offset);
typedef unique_ptr<BaseStatistics> (*aggregate_statistics_t)(ClientContext &context, BoundAggregateExpression &expr,
FunctionData *bind_data,
vector<unique_ptr<BaseStatistics>> &child_stats,
NodeStatistics *node_stats);
typedef unique_ptr<FunctionData> (*bind_aggregate_function_t)(ClientContext &context, AggregateFunction &function,
vector<unique_ptr<Expression>> &arguments);
typedef void (*aggregate_destructor_t)(Vector &state, idx_t count);
typedef void (*aggregate_simple_update_t)(Vector inputs[], FunctionData *bind_data, idx_t input_count, data_ptr_t state,
idx_t count);
typedef std::pair<idx_t, idx_t> FrameBounds;
typedef void (*aggregate_window_t)(Vector inputs[], FunctionData *bind_data, idx_t input_count, data_ptr_t state,
const FrameBounds &frame, const FrameBounds &prev, Vector &result, idx_t offset);
class AggregateFunction : public BaseScalarFunction {
public:
AggregateFunction(const string &name, const vector<LogicalType> &arguments, const LogicalType &return_type,
aggregate_size_t state_size, aggregate_initialize_t initialize, aggregate_update_t update,
aggregate_combine_t combine, aggregate_finalize_t finalize,
aggregate_simple_update_t simple_update = nullptr, bind_aggregate_function_t bind = nullptr,
aggregate_destructor_t destructor = nullptr, aggregate_statistics_t statistics = nullptr,
aggregate_window_t window = nullptr, bool order_sensitive = false)
: BaseScalarFunction(name, arguments, return_type, false), state_size(state_size), initialize(initialize),
update(update), combine(combine), finalize(finalize), simple_update(simple_update), window(window),
order_sensitive(order_sensitive), bind(bind), destructor(destructor), statistics(statistics) {
}
AggregateFunction(const vector<LogicalType> &arguments, const LogicalType &return_type, aggregate_size_t state_size,
aggregate_initialize_t initialize, aggregate_update_t update, aggregate_combine_t combine,
aggregate_finalize_t finalize, aggregate_simple_update_t simple_update = nullptr,
bind_aggregate_function_t bind = nullptr, aggregate_destructor_t destructor = nullptr,
aggregate_statistics_t statistics = nullptr, aggregate_window_t window = nullptr,
bool order_sensitive = false)
: AggregateFunction(string(), arguments, return_type, state_size, initialize, update, combine, finalize,
simple_update, bind, destructor, statistics, window, order_sensitive) {
}
aggregate_size_t state_size;
aggregate_initialize_t initialize;
aggregate_update_t update;
aggregate_combine_t combine;
aggregate_finalize_t finalize;
aggregate_simple_update_t simple_update;
aggregate_window_t window;
bool order_sensitive;
bind_aggregate_function_t bind;
aggregate_destructor_t destructor;
aggregate_statistics_t statistics;
bool operator==(const AggregateFunction &rhs) const {
return state_size == rhs.state_size && initialize == rhs.initialize && update == rhs.update &&
combine == rhs.combine && finalize == rhs.finalize && window == rhs.window;
}
bool operator!=(const AggregateFunction &rhs) const {
return !(*this == rhs);
}
static unique_ptr<BoundAggregateExpression>
BindAggregateFunction(ClientContext &context, AggregateFunction bound_function,
vector<unique_ptr<Expression>> children, unique_ptr<Expression> filter = nullptr,
bool is_distinct = false, unique_ptr<BoundOrderModifier> order_bys = nullptr);
static unique_ptr<FunctionData> BindSortedAggregate(AggregateFunction &bound_function,
vector<unique_ptr<Expression>> &children,
unique_ptr<FunctionData> bind_info,
unique_ptr<BoundOrderModifier> order_bys);
public:
template <class STATE, class RESULT_TYPE, class OP>
static AggregateFunction NullaryAggregate(LogicalType return_type) {
return AggregateFunction(
{}, return_type, AggregateFunction::StateSize<STATE>, AggregateFunction::StateInitialize<STATE, OP>,
AggregateFunction::NullaryScatterUpdate<STATE, OP>, AggregateFunction::StateCombine<STATE, OP>,
AggregateFunction::StateFinalize<STATE, RESULT_TYPE, OP>, AggregateFunction::NullaryUpdate<STATE, OP>);
}
template <class STATE, class INPUT_TYPE, class RESULT_TYPE, class OP>
static AggregateFunction UnaryAggregate(const LogicalType &input_type, LogicalType return_type) {
return AggregateFunction(
{input_type}, return_type, AggregateFunction::StateSize<STATE>,
AggregateFunction::StateInitialize<STATE, OP>, AggregateFunction::UnaryScatterUpdate<STATE, INPUT_TYPE, OP>,
AggregateFunction::StateCombine<STATE, OP>, AggregateFunction::StateFinalize<STATE, RESULT_TYPE, OP>,
AggregateFunction::UnaryUpdate<STATE, INPUT_TYPE, OP>);
}
template <class STATE, class INPUT_TYPE, class RESULT_TYPE, class OP>
static AggregateFunction UnaryAggregateDestructor(LogicalType input_type, LogicalType return_type) {
auto aggregate = UnaryAggregate<STATE, INPUT_TYPE, RESULT_TYPE, OP>(input_type, return_type);
aggregate.destructor = AggregateFunction::StateDestroy<STATE, OP>;
return aggregate;
}
template <class STATE, class A_TYPE, class B_TYPE, class RESULT_TYPE, class OP>
static AggregateFunction BinaryAggregate(const LogicalType &a_type, const LogicalType &b_type,
LogicalType return_type) {
return AggregateFunction({a_type, b_type}, return_type, AggregateFunction::StateSize<STATE>,
AggregateFunction::StateInitialize<STATE, OP>,
AggregateFunction::BinaryScatterUpdate<STATE, A_TYPE, B_TYPE, OP>,
AggregateFunction::StateCombine<STATE, OP>,
AggregateFunction::StateFinalize<STATE, RESULT_TYPE, OP>,
AggregateFunction::BinaryUpdate<STATE, A_TYPE, B_TYPE, OP>);
}
public:
template <class STATE>
static idx_t StateSize() {
return sizeof(STATE);
}
template <class STATE, class OP>
static void StateInitialize(data_ptr_t state) {
OP::Initialize((STATE *)state);
}
template <class STATE, class OP>
static void NullaryScatterUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, Vector &states,
idx_t count) {
D_ASSERT(input_count == 0);
AggregateExecutor::NullaryScatter<STATE, OP>(states, bind_data, count);
}
template <class STATE, class OP>
static void NullaryUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, data_ptr_t state,
idx_t count) {
D_ASSERT(input_count == 0);
AggregateExecutor::NullaryUpdate<STATE, OP>(state, bind_data, count);
}
template <class STATE, class T, class OP>
static void UnaryScatterUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, Vector &states,
idx_t count) {
D_ASSERT(input_count == 1);
AggregateExecutor::UnaryScatter<STATE, T, OP>(inputs[0], states, bind_data, count);
}
template <class STATE, class INPUT_TYPE, class OP>
static void UnaryUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, data_ptr_t state,
idx_t count) {
D_ASSERT(input_count == 1);
AggregateExecutor::UnaryUpdate<STATE, INPUT_TYPE, OP>(inputs[0], bind_data, state, count);
}
template <class STATE, class INPUT_TYPE, class RESULT_TYPE, class OP>
static void UnaryWindow(Vector inputs[], FunctionData *bind_data, idx_t input_count, data_ptr_t state,
const FrameBounds &frame, const FrameBounds &prev, Vector &result, idx_t rid) {
D_ASSERT(input_count == 1);
AggregateExecutor::UnaryWindow<STATE, INPUT_TYPE, RESULT_TYPE, OP>(inputs[0], bind_data, state, frame, prev,
result, rid);
}
template <class STATE, class A_TYPE, class B_TYPE, class OP>
static void BinaryScatterUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, Vector &states,
idx_t count) {
D_ASSERT(input_count == 2);
AggregateExecutor::BinaryScatter<STATE, A_TYPE, B_TYPE, OP>(bind_data, inputs[0], inputs[1], states, count);
}
template <class STATE, class A_TYPE, class B_TYPE, class OP>
static void BinaryUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, data_ptr_t state,
idx_t count) {
D_ASSERT(input_count == 2);
AggregateExecutor::BinaryUpdate<STATE, A_TYPE, B_TYPE, OP>(bind_data, inputs[0], inputs[1], state, count);
}
template <class STATE, class OP>
static void StateCombine(Vector &source, Vector &target, idx_t count) {
AggregateExecutor::Combine<STATE, OP>(source, target, count);
}
template <class STATE, class RESULT_TYPE, class OP>
static void StateFinalize(Vector &states, FunctionData *bind_data, Vector &result, idx_t count, idx_t offset) {
AggregateExecutor::Finalize<STATE, RESULT_TYPE, OP>(states, bind_data, result, count, offset);
}
template <class STATE, class OP>
static void StateDestroy(Vector &states, idx_t count) {
AggregateExecutor::Destroy<STATE, OP>(states, count);
}
};
}
namespace duckdb {
struct UDFWrapper {
public:
template <typename TR, typename... Args>
static scalar_function_t CreateScalarFunction(const string &name, TR (*udf_func)(Args...)) {
const std::size_t num_template_argc = sizeof...(Args);
switch (num_template_argc) {
case 1:
return CreateUnaryFunction<TR, Args...>(name, udf_func);
case 2:
return CreateBinaryFunction<TR, Args...>(name, udf_func);
case 3:
return CreateTernaryFunction<TR, Args...>(name, udf_func);
default: throw std::runtime_error("UDF function only supported until ternary!");
} }
template <typename TR, typename... Args>
static scalar_function_t CreateScalarFunction(const string &name, vector<LogicalType> args, LogicalType ret_type,
TR (*udf_func)(Args...)) {
if (!TypesMatch<TR>(ret_type)) { throw std::runtime_error("Return type doesn't match with the first template type.");
}
const std::size_t num_template_types = sizeof...(Args);
if (num_template_types != args.size()) { throw std::runtime_error(
"The number of templated types should be the same quantity of the LogicalType arguments.");
}
switch (num_template_types) {
case 1:
return CreateUnaryFunction<TR, Args...>(name, args, ret_type, udf_func);
case 2:
return CreateBinaryFunction<TR, Args...>(name, args, ret_type, udf_func);
case 3:
return CreateTernaryFunction<TR, Args...>(name, args, ret_type, udf_func);
default: throw std::runtime_error("UDF function only supported until ternary!");
} }
template <typename TR, typename... Args>
static void RegisterFunction(const string &name, scalar_function_t udf_function, ClientContext &context,
LogicalType varargs = LogicalType(LogicalTypeId::INVALID)) {
vector<LogicalType> arguments;
GetArgumentTypesRecursive<Args...>(arguments);
LogicalType ret_type = GetArgumentType<TR>();
RegisterFunction(name, arguments, ret_type, udf_function, context, varargs);
}
DUCKDB_API static void RegisterFunction(string name, vector<LogicalType> args, LogicalType ret_type,
scalar_function_t udf_function, ClientContext &context,
LogicalType varargs = LogicalType(LogicalTypeId::INVALID));
template <typename UDF_OP, typename STATE, typename TR, typename TA>
static AggregateFunction CreateAggregateFunction(const string &name) {
return CreateUnaryAggregateFunction<UDF_OP, STATE, TR, TA>(name);
}
template <typename UDF_OP, typename STATE, typename TR, typename TA, typename TB>
static AggregateFunction CreateAggregateFunction(const string &name) {
return CreateBinaryAggregateFunction<UDF_OP, STATE, TR, TA, TB>(name);
}
template <typename UDF_OP, typename STATE, typename TR, typename TA>
static AggregateFunction CreateAggregateFunction(const string &name, LogicalType ret_type, LogicalType input_type) {
if (!TypesMatch<TR>(ret_type)) { throw std::runtime_error("The return argument don't match!");
}
if (!TypesMatch<TA>(input_type)) { throw std::runtime_error("The input argument don't match!");
}
return CreateUnaryAggregateFunction<UDF_OP, STATE, TR, TA>(name, ret_type, input_type);
}
template <typename UDF_OP, typename STATE, typename TR, typename TA, typename TB>
static AggregateFunction CreateAggregateFunction(const string &name, LogicalType ret_type, LogicalType input_typeA,
LogicalType input_typeB) {
if (!TypesMatch<TR>(ret_type)) { throw std::runtime_error("The return argument don't match!");
}
if (!TypesMatch<TA>(input_typeA)) {
throw std::runtime_error("The first input argument don't match!");
}
if (!TypesMatch<TB>(input_typeB)) {
throw std::runtime_error("The second input argument don't match!");
}
return CreateBinaryAggregateFunction<UDF_OP, STATE, TR, TA, TB>(name, ret_type, input_typeA, input_typeB);
}
static AggregateFunction CreateAggregateFunction(string name, vector<LogicalType> arguments,
LogicalType return_type, aggregate_size_t state_size,
aggregate_initialize_t initialize, aggregate_update_t update,
aggregate_combine_t combine, aggregate_finalize_t finalize,
aggregate_simple_update_t simple_update = nullptr,
bind_aggregate_function_t bind = nullptr,
aggregate_destructor_t destructor = nullptr) {
AggregateFunction aggr_function(move(name), move(arguments), move(return_type), state_size, initialize, update,
combine, finalize, simple_update, bind, destructor);
return aggr_function;
}
DUCKDB_API static void RegisterAggrFunction(AggregateFunction aggr_function, ClientContext &context,
LogicalType varargs = LogicalType(LogicalTypeId::INVALID));
private:
struct UnaryUDFExecutor {
template <class INPUT_TYPE, class RESULT_TYPE>
static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) {
typedef RESULT_TYPE (*unary_function_t)(INPUT_TYPE);
auto udf = (unary_function_t)dataptr;
return udf(input);
}
};
template <typename TR, typename TA>
static scalar_function_t CreateUnaryFunction(const string &name, TR (*udf_func)(TA)) {
scalar_function_t udf_function = [=](DataChunk &input, ExpressionState &state, Vector &result) -> void {
UnaryExecutor::GenericExecute<TA, TR, UnaryUDFExecutor>(input.data[0], result, input.size(),
(void *)udf_func);
};
return udf_function;
}
template <typename TR, typename TA, typename TB>
static scalar_function_t CreateBinaryFunction(const string &name, TR (*udf_func)(TA, TB)) {
scalar_function_t udf_function = [=](DataChunk &input, ExpressionState &state, Vector &result) -> void {
BinaryExecutor::Execute<TA, TB, TR>(input.data[0], input.data[1], result, input.size(), udf_func);
};
return udf_function;
}
template <typename TR, typename TA, typename TB, typename TC>
static scalar_function_t CreateTernaryFunction(const string &name, TR (*udf_func)(TA, TB, TC)) {
scalar_function_t udf_function = [=](DataChunk &input, ExpressionState &state, Vector &result) -> void {
TernaryExecutor::Execute<TA, TB, TC, TR>(input.data[0], input.data[1], input.data[2], result, input.size(),
udf_func);
};
return udf_function;
}
template <typename TR, typename... Args>
static scalar_function_t CreateUnaryFunction(const string &name, TR (*udf_func)(Args...)) { throw std::runtime_error("Incorrect number of arguments for unary function");
}
template <typename TR, typename... Args>
static scalar_function_t CreateBinaryFunction(const string &name, TR (*udf_func)(Args...)) { throw std::runtime_error("Incorrect number of arguments for binary function");
}
template <typename TR, typename... Args>
static scalar_function_t CreateTernaryFunction(const string &name, TR (*udf_func)(Args...)) { throw std::runtime_error("Incorrect number of arguments for ternary function");
}
template <typename T>
static LogicalType GetArgumentType() {
if (std::is_same<T, bool>()) {
return LogicalType(LogicalTypeId::BOOLEAN);
} else if (std::is_same<T, int8_t>()) {
return LogicalType(LogicalTypeId::TINYINT);
} else if (std::is_same<T, int16_t>()) {
return LogicalType(LogicalTypeId::SMALLINT);
} else if (std::is_same<T, int32_t>()) {
return LogicalType(LogicalTypeId::INTEGER);
} else if (std::is_same<T, int64_t>()) {
return LogicalType(LogicalTypeId::BIGINT);
} else if (std::is_same<T, float>()) {
return LogicalType(LogicalTypeId::FLOAT);
} else if (std::is_same<T, double>()) {
return LogicalType(LogicalTypeId::DOUBLE);
} else if (std::is_same<T, string_t>()) {
return LogicalType(LogicalTypeId::VARCHAR);
} else { throw std::runtime_error("Unrecognized type!");
} }
template <typename TA, typename TB, typename... Args>
static void GetArgumentTypesRecursive(vector<LogicalType> &arguments) {
arguments.push_back(GetArgumentType<TA>());
GetArgumentTypesRecursive<TB, Args...>(arguments);
}
template <typename TA>
static void GetArgumentTypesRecursive(vector<LogicalType> &arguments) {
arguments.push_back(GetArgumentType<TA>());
}
private:
template <typename TR, typename... Args>
static scalar_function_t CreateUnaryFunction(const string &name, vector<LogicalType> args, LogicalType ret_type,
TR (*udf_func)(Args...)) { throw std::runtime_error("Incorrect number of arguments for unary function");
}
template <typename TR, typename TA>
static scalar_function_t CreateUnaryFunction(const string &name, vector<LogicalType> args, LogicalType ret_type,
TR (*udf_func)(TA)) {
if (args.size() != 1) { throw std::runtime_error("The number of LogicalType arguments (\"args\") should be 1!");
}
if (!TypesMatch<TA>(args[0])) {
throw std::runtime_error("The first arguments don't match!");
}
scalar_function_t udf_function = [=](DataChunk &input, ExpressionState &state, Vector &result) -> void {
UnaryExecutor::GenericExecute<TA, TR, UnaryUDFExecutor>(input.data[0], result, input.size(),
(void *)udf_func);
};
return udf_function;
}
template <typename TR, typename... Args>
static scalar_function_t CreateBinaryFunction(const string &name, vector<LogicalType> args, LogicalType ret_type,
TR (*udf_func)(Args...)) { throw std::runtime_error("Incorrect number of arguments for binary function");
}
template <typename TR, typename TA, typename TB>
static scalar_function_t CreateBinaryFunction(const string &name, vector<LogicalType> args, LogicalType ret_type,
TR (*udf_func)(TA, TB)) {
if (args.size() != 2) { throw std::runtime_error("The number of LogicalType arguments (\"args\") should be 2!");
}
if (!TypesMatch<TA>(args[0])) {
throw std::runtime_error("The first arguments don't match!");
}
if (!TypesMatch<TB>(args[1])) {
throw std::runtime_error("The second arguments don't match!");
}
scalar_function_t udf_function = [=](DataChunk &input, ExpressionState &state, Vector &result) {
BinaryExecutor::Execute<TA, TB, TR>(input.data[0], input.data[1], result, input.size(), udf_func);
};
return udf_function;
}
template <typename TR, typename... Args>
static scalar_function_t CreateTernaryFunction(const string &name, vector<LogicalType> args, LogicalType ret_type,
TR (*udf_func)(Args...)) { throw std::runtime_error("Incorrect number of arguments for ternary function");
}
template <typename TR, typename TA, typename TB, typename TC>
static scalar_function_t CreateTernaryFunction(const string &name, vector<LogicalType> args, LogicalType ret_type,
TR (*udf_func)(TA, TB, TC)) {
if (args.size() != 3) { throw std::runtime_error("The number of LogicalType arguments (\"args\") should be 3!");
}
if (!TypesMatch<TA>(args[0])) {
throw std::runtime_error("The first arguments don't match!");
}
if (!TypesMatch<TB>(args[1])) {
throw std::runtime_error("The second arguments don't match!");
}
if (!TypesMatch<TC>(args[2])) {
throw std::runtime_error("The second arguments don't match!");
}
scalar_function_t udf_function = [=](DataChunk &input, ExpressionState &state, Vector &result) -> void {
TernaryExecutor::Execute<TA, TB, TC, TR>(input.data[0], input.data[1], input.data[2], result, input.size(),
udf_func);
};
return udf_function;
}
template <typename T>
static bool TypesMatch(LogicalType sql_type) {
switch (sql_type.id()) {
case LogicalTypeId::BOOLEAN:
return std::is_same<T, bool>();
case LogicalTypeId::TINYINT:
return std::is_same<T, int8_t>();
case LogicalTypeId::SMALLINT:
return std::is_same<T, int16_t>();
case LogicalTypeId::INTEGER:
return std::is_same<T, int32_t>();
case LogicalTypeId::BIGINT:
return std::is_same<T, int64_t>();
case LogicalTypeId::DATE:
return std::is_same<T, date_t>();
case LogicalTypeId::TIME:
return std::is_same<T, dtime_t>();
case LogicalTypeId::TIMESTAMP:
case LogicalTypeId::TIMESTAMP_MS:
case LogicalTypeId::TIMESTAMP_NS:
case LogicalTypeId::TIMESTAMP_SEC:
return std::is_same<T, timestamp_t>();
case LogicalTypeId::FLOAT:
return std::is_same<T, float>();
case LogicalTypeId::DOUBLE:
return std::is_same<T, double>();
case LogicalTypeId::VARCHAR:
case LogicalTypeId::CHAR:
case LogicalTypeId::BLOB:
return std::is_same<T, string_t>();
default: throw std::runtime_error("Type is not supported!");
} }
private:
template <typename UDF_OP, typename STATE, typename TR, typename TA>
static AggregateFunction CreateUnaryAggregateFunction(const string &name) {
LogicalType return_type = GetArgumentType<TR>();
LogicalType input_type = GetArgumentType<TA>();
return CreateUnaryAggregateFunction<UDF_OP, STATE, TR, TA>(name, return_type, input_type);
}
template <typename UDF_OP, typename STATE, typename TR, typename TA>
static AggregateFunction CreateUnaryAggregateFunction(const string &name, LogicalType ret_type,
LogicalType input_type) {
AggregateFunction aggr_function =
AggregateFunction::UnaryAggregate<STATE, TR, TA, UDF_OP>(input_type, ret_type);
aggr_function.name = name;
return aggr_function;
}
template <typename UDF_OP, typename STATE, typename TR, typename TA, typename TB>
static AggregateFunction CreateBinaryAggregateFunction(const string &name) {
LogicalType return_type = GetArgumentType<TR>();
LogicalType input_typeA = GetArgumentType<TA>();
LogicalType input_typeB = GetArgumentType<TB>();
return CreateBinaryAggregateFunction<UDF_OP, STATE, TR, TA, TB>(name, return_type, input_typeA, input_typeB);
}
template <typename UDF_OP, typename STATE, typename TR, typename TA, typename TB>
static AggregateFunction CreateBinaryAggregateFunction(const string &name, LogicalType ret_type,
LogicalType input_typeA, LogicalType input_typeB) {
AggregateFunction aggr_function =
AggregateFunction::BinaryAggregate<STATE, TR, TA, TB, UDF_OP>(input_typeA, input_typeB, ret_type);
aggr_function.name = name;
return aggr_function;
}
};
}
namespace duckdb {
class ChunkCollection {
public:
ChunkCollection() : count(0) {
}
DUCKDB_API vector<LogicalType> &Types() {
return types;
}
const vector<LogicalType> &Types() const {
return types;
}
DUCKDB_API const idx_t &Count() const {
return count;
}
DUCKDB_API idx_t ColumnCount() const {
return types.size();
}
DUCKDB_API void Append(DataChunk &new_chunk);
DUCKDB_API void Append(unique_ptr<DataChunk> new_chunk);
DUCKDB_API void Append(ChunkCollection &other);
DUCKDB_API void Merge(ChunkCollection &other);
DUCKDB_API void Fuse(ChunkCollection &other);
DUCKDB_API void Verify();
DUCKDB_API Value GetValue(idx_t column, idx_t index);
DUCKDB_API void SetValue(idx_t column, idx_t index, const Value &value);
DUCKDB_API void CopyCell(idx_t column, idx_t index, Vector &target, idx_t target_offset);
DUCKDB_API string ToString() const {
return chunks.size() == 0 ? "ChunkCollection [ 0 ]"
: "ChunkCollection [ " + std::to_string(count) + " ]: \n" + chunks[0]->ToString();
}
DUCKDB_API void Print();
DUCKDB_API DataChunk &GetChunkForRow(idx_t row_index) {
return *chunks[LocateChunk(row_index)];
}
DUCKDB_API DataChunk &GetChunk(idx_t chunk_index) {
D_ASSERT(chunk_index < chunks.size());
return *chunks[chunk_index];
}
const DataChunk &GetChunk(idx_t chunk_index) const {
D_ASSERT(chunk_index < chunks.size());
return *chunks[chunk_index];
}
DUCKDB_API const vector<unique_ptr<DataChunk>> &Chunks() {
return chunks;
}
DUCKDB_API idx_t ChunkCount() const {
return chunks.size();
}
DUCKDB_API void Reset() {
count = 0;
chunks.clear();
types.clear();
}
DUCKDB_API unique_ptr<DataChunk> Fetch() {
if (ChunkCount() == 0) {
return nullptr;
}
auto res = move(chunks[0]);
chunks.erase(chunks.begin() + 0);
return res;
}
DUCKDB_API void Sort(vector<OrderType> &desc, vector<OrderByNullType> &null_order, idx_t result[]);
DUCKDB_API void Reorder(idx_t order[]);
DUCKDB_API bool Equals(ChunkCollection &other);
DUCKDB_API idx_t LocateChunk(idx_t index) {
idx_t result = index / STANDARD_VECTOR_SIZE;
D_ASSERT(result < chunks.size());
return result;
}
DUCKDB_API void Heap(vector<OrderType> &desc, vector<OrderByNullType> &null_order, idx_t heap[], idx_t heap_size);
DUCKDB_API idx_t MaterializeHeapChunk(DataChunk &target, idx_t order[], idx_t start_offset, idx_t heap_size);
private:
idx_t count;
vector<unique_ptr<DataChunk>> chunks;
vector<LogicalType> types;
};
}
namespace duckdb {
enum class StatementType : uint8_t {
INVALID_STATEMENT, SELECT_STATEMENT, INSERT_STATEMENT, UPDATE_STATEMENT, CREATE_STATEMENT, DELETE_STATEMENT, PREPARE_STATEMENT, EXECUTE_STATEMENT, ALTER_STATEMENT, TRANSACTION_STATEMENT, COPY_STATEMENT, ANALYZE_STATEMENT, VARIABLE_SET_STATEMENT, CREATE_FUNC_STATEMENT, EXPLAIN_STATEMENT, DROP_STATEMENT, EXPORT_STATEMENT, PRAGMA_STATEMENT, SHOW_STATEMENT, VACUUM_STATEMENT, CALL_STATEMENT, SET_STATEMENT, LOAD_STATEMENT, RELATION_STATEMENT
};
string StatementTypeToString(StatementType type);
bool StatementTypeReturnChanges(StatementType type);
}
struct ArrowSchema;
namespace duckdb {
enum class QueryResultType : uint8_t { MATERIALIZED_RESULT, STREAM_RESULT };
class QueryResult {
public:
DUCKDB_API QueryResult(QueryResultType type, StatementType statement_type);
DUCKDB_API QueryResult(QueryResultType type, StatementType statement_type, vector<LogicalType> types,
vector<string> names);
DUCKDB_API QueryResult(QueryResultType type, string error);
DUCKDB_API virtual ~QueryResult() {
}
QueryResultType type;
StatementType statement_type;
vector<LogicalType> types;
vector<string> names;
bool success;
string error;
unique_ptr<QueryResult> next;
public:
DUCKDB_API virtual unique_ptr<DataChunk> Fetch();
DUCKDB_API virtual unique_ptr<DataChunk> FetchRaw() = 0;
DUCKDB_API virtual string ToString() = 0;
DUCKDB_API void Print();
DUCKDB_API bool Equals(QueryResult &other);
DUCKDB_API idx_t ColumnCount() {
return types.size();
}
DUCKDB_API bool TryFetch(unique_ptr<DataChunk> &result, string &error) {
try {
result = Fetch();
return success;
} catch (std::exception &ex) {
error = ex.what();
return false;
} catch (...) {
error = "Unknown error in Fetch";
return false;
}
}
DUCKDB_API void ToArrowSchema(ArrowSchema *out_array);
private:
unique_ptr<DataChunk> iterator_chunk;
private:
class QueryResultIterator;
class QueryResultRow {
public:
explicit 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>();
}
};
class QueryResultIterator {
public:
explicit 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->ColumnCount() > 0;
}
const QueryResultRow &operator*() const {
return current_row;
}
};
public:
DUCKDB_API QueryResultIterator begin() {
return QueryResultIterator(this);
}
DUCKDB_API QueryResultIterator end() {
return QueryResultIterator(nullptr);
}
protected:
DUCKDB_API string HeaderToString();
private:
QueryResult(const QueryResult &) = delete;
};
}
namespace duckdb {
class MaterializedQueryResult : public QueryResult {
public:
DUCKDB_API explicit MaterializedQueryResult(StatementType statement_type);
DUCKDB_API MaterializedQueryResult(StatementType statement_type, vector<LogicalType> types, vector<string> names);
DUCKDB_API explicit MaterializedQueryResult(string error);
ChunkCollection collection;
public:
DUCKDB_API unique_ptr<DataChunk> Fetch() override;
DUCKDB_API unique_ptr<DataChunk> FetchRaw() override;
DUCKDB_API string ToString() override;
DUCKDB_API 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>();
}
};
}
namespace duckdb {
class ClientContext;
class PreparedStatementData;
class PreparedStatement {
public:
DUCKDB_API PreparedStatement(shared_ptr<ClientContext> context, shared_ptr<PreparedStatementData> data,
string query, idx_t n_param);
DUCKDB_API explicit PreparedStatement(string error);
DUCKDB_API ~PreparedStatement();
public:
shared_ptr<ClientContext> context;
shared_ptr<PreparedStatementData> data;
string query;
bool success;
string error;
idx_t n_param;
public:
idx_t ColumnCount();
StatementType GetStatementType();
const vector<LogicalType> &GetTypes();
const vector<string> &GetNames();
template <typename... Args>
unique_ptr<QueryResult> Execute(Args... args) {
vector<Value> values;
return ExecuteRecursive(values, args...);
}
DUCKDB_API 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 {
enum class JoinType : uint8_t {
INVALID = 0, LEFT = 1, RIGHT = 2, INNER = 3, OUTER = 4, SEMI = 5, ANTI = 6, MARK = 7, SINGLE = 8 };
string JoinTypeToString(JoinType type);
bool IsLeftOuterJoin(JoinType type);
bool IsRightOuterJoin(JoinType type);
}
namespace duckdb {
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,
QUERY_RELATION
};
string RelationTypeToString(RelationType type);
}
#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:
DUCKDB_API Relation(ClientContext &context, RelationType type) : context(context), type(type) {
}
DUCKDB_API virtual ~Relation() {
}
ClientContext &context;
RelationType type;
public:
DUCKDB_API virtual const vector<ColumnDefinition> &Columns() = 0;
DUCKDB_API virtual unique_ptr<QueryNode> GetQueryNode();
DUCKDB_API virtual BoundStatement Bind(Binder &binder);
DUCKDB_API virtual string GetAlias();
DUCKDB_API unique_ptr<QueryResult> Execute();
DUCKDB_API string ToString();
DUCKDB_API virtual string ToString(idx_t depth) = 0;
DUCKDB_API void Print();
DUCKDB_API void Head(idx_t limit = 10);
DUCKDB_API shared_ptr<Relation> CreateView(const string &name, bool replace = true, bool temporary = false);
DUCKDB_API unique_ptr<QueryResult> Query(const string &sql);
DUCKDB_API unique_ptr<QueryResult> Query(const string &name, const string &sql);
DUCKDB_API unique_ptr<QueryResult> Explain();
DUCKDB_API virtual unique_ptr<TableRef> GetTableRef();
DUCKDB_API virtual bool IsReadOnly() {
return true;
}
public:
DUCKDB_API shared_ptr<Relation> Project(const string &select_list);
DUCKDB_API shared_ptr<Relation> Project(const string &expression, const string &alias);
DUCKDB_API shared_ptr<Relation> Project(const string &select_list, const vector<string> &aliases);
DUCKDB_API shared_ptr<Relation> Project(const vector<string> &expressions);
DUCKDB_API shared_ptr<Relation> Project(const vector<string> &expressions, const vector<string> &aliases);
DUCKDB_API shared_ptr<Relation> Filter(const string &expression);
DUCKDB_API shared_ptr<Relation> Filter(const vector<string> &expressions);
DUCKDB_API shared_ptr<Relation> Limit(int64_t n, int64_t offset = 0);
DUCKDB_API shared_ptr<Relation> Order(const string &expression);
DUCKDB_API shared_ptr<Relation> Order(const vector<string> &expressions);
DUCKDB_API shared_ptr<Relation> Join(const shared_ptr<Relation> &other, const string &condition,
JoinType type = JoinType::INNER);
DUCKDB_API shared_ptr<Relation> Union(const shared_ptr<Relation> &other);
DUCKDB_API shared_ptr<Relation> Except(const shared_ptr<Relation> &other);
DUCKDB_API shared_ptr<Relation> Intersect(const shared_ptr<Relation> &other);
DUCKDB_API shared_ptr<Relation> Distinct();
DUCKDB_API shared_ptr<Relation> Aggregate(const string &aggregate_list);
DUCKDB_API shared_ptr<Relation> Aggregate(const vector<string> &aggregates);
DUCKDB_API shared_ptr<Relation> Aggregate(const string &aggregate_list, const string &group_list);
DUCKDB_API shared_ptr<Relation> Aggregate(const vector<string> &aggregates, const vector<string> &groups);
DUCKDB_API shared_ptr<Relation> Alias(const string &alias);
DUCKDB_API void Insert(const string &table_name);
DUCKDB_API void Insert(const string &schema_name, const string &table_name);
DUCKDB_API void Insert(const vector<vector<Value>> &values);
DUCKDB_API void Create(const string &table_name);
DUCKDB_API void Create(const string &schema_name, const string &table_name);
DUCKDB_API void WriteCSV(const string &csv_file);
DUCKDB_API virtual void Update(const string &update, const string &condition = string());
DUCKDB_API virtual void Delete(const string &condition = string());
DUCKDB_API shared_ptr<Relation> TableFunction(const std::string &fname, vector<Value> values);
public:
DUCKDB_API virtual bool InheritsColumnBindings() {
return false;
}
DUCKDB_API virtual Relation *ChildRelation() {
return nullptr;
}
protected:
DUCKDB_API string RenderWhitespace(idx_t depth);
};
}
namespace duckdb {
class ClientContext;
class MaterializedQueryResult;
class PreparedStatementData;
class StreamQueryResult : public QueryResult {
public:
DUCKDB_API StreamQueryResult(StatementType statement_type, shared_ptr<ClientContext> context,
vector<LogicalType> types, vector<string> names,
shared_ptr<PreparedStatementData> prepared = nullptr);
DUCKDB_API ~StreamQueryResult() override;
bool is_open;
public:
DUCKDB_API unique_ptr<DataChunk> FetchRaw() override;
DUCKDB_API string ToString() override;
DUCKDB_API unique_ptr<MaterializedQueryResult> Materialize();
DUCKDB_API void Close();
private:
shared_ptr<ClientContext> context;
shared_ptr<PreparedStatementData> prepared;
};
}
namespace duckdb {
struct TableDescription {
string schema;
string table;
vector<ColumnDefinition> columns;
};
}
namespace duckdb {
class Printer {
public:
static void Print(const string &str);
static void PrintProgress(int percentage, const char *pbstr, int pbwidth);
static void FinishProgressBarPrint(const char *pbstr, int pbwidth);
};
}
namespace duckdb {
class SQLStatement {
public:
explicit SQLStatement(StatementType type) : type(type) {};
virtual ~SQLStatement() {
}
StatementType type;
idx_t stmt_location;
idx_t stmt_length;
idx_t n_param;
string query;
public:
virtual unique_ptr<SQLStatement> Copy() const = 0;
};
}
namespace duckdb {
class ChunkCollection;
class ClientContext;
class DatabaseInstance;
class DuckDB;
class LogicalOperator;
typedef void (*warning_callback)(std::string);
class Connection {
public:
DUCKDB_API explicit Connection(DuckDB &database);
DUCKDB_API explicit Connection(DatabaseInstance &database);
shared_ptr<ClientContext> context;
warning_callback warning_cb;
public:
DUCKDB_API string GetProfilingInformation(ProfilerPrintFormat format = ProfilerPrintFormat::QUERY_TREE);
DUCKDB_API void Interrupt();
DUCKDB_API void EnableProfiling();
DUCKDB_API void DisableProfiling();
DUCKDB_API void SetWarningCallback(warning_callback);
DUCKDB_API void EnableQueryVerification();
DUCKDB_API void DisableQueryVerification();
DUCKDB_API void ForceParallelism();
DUCKDB_API unique_ptr<QueryResult> SendQuery(const string &query);
DUCKDB_API unique_ptr<MaterializedQueryResult> Query(const string &query);
DUCKDB_API unique_ptr<MaterializedQueryResult> Query(unique_ptr<SQLStatement> statement);
template <typename... Args>
unique_ptr<QueryResult> Query(const string &query, Args... args) {
vector<Value> values;
return QueryParamsRecursive(query, values, args...);
}
DUCKDB_API unique_ptr<PreparedStatement> Prepare(const string &query);
DUCKDB_API unique_ptr<PreparedStatement> Prepare(unique_ptr<SQLStatement> statement);
DUCKDB_API unique_ptr<TableDescription> TableInfo(const string &table_name);
DUCKDB_API unique_ptr<TableDescription> TableInfo(const string &schema_name, const string &table_name);
DUCKDB_API vector<unique_ptr<SQLStatement>> ExtractStatements(const string &query);
DUCKDB_API unique_ptr<LogicalOperator> ExtractPlan(const string &query);
DUCKDB_API void Append(TableDescription &description, DataChunk &chunk);
DUCKDB_API void Append(TableDescription &description, ChunkCollection &collection);
DUCKDB_API shared_ptr<Relation> Table(const string &tname);
DUCKDB_API shared_ptr<Relation> Table(const string &schema_name, const string &table_name);
DUCKDB_API shared_ptr<Relation> View(const string &tname);
DUCKDB_API shared_ptr<Relation> View(const string &schema_name, const string &table_name);
DUCKDB_API shared_ptr<Relation> TableFunction(const string &tname);
DUCKDB_API shared_ptr<Relation> TableFunction(const string &tname, const vector<Value> &values);
DUCKDB_API shared_ptr<Relation> Values(const vector<vector<Value>> &values);
DUCKDB_API shared_ptr<Relation> Values(const vector<vector<Value>> &values, const vector<string> &column_names,
const string &alias = "values");
DUCKDB_API shared_ptr<Relation> Values(const string &values);
DUCKDB_API shared_ptr<Relation> Values(const string &values, const vector<string> &column_names,
const string &alias = "values");
DUCKDB_API shared_ptr<Relation> ReadCSV(const string &csv_file);
DUCKDB_API shared_ptr<Relation> ReadCSV(const string &csv_file, const vector<string> &columns);
DUCKDB_API shared_ptr<Relation> RelationFromQuery(string query, string alias = "queryrelation");
DUCKDB_API void BeginTransaction();
DUCKDB_API void Commit();
DUCKDB_API void Rollback();
DUCKDB_API void SetAutoCommit(bool auto_commit);
DUCKDB_API bool IsAutoCommit();
template <typename TR, typename... Args>
void CreateScalarFunction(const string &name, TR (*udf_func)(Args...)) {
scalar_function_t function = UDFWrapper::CreateScalarFunction<TR, Args...>(name, udf_func);
UDFWrapper::RegisterFunction<TR, Args...>(name, function, *context);
}
template <typename TR, typename... Args>
void CreateScalarFunction(const string &name, vector<LogicalType> args, LogicalType ret_type,
TR (*udf_func)(Args...)) {
scalar_function_t function =
UDFWrapper::CreateScalarFunction<TR, Args...>(name, args, move(ret_type), udf_func);
UDFWrapper::RegisterFunction(name, args, ret_type, function, *context);
}
template <typename TR, typename... Args>
void CreateVectorizedFunction(const string &name, scalar_function_t udf_func,
LogicalType varargs = LogicalType::INVALID) {
UDFWrapper::RegisterFunction<TR, Args...>(name, udf_func, *context, move(varargs));
}
DUCKDB_API void CreateVectorizedFunction(const string &name, vector<LogicalType> args, LogicalType ret_type,
scalar_function_t udf_func, LogicalType varargs = LogicalType::INVALID) {
UDFWrapper::RegisterFunction(name, move(args), move(ret_type), udf_func, *context, move(varargs));
}
template <typename UDF_OP, typename STATE, typename TR, typename TA>
void CreateAggregateFunction(const string &name) {
AggregateFunction function = UDFWrapper::CreateAggregateFunction<UDF_OP, STATE, TR, TA>(name);
UDFWrapper::RegisterAggrFunction(function, *context);
}
template <typename UDF_OP, typename STATE, typename TR, typename TA, typename TB>
void CreateAggregateFunction(const string &name) {
AggregateFunction function = UDFWrapper::CreateAggregateFunction<UDF_OP, STATE, TR, TA, TB>(name);
UDFWrapper::RegisterAggrFunction(function, *context);
}
template <typename UDF_OP, typename STATE, typename TR, typename TA>
void CreateAggregateFunction(const string &name, LogicalType ret_type, LogicalType input_typeA) {
AggregateFunction function =
UDFWrapper::CreateAggregateFunction<UDF_OP, STATE, TR, TA>(name, ret_type, input_typeA);
UDFWrapper::RegisterAggrFunction(function, *context);
}
template <typename UDF_OP, typename STATE, typename TR, typename TA, typename TB>
void CreateAggregateFunction(const string &name, LogicalType ret_type, LogicalType input_typeA,
LogicalType input_typeB) {
AggregateFunction function =
UDFWrapper::CreateAggregateFunction<UDF_OP, STATE, TR, TA, TB>(name, ret_type, input_typeA, input_typeB);
UDFWrapper::RegisterAggrFunction(function, *context);
}
DUCKDB_API void CreateAggregateFunction(const string &name, vector<LogicalType> arguments, LogicalType return_type,
aggregate_size_t state_size, aggregate_initialize_t initialize,
aggregate_update_t update, aggregate_combine_t combine,
aggregate_finalize_t finalize,
aggregate_simple_update_t simple_update = nullptr,
bind_aggregate_function_t bind = nullptr,
aggregate_destructor_t destructor = nullptr) {
AggregateFunction function =
UDFWrapper::CreateAggregateFunction(name, arguments, return_type, state_size, initialize, update, combine,
finalize, simple_update, bind, destructor);
UDFWrapper::RegisterAggrFunction(function, *context);
}
private:
unique_ptr<QueryResult> QueryParamsRecursive(const string &query, vector<Value> &values);
template <typename T, typename... Args>
unique_ptr<QueryResult> QueryParamsRecursive(const string &query, vector<Value> &values, T value, Args... args) {
values.push_back(Value::CreateValue<T>(value));
return QueryParamsRecursive(query, values, args...);
}
};
}
namespace duckdb {
class Allocator;
class ClientContext;
class DatabaseInstance;
struct PrivateAllocatorData {
virtual ~PrivateAllocatorData() {
}
};
typedef data_ptr_t (*allocate_function_ptr_t)(PrivateAllocatorData *private_data, idx_t size);
typedef void (*free_function_ptr_t)(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t size);
typedef data_ptr_t (*reallocate_function_ptr_t)(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t size);
class AllocatedData {
public:
AllocatedData(Allocator &allocator, data_ptr_t pointer, idx_t allocated_size);
~AllocatedData();
data_ptr_t get() {
return pointer;
}
const_data_ptr_t get() const {
return pointer;
}
void Reset();
private:
Allocator &allocator;
data_ptr_t pointer;
idx_t allocated_size;
};
class Allocator {
public:
Allocator();
Allocator(allocate_function_ptr_t allocate_function_p, free_function_ptr_t free_function_p,
reallocate_function_ptr_t reallocate_function_p, unique_ptr<PrivateAllocatorData> private_data);
data_ptr_t AllocateData(idx_t size);
void FreeData(data_ptr_t pointer, idx_t size);
data_ptr_t ReallocateData(data_ptr_t pointer, idx_t size);
unique_ptr<AllocatedData> Allocate(idx_t size) {
return make_unique<AllocatedData>(*this, AllocateData(size), size);
}
static data_ptr_t DefaultAllocate(PrivateAllocatorData *private_data, idx_t size) {
return (data_ptr_t)malloc(size);
}
static void DefaultFree(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t size) {
free(pointer);
}
static data_ptr_t DefaultReallocate(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t size) {
return (data_ptr_t)realloc(pointer, size);
}
static Allocator &Get(ClientContext &context);
static Allocator &Get(DatabaseInstance &db);
PrivateAllocatorData *GetPrivateData() {
return private_data.get();
}
private:
allocate_function_ptr_t allocate_function;
free_function_ptr_t free_function;
reallocate_function_ptr_t reallocate_function;
unique_ptr<PrivateAllocatorData> private_data;
};
}
namespace duckdb {
class TableFunctionRef;
typedef unique_ptr<TableFunctionRef> (*replacement_scan_t)(const string &table_name, void *data);
struct ReplacementScan {
explicit ReplacementScan(replacement_scan_t function, void *data = nullptr) : function(function), data(data) {
}
replacement_scan_t function;
void *data;
};
}
#include <set>
namespace duckdb {
using std::set;
}
namespace duckdb {
enum class CompressionType : uint8_t {
COMPRESSION_INVALID = 0,
COMPRESSION_UNCOMPRESSED = 1,
COMPRESSION_CONSTANT = 2,
COMPRESSION_RLE = 3,
COMPRESSION_DICTIONARY = 4,
COMPRESSION_PFOR_DELTA = 5,
COMPRESSION_BITPACKING = 6,
COMPRESSION_FSST = 7
};
CompressionType CompressionTypeFromString(const string &str);
string CompressionTypeToString(CompressionType type);
}
namespace duckdb {
enum class OptimizerType : uint32_t {
INVALID = 0,
EXPRESSION_REWRITER,
FILTER_PULLUP,
FILTER_PUSHDOWN,
REGEX_RANGE,
IN_CLAUSE,
JOIN_ORDER,
DELIMINATOR,
UNUSED_COLUMNS,
STATISTICS_PROPAGATION,
COMMON_SUBEXPRESSIONS,
COMMON_AGGREGATE,
COLUMN_LIFETIME,
TOP_N,
REORDER_FILTER
};
string OptimizerTypeToString(OptimizerType type);
}
namespace duckdb {
class ClientContext;
class TableFunctionRef;
class CompressionFunction;
struct CompressionFunctionSet;
enum class AccessMode : uint8_t { UNDEFINED = 0, AUTOMATIC = 1, READ_ONLY = 2, READ_WRITE = 3 };
enum class CheckpointAbort : uint8_t {
NO_ABORT = 0,
DEBUG_ABORT_BEFORE_TRUNCATE = 1,
DEBUG_ABORT_BEFORE_HEADER = 2,
DEBUG_ABORT_AFTER_FREE_LIST_WRITE = 3
};
enum class ConfigurationOptionType : uint32_t {
INVALID = 0,
ACCESS_MODE,
DEFAULT_ORDER_TYPE,
DEFAULT_NULL_ORDER,
ENABLE_EXTERNAL_ACCESS,
ENABLE_OBJECT_CACHE,
MAXIMUM_MEMORY,
THREADS
};
struct ConfigurationOption {
ConfigurationOptionType type;
const char *name;
const char *description;
LogicalTypeId parameter_type;
};
struct DBConfig {
friend class DatabaseInstance;
friend class StorageManager;
public:
DUCKDB_API DBConfig();
DUCKDB_API ~DBConfig();
AccessMode access_mode = AccessMode::AUTOMATIC;
Allocator allocator;
idx_t checkpoint_wal_size = 1 << 24;
bool use_direct_io = false;
unique_ptr<FileSystem> file_system;
idx_t maximum_memory = (idx_t)-1;
idx_t maximum_threads = (idx_t)-1;
bool use_temporary_directory = true;
string temporary_directory;
string collation = string();
OrderType default_order_type = OrderType::ASCENDING;
OrderByNullType default_null_order = OrderByNullType::NULLS_FIRST;
bool enable_external_access = true;
bool object_cache_enable = false;
unordered_map<std::string, Value> set_variables;
bool force_checkpoint = false;
bool checkpoint_on_shutdown = true;
CheckpointAbort checkpoint_abort = CheckpointAbort::NO_ABORT;
vector<ReplacementScan> replacement_scans;
bool initialize_default_database = true;
set<OptimizerType> disabled_optimizers;
CompressionType force_compression = CompressionType::COMPRESSION_INVALID;
bool debug_many_free_list_blocks = false;
public:
DUCKDB_API static DBConfig &GetConfig(ClientContext &context);
DUCKDB_API static DBConfig &GetConfig(DatabaseInstance &db);
DUCKDB_API static vector<ConfigurationOption> GetOptions();
DUCKDB_API static idx_t GetOptionCount();
DUCKDB_API static ConfigurationOption *GetOptionByIndex(idx_t index);
DUCKDB_API static ConfigurationOption *GetOptionByName(const string &name);
DUCKDB_API void SetOption(const ConfigurationOption &option, const Value &value);
DUCKDB_API static idx_t ParseMemoryLimit(const string &arg);
DUCKDB_API vector<CompressionFunction *> GetCompressionFunctions(PhysicalType data_type);
DUCKDB_API CompressionFunction *GetCompressionFunction(CompressionType type, PhysicalType data_type);
private:
unique_ptr<CompressionFunctionSet> compression_functions;
};
}
namespace duckdb {
class DuckDB;
class Extension {
public:
DUCKDB_API virtual void Load(DuckDB &db) = 0;
DUCKDB_API virtual ~Extension() = default;
};
}
namespace duckdb {
class StorageManager;
class Catalog;
class TransactionManager;
class ConnectionManager;
class FileSystem;
class TaskScheduler;
class ObjectCache;
class DatabaseInstance : public std::enable_shared_from_this<DatabaseInstance> {
friend class DuckDB;
public:
DUCKDB_API DatabaseInstance();
DUCKDB_API ~DatabaseInstance();
DBConfig config;
public:
StorageManager &GetStorageManager();
Catalog &GetCatalog();
FileSystem &GetFileSystem();
TransactionManager &GetTransactionManager();
TaskScheduler &GetScheduler();
ObjectCache &GetObjectCache();
ConnectionManager &GetConnectionManager();
idx_t NumberOfThreads();
static DatabaseInstance &GetDatabase(ClientContext &context);
private:
void Initialize(const char *path, DBConfig *config);
void Configure(DBConfig &config);
private:
unique_ptr<StorageManager> storage;
unique_ptr<Catalog> catalog;
unique_ptr<TransactionManager> transaction_manager;
unique_ptr<TaskScheduler> scheduler;
unique_ptr<ObjectCache> object_cache;
unique_ptr<ConnectionManager> connection_manager;
};
class DuckDB {
public:
DUCKDB_API explicit DuckDB(const char *path = nullptr, DBConfig *config = nullptr);
DUCKDB_API explicit DuckDB(const string &path, DBConfig *config = nullptr);
DUCKDB_API ~DuckDB();
shared_ptr<DatabaseInstance> instance;
public:
template <class T>
void LoadExtension() {
T extension;
extension.Load(*this);
}
DUCKDB_API FileSystem &GetFileSystem();
DUCKDB_API idx_t NumberOfThreads();
DUCKDB_API static const char *SourceID();
DUCKDB_API static const char *LibraryVersion();
};
}
#ifdef DUCKDB_BUILD_LOADABLE_EXTENSION
#ifdef _WIN32
#include <windows.h>
#include <delayimp.h>
extern "C" {
FARPROC WINAPI duckdb_dllimport_delay_hook(unsigned dliNotify, PDelayLoadInfo pdli) {
switch (dliNotify) {
case dliNotePreLoadLibrary:
if (strcmp(pdli->szDll, "duckdb.dll") != 0) {
return NULL;
}
return (FARPROC)GetModuleHandle(NULL);
default:
return NULL;
}
return NULL;
}
ExternC const PfnDliHook __pfnDliNotifyHook2 = duckdb_dllimport_delay_hook;
ExternC const PfnDliHook __pfnDliFailureHook2 = duckdb_dllimport_delay_hook;
}
#endif
#endif
#ifdef _WIN32
#ifdef DUCKDB_BUILD_LIBRARY
#define DUCKDB_API __declspec(dllexport)
#else
#define DUCKDB_API __declspec(dllimport)
#endif
#else
#define DUCKDB_API
#endif
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef uint64_t idx_t;
typedef enum DUCKDB_TYPE {
DUCKDB_TYPE_INVALID = 0,
DUCKDB_TYPE_BOOLEAN,
DUCKDB_TYPE_TINYINT,
DUCKDB_TYPE_SMALLINT,
DUCKDB_TYPE_INTEGER,
DUCKDB_TYPE_BIGINT,
DUCKDB_TYPE_UTINYINT,
DUCKDB_TYPE_USMALLINT,
DUCKDB_TYPE_UINTEGER,
DUCKDB_TYPE_UBIGINT,
DUCKDB_TYPE_FLOAT,
DUCKDB_TYPE_DOUBLE,
DUCKDB_TYPE_TIMESTAMP,
DUCKDB_TYPE_DATE,
DUCKDB_TYPE_TIME,
DUCKDB_TYPE_INTERVAL,
DUCKDB_TYPE_HUGEINT,
DUCKDB_TYPE_VARCHAR,
DUCKDB_TYPE_BLOB
} duckdb_type;
typedef struct {
int32_t days;
} duckdb_date;
typedef struct {
int32_t year;
int8_t month;
int8_t day;
} duckdb_date_struct;
typedef struct {
int64_t micros;
} duckdb_time;
typedef struct {
int8_t hour;
int8_t min;
int8_t sec;
int32_t micros;
} duckdb_time_struct;
typedef struct {
int64_t micros;
} duckdb_timestamp;
typedef struct {
duckdb_date_struct date;
duckdb_time_struct time;
} duckdb_timestamp_struct;
typedef struct {
int32_t months;
int32_t days;
int64_t micros;
} duckdb_interval;
typedef struct {
uint64_t lower;
int64_t upper;
} duckdb_hugeint;
typedef struct {
void *data;
idx_t size;
} duckdb_blob;
typedef struct {
void *data;
bool *nullmask;
duckdb_type type;
char *name;
void *internal_data;
} duckdb_column;
typedef struct {
idx_t column_count;
idx_t row_count;
idx_t rows_changed;
duckdb_column *columns;
char *error_message;
void *internal_data;
} duckdb_result;
typedef void *duckdb_database;
typedef void *duckdb_connection;
typedef void *duckdb_prepared_statement;
typedef void *duckdb_appender;
typedef void *duckdb_arrow;
typedef void *duckdb_config;
typedef void *duckdb_arrow_schema;
typedef void *duckdb_arrow_array;
typedef enum { DuckDBSuccess = 0, DuckDBError = 1 } duckdb_state;
DUCKDB_API duckdb_state duckdb_open(const char *path, duckdb_database *out_database);
DUCKDB_API duckdb_state duckdb_open_ext(const char *path, duckdb_database *out_database, duckdb_config config,
char **out_error);
DUCKDB_API void duckdb_close(duckdb_database *database);
DUCKDB_API duckdb_state duckdb_connect(duckdb_database database, duckdb_connection *out_connection);
DUCKDB_API void duckdb_disconnect(duckdb_connection *connection);
DUCKDB_API duckdb_state duckdb_create_config(duckdb_config *out_config);
DUCKDB_API size_t duckdb_config_count();
DUCKDB_API duckdb_state duckdb_get_config_flag(size_t index, const char **out_name, const char **out_description);
DUCKDB_API duckdb_state duckdb_set_config(duckdb_config config, const char *name, const char *option);
DUCKDB_API void duckdb_destroy_config(duckdb_config *config);
DUCKDB_API duckdb_state duckdb_query(duckdb_connection connection, const char *query, duckdb_result *out_result);
DUCKDB_API void duckdb_destroy_result(duckdb_result *result);
DUCKDB_API const char *duckdb_column_name(duckdb_result *result, idx_t col);
DUCKDB_API duckdb_type duckdb_column_type(duckdb_result *result, idx_t col);
DUCKDB_API idx_t duckdb_column_count(duckdb_result *result);
DUCKDB_API idx_t duckdb_row_count(duckdb_result *result);
DUCKDB_API idx_t duckdb_rows_changed(duckdb_result *result);
DUCKDB_API void *duckdb_column_data(duckdb_result *result, idx_t col);
DUCKDB_API bool *duckdb_nullmask_data(duckdb_result *result, idx_t col);
DUCKDB_API char *duckdb_result_error(duckdb_result *result);
DUCKDB_API bool duckdb_value_boolean(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API int8_t duckdb_value_int8(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API int16_t duckdb_value_int16(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API int32_t duckdb_value_int32(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API int64_t duckdb_value_int64(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API duckdb_hugeint duckdb_value_hugeint(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API uint8_t duckdb_value_uint8(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API uint16_t duckdb_value_uint16(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API uint32_t duckdb_value_uint32(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API uint64_t duckdb_value_uint64(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API float duckdb_value_float(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API double duckdb_value_double(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API duckdb_date duckdb_value_date(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API duckdb_time duckdb_value_time(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API duckdb_timestamp duckdb_value_timestamp(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API duckdb_interval duckdb_value_interval(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API char *duckdb_value_varchar(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API char *duckdb_value_varchar_internal(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API duckdb_blob duckdb_value_blob(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API bool duckdb_value_is_null(duckdb_result *result, idx_t col, idx_t row);
DUCKDB_API void *duckdb_malloc(size_t size);
DUCKDB_API void duckdb_free(void *ptr);
DUCKDB_API duckdb_date_struct duckdb_from_date(duckdb_date date);
DUCKDB_API duckdb_date duckdb_to_date(duckdb_date_struct date);
DUCKDB_API duckdb_time_struct duckdb_from_time(duckdb_time time);
DUCKDB_API duckdb_time duckdb_to_time(duckdb_time_struct time);
DUCKDB_API duckdb_timestamp_struct duckdb_from_timestamp(duckdb_timestamp ts);
DUCKDB_API duckdb_timestamp duckdb_to_timestamp(duckdb_timestamp_struct ts);
DUCKDB_API double duckdb_hugeint_to_double(duckdb_hugeint val);
DUCKDB_API duckdb_hugeint duckdb_double_to_hugeint(double val);
DUCKDB_API duckdb_state duckdb_prepare(duckdb_connection connection, const char *query,
duckdb_prepared_statement *out_prepared_statement);
DUCKDB_API void duckdb_destroy_prepare(duckdb_prepared_statement *prepared_statement);
DUCKDB_API const char *duckdb_prepare_error(duckdb_prepared_statement prepared_statement);
DUCKDB_API idx_t duckdb_nparams(duckdb_prepared_statement prepared_statement);
DUCKDB_API duckdb_type duckdb_param_type(duckdb_prepared_statement prepared_statement, idx_t param_idx);
DUCKDB_API duckdb_state duckdb_bind_boolean(duckdb_prepared_statement prepared_statement, idx_t param_idx, bool val);
DUCKDB_API duckdb_state duckdb_bind_int8(duckdb_prepared_statement prepared_statement, idx_t param_idx, int8_t val);
DUCKDB_API duckdb_state duckdb_bind_int16(duckdb_prepared_statement prepared_statement, idx_t param_idx, int16_t val);
DUCKDB_API duckdb_state duckdb_bind_int32(duckdb_prepared_statement prepared_statement, idx_t param_idx, int32_t val);
DUCKDB_API duckdb_state duckdb_bind_int64(duckdb_prepared_statement prepared_statement, idx_t param_idx, int64_t val);
DUCKDB_API duckdb_state duckdb_bind_hugeint(duckdb_prepared_statement prepared_statement, idx_t param_idx,
duckdb_hugeint val);
DUCKDB_API duckdb_state duckdb_bind_uint8(duckdb_prepared_statement prepared_statement, idx_t param_idx, uint8_t val);
DUCKDB_API duckdb_state duckdb_bind_uint16(duckdb_prepared_statement prepared_statement, idx_t param_idx, uint16_t val);
DUCKDB_API duckdb_state duckdb_bind_uint32(duckdb_prepared_statement prepared_statement, idx_t param_idx, uint32_t val);
DUCKDB_API duckdb_state duckdb_bind_uint64(duckdb_prepared_statement prepared_statement, idx_t param_idx, uint64_t val);
DUCKDB_API duckdb_state duckdb_bind_float(duckdb_prepared_statement prepared_statement, idx_t param_idx, float val);
DUCKDB_API duckdb_state duckdb_bind_double(duckdb_prepared_statement prepared_statement, idx_t param_idx, double val);
DUCKDB_API duckdb_state duckdb_bind_date(duckdb_prepared_statement prepared_statement, idx_t param_idx,
duckdb_date val);
DUCKDB_API duckdb_state duckdb_bind_time(duckdb_prepared_statement prepared_statement, idx_t param_idx,
duckdb_time val);
DUCKDB_API duckdb_state duckdb_bind_timestamp(duckdb_prepared_statement prepared_statement, idx_t param_idx,
duckdb_timestamp val);
DUCKDB_API duckdb_state duckdb_bind_interval(duckdb_prepared_statement prepared_statement, idx_t param_idx,
duckdb_interval val);
DUCKDB_API duckdb_state duckdb_bind_varchar(duckdb_prepared_statement prepared_statement, idx_t param_idx,
const char *val);
DUCKDB_API duckdb_state duckdb_bind_varchar_length(duckdb_prepared_statement prepared_statement, idx_t param_idx,
const char *val, idx_t length);
DUCKDB_API duckdb_state duckdb_bind_blob(duckdb_prepared_statement prepared_statement, idx_t param_idx,
const void *data, idx_t length);
DUCKDB_API duckdb_state duckdb_bind_null(duckdb_prepared_statement prepared_statement, idx_t param_idx);
DUCKDB_API duckdb_state duckdb_execute_prepared(duckdb_prepared_statement prepared_statement,
duckdb_result *out_result);
DUCKDB_API duckdb_state duckdb_execute_prepared_arrow(duckdb_prepared_statement prepared_statement,
duckdb_arrow *out_result);
DUCKDB_API duckdb_state duckdb_appender_create(duckdb_connection connection, const char *schema, const char *table,
duckdb_appender *out_appender);
DUCKDB_API const char *duckdb_appender_error(duckdb_appender appender);
DUCKDB_API duckdb_state duckdb_appender_flush(duckdb_appender appender);
DUCKDB_API duckdb_state duckdb_appender_close(duckdb_appender appender);
DUCKDB_API duckdb_state duckdb_appender_destroy(duckdb_appender *appender);
DUCKDB_API duckdb_state duckdb_appender_begin_row(duckdb_appender appender);
DUCKDB_API duckdb_state duckdb_appender_end_row(duckdb_appender appender);
DUCKDB_API duckdb_state duckdb_append_bool(duckdb_appender appender, bool value);
DUCKDB_API duckdb_state duckdb_append_int8(duckdb_appender appender, int8_t value);
DUCKDB_API duckdb_state duckdb_append_int16(duckdb_appender appender, int16_t value);
DUCKDB_API duckdb_state duckdb_append_int32(duckdb_appender appender, int32_t value);
DUCKDB_API duckdb_state duckdb_append_int64(duckdb_appender appender, int64_t value);
DUCKDB_API duckdb_state duckdb_append_hugeint(duckdb_appender appender, duckdb_hugeint value);
DUCKDB_API duckdb_state duckdb_append_uint8(duckdb_appender appender, uint8_t value);
DUCKDB_API duckdb_state duckdb_append_uint16(duckdb_appender appender, uint16_t value);
DUCKDB_API duckdb_state duckdb_append_uint32(duckdb_appender appender, uint32_t value);
DUCKDB_API duckdb_state duckdb_append_uint64(duckdb_appender appender, uint64_t value);
DUCKDB_API duckdb_state duckdb_append_float(duckdb_appender appender, float value);
DUCKDB_API duckdb_state duckdb_append_double(duckdb_appender appender, double value);
DUCKDB_API duckdb_state duckdb_append_date(duckdb_appender appender, duckdb_date value);
DUCKDB_API duckdb_state duckdb_append_time(duckdb_appender appender, duckdb_time value);
DUCKDB_API duckdb_state duckdb_append_timestamp(duckdb_appender appender, duckdb_timestamp value);
DUCKDB_API duckdb_state duckdb_append_interval(duckdb_appender appender, duckdb_interval value);
DUCKDB_API duckdb_state duckdb_append_varchar(duckdb_appender appender, const char *val);
DUCKDB_API duckdb_state duckdb_append_varchar_length(duckdb_appender appender, const char *val, idx_t length);
DUCKDB_API duckdb_state duckdb_append_blob(duckdb_appender appender, const void *data, idx_t length);
DUCKDB_API duckdb_state duckdb_append_null(duckdb_appender appender);
DUCKDB_API duckdb_state duckdb_query_arrow(duckdb_connection connection, const char *query, duckdb_arrow *out_result);
DUCKDB_API duckdb_state duckdb_query_arrow_schema(duckdb_arrow result, duckdb_arrow_schema *out_schema);
DUCKDB_API duckdb_state duckdb_query_arrow_array(duckdb_arrow result, duckdb_arrow_array *out_array);
DUCKDB_API idx_t duckdb_arrow_column_count(duckdb_arrow result);
DUCKDB_API idx_t duckdb_arrow_row_count(duckdb_arrow result);
DUCKDB_API idx_t duckdb_arrow_rows_changed(duckdb_arrow result);
DUCKDB_API const char *duckdb_query_arrow_error(duckdb_arrow result);
DUCKDB_API void duckdb_destroy_arrow(duckdb_arrow *result);
#ifdef __cplusplus
}
#endif
namespace duckdb {
class Date {
public:
static const string_t MONTH_NAMES[12];
static const string_t MONTH_NAMES_ABBREVIATED[12];
static const string_t DAY_NAMES[7];
static const string_t DAY_NAMES_ABBREVIATED[7];
static const int32_t NORMAL_DAYS[13];
static const int32_t CUMULATIVE_DAYS[13];
static const int32_t LEAP_DAYS[13];
static const int32_t CUMULATIVE_LEAP_DAYS[13];
static const int32_t CUMULATIVE_YEAR_DAYS[401];
static const int8_t MONTH_PER_DAY_OF_YEAR[365];
static const int8_t LEAP_MONTH_PER_DAY_OF_YEAR[366];
constexpr static const int32_t DATE_MIN_YEAR = -5877641;
constexpr static const int32_t DATE_MIN_MONTH = 6;
constexpr static const int32_t DATE_MIN_DAY = 23;
constexpr static const int32_t DATE_MAX_YEAR = 5881580;
constexpr static const int32_t DATE_MAX_MONTH = 7;
constexpr static const int32_t DATE_MAX_DAY = 11;
constexpr static const int32_t EPOCH_YEAR = 1970;
constexpr static const int32_t YEAR_INTERVAL = 400;
constexpr static const int32_t DAYS_PER_YEAR_INTERVAL = 146097;
public:
static date_t FromString(const string &str, bool strict = false);
static date_t FromCString(const char *str, idx_t len, bool strict = false);
static string ToString(date_t date);
static bool TryConvertDate(const char *buf, idx_t len, idx_t &pos, date_t &result, bool strict = false);
static string Format(int32_t year, int32_t month, int32_t day);
static void Convert(date_t date, int32_t &out_year, int32_t &out_month, int32_t &out_day);
static date_t FromDate(int32_t year, int32_t month, int32_t day);
static bool TryFromDate(int32_t year, int32_t month, int32_t day, date_t &result);
static bool IsLeapYear(int32_t year);
static bool IsValid(int32_t year, int32_t month, int32_t day);
static int32_t MonthDays(int32_t year, int32_t month);
static int64_t Epoch(date_t date);
static int64_t EpochNanoseconds(date_t date);
static date_t EpochToDate(int64_t epoch);
static int32_t EpochDays(date_t date);
static date_t EpochDaysToDate(int32_t epoch);
static int32_t ExtractYear(date_t date);
static int32_t ExtractYear(date_t date, int32_t *last_year);
static int32_t ExtractYear(timestamp_t ts, int32_t *last_year);
static int32_t ExtractMonth(date_t date);
static int32_t ExtractDay(date_t date);
static int32_t ExtractISODayOfTheWeek(date_t date);
static int32_t ExtractDayOfTheYear(date_t date);
static int32_t ExtractISOWeekNumber(date_t date);
static int32_t ExtractWeekNumberRegular(date_t date, bool monday_first = true);
static date_t GetMondayOfCurrentWeek(date_t date);
static bool ParseDoubleDigit(const char *buf, idx_t len, idx_t &pos, int32_t &result);
static string ConversionError(const string &str);
static string ConversionError(string_t str);
private:
static void ExtractYearOffset(int32_t &n, int32_t &year, int32_t &year_offset);
};
}
#ifndef ARROW_FLAG_DICTIONARY_ORDERED
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define ARROW_FLAG_DICTIONARY_ORDERED 1
#define ARROW_FLAG_NULLABLE 2
#define ARROW_FLAG_MAP_KEYS_SORTED 4
struct ArrowSchema {
const char *format;
const char *name;
const char *metadata;
int64_t flags;
int64_t n_children;
struct ArrowSchema **children;
struct ArrowSchema *dictionary;
void (*release)(struct ArrowSchema *);
void *private_data;
};
struct ArrowArray {
int64_t length;
int64_t null_count;
int64_t offset;
int64_t n_buffers;
int64_t n_children;
const void **buffers;
struct ArrowArray **children;
struct ArrowArray *dictionary;
void (*release)(struct ArrowArray *);
void *private_data;
};
struct ArrowArrayStream {
int (*get_schema)(struct ArrowArrayStream *, struct ArrowSchema *out);
int (*get_next)(struct ArrowArrayStream *, struct ArrowArray *out);
const char *(*get_last_error)(struct ArrowArrayStream *);
void (*release)(struct ArrowArrayStream *);
void *private_data;
};
#ifdef __cplusplus
}
#endif
#endif
namespace duckdb {
class Blob {
public:
static constexpr const char *HEX_TABLE = "0123456789ABCDEF";
static const int HEX_MAP[256];
static constexpr const char *BASE64_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static constexpr const char BASE64_PADDING = '=';
public:
static idx_t GetStringSize(string_t blob);
static void ToString(string_t blob, char *output);
static string ToString(string_t blob);
static bool TryGetBlobSize(string_t str, idx_t &result_size, string *error_message);
static idx_t GetBlobSize(string_t str);
static void ToBlob(string_t str, data_ptr_t output);
static string ToBlob(string_t str);
static idx_t ToBase64Size(string_t blob);
static void ToBase64(string_t blob, char *output);
static idx_t FromBase64Size(string_t str);
static void FromBase64(string_t str, data_ptr_t output, idx_t output_size);
};
}
namespace duckdb {
class Decimal {
public:
static constexpr uint8_t MAX_WIDTH_INT16 = 4;
static constexpr uint8_t MAX_WIDTH_INT32 = 9;
static constexpr uint8_t MAX_WIDTH_INT64 = 18;
static constexpr uint8_t MAX_WIDTH_INT128 = 38;
static constexpr uint8_t MAX_WIDTH_DECIMAL = MAX_WIDTH_INT128;
public:
static string ToString(int16_t value, uint8_t scale);
static string ToString(int32_t value, uint8_t scale);
static string ToString(int64_t value, uint8_t scale);
static string ToString(hugeint_t value, uint8_t scale);
};
}
namespace duckdb {
struct timestamp_struct {
int32_t year;
int8_t month;
int8_t day;
int8_t hour;
int8_t min;
int8_t sec;
int16_t msec;
};
class Timestamp {
public:
static timestamp_t FromString(const string &str);
static bool TryConvertTimestamp(const char *str, idx_t len, timestamp_t &result);
static timestamp_t FromCString(const char *str, idx_t len);
static string ToString(timestamp_t timestamp);
static date_t GetDate(timestamp_t timestamp);
static dtime_t GetTime(timestamp_t timestamp);
static timestamp_t FromDatetime(date_t date, dtime_t time);
static bool TryFromDatetime(date_t date, dtime_t time, timestamp_t &result);
static void Convert(timestamp_t date, date_t &out_date, dtime_t &out_time);
static timestamp_t GetCurrentTimestamp();
static timestamp_t FromEpochSeconds(int64_t ms);
static timestamp_t FromEpochMs(int64_t ms);
static timestamp_t FromEpochMicroSeconds(int64_t micros);
static timestamp_t FromEpochNanoSeconds(int64_t micros);
static int64_t GetEpochSeconds(timestamp_t timestamp);
static int64_t GetEpochMs(timestamp_t timestamp);
static int64_t GetEpochMicroSeconds(timestamp_t timestamp);
static int64_t GetEpochNanoSeconds(timestamp_t timestamp);
static bool TryParseUTCOffset(const char *str, idx_t &pos, idx_t len, int &hour_offset, int &minute_offset);
static string ConversionError(const string &str);
static string ConversionError(string_t str);
};
}
namespace duckdb {
class Time {
public:
static dtime_t FromString(const string &str, bool strict = false);
static dtime_t FromCString(const char *buf, idx_t len, bool strict = false);
static bool TryConvertTime(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict = false);
static string ToString(dtime_t time);
static dtime_t FromTime(int32_t hour, int32_t minute, int32_t second, int32_t microseconds = 0);
static void Convert(dtime_t time, int32_t &out_hour, int32_t &out_min, int32_t &out_sec, int32_t &out_micros);
static string ConversionError(const string &str);
static string ConversionError(string_t str);
private:
static bool TryConvertInternal(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict);
};
}
namespace duckdb {
#define SERIALIZER_DEFAULT_SIZE 1024
struct BinaryData {
unique_ptr<data_t[]> data;
idx_t size;
};
class BufferedSerializer : public Serializer {
public:
explicit BufferedSerializer(idx_t maximum_size = SERIALIZER_DEFAULT_SIZE);
BufferedSerializer(unique_ptr<data_t[]> data, idx_t size);
BufferedSerializer(data_ptr_t data, idx_t size);
idx_t maximum_size;
data_ptr_t data;
BinaryData blob;
public:
void WriteData(const_data_ptr_t buffer, uint64_t write_size) override;
BinaryData GetData() {
return std::move(blob);
}
void Reset() {
blob.size = 0;
}
};
}
namespace duckdb {
class ClientContext;
class DuckDB;
class TableCatalogEntry;
class Connection;
class Appender {
static constexpr const idx_t FLUSH_COUNT = 100;
shared_ptr<ClientContext> context;
unique_ptr<TableDescription> description;
vector<LogicalType> types;
ChunkCollection collection;
unique_ptr<DataChunk> chunk;
idx_t column = 0;
public:
DUCKDB_API Appender(Connection &con, const string &schema_name, const string &table_name);
DUCKDB_API Appender(Connection &con, const string &table_name);
DUCKDB_API ~Appender();
DUCKDB_API void BeginRow();
DUCKDB_API void EndRow();
template <class T>
void Append(T value) {
throw Exception("Undefined type for Appender::Append!");
}
DUCKDB_API void Append(const char *value, uint32_t length);
template <typename... Args>
void AppendRow(Args... args) {
BeginRow();
AppendRowRecursive(args...);
}
DUCKDB_API void Flush();
DUCKDB_API void Close();
DUCKDB_API vector<LogicalType> &GetTypes() {
return types;
}
DUCKDB_API idx_t CurrentColumn() {
return column;
}
private:
void InitializeChunk();
void FlushChunk();
template <class T>
void AppendValueInternal(T value);
template <class SRC, class DST>
void AppendValueInternal(Vector &vector, SRC input);
void AppendRowRecursive() {
EndRow();
}
template <typename T, typename... Args>
void AppendRowRecursive(T value, Args... args) {
Append<T>(value);
AppendRowRecursive(args...);
}
void AppendValue(const Value &value);
};
template <>
void DUCKDB_API Appender::Append(bool value);
template <>
void DUCKDB_API Appender::Append(int8_t value);
template <>
void DUCKDB_API Appender::Append(int16_t value);
template <>
void DUCKDB_API Appender::Append(int32_t value);
template <>
void DUCKDB_API Appender::Append(int64_t value);
template <>
void DUCKDB_API Appender::Append(hugeint_t value);
template <>
void DUCKDB_API Appender::Append(uint8_t value);
template <>
void DUCKDB_API Appender::Append(uint16_t value);
template <>
void DUCKDB_API Appender::Append(uint32_t value);
template <>
void DUCKDB_API Appender::Append(uint64_t value);
template <>
void DUCKDB_API Appender::Append(float value);
template <>
void DUCKDB_API Appender::Append(double value);
template <>
void DUCKDB_API Appender::Append(date_t value);
template <>
void DUCKDB_API Appender::Append(dtime_t value);
template <>
void DUCKDB_API Appender::Append(timestamp_t value);
template <>
void DUCKDB_API Appender::Append(interval_t value);
template <>
void DUCKDB_API Appender::Append(const char *value);
template <>
void DUCKDB_API Appender::Append(string_t value);
template <>
void DUCKDB_API Appender::Append(Value value);
template <>
void DUCKDB_API Appender::Append(std::nullptr_t value);
}
namespace duckdb {
class ClientContext;
class DefaultGenerator {
public:
explicit DefaultGenerator(Catalog &catalog) : catalog(catalog), created_all_entries(false) {
}
virtual ~DefaultGenerator() {
}
Catalog &catalog;
atomic<bool> created_all_entries;
public:
virtual unique_ptr<CatalogEntry> CreateDefaultEntry(ClientContext &context, const string &entry_name) = 0;
virtual vector<string> GetDefaultEntries() = 0;
};
}
#include <functional>
#include <memory>
namespace duckdb {
struct AlterInfo;
class ClientContext;
typedef unordered_map<CatalogSet *, unique_lock<mutex>> set_lock_map_t;
struct MappingValue {
explicit MappingValue(idx_t index_) : index(index_), timestamp(0), deleted(false), parent(nullptr) {
}
idx_t index;
transaction_t timestamp;
bool deleted;
unique_ptr<MappingValue> child;
MappingValue *parent;
};
class CatalogSet {
friend class DependencyManager;
public:
explicit CatalogSet(Catalog &catalog, unique_ptr<DefaultGenerator> defaults = nullptr);
bool CreateEntry(ClientContext &context, const string &name, unique_ptr<CatalogEntry> value,
unordered_set<CatalogEntry *> &dependencies);
bool AlterEntry(ClientContext &context, const string &name, AlterInfo *alter_info);
bool DropEntry(ClientContext &context, const string &name, bool cascade);
void CleanupEntry(CatalogEntry *catalog_entry);
CatalogEntry *GetEntry(ClientContext &context, const string &name);
string SimilarEntry(ClientContext &context, const string &name);
void Undo(CatalogEntry *entry);
void Scan(const std::function<void(CatalogEntry *)> &callback);
void Scan(ClientContext &context, const std::function<void(CatalogEntry *)> &callback);
template <class T>
vector<T *> GetEntries(ClientContext &context) {
vector<T *> result;
Scan(context, [&](CatalogEntry *entry) { result.push_back((T *)entry); });
return result;
}
static bool HasConflict(ClientContext &context, transaction_t timestamp);
static bool UseTimestamp(ClientContext &context, transaction_t timestamp);
CatalogEntry *GetEntryFromIndex(idx_t index);
void UpdateTimestamp(CatalogEntry *entry, transaction_t timestamp);
private:
CatalogEntry *GetEntryForTransaction(ClientContext &context, CatalogEntry *current);
CatalogEntry *GetCommittedEntry(CatalogEntry *current);
bool GetEntryInternal(ClientContext &context, const string &name, idx_t &entry_index, CatalogEntry *&entry);
bool GetEntryInternal(ClientContext &context, idx_t entry_index, CatalogEntry *&entry);
void DropEntryInternal(ClientContext &context, idx_t entry_index, CatalogEntry &entry, bool cascade,
set_lock_map_t &lock_set);
CatalogEntry *CreateEntryInternal(ClientContext &context, unique_ptr<CatalogEntry> entry);
MappingValue *GetMapping(ClientContext &context, const string &name, bool allow_lowercase_alias,
bool get_latest = false);
void PutMapping(ClientContext &context, const string &name, idx_t entry_index);
void DeleteMapping(ClientContext &context, const string &name);
private:
Catalog &catalog;
mutex catalog_lock;
unordered_map<string, unique_ptr<MappingValue>> mapping;
unordered_map<idx_t, unique_ptr<CatalogEntry>> entries;
idx_t current_entry = 0;
unique_ptr<DefaultGenerator> defaults;
};
}
namespace duckdb {
class ClientContext;
class StandardEntry;
class TableCatalogEntry;
class TableFunctionCatalogEntry;
class SequenceCatalogEntry;
class Serializer;
class Deserializer;
enum class OnCreateConflict : uint8_t;
struct AlterTableInfo;
struct CreateIndexInfo;
struct CreateFunctionInfo;
struct CreateCollationInfo;
struct CreateViewInfo;
struct BoundCreateTableInfo;
struct CreatePragmaFunctionInfo;
struct CreateSequenceInfo;
struct CreateSchemaInfo;
struct CreateTableFunctionInfo;
struct CreateCopyFunctionInfo;
struct DropInfo;
class SchemaCatalogEntry : public CatalogEntry {
friend class Catalog;
public:
SchemaCatalogEntry(Catalog *catalog, string name, bool is_internal);
private:
CatalogSet tables;
CatalogSet indexes;
CatalogSet table_functions;
CatalogSet copy_functions;
CatalogSet pragma_functions;
CatalogSet functions;
CatalogSet sequences;
CatalogSet collations;
public:
CatalogEntry *GetEntry(ClientContext &context, CatalogType type, const string &name, bool if_exists,
QueryErrorContext error_context = QueryErrorContext());
void Scan(ClientContext &context, CatalogType type, const std::function<void(CatalogEntry *)> &callback);
void Scan(CatalogType type, const std::function<void(CatalogEntry *)> &callback);
virtual void Serialize(Serializer &serializer);
static unique_ptr<CreateSchemaInfo> Deserialize(Deserializer &source);
string ToSQL() override;
CatalogEntry *CreateIndex(ClientContext &context, CreateIndexInfo *info, TableCatalogEntry *table);
private:
CatalogEntry *CreateFunction(ClientContext &context, CreateFunctionInfo *info);
CatalogEntry *CreateTable(ClientContext &context, BoundCreateTableInfo *info);
CatalogEntry *CreateView(ClientContext &context, CreateViewInfo *info);
CatalogEntry *CreateSequence(ClientContext &context, CreateSequenceInfo *info);
CatalogEntry *CreateTableFunction(ClientContext &context, CreateTableFunctionInfo *info);
CatalogEntry *CreateCopyFunction(ClientContext &context, CreateCopyFunctionInfo *info);
CatalogEntry *CreatePragmaFunction(ClientContext &context, CreatePragmaFunctionInfo *info);
CatalogEntry *CreateCollation(ClientContext &context, CreateCollationInfo *info);
void DropEntry(ClientContext &context, DropInfo *info);
void Alter(ClientContext &context, AlterInfo *info);
CatalogEntry *AddEntry(ClientContext &context, unique_ptr<StandardEntry> entry, OnCreateConflict on_conflict);
CatalogEntry *AddEntry(ClientContext &context, unique_ptr<StandardEntry> entry, OnCreateConflict on_conflict,
unordered_set<CatalogEntry *> dependencies);
CatalogSet &GetCatalogSet(CatalogType type);
};
}
#include <deque>
namespace duckdb {
using std::deque;
}
namespace duckdb {
enum class ExplainOutputType : uint8_t { ALL = 0, OPTIMIZED_ONLY = 1, PHYSICAL_ONLY = 2 };
}
#include <utility>
namespace duckdb {
using std::make_pair;
using std::pair;
}
#ifndef DUCKDB_NO_THREADS
#include <thread>
namespace duckdb {
using std::thread;
}
#include <future>
#endif
namespace duckdb {
enum class PhysicalOperatorType : uint8_t {
INVALID,
ORDER_BY,
LIMIT,
TOP_N,
WINDOW,
UNNEST,
SIMPLE_AGGREGATE,
HASH_GROUP_BY,
PERFECT_HASH_GROUP_BY,
FILTER,
PROJECTION,
COPY_TO_FILE,
RESERVOIR_SAMPLE,
STREAMING_SAMPLE,
TABLE_SCAN,
DUMMY_SCAN,
CHUNK_SCAN,
RECURSIVE_CTE_SCAN,
DELIM_SCAN,
EXPRESSION_SCAN,
BLOCKWISE_NL_JOIN,
NESTED_LOOP_JOIN,
HASH_JOIN,
CROSS_PRODUCT,
PIECEWISE_MERGE_JOIN,
DELIM_JOIN,
INDEX_JOIN,
UNION,
RECURSIVE_CTE,
INSERT,
DELETE_OPERATOR,
UPDATE,
CREATE_TABLE,
CREATE_TABLE_AS,
CREATE_INDEX,
ALTER,
CREATE_SEQUENCE,
CREATE_VIEW,
CREATE_SCHEMA,
CREATE_MACRO,
DROP,
PRAGMA,
TRANSACTION,
EXPLAIN,
EMPTY_RESULT,
EXECUTE,
PREPARE,
VACUUM,
EXPORT,
SET,
LOAD,
INOUT_FUNCTION
};
string PhysicalOperatorToString(PhysicalOperatorType type);
}
namespace duckdb {
class ClientContext;
class ThreadContext;
class TaskContext;
class ExecutionContext {
public:
ExecutionContext(ClientContext &client_p, ThreadContext &thread_p, TaskContext &task_p)
: client(client_p), thread(thread_p), task(task_p) {
}
ClientContext &client;
ThreadContext &thread;
TaskContext &task;
};
}
#include <functional>
#include <utility>
namespace duckdb {
class ExpressionExecutor;
class PhysicalOperator;
class PhysicalOperatorState {
public:
PhysicalOperatorState(PhysicalOperator &op, PhysicalOperator *child);
virtual ~PhysicalOperatorState() = default;
bool finished;
DataChunk child_chunk;
unique_ptr<PhysicalOperatorState> child_state;
};
class PhysicalOperator {
public:
PhysicalOperator(PhysicalOperatorType type, vector<LogicalType> types, idx_t estimated_cardinality)
: type(type), types(std::move(types)), estimated_cardinality(estimated_cardinality) {
}
virtual ~PhysicalOperator() {
}
PhysicalOperatorType type;
vector<unique_ptr<PhysicalOperator>> children;
vector<LogicalType> types;
idx_t estimated_cardinality;
public:
virtual string GetName() const;
virtual string ParamsToString() const {
return "";
}
virtual string ToString() const;
void Print();
vector<LogicalType> &GetTypes() {
return types;
}
virtual void InitializeChunk(DataChunk &chunk) {
auto &types = GetTypes();
chunk.Initialize(types);
}
virtual void GetChunkInternal(ExecutionContext &context, DataChunk &chunk, PhysicalOperatorState *state) const = 0;
void GetChunk(ExecutionContext &context, DataChunk &chunk, PhysicalOperatorState *state) const;
virtual unique_ptr<PhysicalOperatorState> GetOperatorState() {
return make_unique<PhysicalOperatorState>(*this, children.size() == 0 ? nullptr : children[0].get());
}
virtual void FinalizeOperatorState(PhysicalOperatorState &state, ExecutionContext &context) {
if (!children.empty() && state.child_state) {
children[0]->FinalizeOperatorState(*state.child_state, context);
}
}
virtual bool IsSink() const {
return false;
}
};
}
namespace duckdb {
class Pipeline;
class GlobalOperatorState {
public:
virtual ~GlobalOperatorState() {
}
};
class LocalSinkState {
public:
virtual ~LocalSinkState() {
}
};
class PhysicalSink : public PhysicalOperator {
public:
PhysicalSink(PhysicalOperatorType type, vector<LogicalType> types, idx_t estimated_cardinality)
: PhysicalOperator(type, move(types), estimated_cardinality) {
}
unique_ptr<GlobalOperatorState> sink_state;
public:
virtual void Sink(ExecutionContext &context, GlobalOperatorState &gstate, LocalSinkState &lstate,
DataChunk &input) const = 0;
virtual void Combine(ExecutionContext &context, GlobalOperatorState &gstate, LocalSinkState &lstate) {
}
virtual bool Finalize(Pipeline &pipeline, ClientContext &context, unique_ptr<GlobalOperatorState> gstate) {
this->sink_state = move(gstate);
return true;
}
virtual unique_ptr<LocalSinkState> GetLocalSinkState(ExecutionContext &context) {
return make_unique<LocalSinkState>();
}
virtual unique_ptr<GlobalOperatorState> GetGlobalState(ClientContext &context) {
return make_unique<GlobalOperatorState>();
}
bool IsSink() const override {
return true;
}
void Schedule(ClientContext &context);
};
}
#include <functional>
namespace duckdb {
class BaseStatistics;
class LogicalGet;
struct ParallelState;
class TableFilterSet;
struct FunctionOperatorData {
virtual ~FunctionOperatorData() {
}
};
struct TableFilterCollection {
TableFilterSet *table_filters;
explicit TableFilterCollection(TableFilterSet *table_filters) : table_filters(table_filters) {
}
};
typedef unique_ptr<FunctionData> (*table_function_bind_t)(ClientContext &context, vector<Value> &inputs,
unordered_map<string, Value> &named_parameters,
vector<LogicalType> &input_table_types,
vector<string> &input_table_names,
vector<LogicalType> &return_types, vector<string> &names);
typedef unique_ptr<FunctionOperatorData> (*table_function_init_t)(ClientContext &context, const FunctionData *bind_data,
const vector<column_t> &column_ids,
TableFilterCollection *filters);
typedef unique_ptr<BaseStatistics> (*table_statistics_t)(ClientContext &context, const FunctionData *bind_data,
column_t column_index);
typedef void (*table_function_t)(ClientContext &context, const FunctionData *bind_data,
FunctionOperatorData *operator_state, DataChunk *input, DataChunk &output);
typedef void (*table_function_parallel_t)(ClientContext &context, const FunctionData *bind_data,
FunctionOperatorData *operator_state, DataChunk *input, DataChunk &output,
ParallelState *parallel_state);
typedef void (*table_function_cleanup_t)(ClientContext &context, const FunctionData *bind_data,
FunctionOperatorData *operator_state);
typedef idx_t (*table_function_max_threads_t)(ClientContext &context, const FunctionData *bind_data);
typedef unique_ptr<ParallelState> (*table_function_init_parallel_state_t)(ClientContext &context,
const FunctionData *bind_data);
typedef unique_ptr<FunctionOperatorData> (*table_function_init_parallel_t)(ClientContext &context,
const FunctionData *bind_data,
ParallelState *state,
const vector<column_t> &column_ids,
TableFilterCollection *filters);
typedef bool (*table_function_parallel_state_next_t)(ClientContext &context, const FunctionData *bind_data,
FunctionOperatorData *state, ParallelState *parallel_state);
typedef int (*table_function_progress_t)(ClientContext &context, const FunctionData *bind_data);
typedef void (*table_function_dependency_t)(unordered_set<CatalogEntry *> &dependencies, const FunctionData *bind_data);
typedef unique_ptr<NodeStatistics> (*table_function_cardinality_t)(ClientContext &context,
const FunctionData *bind_data);
typedef void (*table_function_pushdown_complex_filter_t)(ClientContext &context, LogicalGet &get,
FunctionData *bind_data,
vector<unique_ptr<Expression>> &filters);
typedef string (*table_function_to_string_t)(const FunctionData *bind_data);
class TableFunction : public SimpleNamedParameterFunction {
public:
TableFunction(string name, vector<LogicalType> arguments, table_function_t function,
table_function_bind_t bind = nullptr, table_function_init_t init = nullptr,
table_statistics_t statistics = nullptr, table_function_cleanup_t cleanup = nullptr,
table_function_dependency_t dependency = nullptr, table_function_cardinality_t cardinality = nullptr,
table_function_pushdown_complex_filter_t pushdown_complex_filter = nullptr,
table_function_to_string_t to_string = nullptr, table_function_max_threads_t max_threads = nullptr,
table_function_init_parallel_state_t init_parallel_state = nullptr,
table_function_parallel_t parallel_function = nullptr,
table_function_init_parallel_t parallel_init = nullptr,
table_function_parallel_state_next_t parallel_state_next = nullptr, bool projection_pushdown = false,
bool filter_pushdown = false, table_function_progress_t query_progress = nullptr)
: SimpleNamedParameterFunction(std::move(name), move(arguments)), bind(bind), init(init), function(function),
statistics(statistics), cleanup(cleanup), dependency(dependency), cardinality(cardinality),
pushdown_complex_filter(pushdown_complex_filter), to_string(to_string), max_threads(max_threads),
init_parallel_state(init_parallel_state), parallel_function(parallel_function), parallel_init(parallel_init),
parallel_state_next(parallel_state_next), table_scan_progress(query_progress),
projection_pushdown(projection_pushdown), filter_pushdown(filter_pushdown) {
}
TableFunction(const vector<LogicalType> &arguments, table_function_t function, table_function_bind_t bind = nullptr,
table_function_init_t init = nullptr, table_statistics_t statistics = nullptr,
table_function_cleanup_t cleanup = nullptr, table_function_dependency_t dependency = nullptr,
table_function_cardinality_t cardinality = nullptr,
table_function_pushdown_complex_filter_t pushdown_complex_filter = nullptr,
table_function_to_string_t to_string = nullptr, table_function_max_threads_t max_threads = nullptr,
table_function_init_parallel_state_t init_parallel_state = nullptr,
table_function_parallel_t parallel_function = nullptr,
table_function_init_parallel_t parallel_init = nullptr,
table_function_parallel_state_next_t parallel_state_next = nullptr, bool projection_pushdown = false,
bool filter_pushdown = false, table_function_progress_t query_progress = nullptr)
: TableFunction(string(), arguments, function, bind, init, statistics, cleanup, dependency, cardinality,
pushdown_complex_filter, to_string, max_threads, init_parallel_state, parallel_function,
parallel_init, parallel_state_next, projection_pushdown, filter_pushdown, query_progress) {
}
TableFunction() : SimpleNamedParameterFunction("", {}) {
}
table_function_bind_t bind;
table_function_init_t init;
table_function_t function;
table_statistics_t statistics;
table_function_cleanup_t cleanup;
table_function_dependency_t dependency;
table_function_cardinality_t cardinality;
table_function_pushdown_complex_filter_t pushdown_complex_filter;
table_function_to_string_t to_string;
table_function_max_threads_t max_threads;
table_function_init_parallel_state_t init_parallel_state;
table_function_parallel_t parallel_function;
table_function_init_parallel_t parallel_init;
table_function_parallel_state_next_t parallel_state_next;
table_function_progress_t table_scan_progress;
bool projection_pushdown;
bool filter_pushdown;
string ToString() override {
return SimpleNamedParameterFunction::ToString();
}
};
}
namespace duckdb {
struct ParallelState {
virtual ~ParallelState() {
}
};
}
namespace duckdb {
class Task {
public:
virtual ~Task() {
}
virtual void Execute() = 0;
};
}
namespace duckdb {
struct ConcurrentQueue;
struct QueueProducerToken;
class ClientContext;
class TaskScheduler;
struct SchedulerThread;
struct ProducerToken {
ProducerToken(TaskScheduler &scheduler, unique_ptr<QueueProducerToken> token);
~ProducerToken();
TaskScheduler &scheduler;
unique_ptr<QueueProducerToken> token;
mutex producer_lock;
};
class TaskScheduler {
constexpr static int64_t TASK_TIMEOUT_USECS = 50000;
public:
TaskScheduler();
~TaskScheduler();
static TaskScheduler &GetScheduler(ClientContext &context);
unique_ptr<ProducerToken> CreateProducer();
void ScheduleTask(ProducerToken &producer, unique_ptr<Task> task);
bool GetTaskFromProducer(ProducerToken &token, unique_ptr<Task> &task);
void ExecuteForever(atomic<bool> *marker);
void SetThreads(int32_t n);
int32_t NumberOfThreads();
private:
void SetThreadsInternal(int32_t n);
unique_ptr<ConcurrentQueue> queue;
vector<unique_ptr<SchedulerThread>> threads;
vector<unique_ptr<atomic<bool>>> markers;
};
}
namespace duckdb {
class Executor;
class TaskContext;
class Pipeline : public std::enable_shared_from_this<Pipeline> {
friend class Executor;
public:
Pipeline(Executor &execution_context, ProducerToken &token);
Executor &executor;
ProducerToken &token;
public:
void Execute(TaskContext &task);
void AddDependency(shared_ptr<Pipeline> &pipeline);
void CompleteDependency();
bool HasDependencies() {
return !dependencies.empty();
}
void Reset(ClientContext &context);
void Schedule();
void FinishTask();
void Finish();
string ToString() const;
void Print() const;
void SetRecursiveCTE(PhysicalOperator *op) {
this->recursive_cte = op;
}
PhysicalOperator *GetRecursiveCTE() {
return recursive_cte;
}
void ClearParents();
void IncrementTasks(idx_t amount) {
this->total_tasks += amount;
}
bool IsFinished() {
return finished;
}
bool GetProgress(int ¤t_percentage);
public:
atomic<idx_t> finished_tasks;
atomic<idx_t> total_tasks;
private:
PhysicalOperator *child;
unique_ptr<GlobalOperatorState> sink_state;
PhysicalSink *sink;
unordered_map<Pipeline *, weak_ptr<Pipeline>> parents;
unordered_map<Pipeline *, weak_ptr<Pipeline>> dependencies;
atomic<idx_t> finished_dependencies;
PhysicalOperator *parallel_node;
unique_ptr<ParallelState> parallel_state;
bool finished;
PhysicalOperator *recursive_cte;
private:
bool GetProgress(ClientContext &context, PhysicalOperator *op, int ¤t_percentage);
void ScheduleSequentialTask();
bool LaunchScanTasks(PhysicalOperator *op, idx_t max_threads, unique_ptr<ParallelState> parallel_state);
bool ScheduleOperator(PhysicalOperator *op);
};
}
#include <queue>
namespace duckdb {
class ClientContext;
class DataChunk;
class PhysicalOperator;
class PhysicalOperatorState;
class ThreadContext;
class Task;
struct ProducerToken;
class Executor {
friend class Pipeline;
friend class PipelineTask;
public:
explicit Executor(ClientContext &context);
~Executor();
ClientContext &context;
public:
void Initialize(PhysicalOperator *physical_plan);
void BuildPipelines(PhysicalOperator *op, Pipeline *parent);
void Reset();
vector<LogicalType> GetTypes();
unique_ptr<DataChunk> FetchChunk();
void PushError(const string &exception);
bool GetError(string &exception);
void Flush(ThreadContext &context);
bool GetPipelinesProgress(int ¤t_progress);
private:
PhysicalOperator *physical_plan;
unique_ptr<PhysicalOperatorState> physical_state;
mutex executor_lock;
vector<shared_ptr<Pipeline>> pipelines;
unique_ptr<ProducerToken> producer;
vector<string> exceptions;
atomic<idx_t> completed_pipelines;
idx_t total_pipelines;
unordered_map<PhysicalOperator *, Pipeline *> delim_join_dependencies;
PhysicalOperator *recursive_cte;
};
}
namespace duckdb {
class ProgressBar {
public:
explicit ProgressBar(Executor *executor, idx_t show_progress_after, idx_t time_update_bar = 100)
: executor(executor), show_progress_after(show_progress_after), time_update_bar(time_update_bar),
current_percentage(-1), stop(false) {
}
~ProgressBar();
void Start();
void Stop();
int GetCurrentPercentage();
void Initialize(idx_t show_progress_after) {
this->show_progress_after = show_progress_after;
}
private:
const string PROGRESS_BAR_STRING = "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||";
static constexpr const idx_t PROGRESS_BAR_WIDTH = 60;
Executor *executor = nullptr;
#ifndef DUCKDB_NO_THREADS
thread progress_bar_thread;
std::condition_variable c;
mutex m;
#endif
idx_t show_progress_after;
idx_t time_update_bar;
atomic<int> current_percentage;
atomic<bool> stop;
bool supported = true;
void ProgressBarThread();
#ifndef DUCKDB_NO_THREADS
template <class DURATION>
bool WaitFor(DURATION duration) {
unique_lock<mutex> l(m);
return !c.wait_for(l, duration, [this]() { return stop.load(); });
}
#endif
};
}
namespace duckdb {
class ClientContext;
class Transaction;
class TransactionManager;
class TransactionContext {
public:
TransactionContext(TransactionManager &transaction_manager, ClientContext &context)
: transaction_manager(transaction_manager), context(context), auto_commit(true), current_transaction(nullptr) {
}
~TransactionContext();
Transaction &ActiveTransaction() {
D_ASSERT(current_transaction);
return *current_transaction;
}
bool HasActiveTransaction() {
return !!current_transaction;
}
void RecordQuery(string query);
void BeginTransaction();
void Commit();
void Rollback();
void ClearTransaction();
void SetAutoCommit(bool value);
bool IsAutoCommit() {
return auto_commit;
}
private:
TransactionManager &transaction_manager;
ClientContext &context;
bool auto_commit;
Transaction *current_transaction;
TransactionContext(const TransactionContext &) = delete;
};
}
#include <random>
namespace duckdb {
class Appender;
class Catalog;
class ChunkCollection;
class DatabaseInstance;
class LogicalOperator;
class PreparedStatementData;
class Relation;
class BufferedFileWriter;
class QueryProfiler;
class QueryProfilerHistory;
class ClientContextLock;
struct CreateScalarFunctionInfo;
class ScalarFunctionCatalogEntry;
class ClientContext : public std::enable_shared_from_this<ClientContext> {
friend class TransactionManager;
public:
DUCKDB_API explicit ClientContext(shared_ptr<DatabaseInstance> db);
DUCKDB_API ~ClientContext();
unique_ptr<QueryProfiler> profiler;
unique_ptr<QueryProfilerHistory> query_profiler_history;
shared_ptr<DatabaseInstance> db;
TransactionContext transaction;
atomic<bool> interrupted;
string query;
Executor executor;
unique_ptr<ProgressBar> progress_bar;
bool enable_progress_bar = false;
bool print_progress_bar = true;
int wait_time = 2000;
unique_ptr<SchemaCatalogEntry> temporary_objects;
unordered_map<string, shared_ptr<PreparedStatementData>> prepared_statements;
bool query_verification_enabled = false;
bool enable_optimizer = true;
bool force_parallelism = false;
bool force_index_join = false;
bool force_external = false;
idx_t perfect_ht_threshold = 12;
unique_ptr<BufferedFileWriter> log_query_writer;
ExplainOutputType explain_output_type = ExplainOutputType::PHYSICAL_ONLY;
std::mt19937 random_engine;
vector<string> catalog_search_path = {TEMP_SCHEMA, DEFAULT_SCHEMA, "pg_catalog"};
public:
DUCKDB_API Transaction &ActiveTransaction() {
return transaction.ActiveTransaction();
}
DUCKDB_API void Interrupt();
DUCKDB_API void EnableProfiling();
DUCKDB_API void DisableProfiling();
DUCKDB_API unique_ptr<QueryResult> Query(const string &query, bool allow_stream_result);
DUCKDB_API unique_ptr<QueryResult> Query(unique_ptr<SQLStatement> statement, bool allow_stream_result);
DUCKDB_API unique_ptr<DataChunk> Fetch();
DUCKDB_API void Cleanup();
DUCKDB_API void Destroy();
DUCKDB_API unique_ptr<TableDescription> TableInfo(const string &schema_name, const string &table_name);
DUCKDB_API void Append(TableDescription &description, ChunkCollection &collection);
DUCKDB_API void TryBindRelation(Relation &relation, vector<ColumnDefinition> &result_columns);
DUCKDB_API unique_ptr<QueryResult> Execute(const shared_ptr<Relation> &relation);
DUCKDB_API unique_ptr<PreparedStatement> Prepare(const string &query);
DUCKDB_API unique_ptr<PreparedStatement> Prepare(unique_ptr<SQLStatement> statement);
DUCKDB_API unique_ptr<QueryResult> Execute(const string &query, shared_ptr<PreparedStatementData> &prepared,
vector<Value> &values, bool allow_stream_result = true);
int GetProgress();
DUCKDB_API void RegisterFunction(CreateFunctionInfo *info);
DUCKDB_API vector<unique_ptr<SQLStatement>> ParseStatements(const string &query);
DUCKDB_API unique_ptr<LogicalOperator> ExtractPlan(const string &query);
void HandlePragmaStatements(vector<unique_ptr<SQLStatement>> &statements);
DUCKDB_API void RunFunctionInTransaction(const std::function<void(void)> &fun,
bool requires_valid_transaction = true);
DUCKDB_API void RunFunctionInTransactionInternal(ClientContextLock &lock, const std::function<void(void)> &fun,
bool requires_valid_transaction = true);
private:
vector<unique_ptr<SQLStatement>> ParseStatementsInternal(ClientContextLock &lock, const string &query);
string VerifyQuery(ClientContextLock &lock, const string &query, unique_ptr<SQLStatement> statement);
void InitialCleanup(ClientContextLock &lock);
void CleanupInternal(ClientContextLock &lock);
string FinalizeQuery(ClientContextLock &lock, bool success);
unique_ptr<DataChunk> FetchInternal(ClientContextLock &lock);
unique_ptr<QueryResult> RunStatements(ClientContextLock &lock, const string &query,
vector<unique_ptr<SQLStatement>> &statements, bool allow_stream_result);
unique_ptr<QueryResult> RunStatement(ClientContextLock &lock, const string &query,
unique_ptr<SQLStatement> statement, bool allow_stream_result);
unique_ptr<QueryResult> RunStatementOrPreparedStatement(ClientContextLock &lock, const string &query,
unique_ptr<SQLStatement> statement,
shared_ptr<PreparedStatementData> &prepared,
vector<Value> *values, bool allow_stream_result);
shared_ptr<PreparedStatementData> CreatePreparedStatement(ClientContextLock &lock, const string &query,
unique_ptr<SQLStatement> statement);
unique_ptr<QueryResult> ExecutePreparedStatement(ClientContextLock &lock, const string &query,
shared_ptr<PreparedStatementData> statement,
vector<Value> bound_values, bool allow_stream_result);
unique_ptr<QueryResult> RunStatementInternal(ClientContextLock &lock, const string &query,
unique_ptr<SQLStatement> statement, bool allow_stream_result);
unique_ptr<PreparedStatement> PrepareInternal(ClientContextLock &lock, unique_ptr<SQLStatement> statement);
void LogQueryInternal(ClientContextLock &lock, const string &query);
unique_ptr<ClientContextLock> LockContext();
bool UpdateFunctionInfoFromEntry(ScalarFunctionCatalogEntry *existing_function, CreateScalarFunctionInfo *new_info);
private:
StreamQueryResult *open_result = nullptr;
mutex context_lock;
};
}
namespace duckdb {
struct ParseInfo {
virtual ~ParseInfo() {
}
};
}
namespace duckdb {
enum class OnCreateConflict : uint8_t {
ERROR_ON_CONFLICT,
IGNORE_ON_CONFLICT,
REPLACE_ON_CONFLICT
};
struct CreateInfo : public ParseInfo {
explicit CreateInfo(CatalogType type, string schema = DEFAULT_SCHEMA)
: type(type), schema(schema), on_conflict(OnCreateConflict::ERROR_ON_CONFLICT), temporary(false),
internal(false) {
}
~CreateInfo() override {
}
CatalogType type;
string schema;
OnCreateConflict on_conflict;
bool temporary;
bool internal;
string sql;
public:
virtual unique_ptr<CreateInfo> Copy() const = 0;
void CopyProperties(CreateInfo &other) const {
other.type = type;
other.schema = schema;
other.on_conflict = on_conflict;
other.temporary = temporary;
other.internal = internal;
other.sql = sql;
}
};
}
namespace duckdb {
struct CreateFunctionInfo : public CreateInfo {
explicit CreateFunctionInfo(CatalogType type) : CreateInfo(type) {
D_ASSERT(type == CatalogType::SCALAR_FUNCTION_ENTRY || type == CatalogType::AGGREGATE_FUNCTION_ENTRY ||
type == CatalogType::TABLE_FUNCTION_ENTRY || type == CatalogType::PRAGMA_FUNCTION_ENTRY ||
type == CatalogType::MACRO_ENTRY);
}
string name;
};
}
namespace duckdb {
template <class T>
class FunctionSet {
public:
explicit FunctionSet(string name) : name(name) {
}
string name;
vector<T> functions;
public:
void AddFunction(T function) {
function.name = name;
functions.push_back(function);
}
};
class ScalarFunctionSet : public FunctionSet<ScalarFunction> {
public:
explicit ScalarFunctionSet(string name) : FunctionSet(move(name)) {
}
};
class AggregateFunctionSet : public FunctionSet<AggregateFunction> {
public:
explicit AggregateFunctionSet(string name) : FunctionSet(move(name)) {
}
};
class TableFunctionSet : public FunctionSet<TableFunction> {
public:
explicit TableFunctionSet(string name) : FunctionSet(move(name)) {
}
};
}
namespace duckdb {
struct CreateTableFunctionInfo : public CreateFunctionInfo {
explicit CreateTableFunctionInfo(TableFunctionSet set)
: CreateFunctionInfo(CatalogType::TABLE_FUNCTION_ENTRY), functions(move(set.functions)) {
this->name = set.name;
}
explicit CreateTableFunctionInfo(TableFunction function) : CreateFunctionInfo(CatalogType::TABLE_FUNCTION_ENTRY) {
this->name = function.name;
functions.push_back(move(function));
}
vector<TableFunction> functions;
public:
unique_ptr<CreateInfo> Copy() const override {
TableFunctionSet set(name);
set.functions = functions;
auto result = make_unique<CreateTableFunctionInfo>(move(set));
CopyProperties(*result);
return move(result);
}
};
}
namespace duckdb {
struct CopyInfo : public ParseInfo {
CopyInfo() : schema(DEFAULT_SCHEMA) {
}
string schema;
string table;
vector<string> select_list;
string file_path;
bool is_from;
string format;
unordered_map<string, vector<Value>> options;
public:
unique_ptr<CopyInfo> Copy() const {
auto result = make_unique<CopyInfo>();
result->schema = schema;
result->table = table;
result->select_list = select_list;
result->file_path = file_path;
result->is_from = is_from;
result->format = format;
result->options = options;
return result;
}
};
}
namespace duckdb {
class ExecutionContext;
struct LocalFunctionData {
virtual ~LocalFunctionData() {
}
};
struct GlobalFunctionData {
virtual ~GlobalFunctionData() {
}
};
typedef unique_ptr<FunctionData> (*copy_to_bind_t)(ClientContext &context, CopyInfo &info, vector<string> &names,
vector<LogicalType> &sql_types);
typedef unique_ptr<LocalFunctionData> (*copy_to_initialize_local_t)(ClientContext &context, FunctionData &bind_data);
typedef unique_ptr<GlobalFunctionData> (*copy_to_initialize_global_t)(ClientContext &context, FunctionData &bind_data);
typedef void (*copy_to_sink_t)(ClientContext &context, FunctionData &bind_data, GlobalFunctionData &gstate,
LocalFunctionData &lstate, DataChunk &input);
typedef void (*copy_to_combine_t)(ClientContext &context, FunctionData &bind_data, GlobalFunctionData &gstate,
LocalFunctionData &lstate);
typedef void (*copy_to_finalize_t)(ClientContext &context, FunctionData &bind_data, GlobalFunctionData &gstate);
typedef unique_ptr<FunctionData> (*copy_from_bind_t)(ClientContext &context, CopyInfo &info,
vector<string> &expected_names,
vector<LogicalType> &expected_types);
class CopyFunction : public Function {
public:
explicit CopyFunction(string name)
: Function(name), copy_to_bind(nullptr), copy_to_initialize_local(nullptr), copy_to_initialize_global(nullptr),
copy_to_sink(nullptr), copy_to_combine(nullptr), copy_to_finalize(nullptr), copy_from_bind(nullptr) {
}
copy_to_bind_t copy_to_bind;
copy_to_initialize_local_t copy_to_initialize_local;
copy_to_initialize_global_t copy_to_initialize_global;
copy_to_sink_t copy_to_sink;
copy_to_combine_t copy_to_combine;
copy_to_finalize_t copy_to_finalize;
copy_from_bind_t copy_from_bind;
TableFunction copy_from_function;
string extension;
};
}
namespace duckdb {
struct CreateCopyFunctionInfo : public CreateInfo {
explicit CreateCopyFunctionInfo(CopyFunction function)
: CreateInfo(CatalogType::COPY_FUNCTION_ENTRY), function(function) {
this->name = function.name;
}
string name;
CopyFunction function;
public:
unique_ptr<CreateInfo> Copy() const override {
auto result = make_unique<CreateCopyFunctionInfo>(function);
CopyProperties(*result);
return move(result);
}
};
}