From 3a6f966098d6ff195a03d3ca398ea929f7d0fffc Mon Sep 17 00:00:00 2001 From: Pradeep Chhetri <30620077+chhetripradeep@users.noreply.github.com> Date: Wed, 7 Sep 2022 17:43:21 +0800 Subject: [PATCH] Bump 0.4.0 -> 0.5.0 (#77) * Bump 0.4.0 -> 0.5.0 Signed-off-by: Pradeep Chhetri * Feedbacks Signed-off-by: Pradeep Chhetri Signed-off-by: Pradeep Chhetri --- .github/workflows/rust.yaml | 2 +- .gitignore | 5 +- Cargo.toml | 4 +- libduckdb-sys/Cargo.toml | 2 +- .../duckdb/bindgen_bundled_version.rs | 147 +- libduckdb-sys/duckdb/duckdb.cpp | 141904 ++++++++++----- libduckdb-sys/duckdb/duckdb.h | 144 +- libduckdb-sys/duckdb/duckdb.hpp | 8835 +- libduckdb-sys/upgrade.sh | 2 +- src/cache.rs | 22 +- src/types/to_sql.rs | 4 +- 11 files changed, 99547 insertions(+), 51524 deletions(-) diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index 625abf94..63cdf38e 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -38,7 +38,7 @@ jobs: name: Download duckdb with: repository: "duckdb/duckdb" - tag: "v0.4.0" + tag: "v0.5.0" fileName: ${{ matrix.duckdb }} out-file-path: . diff --git a/.gitignore b/.gitignore index 24b5d52a..5ff91ed2 100644 --- a/.gitignore +++ b/.gitignore @@ -15,8 +15,9 @@ Cargo.lock /target **/target -# Ignore vscode +# Ignore vscode and intellij .vscode +.idea # Ignore zip file *.zip @@ -24,4 +25,4 @@ Cargo.lock # ccls .ccls-cache/ -*.db \ No newline at end of file +*.db diff --git a/Cargo.toml b/Cargo.toml index f15c33e3..853057df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "duckdb" -version = "0.4.0" +version = "0.5.0" authors = ["wangfenjin "] edition = "2021" description = "Ergonomic wrapper for DuckDB" @@ -69,7 +69,7 @@ tempdir = "0.3.7" [dependencies.libduckdb-sys] path = "libduckdb-sys" -version = "0.4.0" +version = "0.5.0" [package.metadata.docs.rs] features = [] diff --git a/libduckdb-sys/Cargo.toml b/libduckdb-sys/Cargo.toml index 282244c7..a846eef3 100644 --- a/libduckdb-sys/Cargo.toml +++ b/libduckdb-sys/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "libduckdb-sys" -version = "0.4.0" +version = "0.5.0" authors = ["wangfenjin "] edition = "2021" build = "build.rs" diff --git a/libduckdb-sys/duckdb/bindgen_bundled_version.rs b/libduckdb-sys/duckdb/bindgen_bundled_version.rs index 9d90a4be..52b09dc8 100644 --- a/libduckdb-sys/duckdb/bindgen_bundled_version.rs +++ b/libduckdb-sys/duckdb/bindgen_bundled_version.rs @@ -106,7 +106,6 @@ pub const __DARWIN_NO_LONG_LONG: u32 = 0; pub const _DARWIN_FEATURE_64_BIT_INODE: u32 = 1; pub const _DARWIN_FEATURE_ONLY_UNIX_CONFORMANCE: u32 = 1; pub const _DARWIN_FEATURE_UNIX_CONFORMANCE: u32 = 3; -pub const __has_ptrcheck: u32 = 0; pub const __PTHREAD_SIZE__: u32 = 8176; pub const __PTHREAD_ATTR_SIZE__: u32 = 56; pub const __PTHREAD_MUTEXATTR_SIZE__: u32 = 8; @@ -203,8 +202,6 @@ pub const __MAC_11_5: u32 = 110500; pub const __MAC_11_6: u32 = 110600; pub const __MAC_12_0: u32 = 120000; pub const __MAC_12_1: u32 = 120100; -pub const __MAC_12_2: u32 = 120200; -pub const __MAC_12_3: u32 = 120300; pub const __IPHONE_2_0: u32 = 20000; pub const __IPHONE_2_1: u32 = 20100; pub const __IPHONE_2_2: u32 = 20200; @@ -263,8 +260,6 @@ pub const __IPHONE_14_8: u32 = 140800; pub const __IPHONE_15_0: u32 = 150000; pub const __IPHONE_15_1: u32 = 150100; pub const __IPHONE_15_2: u32 = 150200; -pub const __IPHONE_15_3: u32 = 150300; -pub const __IPHONE_15_4: u32 = 150400; pub const __TVOS_9_0: u32 = 90000; pub const __TVOS_9_1: u32 = 90100; pub const __TVOS_9_2: u32 = 90200; @@ -296,8 +291,6 @@ pub const __TVOS_14_7: u32 = 140700; pub const __TVOS_15_0: u32 = 150000; pub const __TVOS_15_1: u32 = 150100; pub const __TVOS_15_2: u32 = 150200; -pub const __TVOS_15_3: u32 = 150300; -pub const __TVOS_15_4: u32 = 150400; pub const __WATCHOS_1_0: u32 = 10000; pub const __WATCHOS_2_0: u32 = 20000; pub const __WATCHOS_2_1: u32 = 20100; @@ -327,8 +320,6 @@ pub const __WATCHOS_7_6: u32 = 70600; pub const __WATCHOS_8_0: u32 = 80000; pub const __WATCHOS_8_1: u32 = 80100; pub const __WATCHOS_8_3: u32 = 80300; -pub const __WATCHOS_8_4: u32 = 80400; -pub const __WATCHOS_8_5: u32 = 80500; pub const MAC_OS_X_VERSION_10_0: u32 = 1000; pub const MAC_OS_X_VERSION_10_1: u32 = 1010; pub const MAC_OS_X_VERSION_10_2: u32 = 1020; @@ -366,7 +357,7 @@ pub const MAC_OS_VERSION_12_0: u32 = 120000; pub const __DRIVERKIT_19_0: u32 = 190000; pub const __DRIVERKIT_20_0: u32 = 200000; pub const __DRIVERKIT_21_0: u32 = 210000; -pub const __MAC_OS_X_VERSION_MAX_ALLOWED: u32 = 120300; +pub const __MAC_OS_X_VERSION_MAX_ALLOWED: u32 = 120100; pub const __ENABLE_LEGACY_MAC_AVAILABILITY: u32 = 1; pub const __DARWIN_WCHAR_MIN: i32 = -2147483648; pub const _FORTIFY_SOURCE: u32 = 2; @@ -14577,10 +14568,7 @@ extern "C" { pub fn valloc(arg1: size_t) -> *mut ::std::os::raw::c_void; } extern "C" { - pub fn aligned_alloc( - __alignment: ::std::os::raw::c_ulong, - __size: ::std::os::raw::c_ulong, - ) -> *mut ::std::os::raw::c_void; + pub fn aligned_alloc(__alignment: size_t, __size: size_t) -> *mut ::std::os::raw::c_void; } extern "C" { pub fn posix_memalign( @@ -15910,6 +15898,7 @@ fn bindgen_test_layout_duckdb_result() { pub type duckdb_database = *mut ::std::os::raw::c_void; pub type duckdb_connection = *mut ::std::os::raw::c_void; pub type duckdb_prepared_statement = *mut ::std::os::raw::c_void; +pub type duckdb_pending_result = *mut ::std::os::raw::c_void; pub type duckdb_appender = *mut ::std::os::raw::c_void; pub type duckdb_arrow = *mut ::std::os::raw::c_void; pub type duckdb_config = *mut ::std::os::raw::c_void; @@ -15922,6 +15911,10 @@ pub type duckdb_value = *mut ::std::os::raw::c_void; pub const duckdb_state_DuckDBSuccess: duckdb_state = 0; pub const duckdb_state_DuckDBError: duckdb_state = 1; pub type duckdb_state = ::std::os::raw::c_uint; +pub const duckdb_pending_state_DUCKDB_PENDING_RESULT_READY: duckdb_pending_state = 0; +pub const duckdb_pending_state_DUCKDB_PENDING_RESULT_NOT_READY: duckdb_pending_state = 1; +pub const duckdb_pending_state_DUCKDB_PENDING_ERROR: duckdb_pending_state = 2; +pub type duckdb_pending_state = ::std::os::raw::c_uint; extern "C" { #[doc = "Creates a new database or opens an existing database file stored at the the given path."] #[doc = "If no path is given a new in-memory database is created instead."] @@ -16155,7 +16148,7 @@ extern "C" { #[doc = ""] #[doc = "The result of this function must not be freed. It will be cleaned up when `duckdb_destroy_result` is called."] #[doc = ""] - #[doc = " result: The result object to fetch the nullmask from."] + #[doc = " result: The result object to fetch the error from."] #[doc = " returns: The error of the result."] pub fn duckdb_result_error(result: *mut duckdb_result) -> *const ::std::os::raw::c_char; } @@ -16413,6 +16406,10 @@ extern "C" { #[doc = " returns: The parameter type"] pub fn duckdb_param_type(prepared_statement: duckdb_prepared_statement, param_idx: idx_t) -> duckdb_type; } +extern "C" { + #[doc = "Clear the params bind to the prepared statement."] + pub fn duckdb_clear_bindings(prepared_statement: duckdb_prepared_statement) -> duckdb_state; +} extern "C" { #[doc = "Binds a bool value to the prepared statement at the specified index."] pub fn duckdb_bind_boolean( @@ -16576,6 +16573,64 @@ extern "C" { out_result: *mut duckdb_arrow, ) -> duckdb_state; } +extern "C" { + #[doc = "Executes the prepared statement with the given bound parameters, and returns a pending result."] + #[doc = "The pending result represents an intermediate structure for a query that is not yet fully executed."] + #[doc = "The pending result can be used to incrementally execute a query, returning control to the client between tasks."] + #[doc = ""] + #[doc = "Note that after calling `duckdb_pending_prepared`, the pending result should always be destroyed using"] + #[doc = "`duckdb_destroy_pending`, even if this function returns DuckDBError."] + #[doc = ""] + #[doc = " prepared_statement: The prepared statement to execute."] + #[doc = " out_result: The pending query result."] + #[doc = " returns: `DuckDBSuccess` on success or `DuckDBError` on failure."] + pub fn duckdb_pending_prepared( + prepared_statement: duckdb_prepared_statement, + out_result: *mut duckdb_pending_result, + ) -> duckdb_state; +} +extern "C" { + #[doc = "Closes the pending result and de-allocates all memory allocated for the result."] + #[doc = ""] + #[doc = " pending_result: The pending result to destroy."] + pub fn duckdb_destroy_pending(pending_result: *mut duckdb_pending_result); +} +extern "C" { + #[doc = "Returns the error message contained within the pending result."] + #[doc = ""] + #[doc = "The result of this function must not be freed. It will be cleaned up when `duckdb_destroy_pending` is called."] + #[doc = ""] + #[doc = " result: The pending result to fetch the error from."] + #[doc = " returns: The error of the pending result."] + pub fn duckdb_pending_error(pending_result: duckdb_pending_result) -> *const ::std::os::raw::c_char; +} +extern "C" { + #[doc = "Executes a single task within the query, returning whether or not the query is ready."] + #[doc = ""] + #[doc = "If this returns DUCKDB_PENDING_RESULT_READY, the duckdb_execute_pending function can be called to obtain the result."] + #[doc = "If this returns DUCKDB_PENDING_RESULT_NOT_READY, the duckdb_pending_execute_task function should be called again."] + #[doc = "If this returns DUCKDB_PENDING_ERROR, an error occurred during execution."] + #[doc = ""] + #[doc = "The error message can be obtained by calling duckdb_pending_error on the pending_result."] + #[doc = ""] + #[doc = " pending_result: The pending result to execute a task within.."] + #[doc = " returns: The state of the pending result after the execution."] + pub fn duckdb_pending_execute_task(pending_result: duckdb_pending_result) -> duckdb_pending_state; +} +extern "C" { + #[doc = "Fully execute a pending query result, returning the final query result."] + #[doc = ""] + #[doc = "If duckdb_pending_execute_task has been called until DUCKDB_PENDING_RESULT_READY was returned, this will return fast."] + #[doc = "Otherwise, all remaining tasks must be executed first."] + #[doc = ""] + #[doc = " pending_result: The pending result to execute."] + #[doc = " out_result: The result object."] + #[doc = " returns: `DuckDBSuccess` on success or `DuckDBError` on failure."] + pub fn duckdb_execute_pending( + pending_result: duckdb_pending_result, + out_result: *mut duckdb_result, + ) -> duckdb_state; +} extern "C" { #[doc = "Destroys the value and de-allocates all memory allocated for that type."] #[doc = ""] @@ -17109,6 +17164,13 @@ extern "C" { destroy: duckdb_delete_callback_t, ); } +extern "C" { + #[doc = "Sets the cardinality estimate for the table function, used for optimization."] + #[doc = ""] + #[doc = " info: The bind data object."] + #[doc = " is_exact: Whether or not the cardinality estimate is exact, or an approximation"] + pub fn duckdb_bind_set_cardinality(info: duckdb_bind_info, cardinality: idx_t, is_exact: bool); +} extern "C" { #[doc = "Report that an error has occurred while calling bind."] #[doc = ""] @@ -17495,6 +17557,7 @@ extern "C" { #[doc = " result: The result to destroy."] pub fn duckdb_destroy_arrow(result: *mut duckdb_arrow); } +pub type duckdb_task_state = *mut ::std::os::raw::c_void; extern "C" { #[doc = "Execute DuckDB tasks on this thread."] #[doc = ""] @@ -17504,6 +17567,60 @@ extern "C" { #[doc = " max_tasks: The maximum amount of tasks to execute"] pub fn duckdb_execute_tasks(database: duckdb_database, max_tasks: idx_t); } +extern "C" { + #[doc = "Creates a task state that can be used with duckdb_execute_tasks_state to execute tasks until"] + #[doc = "duckdb_finish_execution is called on the state."] + #[doc = ""] + #[doc = "duckdb_destroy_state should be called on the result in order to free memory."] + #[doc = ""] + #[doc = " database: The database object to create the task state for"] + #[doc = " returns: The task state that can be used with duckdb_execute_tasks_state."] + pub fn duckdb_create_task_state(database: duckdb_database) -> duckdb_task_state; +} +extern "C" { + #[doc = "Execute DuckDB tasks on this thread."] + #[doc = ""] + #[doc = "The thread will keep on executing tasks forever, until duckdb_finish_execution is called on the state."] + #[doc = "Multiple threads can share the same duckdb_task_state."] + #[doc = ""] + #[doc = " state: The task state of the executor"] + pub fn duckdb_execute_tasks_state(state: duckdb_task_state); +} +extern "C" { + #[doc = "Execute DuckDB tasks on this thread."] + #[doc = ""] + #[doc = "The thread will keep on executing tasks until either duckdb_finish_execution is called on the state,"] + #[doc = "max_tasks tasks have been executed or there are no more tasks to be executed."] + #[doc = ""] + #[doc = "Multiple threads can share the same duckdb_task_state."] + #[doc = ""] + #[doc = " state: The task state of the executor"] + #[doc = " max_tasks: The maximum amount of tasks to execute"] + #[doc = " returns: The amount of tasks that have actually been executed"] + pub fn duckdb_execute_n_tasks_state(state: duckdb_task_state, max_tasks: idx_t) -> idx_t; +} +extern "C" { + #[doc = "Finish execution on a specific task."] + #[doc = ""] + #[doc = " state: The task state to finish execution"] + pub fn duckdb_finish_execution(state: duckdb_task_state); +} +extern "C" { + #[doc = "Check if the provided duckdb_task_state has finished execution"] + #[doc = ""] + #[doc = " state: The task state to inspect"] + #[doc = " returns: Whether or not duckdb_finish_execution has been called on the task state"] + pub fn duckdb_task_state_is_finished(state: duckdb_task_state) -> bool; +} +extern "C" { + #[doc = "Destroys the task state returned from duckdb_create_task_state."] + #[doc = ""] + #[doc = "Note that this should not be called while there is an active duckdb_execute_tasks_state running"] + #[doc = "on the task state."] + #[doc = ""] + #[doc = " state: The task state to clean up"] + pub fn duckdb_destroy_task_state(state: duckdb_task_state); +} pub type __builtin_va_list = [__va_list_tag; 1usize]; #[repr(C)] #[derive(Debug, Copy, Clone)] diff --git a/libduckdb-sys/duckdb/duckdb.cpp b/libduckdb-sys/duckdb/duckdb.cpp index 01cfaceb..815fcddd 100644 --- a/libduckdb-sys/duckdb/duckdb.cpp +++ b/libduckdb-sys/duckdb/duckdb.cpp @@ -37,6 +37,8 @@ class CatalogSearchPath { CatalogSearchPath(const CatalogSearchPath &other) = delete; DUCKDB_API void Set(const string &new_value, bool is_set_schema); + DUCKDB_API void Set(vector &new_paths, bool is_set_schema = false); + DUCKDB_API const vector &Get(); DUCKDB_API const vector &GetSetPaths() { return set_paths; @@ -89,13 +91,13 @@ namespace duckdb { struct CreateAggregateFunctionInfo : public CreateFunctionInfo { explicit CreateAggregateFunctionInfo(AggregateFunction function) : CreateFunctionInfo(CatalogType::AGGREGATE_FUNCTION_ENTRY), functions(function.name) { - this->name = function.name; + name = function.name; functions.AddFunction(move(function)); } explicit CreateAggregateFunctionInfo(AggregateFunctionSet set) : CreateFunctionInfo(CatalogType::AGGREGATE_FUNCTION_ENTRY), functions(move(set)) { - this->name = functions.name; + name = functions.name; for (auto &func : functions.functions) { func.name = functions.name; } @@ -121,11 +123,11 @@ class AggregateFunctionCatalogEntry : public StandardEntry { public: AggregateFunctionCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, CreateAggregateFunctionInfo *info) : StandardEntry(CatalogType::AGGREGATE_FUNCTION_ENTRY, schema, catalog, info->name), - functions(info->functions.functions) { + functions(info->functions) { } //! The aggregate functions - vector functions; + AggregateFunctionSet functions; }; } // namespace duckdb @@ -174,6 +176,11 @@ struct CreateCollationInfo : public CreateInfo { //! speeds up processing. bool not_required_for_equality; +protected: + void SerializeInternal(Serializer &) const override { + throw NotImplementedException("Cannot serialize '%s'", CatalogTypeToString(type)); + } + public: unique_ptr Copy() const override { auto result = make_unique(name, function, combinable, not_required_for_equality); @@ -274,11 +281,21 @@ namespace duckdb { //===--------------------------------------------------------------------===// // Index Types //===--------------------------------------------------------------------===// -enum class IndexType { +enum class IndexType : uint8_t { INVALID = 0, // invalid index type ART = 1 // Adaptive Radix Tree }; +//===--------------------------------------------------------------------===// +// Index Constraint Types +//===--------------------------------------------------------------------===// +enum IndexConstraintType : uint8_t { + NONE = 0, // index is an index don't built to any constraint + UNIQUE = 1, // index is an index built to enforce a UNIQUE constraint + PRIMARY = 2, // index is an index built to enforce a PRIMARY KEY constraint + FOREIGN = 3 // index is an index built to enforce a FOREIGN KEY constraint +}; + } // namespace duckdb @@ -334,26 +351,156 @@ struct CreateIndexInfo : public CreateInfo { IndexType index_type; //! Name of the Index string index_name; - //! If it is an unique index - bool unique = false; + //! Index Constraint Type + IndexConstraintType constraint_type; //! The table to create the index on unique_ptr table; //! Set of expressions to index by vector> expressions; + vector> parsed_expressions; + + vector column_ids; + +protected: + void SerializeInternal(Serializer &serializer) const override; public: - unique_ptr Copy() const override { - auto result = make_unique(); - CopyProperties(*result); - result->index_type = index_type; - result->index_name = index_name; - result->unique = unique; - result->table = unique_ptr_cast(table->Copy()); - for (auto &expr : expressions) { - result->expressions.push_back(expr->Copy()); - } - return move(result); + unique_ptr Copy() const override; + + static unique_ptr Deserialize(Deserializer &deserializer); +}; + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/storage/meta_block_writer.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/storage/block.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + +namespace duckdb { + +class Block : public FileBuffer { +public: + Block(Allocator &allocator, block_id_t id); + Block(FileBuffer &source, block_id_t id); + + block_id_t id; +}; + +struct BlockPointer { + BlockPointer(block_id_t block_id_p, uint32_t offset_p) : block_id(block_id_p), offset(offset_p) {}; + BlockPointer() {}; + block_id_t block_id; + uint32_t offset; +}; + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/storage/block_manager.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + +namespace duckdb { +class ClientContext; +class DatabaseInstance; + +//! BlockManager is an abstract representation to manage blocks on DuckDB. When writing or reading blocks, the +//! BlockManager creates and accesses blocks. The concrete types implements how blocks are stored. +class BlockManager { +public: + virtual ~BlockManager() = default; + + virtual void StartCheckpoint() = 0; + //! Creates a new block inside the block manager + virtual unique_ptr CreateBlock(block_id_t block_id) = 0; + //! Return the next free block id + virtual block_id_t GetFreeBlockId() = 0; + //! Returns whether or not a specified block is the root block + virtual bool IsRootBlock(block_id_t root) = 0; + //! Mark a block as "modified"; modified blocks are added to the free list after a checkpoint (i.e. their data is + //! assumed to be rewritten) + virtual void MarkBlockAsModified(block_id_t block_id) = 0; + //! Increase the reference count of a block. The block should hold at least one reference before this method is + //! called. + virtual void IncreaseBlockReferenceCount(block_id_t block_id) = 0; + //! Get the first meta block id + virtual block_id_t GetMetaBlock() = 0; + //! Read the content of the block from disk + virtual void Read(Block &block) = 0; + //! Writes the block to disk + virtual void Write(FileBuffer &block, block_id_t block_id) = 0; + //! Writes the block to disk + void Write(Block &block) { + Write(block, block.id); } + //! Write the header; should be the final step of a checkpoint + virtual void WriteHeader(DatabaseHeader header) = 0; + + //! Returns the number of total blocks + virtual idx_t TotalBlocks() = 0; + //! Returns the number of free blocks + virtual idx_t FreeBlocks() = 0; + + static BlockManager &GetBlockManager(ClientContext &context); + static BlockManager &GetBlockManager(DatabaseInstance &db); +}; +} // namespace duckdb + + + +namespace duckdb { +class DatabaseInstance; + +//! This struct is responsible for writing metadata to disk +class MetaBlockWriter : public Serializer { +public: + MetaBlockWriter(DatabaseInstance &db, block_id_t initial_block_id = INVALID_BLOCK); + ~MetaBlockWriter() override; + + DatabaseInstance &db; + unique_ptr block; + set written_blocks; + idx_t offset; + +public: + BlockPointer GetBlockPointer(); + void Flush(); + + void WriteData(const_data_ptr_t buffer, idx_t write_size) override; + +protected: + virtual block_id_t GetNextBlockId(); }; } // namespace duckdb @@ -367,16 +514,20 @@ class Index; //! An index catalog entry class IndexCatalogEntry : public StandardEntry { public: - //! Create a real TableCatalogEntry and initialize storage for it + //! Create an IndexCatalogEntry and initialize storage for it IndexCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, CreateIndexInfo *info); ~IndexCatalogEntry() override; Index *index; shared_ptr info; string sql; + vector> expressions; + vector> parsed_expressions; public: string ToSQL() override; + void Serialize(duckdb::MetaBlockWriter &serializer); + static unique_ptr Deserialize(Deserializer &source, ClientContext &context); }; } // namespace duckdb @@ -413,7 +564,7 @@ class IndexCatalogEntry : public StandardEntry { //===----------------------------------------------------------------------===// -//! The SelectStatement of the view + @@ -463,11 +614,9 @@ enum class MacroType : uint8_t { VOID_MACRO = 0, TABLE_MACRO = 1, SCALAR_MACRO = class MacroFunction { public: - // explicit MacroFunction(unique_ptr expression); MacroFunction(MacroType type); - // MacroFunction(void); - // The type + //! The type MacroType type; //! The positional parameters vector> parameters; @@ -486,6 +635,8 @@ class MacroFunction { FunctionExpression &function_expr, vector> &positionals, unordered_map> &defaults); + + virtual string ToSQL(const string &schema, const string &name); }; } // namespace duckdb @@ -541,6 +692,10 @@ class MacroCatalogEntry : public StandardEntry { public: //! Serialize the meta information virtual void Serialize(Serializer &serializer) = 0; + + string ToSQL() override { + return function->ToSQL(schema->name, name); + } }; } // namespace duckdb @@ -557,7 +712,7 @@ class ScalarMacroCatalogEntry : public MacroCatalogEntry { //! Serialize the meta information of the ScalarMacroCatalogEntry void Serialize(Serializer &serializer) override; //! Deserializes to a CreateMacroInfo - static unique_ptr Deserialize(Deserializer &source); + static unique_ptr Deserialize(Deserializer &source, ClientContext &context); }; } // namespace duckdb @@ -572,103 +727,9 @@ class ScalarMacroCatalogEntry : public MacroCatalogEntry { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/function/pragma_function.hpp -// -// -//===----------------------------------------------------------------------===// - - - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/parser/parsed_data/pragma_info.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - -namespace duckdb { - -enum class PragmaType : uint8_t { PRAGMA_STATEMENT, PRAGMA_CALL }; - -struct PragmaInfo : public ParseInfo { - //! Name of the PRAGMA statement - string name; - //! Parameter list (if any) - vector parameters; - //! Named parameter list (if any) - named_parameter_map_t named_parameters; - -public: - unique_ptr Copy() const { - auto result = make_unique(); - result->name = name; - result->parameters = parameters; - result->named_parameters = named_parameters; - return result; - } -}; - -} // namespace duckdb - - - -namespace duckdb { -class ClientContext; - -//! Return a substitute query to execute instead of this pragma statement -typedef string (*pragma_query_t)(ClientContext &context, const FunctionParameters ¶meters); -//! Execute the main pragma function -typedef void (*pragma_function_t)(ClientContext &context, const FunctionParameters ¶meters); - -//! Pragma functions are invoked by calling PRAGMA x -//! Pragma functions come in three types: -//! * Call: function call, e.g. PRAGMA table_info('tbl') -//! -> call statements can take multiple parameters -//! * Statement: statement without parameters, e.g. PRAGMA show_tables -//! -> this is similar to a call pragma but without parameters -//! Pragma functions can either return a new query to execute (pragma_query_t) -//! or they can -class PragmaFunction : public SimpleNamedParameterFunction { -public: - // Call - DUCKDB_API static PragmaFunction PragmaCall(const string &name, pragma_query_t query, vector arguments, - LogicalType varargs = LogicalType::INVALID); - DUCKDB_API static PragmaFunction PragmaCall(const string &name, pragma_function_t function, - vector arguments, - LogicalType varargs = LogicalType::INVALID); - // Statement - DUCKDB_API static PragmaFunction PragmaStatement(const string &name, pragma_query_t query); - DUCKDB_API static PragmaFunction PragmaStatement(const string &name, pragma_function_t function); - - DUCKDB_API string ToString() override; - -public: - PragmaType type; - - pragma_query_t query; - pragma_function_t function; - named_parameter_type_map_t named_parameters; - -private: - PragmaFunction(string name, PragmaType pragma_type, pragma_query_t query, pragma_function_t function, - vector arguments, LogicalType varargs); -}; - -} // namespace duckdb - - namespace duckdb { class Catalog; @@ -680,7 +741,7 @@ class PragmaFunctionCatalogEntry : public StandardEntry { PragmaFunctionCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, CreatePragmaFunctionInfo *info); //! The pragma functions - vector functions; + PragmaFunctionSet functions; }; } // namespace duckdb @@ -715,24 +776,24 @@ namespace duckdb { struct CreateScalarFunctionInfo : public CreateFunctionInfo { explicit CreateScalarFunctionInfo(ScalarFunction function) - : CreateFunctionInfo(CatalogType::SCALAR_FUNCTION_ENTRY) { - this->name = function.name; - functions.push_back(function); + : CreateFunctionInfo(CatalogType::SCALAR_FUNCTION_ENTRY), functions(function.name) { + name = function.name; + functions.AddFunction(move(function)); } explicit CreateScalarFunctionInfo(ScalarFunctionSet set) - : CreateFunctionInfo(CatalogType::SCALAR_FUNCTION_ENTRY), functions(move(set.functions)) { - this->name = set.name; - for (auto &func : functions) { - func.name = set.name; + : CreateFunctionInfo(CatalogType::SCALAR_FUNCTION_ENTRY), functions(move(set)) { + name = functions.name; + for (auto &func : functions.functions) { + func.name = functions.name; } } - vector functions; + ScalarFunctionSet functions; public: unique_ptr Copy() const override { ScalarFunctionSet set(name); - set.functions = functions; + set.functions = functions.functions; auto result = make_unique(move(set)); CopyProperties(*result); return move(result); @@ -752,7 +813,7 @@ class ScalarFunctionCatalogEntry : public StandardEntry { } //! The scalar functions - vector functions; + ScalarFunctionSet functions; }; } // namespace duckdb @@ -801,7 +862,7 @@ class ViewCatalogEntry : public StandardEntry { //! Serialize the meta information of the ViewCatalogEntry a serializer virtual void Serialize(Serializer &serializer); //! Deserializes to a CreateTableInfo - static unique_ptr Deserialize(Deserializer &source); + static unique_ptr Deserialize(Deserializer &source, ClientContext &context); unique_ptr Copy(ClientContext &context) override; @@ -979,7 +1040,7 @@ struct CreateTypeInfo : public CreateInfo { //! Name of the Type string name; //! Logical Type - LogicalType type; + LogicalType type; // Shouldn't this be named `logical_type`? (shadows a parent member `type`) public: unique_ptr Copy() const override { @@ -989,6 +1050,11 @@ struct CreateTypeInfo : public CreateInfo { result->type = type; return move(result); } + +protected: + void SerializeInternal(Serializer &) const override { + throw NotImplementedException("Cannot serialize '%s'", CatalogTypeToString(CreateInfo::type)); + } }; } // namespace duckdb @@ -1064,7 +1130,7 @@ struct ClientData { unique_ptr random_engine; //! The catalog search path - const unique_ptr catalog_search_path; + unique_ptr catalog_search_path; //! The file opener of the client context unique_ptr file_opener; @@ -1219,23 +1285,20 @@ namespace duckdb { struct CreatePragmaFunctionInfo : public CreateFunctionInfo { explicit CreatePragmaFunctionInfo(PragmaFunction function) - : CreateFunctionInfo(CatalogType::PRAGMA_FUNCTION_ENTRY) { - functions.push_back(move(function)); - this->name = function.name; + : CreateFunctionInfo(CatalogType::PRAGMA_FUNCTION_ENTRY), functions(function.name) { + name = function.name; + functions.AddFunction(move(function)); } - CreatePragmaFunctionInfo(string name, vector functions_) - : CreateFunctionInfo(CatalogType::PRAGMA_FUNCTION_ENTRY), functions(move(functions_)) { + CreatePragmaFunctionInfo(string name, PragmaFunctionSet functions_) + : CreateFunctionInfo(CatalogType::PRAGMA_FUNCTION_ENTRY), functions(functions_) { this->name = name; - for (auto &function : functions) { - function.name = name; - } } - vector functions; + PragmaFunctionSet functions; public: unique_ptr Copy() const override { - auto result = make_unique(functions[0].name, functions); + auto result = make_unique(functions.name, functions); CopyProperties(*result); return move(result); } @@ -1268,6 +1331,16 @@ struct CreateSchemaInfo : public CreateInfo { CopyProperties(*result); return move(result); } + + static unique_ptr Deserialize(Deserializer &deserializer) { + auto result = make_unique(); + result->DeserializeBase(deserializer); + return result; + } + +protected: + void SerializeInternal(Serializer &) const override { + } }; } // namespace duckdb @@ -1315,6 +1388,30 @@ struct CreateViewInfo : public CreateInfo { result->query = unique_ptr_cast(query->Copy()); return move(result); } + + static unique_ptr Deserialize(Deserializer &deserializer) { + auto result = make_unique(); + result->DeserializeBase(deserializer); + + FieldReader reader(deserializer); + result->view_name = reader.ReadRequired(); + result->aliases = reader.ReadRequiredList(); + result->types = reader.ReadRequiredSerializableList(); + result->query = reader.ReadOptional(nullptr); + reader.Finalize(); + + return result; + } + +protected: + void SerializeInternal(Serializer &serializer) const override { + FieldWriter writer(serializer); + writer.WriteString(view_name); + writer.WriteList(aliases); + writer.WriteRegularSerializableList(types); + writer.WriteOptional(query); + writer.Finalize(); + } }; } // namespace duckdb @@ -1394,10 +1491,8 @@ struct DropInfo : public ParseInfo { namespace duckdb { struct CreateTableInfo : public CreateInfo { - CreateTableInfo() : CreateInfo(CatalogType::TABLE_ENTRY, INVALID_SCHEMA) { - } - CreateTableInfo(string schema, string name) : CreateInfo(CatalogType::TABLE_ENTRY, schema), table(name) { - } + DUCKDB_API CreateTableInfo(); + DUCKDB_API CreateTableInfo(string schema, string name); //! Table name to insert to string table; @@ -1408,21 +1503,13 @@ struct CreateTableInfo : public CreateInfo { //! CREATE TABLE from QUERY unique_ptr query; +protected: + void SerializeInternal(Serializer &serializer) const override; + public: - unique_ptr Copy() const override { - auto result = make_unique(schema, table); - CopyProperties(*result); - for (auto &column : columns) { - result->columns.push_back(column.Copy()); - } - for (auto &constraint : constraints) { - result->constraints.push_back(constraint->Copy()); - } - if (query) { - result->query = unique_ptr_cast(query->Copy()); - } - return move(result); - } + DUCKDB_API static unique_ptr Deserialize(Deserializer &deserializer); + + DUCKDB_API unique_ptr Copy() const override; }; } // namespace duckdb @@ -1543,36 +1630,6 @@ class SegmentTree { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/storage/block.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - -namespace duckdb { - -class Block : public FileBuffer { -public: - Block(Allocator &allocator, block_id_t id); - Block(FileBuffer &source, block_id_t id); - - block_id_t id; -}; - -struct BlockPointer { - block_id_t block_id; - uint32_t offset; -}; - -} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -1932,7 +1989,8 @@ class RowGroup : public SegmentBase { void UpdateColumn(Transaction &transaction, DataChunk &updates, Vector &row_ids, const vector &column_path); - void MergeStatistics(idx_t column_idx, BaseStatistics &other); + void MergeStatistics(idx_t column_idx, const BaseStatistics &other); + void MergeIntoStatistics(idx_t column_idx, BaseStatistics &other); unique_ptr GetStatistics(idx_t column_idx); void GetStorageInfo(idx_t row_group_index, vector> &result); @@ -2005,6 +2063,316 @@ class PersistentTableData { +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/storage/table_index.hpp +// +// +//===----------------------------------------------------------------------===// + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/storage/index.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/expression_executor.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + +namespace duckdb { +class Allocator; +class ExecutionContext; + +//! ExpressionExecutor is responsible for executing a set of expressions and storing the result in a data chunk +class ExpressionExecutor { +public: + DUCKDB_API ExpressionExecutor(Allocator &allocator); + DUCKDB_API explicit ExpressionExecutor(Allocator &allocator, const Expression *expression); + DUCKDB_API explicit ExpressionExecutor(Allocator &allocator, const Expression &expression); + DUCKDB_API explicit ExpressionExecutor(Allocator &allocator, const vector> &expressions); + + Allocator &allocator; + //! The expressions of the executor + vector expressions; + //! The data chunk of the current physical operator, used to resolve + //! column references and determines the output cardinality + DataChunk *chunk = nullptr; + +public: + //! Add an expression to the set of to-be-executed expressions of the executor + DUCKDB_API void AddExpression(const Expression &expr); + + //! Execute the set of expressions with the given input chunk and store the result in the output chunk + DUCKDB_API void Execute(DataChunk *input, DataChunk &result); + inline void Execute(DataChunk &input, DataChunk &result) { + Execute(&input, result); + } + inline void Execute(DataChunk &result) { + Execute(nullptr, result); + } + + //! Execute the ExpressionExecutor and put the result in the result vector; this should only be used for expression + //! executors with a single expression + DUCKDB_API void ExecuteExpression(DataChunk &input, Vector &result); + //! Execute the ExpressionExecutor and put the result in the result vector; this should only be used for expression + //! executors with a single expression + DUCKDB_API void ExecuteExpression(Vector &result); + //! Execute the ExpressionExecutor and generate a selection vector from all true values in the result; this should + //! only be used with a single boolean expression + DUCKDB_API idx_t SelectExpression(DataChunk &input, SelectionVector &sel); + + //! Execute the expression with index `expr_idx` and store the result in the result vector + DUCKDB_API void ExecuteExpression(idx_t expr_idx, Vector &result); + //! Evaluate a scalar expression and fold it into a single value + DUCKDB_API static Value EvaluateScalar(const Expression &expr, bool allow_unfoldable = false); + //! Try to evaluate a scalar expression and fold it into a single value, returns false if an exception is thrown + DUCKDB_API static bool TryEvaluateScalar(const Expression &expr, Value &result); + + //! Initialize the state of a given expression + static unique_ptr InitializeState(const Expression &expr, ExpressionExecutorState &state); + + inline void SetChunk(DataChunk *chunk) { + this->chunk = chunk; + } + inline void SetChunk(DataChunk &chunk) { + SetChunk(&chunk); + } + + DUCKDB_API vector> &GetStates(); + +protected: + void Initialize(const Expression &expr, ExpressionExecutorState &state); + + static unique_ptr InitializeState(const BoundReferenceExpression &expr, + ExpressionExecutorState &state); + static unique_ptr InitializeState(const BoundBetweenExpression &expr, + ExpressionExecutorState &state); + static unique_ptr InitializeState(const BoundCaseExpression &expr, ExpressionExecutorState &state); + static unique_ptr InitializeState(const BoundCastExpression &expr, ExpressionExecutorState &state); + static unique_ptr InitializeState(const BoundComparisonExpression &expr, + ExpressionExecutorState &state); + static unique_ptr InitializeState(const BoundConjunctionExpression &expr, + ExpressionExecutorState &state); + static unique_ptr InitializeState(const BoundConstantExpression &expr, + ExpressionExecutorState &state); + static unique_ptr InitializeState(const BoundFunctionExpression &expr, + ExpressionExecutorState &state); + static unique_ptr InitializeState(const BoundOperatorExpression &expr, + ExpressionExecutorState &state); + static unique_ptr InitializeState(const BoundParameterExpression &expr, + ExpressionExecutorState &state); + + void Execute(const Expression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + Vector &result); + + void Execute(const BoundBetweenExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + Vector &result); + void Execute(const BoundCaseExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + Vector &result); + void Execute(const BoundCastExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + Vector &result); + + void Execute(const BoundComparisonExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + Vector &result); + void Execute(const BoundConjunctionExpression &expr, ExpressionState *state, const SelectionVector *sel, + idx_t count, Vector &result); + void Execute(const BoundConstantExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + Vector &result); + void Execute(const BoundFunctionExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + Vector &result); + void Execute(const BoundOperatorExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + Vector &result); + void Execute(const BoundParameterExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + Vector &result); + void Execute(const BoundReferenceExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + Vector &result); + + //! Execute the (boolean-returning) expression and generate a selection vector with all entries that are "true" in + //! the result + idx_t Select(const Expression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + SelectionVector *true_sel, SelectionVector *false_sel); + idx_t DefaultSelect(const Expression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + SelectionVector *true_sel, SelectionVector *false_sel); + + idx_t Select(const BoundBetweenExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + SelectionVector *true_sel, SelectionVector *false_sel); + idx_t Select(const BoundComparisonExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, + SelectionVector *true_sel, SelectionVector *false_sel); + idx_t Select(const BoundConjunctionExpression &expr, ExpressionState *state, const SelectionVector *sel, + idx_t count, SelectionVector *true_sel, SelectionVector *false_sel); + + //! Verify that the output of a step in the ExpressionExecutor is correct + void Verify(const Expression &expr, Vector &result, idx_t count); + + void FillSwitch(Vector &vector, Vector &result, const SelectionVector &sel, sel_t count); + +private: + //! The states of the expression executor; this holds any intermediates and temporary states of expressions + vector> states; +}; +} // namespace duckdb + + + +namespace duckdb { + +class ClientContext; +class Transaction; + +struct IndexLock; + +//! The index is an abstract base class that serves as the basis for indexes +class Index { +public: + Index(IndexType type, const vector &column_ids, const vector> &unbound_expressions, + IndexConstraintType constraint_type); + virtual ~Index() = default; + + //! The type of the index + IndexType type; + //! Column identifiers to extract from the base table + vector column_ids; + //! unordered_set of column_ids used by the index + unordered_set column_id_set; + //! Unbound expressions used by the index + vector> unbound_expressions; + //! The physical types stored in the index + vector types; + //! The logical types of the expressions + vector logical_types; + //! constraint type + IndexConstraintType constraint_type; + +public: + //! Initialize a scan on the index with the given expression and column ids + //! to fetch from the base table when we only have one query predicate + virtual unique_ptr InitializeScanSinglePredicate(Transaction &transaction, Value value, + ExpressionType expressionType) = 0; + //! Initialize a scan on the index with the given expression and column ids + //! to fetch from the base table for two query predicates + virtual unique_ptr InitializeScanTwoPredicates(Transaction &transaction, Value low_value, + ExpressionType low_expression_type, Value high_value, + ExpressionType high_expression_type) = 0; + //! Perform a lookup on the index, fetching up to max_count result ids. Returns true if all row ids were fetched, + //! and false otherwise. + virtual bool Scan(Transaction &transaction, DataTable &table, IndexScanState &state, idx_t max_count, + vector &result_ids) = 0; + + //! Obtain a lock on the index + virtual void InitializeLock(IndexLock &state); + //! Called when data is appended to the index. The lock obtained from InitializeAppend must be held + virtual bool Append(IndexLock &state, DataChunk &entries, Vector &row_identifiers) = 0; + bool Append(DataChunk &entries, Vector &row_identifiers); + //! Verify that data can be appended to the index + virtual void VerifyAppend(DataChunk &chunk) = 0; + //! Verify that data can be appended to the index for foreign key constraint + virtual void VerifyAppendForeignKey(DataChunk &chunk, string *err_msg_ptr) = 0; + //! Verify that data can be delete from the index for foreign key constraint + virtual void VerifyDeleteForeignKey(DataChunk &chunk, string *err_msg_ptr) = 0; + + //! Called when data inside the index is Deleted + virtual void Delete(IndexLock &state, DataChunk &entries, Vector &row_identifiers) = 0; + void Delete(DataChunk &entries, Vector &row_identifiers); + + //! Insert data into the index. Does not lock the index. + virtual bool Insert(IndexLock &lock, DataChunk &input, Vector &row_identifiers) = 0; + + //! Returns true if the index is affected by updates on the specified column ids, and false otherwise + bool IndexIsUpdated(const vector &column_ids) const; + + //! Returns unique flag + bool IsUnique() { + return (constraint_type == IndexConstraintType::UNIQUE || constraint_type == IndexConstraintType::PRIMARY); + } + //! Returns primary flag + bool IsPrimary() { + return (constraint_type == IndexConstraintType::PRIMARY); + } + //! Returns foreign flag + bool IsForeign() { + return (constraint_type == IndexConstraintType::FOREIGN); + } + //! Serializes the index and returns the pair of block_id offset positions + virtual BlockPointer Serialize(duckdb::MetaBlockWriter &writer); + +protected: + void ExecuteExpressions(DataChunk &input, DataChunk &result); + + //! Lock used for updating the index + mutex lock; + +private: + //! Bound expressions used by the index + vector> bound_expressions; + //! Expression executor for the index expressions + ExpressionExecutor executor; + + unique_ptr BindExpression(unique_ptr expr); +}; + +} // namespace duckdb + +namespace duckdb { +class TableIndex { +public: + //! Scan the catalog set, invoking the callback method for every entry + template + void Scan(T &&callback) { + // lock the catalog set + lock_guard lock(indexes_lock); + for (auto &index : indexes) { + if (callback(*index)) { + break; + } + } + } + + void AddIndex(unique_ptr index); + + void RemoveIndex(Index *index); + + bool Empty(); + + idx_t Count(); + + Index *FindForeignKeyIndex(const vector &fk_keys, ForeignKeyType fk_type); + + //! Serialize all indexes owned by this table, returns a vector of block info of all indexes + vector SerializeIndexes(duckdb::MetaBlockWriter &writer); + +private: + //! Indexes associated with the current table + mutex indexes_lock; + vector> indexes; +}; +} // namespace duckdb + namespace duckdb { class CatalogEntry; @@ -2034,6 +2402,13 @@ struct BoundCreateTableInfo { unique_ptr data; //! CREATE TABLE from QUERY unique_ptr query; + //! Indexes created by this table + vector indexes; + + //! Serializes a BoundCreateTableInfo to a stand-alone binary blob + void Serialize(Serializer &serializer) const; + //! Deserializes a blob back into a BoundCreateTableInfo + static unique_ptr Deserialize(Deserializer &source, PlanDeserializationState &state); CreateTableInfo &Base() { D_ASSERT(base); @@ -2434,8 +2809,10 @@ LogicalType Catalog::GetType(ClientContext &context, const string &schema, const void Catalog::Alter(ClientContext &context, AlterInfo *info) { ModifyCatalog(); - auto lookup = LookupEntry(context, info->GetCatalogType(), info->schema, info->name); - D_ASSERT(lookup.Found()); // It must have thrown otherwise. + auto lookup = LookupEntry(context, info->GetCatalogType(), info->schema, info->name, info->if_exists); + if (!lookup.Found()) { + return; + } return lookup.schema->Alter(context, info); } @@ -2757,17 +3134,6 @@ CopyFunctionCatalogEntry::CopyFunctionCatalogEntry(Catalog *catalog, SchemaCatal -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/storage/index.hpp -// -// -//===----------------------------------------------------------------------===// - - - - @@ -2776,7 +3142,7 @@ CopyFunctionCatalogEntry::CopyFunctionCatalogEntry(Catalog *catalog, SchemaCatal //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/execution/expression_executor.hpp +// duckdb/storage/statistics/column_statistics.hpp // // //===----------------------------------------------------------------------===// @@ -2785,264 +3151,20 @@ CopyFunctionCatalogEntry::CopyFunctionCatalogEntry(Catalog *catalog, SchemaCatal - - - -namespace duckdb { -class ExecutionContext; -//! ExpressionExecutor is responsible for executing a set of expressions and storing the result in a data chunk -class ExpressionExecutor { -public: - DUCKDB_API ExpressionExecutor(); - DUCKDB_API explicit ExpressionExecutor(const Expression *expression); - DUCKDB_API explicit ExpressionExecutor(const Expression &expression); - DUCKDB_API explicit ExpressionExecutor(const vector> &expressions); - - //! Add an expression to the set of to-be-executed expressions of the executor - DUCKDB_API void AddExpression(const Expression &expr); - - //! Execute the set of expressions with the given input chunk and store the result in the output chunk - DUCKDB_API void Execute(DataChunk *input, DataChunk &result); - inline void Execute(DataChunk &input, DataChunk &result) { - Execute(&input, result); - } - inline void Execute(DataChunk &result) { - Execute(nullptr, result); - } - - //! Execute the ExpressionExecutor and put the result in the result vector; this should only be used for expression - //! executors with a single expression - DUCKDB_API void ExecuteExpression(DataChunk &input, Vector &result); - //! Execute the ExpressionExecutor and put the result in the result vector; this should only be used for expression - //! executors with a single expression - DUCKDB_API void ExecuteExpression(Vector &result); - //! Execute the ExpressionExecutor and generate a selection vector from all true values in the result; this should - //! only be used with a single boolean expression - DUCKDB_API idx_t SelectExpression(DataChunk &input, SelectionVector &sel); - - //! Execute the expression with index `expr_idx` and store the result in the result vector - DUCKDB_API void ExecuteExpression(idx_t expr_idx, Vector &result); - //! Evaluate a scalar expression and fold it into a single value - DUCKDB_API static Value EvaluateScalar(const Expression &expr); - //! Try to evaluate a scalar expression and fold it into a single value, returns false if an exception is thrown - DUCKDB_API static bool TryEvaluateScalar(const Expression &expr, Value &result); - - //! Initialize the state of a given expression - static unique_ptr InitializeState(const Expression &expr, ExpressionExecutorState &state); - - inline void SetChunk(DataChunk *chunk) { - this->chunk = chunk; - } - inline void SetChunk(DataChunk &chunk) { - SetChunk(&chunk); - } - - DUCKDB_API vector> &GetStates(); - - //! The expressions of the executor - vector expressions; - //! The data chunk of the current physical operator, used to resolve - //! column references and determines the output cardinality - DataChunk *chunk = nullptr; - -protected: - void Initialize(const Expression &expr, ExpressionExecutorState &state); - - static unique_ptr InitializeState(const BoundReferenceExpression &expr, - ExpressionExecutorState &state); - static unique_ptr InitializeState(const BoundBetweenExpression &expr, - ExpressionExecutorState &state); - static unique_ptr InitializeState(const BoundCaseExpression &expr, ExpressionExecutorState &state); - static unique_ptr InitializeState(const BoundCastExpression &expr, ExpressionExecutorState &state); - static unique_ptr InitializeState(const BoundComparisonExpression &expr, - ExpressionExecutorState &state); - static unique_ptr InitializeState(const BoundConjunctionExpression &expr, - ExpressionExecutorState &state); - static unique_ptr InitializeState(const BoundConstantExpression &expr, - ExpressionExecutorState &state); - static unique_ptr InitializeState(const BoundFunctionExpression &expr, - ExpressionExecutorState &state); - static unique_ptr InitializeState(const BoundOperatorExpression &expr, - ExpressionExecutorState &state); - static unique_ptr InitializeState(const BoundParameterExpression &expr, - ExpressionExecutorState &state); - - void Execute(const Expression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - Vector &result); - - void Execute(const BoundBetweenExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - Vector &result); - void Execute(const BoundCaseExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - Vector &result); - void Execute(const BoundCastExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - Vector &result); - - void Execute(const BoundComparisonExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - Vector &result); - void Execute(const BoundConjunctionExpression &expr, ExpressionState *state, const SelectionVector *sel, - idx_t count, Vector &result); - void Execute(const BoundConstantExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - Vector &result); - void Execute(const BoundFunctionExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - Vector &result); - void Execute(const BoundOperatorExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - Vector &result); - void Execute(const BoundParameterExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - Vector &result); - void Execute(const BoundReferenceExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - Vector &result); - - //! Execute the (boolean-returning) expression and generate a selection vector with all entries that are "true" in - //! the result - idx_t Select(const Expression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - SelectionVector *true_sel, SelectionVector *false_sel); - idx_t DefaultSelect(const Expression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - SelectionVector *true_sel, SelectionVector *false_sel); - - idx_t Select(const BoundBetweenExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - SelectionVector *true_sel, SelectionVector *false_sel); - idx_t Select(const BoundComparisonExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, - SelectionVector *true_sel, SelectionVector *false_sel); - idx_t Select(const BoundConjunctionExpression &expr, ExpressionState *state, const SelectionVector *sel, - idx_t count, SelectionVector *true_sel, SelectionVector *false_sel); - - //! Verify that the output of a step in the ExpressionExecutor is correct - void Verify(const Expression &expr, Vector &result, idx_t count); - - void FillSwitch(Vector &vector, Vector &result, const SelectionVector &sel, sel_t count); - -private: - //! The states of the expression executor; this holds any intermediates and temporary states of expressions - vector> states; -}; -} // namespace duckdb - - namespace duckdb { -class ClientContext; -class Transaction; - -struct IndexLock; - -enum IndexConstraintType : uint8_t { - NONE = 0, // index is an index don't built to any constraint - UNIQUE = 1, // index is an index built to enforce a UNIQUE constraint - PRIMARY = 2, // index is an index built to enforce a PRIMARY KEY constraint - FOREIGN = 3 // index is an index built to enforce a FOREIGN KEY constraint -}; - -//! The index is an abstract base class that serves as the basis for indexes -class Index { +class ColumnStatistics { public: - Index(IndexType type, const vector &column_ids, const vector> &unbound_expressions, - IndexConstraintType constraint_type); - virtual ~Index() = default; + explicit ColumnStatistics(unique_ptr stats_p); - //! The type of the index - IndexType type; - //! Column identifiers to extract from the base table - vector column_ids; - //! unordered_set of column_ids used by the index - unordered_set column_id_set; - //! Unbound expressions used by the index - vector> unbound_expressions; - //! The physical types stored in the index - vector types; - //! The logical types of the expressions - vector logical_types; - // ! constraint type - IndexConstraintType constraint_type; + unique_ptr stats; public: - //! Initialize a scan on the index with the given expression and column ids - //! to fetch from the base table when we only have one query predicate - virtual unique_ptr InitializeScanSinglePredicate(Transaction &transaction, Value value, - ExpressionType expressionType) = 0; - //! Initialize a scan on the index with the given expression and column ids - //! to fetch from the base table for two query predicates - virtual unique_ptr InitializeScanTwoPredicates(Transaction &transaction, Value low_value, - ExpressionType low_expression_type, Value high_value, - ExpressionType high_expression_type) = 0; - //! Perform a lookup on the index, fetching up to max_count result ids. Returns true if all row ids were fetched, - //! and false otherwise. - virtual bool Scan(Transaction &transaction, DataTable &table, IndexScanState &state, idx_t max_count, - vector &result_ids) = 0; - - //! Obtain a lock on the index - virtual void InitializeLock(IndexLock &state); - //! Called when data is appended to the index. The lock obtained from InitializeAppend must be held - virtual bool Append(IndexLock &state, DataChunk &entries, Vector &row_identifiers) = 0; - bool Append(DataChunk &entries, Vector &row_identifiers); - //! Verify that data can be appended to the index - virtual void VerifyAppend(DataChunk &chunk) = 0; - //! Verify that data can be appended to the index for foreign key constraint - virtual void VerifyAppendForeignKey(DataChunk &chunk, string *err_msg_ptr) = 0; - //! Verify that data can be delete from the index for foreign key constraint - virtual void VerifyDeleteForeignKey(DataChunk &chunk, string *err_msg_ptr) = 0; - - //! Called when data inside the index is Deleted - virtual void Delete(IndexLock &state, DataChunk &entries, Vector &row_identifiers) = 0; - void Delete(DataChunk &entries, Vector &row_identifiers); - - //! Insert data into the index. Does not lock the index. - virtual bool Insert(IndexLock &lock, DataChunk &input, Vector &row_identifiers) = 0; - - //! Returns true if the index is affected by updates on the specified column ids, and false otherwise - bool IndexIsUpdated(const vector &column_ids) const; - - //! Returns unique flag - bool IsUnique() { - return (constraint_type == IndexConstraintType::UNIQUE || constraint_type == IndexConstraintType::PRIMARY); - } - //! Returns primary flag - bool IsPrimary() { - return (constraint_type == IndexConstraintType::PRIMARY); - } - //! Returns foreign flag - bool IsForeign() { - return (constraint_type == IndexConstraintType::FOREIGN); - } - -protected: - void ExecuteExpressions(DataChunk &input, DataChunk &result); - - //! Lock used for updating the index - mutex lock; - -private: - //! Bound expressions used by the index - vector> bound_expressions; - //! Expression executor for the index expressions - ExpressionExecutor executor; - - unique_ptr BindExpression(unique_ptr expr); -}; - -} // namespace duckdb - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/storage/table_statistics.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { - -struct TableStatistics { - idx_t estimated_cardinality; + static shared_ptr CreateEmptyStats(const LogicalType &type); }; } // namespace duckdb - //===----------------------------------------------------------------------===// // DuckDB // @@ -3071,65 +3193,6 @@ struct TableStatistics { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/storage/block_manager.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - -namespace duckdb { -class ClientContext; -class DatabaseInstance; - -//! BlockManager is an abstract representation to manage blocks on DuckDB. When writing or reading blocks, the -//! BlockManager creates and accesses blocks. The concrete types implements how blocks are stored. -class BlockManager { -public: - virtual ~BlockManager() = default; - - virtual void StartCheckpoint() = 0; - //! Creates a new block inside the block manager - virtual unique_ptr CreateBlock(block_id_t block_id) = 0; - //! Return the next free block id - virtual block_id_t GetFreeBlockId() = 0; - //! Returns whether or not a specified block is the root block - virtual bool IsRootBlock(block_id_t root) = 0; - //! Mark a block as "modified"; modified blocks are added to the free list after a checkpoint (i.e. their data is - //! assumed to be rewritten) - virtual void MarkBlockAsModified(block_id_t block_id) = 0; - //! Increase the reference count of a block. The block should hold at least one reference before this method is - //! called. - virtual void IncreaseBlockReferenceCount(block_id_t block_id) = 0; - //! Get the first meta block id - virtual block_id_t GetMetaBlock() = 0; - //! Read the content of the block from disk - virtual void Read(Block &block) = 0; - //! Writes the block to disk - virtual void Write(FileBuffer &block, block_id_t block_id) = 0; - //! Writes the block to disk - void Write(Block &block) { - Write(block, block.id); - } - //! Write the header; should be the final step of a checkpoint - virtual void WriteHeader(DatabaseHeader header) = 0; - - //! Returns the number of total blocks - virtual idx_t TotalBlocks() = 0; - //! Returns the number of free blocks - virtual idx_t FreeBlocks() = 0; - - static BlockManager &GetBlockManager(ClientContext &context); - static BlockManager &GetBlockManager(DatabaseInstance &db); -}; -} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -3176,8 +3239,17 @@ class BlockHandle { return readers; } + inline bool IsSwizzled() const { + return !unswizzled; + } + + inline void SetSwizzling(const char *unswizzler) { + unswizzled = unswizzler; + } + private: - static unique_ptr Load(shared_ptr &handle); + static BufferHandle Load(shared_ptr &handle, unique_ptr buffer = nullptr); + unique_ptr UnloadAndTakeBlock(); void Unload(); bool CanUnload(); @@ -3197,6 +3269,8 @@ class BlockHandle { const bool can_destroy; //! The memory usage of the block idx_t memory_usage; + //! Does the block contain any memory pointers? + const char *unswizzled; }; } // namespace duckdb @@ -3223,6 +3297,7 @@ class DatabaseInstance; class ManagedBuffer : public FileBuffer { public: ManagedBuffer(DatabaseInstance &db, idx_t size, bool can_destroy, block_id_t id); + ManagedBuffer(DatabaseInstance &db, FileBuffer &source, bool can_destroy, block_id_t id); DatabaseInstance &db; //! Whether or not the managed buffer can be freely destroyed when unpinned. @@ -3238,6 +3313,7 @@ class ManagedBuffer : public FileBuffer { } // namespace duckdb + namespace duckdb { class DatabaseInstance; class TemporaryDirectoryHandle; @@ -3267,12 +3343,12 @@ class BufferManager { //! Allocate an in-memory buffer with a single pin. //! The allocated memory is released when the buffer handle is destroyed. - DUCKDB_API unique_ptr Allocate(idx_t block_size); + DUCKDB_API BufferHandle Allocate(idx_t block_size); //! Reallocate an in-memory buffer that is pinned. void ReAllocate(shared_ptr &handle, idx_t block_size); - unique_ptr Pin(shared_ptr &handle); + BufferHandle Pin(shared_ptr &handle); void Unpin(shared_ptr &handle); void UnregisterBlock(block_id_t block_id, bool can_destroy); @@ -3297,10 +3373,14 @@ class BufferManager { void SetTemporaryDirectory(string new_dir); + DUCKDB_API Allocator &GetBufferAllocator(); + private: //! Evict blocks until the currently used memory + extra_memory fit, returns false if this was not possible //! (i.e. not enough blocks could be evicted) - bool EvictBlocks(idx_t extra_memory, idx_t memory_limit); + //! If the "buffer" argument is specified AND the system can find a buffer to re-use for the given allocation size + //! "buffer" will be made to point to the re-usable memory. Note that this is not guaranteed. + bool EvictBlocks(idx_t extra_memory, idx_t memory_limit, unique_ptr *buffer = nullptr); //! Garbage collect eviction queue void PurgeQueue(); @@ -3308,7 +3388,7 @@ class BufferManager { //! Write a temporary buffer to disk void WriteTemporaryBuffer(ManagedBuffer &buffer); //! Read a temporary buffer from disk - unique_ptr ReadTemporaryBuffer(block_id_t id); + unique_ptr ReadTemporaryBuffer(block_id_t id, unique_ptr buffer = nullptr); //! Get the path of the temporary buffer string GetTemporaryPath(block_id_t id); @@ -3320,6 +3400,11 @@ class BufferManager { string InMemoryWarning(); + static data_ptr_t BufferAllocatorAllocate(PrivateAllocatorData *private_data, idx_t size); + static void BufferAllocatorFree(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t size); + static data_ptr_t BufferAllocatorRealloc(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t old_size, + idx_t size); + private: //! The database instance DatabaseInstance &db; @@ -3343,6 +3428,8 @@ class BufferManager { unique_ptr queue; //! The temporary id used for managed buffers atomic temporary_id; + //! Allocator associated with the buffer manager, that passes all allocations through this buffer manager + Allocator buffer_allocator; }; } // namespace duckdb @@ -3458,8 +3545,8 @@ typedef void (*compression_skip_t)(ColumnSegment &segment, ColumnScanState &stat // Append (optional) //===--------------------------------------------------------------------===// typedef unique_ptr (*compression_init_segment_t)(ColumnSegment &segment, block_id_t block_id); -typedef idx_t (*compression_append_t)(ColumnSegment &segment, SegmentStatistics &stats, VectorData &data, idx_t offset, - idx_t count); +typedef idx_t (*compression_append_t)(ColumnSegment &segment, SegmentStatistics &stats, UnifiedVectorFormat &data, + idx_t offset, idx_t count); typedef idx_t (*compression_finalize_append_t)(ColumnSegment &segment, SegmentStatistics &stats); typedef void (*compression_revert_append_t)(ColumnSegment &segment, idx_t start_row); @@ -3598,7 +3685,7 @@ class ColumnSegment : public SegmentBase { //! Initialize an append of this segment. Appends are only supported on transient segments. void InitializeAppend(ColumnAppendState &state); //! Appends a (part of) vector to the segment, returns the amount of entries successfully appended - idx_t Append(ColumnAppendState &state, VectorData &data, idx_t offset, idx_t count); + idx_t Append(ColumnAppendState &state, UnifiedVectorFormat &data, idx_t offset, idx_t count); //! Finalize the segment for appending - no more appends can follow on this segment //! The segment should be compacted as much as possible //! Returns the number of bytes occupied within the segment @@ -3655,11 +3742,10 @@ class ColumnSegment : public SegmentBase { - //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/storage/statistics/column_statistics.hpp +// duckdb/storage/table_statistics.hpp // // //===----------------------------------------------------------------------===// @@ -3668,24 +3754,17 @@ class ColumnSegment : public SegmentBase { -namespace duckdb { - -class ColumnStatistics { -public: - explicit ColumnStatistics(unique_ptr stats_p); - unique_ptr stats; +namespace duckdb { -public: - static shared_ptr CreateEmptyStats(const LogicalType &type); +struct TableStatistics { + idx_t estimated_cardinality; }; } // namespace duckdb - - namespace duckdb { class ClientContext; class ColumnDefinition; @@ -3697,57 +3776,6 @@ class Transaction; class WriteAheadLog; class TableDataWriter; -class TableIndexList { -public: - //! Scan the catalog set, invoking the callback method for every entry - template - void Scan(T &&callback) { - // lock the catalog set - lock_guard lock(indexes_lock); - for (auto &index : indexes) { - if (callback(*index)) { - break; - } - } - } - - void AddIndex(unique_ptr index) { - D_ASSERT(index); - lock_guard lock(indexes_lock); - indexes.push_back(move(index)); - } - - void RemoveIndex(Index *index) { - D_ASSERT(index); - lock_guard lock(indexes_lock); - - for (idx_t index_idx = 0; index_idx < indexes.size(); index_idx++) { - auto &index_entry = indexes[index_idx]; - if (index_entry.get() == index) { - indexes.erase(indexes.begin() + index_idx); - break; - } - } - } - - bool Empty() { - lock_guard lock(indexes_lock); - return indexes.empty(); - } - - idx_t Count() { - lock_guard lock(indexes_lock); - return indexes.size(); - } - - Index *FindForeignKeyIndex(const vector &fk_keys, ForeignKeyType fk_type); - -private: - //! Indexes associated with the current table - mutex indexes_lock; - vector> indexes; -}; - struct DataTableInfo { DataTableInfo(DatabaseInstance &db, string schema, string table) : db(db), cardinality(0), schema(move(schema)), table(move(table)) { @@ -3763,7 +3791,7 @@ struct DataTableInfo { // name of the table string table; - TableIndexList indexes; + TableIndex indexes; bool IsTemporary() { return schema == TEMP_SCHEMA; @@ -3791,6 +3819,8 @@ class DataTable { //! Constructs a DataTable as a delta on an existing data table but with one column changed type DataTable(ClientContext &context, DataTable &parent, idx_t changed_idx, const LogicalType &target_type, vector bound_columns, Expression &cast_expr); + //! Constructs a DataTable as a delta on an existing data table but with one column added new constraint + DataTable(ClientContext &context, DataTable &parent, unique_ptr constraint); shared_ptr info; @@ -3876,9 +3906,10 @@ class DataTable { } unique_ptr GetStatistics(ClientContext &context, column_t column_id); + void SetStatistics(column_t column_id, const std::function &set_fun); //! Checkpoint the table to the specified table data writer - BlockPointer Checkpoint(TableDataWriter &writer); + void Checkpoint(TableDataWriter &writer); void CommitDropTable(); void CommitDropColumn(idx_t index); @@ -3888,8 +3919,11 @@ class DataTable { void AppendRowGroup(idx_t start_row); vector> GetStorageInfo(); + static bool IsForeignKeyIndex(const vector &fk_keys, Index &index, ForeignKeyType fk_type); private: + //! Verify the new added constraints against current persistent&local data + void VerifyNewConstraint(ClientContext &context, DataTable &parent, const Constraint *constraint); //! Verify constraints with a chunk from the Append containing all columns of the table void VerifyAppendConstraints(TableCatalogEntry &table, ClientContext &context, DataChunk &chunk); //! Verify constraints with a chunk from the Update containing only the specified column_ids @@ -3925,48 +3959,317 @@ class DataTable { }; } // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/index/art/art.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/index/art/art_key.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/bit_operations.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + + +#include +#include // strlen() on Solaris +#include namespace duckdb { -IndexCatalogEntry::IndexCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, CreateIndexInfo *info) - : StandardEntry(CatalogType::INDEX_ENTRY, schema, catalog, info->index_name), index(nullptr), sql(info->sql) { -} +#define BSWAP16(x) ((uint16_t)((((uint16_t)(x)&0xff00) >> 8) | (((uint16_t)(x)&0x00ff) << 8))) -IndexCatalogEntry::~IndexCatalogEntry() { - // remove the associated index from the info - if (!info || !index) { - return; +#define BSWAP32(x) \ + ((uint32_t)((((uint32_t)(x)&0xff000000) >> 24) | (((uint32_t)(x)&0x00ff0000) >> 8) | \ + (((uint32_t)(x)&0x0000ff00) << 8) | (((uint32_t)(x)&0x000000ff) << 24))) + +#define BSWAP64(x) \ + ((uint64_t)((((uint64_t)(x)&0xff00000000000000ull) >> 56) | (((uint64_t)(x)&0x00ff000000000000ull) >> 40) | \ + (((uint64_t)(x)&0x0000ff0000000000ull) >> 24) | (((uint64_t)(x)&0x000000ff00000000ull) >> 8) | \ + (((uint64_t)(x)&0x00000000ff000000ull) << 8) | (((uint64_t)(x)&0x0000000000ff0000ull) << 24) | \ + (((uint64_t)(x)&0x000000000000ff00ull) << 40) | (((uint64_t)(x)&0x00000000000000ffull) << 56))) + +struct Radix { +public: + static inline bool IsLittleEndian() { + int n = 1; + if (*(char *)&n == 1) { + return true; + } else { + return false; + } } - info->indexes.RemoveIndex(index); -} -string IndexCatalogEntry::ToSQL() { - if (sql.empty()) { - throw InternalException("Cannot convert INDEX to SQL because it was not created with a SQL statement"); + template + static inline void EncodeData(data_ptr_t dataptr, T value) { + throw NotImplementedException("Cannot create data from this type"); } - if (sql[sql.size() - 1] != ';') { - sql += ";"; + + static inline void EncodeStringDataPrefix(data_ptr_t dataptr, string_t value, idx_t prefix_len) { + auto len = value.GetSize(); + memcpy(dataptr, value.GetDataUnsafe(), MinValue(len, prefix_len)); + if (len < prefix_len) { + memset(dataptr + len, '\0', prefix_len - len); + } } - return sql; + + static inline uint8_t FlipSign(uint8_t key_byte) { + return key_byte ^ 128; + } + + static inline uint32_t EncodeFloat(float x) { + uint64_t buff; + + //! zero + if (x == 0) { + buff = 0; + buff |= (1u << 31); + return buff; + } + // nan + if (Value::IsNan(x)) { + return UINT_MAX; + } + //! infinity + if (x > FLT_MAX) { + return UINT_MAX - 1; + } + //! -infinity + if (x < -FLT_MAX) { + return 0; + } + buff = Load((const_data_ptr_t)&x); + if ((buff & (1u << 31)) == 0) { //! +0 and positive numbers + buff |= (1u << 31); + } else { //! negative numbers + buff = ~buff; //! complement 1 + } + + return buff; + } + + static inline uint64_t EncodeDouble(double x) { + uint64_t buff; + //! zero + if (x == 0) { + buff = 0; + buff += (1ull << 63); + return buff; + } + // nan + if (Value::IsNan(x)) { + return ULLONG_MAX; + } + //! infinity + if (x > DBL_MAX) { + return ULLONG_MAX - 1; + } + //! -infinity + if (x < -DBL_MAX) { + return 0; + } + buff = Load((const_data_ptr_t)&x); + if (buff < (1ull << 63)) { //! +0 and positive numbers + buff += (1ull << 63); + } else { //! negative numbers + buff = ~buff; //! complement 1 + } + return buff; + } +}; + +template <> +inline void Radix::EncodeData(data_ptr_t dataptr, bool value) { + Store(value ? 1 : 0, dataptr); +} + +template <> +inline void Radix::EncodeData(data_ptr_t dataptr, int8_t value) { + Store(value, dataptr); + dataptr[0] = FlipSign(dataptr[0]); +} + +template <> +inline void Radix::EncodeData(data_ptr_t dataptr, int16_t value) { + Store(BSWAP16(value), dataptr); + dataptr[0] = FlipSign(dataptr[0]); +} + +template <> +inline void Radix::EncodeData(data_ptr_t dataptr, int32_t value) { + Store(BSWAP32(value), dataptr); + dataptr[0] = FlipSign(dataptr[0]); +} + +template <> +inline void Radix::EncodeData(data_ptr_t dataptr, int64_t value) { + Store(BSWAP64(value), dataptr); + dataptr[0] = FlipSign(dataptr[0]); +} + +template <> +inline void Radix::EncodeData(data_ptr_t dataptr, uint8_t value) { + Store(value, dataptr); +} + +template <> +inline void Radix::EncodeData(data_ptr_t dataptr, uint16_t value) { + Store(BSWAP16(value), dataptr); +} + +template <> +inline void Radix::EncodeData(data_ptr_t dataptr, uint32_t value) { + Store(BSWAP32(value), dataptr); +} + +template <> +inline void Radix::EncodeData(data_ptr_t dataptr, uint64_t value) { + Store(BSWAP64(value), dataptr); +} + +template <> +inline void Radix::EncodeData(data_ptr_t dataptr, hugeint_t value) { + EncodeData(dataptr, value.upper); + EncodeData(dataptr + sizeof(value.upper), value.lower); +} + +template <> +inline void Radix::EncodeData(data_ptr_t dataptr, float value) { + uint32_t converted_value = EncodeFloat(value); + Store(BSWAP32(converted_value), dataptr); +} + +template <> +inline void Radix::EncodeData(data_ptr_t dataptr, double value) { + uint64_t converted_value = EncodeDouble(value); + Store(BSWAP64(converted_value), dataptr); +} + +template <> +inline void Radix::EncodeData(data_ptr_t dataptr, interval_t value) { + EncodeData(dataptr, value.months); + dataptr += sizeof(value.months); + EncodeData(dataptr, value.days); + dataptr += sizeof(value.days); + EncodeData(dataptr, value.micros); } } // namespace duckdb + namespace duckdb { -PragmaFunctionCatalogEntry::PragmaFunctionCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, - CreatePragmaFunctionInfo *info) - : StandardEntry(CatalogType::PRAGMA_FUNCTION_ENTRY, schema, catalog, info->name), functions(move(info->functions)) { -} +class Key { +public: + Key(unique_ptr data, idx_t len); + + explicit Key(idx_t len); + + idx_t len; + unique_ptr data; + +public: + template + static inline unique_ptr CreateKey(T element) { + auto data = Key::CreateData(element); + return make_unique(move(data), sizeof(element)); + } + + template + static inline unique_ptr CreateKey(const Value &element) { + return CreateKey(element.GetValueUnsafe()); + } + +public: + data_t &operator[](std::size_t i) { + return data[i]; + } + const data_t &operator[](std::size_t i) const { + return data[i]; + } + bool operator>(const Key &k) const; + bool operator<(const Key &k) const; + bool operator>=(const Key &k) const; + bool operator==(const Key &k) const; + +private: + template + static inline unique_ptr CreateData(T value) { + auto data = unique_ptr(new data_t[sizeof(value)]); + Radix::EncodeData(data.get(), value); + return data; + } +}; + +template <> +unique_ptr Key::CreateKey(string_t value); +template <> +unique_ptr Key::CreateKey(const char *value); } // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/catalog/catalog_entry/macro_catalog_entry.hpp +// duckdb/execution/index/art/leaf.hpp +// +// +//===----------------------------------------------------------------------===// + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/index/art/node.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/storage/meta_block_reader.hpp // // //===----------------------------------------------------------------------===// @@ -3977,26 +4280,38 @@ PragmaFunctionCatalogEntry::PragmaFunctionCatalogEntry(Catalog *catalog, SchemaC + namespace duckdb { +class BlockHandle; +class BufferHandle; +class DatabaseInstance; -//! A macro function in the catalog -class TableMacroCatalogEntry : public MacroCatalogEntry { +//! This struct is responsible for reading meta data from disk +class MetaBlockReader : public Deserializer { public: - TableMacroCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, CreateMacroInfo *info); + MetaBlockReader(DatabaseInstance &db, block_id_t block); + ~MetaBlockReader() override; + + DatabaseInstance &db; + shared_ptr block; + BufferHandle handle; + idx_t offset; + block_id_t next_block; public: - //! Serialize the meta information of the ScalarMacroCatalogEntry - void Serialize(Serializer &serializer) override; - //! Deserializes to a CreateMacroInfo - static unique_ptr Deserialize(Deserializer &source); -}; + //! Read content of size read_size into the buffer + void ReadData(data_ptr_t buffer, idx_t read_size) override; +private: + void ReadNewBlock(block_id_t id); +}; } // namespace duckdb + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/field_writer.hpp +// duckdb/execution/index/art/prefix.hpp // // //===----------------------------------------------------------------------===// @@ -4005,275 +4320,640 @@ class TableMacroCatalogEntry : public MacroCatalogEntry { -#include namespace duckdb { -class BufferedSerializer; +class Prefix { +public: + Prefix(); + // Prefix created from key starting on `depth`. + Prefix(Key &key, uint32_t depth, uint32_t size); + + // Returns the Prefix's size + uint32_t Size() const; + + // Subscript operator + uint8_t &operator[](idx_t idx); + + // Assign operator + Prefix &operator=(const Prefix &src); + + // Move operator + Prefix &operator=(Prefix &&other) noexcept; + + // Concatenate Prefix with a key and another prefix + // Used when deleting a Node. + // other.prefix + key + this->Prefix + void Concatenate(uint8_t key, Prefix &other); + // Reduces the prefix in n elements, and returns what would be the first one as a key + uint8_t Reduce(uint32_t n); + // Serializes Prefix + void Serialize(duckdb::MetaBlockWriter &writer); + // Deserializes Prefix + void Deserialize(duckdb::MetaBlockReader &reader); + + // Compare the key with the prefix of the node, return the position where it mismatches + uint32_t KeyMismatchPosition(Key &key, uint64_t depth); + +private: + unique_ptr prefix; + uint32_t size; +}; + +} // namespace duckdb + + +namespace duckdb { +enum class NodeType : uint8_t { N4 = 0, N16 = 1, N48 = 2, N256 = 3, NLeaf = 4 }; + +class ART; +class Node; +class SwizzleablePointer; + +struct InternalType { + explicit InternalType(Node *n); + void Set(uint8_t *key_p, uint16_t key_size_p, SwizzleablePointer *children_p, uint16_t children_size_p); + uint8_t *key; + uint16_t key_size; + SwizzleablePointer *children; + uint16_t children_size; +}; -class FieldWriter { +class Node { public: - FieldWriter(Serializer &serializer); - ~FieldWriter(); + static const uint8_t EMPTY_MARKER = 48; public: - template - void WriteField(const T &element) { - static_assert(std::is_trivially_destructible(), "WriteField object must be trivially destructible"); + explicit Node(NodeType type); - AddField(); - WriteData((const_data_ptr_t)&element, sizeof(T)); + virtual ~Node() { } + //! number of non-null children + uint16_t count; + //! node type + NodeType type; + //! compressed path (prefix) + Prefix prefix; - //! Write a string with a length prefix - void WriteString(const string &val) { - WriteStringLen((const_data_ptr_t)val.c_str(), val.size()); - } - void WriteStringLen(const_data_ptr_t val, idx_t len) { - AddField(); - Write((uint32_t)len); - if (len > 0) { - WriteData(val, len); - } + //! Get the position of a child corresponding exactly to the specific byte, returns DConstants::INVALID_INDEX if not + //! exists + virtual idx_t GetChildPos(uint8_t k) { + return DConstants::INVALID_INDEX; } - void WriteBlob(const_data_ptr_t val, idx_t len) { - AddField(); - if (len > 0) { - WriteData(val, len); - } + //! Get the position of the first child that is greater or equal to the specific byte, or DConstants::INVALID_INDEX + //! if there are no children matching the criteria + virtual idx_t GetChildGreaterEqual(uint8_t k, bool &equal) { + throw InternalException("Unimplemented GetChildGreaterEqual for ARTNode"); } + //! Get the position of the biggest element in node + virtual idx_t GetMin(); - template > - void WriteList(const CONTAINER_TYPE &elements) { - AddField(); - Write(elements.size()); - for (auto &element : elements) { - Write(element); - } - } + //! Serialize this Node + BlockPointer Serialize(ART &art, duckdb::MetaBlockWriter &writer); - template - void WriteSerializable(const T &element) { - AddField(); - element.Serialize(*buffer); - } + static Node *Deserialize(ART &art, idx_t block_id, idx_t offset); - template - void WriteSerializableList(const vector> &elements) { - AddField(); - Write(elements.size()); - for (idx_t i = 0; i < elements.size(); i++) { - elements[i]->Serialize(*buffer); - } + //! Get the next position in the node, or DConstants::INVALID_INDEX if there is no next position. if pos == + //! DConstants::INVALID_INDEX, then the first valid position in the node will be returned. + virtual idx_t GetNextPos(idx_t pos) { + return DConstants::INVALID_INDEX; } + //! Get the child at the specified position in the node. pos should be between [0, count). Throws an assertion if + //! the element is not found. + virtual Node *GetChild(ART &art, idx_t pos); - template - void WriteRegularSerializableList(const vector &elements) { - AddField(); - Write(elements.size()); - for (idx_t i = 0; i < elements.size(); i++) { - elements[i].Serialize(*buffer); - } - } + //! Replaces the pointer + virtual void ReplaceChildPointer(idx_t pos, Node *node); - template - void WriteOptional(const unique_ptr &element) { - AddField(); - Write(element ? true : false); - if (element) { - element->Serialize(*buffer); - } - } + //! Insert leaf into inner node + static void InsertLeaf(Node *&node, uint8_t key, Node *new_node); + //! Erase entry from node + static void Erase(Node *&node, idx_t pos, ART &art); - // Called after all fields have been written. Should always be called. - void Finalize(); +private: + //! Serialize Internal Nodes + BlockPointer SerializeInternal(ART &art, duckdb::MetaBlockWriter &writer, InternalType &internal_type); + //! Deserialize Internal Nodes + void DeserializeInternal(duckdb::MetaBlockReader &reader); +}; - Serializer &GetSerializer() { - return *buffer; - } +} // namespace duckdb -private: - void AddField() { - field_count++; - } - template - void Write(const T &element) { - WriteData((const_data_ptr_t)&element, sizeof(T)); + +namespace duckdb { + +class Leaf : public Node { +public: + Leaf(Key &value, unsigned depth, row_t row_id); + + Leaf(unique_ptr row_ids, idx_t num_elements, Prefix &prefix); + idx_t capacity; + + row_t GetRowId(idx_t index) { + return row_ids[index]; } - void WriteData(const_data_ptr_t buffer, idx_t write_size); +public: + void Insert(row_t row_id); + void Remove(row_t row_id); + + BlockPointer Serialize(duckdb::MetaBlockWriter &writer); + + static Leaf *Deserialize(duckdb::MetaBlockReader &reader); private: - Serializer &serializer; - unique_ptr buffer; - idx_t field_count; - bool finalized; + unique_ptr row_ids; }; -template <> -void FieldWriter::Write(const string &val); +} // namespace duckdb + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/index/art/node4.hpp +// +// +//===----------------------------------------------------------------------===// + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/index/art/swizzleable_pointer.hpp +// +// +//===----------------------------------------------------------------------===// + + + +namespace duckdb { + +class SwizzleablePointer { +public: + ~SwizzleablePointer(); + explicit SwizzleablePointer(duckdb::MetaBlockReader &reader); + SwizzleablePointer() : pointer(0) {}; -class FieldDeserializer : public Deserializer { + uint64_t pointer; + + //! Transforms from Node* to uint64_t + SwizzleablePointer &operator=(const Node *ptr); + friend bool operator!=(const SwizzleablePointer &s_ptr, const uint64_t &ptr); + + //! Extracts block info from swizzled pointer + BlockPointer GetSwizzledBlockInfo(); + //! Checks if pointer is swizzled + bool IsSwizzled(); + //! Deletes the underlying object (if necessary) and set the pointer to null_ptr + void Reset(); + //! Unswizzle the pointer (if possible) + Node *Unswizzle(ART &art); + + BlockPointer Serialize(ART &art, duckdb::MetaBlockWriter &writer); +}; +} // namespace duckdb + + +namespace duckdb { + +class Node4 : public Node { public: - FieldDeserializer(Deserializer &root); + Node4(); + uint8_t key[4]; + // Pointers to the child nodes + SwizzleablePointer children[4]; public: - void ReadData(data_ptr_t buffer, idx_t read_size) override; + //! Get position of a byte, returns -1 if not exists + idx_t GetChildPos(uint8_t k) override; + //! Get the position of the first child that is greater or equal to the specific byte, or DConstants::INVALID_INDEX + //! if there are no children matching the criteria + idx_t GetChildGreaterEqual(uint8_t k, bool &equal) override; + //! Get the next position in the node, or DConstants::INVALID_INDEX if there is no next position + idx_t GetNextPos(idx_t pos) override; + //! Get Node4 Child + Node *GetChild(ART &art, idx_t pos) override; + //! Replace child pointer + void ReplaceChildPointer(idx_t pos, Node *node) override; - void SetRemainingData(idx_t remaining_data); - idx_t RemainingData(); + idx_t GetMin() override; -private: - Deserializer &root; - idx_t remaining_data; + //! Insert Leaf to the Node4 + static void Insert(Node *&node, uint8_t key_byte, Node *new_child); + //! Remove Leaf from Node4 + static void Erase(Node *&node, int pos, ART &art); }; +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/index/art/node16.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { -class FieldReader { +class Node16 : public Node { public: - FieldReader(Deserializer &source); - ~FieldReader(); + explicit Node16(); + uint8_t key[16]; + SwizzleablePointer children[16]; public: - template - T ReadRequired() { - if (field_count >= max_field_count) { - // field is not there, throw an exception - throw SerializationException("Attempting to read a required field, but field is missing"); - } - // field is there, read the actual value - AddField(); - return source.Read(); - } + //! Get position of a byte, returns -1 if not exists + idx_t GetChildPos(uint8_t k) override; + //! Get the position of the first child that is greater or equal to the specific byte, or DConstants::INVALID_INDEX + //! if there are no children matching the criteria + idx_t GetChildGreaterEqual(uint8_t k, bool &equal) override; + //! Get the next position in the node, or DConstants::INVALID_INDEX if there is no next position + idx_t GetNextPos(idx_t pos) override; + //! Get Node16 Child + Node *GetChild(ART &art, idx_t pos) override; - template - T ReadField(T default_value) { - if (field_count >= max_field_count) { - // field is not there, read the default value - return default_value; - } - // field is there, read the actual value - AddField(); - return source.Read(); - } + //! Replace child pointer + void ReplaceChildPointer(idx_t pos, Node *node) override; - template - vector ReadRequiredList() { - if (field_count >= max_field_count) { - // field is not there, throw an exception - throw SerializationException("Attempting to read a required field, but field is missing"); - } - AddField(); - auto result_count = source.Read(); - vector result; - for (idx_t i = 0; i < result_count; i++) { - result.push_back(source.Read()); - } - return result; - } + idx_t GetMin() override; - template - unique_ptr ReadOptional(unique_ptr default_value) { - if (field_count >= max_field_count) { - // field is not there, read the default value - return default_value; - } - // field is there, read the actual value - AddField(); - return source.template ReadOptional(); - } + //! Insert node into Node16 + static void Insert(Node *&node, uint8_t key_byte, Node *child); + //! Shrink to node 4 + static void Erase(Node *&node, int pos, ART &art); +}; +} // namespace duckdb - template > - RETURN_TYPE ReadSerializable(RETURN_TYPE default_value) { - if (field_count >= max_field_count) { - // field is not there, read the default value - return default_value; - } - // field is there, read the actual value - AddField(); - return T::Deserialize(source); - } +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/index/art/node48.hpp +// +// +//===----------------------------------------------------------------------===// - template , typename... ARGS> - RETURN_TYPE ReadSerializable(RETURN_TYPE default_value, ARGS &&...args) { - if (field_count >= max_field_count) { - // field is not there, read the default value - return default_value; - } - // field is there, read the actual value - AddField(); - return T::Deserialize(source, std::forward(args)...); - } - template > - RETURN_TYPE ReadRequiredSerializable() { - if (field_count >= max_field_count) { - // field is not there, read the default value - throw SerializationException("Attempting to read mandatory field, but field is missing"); - } - // field is there, read the actual value - AddField(); - return T::Deserialize(source); - } - template , typename... ARGS> - RETURN_TYPE ReadRequiredSerializable(ARGS &&...args) { - if (field_count >= max_field_count) { - // field is not there, read the default value - throw SerializationException("Attempting to read mandatory field, but field is missing"); - } - // field is there, read the actual value - AddField(); - return T::Deserialize(source, std::forward(args)...); - } - template > - vector ReadRequiredSerializableList() { - if (field_count >= max_field_count) { - // field is not there, read the default value - throw SerializationException("Attempting to read mandatory field, but field is missing"); - } - // field is there, read the actual value - AddField(); - auto result_count = source.Read(); - vector result; - for (idx_t i = 0; i < result_count; i++) { - result.push_back(T::Deserialize(source)); - } - return result; +namespace duckdb { + +class Node48 : public Node { +public: + explicit Node48(); + uint8_t child_index[256]; + + SwizzleablePointer children[48]; + +public: + //! Get position of a byte, returns -1 if not exists + idx_t GetChildPos(uint8_t k) override; + //! Get the position of the first child that is greater or equal to the specific byte, or DConstants::INVALID_INDEX + //! if there are no children matching the criteria + idx_t GetChildGreaterEqual(uint8_t k, bool &equal) override; + //! Get the next position in the node, or DConstants::INVALID_INDEX if there is no next position + idx_t GetNextPos(idx_t pos) override; + //! Get Node48 Child + Node *GetChild(ART &art, idx_t pos) override; + + idx_t GetMin() override; + //! Replace child pointer + void ReplaceChildPointer(idx_t pos, Node *node) override; + + //! Insert node in Node48 + static void Insert(Node *&node, uint8_t key_byte, Node *child); + + //! Shrink to node 16 + static void Erase(Node *&node, int pos, ART &art); +}; +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/index/art/node256.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { + +class Node256 : public Node { +public: + explicit Node256(); + + SwizzleablePointer children[256]; + +public: + //! Get position of a specific byte, returns DConstants::INVALID_INDEX if not exists + idx_t GetChildPos(uint8_t k) override; + //! Get the position of the first child that is greater or equal to the specific byte, or DConstants::INVALID_INDEX + //! if there are no children matching the criteria + idx_t GetChildGreaterEqual(uint8_t k, bool &equal) override; + //! Get the next position in the node, or DConstants::INVALID_INDEX if there is no next position + idx_t GetNextPos(idx_t pos) override; + //! Get Node256 Child + Node *GetChild(ART &art, idx_t pos) override; + + //! Replace child pointer + void ReplaceChildPointer(idx_t pos, Node *node) override; + idx_t GetMin() override; + + //! Insert node From Node256 + static void Insert(Node *&node, uint8_t key_byte, Node *child); + + //! Shrink to node 48 + static void Erase(Node *&node, int pos, ART &art); +}; +} // namespace duckdb + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/index/art/iterator.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +struct IteratorEntry { + IteratorEntry() { } - void ReadBlob(data_ptr_t result, idx_t read_size) { - if (field_count >= max_field_count) { - // field is not there, throw an exception - throw SerializationException("Attempting to read a required field, but field is missing"); - } - // field is there, read the actual value - AddField(); - source.ReadData(result, read_size); + IteratorEntry(Node *node, idx_t pos) : node(node), pos(pos) { } - //! Called after all fields have been read. Should always be called. - void Finalize(); + Node *node = nullptr; + idx_t pos = 0; +}; - Deserializer &GetSource() { - return source; - } +//! Keeps track of the current key in the iterator +class IteratorCurrentKey { +public: + //! Push Byte + void Push(uint8_t key); + //! Pops n elements + void Pop(idx_t n); + //! Subscript operator + uint8_t &operator[](idx_t idx); + bool operator>(const Key &k) const; + bool operator>=(const Key &k) const; + bool operator==(const Key &k) const; + +private: + //! The current key position + idx_t cur_key_pos = 0; + //! The current key of the Leaf Node + vector key; +}; + +class Iterator { +public: + //! Current Key + IteratorCurrentKey cur_key; + //! Pointer to the ART tree we are iterating + ART *art = nullptr; + + //! Scan the tree + bool Scan(Key *bound, idx_t max_count, vector &result_ids, bool is_inclusive); + //! Finds minimum value of the tree + void FindMinimum(Node &node); + //! Goes to lower bound + bool LowerBound(Node *node, Key &key, bool inclusive); private: - void AddField() { - field_count++; + //! Stack of iterator entries + stack nodes; + //! Last visited leaf + Leaf *last_leaf = nullptr; + //! Go to the next node + bool Next(); + //! Push part of the key to cur_key + void PushKey(Node *node, uint16_t pos); +}; +} // namespace duckdb + + +namespace duckdb { + +struct ARTIndexScanState : public IndexScanState { + ARTIndexScanState() : checked(false), result_index(0) { } + Value values[2]; + ExpressionType expressions[2]; + bool checked; + vector result_ids; + Iterator iterator; + //! Stores the current leaf + Leaf *cur_leaf = nullptr; + //! Offset to leaf + idx_t result_index = 0; +}; + +enum VerifyExistenceType : uint8_t { + APPEND = 0, // for purpose to append into table + APPEND_FK = 1, // for purpose to append into table has foreign key + DELETE_FK = 2 // for purpose to delete from table related to foreign key +}; + +class ART : public Index { +public: + ART(const vector &column_ids, const vector> &unbound_expressions, + IndexConstraintType constraint_type, DatabaseInstance &db, idx_t block_id = DConstants::INVALID_INDEX, + idx_t block_offset = DConstants::INVALID_INDEX); + ~ART() override; + + //! Root of the tree + Node *tree; + + DatabaseInstance &db; + + //! Initialize a scan on the index with the given expression and column ids + //! to fetch from the base table for a single predicate + unique_ptr InitializeScanSinglePredicate(Transaction &transaction, Value value, + ExpressionType expression_type) override; + + //! Initialize a scan on the index with the given expression and column ids + //! to fetch from the base table for two predicates + unique_ptr InitializeScanTwoPredicates(Transaction &transaction, Value low_value, + ExpressionType low_expression_type, Value high_value, + ExpressionType high_expression_type) override; + + //! Perform a lookup on the index + bool Scan(Transaction &transaction, DataTable &table, IndexScanState &state, idx_t max_count, + vector &result_ids) override; + //! Append entries to the index + bool Append(IndexLock &lock, DataChunk &entries, Vector &row_identifiers) override; + //! Verify that data can be appended to the index + void VerifyAppend(DataChunk &chunk) override; + //! Verify that data can be appended to the index for foreign key constraint + void VerifyAppendForeignKey(DataChunk &chunk, string *err_msg_ptr) override; + //! Verify that data can be delete from the index for foreign key constraint + void VerifyDeleteForeignKey(DataChunk &chunk, string *err_msg_ptr) override; + //! Delete entries in the index + void Delete(IndexLock &lock, DataChunk &entries, Vector &row_identifiers) override; + //! Insert data into the index. + bool Insert(IndexLock &lock, DataChunk &data, Vector &row_ids) override; + + bool SearchEqual(ARTIndexScanState *state, idx_t max_count, vector &result_ids); + //! Search Equal used for Joins that do not need to fetch data + void SearchEqualJoinNoFetch(Value &equal_value, idx_t &result_size); + //! Serialized the ART + BlockPointer Serialize(duckdb::MetaBlockWriter &writer) override; + private: - FieldDeserializer source; - idx_t field_count; - idx_t max_field_count; - idx_t total_size; - bool finalized; + //! Insert a row id into a leaf node + bool InsertToLeaf(Leaf &leaf, row_t row_id); + //! Insert the leaf value into the tree + bool Insert(Node *&node, unique_ptr key, unsigned depth, row_t row_id); + + //! Erase element from leaf (if leaf has more than one value) or eliminate the leaf itself + void Erase(Node *&node, Key &key, unsigned depth, row_t row_id); + + //! Find the node with a matching key, optimistic version + Node *Lookup(Node *node, Key &key, unsigned depth); + + bool SearchGreater(ARTIndexScanState *state, bool inclusive, idx_t max_count, vector &result_ids); + bool SearchLess(ARTIndexScanState *state, bool inclusive, idx_t max_count, vector &result_ids); + bool SearchCloseRange(ARTIndexScanState *state, bool left_inclusive, bool right_inclusive, idx_t max_count, + vector &result_ids); + + void GenerateKeys(DataChunk &input, vector> &keys); + + void VerifyExistence(DataChunk &chunk, VerifyExistenceType verify_type, string *err_msg_ptr = nullptr); +}; + +} // namespace duckdb + + + +namespace duckdb { + +IndexCatalogEntry::IndexCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, CreateIndexInfo *info) + : StandardEntry(CatalogType::INDEX_ENTRY, schema, catalog, info->index_name), index(nullptr), sql(info->sql) { +} + +IndexCatalogEntry::~IndexCatalogEntry() { + // remove the associated index from the info + if (!info || !index) { + return; + } + info->indexes.RemoveIndex(index); +} + +string IndexCatalogEntry::ToSQL() { + if (sql.empty()) { + throw InternalException("Cannot convert INDEX to SQL because it was not created with a SQL statement"); + } + if (sql[sql.size() - 1] != ';') { + sql += ";"; + } + return sql; +} + +void IndexCatalogEntry::Serialize(duckdb::MetaBlockWriter &serializer) { + // Here we serialize the index metadata in the following order: + // schema name, table name, index name, sql, index type, index constraint type, expression list. + // column_ids, unbound_expression + FieldWriter writer(serializer); + writer.WriteString(info->schema); + writer.WriteString(info->table); + writer.WriteString(name); + writer.WriteString(sql); + writer.WriteField(index->type); + writer.WriteField(index->constraint_type); + writer.WriteSerializableList(expressions); + writer.WriteSerializableList(parsed_expressions); + writer.WriteList(index->column_ids); + writer.Finalize(); +} + +unique_ptr IndexCatalogEntry::Deserialize(Deserializer &source, ClientContext &context) { + // Here we deserialize the index metadata in the following order: + // root block, root offset, schema name, table name, index name, sql, index type, index constraint type, expression + // list. + + auto create_index_info = make_unique(); + + FieldReader reader(source); + + create_index_info->schema = reader.ReadRequired(); + create_index_info->table = make_unique(); + create_index_info->table->schema_name = create_index_info->schema; + create_index_info->table->table_name = reader.ReadRequired(); + create_index_info->index_name = reader.ReadRequired(); + create_index_info->sql = reader.ReadRequired(); + create_index_info->index_type = IndexType(reader.ReadRequired()); + create_index_info->constraint_type = IndexConstraintType(reader.ReadRequired()); + create_index_info->expressions = reader.ReadRequiredSerializableList(); + create_index_info->parsed_expressions = reader.ReadRequiredSerializableList(); + + create_index_info->column_ids = reader.ReadRequiredList(); + reader.Finalize(); + return create_index_info; +} + +} // namespace duckdb + + + +namespace duckdb { + +PragmaFunctionCatalogEntry::PragmaFunctionCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, + CreatePragmaFunctionInfo *info) + : StandardEntry(CatalogType::PRAGMA_FUNCTION_ENTRY, schema, catalog, info->name), functions(move(info->functions)) { +} + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/catalog/catalog_entry/macro_catalog_entry.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + +namespace duckdb { + +//! A macro function in the catalog +class TableMacroCatalogEntry : public MacroCatalogEntry { +public: + TableMacroCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, CreateMacroInfo *info); + +public: + //! Serialize the meta information of the ScalarMacroCatalogEntry + void Serialize(Serializer &serializer) override; + //! Deserializes to a CreateMacroInfo + static unique_ptr Deserialize(Deserializer &source, ClientContext &context); }; } // namespace duckdb + //===----------------------------------------------------------------------===// // DuckDB // @@ -4304,6 +4984,8 @@ class ScalarMacroFunction : public MacroFunction { public: unique_ptr Copy() override; + + string ToSQL(const string &schema, const string &name) override; }; } // namespace duckdb @@ -4317,7 +4999,7 @@ class ScalarMacroFunction : public MacroFunction { //===----------------------------------------------------------------------===// -//! The SelectStatement of the view + @@ -4338,6 +5020,8 @@ class TableMacroFunction : public MacroFunction { public: unique_ptr Copy() override; + + string ToSQL(const string &schema, const string &name) override; }; } // namespace duckdb @@ -4376,7 +5060,7 @@ void ScalarMacroCatalogEntry::Serialize(Serializer &main_serializer) { writer.Finalize(); } -unique_ptr ScalarMacroCatalogEntry::Deserialize(Deserializer &main_source) { +unique_ptr ScalarMacroCatalogEntry::Deserialize(Deserializer &main_source, ClientContext &context) { auto info = make_unique(CatalogType::MACRO_ENTRY); FieldReader reader(main_source); info->schema = reader.ReadRequired(); @@ -4419,7 +5103,7 @@ void TableMacroCatalogEntry::Serialize(Serializer &main_serializer) { writer.Finalize(); } -unique_ptr TableMacroCatalogEntry::Deserialize(Deserializer &main_source) { +unique_ptr TableMacroCatalogEntry::Deserialize(Deserializer &main_source, ClientContext &context) { auto info = make_unique(CatalogType::TABLE_MACRO_ENTRY); FieldReader reader(main_source); info->schema = reader.ReadRequired(); @@ -4456,6 +5140,7 @@ unique_ptr TableMacroCatalogEntry::Deserialize(Deserializer &ma + //===----------------------------------------------------------------------===// // DuckDB // @@ -4499,6 +5184,7 @@ class DefaultFunctionGenerator : public DefaultGenerator { } // namespace duckdb + //===----------------------------------------------------------------------===// // DuckDB // @@ -4528,64 +5214,20 @@ class DefaultViewGenerator : public DefaultGenerator { } // namespace duckdb - - - - - - - - - - - - - - - - //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/planner/constraints/bound_foreign_key_constraint.hpp +// duckdb/common/algorithm.hpp // // //===----------------------------------------------------------------------===// +#include -namespace duckdb { - -class BoundForeignKeyConstraint : public BoundConstraint { -public: - BoundForeignKeyConstraint(ForeignKeyInfo info_p, unordered_set pk_key_set_p, - unordered_set fk_key_set_p) - : BoundConstraint(ConstraintType::FOREIGN_KEY), info(move(info_p)), pk_key_set(move(pk_key_set_p)), - fk_key_set(move(fk_key_set_p)) { -#ifdef DEBUG - D_ASSERT(info.pk_keys.size() == pk_key_set.size()); - for (auto &key : info.pk_keys) { - D_ASSERT(pk_key_set.find(key) != pk_key_set.end()); - } - D_ASSERT(info.fk_keys.size() == fk_key_set.size()); - for (auto &key : info.fk_keys) { - D_ASSERT(fk_key_set.find(key) != fk_key_set.end()); - } -#endif - } - - ForeignKeyInfo info; - //! The same keys but stored as an unordered set - unordered_set pk_key_set; - //! The same keys but stored as an unordered set - unordered_set fk_key_set; -}; - -} // namespace duckdb - //===----------------------------------------------------------------------===// // DuckDB // @@ -4627,17 +5269,59 @@ class ForeignKeyConstraint : public Constraint { + + + + + + + + + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/algorithm.hpp +// duckdb/planner/constraints/bound_foreign_key_constraint.hpp // // //===----------------------------------------------------------------------===// -#include + + + +namespace duckdb { + +class BoundForeignKeyConstraint : public BoundConstraint { +public: + BoundForeignKeyConstraint(ForeignKeyInfo info_p, unordered_set pk_key_set_p, + unordered_set fk_key_set_p) + : BoundConstraint(ConstraintType::FOREIGN_KEY), info(move(info_p)), pk_key_set(move(pk_key_set_p)), + fk_key_set(move(fk_key_set_p)) { +#ifdef DEBUG + D_ASSERT(info.pk_keys.size() == pk_key_set.size()); + for (auto &key : info.pk_keys) { + D_ASSERT(pk_key_set.find(key) != pk_key_set.end()); + } + D_ASSERT(info.fk_keys.size() == fk_key_set.size()); + for (auto &key : info.fk_keys) { + D_ASSERT(fk_key_set.find(key) != fk_key_set.end()); + } +#endif + } + + ForeignKeyInfo info; + //! The same keys but stored as an unordered set + unordered_set pk_key_set; + //! The same keys but stored as an unordered set + unordered_set fk_key_set; +}; + +} // namespace duckdb + + + #include @@ -4656,7 +5340,7 @@ void FindForeignKeyInformation(CatalogEntry *entry, AlterForeignKeyType alter_fk } auto &fk = (ForeignKeyConstraint &)*cond; if (fk.info.type == ForeignKeyType::FK_TYPE_FOREIGN_KEY_TABLE) { - fk_arrays.push_back(make_unique(fk.info.schema, fk.info.table, entry->name, + fk_arrays.push_back(make_unique(fk.info.schema, fk.info.table, false, entry->name, fk.pk_columns, fk.fk_columns, fk.info.pk_keys, fk.info.fk_keys, alter_fk_type)); } else if (fk.info.type == ForeignKeyType::FK_TYPE_PRIMARY_KEY_TABLE && @@ -4824,15 +5508,15 @@ CatalogEntry *SchemaCatalogEntry::AddFunction(ClientContext &context, CreateFunc case CatalogType::SCALAR_FUNCTION_ENTRY: { auto scalar_info = (CreateScalarFunctionInfo *)info; auto &scalars = *(ScalarFunctionCatalogEntry *)entry; - for (const auto &scalar : scalars.functions) { - scalar_info->functions.emplace_back(scalar); + for (const auto &scalar : scalars.functions.functions) { + scalar_info->functions.AddFunction(scalar); } break; } case CatalogType::AGGREGATE_FUNCTION_ENTRY: { auto agg_info = (CreateAggregateFunctionInfo *)info; auto &aggs = *(AggregateFunctionCatalogEntry *)entry; - for (const auto &agg : aggs.functions) { + for (const auto &agg : aggs.functions.functions) { agg_info->functions.AddFunction(agg); } break; @@ -5022,6 +5706,9 @@ string SequenceCatalogEntry::ToSQL() { + + + //===----------------------------------------------------------------------===// // DuckDB // @@ -5136,6 +5823,76 @@ class UniqueConstraint : public Constraint { + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/parsed_expression_iterator.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +#include + +namespace duckdb { + +class ParsedExpressionIterator { +public: + static void EnumerateChildren(const ParsedExpression &expression, + const std::function &callback); + static void EnumerateChildren(ParsedExpression &expr, const std::function &callback); + static void EnumerateChildren(ParsedExpression &expr, + const std::function &child)> &callback); + + static void EnumerateTableRefChildren(TableRef &ref, + const std::function &child)> &callback); + static void EnumerateQueryNodeChildren(QueryNode &node, + const std::function &child)> &callback); + + static void EnumerateQueryNodeModifiers(QueryNode &node, + const std::function &child)> &callback); +}; + +} // namespace duckdb + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/constraints/bound_check_constraint.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + +namespace duckdb { + +//! The CheckConstraint contains an expression that must evaluate to TRUE for +//! every row in a table +class BoundCheckConstraint : public BoundConstraint { +public: + BoundCheckConstraint() : BoundConstraint(ConstraintType::CHECK) { + } + + //! The expression + unique_ptr expression; + //! The columns used by the CHECK constraint + unordered_set bound_columns; +}; + +} // namespace duckdb + + //===----------------------------------------------------------------------===// // DuckDB // @@ -5199,10 +5956,11 @@ class BoundUniqueConstraint : public BoundConstraint { } // namespace duckdb + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/planner/constraints/bound_check_constraint.hpp +// duckdb/planner/expression_binder/alter_binder.hpp // // //===----------------------------------------------------------------------===// @@ -5212,20 +5970,63 @@ class BoundUniqueConstraint : public BoundConstraint { +namespace duckdb { +class TableCatalogEntry; + +//! The ALTER binder is responsible for binding an expression within alter statements +class AlterBinder : public ExpressionBinder { +public: + AlterBinder(Binder &binder, ClientContext &context, TableCatalogEntry &table, vector &bound_columns, + LogicalType target_type); + + TableCatalogEntry &table; + vector &bound_columns; + +protected: + BindResult BindExpression(unique_ptr *expr_ptr, idx_t depth, + bool root_expression = false) override; + + BindResult BindColumn(ColumnRefExpression &expr); + + string UnsupportedAggregateMessage() override; +}; + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/filter/null_filter.hpp +// +// +//===----------------------------------------------------------------------===// + + + + namespace duckdb { -//! The CheckConstraint contains an expression that must evaluate to TRUE for -//! every row in a table -class BoundCheckConstraint : public BoundConstraint { +class IsNullFilter : public TableFilter { public: - BoundCheckConstraint() : BoundConstraint(ConstraintType::CHECK) { - } + IsNullFilter(); - //! The expression - unique_ptr expression; - //! The columns used by the CHECK constraint - unordered_set bound_columns; +public: + FilterPropagateResult CheckStatistics(BaseStatistics &stats) override; + string ToString(const string &column_name) override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(FieldReader &source); +}; + +class IsNotNullFilter : public TableFilter { +public: + IsNotNullFilter(); + +public: + FilterPropagateResult CheckStatistics(BaseStatistics &stats) override; + string ToString(const string &column_name) override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(FieldReader &source); }; } // namespace duckdb @@ -5476,771 +6277,13 @@ class StorageManager { } // namespace duckdb +#include -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/index/art/art.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - - +namespace duckdb { - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/index/art/art_key.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/bit_operations.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - - - -#include -#include // strlen() on Solaris -#include - -namespace duckdb { - -#define BSWAP16(x) ((uint16_t)((((uint16_t)(x)&0xff00) >> 8) | (((uint16_t)(x)&0x00ff) << 8))) - -#define BSWAP32(x) \ - ((uint32_t)((((uint32_t)(x)&0xff000000) >> 24) | (((uint32_t)(x)&0x00ff0000) >> 8) | \ - (((uint32_t)(x)&0x0000ff00) << 8) | (((uint32_t)(x)&0x000000ff) << 24))) - -#define BSWAP64(x) \ - ((uint64_t)((((uint64_t)(x)&0xff00000000000000ull) >> 56) | (((uint64_t)(x)&0x00ff000000000000ull) >> 40) | \ - (((uint64_t)(x)&0x0000ff0000000000ull) >> 24) | (((uint64_t)(x)&0x000000ff00000000ull) >> 8) | \ - (((uint64_t)(x)&0x00000000ff000000ull) << 8) | (((uint64_t)(x)&0x0000000000ff0000ull) << 24) | \ - (((uint64_t)(x)&0x000000000000ff00ull) << 40) | (((uint64_t)(x)&0x00000000000000ffull) << 56))) - -struct Radix { -public: - static inline bool IsLittleEndian() { - int n = 1; - if (*(char *)&n == 1) { - return true; - } else { - return false; - } - } - - template - static inline void EncodeData(data_ptr_t dataptr, T value, bool is_little_endian) { - throw NotImplementedException("Cannot create data from this type"); - } - - static inline void EncodeStringDataPrefix(data_ptr_t dataptr, string_t value, idx_t prefix_len) { - auto len = value.GetSize(); - memcpy(dataptr, value.GetDataUnsafe(), MinValue(len, prefix_len)); - if (len < prefix_len) { - memset(dataptr + len, '\0', prefix_len - len); - } - } - - static inline uint8_t FlipSign(uint8_t key_byte) { - return key_byte ^ 128; - } - - static inline uint32_t EncodeFloat(float x) { - uint64_t buff; - - //! zero - if (x == 0) { - buff = 0; - buff |= (1u << 31); - return buff; - } - // nan - if (Value::IsNan(x)) { - return UINT_MAX; - } - //! infinity - if (x > FLT_MAX) { - return UINT_MAX - 1; - } - //! -infinity - if (x < -FLT_MAX) { - return 0; - } - buff = Load((const_data_ptr_t)&x); - if ((buff & (1u << 31)) == 0) { //! +0 and positive numbers - buff |= (1u << 31); - } else { //! negative numbers - buff = ~buff; //! complement 1 - } - - return buff; - } - - static inline uint64_t EncodeDouble(double x) { - uint64_t buff; - //! zero - if (x == 0) { - buff = 0; - buff += (1ull << 63); - return buff; - } - // nan - if (Value::IsNan(x)) { - return ULLONG_MAX; - } - //! infinity - if (x > DBL_MAX) { - return ULLONG_MAX - 1; - } - //! -infinity - if (x < -DBL_MAX) { - return 0; - } - buff = Load((const_data_ptr_t)&x); - if (buff < (1ull << 63)) { //! +0 and positive numbers - buff += (1ull << 63); - } else { //! negative numbers - buff = ~buff; //! complement 1 - } - return buff; - } -}; - -template <> -inline void Radix::EncodeData(data_ptr_t dataptr, bool value, bool is_little_endian) { - Store(value ? 1 : 0, dataptr); -} - -template <> -inline void Radix::EncodeData(data_ptr_t dataptr, int8_t value, bool is_little_endian) { - Store(value, dataptr); - dataptr[0] = FlipSign(dataptr[0]); -} - -template <> -inline void Radix::EncodeData(data_ptr_t dataptr, int16_t value, bool is_little_endian) { - Store(is_little_endian ? BSWAP16(value) : value, dataptr); - dataptr[0] = FlipSign(dataptr[0]); -} - -template <> -inline void Radix::EncodeData(data_ptr_t dataptr, int32_t value, bool is_little_endian) { - Store(is_little_endian ? BSWAP32(value) : value, dataptr); - dataptr[0] = FlipSign(dataptr[0]); -} - -template <> -inline void Radix::EncodeData(data_ptr_t dataptr, int64_t value, bool is_little_endian) { - Store(is_little_endian ? BSWAP64(value) : value, dataptr); - dataptr[0] = FlipSign(dataptr[0]); -} - -template <> -inline void Radix::EncodeData(data_ptr_t dataptr, uint8_t value, bool is_little_endian) { - Store(value, dataptr); -} - -template <> -inline void Radix::EncodeData(data_ptr_t dataptr, uint16_t value, bool is_little_endian) { - Store(is_little_endian ? BSWAP16(value) : value, dataptr); -} - -template <> -inline void Radix::EncodeData(data_ptr_t dataptr, uint32_t value, bool is_little_endian) { - Store(is_little_endian ? BSWAP32(value) : value, dataptr); -} - -template <> -inline void Radix::EncodeData(data_ptr_t dataptr, uint64_t value, bool is_little_endian) { - Store(is_little_endian ? BSWAP64(value) : value, dataptr); -} - -template <> -inline void Radix::EncodeData(data_ptr_t dataptr, hugeint_t value, bool is_little_endian) { - EncodeData(dataptr, value.upper, is_little_endian); - EncodeData(dataptr + sizeof(value.upper), value.lower, is_little_endian); -} - -template <> -inline void Radix::EncodeData(data_ptr_t dataptr, float value, bool is_little_endian) { - uint32_t converted_value = EncodeFloat(value); - Store(is_little_endian ? BSWAP32(converted_value) : converted_value, dataptr); -} - -template <> -inline void Radix::EncodeData(data_ptr_t dataptr, double value, bool is_little_endian) { - uint64_t converted_value = EncodeDouble(value); - Store(is_little_endian ? BSWAP64(converted_value) : converted_value, dataptr); -} - -template <> -inline void Radix::EncodeData(data_ptr_t dataptr, interval_t value, bool is_little_endian) { - EncodeData(dataptr, value.months, is_little_endian); - dataptr += sizeof(value.months); - EncodeData(dataptr, value.days, is_little_endian); - dataptr += sizeof(value.days); - EncodeData(dataptr, value.micros, is_little_endian); -} - -} // namespace duckdb - - - - -namespace duckdb { - -class Key { -public: - Key(unique_ptr data, idx_t len); - - idx_t len; - unique_ptr data; - -public: - template - static inline unique_ptr CreateKey(T element, bool is_little_endian) { - auto data = Key::CreateData(element, is_little_endian); - return make_unique(move(data), sizeof(element)); - } - - template - static inline unique_ptr CreateKey(const Value &element, bool is_little_endian) { - return CreateKey(element.GetValueUnsafe(), is_little_endian); - } - -public: - data_t &operator[](std::size_t i) { - return data[i]; - } - const data_t &operator[](std::size_t i) const { - return data[i]; - } - bool operator>(const Key &k) const; - bool operator<(const Key &k) const; - bool operator>=(const Key &k) const; - bool operator==(const Key &k) const; - -private: - template - static inline unique_ptr CreateData(T value, bool is_little_endian) { - auto data = unique_ptr(new data_t[sizeof(value)]); - Radix::EncodeData(data.get(), value, is_little_endian); - return data; - } -}; - -template <> -unique_ptr Key::CreateKey(string_t value, bool is_little_endian); -template <> -unique_ptr Key::CreateKey(const char *value, bool is_little_endian); - -} // namespace duckdb - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/index/art/leaf.hpp -// -// -//===----------------------------------------------------------------------===// - - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/index/art/node.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { -enum class NodeType : uint8_t { N4 = 0, N16 = 1, N48 = 2, N256 = 3, NLeaf = 4 }; - -class ART; - -class Node { -public: - static const uint8_t EMPTY_MARKER = 48; - -public: - Node(ART &art, NodeType type, size_t compressed_prefix_size); - virtual ~Node() { - } - - //! length of the compressed path (prefix) - uint32_t prefix_length; - //! number of non-null children - uint16_t count; - //! node type - NodeType type; - //! compressed path (prefix) - unique_ptr prefix; - -public: - //! Get the position of a child corresponding exactly to the specific byte, returns DConstants::INVALID_INDEX if not - //! exists - virtual idx_t GetChildPos(uint8_t k) { - return DConstants::INVALID_INDEX; - } - //! Get the position of the first child that is greater or equal to the specific byte, or DConstants::INVALID_INDEX - //! if there are no children matching the criteria - virtual idx_t GetChildGreaterEqual(uint8_t k, bool &equal) { - throw InternalException("Unimplemented GetChildGreaterEqual for ARTNode"); - } - //! Get the position of the biggest element in node - virtual idx_t GetMin(); - //! Get the next position in the node, or DConstants::INVALID_INDEX if there is no next position. if pos == - //! DConstants::INVALID_INDEX, then the first valid position in the node will be returned. - virtual idx_t GetNextPos(idx_t pos) { - return DConstants::INVALID_INDEX; - } - //! Get the child at the specified position in the node. pos should be between [0, count). Throws an assertion if - //! the element is not found. - virtual unique_ptr *GetChild(idx_t pos); - - //! Compare the key with the prefix of the node, return the number matching bytes - static uint32_t PrefixMismatch(ART &art, Node *node, Key &key, uint64_t depth); - //! Insert leaf into inner node - static void InsertLeaf(ART &art, unique_ptr &node, uint8_t key, unique_ptr &new_node); - //! Erase entry from node - static void Erase(ART &art, unique_ptr &node, idx_t pos); - -protected: - //! Copies the prefix from the source to the destination node - static void CopyPrefix(ART &art, Node *src, Node *dst); -}; - -} // namespace duckdb - - -namespace duckdb { - -class Leaf : public Node { -public: - Leaf(ART &art, unique_ptr value, row_t row_id); - - unique_ptr value; - idx_t capacity; - idx_t num_elements; - - row_t GetRowId(idx_t index) { - return row_ids[index]; - } - -public: - void Insert(row_t row_id); - void Remove(row_t row_id); - -private: - unique_ptr row_ids; -}; - -} // namespace duckdb - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/index/art/node4.hpp -// -// -//===----------------------------------------------------------------------===// - - - - -namespace duckdb { - -class Node4 : public Node { -public: - Node4(ART &art, size_t compression_length); - - uint8_t key[4]; - unique_ptr child[4]; - -public: - //! Get position of a byte, returns -1 if not exists - idx_t GetChildPos(uint8_t k) override; - //! Get the position of the first child that is greater or equal to the specific byte, or DConstants::INVALID_INDEX - //! if there are no children matching the criteria - idx_t GetChildGreaterEqual(uint8_t k, bool &equal) override; - //! Get the next position in the node, or DConstants::INVALID_INDEX if there is no next position - idx_t GetNextPos(idx_t pos) override; - //! Get Node4 Child - unique_ptr *GetChild(idx_t pos) override; - - idx_t GetMin() override; - - //! Insert Leaf to the Node4 - static void Insert(ART &art, unique_ptr &node, uint8_t key_byte, unique_ptr &child); - //! Remove Leaf from Node4 - static void Erase(ART &art, unique_ptr &node, int pos); -}; -} // namespace duckdb - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/index/art/node16.hpp -// -// -//===----------------------------------------------------------------------===// - - - - -namespace duckdb { - -class Node16 : public Node { -public: - Node16(ART &art, size_t compression_lengthh); - - uint8_t key[16]; - unique_ptr child[16]; - -public: - //! Get position of a byte, returns -1 if not exists - idx_t GetChildPos(uint8_t k) override; - //! Get the position of the first child that is greater or equal to the specific byte, or DConstants::INVALID_INDEX - //! if there are no children matching the criteria - idx_t GetChildGreaterEqual(uint8_t k, bool &equal) override; - //! Get the next position in the node, or DConstants::INVALID_INDEX if there is no next position - idx_t GetNextPos(idx_t pos) override; - //! Get Node16 Child - unique_ptr *GetChild(idx_t pos) override; - - idx_t GetMin() override; - - //! Insert node into Node16 - static void Insert(ART &art, unique_ptr &node, uint8_t key_byte, unique_ptr &child); - //! Shrink to node 4 - static void Erase(ART &art, unique_ptr &node, int pos); -}; -} // namespace duckdb - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/index/art/node48.hpp -// -// -//===----------------------------------------------------------------------===// - - - - -namespace duckdb { - -class Node48 : public Node { -public: - Node48(ART &art, size_t compression_length); - - uint8_t child_index[256]; - unique_ptr child[48]; - -public: - //! Get position of a byte, returns -1 if not exists - idx_t GetChildPos(uint8_t k) override; - //! Get the position of the first child that is greater or equal to the specific byte, or DConstants::INVALID_INDEX - //! if there are no children matching the criteria - idx_t GetChildGreaterEqual(uint8_t k, bool &equal) override; - //! Get the next position in the node, or DConstants::INVALID_INDEX if there is no next position - idx_t GetNextPos(idx_t pos) override; - //! Get Node48 Child - unique_ptr *GetChild(idx_t pos) override; - - idx_t GetMin() override; - - //! Insert node in Node48 - static void Insert(ART &art, unique_ptr &node, uint8_t key_byte, unique_ptr &child); - - //! Shrink to node 16 - static void Erase(ART &art, unique_ptr &node, int pos); -}; -} // namespace duckdb - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/index/art/node256.hpp -// -// -//===----------------------------------------------------------------------===// - - - - -namespace duckdb { - -class Node256 : public Node { -public: - Node256(ART &art, size_t compression_length); - - unique_ptr child[256]; - -public: - //! Get position of a specific byte, returns DConstants::INVALID_INDEX if not exists - idx_t GetChildPos(uint8_t k) override; - //! Get the position of the first child that is greater or equal to the specific byte, or DConstants::INVALID_INDEX - //! if there are no children matching the criteria - idx_t GetChildGreaterEqual(uint8_t k, bool &equal) override; - //! Get the next position in the node, or DConstants::INVALID_INDEX if there is no next position - idx_t GetNextPos(idx_t pos) override; - //! Get Node256 Child - unique_ptr *GetChild(idx_t pos) override; - - idx_t GetMin() override; - - //! Insert node From Node256 - static void Insert(ART &art, unique_ptr &node, uint8_t key_byte, unique_ptr &child); - - //! Shrink to node 48 - static void Erase(ART &art, unique_ptr &node, int pos); -}; -} // namespace duckdb - - -namespace duckdb { -struct IteratorEntry { - IteratorEntry() { - } - IteratorEntry(Node *node, idx_t pos) : node(node), pos(pos) { - } - - Node *node = nullptr; - idx_t pos = 0; -}; - -struct Iterator { - //! The current Leaf Node, valid if depth>0 - Leaf *node = nullptr; - //! The current depth - int32_t depth = 0; - //! Stack, the size is determined at runtime - vector stack; - - bool start = false; - - void SetEntry(idx_t depth, IteratorEntry entry); -}; - -struct ARTIndexScanState : public IndexScanState { - ARTIndexScanState() : checked(false), result_index(0) { - } - - Value values[2]; - ExpressionType expressions[2]; - bool checked; - vector result_ids; - Iterator iterator; - //! Stores the current leaf - Leaf *cur_leaf = nullptr; - //! Offset to leaf - idx_t result_index = 0; -}; - -enum VerifyExistenceType : uint8_t { - APPEND = 0, // for purpose to append into table - APPEND_FK = 1, // for purpose to append into table has foreign key - DELETE_FK = 2 // for purpose to delete from table related to foreign key -}; - -class ART : public Index { -public: - ART(const vector &column_ids, const vector> &unbound_expressions, - IndexConstraintType constraint_type); - ~ART() override; - - //! Root of the tree - unique_ptr tree; - //! True if machine is little endian - bool is_little_endian; - -public: - //! Initialize a scan on the index with the given expression and column ids - //! to fetch from the base table for a single predicate - unique_ptr InitializeScanSinglePredicate(Transaction &transaction, Value value, - ExpressionType expressionType) override; - - //! Initialize a scan on the index with the given expression and column ids - //! to fetch from the base table for two predicates - unique_ptr InitializeScanTwoPredicates(Transaction &transaction, Value low_value, - ExpressionType low_expression_type, Value high_value, - ExpressionType high_expression_type) override; - - //! Perform a lookup on the index - bool Scan(Transaction &transaction, DataTable &table, IndexScanState &state, idx_t max_count, - vector &result_ids) override; - //! Append entries to the index - bool Append(IndexLock &lock, DataChunk &entries, Vector &row_identifiers) override; - //! Verify that data can be appended to the index - void VerifyAppend(DataChunk &chunk) override; - //! Verify that data can be appended to the index for foreign key constraint - void VerifyAppendForeignKey(DataChunk &chunk, string *err_msg_ptr) override; - //! Verify that data can be delete from the index for foreign key constraint - void VerifyDeleteForeignKey(DataChunk &chunk, string *err_msg_ptr) override; - //! Delete entries in the index - void Delete(IndexLock &lock, DataChunk &entries, Vector &row_identifiers) override; - //! Insert data into the index. - bool Insert(IndexLock &lock, DataChunk &data, Vector &row_ids) override; - - bool SearchEqual(ARTIndexScanState *state, idx_t max_count, vector &result_ids); - //! Search Equal used for Joins that do not need to fetch data - void SearchEqualJoinNoFetch(Value &equal_value, idx_t &result_size); - -private: - DataChunk expression_result; - -private: - //! Insert a row id into a leaf node - bool InsertToLeaf(Leaf &leaf, row_t row_id); - //! Insert the leaf value into the tree - bool Insert(unique_ptr &node, unique_ptr key, unsigned depth, row_t row_id); - - //! Erase element from leaf (if leaf has more than one value) or eliminate the leaf itself - void Erase(unique_ptr &node, Key &key, unsigned depth, row_t row_id); - - //! Check if the key of the leaf is equal to the searched key - bool LeafMatches(Node *node, Key &key, unsigned depth); - - //! Find the node with a matching key, optimistic version - Node *Lookup(unique_ptr &node, Key &key, unsigned depth); - - //! Find the first node that is bigger (or equal to) a specific key - bool Bound(unique_ptr &node, Key &key, Iterator &iterator, bool inclusive); - - //! Gets next node for range queries - bool IteratorNext(Iterator &iter); - - bool SearchGreater(ARTIndexScanState *state, bool inclusive, idx_t max_count, vector &result_ids); - bool SearchLess(ARTIndexScanState *state, bool inclusive, idx_t max_count, vector &result_ids); - bool SearchCloseRange(ARTIndexScanState *state, bool left_inclusive, bool right_inclusive, idx_t max_count, - vector &result_ids); - -private: - template - bool IteratorScan(ARTIndexScanState *state, Iterator *it, Key *upper_bound, idx_t max_count, - vector &result_ids); - - void GenerateKeys(DataChunk &input, vector> &keys); - - void VerifyExistence(DataChunk &chunk, VerifyExistenceType verify_type, string *err_msg_ptr = NULL); -}; - -} // namespace duckdb - - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/parser/parsed_expression_iterator.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -#include - -namespace duckdb { - -class ParsedExpressionIterator { -public: - static void EnumerateChildren(const ParsedExpression &expression, - const std::function &callback); - static void EnumerateChildren(ParsedExpression &expr, const std::function &callback); - static void EnumerateChildren(ParsedExpression &expr, - const std::function &child)> &callback); - - static void EnumerateTableRefChildren(TableRef &ref, - const std::function &child)> &callback); - static void EnumerateQueryNodeChildren(QueryNode &node, - const std::function &child)> &callback); - - static void EnumerateQueryNodeModifiers(QueryNode &node, - const std::function &child)> &callback); -}; - -} // namespace duckdb - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/expression_binder/alter_binder.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { -class TableCatalogEntry; - -//! The ALTER binder is responsible for binding an expression within alter statements -class AlterBinder : public ExpressionBinder { -public: - AlterBinder(Binder &binder, ClientContext &context, TableCatalogEntry &table, vector &bound_columns, - LogicalType target_type); - - TableCatalogEntry &table; - vector &bound_columns; - -protected: - BindResult BindExpression(unique_ptr *expr_ptr, idx_t depth, - bool root_expression = false) override; - - BindResult BindColumn(ColumnRefExpression &expr); - - string UnsupportedAggregateMessage() override; -}; - -} // namespace duckdb - - - -#include - -namespace duckdb { - -const string &TableCatalogEntry::GetColumnName(column_t index) { - return columns[index].Name(); -} +const string &TableCatalogEntry::GetColumnName(column_t index) { + return columns[index].Name(); +} column_t TableCatalogEntry::GetColumnIndex(string &column_name, bool if_exists) { auto entry = name_map.find(column_name); @@ -6254,12 +6297,16 @@ column_t TableCatalogEntry::GetColumnIndex(string &column_name, bool if_exists) throw BinderException("Table \"%s\" does not have a column with name \"%s\"", name, column_name); } } + if (entry->second == COLUMN_IDENTIFIER_ROW_ID) { + column_name = "rowid"; + return COLUMN_IDENTIFIER_ROW_ID; + } column_name = GetColumnName(entry->second); return entry->second; } void AddDataTableIndex(DataTable *storage, vector &columns, vector &keys, - IndexConstraintType constraint_type) { + IndexConstraintType constraint_type, BlockPointer *index_block = nullptr) { // fetch types and create expressions for the index from the columns vector column_ids; vector> unbound_expressions; @@ -6279,8 +6326,14 @@ void AddDataTableIndex(DataTable *storage, vector &columns, ve column_ids.push_back(column.StorageOid()); } // create an adaptive radix tree around the expressions - auto art = make_unique(column_ids, move(unbound_expressions), constraint_type); - storage->AddIndex(move(art), bound_expressions); + if (index_block) { + auto art = make_unique(column_ids, move(unbound_expressions), constraint_type, storage->db, + index_block->block_id, index_block->offset); + storage->info->indexes.AddIndex(move(art)); + } else { + auto art = make_unique(column_ids, move(unbound_expressions), constraint_type, storage->db); + storage->AddIndex(move(art), bound_expressions); + } } TableCatalogEntry::TableCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, BoundCreateTableInfo *info, @@ -6314,8 +6367,8 @@ TableCatalogEntry::TableCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schem storage_columns.push_back(col_def.Copy()); } storage = make_shared(catalog->db, schema->name, name, move(storage_columns), move(info->data)); - // create the unique indexes for the UNIQUE and PRIMARY KEY and FOREIGN KEY constraints + idx_t indexes_idx = 0; for (idx_t i = 0; i < bound_constraints.size(); i++) { auto &constraint = bound_constraints[i]; if (constraint->type == ConstraintType::UNIQUE) { @@ -6325,13 +6378,23 @@ TableCatalogEntry::TableCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schem if (unique.is_primary_key) { constraint_type = IndexConstraintType::PRIMARY; } - AddDataTableIndex(storage.get(), get_columns, unique.keys, constraint_type); + if (info->indexes.empty()) { + AddDataTableIndex(storage.get(), get_columns, unique.keys, constraint_type); + } else { + AddDataTableIndex(storage.get(), get_columns, unique.keys, constraint_type, + &info->indexes[indexes_idx++]); + } } else if (constraint->type == ConstraintType::FOREIGN_KEY) { // foreign key constraint: create a foreign key index auto &bfk = (BoundForeignKeyConstraint &)*constraint; if (bfk.info.type == ForeignKeyType::FK_TYPE_FOREIGN_KEY_TABLE || bfk.info.type == ForeignKeyType::FK_TYPE_SELF_REFERENCE_TABLE) { - AddDataTableIndex(storage.get(), get_columns, bfk.info.fk_keys, IndexConstraintType::FOREIGN); + if (info->indexes.empty()) { + AddDataTableIndex(storage.get(), get_columns, bfk.info.fk_keys, IndexConstraintType::FOREIGN); + } else { + AddDataTableIndex(storage.get(), get_columns, bfk.info.fk_keys, IndexConstraintType::FOREIGN, + &info->indexes[indexes_idx++]); + } } } } @@ -6391,7 +6454,19 @@ unique_ptr TableCatalogEntry::AlterEntry(ClientContext &context, A } case AlterTableType::FOREIGN_KEY_CONSTRAINT: { auto foreign_key_constraint_info = (AlterForeignKeyInfo *)table_info; - return SetForeignKeyConstraint(context, *foreign_key_constraint_info); + if (foreign_key_constraint_info->type == AlterForeignKeyType::AFT_ADD) { + return AddForeignKeyConstraint(context, *foreign_key_constraint_info); + } else { + return DropForeignKeyConstraint(context, *foreign_key_constraint_info); + } + } + case AlterTableType::SET_NOT_NULL: { + auto set_not_null_info = (SetNotNullInfo *)table_info; + return SetNotNull(context, *set_not_null_info); + } + case AlterTableType::DROP_NOT_NULL: { + auto drop_not_null_info = (DropNotNullInfo *)table_info; + return DropNotNull(context, *drop_not_null_info); } default: throw InternalException("Unrecognized alter table type!"); @@ -6478,6 +6553,13 @@ unique_ptr TableCatalogEntry::RenameColumn(ClientContext &context, } unique_ptr TableCatalogEntry::AddColumn(ClientContext &context, AddColumnInfo &info) { + auto col_name = info.new_column.GetName(); + + // We're checking for the opposite condition (ADD COLUMN IF _NOT_ EXISTS ...). + if (info.if_column_not_exists && GetColumnIndex(col_name, true) != DConstants::INVALID_INDEX) { + return nullptr; + } + auto create_info = make_unique(schema->name, name); create_info->temporary = temporary; @@ -6504,7 +6586,7 @@ unique_ptr TableCatalogEntry::AddColumn(ClientContext &context, Ad } unique_ptr TableCatalogEntry::RemoveColumn(ClientContext &context, RemoveColumnInfo &info) { - auto removed_index = GetColumnIndex(info.removed_column, info.if_exists); + auto removed_index = GetColumnIndex(info.removed_column, info.if_column_exists); if (removed_index == DConstants::INVALID_INDEX) { return nullptr; } @@ -6642,6 +6724,69 @@ unique_ptr TableCatalogEntry::SetDefault(ClientContext &context, S return make_unique(catalog, schema, (BoundCreateTableInfo *)bound_create_info.get(), storage); } +unique_ptr TableCatalogEntry::SetNotNull(ClientContext &context, SetNotNullInfo &info) { + + auto create_info = make_unique(schema->name, name); + for (idx_t i = 0; i < columns.size(); i++) { + auto copy = columns[i].Copy(); + create_info->columns.push_back(move(copy)); + } + + idx_t not_null_idx = GetColumnIndex(info.column_name); + bool has_not_null = false; + for (idx_t i = 0; i < constraints.size(); i++) { + auto constraint = constraints[i]->Copy(); + if (constraint->type == ConstraintType::NOT_NULL) { + auto ¬_null = (NotNullConstraint &)*constraint; + if (not_null.index == not_null_idx) { + has_not_null = true; + } + } + create_info->constraints.push_back(move(constraint)); + } + if (!has_not_null) { + create_info->constraints.push_back(make_unique(not_null_idx)); + } + auto binder = Binder::CreateBinder(context); + auto bound_create_info = binder->BindCreateTableInfo(move(create_info)); + + // Early return + if (has_not_null) { + return make_unique(catalog, schema, (BoundCreateTableInfo *)bound_create_info.get(), + storage); + } + + // Return with new storage info + auto new_storage = make_shared(context, *storage, make_unique(not_null_idx)); + return make_unique(catalog, schema, (BoundCreateTableInfo *)bound_create_info.get(), + new_storage); +} + +unique_ptr TableCatalogEntry::DropNotNull(ClientContext &context, DropNotNullInfo &info) { + auto create_info = make_unique(schema->name, name); + for (idx_t i = 0; i < columns.size(); i++) { + auto copy = columns[i].Copy(); + create_info->columns.push_back(move(copy)); + } + + idx_t not_null_idx = GetColumnIndex(info.column_name); + for (idx_t i = 0; i < constraints.size(); i++) { + auto constraint = constraints[i]->Copy(); + // Skip/drop not_null + if (constraint->type == ConstraintType::NOT_NULL) { + auto ¬_null = (NotNullConstraint &)*constraint; + if (not_null.index == not_null_idx) { + continue; + } + } + create_info->constraints.push_back(move(constraint)); + } + + auto binder = Binder::CreateBinder(context); + auto bound_create_info = binder->BindCreateTableInfo(move(create_info)); + return make_unique(catalog, schema, (BoundCreateTableInfo *)bound_create_info.get(), storage); +} + unique_ptr TableCatalogEntry::ChangeColumnType(ClientContext &context, ChangeColumnTypeInfo &info) { if (info.target_type.id() == LogicalTypeId::USER) { auto &catalog = Catalog::GetCatalog(context); @@ -6729,7 +6874,35 @@ unique_ptr TableCatalogEntry::ChangeColumnType(ClientContext &cont return move(result); } -unique_ptr TableCatalogEntry::SetForeignKeyConstraint(ClientContext &context, AlterForeignKeyInfo &info) { +unique_ptr TableCatalogEntry::AddForeignKeyConstraint(ClientContext &context, AlterForeignKeyInfo &info) { + D_ASSERT(info.type == AlterForeignKeyType::AFT_ADD); + auto create_info = make_unique(schema->name, name); + create_info->temporary = temporary; + + for (idx_t i = 0; i < columns.size(); i++) { + create_info->columns.push_back(columns[i].Copy()); + } + for (idx_t i = 0; i < constraints.size(); i++) { + create_info->constraints.push_back(constraints[i]->Copy()); + } + ForeignKeyInfo fk_info; + fk_info.type = ForeignKeyType::FK_TYPE_PRIMARY_KEY_TABLE; + fk_info.schema = info.schema; + fk_info.table = info.fk_table; + fk_info.pk_keys = info.pk_keys; + fk_info.fk_keys = info.fk_keys; + create_info->constraints.push_back( + make_unique(info.pk_columns, info.fk_columns, move(fk_info))); + + auto binder = Binder::CreateBinder(context); + auto bound_create_info = binder->BindCreateTableInfo(move(create_info)); + + return make_unique(catalog, schema, (BoundCreateTableInfo *)bound_create_info.get(), storage); +} + +unique_ptr TableCatalogEntry::DropForeignKeyConstraint(ClientContext &context, + AlterForeignKeyInfo &info) { + D_ASSERT(info.type == AlterForeignKeyType::AFT_DELETE); auto create_info = make_unique(schema->name, name); create_info->temporary = temporary; @@ -6746,16 +6919,6 @@ unique_ptr TableCatalogEntry::SetForeignKeyConstraint(ClientContex } create_info->constraints.push_back(move(constraint)); } - if (info.type == AlterForeignKeyType::AFT_ADD) { - ForeignKeyInfo fk_info; - fk_info.type = ForeignKeyType::FK_TYPE_PRIMARY_KEY_TABLE; - fk_info.schema = info.schema; - fk_info.table = info.fk_table; - fk_info.pk_keys = info.pk_keys; - fk_info.fk_keys = info.fk_keys; - create_info->constraints.push_back( - make_unique(info.pk_columns, info.fk_columns, move(fk_info))); - } auto binder = Binder::CreateBinder(context); auto bound_create_info = binder->BindCreateTableInfo(move(create_info)); @@ -6794,7 +6957,7 @@ void TableCatalogEntry::Serialize(Serializer &serializer) { writer.Finalize(); } -unique_ptr TableCatalogEntry::Deserialize(Deserializer &source) { +unique_ptr TableCatalogEntry::Deserialize(Deserializer &source, ClientContext &context) { auto info = make_unique(); FieldReader reader(source); @@ -6969,7 +7132,7 @@ namespace duckdb { TableFunctionCatalogEntry::TableFunctionCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, CreateTableFunctionInfo *info) : StandardEntry(CatalogType::TABLE_FUNCTION_ENTRY, schema, catalog, info->name), functions(move(info->functions)) { - D_ASSERT(this->functions.size() > 0); + D_ASSERT(this->functions.Size() > 0); } } // namespace duckdb @@ -7098,7 +7261,7 @@ void ViewCatalogEntry::Serialize(Serializer &serializer) { writer.Finalize(); } -unique_ptr ViewCatalogEntry::Deserialize(Deserializer &source) { +unique_ptr ViewCatalogEntry::Deserialize(Deserializer &source, ClientContext &context) { auto info = make_unique(); FieldReader reader(source); @@ -7184,8 +7347,7 @@ CatalogSearchPath::CatalogSearchPath(ClientContext &context_p) : context(context SetPaths(ParsePaths("")); } -void CatalogSearchPath::Set(const string &new_value, bool is_set_schema) { - auto new_paths = ParsePaths(new_value); +void CatalogSearchPath::Set(vector &new_paths, bool is_set_schema) { if (is_set_schema && new_paths.size() != 1) { throw CatalogException("SET schema can set only 1 schema. This has %d", new_paths.size()); } @@ -7199,6 +7361,11 @@ void CatalogSearchPath::Set(const string &new_value, bool is_set_schema) { SetPaths(set_paths); } +void CatalogSearchPath::Set(const string &new_value, bool is_set_schema) { + auto new_paths = ParsePaths(new_value); + Set(new_paths, is_set_schema); +} + const vector &CatalogSearchPath::Get() { return paths; } @@ -8017,10 +8184,12 @@ struct PGList; } // namespace duckdb_libpgquery namespace duckdb { +class ParserExtension; struct ParserOptions { bool preserve_identifier_case = true; idx_t max_expression_depth = 1000; + const vector *extensions = nullptr; }; //! The parser is responsible for parsing the query and converting it into a set @@ -8181,6 +8350,7 @@ static DefaultMacro internal_macros[] = { {DEFAULT_SCHEMA, "list_entropy", {"l", nullptr}, "list_aggr(l, 'entropy')"}, {DEFAULT_SCHEMA, "list_last", {"l", nullptr}, "list_aggr(l, 'last')"}, {DEFAULT_SCHEMA, "list_first", {"l", nullptr}, "list_aggr(l, 'first')"}, + {DEFAULT_SCHEMA, "list_any_value", {"l", nullptr}, "list_aggr(l, 'any_value')"}, {DEFAULT_SCHEMA, "list_kurtosis", {"l", nullptr}, "list_aggr(l, 'kurtosis')"}, {DEFAULT_SCHEMA, "list_min", {"l", nullptr}, "list_aggr(l, 'min')"}, {DEFAULT_SCHEMA, "list_max", {"l", nullptr}, "list_aggr(l, 'max')"}, @@ -8319,6 +8489,7 @@ vector DefaultSchemaGenerator::GetDefaultEntries() { + namespace duckdb { struct DefaultType { @@ -8379,6 +8550,7 @@ static DefaultType internal_types[] = {{"int", LogicalTypeId::INTEGER}, {"guid", LogicalTypeId::UUID}, {"struct", LogicalTypeId::STRUCT}, {"row", LogicalTypeId::STRUCT}, + {"list", LogicalTypeId::LIST}, {"map", LogicalTypeId::MAP}, {"utinyint", LogicalTypeId::UTINYINT}, {"uint8", LogicalTypeId::UTINYINT}, @@ -8756,50 +8928,1115 @@ void DependencyManager::AddOwnership(ClientContext &context, CatalogEntry *owner } // namespace duckdb + + +#ifdef DUCKDB_DEBUG_ALLOCATION + + + +#include +#endif + namespace duckdb { +AllocatedData::AllocatedData() : allocator(nullptr), pointer(nullptr), allocated_size(0) { +} + AllocatedData::AllocatedData(Allocator &allocator, data_ptr_t pointer, idx_t allocated_size) - : allocator(allocator), pointer(pointer), allocated_size(allocated_size) { + : allocator(&allocator), pointer(pointer), allocated_size(allocated_size) { } AllocatedData::~AllocatedData() { Reset(); } +AllocatedData::AllocatedData(AllocatedData &&other) noexcept + : allocator(other.allocator), pointer(nullptr), allocated_size(0) { + std::swap(pointer, other.pointer); + std::swap(allocated_size, other.allocated_size); +} + +AllocatedData &AllocatedData::operator=(AllocatedData &&other) noexcept { + std::swap(allocator, other.allocator); + std::swap(pointer, other.pointer); + std::swap(allocated_size, other.allocated_size); + return *this; +} + void AllocatedData::Reset() { if (!pointer) { return; } - allocator.FreeData(pointer, allocated_size); + D_ASSERT(allocator); + allocator->FreeData(pointer, allocated_size); pointer = nullptr; } +//===--------------------------------------------------------------------===// +// Debug Info +//===--------------------------------------------------------------------===// +struct AllocatorDebugInfo { +#ifdef DEBUG + AllocatorDebugInfo(); + ~AllocatorDebugInfo(); + + static string GetStackTrace(int max_depth = 128); + + void AllocateData(data_ptr_t pointer, idx_t size); + void FreeData(data_ptr_t pointer, idx_t size); + void ReallocateData(data_ptr_t pointer, data_ptr_t new_pointer, idx_t old_size, idx_t new_size); + +private: + //! The number of bytes that are outstanding (i.e. that have been allocated - but not freed) + //! Used for debug purposes + atomic allocation_count; +#ifdef DUCKDB_DEBUG_ALLOCATION + mutex pointer_lock; + //! Set of active outstanding pointers together with stack traces + unordered_map> pointers; +#endif +#endif +}; + +PrivateAllocatorData::PrivateAllocatorData() { +} + +PrivateAllocatorData::~PrivateAllocatorData() { +} + +//===--------------------------------------------------------------------===// +// Allocator +//===--------------------------------------------------------------------===// Allocator::Allocator() - : allocate_function(Allocator::DefaultAllocate), free_function(Allocator::DefaultFree), - reallocate_function(Allocator::DefaultReallocate) { + : Allocator(Allocator::DefaultAllocate, Allocator::DefaultFree, Allocator::DefaultReallocate, nullptr) { } 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 private_data) + reallocate_function_ptr_t reallocate_function_p, unique_ptr private_data_p) : allocate_function(allocate_function_p), free_function(free_function_p), - reallocate_function(reallocate_function_p), private_data(move(private_data)) { + reallocate_function(reallocate_function_p), private_data(move(private_data_p)) { + D_ASSERT(allocate_function); + D_ASSERT(free_function); + D_ASSERT(reallocate_function); +#ifdef DEBUG + if (!private_data) { + private_data = make_unique(); + } + private_data->debug_info = make_unique(); +#endif +} + +Allocator::~Allocator() { } data_ptr_t Allocator::AllocateData(idx_t size) { - return allocate_function(private_data.get(), size); + auto result = allocate_function(private_data.get(), size); +#ifdef DEBUG + D_ASSERT(private_data); + private_data->debug_info->AllocateData(result, size); +#endif + return result; } void Allocator::FreeData(data_ptr_t pointer, idx_t size) { if (!pointer) { return; } - return free_function(private_data.get(), pointer, size); +#ifdef DEBUG + D_ASSERT(private_data); + private_data->debug_info->FreeData(pointer, size); +#endif + free_function(private_data.get(), pointer, size); } -data_ptr_t Allocator::ReallocateData(data_ptr_t pointer, idx_t size) { +data_ptr_t Allocator::ReallocateData(data_ptr_t pointer, idx_t old_size, idx_t size) { if (!pointer) { - return pointer; + return nullptr; + } + auto new_pointer = reallocate_function(private_data.get(), pointer, old_size, size); +#ifdef DEBUG + D_ASSERT(private_data); + private_data->debug_info->ReallocateData(pointer, new_pointer, old_size, size); +#endif + return new_pointer; +} + +Allocator &Allocator::DefaultAllocator() { + static Allocator DEFAULT_ALLOCATOR; + return DEFAULT_ALLOCATOR; +} + +//===--------------------------------------------------------------------===// +// Debug Info (extended) +//===--------------------------------------------------------------------===// +#ifdef DEBUG +AllocatorDebugInfo::AllocatorDebugInfo() { + allocation_count = 0; +} +AllocatorDebugInfo::~AllocatorDebugInfo() { +#ifdef DUCKDB_DEBUG_ALLOCATION + if (allocation_count != 0) { + printf("Outstanding allocations found for Allocator\n"); + for (auto &entry : pointers) { + printf("Allocation of size %ld at address %p\n", entry.second.first, (void *)entry.first); + printf("Stack trace:\n%s\n", entry.second.second.c_str()); + printf("\n"); + } + } +#endif + //! Verify that there is no outstanding memory still associated with the batched allocator + //! Only works for access to the batched allocator through the batched allocator interface + //! If this assertion triggers, enable DUCKDB_DEBUG_ALLOCATION for more information about the allocations + D_ASSERT(allocation_count == 0); +} + +string AllocatorDebugInfo::GetStackTrace(int max_depth) { +#ifdef DUCKDB_DEBUG_ALLOCATION + string result; + auto callstack = unique_ptr(new void *[max_depth]); + int frames = backtrace(callstack.get(), max_depth); + char **strs = backtrace_symbols(callstack.get(), frames); + for (int i = 0; i < frames; i++) { + result += strs[i]; + result += "\n"; + } + free(strs); + return result; +#else + throw InternalException("GetStackTrace not supported without DUCKDB_DEBUG_ALLOCATION"); +#endif +} + +void AllocatorDebugInfo::AllocateData(data_ptr_t pointer, idx_t size) { + allocation_count += size; +#ifdef DUCKDB_DEBUG_ALLOCATION + lock_guard l(pointer_lock); + pointers[pointer] = make_pair(size, GetStackTrace()); +#endif +} + +void AllocatorDebugInfo::FreeData(data_ptr_t pointer, idx_t size) { + D_ASSERT(allocation_count >= size); + allocation_count -= size; +#ifdef DUCKDB_DEBUG_ALLOCATION + lock_guard l(pointer_lock); + // verify that the pointer exists + D_ASSERT(pointers.find(pointer) != pointers.end()); + // verify that the stored size matches the passed in size + D_ASSERT(pointers[pointer].first == size); + // erase the pointer + pointers.erase(pointer); +#endif +} + +void AllocatorDebugInfo::ReallocateData(data_ptr_t pointer, data_ptr_t new_pointer, idx_t old_size, idx_t new_size) { + FreeData(pointer, old_size); + AllocateData(new_pointer, new_size); +} + +#endif + +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/arrow/arrow_appender.hpp +// +// +//===----------------------------------------------------------------------===// + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/arrow/arrow_converter.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +struct ArrowSchema; + +namespace duckdb { + +struct ArrowConverter { + DUCKDB_API static void ToArrowSchema(ArrowSchema *out_schema, vector &types, vector &names, + string &config_timezone); + DUCKDB_API static void ToArrowArray(DataChunk &input, ArrowArray *out_array); +}; + +} // namespace duckdb + + +struct ArrowSchema; + +namespace duckdb { + +struct ArrowAppendData; + +//! The ArrowAppender class can be used to incrementally construct an arrow array by appending data chunks into it +class ArrowAppender { +public: + DUCKDB_API ArrowAppender(vector types, idx_t initial_capacity); + DUCKDB_API ~ArrowAppender(); + + //! Append a data chunk to the underlying arrow array + DUCKDB_API void Append(DataChunk &input); + //! Returns the underlying arrow array + DUCKDB_API ArrowArray Finalize(); + +private: + //! The types of the chunks that will be appended in + vector types; + //! The root arrow append data + vector> root_data; + //! The total row count that has been appended + idx_t row_count = 0; +}; + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/arrow/arrow_buffer.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +struct ArrowSchema; + +namespace duckdb { + +struct ArrowBuffer { + static constexpr const idx_t MINIMUM_SHRINK_SIZE = 4096; + + ArrowBuffer() : dataptr(nullptr), count(0), capacity(0) { + } + ~ArrowBuffer() { + if (!dataptr) { + return; + } + free(dataptr); + dataptr = nullptr; + count = 0; + capacity = 0; + } + // disable copy constructors + ArrowBuffer(const ArrowBuffer &other) = delete; + ArrowBuffer &operator=(const ArrowBuffer &) = delete; + //! enable move constructors + ArrowBuffer(ArrowBuffer &&other) noexcept { + std::swap(dataptr, other.dataptr); + std::swap(count, other.count); + std::swap(capacity, other.capacity); + } + ArrowBuffer &operator=(ArrowBuffer &&other) noexcept { + std::swap(dataptr, other.dataptr); + std::swap(count, other.count); + std::swap(capacity, other.capacity); + return *this; + } + + void reserve(idx_t bytes) { // NOLINT + auto new_capacity = NextPowerOfTwo(bytes); + if (new_capacity <= capacity) { + return; + } + ReserveInternal(new_capacity); + } + + void resize(idx_t bytes) { // NOLINT + reserve(bytes); + count = bytes; + } + + void resize(idx_t bytes, data_t value) { // NOLINT + reserve(bytes); + for (idx_t i = count; i < bytes; i++) { + dataptr[i] = value; + } + count = bytes; + } + + idx_t size() { // NOLINT + return count; + } + + data_ptr_t data() { // NOLINT + return dataptr; + } + +private: + void ReserveInternal(idx_t bytes) { + if (dataptr) { + dataptr = (data_ptr_t)realloc(dataptr, bytes); + } else { + dataptr = (data_ptr_t)malloc(bytes); + } + capacity = bytes; + } + +private: + data_ptr_t dataptr = nullptr; + idx_t count = 0; + idx_t capacity = 0; +}; + +} // namespace duckdb + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/array.hpp +// +// +//===----------------------------------------------------------------------===// + + + +#include + +namespace duckdb { +using std::array; +} + + + + +namespace duckdb { + +//===--------------------------------------------------------------------===// +// Arrow append data +//===--------------------------------------------------------------------===// +typedef void (*initialize_t)(ArrowAppendData &result, const LogicalType &type, idx_t capacity); +typedef void (*append_vector_t)(ArrowAppendData &append_data, Vector &input, idx_t size); +typedef void (*finalize_t)(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result); + +struct ArrowAppendData { + // the buffers of the arrow vector + ArrowBuffer validity; + ArrowBuffer main_buffer; + ArrowBuffer aux_buffer; + + idx_t row_count = 0; + idx_t null_count = 0; + + // function pointers for construction + initialize_t initialize = nullptr; + append_vector_t append_vector = nullptr; + finalize_t finalize = nullptr; + + // child data (if any) + vector> child_data; + + //! the arrow array C API data, only set after Finalize + unique_ptr array; + duckdb::array buffers = {{nullptr, nullptr, nullptr}}; + vector child_pointers; +}; + +//===--------------------------------------------------------------------===// +// ArrowAppender +//===--------------------------------------------------------------------===// +static unique_ptr InitializeArrowChild(const LogicalType &type, idx_t capacity); +static ArrowArray *FinalizeArrowChild(const LogicalType &type, ArrowAppendData &append_data); + +ArrowAppender::ArrowAppender(vector types_p, idx_t initial_capacity) : types(move(types_p)) { + for (auto &type : types) { + auto entry = InitializeArrowChild(type, initial_capacity); + root_data.push_back(move(entry)); + } +} + +ArrowAppender::~ArrowAppender() { +} + +//===--------------------------------------------------------------------===// +// Append Helper Functions +//===--------------------------------------------------------------------===// +static void GetBitPosition(idx_t row_idx, idx_t ¤t_byte, uint8_t ¤t_bit) { + current_byte = row_idx / 8; + current_bit = row_idx % 8; +} + +static void UnsetBit(uint8_t *data, idx_t current_byte, uint8_t current_bit) { + data[current_byte] &= ~(1 << current_bit); +} + +static void NextBit(idx_t ¤t_byte, uint8_t ¤t_bit) { + current_bit++; + if (current_bit == 8) { + current_byte++; + current_bit = 0; + } +} + +static void ResizeValidity(ArrowBuffer &buffer, idx_t row_count) { + auto byte_count = (row_count + 7) / 8; + buffer.resize(byte_count, 0xFF); +} + +static void SetNull(ArrowAppendData &append_data, uint8_t *validity_data, idx_t current_byte, uint8_t current_bit) { + UnsetBit(validity_data, current_byte, current_bit); + append_data.null_count++; +} + +static void AppendValidity(ArrowAppendData &append_data, UnifiedVectorFormat &format, idx_t size) { + // resize the buffer, filling the validity buffer with all valid values + ResizeValidity(append_data.validity, append_data.row_count + size); + if (format.validity.AllValid()) { + // if all values are valid we don't need to do anything else + return; + } + + // otherwise we iterate through the validity mask + auto validity_data = (uint8_t *)append_data.validity.data(); + uint8_t current_bit; + idx_t current_byte; + GetBitPosition(append_data.row_count, current_byte, current_bit); + for (idx_t i = 0; i < size; i++) { + auto source_idx = format.sel->get_index(i); + // append the validity mask + if (!format.validity.RowIsValid(source_idx)) { + SetNull(append_data, validity_data, current_byte, current_bit); + } + NextBit(current_byte, current_bit); + } +} + +//===--------------------------------------------------------------------===// +// Scalar Types +//===--------------------------------------------------------------------===// +struct ArrowScalarConverter { + template + static TGT Operation(SRC input) { + return input; + } + + static bool SkipNulls() { + return false; + } + + template + static void SetNull(TGT &value) { + } +}; + +struct ArrowIntervalConverter { + template + static TGT Operation(SRC input) { + return Interval::GetMilli(input); + } + + static bool SkipNulls() { + return true; + } + + template + static void SetNull(TGT &value) { + value = 0; + } +}; + +template +struct ArrowScalarBaseData { + static void Append(ArrowAppendData &append_data, Vector &input, idx_t size) { + UnifiedVectorFormat format; + input.ToUnifiedFormat(size, format); + + // append the validity mask + AppendValidity(append_data, format, size); + + // append the main data + append_data.main_buffer.resize(append_data.main_buffer.size() + sizeof(TGT) * size); + auto data = (SRC *)format.data; + auto result_data = (TGT *)append_data.main_buffer.data(); + + for (idx_t i = 0; i < size; i++) { + auto source_idx = format.sel->get_index(i); + auto result_idx = append_data.row_count + i; + + if (OP::SkipNulls() && !format.validity.RowIsValid(source_idx)) { + OP::template SetNull(result_data[result_idx]); + continue; + } + result_data[result_idx] = OP::template Operation(data[source_idx]); + } + append_data.row_count += size; + } +}; + +template +struct ArrowScalarData : public ArrowScalarBaseData { + static void Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { + result.main_buffer.reserve(capacity * sizeof(TGT)); + } + + static void Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { + result->n_buffers = 2; + result->buffers[1] = append_data.main_buffer.data(); + } +}; + +//===--------------------------------------------------------------------===// +// Enums +//===--------------------------------------------------------------------===// +template +struct ArrowEnumData : public ArrowScalarBaseData { + static void Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { + result.main_buffer.reserve(capacity * sizeof(TGT)); + // construct the enum child data + auto enum_data = InitializeArrowChild(LogicalType::VARCHAR, EnumType::GetSize(type)); + enum_data->append_vector(*enum_data, EnumType::GetValuesInsertOrder(type), EnumType::GetSize(type)); + result.child_data.push_back(move(enum_data)); + } + + static void Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { + result->n_buffers = 2; + result->buffers[1] = append_data.main_buffer.data(); + // finalize the enum child data, and assign it to the dictionary + result->dictionary = FinalizeArrowChild(LogicalType::VARCHAR, *append_data.child_data[0]); + } +}; + +//===--------------------------------------------------------------------===// +// Boolean +//===--------------------------------------------------------------------===// +struct ArrowBoolData { + static void Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { + auto byte_count = (capacity + 7) / 8; + result.main_buffer.reserve(byte_count); + } + + static void Append(ArrowAppendData &append_data, Vector &input, idx_t size) { + UnifiedVectorFormat format; + input.ToUnifiedFormat(size, format); + + // we initialize both the validity and the bit set to 1's + ResizeValidity(append_data.validity, append_data.row_count + size); + ResizeValidity(append_data.main_buffer, append_data.row_count + size); + auto data = (bool *)format.data; + + auto result_data = (uint8_t *)append_data.main_buffer.data(); + auto validity_data = (uint8_t *)append_data.validity.data(); + uint8_t current_bit; + idx_t current_byte; + GetBitPosition(append_data.row_count, current_byte, current_bit); + for (idx_t i = 0; i < size; i++) { + auto source_idx = format.sel->get_index(i); + // append the validity mask + if (!format.validity.RowIsValid(source_idx)) { + SetNull(append_data, validity_data, current_byte, current_bit); + } else if (!data[source_idx]) { + UnsetBit(result_data, current_byte, current_bit); + } + NextBit(current_byte, current_bit); + } + append_data.row_count += size; + } + + static void Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { + result->n_buffers = 2; + result->buffers[1] = append_data.main_buffer.data(); + } +}; + +//===--------------------------------------------------------------------===// +// Varchar +//===--------------------------------------------------------------------===// +struct ArrowVarcharConverter { + template + static idx_t GetLength(SRC input) { + return input.GetSize(); + } + + template + static void WriteData(data_ptr_t target, SRC input) { + memcpy(target, input.GetDataUnsafe(), input.GetSize()); + } +}; + +struct ArrowUUIDConverter { + template + static idx_t GetLength(SRC input) { + return UUID::STRING_SIZE; + } + + template + static void WriteData(data_ptr_t target, SRC input) { + UUID::ToString(input, (char *)target); + } +}; + +template +struct ArrowVarcharData { + static void Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { + result.main_buffer.reserve((capacity + 1) * sizeof(uint32_t)); + result.aux_buffer.reserve(capacity); + } + + static void Append(ArrowAppendData &append_data, Vector &input, idx_t size) { + UnifiedVectorFormat format; + input.ToUnifiedFormat(size, format); + + // resize the validity mask and set up the validity buffer for iteration + ResizeValidity(append_data.validity, append_data.row_count + size); + auto validity_data = (uint8_t *)append_data.validity.data(); + + // resize the offset buffer - the offset buffer holds the offsets into the child array + append_data.main_buffer.resize(append_data.main_buffer.size() + sizeof(uint32_t) * (size + 1)); + auto data = (SRC *)format.data; + auto offset_data = (uint32_t *)append_data.main_buffer.data(); + if (append_data.row_count == 0) { + // first entry + offset_data[0] = 0; + } + // now append the string data to the auxiliary buffer + // the auxiliary buffer's length depends on the string lengths, so we resize as required + auto last_offset = offset_data[append_data.row_count]; + for (idx_t i = 0; i < size; i++) { + auto source_idx = format.sel->get_index(i); + auto offset_idx = append_data.row_count + i + 1; + + if (!format.validity.RowIsValid(source_idx)) { + uint8_t current_bit; + idx_t current_byte; + GetBitPosition(append_data.row_count + i, current_byte, current_bit); + SetNull(append_data, validity_data, current_byte, current_bit); + offset_data[offset_idx] = last_offset; + continue; + } + + auto string_length = OP::GetLength(data[source_idx]); + + // append the offset data + auto current_offset = last_offset + string_length; + offset_data[offset_idx] = current_offset; + + // resize the string buffer if required, and write the string data + append_data.aux_buffer.resize(current_offset); + OP::WriteData(append_data.aux_buffer.data() + last_offset, data[source_idx]); + + last_offset = current_offset; + } + append_data.row_count += size; + } + + static void Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { + result->n_buffers = 3; + result->buffers[1] = append_data.main_buffer.data(); + result->buffers[2] = append_data.aux_buffer.data(); + } +}; + +//===--------------------------------------------------------------------===// +// Structs +//===--------------------------------------------------------------------===// +struct ArrowStructData { + static void Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { + auto &children = StructType::GetChildTypes(type); + for (auto &child : children) { + auto child_buffer = InitializeArrowChild(child.second, capacity); + result.child_data.push_back(move(child_buffer)); + } + } + + static void Append(ArrowAppendData &append_data, Vector &input, idx_t size) { + UnifiedVectorFormat format; + input.ToUnifiedFormat(size, format); + + AppendValidity(append_data, format, size); + // append the children of the struct + auto &children = StructVector::GetEntries(input); + for (idx_t child_idx = 0; child_idx < children.size(); child_idx++) { + auto &child = children[child_idx]; + auto &child_data = *append_data.child_data[child_idx]; + child_data.append_vector(child_data, *child, size); + } + append_data.row_count += size; + } + + static void Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { + result->n_buffers = 1; + + auto &child_types = StructType::GetChildTypes(type); + append_data.child_pointers.resize(child_types.size()); + result->children = append_data.child_pointers.data(); + result->n_children = child_types.size(); + for (idx_t i = 0; i < child_types.size(); i++) { + auto &child_type = child_types[i].second; + append_data.child_pointers[i] = FinalizeArrowChild(child_type, *append_data.child_data[i]); + } + } +}; + +//===--------------------------------------------------------------------===// +// Lists +//===--------------------------------------------------------------------===// +void AppendListOffsets(ArrowAppendData &append_data, UnifiedVectorFormat &format, idx_t size, + vector &child_sel) { + // resize the offset buffer - the offset buffer holds the offsets into the child array + append_data.main_buffer.resize(append_data.main_buffer.size() + sizeof(uint32_t) * (size + 1)); + auto data = (list_entry_t *)format.data; + auto offset_data = (uint32_t *)append_data.main_buffer.data(); + if (append_data.row_count == 0) { + // first entry + offset_data[0] = 0; + } + // set up the offsets using the list entries + auto last_offset = offset_data[append_data.row_count]; + for (idx_t i = 0; i < size; i++) { + auto source_idx = format.sel->get_index(i); + auto offset_idx = append_data.row_count + i + 1; + + if (!format.validity.RowIsValid(source_idx)) { + offset_data[offset_idx] = last_offset; + continue; + } + + // append the offset data + auto list_length = data[source_idx].length; + last_offset += list_length; + offset_data[offset_idx] = last_offset; + + for (idx_t k = 0; k < list_length; k++) { + child_sel.push_back(data[source_idx].offset + k); + } + } +} + +struct ArrowListData { + static void Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { + auto &child_type = ListType::GetChildType(type); + result.main_buffer.reserve((capacity + 1) * sizeof(uint32_t)); + auto child_buffer = InitializeArrowChild(child_type, capacity); + result.child_data.push_back(move(child_buffer)); + } + + static void Append(ArrowAppendData &append_data, Vector &input, idx_t size) { + UnifiedVectorFormat format; + input.ToUnifiedFormat(size, format); + + vector child_indices; + AppendValidity(append_data, format, size); + AppendListOffsets(append_data, format, size, child_indices); + + // append the child vector of the list + SelectionVector child_sel(child_indices.data()); + auto &child = ListVector::GetEntry(input); + auto child_size = child_indices.size(); + child.Slice(child_sel, child_size); + + append_data.child_data[0]->append_vector(*append_data.child_data[0], child, child_size); + append_data.row_count += size; + } + + static void Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { + result->n_buffers = 2; + result->buffers[1] = append_data.main_buffer.data(); + + auto &child_type = ListType::GetChildType(type); + append_data.child_pointers.resize(1); + result->children = append_data.child_pointers.data(); + result->n_children = 1; + append_data.child_pointers[0] = FinalizeArrowChild(child_type, *append_data.child_data[0]); + } +}; + +//===--------------------------------------------------------------------===// +// Maps +//===--------------------------------------------------------------------===// +struct ArrowMapData { + static void Initialize(ArrowAppendData &result, const LogicalType &type, idx_t capacity) { + // map types are stored in a (too) clever way + // the main buffer holds the null values and the offsets + // then we have a single child, which is a struct of the map_type, and the key_type + result.main_buffer.reserve((capacity + 1) * sizeof(uint32_t)); + + auto &key_type = MapType::KeyType(type); + auto &value_type = MapType::ValueType(type); + auto internal_struct = make_unique(); + internal_struct->child_data.push_back(InitializeArrowChild(key_type, capacity)); + internal_struct->child_data.push_back(InitializeArrowChild(value_type, capacity)); + + result.child_data.push_back(move(internal_struct)); + } + + static void Append(ArrowAppendData &append_data, Vector &input, idx_t size) { + UnifiedVectorFormat format; + input.ToUnifiedFormat(size, format); + + AppendValidity(append_data, format, size); + // maps exist as a struct of two lists, e.g. STRUCT(key VARCHAR[], value VARCHAR[]) + // since both lists are the same, arrow tries to be smart by storing the offsets only once + // we can append the offsets from any of the two children + auto &children = StructVector::GetEntries(input); + + UnifiedVectorFormat child_format; + children[0]->ToUnifiedFormat(size, child_format); + vector child_indices; + AppendListOffsets(append_data, child_format, size, child_indices); + + // now we can append the children to the lists + auto &struct_entries = StructVector::GetEntries(input); + D_ASSERT(struct_entries.size() == 2); + SelectionVector child_sel(child_indices.data()); + auto &key_vector = ListVector::GetEntry(*struct_entries[0]); + auto &value_vector = ListVector::GetEntry(*struct_entries[1]); + auto list_size = child_indices.size(); + key_vector.Slice(child_sel, list_size); + value_vector.Slice(child_sel, list_size); + + // perform the append + auto &struct_data = *append_data.child_data[0]; + auto &key_data = *struct_data.child_data[0]; + auto &value_data = *struct_data.child_data[1]; + key_data.append_vector(key_data, key_vector, list_size); + value_data.append_vector(value_data, value_vector, list_size); + + append_data.row_count += size; + struct_data.row_count += size; + } + + static void Finalize(ArrowAppendData &append_data, const LogicalType &type, ArrowArray *result) { + // set up the main map buffer + result->n_buffers = 2; + result->buffers[1] = append_data.main_buffer.data(); + + // the main map buffer has a single child: a struct + append_data.child_pointers.resize(1); + result->children = append_data.child_pointers.data(); + result->n_children = 1; + append_data.child_pointers[0] = FinalizeArrowChild(type, *append_data.child_data[0]); + + // now that struct has two children: the key and the value type + auto &struct_data = *append_data.child_data[0]; + auto &struct_result = append_data.child_pointers[0]; + struct_data.child_pointers.resize(2); + struct_result->n_buffers = 1; + struct_result->n_children = 2; + struct_result->length = struct_data.child_data[0]->row_count; + struct_result->children = struct_data.child_pointers.data(); + + D_ASSERT(struct_data.child_data[0]->row_count == struct_data.child_data[1]->row_count); + + auto &key_type = MapType::KeyType(type); + auto &value_type = MapType::ValueType(type); + struct_data.child_pointers[0] = FinalizeArrowChild(key_type, *struct_data.child_data[0]); + struct_data.child_pointers[1] = FinalizeArrowChild(value_type, *struct_data.child_data[1]); + + // keys cannot have null values + if (struct_data.child_pointers[0]->null_count > 0) { + throw std::runtime_error("Arrow doesn't accept NULL keys on Maps"); + } + } +}; + +//! Append a data chunk to the underlying arrow array +void ArrowAppender::Append(DataChunk &input) { + D_ASSERT(types == input.GetTypes()); + for (idx_t i = 0; i < input.ColumnCount(); i++) { + root_data[i]->append_vector(*root_data[i], input.data[i], input.size()); + } + row_count += input.size(); +} +//===--------------------------------------------------------------------===// +// Initialize Arrow Child +//===--------------------------------------------------------------------===// +template +static void InitializeFunctionPointers(ArrowAppendData &append_data) { + append_data.initialize = OP::Initialize; + append_data.append_vector = OP::Append; + append_data.finalize = OP::Finalize; +} + +static void InitializeFunctionPointers(ArrowAppendData &append_data, const LogicalType &type) { + // handle special logical types + switch (type.id()) { + case LogicalTypeId::BOOLEAN: + InitializeFunctionPointers(append_data); + break; + case LogicalTypeId::TINYINT: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::SMALLINT: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::DATE: + case LogicalTypeId::INTEGER: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::TIME: + case LogicalTypeId::TIMESTAMP_SEC: + case LogicalTypeId::TIMESTAMP_MS: + case LogicalTypeId::TIMESTAMP: + case LogicalTypeId::TIMESTAMP_NS: + case LogicalTypeId::TIMESTAMP_TZ: + case LogicalTypeId::TIME_TZ: + case LogicalTypeId::BIGINT: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::HUGEINT: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::UTINYINT: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::USMALLINT: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::UINTEGER: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::UBIGINT: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::FLOAT: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::DOUBLE: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::DECIMAL: + switch (type.InternalType()) { + case PhysicalType::INT16: + InitializeFunctionPointers>(append_data); + break; + case PhysicalType::INT32: + InitializeFunctionPointers>(append_data); + break; + case PhysicalType::INT64: + InitializeFunctionPointers>(append_data); + break; + case PhysicalType::INT128: + InitializeFunctionPointers>(append_data); + break; + default: + throw InternalException("Unsupported internal decimal type"); + } + break; + case LogicalTypeId::VARCHAR: + case LogicalTypeId::BLOB: + case LogicalTypeId::JSON: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::UUID: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::ENUM: + switch (type.InternalType()) { + case PhysicalType::UINT8: + InitializeFunctionPointers>(append_data); + break; + case PhysicalType::UINT16: + InitializeFunctionPointers>(append_data); + break; + case PhysicalType::UINT32: + InitializeFunctionPointers>(append_data); + break; + default: + throw InternalException("Unsupported internal enum type"); + } + break; + case LogicalTypeId::INTERVAL: + InitializeFunctionPointers>(append_data); + break; + case LogicalTypeId::STRUCT: + InitializeFunctionPointers(append_data); + break; + case LogicalTypeId::LIST: + InitializeFunctionPointers(append_data); + break; + case LogicalTypeId::MAP: + InitializeFunctionPointers(append_data); + break; + default: + throw InternalException("Unsupported type in DuckDB -> Arrow Conversion: %s\n", type.ToString()); } - return reallocate_function(private_data.get(), pointer, size); +} + +unique_ptr InitializeArrowChild(const LogicalType &type, idx_t capacity) { + auto result = make_unique(); + InitializeFunctionPointers(*result, type); + + auto byte_count = (capacity + 7) / 8; + result->validity.reserve(byte_count); + result->initialize(*result, type, capacity); + return result; +} + +static void ReleaseDuckDBArrowAppendArray(ArrowArray *array) { + if (!array || !array->release) { + return; + } + array->release = nullptr; + auto holder = static_cast(array->private_data); + delete holder; +} + +//===--------------------------------------------------------------------===// +// Finalize Arrow Child +//===--------------------------------------------------------------------===// +ArrowArray *FinalizeArrowChild(const LogicalType &type, ArrowAppendData &append_data) { + auto result = make_unique(); + + result->private_data = nullptr; + result->release = ReleaseDuckDBArrowAppendArray; + result->n_children = 0; + result->null_count = 0; + result->offset = 0; + result->dictionary = nullptr; + result->buffers = append_data.buffers.data(); + result->null_count = append_data.null_count; + result->length = append_data.row_count; + result->buffers[0] = append_data.validity.data(); + + if (append_data.finalize) { + append_data.finalize(append_data, type, result.get()); + } + + append_data.array = move(result); + return append_data.array.get(); +} + +//! Returns the underlying arrow array +ArrowArray ArrowAppender::Finalize() { + D_ASSERT(root_data.size() == types.size()); + auto root_holder = make_unique(); + + ArrowArray result; + root_holder->child_pointers.resize(types.size()); + result.children = root_holder->child_pointers.data(); + result.n_children = types.size(); + + // Configure root array + result.length = row_count; + result.n_children = types.size(); + result.n_buffers = 1; + result.buffers = root_holder->buffers.data(); // there is no actual buffer there since we don't have NULLs + result.offset = 0; + result.null_count = 0; // needs to be 0 + result.dictionary = nullptr; + root_holder->child_data = move(root_data); + + for (idx_t i = 0; i < root_holder->child_data.size(); i++) { + root_holder->child_pointers[i] = FinalizeArrowChild(types[i], *root_holder->child_data[i]); + } + + // Release ownership to caller + result.private_data = root_holder.release(); + result.release = ReleaseDuckDBArrowAppendArray; + return result; } } // namespace duckdb @@ -8810,10 +10047,358 @@ data_ptr_t Allocator::ReallocateData(data_ptr_t pointer, idx_t size) { + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/types/sel_cache.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +//! Selection vector cache used for caching vector slices +struct SelCache { + unordered_map> cache; +}; + +} // namespace duckdb + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/result_arrow_wrapper.hpp +// duckdb/common/types/vector_cache.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + +namespace duckdb { +class Allocator; +class Vector; + +//! The VectorCache holds cached data that allows for re-use of the same memory by vectors +class VectorCache { +public: + //! Instantiate a vector cache with the given type + DUCKDB_API explicit VectorCache(Allocator &allocator, const LogicalType &type); + + buffer_ptr buffer; + +public: + void ResetFromCache(Vector &result) const; + + const LogicalType &GetType() const; +}; + +} // namespace duckdb + + + +#include + + +namespace duckdb { + +void ArrowConverter::ToArrowArray(DataChunk &input, ArrowArray *out_array) { + ArrowAppender appender(input.GetTypes(), input.size()); + appender.Append(input); + *out_array = appender.Finalize(); +} + +//===--------------------------------------------------------------------===// +// Arrow Schema +//===--------------------------------------------------------------------===// +struct DuckDBArrowSchemaHolder { + // unused in children + vector children; + // unused in children + vector children_ptrs; + //! used for nested structures + std::list> nested_children; + std::list> nested_children_ptr; + //! This holds strings created to represent decimal types + vector> owned_type_names; +}; + +static void ReleaseDuckDBArrowSchema(ArrowSchema *schema) { + if (!schema || !schema->release) { + return; + } + schema->release = nullptr; + auto holder = static_cast(schema->private_data); + delete holder; +} + +void InitializeChild(ArrowSchema &child, const string &name = "") { + //! Child is cleaned up by parent + child.private_data = nullptr; + child.release = ReleaseDuckDBArrowSchema; + + //! Store the child schema + child.flags = ARROW_FLAG_NULLABLE; + child.name = name.c_str(); + child.n_children = 0; + child.children = nullptr; + child.metadata = nullptr; + child.dictionary = nullptr; +} +void SetArrowFormat(DuckDBArrowSchemaHolder &root_holder, ArrowSchema &child, const LogicalType &type, + string &config_timezone); + +void SetArrowMapFormat(DuckDBArrowSchemaHolder &root_holder, ArrowSchema &child, const LogicalType &type, + string &config_timezone) { + child.format = "+m"; + //! Map has one child which is a struct + child.n_children = 1; + root_holder.nested_children.emplace_back(); + root_holder.nested_children.back().resize(1); + root_holder.nested_children_ptr.emplace_back(); + root_holder.nested_children_ptr.back().push_back(&root_holder.nested_children.back()[0]); + InitializeChild(root_holder.nested_children.back()[0]); + child.children = &root_holder.nested_children_ptr.back()[0]; + child.children[0]->name = "entries"; + child_list_t struct_child_types; + struct_child_types.push_back(std::make_pair("key", ListType::GetChildType(StructType::GetChildType(type, 0)))); + struct_child_types.push_back(std::make_pair("value", ListType::GetChildType(StructType::GetChildType(type, 1)))); + auto struct_type = LogicalType::STRUCT(move(struct_child_types)); + SetArrowFormat(root_holder, *child.children[0], struct_type, config_timezone); +} + +void SetArrowFormat(DuckDBArrowSchemaHolder &root_holder, ArrowSchema &child, const LogicalType &type, + string &config_timezone) { + switch (type.id()) { + case LogicalTypeId::BOOLEAN: + child.format = "b"; + break; + case LogicalTypeId::TINYINT: + child.format = "c"; + break; + case LogicalTypeId::SMALLINT: + child.format = "s"; + break; + case LogicalTypeId::INTEGER: + child.format = "i"; + break; + case LogicalTypeId::BIGINT: + child.format = "l"; + break; + case LogicalTypeId::UTINYINT: + child.format = "C"; + break; + case LogicalTypeId::USMALLINT: + child.format = "S"; + break; + case LogicalTypeId::UINTEGER: + child.format = "I"; + break; + case LogicalTypeId::UBIGINT: + child.format = "L"; + break; + case LogicalTypeId::FLOAT: + child.format = "f"; + break; + case LogicalTypeId::HUGEINT: + child.format = "d:38,0"; + break; + case LogicalTypeId::DOUBLE: + child.format = "g"; + break; + case LogicalTypeId::UUID: + case LogicalTypeId::JSON: + case LogicalTypeId::VARCHAR: + child.format = "u"; + break; + case LogicalTypeId::DATE: + child.format = "tdD"; + break; + case LogicalTypeId::TIME: + case LogicalTypeId::TIME_TZ: + child.format = "ttu"; + break; + case LogicalTypeId::TIMESTAMP: + child.format = "tsu:"; + break; + case LogicalTypeId::TIMESTAMP_TZ: { + string format = "tsu:" + config_timezone; + unique_ptr format_ptr = unique_ptr(new char[format.size() + 1]); + for (size_t i = 0; i < format.size(); i++) { + format_ptr[i] = format[i]; + } + format_ptr[format.size()] = '\0'; + root_holder.owned_type_names.push_back(move(format_ptr)); + child.format = root_holder.owned_type_names.back().get(); + break; + } + case LogicalTypeId::TIMESTAMP_SEC: + child.format = "tss:"; + break; + case LogicalTypeId::TIMESTAMP_NS: + child.format = "tsn:"; + break; + case LogicalTypeId::TIMESTAMP_MS: + child.format = "tsm:"; + break; + case LogicalTypeId::INTERVAL: + child.format = "tDm"; + break; + case LogicalTypeId::DECIMAL: { + uint8_t width, scale; + type.GetDecimalProperties(width, scale); + string format = "d:" + to_string(width) + "," + to_string(scale); + unique_ptr format_ptr = unique_ptr(new char[format.size() + 1]); + for (size_t i = 0; i < format.size(); i++) { + format_ptr[i] = format[i]; + } + format_ptr[format.size()] = '\0'; + root_holder.owned_type_names.push_back(move(format_ptr)); + child.format = root_holder.owned_type_names.back().get(); + break; + } + case LogicalTypeId::SQLNULL: { + child.format = "n"; + break; + } + case LogicalTypeId::BLOB: { + child.format = "z"; + break; + } + case LogicalTypeId::LIST: { + child.format = "+l"; + child.n_children = 1; + root_holder.nested_children.emplace_back(); + root_holder.nested_children.back().resize(1); + root_holder.nested_children_ptr.emplace_back(); + root_holder.nested_children_ptr.back().push_back(&root_holder.nested_children.back()[0]); + InitializeChild(root_holder.nested_children.back()[0]); + child.children = &root_holder.nested_children_ptr.back()[0]; + child.children[0]->name = "l"; + SetArrowFormat(root_holder, **child.children, ListType::GetChildType(type), config_timezone); + break; + } + case LogicalTypeId::STRUCT: { + child.format = "+s"; + auto &child_types = StructType::GetChildTypes(type); + child.n_children = child_types.size(); + root_holder.nested_children.emplace_back(); + root_holder.nested_children.back().resize(child_types.size()); + root_holder.nested_children_ptr.emplace_back(); + root_holder.nested_children_ptr.back().resize(child_types.size()); + for (idx_t type_idx = 0; type_idx < child_types.size(); type_idx++) { + root_holder.nested_children_ptr.back()[type_idx] = &root_holder.nested_children.back()[type_idx]; + } + child.children = &root_holder.nested_children_ptr.back()[0]; + for (size_t type_idx = 0; type_idx < child_types.size(); type_idx++) { + + InitializeChild(*child.children[type_idx]); + + auto &struct_col_name = child_types[type_idx].first; + unique_ptr name_ptr = unique_ptr(new char[struct_col_name.size() + 1]); + for (size_t i = 0; i < struct_col_name.size(); i++) { + name_ptr[i] = struct_col_name[i]; + } + name_ptr[struct_col_name.size()] = '\0'; + root_holder.owned_type_names.push_back(move(name_ptr)); + + child.children[type_idx]->name = root_holder.owned_type_names.back().get(); + SetArrowFormat(root_holder, *child.children[type_idx], child_types[type_idx].second, config_timezone); + } + break; + } + case LogicalTypeId::MAP: { + SetArrowMapFormat(root_holder, child, type, config_timezone); + break; + } + case LogicalTypeId::ENUM: { + // TODO what do we do with pointer enums here? + switch (EnumType::GetPhysicalType(type)) { + case PhysicalType::UINT8: + child.format = "C"; + break; + case PhysicalType::UINT16: + child.format = "S"; + break; + case PhysicalType::UINT32: + child.format = "I"; + break; + default: + throw InternalException("Unsupported Enum Internal Type"); + } + root_holder.nested_children.emplace_back(); + root_holder.nested_children.back().resize(1); + root_holder.nested_children_ptr.emplace_back(); + root_holder.nested_children_ptr.back().push_back(&root_holder.nested_children.back()[0]); + InitializeChild(root_holder.nested_children.back()[0]); + child.dictionary = root_holder.nested_children_ptr.back()[0]; + child.dictionary->format = "u"; + break; + } + default: + throw InternalException("Unsupported Arrow type " + type.ToString()); + } +} + +void ArrowConverter::ToArrowSchema(ArrowSchema *out_schema, vector &types, vector &names, + string &config_timezone) { + D_ASSERT(out_schema); + D_ASSERT(types.size() == names.size()); + idx_t column_count = types.size(); + // Allocate as unique_ptr first to cleanup properly on error + auto root_holder = make_unique(); + + // Allocate the children + root_holder->children.resize(column_count); + root_holder->children_ptrs.resize(column_count, nullptr); + for (size_t i = 0; i < column_count; ++i) { + root_holder->children_ptrs[i] = &root_holder->children[i]; + } + out_schema->children = root_holder->children_ptrs.data(); + out_schema->n_children = column_count; + + // Store the schema + out_schema->format = "+s"; // struct apparently + out_schema->flags = 0; + out_schema->metadata = nullptr; + out_schema->name = "duckdb_query_result"; + out_schema->dictionary = nullptr; + + // Configure all child schemas + for (idx_t col_idx = 0; col_idx < column_count; col_idx++) { + + auto &child = root_holder->children[col_idx]; + InitializeChild(child, names[col_idx]); + SetArrowFormat(*root_holder, child, types[col_idx], config_timezone); + } + + // Release ownership to caller + out_schema->private_data = root_holder.release(); + out_schema->release = ReleaseDuckDBArrowSchema; +} + +} // namespace duckdb + + + + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/arrow/result_arrow_wrapper.hpp // // //===----------------------------------------------------------------------===// @@ -8829,7 +10414,7 @@ class ResultArrowArrayStreamWrapper { explicit ResultArrowArrayStreamWrapper(unique_ptr result, idx_t batch_size); ArrowArrayStream stream; unique_ptr result; - std::string last_error; + PreservedError last_error; idx_t batch_size; vector column_types; vector column_names; @@ -8844,6 +10429,8 @@ class ResultArrowArrayStreamWrapper { } // namespace duckdb + + namespace duckdb { ArrowSchemaWrapper::~ArrowSchemaWrapper() { @@ -8913,19 +10500,20 @@ int ResultArrowArrayStreamWrapper::MyStreamGetSchema(struct ArrowArrayStream *st } auto my_stream = (ResultArrowArrayStreamWrapper *)stream->private_data; if (!my_stream->column_types.empty()) { - QueryResult::ToArrowSchema(out, my_stream->column_types, my_stream->column_names, my_stream->timezone_config); + ArrowConverter::ToArrowSchema(out, my_stream->column_types, my_stream->column_names, + my_stream->timezone_config); return 0; } auto &result = *my_stream->result; - if (!result.success) { - my_stream->last_error = "Query Failed"; + if (result.HasError()) { + my_stream->last_error = result.GetErrorObject(); return -1; } if (result.type == QueryResultType::STREAM_RESULT) { auto &stream_result = (StreamQueryResult &)result; if (!stream_result.IsOpen()) { - my_stream->last_error = "Query Stream is closed"; + my_stream->last_error = PreservedError("Query Stream is closed"); return -1; } } @@ -8933,7 +10521,7 @@ int ResultArrowArrayStreamWrapper::MyStreamGetSchema(struct ArrowArrayStream *st my_stream->column_types = result.types; my_stream->column_names = result.names; } - QueryResult::ToArrowSchema(out, my_stream->column_types, my_stream->column_names, my_stream->timezone_config); + ArrowConverter::ToArrowSchema(out, my_stream->column_types, my_stream->column_names, my_stream->timezone_config); return 0; } @@ -8943,8 +10531,8 @@ int ResultArrowArrayStreamWrapper::MyStreamGetNext(struct ArrowArrayStream *stre } auto my_stream = (ResultArrowArrayStreamWrapper *)stream->private_data; auto &result = *my_stream->result; - if (!result.success) { - my_stream->last_error = "Query Failed"; + if (result.HasError()) { + my_stream->last_error = result.GetErrorObject(); return -1; } if (result.type == QueryResultType::STREAM_RESULT) { @@ -8959,25 +10547,17 @@ int ResultArrowArrayStreamWrapper::MyStreamGetNext(struct ArrowArrayStream *stre my_stream->column_types = result.types; my_stream->column_names = result.names; } - unique_ptr chunk_result = result.Fetch(); - if (!chunk_result) { + idx_t result_count; + PreservedError error; + if (!ArrowUtil::TryFetchChunk(&result, my_stream->batch_size, out, result_count, error)) { + D_ASSERT(error); + my_stream->last_error = error; + return -1; + } + if (result_count == 0) { // Nothing to output out->release = nullptr; - return 0; - } - unique_ptr agg_chunk_result = make_unique(); - agg_chunk_result->Initialize(chunk_result->GetTypes()); - agg_chunk_result->Append(*chunk_result, true); - - while (agg_chunk_result->size() < my_stream->batch_size) { - auto new_chunk = result.Fetch(); - if (!new_chunk) { - break; - } else { - agg_chunk_result->Append(*new_chunk, true); - } } - agg_chunk_result->ToArrowArray(out); return 0; } @@ -8995,8 +10575,9 @@ const char *ResultArrowArrayStreamWrapper::MyStreamGetLastError(struct ArrowArra } D_ASSERT(stream->private_data); auto my_stream = (ResultArrowArrayStreamWrapper *)stream->private_data; - return my_stream->last_error.c_str(); + return my_stream->last_error.Message().c_str(); } + ResultArrowArrayStreamWrapper::ResultArrowArrayStreamWrapper(unique_ptr result_p, idx_t batch_size_p) : result(move(result_p)) { //! We first initialize the private data of the stream @@ -9013,33 +10594,53 @@ ResultArrowArrayStreamWrapper::ResultArrowArrayStreamWrapper(unique_ptr ArrowUtil::FetchNext(QueryResult &result) { - auto chunk = result.Fetch(); - if (!result.success) { - throw std::runtime_error(result.error); +bool ArrowUtil::TryFetchNext(QueryResult &result, unique_ptr &chunk, PreservedError &error) { + if (result.type == QueryResultType::STREAM_RESULT) { + auto &stream_result = (StreamQueryResult &)result; + if (!stream_result.IsOpen()) { + return true; + } } - return chunk; + return result.TryFetch(chunk, error); } -unique_ptr ArrowUtil::FetchChunk(QueryResult *result, idx_t chunk_size) { - - auto data_chunk = FetchNext(*result); - if (!data_chunk) { - return data_chunk; - } - while (data_chunk->size() < chunk_size) { - auto next_chunk = FetchNext(*result); - if (!next_chunk || next_chunk->size() == 0) { +bool ArrowUtil::TryFetchChunk(QueryResult *result, idx_t chunk_size, ArrowArray *out, idx_t &count, + PreservedError &error) { + count = 0; + ArrowAppender appender(result->types, chunk_size); + while (count < chunk_size) { + unique_ptr data_chunk; + if (!TryFetchNext(*result, data_chunk, error)) { + if (result->HasError()) { + error = result->GetErrorObject(); + } + return false; + } + if (!data_chunk || data_chunk->size() == 0) { break; } - data_chunk->Append(*next_chunk, true); + count += data_chunk->size(); + appender.Append(*data_chunk); } - return data_chunk; + if (count > 0) { + *out = appender.Finalize(); + } + return true; +} + +idx_t ArrowUtil::FetchChunk(QueryResult *result, idx_t chunk_size, ArrowArray *out) { + PreservedError error; + idx_t result_count; + if (!TryFetchChunk(result, chunk_size, out, result_count, error)) { + error.Throw(); + } + return result_count; } } // namespace duckdb + namespace duckdb { void DuckDBAssertInternal(bool condition, const char *condition_name, const char *file, int linenr) { @@ -9073,13 +10674,17 @@ uint64_t Checksum(uint8_t *buffer, size_t size); namespace duckdb { +hash_t Checksum(uint64_t x) { + return x * UINT64_C(0xbf58476d1ce4e5b9); +} + uint64_t Checksum(uint8_t *buffer, size_t size) { uint64_t result = 5381; uint64_t *ptr = (uint64_t *)buffer; size_t i; - // for efficiency, we first hash uint64_t values + // for efficiency, we first checksum uint64_t values for (i = 0; i < size / 8; i++) { - result ^= Hash(ptr[i]); + result ^= Checksum(ptr[i]); } if (size - i * 8 > 0) { // the remaining 0-7 bytes we hash using a string hash @@ -9329,6 +10934,10 @@ uint64_t NextPowerOfTwo(uint64_t v) { return v; } +bool IsRowIdColumnId(column_t column_id) { + return column_id == COLUMN_IDENTIFIER_ROW_ID; +} + } // namespace duckdb /* ** This code taken from the SQLite test library. Originally found on @@ -9726,6 +11335,7 @@ uint64_t CycleCounter::Tick() const { + namespace duckdb { // LCOV_EXCL_START @@ -10064,6 +11674,87 @@ ExpressionType OperatorToExpressionType(const string &op) { return ExpressionType::INVALID; } +string ExpressionClassToString(ExpressionClass type) { + switch (type) { + case ExpressionClass::INVALID: + return "INVALID"; + case ExpressionClass::AGGREGATE: + return "AGGREGATE"; + case ExpressionClass::CASE: + return "CASE"; + case ExpressionClass::CAST: + return "CAST"; + case ExpressionClass::COLUMN_REF: + return "COLUMN_REF"; + case ExpressionClass::COMPARISON: + return "COMPARISON"; + case ExpressionClass::CONJUNCTION: + return "CONJUNCTION"; + case ExpressionClass::CONSTANT: + return "CONSTANT"; + case ExpressionClass::DEFAULT: + return "DEFAULT"; + case ExpressionClass::FUNCTION: + return "FUNCTION"; + case ExpressionClass::OPERATOR: + return "OPERATOR"; + case ExpressionClass::STAR: + return "STAR"; + case ExpressionClass::SUBQUERY: + return "SUBQUERY"; + case ExpressionClass::WINDOW: + return "WINDOW"; + case ExpressionClass::PARAMETER: + return "PARAMETER"; + case ExpressionClass::COLLATE: + return "COLLATE"; + case ExpressionClass::LAMBDA: + return "LAMBDA"; + case ExpressionClass::POSITIONAL_REFERENCE: + return "POSITIONAL_REFERENCE"; + case ExpressionClass::BETWEEN: + return "BETWEEN"; + case ExpressionClass::BOUND_AGGREGATE: + return "BOUND_AGGREGATE"; + case ExpressionClass::BOUND_CASE: + return "BOUND_CASE"; + case ExpressionClass::BOUND_CAST: + return "BOUND_CAST"; + case ExpressionClass::BOUND_COLUMN_REF: + return "BOUND_COLUMN_REF"; + case ExpressionClass::BOUND_COMPARISON: + return "BOUND_COMPARISON"; + case ExpressionClass::BOUND_CONJUNCTION: + return "BOUND_CONJUNCTION"; + case ExpressionClass::BOUND_CONSTANT: + return "BOUND_CONSTANT"; + case ExpressionClass::BOUND_DEFAULT: + return "BOUND_DEFAULT"; + case ExpressionClass::BOUND_FUNCTION: + return "BOUND_FUNCTION"; + case ExpressionClass::BOUND_OPERATOR: + return "BOUND_OPERATOR"; + case ExpressionClass::BOUND_PARAMETER: + return "BOUND_PARAMETER"; + case ExpressionClass::BOUND_REF: + return "BOUND_REF"; + case ExpressionClass::BOUND_SUBQUERY: + return "BOUND_SUBQUERY"; + case ExpressionClass::BOUND_WINDOW: + return "BOUND_WINDOW"; + case ExpressionClass::BOUND_BETWEEN: + return "BOUND_BETWEEN"; + case ExpressionClass::BOUND_UNNEST: + return "BOUND_UNNEST"; + case ExpressionClass::BOUND_LAMBDA: + return "BOUND_LAMBDA"; + case ExpressionClass::BOUND_EXPRESSION: + return "BOUND_EXPRESSION"; + default: + return "ExpressionClass::!!UNIMPLEMENTED_CASE!!"; + } +} + } // namespace duckdb @@ -10268,6 +11959,7 @@ static DefaultOptimizerType internal_optimizer_types[] = { {"column_lifetime", OptimizerType::COLUMN_LIFETIME}, {"top_n", OptimizerType::TOP_N}, {"reorder_filter", OptimizerType::REORDER_FILTER}, + {"extension", OptimizerType::EXTENSION}, {nullptr, OptimizerType::INVALID}}; string OptimizerTypeToString(OptimizerType type) { @@ -10308,6 +12000,8 @@ string PhysicalOperatorToString(PhysicalOperatorType type) { return "DUMMY_SCAN"; case PhysicalOperatorType::CHUNK_SCAN: return "CHUNK_SCAN"; + case PhysicalOperatorType::COLUMN_DATA_SCAN: + return "COLUMN_DATA_SCAN"; case PhysicalOperatorType::DELIM_SCAN: return "DELIM_SCAN"; case PhysicalOperatorType::ORDER_BY: @@ -10330,8 +12024,8 @@ string PhysicalOperatorToString(PhysicalOperatorType type) { return "STREAMING_WINDOW"; case PhysicalOperatorType::UNNEST: return "UNNEST"; - case PhysicalOperatorType::SIMPLE_AGGREGATE: - return "SIMPLE_AGGREGATE"; + case PhysicalOperatorType::UNGROUPED_AGGREGATE: + return "UNGROUPED_AGGREGATE"; case PhysicalOperatorType::HASH_GROUP_BY: return "HASH_GROUP_BY"; case PhysicalOperatorType::PERFECT_HASH_GROUP_BY: @@ -10542,6 +12236,10 @@ string StatementTypeToString(StatementType type) { return "SET"; case StatementType::LOAD_STATEMENT: return "LOAD"; + case StatementType::EXTENSION_STATEMENT: + return "EXTENSION"; + case StatementType::LOGICAL_PLAN_STATEMENT: + return "LOGICAL_PLAN"; case StatementType::INVALID_STATEMENT: break; } @@ -10568,13 +12266,20 @@ string StatementReturnTypeToString(StatementReturnType type) { +#ifdef DUCKDB_CRASH_ON_ASSERT + +#include +#include +#endif + namespace duckdb { -Exception::Exception(const string &msg) : std::exception(), type(ExceptionType::INVALID) { +Exception::Exception(const string &msg) : std::exception(), type(ExceptionType::INVALID), raw_message_(msg) { exception_message_ = msg; } -Exception::Exception(ExceptionType exception_type, const string &message) : std::exception(), type(exception_type) { +Exception::Exception(ExceptionType exception_type, const string &message) + : std::exception(), type(exception_type), raw_message_(message) { exception_message_ = ExceptionTypeToString(exception_type) + " Error: " + message; } @@ -10582,6 +12287,10 @@ const char *Exception::what() const noexcept { return exception_message_.c_str(); } +const string &Exception::RawMessage() const { + return raw_message_; +} + bool Exception::UncaughtException() { #if __cplusplus >= 201703L return std::uncaught_exceptions() > 0; @@ -10664,11 +12373,64 @@ string Exception::ExceptionTypeToString(ExceptionType type) { return "Out of Memory"; case ExceptionType::PERMISSION: return "Permission"; + case ExceptionType::PARAMETER_NOT_RESOLVED: + return "Parameter Not Resolved"; + case ExceptionType::PARAMETER_NOT_ALLOWED: + return "Parameter Not Allowed"; default: return "Unknown"; } } +void Exception::ThrowAsTypeWithMessage(ExceptionType type, const string &message) { + switch (type) { + case ExceptionType::OUT_OF_RANGE: + throw OutOfRangeException(message); + case ExceptionType::CONVERSION: + throw ConversionException(message); // FIXME: make a separation between Conversion/Cast exception? + case ExceptionType::INVALID_TYPE: + throw InvalidTypeException(message); + case ExceptionType::MISMATCH_TYPE: + throw TypeMismatchException(message); + case ExceptionType::TRANSACTION: + throw TransactionException(message); + case ExceptionType::NOT_IMPLEMENTED: + throw NotImplementedException(message); + case ExceptionType::CATALOG: + throw CatalogException(message); + case ExceptionType::CONNECTION: + throw ConnectionException(message); + case ExceptionType::PARSER: + throw ParserException(message); + case ExceptionType::PERMISSION: + throw PermissionException(message); + case ExceptionType::SYNTAX: + throw SyntaxException(message); + case ExceptionType::CONSTRAINT: + throw ConstraintException(message); + case ExceptionType::BINDER: + throw BinderException(message); + case ExceptionType::IO: + throw IOException(message); + case ExceptionType::SERIALIZATION: + throw SerializationException(message); + case ExceptionType::INTERRUPT: + throw InterruptException(); + case ExceptionType::INTERNAL: + throw InternalException(message); + case ExceptionType::INVALID_INPUT: + throw InvalidInputException(message); + case ExceptionType::OUT_OF_MEMORY: + throw OutOfMemoryException(message); + case ExceptionType::PARAMETER_NOT_ALLOWED: + throw ParameterNotAllowedException(message); + case ExceptionType::PARAMETER_NOT_RESOLVED: + throw ParameterNotResolvedException(); + default: + throw Exception(type, message); + } +} + StandardException::StandardException(ExceptionType exception_type, const string &message) : Exception(exception_type, message) { } @@ -10683,6 +12445,9 @@ CastException::CastException(const LogicalType &orig_type, const LogicalType &ne "Type " + orig_type.ToString() + " can't be cast as " + new_type.ToString()) { } +CastException::CastException(const string &msg) : Exception(ExceptionType::CONVERSION, msg) { +} + ValueOutOfRangeException::ValueOutOfRangeException(const int64_t value, const PhysicalType orig_type, const PhysicalType new_type) : Exception(ExceptionType::CONVERSION, "Type " + TypeIdToString(orig_type) + " with value " + @@ -10713,6 +12478,9 @@ ValueOutOfRangeException::ValueOutOfRangeException(const PhysicalType var_type, "The value is too long to fit into type " + TypeIdToString(var_type) + "(" + to_string(length) + ")") { } +ValueOutOfRangeException::ValueOutOfRangeException(const string &msg) : Exception(ExceptionType::OUT_OF_RANGE, msg) { +} + ConversionException::ConversionException(const string &msg) : Exception(ExceptionType::CONVERSION, msg) { } @@ -10724,6 +12492,9 @@ InvalidTypeException::InvalidTypeException(const LogicalType &type, const string : Exception(ExceptionType::INVALID_TYPE, "Invalid Type [" + type.ToString() + "]: " + msg) { } +InvalidTypeException::InvalidTypeException(const string &msg) : Exception(ExceptionType::INVALID_TYPE, msg) { +} + TypeMismatchException::TypeMismatchException(const PhysicalType type_1, const PhysicalType type_2, const string &msg) : Exception(ExceptionType::MISMATCH_TYPE, "Type " + TypeIdToString(type_1) + " does not match with " + TypeIdToString(type_2) + ". " + msg) { @@ -10734,6 +12505,9 @@ TypeMismatchException::TypeMismatchException(const LogicalType &type_1, const Lo "Type " + type_1.ToString() + " does not match with " + type_2.ToString() + ". " + msg) { } +TypeMismatchException::TypeMismatchException(const string &msg) : Exception(ExceptionType::MISMATCH_TYPE, msg) { +} + TransactionException::TransactionException(const string &msg) : Exception(ExceptionType::TRANSACTION, msg) { } @@ -10746,6 +12520,9 @@ OutOfRangeException::OutOfRangeException(const string &msg) : Exception(Exceptio CatalogException::CatalogException(const string &msg) : StandardException(ExceptionType::CATALOG, msg) { } +ConnectionException::ConnectionException(const string &msg) : StandardException(ExceptionType::CONNECTION, msg) { +} + ParserException::ParserException(const string &msg) : StandardException(ExceptionType::PARSER, msg) { } @@ -10773,10 +12550,14 @@ SequenceException::SequenceException(const string &msg) : Exception(ExceptionTyp InterruptException::InterruptException() : Exception(ExceptionType::INTERRUPT, "Interrupted!") { } -FatalException::FatalException(const string &msg) : Exception(ExceptionType::FATAL, msg) { +FatalException::FatalException(ExceptionType type, const string &msg) : Exception(type, msg) { } -InternalException::InternalException(const string &msg) : Exception(ExceptionType::INTERNAL, msg) { +InternalException::InternalException(const string &msg) : FatalException(ExceptionType::INTERNAL, msg) { +#ifdef DUCKDB_CRASH_ON_ASSERT + Printer::Print("ABORT THROWN BY INTERNAL EXCEPTION: " + msg); + abort(); +#endif } InvalidInputException::InvalidInputException(const string &msg) : Exception(ExceptionType::INVALID_INPUT, msg) { @@ -10785,13 +12566,21 @@ InvalidInputException::InvalidInputException(const string &msg) : Exception(Exce OutOfMemoryException::OutOfMemoryException(const string &msg) : Exception(ExceptionType::OUT_OF_MEMORY, msg) { } +ParameterNotAllowedException::ParameterNotAllowedException(const string &msg) + : StandardException(ExceptionType::PARAMETER_NOT_ALLOWED, msg) { +} + +ParameterNotResolvedException::ParameterNotResolvedException() + : Exception(ExceptionType::PARAMETER_NOT_RESOLVED, "Parameter types could not be resolved") { +} + } // namespace duckdb // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2 // See the end of this file for a list /* @@ -10833,7 +12622,7 @@ OutOfMemoryException::OutOfMemoryException(const string &msg) : Exception(Except // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2 // See the end of this file for a list // Formatting library for C++ - the core API @@ -15617,7 +17406,7 @@ FMT_END_NAMESPACE // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2 // See the end of this file for a list // Formatting library for C++ - legacy printf implementation @@ -15636,7 +17425,7 @@ FMT_END_NAMESPACE // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2 // See the end of this file for a list // Formatting library for C++ - std::ostream support @@ -16569,6 +18358,7 @@ namespace duckdb { //===--------------------------------------------------------------------===// FieldWriter::FieldWriter(Serializer &serializer_p) : serializer(serializer_p), buffer(make_unique()), field_count(0), finalized(false) { + buffer->SetVersion(serializer.GetVersion()); } FieldWriter::~FieldWriter() { @@ -16608,6 +18398,7 @@ void FieldWriter::Finalize() { // Field Deserializer //===--------------------------------------------------------------------===// FieldDeserializer::FieldDeserializer(Deserializer &root) : root(root), remaining_data(idx_t(-1)) { + SetVersion(root.GetVersion()); } void FieldDeserializer::ReadData(data_ptr_t buffer, idx_t read_size) { @@ -16691,6 +18482,9 @@ FileBuffer::FileBuffer(FileBuffer &source, FileBufferType type_p) : allocator(so } FileBuffer::~FileBuffer() { + if (!malloced_buffer) { + return; + } allocator.FreeData(malloced_buffer, malloced_size); } @@ -16699,51 +18493,24 @@ void FileBuffer::SetMallocedSize(uint64_t &bufsiz) { if (type == FileBufferType::MANAGED_BUFFER && bufsiz != Storage::FILE_HEADER_SIZE) { bufsiz += Storage::BLOCK_HEADER_SIZE; } - if (type == FileBufferType::BLOCK) { - const int sector_size = Storage::SECTOR_SIZE; - // round up to the nearest sector_size - if (bufsiz % sector_size != 0) { - bufsiz += sector_size - (bufsiz % sector_size); - } - D_ASSERT(bufsiz % sector_size == 0); - D_ASSERT(bufsiz >= sector_size); - // we add (sector_size - 1) to ensure that we can align the buffer to sector_size - malloced_size = bufsiz + (sector_size - 1); - } else { - malloced_size = bufsiz; - } + malloced_size = bufsiz; } void FileBuffer::Construct(uint64_t bufsiz) { if (!malloced_buffer) { throw std::bad_alloc(); } - if (type == FileBufferType::BLOCK) { - const int sector_size = Storage::SECTOR_SIZE; - // round to multiple of sector_size - uint64_t num = (uint64_t)malloced_buffer; - uint64_t remainder = num % sector_size; - if (remainder != 0) { - num = num + sector_size - remainder; - } - D_ASSERT(num % sector_size == 0); - D_ASSERT(num + bufsiz <= ((uint64_t)malloced_buffer + bufsiz + (sector_size - 1))); - D_ASSERT(num >= (uint64_t)malloced_buffer); - // construct the FileBuffer object - internal_buffer = (data_ptr_t)num; - internal_size = bufsiz; - } else { - internal_buffer = malloced_buffer; - internal_size = malloced_size; - } + internal_buffer = malloced_buffer; + internal_size = malloced_size; buffer = internal_buffer + Storage::BLOCK_HEADER_SIZE; size = internal_size - Storage::BLOCK_HEADER_SIZE; } void FileBuffer::Resize(uint64_t bufsiz) { D_ASSERT(type == FileBufferType::MANAGED_BUFFER); + auto old_size = malloced_size; SetMallocedSize(bufsiz); - malloced_buffer = allocator.ReallocateData(malloced_buffer, malloced_size); + malloced_buffer = allocator.ReallocateData(malloced_buffer, old_size, malloced_size); Construct(bufsiz); } @@ -16785,6 +18552,32 @@ void FileBuffer::Clear() { +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/file_opener.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { + +class Value; + +//! Abstract type that provide client-specific context to FileSystem. +class FileOpener { +public: + virtual ~FileOpener() {}; + + virtual bool TryGetCurrentSetting(const string &key, Value &result) = 0; +}; + +} // namespace duckdb + @@ -16806,6 +18599,7 @@ void FileBuffer::Clear() { #undef RemoveDirectory #endif + //===----------------------------------------------------------------------===// // DuckDB // @@ -16820,7 +18614,7 @@ void FileBuffer::Clear() { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3 // See the end of this file for a list /* @@ -17759,6 +19553,10 @@ struct JaccardFun { static void RegisterFunction(BuiltinFunctions &set); }; +struct JaroWinklerFun { + static void RegisterFunction(BuiltinFunctions &set); +}; + } // namespace duckdb @@ -17777,6 +19575,7 @@ struct JaccardFun { #include #else #include +#include #ifdef __MINGW32__ // need to manually define this for mingw @@ -17814,7 +19613,7 @@ idx_t FileSystem::GetAvailableMemory() { errno = 0; idx_t max_memory = MinValue((idx_t)sysconf(_SC_PHYS_PAGES) * (idx_t)sysconf(_SC_PAGESIZE), UINTPTR_MAX); if (errno != 0) { - throw IOException("Could not fetch available system memory!"); + return DConstants::INVALID_INDEX; } return max_memory; } @@ -17841,10 +19640,17 @@ void FileSystem::SetWorkingDirectory(const string &path) { idx_t FileSystem::GetAvailableMemory() { ULONGLONG available_memory_kb; - if (!GetPhysicallyInstalledSystemMemory(&available_memory_kb)) { - throw IOException("Could not fetch available system memory!"); + if (GetPhysicallyInstalledSystemMemory(&available_memory_kb)) { + return MinValue(available_memory_kb * 1000, UINTPTR_MAX); } - return MinValue(available_memory_kb * 1024, UINTPTR_MAX); + // fallback: try GlobalMemoryStatusEx + MEMORYSTATUSEX mem_state; + mem_state.dwLength = sizeof(MEMORYSTATUSEX); + + if (GlobalMemoryStatusEx(&mem_state)) { + return MinValue(mem_state.ullTotalPhys, UINTPTR_MAX); + } + return DConstants::INVALID_INDEX; } string FileSystem::GetWorkingDirectory() { @@ -17891,7 +19697,17 @@ string FileSystem::ExtractBaseName(const string &path) { return vec[0]; } -string FileSystem::GetHomeDirectory() { +string FileSystem::GetHomeDirectory(FileOpener *opener) { + // read the home_directory setting first, if it is set + if (opener) { + Value result; + if (opener->TryGetCurrentSetting("home_directory", result)) { + if (!result.IsNull() && !result.ToString().empty()) { + return result.ToString(); + } + } + } + // fallback to the default home directories for the specified system #ifdef DUCKDB_WINDOWS const char *homedir = getenv("USERPROFILE"); #else @@ -17903,6 +19719,16 @@ string FileSystem::GetHomeDirectory() { return string(); } +string FileSystem::ExpandPath(const string &path, FileOpener *opener) { + if (path.empty()) { + return path; + } + if (path[0] == '~') { + return GetHomeDirectory(opener) + path.substr(1); + } + return path; +} + // LCOV_EXCL_START unique_ptr FileSystem::OpenFile(const string &path, uint8_t flags, FileLockType lock, FileCompressionType compression, FileOpener *opener) { @@ -18152,7 +19978,7 @@ static constexpr const unsigned char GZIP_FLAG_UNSUPPORTED = // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #4 // See the end of this file for a list /* miniz.c 2.0.8 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing @@ -19450,7 +21276,7 @@ void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const ch // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #4 // See the end of this file for a list //===----------------------------------------------------------------------===// @@ -19928,156 +21754,165 @@ idx_t GZipFileSystem::OutBufferSize() { } } // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/hive_partitioning.hpp +// +// +//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/windows_undefs.hpp +// duckdb/optimizer/statistics_propagator.hpp // // //===----------------------------------------------------------------------===// -#ifdef WIN32 -#ifdef min -#undef min -#endif -#ifdef max -#undef max -#endif -#ifdef ERROR -#undef ERROR -#endif -#ifdef small -#undef small -#endif +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/column_binding_map.hpp +// +// +//===----------------------------------------------------------------------===// + + -#ifdef CreateDirectory -#undef CreateDirectory -#endif -#ifdef MoveFile -#undef MoveFile -#endif -#ifdef RemoveDirectory -#undef RemoveDirectory -#endif -#endif -#include namespace duckdb { -using std::numeric_limits; +struct ColumnBindingHashFunction { + uint64_t operator()(const ColumnBinding &a) const { + return CombineHash(Hash(a.table_index), Hash(a.column_index)); + } +}; -int8_t NumericLimits::Minimum() { - return numeric_limits::lowest(); -} +struct ColumnBindingEquality { + bool operator()(const ColumnBinding &a, const ColumnBinding &b) const { + return a == b; + } +}; -int8_t NumericLimits::Maximum() { - return numeric_limits::max(); -} +template +using column_binding_map_t = unordered_map; -int16_t NumericLimits::Minimum() { - return numeric_limits::lowest(); -} +using column_binding_set_t = unordered_set; -int16_t NumericLimits::Maximum() { - return numeric_limits::max(); -} +} // namespace duckdb -int32_t NumericLimits::Minimum() { - return numeric_limits::lowest(); -} -int32_t NumericLimits::Maximum() { - return numeric_limits::max(); -} -int64_t NumericLimits::Minimum() { - return numeric_limits::lowest(); -} -int64_t NumericLimits::Maximum() { - return numeric_limits::max(); -} -float NumericLimits::Minimum() { - return numeric_limits::lowest(); -} +namespace duckdb { +class ClientContext; +class LogicalOperator; +class TableFilter; +struct BoundOrderByNode; -float NumericLimits::Maximum() { - return numeric_limits::max(); -} +class StatisticsPropagator { +public: + explicit StatisticsPropagator(ClientContext &context); -double NumericLimits::Minimum() { - return numeric_limits::lowest(); -} + unique_ptr PropagateStatistics(unique_ptr &node_ptr); -double NumericLimits::Maximum() { - return numeric_limits::max(); -} +private: + //! Propagate statistics through an operator + unique_ptr PropagateStatistics(LogicalOperator &node, unique_ptr *node_ptr); -uint8_t NumericLimits::Minimum() { - return numeric_limits::lowest(); -} + unique_ptr PropagateStatistics(LogicalFilter &op, unique_ptr *node_ptr); + unique_ptr PropagateStatistics(LogicalGet &op, unique_ptr *node_ptr); + unique_ptr PropagateStatistics(LogicalJoin &op, unique_ptr *node_ptr); + unique_ptr PropagateStatistics(LogicalProjection &op, unique_ptr *node_ptr); + void PropagateStatistics(LogicalComparisonJoin &op, unique_ptr *node_ptr); + void PropagateStatistics(LogicalAnyJoin &op, unique_ptr *node_ptr); + unique_ptr PropagateStatistics(LogicalSetOperation &op, unique_ptr *node_ptr); + unique_ptr PropagateStatistics(LogicalAggregate &op, unique_ptr *node_ptr); + unique_ptr PropagateStatistics(LogicalCrossProduct &op, unique_ptr *node_ptr); + unique_ptr PropagateStatistics(LogicalLimit &op, unique_ptr *node_ptr); + unique_ptr PropagateStatistics(LogicalOrder &op, unique_ptr *node_ptr); + unique_ptr PropagateStatistics(LogicalWindow &op, unique_ptr *node_ptr); -uint8_t NumericLimits::Maximum() { - return numeric_limits::max(); -} + unique_ptr PropagateChildren(LogicalOperator &node, unique_ptr *node_ptr); -uint16_t NumericLimits::Minimum() { - return numeric_limits::lowest(); -} + //! Return statistics from a constant value + unique_ptr StatisticsFromValue(const Value &input); + //! Run a comparison with two sets of statistics, returns if the comparison will always returns true/false or not + FilterPropagateResult PropagateComparison(BaseStatistics &left, BaseStatistics &right, ExpressionType comparison); -uint16_t NumericLimits::Maximum() { - return numeric_limits::max(); -} + //! Update filter statistics from a filter with a constant + void UpdateFilterStatistics(BaseStatistics &input, ExpressionType comparison_type, const Value &constant); + //! Update statistics from a filter between two stats + void UpdateFilterStatistics(BaseStatistics &lstats, BaseStatistics &rstats, ExpressionType comparison_type); + //! Update filter statistics from a generic comparison + void UpdateFilterStatistics(Expression &left, Expression &right, ExpressionType comparison_type); + //! Update filter statistics from an expression + void UpdateFilterStatistics(Expression &condition); + //! Set the statistics of a specific column binding to not contain null values + void SetStatisticsNotNull(ColumnBinding binding); -uint32_t NumericLimits::Minimum() { - return numeric_limits::lowest(); -} + //! Run a comparison between the statistics and the table filter; returns the prune result + FilterPropagateResult PropagateTableFilter(BaseStatistics &stats, TableFilter &filter); + //! Update filter statistics from a TableFilter + void UpdateFilterStatistics(BaseStatistics &input, TableFilter &filter); -uint32_t NumericLimits::Maximum() { - return numeric_limits::max(); -} + //! Add cardinalities together (i.e. new max is stats.max + new_stats.max): used for union + void AddCardinalities(unique_ptr &stats, NodeStatistics &new_stats); + //! Multiply the cardinalities together (i.e. new max cardinality is stats.max * new_stats.max): used for + //! joins/cross products + void MultiplyCardinalities(unique_ptr &stats, NodeStatistics &new_stats); -uint64_t NumericLimits::Minimum() { - return numeric_limits::lowest(); -} + unique_ptr PropagateExpression(unique_ptr &expr); + unique_ptr PropagateExpression(Expression &expr, unique_ptr *expr_ptr); -uint64_t NumericLimits::Maximum() { - return numeric_limits::max(); -} + unique_ptr PropagateExpression(BoundAggregateExpression &expr, unique_ptr *expr_ptr); + unique_ptr PropagateExpression(BoundBetweenExpression &expr, unique_ptr *expr_ptr); + unique_ptr PropagateExpression(BoundCaseExpression &expr, unique_ptr *expr_ptr); + unique_ptr PropagateExpression(BoundCastExpression &expr, unique_ptr *expr_ptr); + unique_ptr PropagateExpression(BoundConjunctionExpression &expr, unique_ptr *expr_ptr); + unique_ptr PropagateExpression(BoundFunctionExpression &expr, unique_ptr *expr_ptr); + unique_ptr PropagateExpression(BoundComparisonExpression &expr, unique_ptr *expr_ptr); + unique_ptr PropagateExpression(BoundConstantExpression &expr, unique_ptr *expr_ptr); + unique_ptr PropagateExpression(BoundColumnRefExpression &expr, unique_ptr *expr_ptr); + unique_ptr PropagateExpression(BoundOperatorExpression &expr, unique_ptr *expr_ptr); -hugeint_t NumericLimits::Minimum() { - hugeint_t result; - result.lower = 1; - result.upper = numeric_limits::lowest(); - return result; -} + void PropagateAndCompress(unique_ptr &expr, unique_ptr &stats); -hugeint_t NumericLimits::Maximum() { - hugeint_t result; - result.lower = numeric_limits::max(); - result.upper = numeric_limits::max(); - return result; -} + void ReplaceWithEmptyResult(unique_ptr &node); + + bool ExpressionIsConstant(Expression &expr, const Value &val); + bool ExpressionIsConstantOrNull(Expression &expr, const Value &val); + +private: + ClientContext &context; + //! The map of ColumnBinding -> statistics for the various nodes + column_binding_map_t> statistics_map; + //! Node stats for the current node + unique_ptr node_stats; +}; } // namespace duckdb + + + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/local_file_system.hpp +// duckdb/optimizer/filter_combiner.hpp // // //===----------------------------------------------------------------------===// @@ -20086,99 +21921,72 @@ hugeint_t NumericLimits::Maximum() { -namespace duckdb { -class LocalFileSystem : public FileSystem { -public: - unique_ptr OpenFile(const string &path, uint8_t flags, FileLockType lock = FileLockType::NO_LOCK, - FileCompressionType compression = FileCompressionType::UNCOMPRESSED, - FileOpener *opener = nullptr) override; - //! Read exactly nr_bytes from the specified location in the file. Fails if nr_bytes could not be read. This is - //! equivalent to calling SetFilePointer(location) followed by calling Read(). - void Read(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) override; - //! Write exactly nr_bytes to the specified location in the file. Fails if nr_bytes could not be read. This is - //! equivalent to calling SetFilePointer(location) followed by calling Write(). - void Write(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) override; - //! Read nr_bytes from the specified file into the buffer, moving the file pointer forward by nr_bytes. Returns the - //! amount of bytes read. - int64_t Read(FileHandle &handle, void *buffer, int64_t nr_bytes) override; - //! Write nr_bytes from the buffer into the file, moving the file pointer forward by nr_bytes. - int64_t Write(FileHandle &handle, void *buffer, int64_t nr_bytes) override; +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/filter/conjunction_filter.hpp +// +// +//===----------------------------------------------------------------------===// - //! Returns the file size of a file handle, returns -1 on error - int64_t GetFileSize(FileHandle &handle) override; - //! Returns the file last modified time of a file handle, returns timespec with zero on all attributes on error - time_t GetLastModifiedTime(FileHandle &handle) override; - //! Returns the file last modified time of a file handle, returns timespec with zero on all attributes on error - FileType GetFileType(FileHandle &handle) override; - //! Truncate a file to a maximum size of new_size, new_size should be smaller than or equal to the current size of - //! the file - void Truncate(FileHandle &handle, int64_t new_size) override; - //! Check if a directory exists - bool DirectoryExists(const string &directory) override; - //! Create a directory if it does not exist - void CreateDirectory(const string &directory) override; - //! Recursively remove a directory and all files in it - void RemoveDirectory(const string &directory) override; - //! List files in a directory, invoking the callback method for each one with (filename, is_dir) - bool ListFiles(const string &directory, const std::function &callback) override; - //! Move a file from source path to the target, StorageManager relies on this being an atomic action for ACID - //! properties - void MoveFile(const string &source, const string &target) override; - //! Check if a file exists - bool FileExists(const string &filename) override; - //! Check if path is a pipe - bool IsPipe(const string &filename) override; - //! Remove a file from disk - void RemoveFile(const string &filename) override; - //! Sync a file handle to disk - void FileSync(FileHandle &handle) override; - //! Runs a glob on the file system, returning a list of matching files - vector Glob(const string &path, FileOpener *opener = nullptr) override; - bool CanHandleFile(const string &fpath) override { - //! Whether or not a sub-system can handle a specific file path - return false; + +namespace duckdb { +class ConjunctionFilter : public TableFilter { +public: + ConjunctionFilter(TableFilterType filter_type_p) : TableFilter(filter_type_p) { } - //! Set the file pointer of a file handle to a specified location. Reads and writes will happen from this location - void Seek(FileHandle &handle, idx_t location) override; - //! Return the current seek posiiton in the file. - idx_t SeekPosition(FileHandle &handle) override; + virtual ~ConjunctionFilter() { + } - //! Whether or not we can seek into the file - bool CanSeek() override; - //! Whether or not the FS handles plain files on disk. This is relevant for certain optimizations, as random reads - //! in a file on-disk are much cheaper than e.g. random reads in a file over the network - bool OnDiskFile(FileHandle &handle) override; + //! The filters of this conjunction + vector> child_filters; - std::string GetName() const override { - return "LocalFileSystem"; +public: + virtual FilterPropagateResult CheckStatistics(BaseStatistics &stats) = 0; + virtual string ToString(const string &column_name) = 0; + + virtual bool Equals(const TableFilter &other) const { + return TableFilter::Equals(other); } +}; - //! Returns the last Win32 error, in string format. Returns an empty string if there is no error, or on non-Windows - //! systems. - static std::string GetLastErrorAsString(); +class ConjunctionOrFilter : public ConjunctionFilter { +public: + ConjunctionOrFilter(); -private: - //! Set the file pointer of a file handle to a specified location. Reads and writes will happen from this location - void SetFilePointer(FileHandle &handle, idx_t location); - idx_t GetFilePointer(FileHandle &handle); +public: + FilterPropagateResult CheckStatistics(BaseStatistics &stats) override; + string ToString(const string &column_name) override; + bool Equals(const TableFilter &other) const override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(FieldReader &source); }; -} // namespace duckdb - +class ConjunctionAndFilter : public ConjunctionFilter { +public: + ConjunctionAndFilter(); +public: + FilterPropagateResult CheckStatistics(BaseStatistics &stats) override; + string ToString(const string &column_name) override; + bool Equals(const TableFilter &other) const override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(FieldReader &source); +}; +} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/file_opener.hpp +// duckdb/planner/filter/constant_filter.hpp // // //===----------------------------------------------------------------------===// @@ -20187,41 +21995,137 @@ class LocalFileSystem : public FileSystem { -namespace duckdb { -class Value; -//! Abstract type that provide client-specific context to FileSystem. -class FileOpener { +namespace duckdb { + +class ConstantFilter : public TableFilter { public: - virtual ~FileOpener() {}; + ConstantFilter(ExpressionType comparison_type, Value constant); - virtual bool TryGetCurrentSetting(const string &key, Value &result) = 0; + //! The comparison type (e.g. COMPARE_EQUAL, COMPARE_GREATERTHAN, COMPARE_LESSTHAN, ...) + ExpressionType comparison_type; + //! The constant value to filter on + Value constant; + +public: + FilterPropagateResult CheckStatistics(BaseStatistics &stats) override; + string ToString(const string &column_name) override; + bool Equals(const TableFilter &other) const override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(FieldReader &source); }; } // namespace duckdb +#include +#include + +namespace duckdb { +enum class ValueComparisonResult { PRUNE_LEFT, PRUNE_RIGHT, UNSATISFIABLE_CONDITION, PRUNE_NOTHING }; +enum class FilterResult { UNSATISFIABLE, SUCCESS, UNSUPPORTED }; +//! The FilterCombiner combines several filters and generates a logically equivalent set that is more efficient +//! Amongst others: +//! (1) it prunes obsolete filter conditions: i.e. [X > 5 and X > 7] => [X > 7] +//! (2) it generates new filters for expressions in the same equivalence set: i.e. [X = Y and X = 500] => [Y = 500] +//! (3) it prunes branches that have unsatisfiable filters: i.e. [X = 5 AND X > 6] => FALSE, prune branch +class FilterCombiner { +public: + struct ExpressionValueInformation { + Value constant; + ExpressionType comparison_type; + }; + FilterResult AddFilter(unique_ptr expr); -#include -#include + void GenerateFilters(const std::function filter)> &callback); + bool HasFilters(); + TableFilterSet GenerateTableScanFilters(vector &column_ids); + // vector> GenerateZonemapChecks(vector &column_ids, vector> + // &pushed_filters); + +private: + FilterResult AddFilter(Expression *expr); + FilterResult AddBoundComparisonFilter(Expression *expr); + FilterResult AddTransitiveFilters(BoundComparisonExpression &comparison); + unique_ptr FindTransitiveFilter(Expression *expr); + // unordered_map> + // FindZonemapChecks(vector &column_ids, unordered_set ¬_constants, Expression *filter); + Expression *GetNode(Expression *expr); + idx_t GetEquivalenceSet(Expression *expr); + FilterResult AddConstantComparison(vector &info_list, ExpressionValueInformation info); + // + // //! Functions used to push and generate OR Filters + // void LookUpConjunctions(Expression *expr); + // bool BFSLookUpConjunctions(BoundConjunctionExpression *conjunction); + // void VerifyOrsToPush(Expression &expr); + // + // bool UpdateConjunctionFilter(BoundComparisonExpression *comparison_expr); + // bool UpdateFilterByColumn(BoundColumnRefExpression *column_ref, BoundComparisonExpression *comparison_expr); + // void GenerateORFilters(TableFilterSet &table_filter, vector &column_ids); + // + // template + // void GenerateConjunctionFilter(BoundConjunctionExpression *conjunction, ConjunctionFilter *last_conj_filter) { + // auto new_filter = NextConjunctionFilter(conjunction); + // auto conj_filter_ptr = (ConjunctionFilter *)new_filter.get(); + // last_conj_filter->child_filters.push_back(move(new_filter)); + // last_conj_filter = conj_filter_ptr; + // } + // + // template + // unique_ptr NextConjunctionFilter(BoundConjunctionExpression *conjunction) { + // unique_ptr conj_filter = make_unique(); + // for (auto &expr : conjunction->children) { + // auto comp_expr = (BoundComparisonExpression *)expr.get(); + // auto &const_expr = + // (comp_expr->left->type == ExpressionType::VALUE_CONSTANT) ? *comp_expr->left : *comp_expr->right; + // auto const_value = ExpressionExecutor::EvaluateScalar(const_expr); + // auto const_filter = make_unique(comp_expr->type, const_value); + // conj_filter->child_filters.push_back(move(const_filter)); + // } + // return move(conj_filter); + // } + +private: + vector> remaining_filters; + + expression_map_t> stored_expressions; + unordered_map equivalence_set_map; + unordered_map> constant_values; + unordered_map> equivalence_map; + idx_t set_index = 0; + // + // //! Structures used for OR Filters + // + // struct ConjunctionsToPush { + // BoundConjunctionExpression *root_or; + // + // // only preserve AND if there is a single column in the expression + // bool preserve_and = true; + // + // // conjunction chain for this column + // vector> conjunctions; + // }; + // + // expression_map_t>> map_col_conjunctions; + // vector vec_colref_insertion_order; + // + // BoundConjunctionExpression *cur_root_or; + // BoundConjunctionExpression *cur_conjunction; + // + // BoundColumnRefExpression *cur_colref_to_push; +}; + +} // namespace duckdb -#ifndef _WIN32 -#include -#include -#include -#include -#include -#include -#else //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/windows_util.hpp +// duckdb/planner/expression_iterator.hpp // // //===----------------------------------------------------------------------===// @@ -20231,1175 +22135,2794 @@ class FileOpener { - - +#include namespace duckdb { +class BoundQueryNode; +class BoundTableRef; -#ifdef DUCKDB_WINDOWS -class WindowsUtil { +class ExpressionIterator { public: - //! Windows helper functions - static std::wstring UTF8ToUnicode(const char *input); - static string UnicodeToUTF8(LPCWSTR input); - static string UTF8ToMBCS(const char *input, bool use_ansi = false); + static void EnumerateChildren(const Expression &expression, + const std::function &callback); + static void EnumerateChildren(Expression &expression, const std::function &callback); + static void EnumerateChildren(Expression &expression, + const std::function &child)> &callback); + + static void EnumerateExpression(unique_ptr &expr, + const std::function &callback); + + static void EnumerateTableRefChildren(BoundTableRef &ref, const std::function &callback); + static void EnumerateQueryNodeChildren(BoundQueryNode &node, + const std::function &callback); }; -#endif } // namespace duckdb -#include -#include -#ifdef __MINGW32__ -#include -// need to manually define this for mingw -extern "C" WINBASEAPI BOOL WINAPI GetPhysicallyInstalledSystemMemory(PULONGLONG); -#endif +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 +// See the end of this file for a list -#undef FILE_CREATE // woo mingw -#endif +// Copyright 2003-2009 The RE2 Authors. All Rights Reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. -namespace duckdb { +#ifndef RE2_RE2_H_ +#define RE2_RE2_H_ -static void AssertValidFileFlags(uint8_t flags) { -#ifdef DEBUG - bool is_read = flags & FileFlags::FILE_FLAGS_READ; - bool is_write = flags & FileFlags::FILE_FLAGS_WRITE; - // require either READ or WRITE (or both) - D_ASSERT(is_read || is_write); - // CREATE/Append flags require writing - D_ASSERT(is_write || !(flags & FileFlags::FILE_FLAGS_APPEND)); - D_ASSERT(is_write || !(flags & FileFlags::FILE_FLAGS_FILE_CREATE)); - D_ASSERT(is_write || !(flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW)); - // cannot combine CREATE and CREATE_NEW flags - D_ASSERT(!(flags & FileFlags::FILE_FLAGS_FILE_CREATE && flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW)); -#endif -} +// C++ interface to the re2 regular-expression library. +// RE2 supports Perl-style regular expressions (with extensions like +// \d, \w, \s, ...). +// +// ----------------------------------------------------------------------- +// REGEXP SYNTAX: +// +// This module uses the re2 library and hence supports +// its syntax for regular expressions, which is similar to Perl's with +// some of the more complicated things thrown away. In particular, +// backreferences and generalized assertions are not available, nor is \Z. +// +// See https://github.com/google/re2/wiki/Syntax for the syntax +// supported by RE2, and a comparison with PCRE and PERL regexps. +// +// For those not familiar with Perl's regular expressions, +// here are some examples of the most commonly used extensions: +// +// "hello (\\w+) world" -- \w matches a "word" character +// "version (\\d+)" -- \d matches a digit +// "hello\\s+world" -- \s matches any whitespace character +// "\\b(\\w+)\\b" -- \b matches non-empty string at word boundary +// "(?i)hello" -- (?i) turns on case-insensitive matching +// "/\\*(.*?)\\*/" -- .*? matches . minimum no. of times possible +// +// ----------------------------------------------------------------------- +// MATCHING INTERFACE: +// +// The "FullMatch" operation checks that supplied text matches a +// supplied pattern exactly. +// +// Example: successful match +// CHECK(RE2::FullMatch("hello", "h.*o")); +// +// Example: unsuccessful match (requires full match): +// CHECK(!RE2::FullMatch("hello", "e")); +// +// ----------------------------------------------------------------------- +// UTF-8 AND THE MATCHING INTERFACE: +// +// By default, the pattern and input text are interpreted as UTF-8. +// The RE2::Latin1 option causes them to be interpreted as Latin-1. +// +// Example: +// CHECK(RE2::FullMatch(utf8_string, RE2(utf8_pattern))); +// CHECK(RE2::FullMatch(latin1_string, RE2(latin1_pattern, RE2::Latin1))); +// +// ----------------------------------------------------------------------- +// MATCHING WITH SUBSTRING EXTRACTION: +// +// You can supply extra pointer arguments to extract matched substrings. +// On match failure, none of the pointees will have been modified. +// On match success, the substrings will be converted (as necessary) and +// their values will be assigned to their pointees until all conversions +// have succeeded or one conversion has failed. +// On conversion failure, the pointees will be in an indeterminate state +// because the caller has no way of knowing which conversion failed. +// However, conversion cannot fail for types like string and StringPiece +// that do not inspect the substring contents. Hence, in the common case +// where all of the pointees are of such types, failure is always due to +// match failure and thus none of the pointees will have been modified. +// +// Example: extracts "ruby" into "s" and 1234 into "i" +// int i; +// std::string s; +// CHECK(RE2::FullMatch("ruby:1234", "(\\w+):(\\d+)", &s, &i)); +// +// Example: fails because string cannot be stored in integer +// CHECK(!RE2::FullMatch("ruby", "(.*)", &i)); +// +// Example: fails because there aren't enough sub-patterns +// CHECK(!RE2::FullMatch("ruby:1234", "\\w+:\\d+", &s)); +// +// Example: does not try to extract any extra sub-patterns +// CHECK(RE2::FullMatch("ruby:1234", "(\\w+):(\\d+)", &s)); +// +// Example: does not try to extract into NULL +// CHECK(RE2::FullMatch("ruby:1234", "(\\w+):(\\d+)", NULL, &i)); +// +// Example: integer overflow causes failure +// CHECK(!RE2::FullMatch("ruby:1234567891234", "\\w+:(\\d+)", &i)); +// +// NOTE(rsc): Asking for substrings slows successful matches quite a bit. +// This may get a little faster in the future, but right now is slower +// than PCRE. On the other hand, failed matches run *very* fast (faster +// than PCRE), as do matches without substring extraction. +// +// ----------------------------------------------------------------------- +// PARTIAL MATCHES +// +// You can use the "PartialMatch" operation when you want the pattern +// to match any substring of the text. +// +// Example: simple search for a string: +// CHECK(RE2::PartialMatch("hello", "ell")); +// +// Example: find first number in a string +// int number; +// CHECK(RE2::PartialMatch("x*100 + 20", "(\\d+)", &number)); +// CHECK_EQ(number, 100); +// +// ----------------------------------------------------------------------- +// PRE-COMPILED REGULAR EXPRESSIONS +// +// RE2 makes it easy to use any string as a regular expression, without +// requiring a separate compilation step. +// +// If speed is of the essence, you can create a pre-compiled "RE2" +// object from the pattern and use it multiple times. If you do so, +// you can typically parse text faster than with sscanf. +// +// Example: precompile pattern for faster matching: +// RE2 pattern("h.*o"); +// while (ReadLine(&str)) { +// if (RE2::FullMatch(str, pattern)) ...; +// } +// +// ----------------------------------------------------------------------- +// SCANNING TEXT INCREMENTALLY +// +// The "Consume" operation may be useful if you want to repeatedly +// match regular expressions at the front of a string and skip over +// them as they match. This requires use of the "StringPiece" type, +// which represents a sub-range of a real string. +// +// Example: read lines of the form "var = value" from a string. +// std::string contents = ...; // Fill string somehow +// StringPiece input(contents); // Wrap a StringPiece around it +// +// std::string var; +// int value; +// while (RE2::Consume(&input, "(\\w+) = (\\d+)\n", &var, &value)) { +// ...; +// } +// +// Each successful call to "Consume" will set "var/value", and also +// advance "input" so it points past the matched text. Note that if the +// regular expression matches an empty string, input will advance +// by 0 bytes. If the regular expression being used might match +// an empty string, the loop body must check for this case and either +// advance the string or break out of the loop. +// +// The "FindAndConsume" operation is similar to "Consume" but does not +// anchor your match at the beginning of the string. For example, you +// could extract all words from a string by repeatedly calling +// RE2::FindAndConsume(&input, "(\\w+)", &word) +// +// ----------------------------------------------------------------------- +// USING VARIABLE NUMBER OF ARGUMENTS +// +// The above operations require you to know the number of arguments +// when you write the code. This is not always possible or easy (for +// example, the regular expression may be calculated at run time). +// You can use the "N" version of the operations when the number of +// match arguments are determined at run time. +// +// Example: +// const RE2::Arg* args[10]; +// int n; +// // ... populate args with pointers to RE2::Arg values ... +// // ... set n to the number of RE2::Arg objects ... +// bool match = RE2::FullMatchN(input, pattern, args, n); +// +// The last statement is equivalent to +// +// bool match = RE2::FullMatch(input, pattern, +// *args[0], *args[1], ..., *args[n - 1]); +// +// ----------------------------------------------------------------------- +// PARSING HEX/OCTAL/C-RADIX NUMBERS +// +// By default, if you pass a pointer to a numeric value, the +// corresponding text is interpreted as a base-10 number. You can +// instead wrap the pointer with a call to one of the operators Hex(), +// Octal(), or CRadix() to interpret the text in another base. The +// CRadix operator interprets C-style "0" (base-8) and "0x" (base-16) +// prefixes, but defaults to base-10. +// +// Example: +// int a, b, c, d; +// CHECK(RE2::FullMatch("100 40 0100 0x40", "(.*) (.*) (.*) (.*)", +// RE2::Octal(&a), RE2::Hex(&b), RE2::CRadix(&c), RE2::CRadix(&d)); +// will leave 64 in a, b, c, and d. -#ifdef __MINGW32__ -bool LocalFileSystem::FileExists(const string &filename) { - auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str()); - const wchar_t *wpath = unicode_path.c_str(); - if (_waccess(wpath, 0) == 0) { - struct _stat64i32 status; - _wstat64i32(wpath, &status); - if (status.st_size > 0) { - return true; - } - } - return false; -} -bool LocalFileSystem::IsPipe(const string &filename) { - auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str()); - const wchar_t *wpath = unicode_path.c_str(); - if (_waccess(wpath, 0) == 0) { - struct _stat64i32 status; - _wstat64i32(wpath, &status); - if (status.st_size == 0) { - return true; - } - } - return false; -} +#include +#include +#include +#include +#include +#include -#else -#ifndef _WIN32 -bool LocalFileSystem::FileExists(const string &filename) { - if (!filename.empty()) { - if (access(filename.c_str(), 0) == 0) { - struct stat status; - stat(filename.c_str(), &status); - if (S_ISREG(status.st_mode)) { - return true; - } - } - } - // if any condition fails - return false; -} -bool LocalFileSystem::IsPipe(const string &filename) { - if (!filename.empty()) { - if (access(filename.c_str(), 0) == 0) { - struct stat status; - stat(filename.c_str(), &status); - if (S_ISFIFO(status.st_mode)) { - return true; - } - } - } - // if any condition fails - return false; -} -#else -bool LocalFileSystem::FileExists(const string &filename) { - auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str()); - const wchar_t *wpath = unicode_path.c_str(); - if (_waccess(wpath, 0) == 0) { - struct _stat64i32 status; - _wstat(wpath, &status); - if (status.st_mode & S_IFREG) { - return true; - } - } - return false; -} -bool LocalFileSystem::IsPipe(const string &filename) { - auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str()); - const wchar_t *wpath = unicode_path.c_str(); - if (_waccess(wpath, 0) == 0) { - struct _stat64i32 status; - _wstat(wpath, &status); - if (status.st_mode & _S_IFCHR) { - return true; - } - } - return false; -} -#endif -#endif +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 +// See the end of this file for a list -#ifndef _WIN32 -// somehow sometimes this is missing -#ifndef O_CLOEXEC -#define O_CLOEXEC 0 -#endif +// Copyright 2001-2010 The RE2 Authors. All Rights Reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. -// Solaris -#ifndef O_DIRECT -#define O_DIRECT 0 +#ifndef RE2_STRINGPIECE_H_ +#define RE2_STRINGPIECE_H_ + +#ifdef min +#undef min #endif -struct UnixFileHandle : public FileHandle { -public: - UnixFileHandle(FileSystem &file_system, string path, int fd) : FileHandle(file_system, move(path)), fd(fd) { - } - ~UnixFileHandle() override { - Close(); - } +// A string-like object that points to a sized piece of memory. +// +// Functions or methods may use const StringPiece& parameters to accept either +// a "const char*" or a "string" value that will be implicitly converted to +// a StringPiece. The implicit conversion means that it is often appropriate +// to include this .h file in other files rather than forward-declaring +// StringPiece as would be appropriate for most other Google classes. +// +// Systematic usage of StringPiece is encouraged as it will reduce unnecessary +// conversions from "const char*" to "string" and back again. +// +// +// Arghh! I wish C++ literals were "string". - int fd; +// Doing this simplifies the logic below. +#ifndef __has_include +#define __has_include(x) 0 +#endif -public: - void Close() override { - if (fd != -1) { - close(fd); - } - }; -}; +#include +#include +#include +#include +#include +#include +#if __has_include() && __cplusplus >= 201703L +#include +#endif -static FileType GetFileTypeInternal(int fd) { // LCOV_EXCL_START - struct stat s; - if (fstat(fd, &s) == -1) { - return FileType::FILE_TYPE_INVALID; - } - switch (s.st_mode & S_IFMT) { - case S_IFBLK: - return FileType::FILE_TYPE_BLOCKDEV; - case S_IFCHR: - return FileType::FILE_TYPE_CHARDEV; - case S_IFIFO: - return FileType::FILE_TYPE_FIFO; - case S_IFDIR: - return FileType::FILE_TYPE_DIR; - case S_IFLNK: - return FileType::FILE_TYPE_LINK; - case S_IFREG: - return FileType::FILE_TYPE_REGULAR; - case S_IFSOCK: - return FileType::FILE_TYPE_SOCKET; - default: - return FileType::FILE_TYPE_INVALID; - } -} // LCOV_EXCL_STOP +namespace duckdb_re2 { -unique_ptr LocalFileSystem::OpenFile(const string &path, uint8_t flags, FileLockType lock_type, - FileCompressionType compression, FileOpener *opener) { - if (compression != FileCompressionType::UNCOMPRESSED) { - throw NotImplementedException("Unsupported compression type for default file system"); - } - - AssertValidFileFlags(flags); +class StringPiece { + public: + typedef std::char_traits traits_type; + typedef char value_type; + typedef char* pointer; + typedef const char* const_pointer; + typedef char& reference; + typedef const char& const_reference; + typedef const char* const_iterator; + typedef const_iterator iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef const_reverse_iterator reverse_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + static const size_type npos = static_cast(-1); - int open_flags = 0; - int rc; - bool open_read = flags & FileFlags::FILE_FLAGS_READ; - bool open_write = flags & FileFlags::FILE_FLAGS_WRITE; - if (open_read && open_write) { - open_flags = O_RDWR; - } else if (open_read) { - open_flags = O_RDONLY; - } else if (open_write) { - open_flags = O_WRONLY; - } else { - throw InternalException("READ, WRITE or both should be specified when opening a file"); - } - if (open_write) { - // need Read or Write - D_ASSERT(flags & FileFlags::FILE_FLAGS_WRITE); - open_flags |= O_CLOEXEC; - if (flags & FileFlags::FILE_FLAGS_FILE_CREATE) { - open_flags |= O_CREAT; - } else if (flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW) { - open_flags |= O_CREAT | O_TRUNC; - } - if (flags & FileFlags::FILE_FLAGS_APPEND) { - open_flags |= O_APPEND; - } - } - if (flags & FileFlags::FILE_FLAGS_DIRECT_IO) { -#if defined(__sun) && defined(__SVR4) - throw Exception("DIRECT_IO not supported on Solaris"); -#endif -#if defined(__DARWIN__) || defined(__APPLE__) || defined(__OpenBSD__) - // OSX does not have O_DIRECT, instead we need to use fcntl afterwards to support direct IO - open_flags |= O_SYNC; -#else - open_flags |= O_DIRECT | O_SYNC; + // We provide non-explicit singleton constructors so users can pass + // in a "const char*" or a "string" wherever a "StringPiece" is + // expected. + StringPiece() + : data_(NULL), size_(0) {} +#if __has_include() && __cplusplus >= 201703L + StringPiece(const std::string_view& str) + : data_(str.data()), size_(str.size()) {} #endif - } - int fd = open(path.c_str(), open_flags, 0666); - if (fd == -1) { - throw IOException("Cannot open file \"%s\": %s", path, strerror(errno)); - } - // #if defined(__DARWIN__) || defined(__APPLE__) - // if (flags & FileFlags::FILE_FLAGS_DIRECT_IO) { - // // OSX requires fcntl for Direct IO - // rc = fcntl(fd, F_NOCACHE, 1); - // if (fd == -1) { - // throw IOException("Could not enable direct IO for file \"%s\": %s", path, strerror(errno)); - // } - // } - // #endif - if (lock_type != FileLockType::NO_LOCK) { - // set lock on file - // but only if it is not an input/output stream - auto file_type = GetFileTypeInternal(fd); - if (file_type != FileType::FILE_TYPE_FIFO && file_type != FileType::FILE_TYPE_SOCKET) { - struct flock fl; - memset(&fl, 0, sizeof fl); - fl.l_type = lock_type == FileLockType::READ_LOCK ? F_RDLCK : F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - rc = fcntl(fd, F_SETLK, &fl); - if (rc == -1) { - throw IOException("Could not set lock on file \"%s\": %s", path, strerror(errno)); - } - } - } - return make_unique(*this, path, fd); -} + StringPiece(const std::string& str) + : data_(str.data()), size_(str.size()) {} + StringPiece(const char* str) + : data_(str), size_(str == NULL ? 0 : strlen(str)) {} + StringPiece(const char* str, size_type len) + : data_(str), size_(len) {} -void LocalFileSystem::SetFilePointer(FileHandle &handle, idx_t location) { - int fd = ((UnixFileHandle &)handle).fd; - off_t offset = lseek(fd, location, SEEK_SET); - if (offset == (off_t)-1) { - throw IOException("Could not seek to location %lld for file \"%s\": %s", location, handle.path, - strerror(errno)); - } -} + const_iterator begin() const { return data_; } + const_iterator end() const { return data_ + size_; } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(data_ + size_); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(data_); + } -idx_t LocalFileSystem::GetFilePointer(FileHandle &handle) { - int fd = ((UnixFileHandle &)handle).fd; - off_t position = lseek(fd, 0, SEEK_CUR); - if (position == (off_t)-1) { - throw IOException("Could not get file position file \"%s\": %s", handle.path, strerror(errno)); - } - return position; -} + size_type size() const { return size_; } + size_type length() const { return size_; } + bool empty() const { return size_ == 0; } -void LocalFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) { - int fd = ((UnixFileHandle &)handle).fd; - int64_t bytes_read = pread(fd, buffer, nr_bytes, location); - if (bytes_read == -1) { - throw IOException("Could not read from file \"%s\": %s", handle.path, strerror(errno)); - } - if (bytes_read != nr_bytes) { - throw IOException("Could not read all bytes from file \"%s\": wanted=%lld read=%lld", handle.path, nr_bytes, - bytes_read); - } -} + const_reference operator[](size_type i) const { return data_[i]; } + const_pointer data() const { return data_; } -int64_t LocalFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes) { - int fd = ((UnixFileHandle &)handle).fd; - int64_t bytes_read = read(fd, buffer, nr_bytes); - if (bytes_read == -1) { - throw IOException("Could not read from file \"%s\": %s", handle.path, strerror(errno)); - } - return bytes_read; -} + void remove_prefix(size_type n) { + data_ += n; + size_ -= n; + } -void LocalFileSystem::Write(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) { - int fd = ((UnixFileHandle &)handle).fd; - int64_t bytes_written = pwrite(fd, buffer, nr_bytes, location); - if (bytes_written == -1) { - throw IOException("Could not write file \"%s\": %s", handle.path, strerror(errno)); - } - if (bytes_written != nr_bytes) { - throw IOException("Could not write all bytes to file \"%s\": wanted=%lld wrote=%lld", handle.path, nr_bytes, - bytes_written); - } -} + void remove_suffix(size_type n) { + size_ -= n; + } -int64_t LocalFileSystem::Write(FileHandle &handle, void *buffer, int64_t nr_bytes) { - int fd = ((UnixFileHandle &)handle).fd; - int64_t bytes_written = write(fd, buffer, nr_bytes); - if (bytes_written == -1) { - throw IOException("Could not write file \"%s\": %s", handle.path, strerror(errno)); - } - return bytes_written; -} + void set(const char* str) { + data_ = str; + size_ = str == NULL ? 0 : strlen(str); + } -int64_t LocalFileSystem::GetFileSize(FileHandle &handle) { - int fd = ((UnixFileHandle &)handle).fd; - struct stat s; - if (fstat(fd, &s) == -1) { - return -1; - } - return s.st_size; -} + void set(const char* str, size_type len) { + data_ = str; + size_ = len; + } -time_t LocalFileSystem::GetLastModifiedTime(FileHandle &handle) { - int fd = ((UnixFileHandle &)handle).fd; - struct stat s; - if (fstat(fd, &s) == -1) { - return -1; - } - return s.st_mtime; -} + // Converts to `std::basic_string`. + template + explicit operator std::basic_string() const { + if (!data_) return {}; + return std::basic_string(data_, size_); + } -FileType LocalFileSystem::GetFileType(FileHandle &handle) { - int fd = ((UnixFileHandle &)handle).fd; - return GetFileTypeInternal(fd); -} + std::string as_string() const { + return std::string(data_, size_); + } -void LocalFileSystem::Truncate(FileHandle &handle, int64_t new_size) { - int fd = ((UnixFileHandle &)handle).fd; - if (ftruncate(fd, new_size) != 0) { - throw IOException("Could not truncate file \"%s\": %s", handle.path, strerror(errno)); - } -} + // We also define ToString() here, since many other string-like + // interfaces name the routine that converts to a C++ string + // "ToString", and it's confusing to have the method that does that + // for a StringPiece be called "as_string()". We also leave the + // "as_string()" method defined here for existing code. + std::string ToString() const { + return std::string(data_, size_); + } -bool LocalFileSystem::DirectoryExists(const string &directory) { - if (!directory.empty()) { - if (access(directory.c_str(), 0) == 0) { - struct stat status; - stat(directory.c_str(), &status); - if (status.st_mode & S_IFDIR) { - return true; - } - } - } - // if any condition fails - return false; -} + void CopyToString(std::string* target) const { + target->assign(data_, size_); + } -void LocalFileSystem::CreateDirectory(const string &directory) { - struct stat st; + void AppendToString(std::string* target) const { + target->append(data_, size_); + } - if (stat(directory.c_str(), &st) != 0) { - /* Directory does not exist. EEXIST for race condition */ - if (mkdir(directory.c_str(), 0755) != 0 && errno != EEXIST) { - throw IOException("Failed to create directory \"%s\"!", directory); - } - } else if (!S_ISDIR(st.st_mode)) { - throw IOException("Failed to create directory \"%s\": path exists but is not a directory!", directory); - } -} + size_type copy(char* buf, size_type n, size_type pos = 0) const; + StringPiece substr(size_type pos = 0, size_type n = npos) const; -int RemoveDirectoryRecursive(const char *path) { - DIR *d = opendir(path); - idx_t path_len = (idx_t)strlen(path); - int r = -1; + int compare(const StringPiece& x) const { + size_type min_size = std::min(size(), x.size()); + if (min_size > 0) { + int r = memcmp(data(), x.data(), min_size); + if (r < 0) return -1; + if (r > 0) return 1; + } + if (size() < x.size()) return -1; + if (size() > x.size()) return 1; + return 0; + } - if (d) { - struct dirent *p; - r = 0; - while (!r && (p = readdir(d))) { - int r2 = -1; - char *buf; - idx_t len; - /* Skip the names "." and ".." as we don't want to recurse on them. */ - if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) { - continue; - } - len = path_len + (idx_t)strlen(p->d_name) + 2; - buf = new char[len]; - if (buf) { - struct stat statbuf; - snprintf(buf, len, "%s/%s", path, p->d_name); - if (!stat(buf, &statbuf)) { - if (S_ISDIR(statbuf.st_mode)) { - r2 = RemoveDirectoryRecursive(buf); - } else { - r2 = unlink(buf); - } - } - delete[] buf; - } - r = r2; - } - closedir(d); - } - if (!r) { - r = rmdir(path); - } - return r; -} + // Does "this" start with "x"? + bool starts_with(const StringPiece& x) const { + return x.empty() || + (size() >= x.size() && memcmp(data(), x.data(), x.size()) == 0); + } -void LocalFileSystem::RemoveDirectory(const string &directory) { - RemoveDirectoryRecursive(directory.c_str()); + // Does "this" end with "x"? + bool ends_with(const StringPiece& x) const { + return x.empty() || + (size() >= x.size() && + memcmp(data() + (size() - x.size()), x.data(), x.size()) == 0); + } + + bool contains(const StringPiece& s) const { + return find(s) != npos; + } + + size_type find(const StringPiece& s, size_type pos = 0) const; + size_type find(char c, size_type pos = 0) const; + size_type rfind(const StringPiece& s, size_type pos = npos) const; + size_type rfind(char c, size_type pos = npos) const; + + private: + const_pointer data_; + size_type size_; +}; + +inline bool operator==(const StringPiece& x, const StringPiece& y) { + StringPiece::size_type len = x.size(); + if (len != y.size()) return false; + return x.data() == y.data() || len == 0 || + memcmp(x.data(), y.data(), len) == 0; } -void LocalFileSystem::RemoveFile(const string &filename) { - if (std::remove(filename.c_str()) != 0) { - throw IOException("Could not remove file \"%s\": %s", filename, strerror(errno)); - } +inline bool operator!=(const StringPiece& x, const StringPiece& y) { + return !(x == y); } -bool LocalFileSystem::ListFiles(const string &directory, const std::function &callback) { - if (!DirectoryExists(directory)) { - return false; - } - DIR *dir = opendir(directory.c_str()); - if (!dir) { - return false; - } - struct dirent *ent; - // loop over all files in the directory - while ((ent = readdir(dir)) != nullptr) { - string name = string(ent->d_name); - // skip . .. and empty files - if (name.empty() || name == "." || name == "..") { - continue; - } - // now stat the file to figure out if it is a regular file or directory - string full_path = JoinPath(directory, name); - if (access(full_path.c_str(), 0) != 0) { - continue; - } - struct stat status; - stat(full_path.c_str(), &status); - if (!(status.st_mode & S_IFREG) && !(status.st_mode & S_IFDIR)) { - // not a file or directory: skip - continue; - } - // invoke callback - callback(name, status.st_mode & S_IFDIR); - } - closedir(dir); - return true; +inline bool operator<(const StringPiece& x, const StringPiece& y) { + StringPiece::size_type min_size = std::min(x.size(), y.size()); + int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size); + return (r < 0) || (r == 0 && x.size() < y.size()); } -void LocalFileSystem::FileSync(FileHandle &handle) { - int fd = ((UnixFileHandle &)handle).fd; - if (fsync(fd) != 0) { - throw FatalException("fsync failed!"); - } +inline bool operator>(const StringPiece& x, const StringPiece& y) { + return y < x; } -void LocalFileSystem::MoveFile(const string &source, const string &target) { - //! FIXME: rename does not guarantee atomicity or overwriting target file if it exists - if (rename(source.c_str(), target.c_str()) != 0) { - throw IOException("Could not rename file!"); - } +inline bool operator<=(const StringPiece& x, const StringPiece& y) { + return !(x > y); } -std::string LocalFileSystem::GetLastErrorAsString() { - return string(); +inline bool operator>=(const StringPiece& x, const StringPiece& y) { + return !(x < y); } -#else +// Allow StringPiece to be logged. +std::ostream& operator<<(std::ostream& o, const StringPiece& p); -constexpr char PIPE_PREFIX[] = "\\\\.\\pipe\\"; +} // namespace duckdb_re2 -// Returns the last Win32 error, in string format. Returns an empty string if there is no error. -std::string LocalFileSystem::GetLastErrorAsString() { - // Get the error message, if any. - DWORD errorMessageID = GetLastError(); - if (errorMessageID == 0) - return std::string(); // No error message has been recorded +#endif // RE2_STRINGPIECE_H_ - LPSTR messageBuffer = nullptr; - idx_t size = - FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); - std::string message(messageBuffer, size); +// LICENSE_CHANGE_END - // Free the buffer. - LocalFree(messageBuffer); - return message; -} +namespace duckdb_re2 { +class Prog; +class Regexp; +} // namespace duckdb_re2 -struct WindowsFileHandle : public FileHandle { -public: - WindowsFileHandle(FileSystem &file_system, string path, HANDLE fd) - : FileHandle(file_system, path), position(0), fd(fd) { - } - virtual ~WindowsFileHandle() { - Close(); - } +namespace duckdb_re2 { - idx_t position; - HANDLE fd; +// Interface for regular expression matching. Also corresponds to a +// pre-compiled regular expression. An "RE2" object is safe for +// concurrent use by multiple threads. +class RE2 { + public: + // We convert user-passed pointers into special Arg objects + class Arg; + class Options; -public: - void Close() override { - CloseHandle(fd); - }; -}; + // Defined in set.h. + class Set; -unique_ptr LocalFileSystem::OpenFile(const string &path, uint8_t flags, FileLockType lock_type, - FileCompressionType compression, FileOpener *opener) { - if (compression != FileCompressionType::UNCOMPRESSED) { - throw NotImplementedException("Unsupported compression type for default file system"); - } - AssertValidFileFlags(flags); + enum ErrorCode { + NoError = 0, - DWORD desired_access; - DWORD share_mode; - DWORD creation_disposition = OPEN_EXISTING; - DWORD flags_and_attributes = FILE_ATTRIBUTE_NORMAL; - bool open_read = flags & FileFlags::FILE_FLAGS_READ; - bool open_write = flags & FileFlags::FILE_FLAGS_WRITE; - if (open_read && open_write) { - desired_access = GENERIC_READ | GENERIC_WRITE; - share_mode = 0; - } else if (open_read) { - desired_access = GENERIC_READ; - share_mode = FILE_SHARE_READ; - } else if (open_write) { - desired_access = GENERIC_WRITE; - share_mode = 0; - } else { - throw InternalException("READ, WRITE or both should be specified when opening a file"); - } - if (open_write) { - if (flags & FileFlags::FILE_FLAGS_FILE_CREATE) { - creation_disposition = OPEN_ALWAYS; - } else if (flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW) { - creation_disposition = CREATE_ALWAYS; - } - } - if (flags & FileFlags::FILE_FLAGS_DIRECT_IO) { - flags_and_attributes |= FILE_FLAG_NO_BUFFERING; - } - auto unicode_path = WindowsUtil::UTF8ToUnicode(path.c_str()); - HANDLE hFile = CreateFileW(unicode_path.c_str(), desired_access, share_mode, NULL, creation_disposition, - flags_and_attributes, NULL); - if (hFile == INVALID_HANDLE_VALUE) { - auto error = LocalFileSystem::GetLastErrorAsString(); - throw IOException("Cannot open file \"%s\": %s", path.c_str(), error); - } - auto handle = make_unique(*this, path.c_str(), hFile); - if (flags & FileFlags::FILE_FLAGS_APPEND) { - auto file_size = GetFileSize(*handle); - SetFilePointer(*handle, file_size); - } - return move(handle); -} + // Unexpected error + ErrorInternal, -void LocalFileSystem::SetFilePointer(FileHandle &handle, idx_t location) { - ((WindowsFileHandle &)handle).position = location; -} + // Parse errors + ErrorBadEscape, // bad escape sequence + ErrorBadCharClass, // bad character class + ErrorBadCharRange, // bad character class range + ErrorMissingBracket, // missing closing ] + ErrorMissingParen, // missing closing ) + ErrorTrailingBackslash, // trailing \ at end of regexp + ErrorRepeatArgument, // repeat argument missing, e.g. "*" + ErrorRepeatSize, // bad repetition argument + ErrorRepeatOp, // bad repetition operator + ErrorBadPerlOp, // bad perl operator + ErrorBadUTF8, // invalid UTF-8 in regexp + ErrorBadNamedCapture, // bad named capture group + ErrorPatternTooLarge // pattern too large (compile failed) + }; -idx_t LocalFileSystem::GetFilePointer(FileHandle &handle) { - return ((WindowsFileHandle &)handle).position; -} + // Predefined common options. + // If you need more complicated things, instantiate + // an Option class, possibly passing one of these to + // the Option constructor, change the settings, and pass that + // Option class to the RE2 constructor. + enum CannedOptions { + DefaultOptions = 0, + Latin1, // treat input as Latin-1 (default UTF-8) + POSIX, // POSIX syntax, leftmost-longest match + Quiet // do not log about regexp parse errors + }; -static DWORD FSInternalRead(FileHandle &handle, HANDLE hFile, void *buffer, int64_t nr_bytes, idx_t location) { - DWORD bytes_read = 0; - OVERLAPPED ov = {}; - ov.Internal = 0; - ov.InternalHigh = 0; - ov.Offset = location & 0xFFFFFFFF; - ov.OffsetHigh = location >> 32; - ov.hEvent = 0; - auto rc = ReadFile(hFile, buffer, (DWORD)nr_bytes, &bytes_read, &ov); - if (!rc) { - auto error = LocalFileSystem::GetLastErrorAsString(); - throw IOException("Could not read file \"%s\" (error in ReadFile): %s", handle.path, error); - } - return bytes_read; -} + // Need to have the const char* and const std::string& forms for implicit + // conversions when passing string literals to FullMatch and PartialMatch. + // Otherwise the StringPiece form would be sufficient. +#ifndef SWIG + RE2(const char* pattern); + RE2(const std::string& pattern); +#endif + RE2(const StringPiece& pattern); + RE2(const StringPiece& pattern, const Options& options); + ~RE2(); -void LocalFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) { - HANDLE hFile = ((WindowsFileHandle &)handle).fd; - auto bytes_read = FSInternalRead(handle, hFile, buffer, nr_bytes, location); - if (bytes_read != nr_bytes) { - throw IOException("Could not read all bytes from file \"%s\": wanted=%lld read=%lld", handle.path, nr_bytes, - bytes_read); - } -} + // Returns whether RE2 was created properly. + bool ok() const { return error_code() == NoError; } -int64_t LocalFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes) { - HANDLE hFile = ((WindowsFileHandle &)handle).fd; - auto &pos = ((WindowsFileHandle &)handle).position; - auto n = std::min(std::max(GetFileSize(handle), pos) - pos, nr_bytes); - auto bytes_read = FSInternalRead(handle, hFile, buffer, n, pos); - pos += bytes_read; - return bytes_read; -} + // The string specification for this RE2. E.g. + // RE2 re("ab*c?d+"); + // re.pattern(); // "ab*c?d+" + const std::string& pattern() const { return pattern_; } -static DWORD FSInternalWrite(FileHandle &handle, HANDLE hFile, void *buffer, int64_t nr_bytes, idx_t location) { - DWORD bytes_written = 0; - OVERLAPPED ov = {}; - ov.Internal = 0; - ov.InternalHigh = 0; - ov.Offset = location & 0xFFFFFFFF; - ov.OffsetHigh = location >> 32; - ov.hEvent = 0; - auto rc = WriteFile(hFile, buffer, (DWORD)nr_bytes, &bytes_written, &ov); - if (!rc) { - auto error = LocalFileSystem::GetLastErrorAsString(); - throw IOException("Could not write file \"%s\" (error in WriteFile): %s", handle.path, error); - } - return bytes_written; -} + // If RE2 could not be created properly, returns an error string. + // Else returns the empty string. + const std::string& error() const { return *error_; } -void LocalFileSystem::Write(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) { - HANDLE hFile = ((WindowsFileHandle &)handle).fd; - auto bytes_written = FSInternalWrite(handle, hFile, buffer, nr_bytes, location); - if (bytes_written != nr_bytes) { - throw IOException("Could not write all bytes from file \"%s\": wanted=%lld wrote=%lld", handle.path, nr_bytes, - bytes_written); - } -} + // If RE2 could not be created properly, returns an error code. + // Else returns RE2::NoError (== 0). + ErrorCode error_code() const { return error_code_; } -int64_t LocalFileSystem::Write(FileHandle &handle, void *buffer, int64_t nr_bytes) { - HANDLE hFile = ((WindowsFileHandle &)handle).fd; - auto &pos = ((WindowsFileHandle &)handle).position; - auto bytes_written = FSInternalWrite(handle, hFile, buffer, nr_bytes, pos); - pos += bytes_written; - return bytes_written; -} + // If RE2 could not be created properly, returns the offending + // portion of the regexp. + const std::string& error_arg() const { return error_arg_; } -int64_t LocalFileSystem::GetFileSize(FileHandle &handle) { - HANDLE hFile = ((WindowsFileHandle &)handle).fd; - LARGE_INTEGER result; - if (!GetFileSizeEx(hFile, &result)) { - return -1; - } - return result.QuadPart; -} + // Returns the program size, a very approximate measure of a regexp's "cost". + // Larger numbers are more expensive than smaller numbers. + int ProgramSize() const; + int ReverseProgramSize() const; -time_t LocalFileSystem::GetLastModifiedTime(FileHandle &handle) { - HANDLE hFile = ((WindowsFileHandle &)handle).fd; + // EXPERIMENTAL! SUBJECT TO CHANGE! + // Outputs the program fanout as a histogram bucketed by powers of 2. + // Returns the number of the largest non-empty bucket. + int ProgramFanout(std::map* histogram) const; + int ReverseProgramFanout(std::map* histogram) const; - // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfiletime - FILETIME last_write; - if (GetFileTime(hFile, nullptr, nullptr, &last_write) == 0) { - return -1; - } + // Returns the underlying Regexp; not for general use. + // Returns entire_regexp_ so that callers don't need + // to know about prefix_ and prefix_foldcase_. + duckdb_re2::Regexp* Regexp() const { return entire_regexp_; } - // https://stackoverflow.com/questions/29266743/what-is-dwlowdatetime-and-dwhighdatetime - ULARGE_INTEGER ul; - ul.LowPart = last_write.dwLowDateTime; - ul.HighPart = last_write.dwHighDateTime; - int64_t fileTime64 = ul.QuadPart; + /***** The array-based matching interface ******/ - // fileTime64 contains a 64-bit value representing the number of - // 100-nanosecond intervals since January 1, 1601 (UTC). - // https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + // The functions here have names ending in 'N' and are used to implement + // the functions whose names are the prefix before the 'N'. It is sometimes + // useful to invoke them directly, but the syntax is awkward, so the 'N'-less + // versions should be preferred. + static bool FullMatchN(const StringPiece& text, const RE2& re, + const Arg* const args[], int n); + static bool PartialMatchN(const StringPiece& text, const RE2& re, + const Arg* const args[], int n); + static bool ConsumeN(StringPiece* input, const RE2& re, + const Arg* const args[], int n); + static bool FindAndConsumeN(StringPiece* input, const RE2& re, + const Arg* const args[], int n); - // Adapted from: https://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux - const auto WINDOWS_TICK = 10000000; - const auto SEC_TO_UNIX_EPOCH = 11644473600LL; - time_t result = (fileTime64 / WINDOWS_TICK - SEC_TO_UNIX_EPOCH); - return result; -} +#ifndef SWIG + private: + template + static inline bool Apply(F f, SP sp, const RE2& re) { + return f(sp, re, NULL, 0); + } -void LocalFileSystem::Truncate(FileHandle &handle, int64_t new_size) { - HANDLE hFile = ((WindowsFileHandle &)handle).fd; - // seek to the location - SetFilePointer(handle, new_size); - // now set the end of file position - if (!SetEndOfFile(hFile)) { - auto error = LocalFileSystem::GetLastErrorAsString(); - throw IOException("Failure in SetEndOfFile call on file \"%s\": %s", handle.path, error); - } -} + template + static inline bool Apply(F f, SP sp, const RE2& re, const A&... a) { + const Arg* const args[] = {&a...}; + const int n = sizeof...(a); + return f(sp, re, args, n); + } -static DWORD WindowsGetFileAttributes(const string &filename) { - auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str()); - return GetFileAttributesW(unicode_path.c_str()); -} + public: + // In order to allow FullMatch() et al. to be called with a varying number + // of arguments of varying types, we use two layers of variadic templates. + // The first layer constructs the temporary Arg objects. The second layer + // (above) constructs the array of pointers to the temporary Arg objects. -bool LocalFileSystem::DirectoryExists(const string &directory) { - DWORD attrs = WindowsGetFileAttributes(directory); - return (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)); -} + /***** The useful part: the matching interface *****/ -void LocalFileSystem::CreateDirectory(const string &directory) { - if (DirectoryExists(directory)) { - return; - } - auto unicode_path = WindowsUtil::UTF8ToUnicode(directory.c_str()); - if (directory.empty() || !CreateDirectoryW(unicode_path.c_str(), NULL) || !DirectoryExists(directory)) { - throw IOException("Could not create directory!"); - } -} + // Matches "text" against "re". If pointer arguments are + // supplied, copies matched sub-patterns into them. + // + // You can pass in a "const char*" or a "std::string" for "text". + // You can pass in a "const char*" or a "std::string" or a "RE2" for "re". + // + // The provided pointer arguments can be pointers to any scalar numeric + // type, or one of: + // std::string (matched piece is copied to string) + // StringPiece (StringPiece is mutated to point to matched piece) + // T (where "bool T::ParseFrom(const char*, size_t)" exists) + // (void*)NULL (the corresponding matched sub-pattern is not copied) + // + // Returns true iff all of the following conditions are satisfied: + // a. "text" matches "re" exactly + // b. The number of matched sub-patterns is >= number of supplied pointers + // c. The "i"th argument has a suitable type for holding the + // string captured as the "i"th sub-pattern. If you pass in + // NULL for the "i"th argument, or pass fewer arguments than + // number of sub-patterns, "i"th captured sub-pattern is + // ignored. + // + // CAVEAT: An optional sub-pattern that does not exist in the + // matched string is assigned the empty string. Therefore, the + // following will return false (because the empty string is not a + // valid number): + // int number; + // RE2::FullMatch("abc", "[a-z]+(\\d+)?", &number); + template + static bool FullMatch(const StringPiece& text, const RE2& re, A&&... a) { + return Apply(FullMatchN, text, re, Arg(std::forward(a))...); + } -static void DeleteDirectoryRecursive(FileSystem &fs, string directory) { - fs.ListFiles(directory, [&](const string &fname, bool is_directory) { - if (is_directory) { - DeleteDirectoryRecursive(fs, fs.JoinPath(directory, fname)); - } else { - fs.RemoveFile(fs.JoinPath(directory, fname)); - } - }); - auto unicode_path = WindowsUtil::UTF8ToUnicode(directory.c_str()); - if (!RemoveDirectoryW(unicode_path.c_str())) { - throw IOException("Failed to delete directory"); - } -} + // Exactly like FullMatch(), except that "re" is allowed to match + // a substring of "text". + template + static bool PartialMatch(const StringPiece& text, const RE2& re, A&&... a) { + return Apply(PartialMatchN, text, re, Arg(std::forward(a))...); + } -void LocalFileSystem::RemoveDirectory(const string &directory) { - if (FileExists(directory)) { - throw IOException("Attempting to delete directory \"%s\", but it is a file and not a directory!", directory); - } - if (!DirectoryExists(directory)) { - return; - } - DeleteDirectoryRecursive(*this, directory.c_str()); -} + // Like FullMatch() and PartialMatch(), except that "re" has to match + // a prefix of the text, and "input" is advanced past the matched + // text. Note: "input" is modified iff this routine returns true + // and "re" matched a non-empty substring of "text". + template + static bool Consume(StringPiece* input, const RE2& re, A&&... a) { + return Apply(ConsumeN, input, re, Arg(std::forward(a))...); + } -void LocalFileSystem::RemoveFile(const string &filename) { - auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str()); - DeleteFileW(unicode_path.c_str()); -} + // Like Consume(), but does not anchor the match at the beginning of + // the text. That is, "re" need not start its match at the beginning + // of "input". For example, "FindAndConsume(s, "(\\w+)", &word)" finds + // the next word in "s" and stores it in "word". + template + static bool FindAndConsume(StringPiece* input, const RE2& re, A&&... a) { + return Apply(FindAndConsumeN, input, re, Arg(std::forward(a))...); + } +#endif -bool LocalFileSystem::ListFiles(const string &directory, const std::function &callback) { - string search_dir = JoinPath(directory, "*"); + // Replace the first match of "re" in "str" with "rewrite". + // Within "rewrite", backslash-escaped digits (\1 to \9) can be + // used to insert text matching corresponding parenthesized group + // from the pattern. \0 in "rewrite" refers to the entire matching + // text. E.g., + // + // std::string s = "yabba dabba doo"; + // CHECK(RE2::Replace(&s, "b+", "d")); + // + // will leave "s" containing "yada dabba doo" + // + // Returns true if the pattern matches and a replacement occurs, + // false otherwise. + static bool Replace(std::string* str, + const RE2& re, + const StringPiece& rewrite); - auto unicode_path = WindowsUtil::UTF8ToUnicode(search_dir.c_str()); + // Like Replace(), except replaces successive non-overlapping occurrences + // of the pattern in the string with the rewrite. E.g. + // + // std::string s = "yabba dabba doo"; + // CHECK(RE2::GlobalReplace(&s, "b+", "d")); + // + // will leave "s" containing "yada dada doo" + // Replacements are not subject to re-matching. + // + // Because GlobalReplace only replaces non-overlapping matches, + // replacing "ana" within "banana" makes only one replacement, not two. + // + // Returns the number of replacements made. + static int GlobalReplace(std::string* str, + const RE2& re, + const StringPiece& rewrite); - WIN32_FIND_DATAW ffd; - HANDLE hFind = FindFirstFileW(unicode_path.c_str(), &ffd); - if (hFind == INVALID_HANDLE_VALUE) { - return false; - } - do { - string cFileName = WindowsUtil::UnicodeToUTF8(ffd.cFileName); - if (cFileName == "." || cFileName == "..") { - continue; - } - callback(cFileName, ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); - } while (FindNextFileW(hFind, &ffd) != 0); + // Like Replace, except that if the pattern matches, "rewrite" + // is copied into "out" with substitutions. The non-matching + // portions of "text" are ignored. + // + // Returns true iff a match occurred and the extraction happened + // successfully; if no match occurs, the string is left unaffected. + // + // REQUIRES: "text" must not alias any part of "*out". + static bool Extract(const StringPiece& text, + const RE2& re, + const StringPiece& rewrite, + std::string* out); - DWORD dwError = GetLastError(); - if (dwError != ERROR_NO_MORE_FILES) { - FindClose(hFind); - return false; - } + // Escapes all potentially meaningful regexp characters in + // 'unquoted'. The returned string, used as a regular expression, + // will exactly match the original string. For example, + // 1.5-2.0? + // may become: + // 1\.5\-2\.0\? + static std::string QuoteMeta(const StringPiece& unquoted); - FindClose(hFind); - return true; -} + // Computes range for any strings matching regexp. The min and max can in + // some cases be arbitrarily precise, so the caller gets to specify the + // maximum desired length of string returned. + // + // Assuming PossibleMatchRange(&min, &max, N) returns successfully, any + // string s that is an anchored match for this regexp satisfies + // min <= s && s <= max. + // + // Note that PossibleMatchRange() will only consider the first copy of an + // infinitely repeated element (i.e., any regexp element followed by a '*' or + // '+' operator). Regexps with "{N}" constructions are not affected, as those + // do not compile down to infinite repetitions. + // + // Returns true on success, false on error. + bool PossibleMatchRange(std::string* min, std::string* max, + int maxlen) const; -void LocalFileSystem::FileSync(FileHandle &handle) { - HANDLE hFile = ((WindowsFileHandle &)handle).fd; - if (FlushFileBuffers(hFile) == 0) { - throw IOException("Could not flush file handle to disk!"); - } -} + // Generic matching interface -void LocalFileSystem::MoveFile(const string &source, const string &target) { - auto source_unicode = WindowsUtil::UTF8ToUnicode(source.c_str()); - auto target_unicode = WindowsUtil::UTF8ToUnicode(target.c_str()); - if (!MoveFileW(source_unicode.c_str(), target_unicode.c_str())) { - throw IOException("Could not move file"); - } -} + // Type of match. + enum Anchor { + UNANCHORED, // No anchoring + ANCHOR_START, // Anchor at start only + ANCHOR_BOTH // Anchor at start and end + }; -FileType LocalFileSystem::GetFileType(FileHandle &handle) { - auto path = ((WindowsFileHandle &)handle).path; - // pipes in windows are just files in '\\.\pipe\' folder - if (strncmp(path.c_str(), PIPE_PREFIX, strlen(PIPE_PREFIX)) == 0) { - return FileType::FILE_TYPE_FIFO; - } - DWORD attrs = WindowsGetFileAttributes(path.c_str()); - if (attrs != INVALID_FILE_ATTRIBUTES) { - if (attrs & FILE_ATTRIBUTE_DIRECTORY) { - return FileType::FILE_TYPE_DIR; - } else { - return FileType::FILE_TYPE_REGULAR; - } - } - return FileType::FILE_TYPE_INVALID; -} -#endif + // Return the number of capturing subpatterns, or -1 if the + // regexp wasn't valid on construction. The overall match ($0) + // does not count: if the regexp is "(a)(b)", returns 2. + int NumberOfCapturingGroups() const { return num_captures_; } -bool LocalFileSystem::CanSeek() { - return true; -} + // Return a map from names to capturing indices. + // The map records the index of the leftmost group + // with the given name. + // Only valid until the re is deleted. + const std::map& NamedCapturingGroups() const; -bool LocalFileSystem::OnDiskFile(FileHandle &handle) { - return true; -} + // Return a map from capturing indices to names. + // The map has no entries for unnamed groups. + // Only valid until the re is deleted. + const std::map& CapturingGroupNames() const; -void LocalFileSystem::Seek(FileHandle &handle, idx_t location) { - if (!CanSeek()) { - throw IOException("Cannot seek in files of this type"); - } - SetFilePointer(handle, location); -} + // General matching routine. + // Match against text starting at offset startpos + // and stopping the search at offset endpos. + // Returns true if match found, false if not. + // On a successful match, fills in submatch[] (up to nsubmatch entries) + // with information about submatches. + // I.e. matching RE2("(foo)|(bar)baz") on "barbazbla" will return true, with + // submatch[0] = "barbaz", submatch[1].data() = NULL, submatch[2] = "bar", + // submatch[3].data() = NULL, ..., up to submatch[nsubmatch-1].data() = NULL. + // Caveat: submatch[] may be clobbered even on match failure. + // + // Don't ask for more match information than you will use: + // runs much faster with nsubmatch == 1 than nsubmatch > 1, and + // runs even faster if nsubmatch == 0. + // Doesn't make sense to use nsubmatch > 1 + NumberOfCapturingGroups(), + // but will be handled correctly. + // + // Passing text == StringPiece(NULL, 0) will be handled like any other + // empty string, but note that on return, it will not be possible to tell + // whether submatch i matched the empty string or did not match: + // either way, submatch[i].data() == NULL. + bool Match(const StringPiece& text, + size_t startpos, + size_t endpos, + Anchor re_anchor, + StringPiece* submatch, + int nsubmatch) const; -idx_t LocalFileSystem::SeekPosition(FileHandle &handle) { - if (!CanSeek()) { - throw IOException("Cannot seek in files of this type"); - } - return GetFilePointer(handle); -} + // Check that the given rewrite string is suitable for use with this + // regular expression. It checks that: + // * The regular expression has enough parenthesized subexpressions + // to satisfy all of the \N tokens in rewrite + // * The rewrite string doesn't have any syntax errors. E.g., + // '\' followed by anything other than a digit or '\'. + // A true return value guarantees that Replace() and Extract() won't + // fail because of a bad rewrite string. + bool CheckRewriteString(const StringPiece& rewrite, + std::string* error) const; -static bool HasGlob(const string &str) { - for (idx_t i = 0; i < str.size(); i++) { - switch (str[i]) { - case '*': - case '?': - case '[': - return true; - default: - break; - } - } - return false; -} + // Returns the maximum submatch needed for the rewrite to be done by + // Replace(). E.g. if rewrite == "foo \\2,\\1", returns 2. + static int MaxSubmatch(const StringPiece& rewrite); -static void GlobFiles(FileSystem &fs, const string &path, const string &glob, bool match_directory, - vector &result, bool join_path) { - fs.ListFiles(path, [&](const string &fname, bool is_directory) { - if (is_directory != match_directory) { - return; - } - if (LikeFun::Glob(fname.c_str(), fname.size(), glob.c_str(), glob.size())) { - if (join_path) { - result.push_back(fs.JoinPath(path, fname)); - } else { - result.push_back(fname); - } - } - }); + // Append the "rewrite" string, with backslash subsitutions from "vec", + // to string "out". + // Returns true on success. This method can fail because of a malformed + // rewrite string. CheckRewriteString guarantees that the rewrite will + // be sucessful. + bool Rewrite(std::string* out, + const StringPiece& rewrite, + const StringPiece* vec, + int veclen) const; + + // Constructor options + class Options { + public: + // The options are (defaults in parentheses): + // + // utf8 (true) text and pattern are UTF-8; otherwise Latin-1 + // posix_syntax (false) restrict regexps to POSIX egrep syntax + // longest_match (false) search for longest match, not first match + // log_errors (true) log syntax and execution errors to ERROR + // max_mem (see below) approx. max memory footprint of RE2 + // literal (false) interpret string as literal, not regexp + // never_nl (false) never match \n, even if it is in regexp + // dot_nl (false) dot matches everything including new line + // never_capture (false) parse all parens as non-capturing + // case_sensitive (true) match is case-sensitive (regexp can override + // with (?i) unless in posix_syntax mode) + // + // The following options are only consulted when posix_syntax == true. + // When posix_syntax == false, these features are always enabled and + // cannot be turned off; to perform multi-line matching in that case, + // begin the regexp with (?m). + // perl_classes (false) allow Perl's \d \s \w \D \S \W + // word_boundary (false) allow Perl's \b \B (word boundary and not) + // one_line (false) ^ and $ only match beginning and end of text + // + // The max_mem option controls how much memory can be used + // to hold the compiled form of the regexp (the Prog) and + // its cached DFA graphs. Code Search placed limits on the number + // of Prog instructions and DFA states: 10,000 for both. + // In RE2, those limits would translate to about 240 KB per Prog + // and perhaps 2.5 MB per DFA (DFA state sizes vary by regexp; RE2 does a + // better job of keeping them small than Code Search did). + // Each RE2 has two Progs (one forward, one reverse), and each Prog + // can have two DFAs (one first match, one longest match). + // That makes 4 DFAs: + // + // forward, first-match - used for UNANCHORED or ANCHOR_START searches + // if opt.longest_match() == false + // forward, longest-match - used for all ANCHOR_BOTH searches, + // and the other two kinds if + // opt.longest_match() == true + // reverse, first-match - never used + // reverse, longest-match - used as second phase for unanchored searches + // + // The RE2 memory budget is statically divided between the two + // Progs and then the DFAs: two thirds to the forward Prog + // and one third to the reverse Prog. The forward Prog gives half + // of what it has left over to each of its DFAs. The reverse Prog + // gives it all to its longest-match DFA. + // + // Once a DFA fills its budget, it flushes its cache and starts over. + // If this happens too often, RE2 falls back on the NFA implementation. + + // For now, make the default budget something close to Code Search. + static const int kDefaultMaxMem = 8<<20; + + enum Encoding { + EncodingUTF8 = 1, + EncodingLatin1 + }; + + Options() : + encoding_(EncodingUTF8), + posix_syntax_(false), + longest_match_(false), + log_errors_(true), + max_mem_(kDefaultMaxMem), + literal_(false), + never_nl_(false), + dot_nl_(false), + never_capture_(false), + case_sensitive_(true), + perl_classes_(false), + word_boundary_(false), + one_line_(false) { + } + + /*implicit*/ Options(CannedOptions); + + Encoding encoding() const { return encoding_; } + void set_encoding(Encoding encoding) { encoding_ = encoding; } + + // Legacy interface to encoding. + // TODO(rsc): Remove once clients have been converted. + bool utf8() const { return encoding_ == EncodingUTF8; } + void set_utf8(bool b) { + if (b) { + encoding_ = EncodingUTF8; + } else { + encoding_ = EncodingLatin1; + } + } + + bool posix_syntax() const { return posix_syntax_; } + void set_posix_syntax(bool b) { posix_syntax_ = b; } + + bool longest_match() const { return longest_match_; } + void set_longest_match(bool b) { longest_match_ = b; } + + bool log_errors() const { return log_errors_; } + void set_log_errors(bool b) { log_errors_ = b; } + + int64_t max_mem() const { return max_mem_; } + void set_max_mem(int64_t m) { max_mem_ = m; } + + bool literal() const { return literal_; } + void set_literal(bool b) { literal_ = b; } + + bool never_nl() const { return never_nl_; } + void set_never_nl(bool b) { never_nl_ = b; } + + bool dot_nl() const { return dot_nl_; } + void set_dot_nl(bool b) { dot_nl_ = b; } + + bool never_capture() const { return never_capture_; } + void set_never_capture(bool b) { never_capture_ = b; } + + bool case_sensitive() const { return case_sensitive_; } + void set_case_sensitive(bool b) { case_sensitive_ = b; } + + bool perl_classes() const { return perl_classes_; } + void set_perl_classes(bool b) { perl_classes_ = b; } + + bool word_boundary() const { return word_boundary_; } + void set_word_boundary(bool b) { word_boundary_ = b; } + + bool one_line() const { return one_line_; } + void set_one_line(bool b) { one_line_ = b; } + + void Copy(const Options& src) { + *this = src; + } + + int ParseFlags() const; + + private: + Encoding encoding_; + bool posix_syntax_; + bool longest_match_; + bool log_errors_; + int64_t max_mem_; + bool literal_; + bool never_nl_; + bool dot_nl_; + bool never_capture_; + bool case_sensitive_; + bool perl_classes_; + bool word_boundary_; + bool one_line_; + }; + + // Returns the options set in the constructor. + const Options& options() const { return options_; } + + // Argument converters; see below. + static inline Arg CRadix(short* x); + static inline Arg CRadix(unsigned short* x); + static inline Arg CRadix(int* x); + static inline Arg CRadix(unsigned int* x); + static inline Arg CRadix(long* x); + static inline Arg CRadix(unsigned long* x); + static inline Arg CRadix(long long* x); + static inline Arg CRadix(unsigned long long* x); + + static inline Arg Hex(short* x); + static inline Arg Hex(unsigned short* x); + static inline Arg Hex(int* x); + static inline Arg Hex(unsigned int* x); + static inline Arg Hex(long* x); + static inline Arg Hex(unsigned long* x); + static inline Arg Hex(long long* x); + static inline Arg Hex(unsigned long long* x); + + static inline Arg Octal(short* x); + static inline Arg Octal(unsigned short* x); + static inline Arg Octal(int* x); + static inline Arg Octal(unsigned int* x); + static inline Arg Octal(long* x); + static inline Arg Octal(unsigned long* x); + static inline Arg Octal(long long* x); + static inline Arg Octal(unsigned long long* x); + + private: + void Init(const StringPiece& pattern, const Options& options); + + bool DoMatch(const StringPiece& text, + Anchor re_anchor, + size_t* consumed, + const Arg* const args[], + int n) const; + + duckdb_re2::Prog* ReverseProg() const; + + std::string pattern_; // string regular expression + Options options_; // option flags + std::string prefix_; // required prefix (before regexp_) + bool prefix_foldcase_; // prefix is ASCII case-insensitive + duckdb_re2::Regexp* entire_regexp_; // parsed regular expression + duckdb_re2::Regexp* suffix_regexp_; // parsed regular expression, prefix removed + duckdb_re2::Prog* prog_; // compiled program for regexp + int num_captures_; // Number of capturing groups + bool is_one_pass_; // can use prog_->SearchOnePass? + + mutable duckdb_re2::Prog* rprog_; // reverse program for regexp + mutable const std::string* error_; // Error indicator + // (or points to empty string) + mutable ErrorCode error_code_; // Error code + mutable std::string error_arg_; // Fragment of regexp showing error + + // Map from capture names to indices + mutable const std::map* named_groups_; + + // Map from capture indices to names + mutable const std::map* group_names_; + + // Onces for lazy computations. + mutable std::once_flag rprog_once_; + mutable std::once_flag named_groups_once_; + mutable std::once_flag group_names_once_; + + RE2(const RE2&) = delete; + RE2& operator=(const RE2&) = delete; +}; + +/***** Implementation details *****/ + +// Hex/Octal/Binary? + +// Special class for parsing into objects that define a ParseFrom() method +template +class _RE2_MatchObject { + public: + static inline bool Parse(const char* str, size_t n, void* dest) { + if (dest == NULL) return true; + T* object = reinterpret_cast(dest); + return object->ParseFrom(str, n); + } +}; + +class RE2::Arg { + public: + // Empty constructor so we can declare arrays of RE2::Arg + Arg(); + + // Constructor specially designed for NULL arguments + Arg(void*); + Arg(std::nullptr_t); + + typedef bool (*Parser)(const char* str, size_t n, void* dest); + +// Type-specific parsers +#define MAKE_PARSER(type, name) \ + Arg(type* p) : arg_(p), parser_(name) {} \ + Arg(type* p, Parser parser) : arg_(p), parser_(parser) {} + + MAKE_PARSER(char, parse_char) + MAKE_PARSER(signed char, parse_schar) + MAKE_PARSER(unsigned char, parse_uchar) + MAKE_PARSER(float, parse_float) + MAKE_PARSER(double, parse_double) + MAKE_PARSER(std::string, parse_string) + MAKE_PARSER(StringPiece, parse_stringpiece) + + MAKE_PARSER(short, parse_short) + MAKE_PARSER(unsigned short, parse_ushort) + MAKE_PARSER(int, parse_int) + MAKE_PARSER(unsigned int, parse_uint) + MAKE_PARSER(long, parse_long) + MAKE_PARSER(unsigned long, parse_ulong) + MAKE_PARSER(long long, parse_longlong) + MAKE_PARSER(unsigned long long, parse_ulonglong) + +#undef MAKE_PARSER + + // Generic constructor templates + template Arg(T* p) + : arg_(p), parser_(_RE2_MatchObject::Parse) { } + template Arg(T* p, Parser parser) + : arg_(p), parser_(parser) { } + + // Parse the data + bool Parse(const char* str, size_t n) const; + + private: + void* arg_; + Parser parser_; + + static bool parse_null (const char* str, size_t n, void* dest); + static bool parse_char (const char* str, size_t n, void* dest); + static bool parse_schar (const char* str, size_t n, void* dest); + static bool parse_uchar (const char* str, size_t n, void* dest); + static bool parse_float (const char* str, size_t n, void* dest); + static bool parse_double (const char* str, size_t n, void* dest); + static bool parse_string (const char* str, size_t n, void* dest); + static bool parse_stringpiece (const char* str, size_t n, void* dest); + +#define DECLARE_INTEGER_PARSER(name) \ + private: \ + static bool parse_##name(const char* str, size_t n, void* dest); \ + static bool parse_##name##_radix(const char* str, size_t n, void* dest, \ + int radix); \ + \ + public: \ + static bool parse_##name##_hex(const char* str, size_t n, void* dest); \ + static bool parse_##name##_octal(const char* str, size_t n, void* dest); \ + static bool parse_##name##_cradix(const char* str, size_t n, void* dest); + + DECLARE_INTEGER_PARSER(short) + DECLARE_INTEGER_PARSER(ushort) + DECLARE_INTEGER_PARSER(int) + DECLARE_INTEGER_PARSER(uint) + DECLARE_INTEGER_PARSER(long) + DECLARE_INTEGER_PARSER(ulong) + DECLARE_INTEGER_PARSER(longlong) + DECLARE_INTEGER_PARSER(ulonglong) + +#undef DECLARE_INTEGER_PARSER + +}; + +inline RE2::Arg::Arg() : arg_(NULL), parser_(parse_null) { } +inline RE2::Arg::Arg(void* p) : arg_(p), parser_(parse_null) { } +inline RE2::Arg::Arg(std::nullptr_t p) : arg_(p), parser_(parse_null) { } + +inline bool RE2::Arg::Parse(const char* str, size_t n) const { + return (*parser_)(str, n, arg_); } -vector LocalFileSystem::Glob(const string &path, FileOpener *opener) { - if (path.empty()) { - return vector(); +// This part of the parser, appropriate only for ints, deals with bases +#define MAKE_INTEGER_PARSER(type, name) \ + inline RE2::Arg RE2::Hex(type* ptr) { \ + return RE2::Arg(ptr, RE2::Arg::parse_##name##_hex); \ + } \ + inline RE2::Arg RE2::Octal(type* ptr) { \ + return RE2::Arg(ptr, RE2::Arg::parse_##name##_octal); \ + } \ + inline RE2::Arg RE2::CRadix(type* ptr) { \ + return RE2::Arg(ptr, RE2::Arg::parse_##name##_cradix); \ + } + +MAKE_INTEGER_PARSER(short, short) +MAKE_INTEGER_PARSER(unsigned short, ushort) +MAKE_INTEGER_PARSER(int, int) +MAKE_INTEGER_PARSER(unsigned int, uint) +MAKE_INTEGER_PARSER(long, long) +MAKE_INTEGER_PARSER(unsigned long, ulong) +MAKE_INTEGER_PARSER(long long, longlong) +MAKE_INTEGER_PARSER(unsigned long long, ulonglong) + +#undef MAKE_INTEGER_PARSER + +#ifndef SWIG + + +// Helper for writing global or static RE2s safely. +// Write +// static LazyRE2 re = {".*"}; +// and then use *re instead of writing +// static RE2 re(".*"); +// The former is more careful about multithreaded +// situations than the latter. +// +// N.B. This class never deletes the RE2 object that +// it constructs: that's a feature, so that it can be used +// for global and function static variables. +class LazyRE2 { + private: + struct NoArg {}; + + public: + typedef RE2 element_type; // support std::pointer_traits + + // Constructor omitted to preserve braced initialization in C++98. + + // Pretend to be a pointer to Type (never NULL due to on-demand creation): + RE2& operator*() const { return *get(); } + RE2* operator->() const { return get(); } + + // Named accessor/initializer: + RE2* get() const { + std::call_once(once_, &LazyRE2::Init, this); + return ptr_; + } + + // All data fields must be public to support {"foo"} initialization. + const char* pattern_; + RE2::CannedOptions options_; + NoArg barrier_against_excess_initializers_; + + mutable RE2* ptr_; + mutable std::once_flag once_; + + private: + static void Init(const LazyRE2* lazy_re2) { + lazy_re2->ptr_ = new RE2(lazy_re2->pattern_, lazy_re2->options_); + } + + void operator=(const LazyRE2&); // disallowed +}; +#endif // SWIG + +} // namespace duckdb_re2 + +using duckdb_re2::RE2; +using duckdb_re2::LazyRE2; + +#endif // RE2_RE2_H_ + + +// LICENSE_CHANGE_END + + +namespace duckdb { + +class HivePartitioning { +public: + //! Parse a filename that follows the hive partitioning scheme + DUCKDB_API static std::map Parse(string &filename); + //! Prunes a list of filenames based on a set of filters, can be used by TableFunctions in the + //! pushdown_complex_filter function to skip files with filename-based filters. Also removes the filters that always + //! evaluate to true. + DUCKDB_API static void ApplyFiltersToFileList(vector &files, vector> &filters, + unordered_map &column_map, idx_t table_index, + bool hive_enabled, bool filename_enabled); +}; + +} // namespace duckdb + + + + + + + + +#include + +namespace duckdb { + +static unordered_map GetKnownColumnValues(string &filename, + unordered_map &column_map, + bool filename_col, bool hive_partition_cols) { + unordered_map result; + + if (filename_col) { + auto lookup_column_id = column_map.find("filename"); + if (lookup_column_id != column_map.end()) { + result[lookup_column_id->second] = filename; + } } - // split up the path into separate chunks - vector splits; - idx_t last_pos = 0; - for (idx_t i = 0; i < path.size(); i++) { - if (path[i] == '\\' || path[i] == '/') { - if (i == last_pos) { - // empty: skip this position - last_pos = i + 1; - continue; - } - if (splits.empty()) { - splits.push_back(path.substr(0, i)); - } else { - splits.push_back(path.substr(last_pos, i - last_pos)); + + if (hive_partition_cols) { + auto partitions = HivePartitioning::Parse(filename); + for (auto &partition : partitions) { + auto lookup_column_id = column_map.find(partition.first); + if (lookup_column_id != column_map.end()) { + result[lookup_column_id->second] = partition.second; } - last_pos = i + 1; } } - splits.push_back(path.substr(last_pos, path.size() - last_pos)); - // handle absolute paths - bool absolute_path = false; - if (path[0] == '/') { - // first character is a slash - unix absolute path - absolute_path = true; - } else if (StringUtil::Contains(splits[0], ":")) { - // first split has a colon - windows absolute path - absolute_path = true; - } else if (splits[0] == "~") { - // starts with home directory - auto home_directory = GetHomeDirectory(); - if (!home_directory.empty()) { - absolute_path = true; - splits[0] = home_directory; + + return result; +} + +// Takes an expression and converts a list of known column_refs to constants +static void ConvertKnownColRefToConstants(unique_ptr &expr, + unordered_map &known_column_values, idx_t table_index) { + if (expr->type == ExpressionType::BOUND_COLUMN_REF) { + auto &bound_colref = (BoundColumnRefExpression &)*expr; + + // This bound column ref is for another table + if (table_index != bound_colref.binding.table_index) { + return; } - } - // Check if the path has a glob at all - if (!HasGlob(path)) { - // no glob: return only the file (if it exists or is a pipe) - vector result; - if (FileExists(path) || IsPipe(path)) { - result.push_back(path); - } else if (!absolute_path) { - Value value; - if (opener->TryGetCurrentSetting("file_search_path", value)) { - auto search_paths_str = value.ToString(); - std::vector search_paths = StringUtil::Split(search_paths_str, ','); - for (const auto &search_path : search_paths) { - auto joined_path = JoinPath(search_path, path); - if (FileExists(joined_path) || IsPipe(joined_path)) { - result.push_back(joined_path); - } - } - } + + auto lookup = known_column_values.find(bound_colref.binding.column_index); + if (lookup != known_column_values.end()) { + expr = make_unique(Value(lookup->second)); } - return result; + } else { + ExpressionIterator::EnumerateChildren(*expr, [&](unique_ptr &child) { + ConvertKnownColRefToConstants(child, known_column_values, table_index); + }); } - vector previous_directories; - if (absolute_path) { - // for absolute paths, we don't start by scanning the current directory - previous_directories.push_back(splits[0]); +} + +// matches hive partitions in file name. For example: +// - s3://bucket/var1=value1/bla/bla/var2=value2 +// - http(s)://domain(:port)/lala/kasdl/var1=value1/?not-a-var=not-a-value +// - folder/folder/folder/../var1=value1/etc/.//var2=value2 +std::map HivePartitioning::Parse(string &filename) { + std::map result; + + string regex = "[\\/\\\\]([^\\/\\?\\\\]+)=([^\\/\\n\\?\\\\]+)"; + duckdb_re2::StringPiece input(filename); // Wrap a StringPiece around it + + string var; + string value; + while (RE2::FindAndConsume(&input, regex, &var, &value)) { + result.insert(std::pair(var, value)); } - for (idx_t i = absolute_path ? 1 : 0; i < splits.size(); i++) { - bool is_last_chunk = i + 1 == splits.size(); - bool has_glob = HasGlob(splits[i]); - // if it's the last chunk we need to find files, otherwise we find directories - // not the last chunk: gather a list of all directories that match the glob pattern - vector result; - if (!has_glob) { - // no glob, just append as-is - if (previous_directories.empty()) { - result.push_back(splits[i]); - } else { - for (auto &prev_directory : previous_directories) { - result.push_back(JoinPath(prev_directory, splits[i])); - } + return result; +} + +// TODO: this can still be improved by removing the parts of filter expressions that are true for all remaining files. +// currently, only expressions that cannot be evaluated during pushdown are removed. +void HivePartitioning::ApplyFiltersToFileList(vector &files, vector> &filters, + unordered_map &column_map, idx_t table_index, + bool hive_enabled, bool filename_enabled) { + vector pruned_files; + vector> pruned_filters; + + if ((!filename_enabled && !hive_enabled) || filters.empty()) { + return; + } + + for (idx_t i = 0; i < files.size(); i++) { + auto &file = files[i]; + bool should_prune_file = false; + auto known_values = GetKnownColumnValues(file, column_map, filename_enabled, hive_enabled); + + FilterCombiner combiner; + for (auto &filter : filters) { + unique_ptr filter_copy = filter->Copy(); + ConvertKnownColRefToConstants(filter_copy, known_values, table_index); + // Evaluate the filter, if it can be evaluated here, we can not prune this filter + Value result_value; + if (!filter_copy->IsScalar() || !filter_copy->IsFoldable() || + !ExpressionExecutor::TryEvaluateScalar(*filter_copy, result_value)) { + // can not be evaluated only with the filename/hive columns added, we can not prune this filter + pruned_filters.emplace_back(filter->Copy()); + } else if (!result_value.GetValue()) { + // filter evaluates to false + should_prune_file = true; } - } else { - if (previous_directories.empty()) { - // no previous directories: list in the current path - GlobFiles(*this, ".", splits[i], !is_last_chunk, result, false); - } else { - // previous directories - // we iterate over each of the previous directories, and apply the glob of the current directory - for (auto &prev_directory : previous_directories) { - GlobFiles(*this, prev_directory, splits[i], !is_last_chunk, result, true); - } + + // Use filter combiner to determine that this filter makes + if (!should_prune_file && combiner.AddFilter(std::move(filter_copy)) == FilterResult::UNSATISFIABLE) { + should_prune_file = true; } } - if (is_last_chunk || result.empty()) { - return result; + + if (!should_prune_file) { + pruned_files.push_back(file); } - previous_directories = move(result); } - return vector(); -} -unique_ptr FileSystem::CreateLocal() { - return make_unique(); + filters = std::move(pruned_filters); + files = std::move(pruned_files); } } // namespace duckdb + + + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/operator/cast_operators.hpp +// duckdb/common/windows_undefs.hpp // // //===----------------------------------------------------------------------===// +#ifdef WIN32 +#ifdef min +#undef min +#endif +#ifdef max +#undef max +#endif +#ifdef ERROR +#undef ERROR +#endif +#ifdef small +#undef small +#endif -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/operator/convert_to_string.hpp -// -// -//===----------------------------------------------------------------------===// - - +#ifdef CreateDirectory +#undef CreateDirectory +#endif +#ifdef MoveFile +#undef MoveFile +#endif +#ifdef RemoveDirectory +#undef RemoveDirectory +#endif +#endif +#include namespace duckdb { -struct ConvertToString { - template - static inline string Operation(SRC input) { - throw InternalException("Unrecognized type for ConvertToString %s", GetTypeId()); - } -}; - -template <> -string ConvertToString::Operation(bool input); -template <> -string ConvertToString::Operation(int8_t input); -template <> -string ConvertToString::Operation(int16_t input); -template <> -string ConvertToString::Operation(int32_t input); -template <> -string ConvertToString::Operation(int64_t input); -template <> -string ConvertToString::Operation(uint8_t input); -template <> -string ConvertToString::Operation(uint16_t input); -template <> -string ConvertToString::Operation(uint32_t input); -template <> -string ConvertToString::Operation(uint64_t input); -template <> -string ConvertToString::Operation(hugeint_t input); -template <> -string ConvertToString::Operation(float input); -template <> -string ConvertToString::Operation(double input); -template <> -string ConvertToString::Operation(interval_t input); -template <> -string ConvertToString::Operation(date_t input); -template <> -string ConvertToString::Operation(dtime_t input); -template <> -string ConvertToString::Operation(timestamp_t input); -template <> -string ConvertToString::Operation(string_t input); +using std::numeric_limits; -} // namespace duckdb +int8_t NumericLimits::Minimum() { + return numeric_limits::lowest(); +} -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/types/null_value.hpp -// -// -//===----------------------------------------------------------------------===// +int8_t NumericLimits::Maximum() { + return numeric_limits::max(); +} +int16_t NumericLimits::Minimum() { + return numeric_limits::lowest(); +} +int16_t NumericLimits::Maximum() { + return numeric_limits::max(); +} +int32_t NumericLimits::Minimum() { + return numeric_limits::lowest(); +} +int32_t NumericLimits::Maximum() { + return numeric_limits::max(); +} +int64_t NumericLimits::Minimum() { + return numeric_limits::lowest(); +} +int64_t NumericLimits::Maximum() { + return numeric_limits::max(); +} +float NumericLimits::Minimum() { + return numeric_limits::lowest(); +} +float NumericLimits::Maximum() { + return numeric_limits::max(); +} -#include -#include -#include +double NumericLimits::Minimum() { + return numeric_limits::lowest(); +} -namespace duckdb { +double NumericLimits::Maximum() { + return numeric_limits::max(); +} -//! Placeholder to insert in Vectors or to use for hashing NULLs -template -inline T NullValue() { - return std::numeric_limits::min(); +uint8_t NumericLimits::Minimum() { + return numeric_limits::lowest(); } -constexpr const char str_nil[2] = {'\200', '\0'}; +uint8_t NumericLimits::Maximum() { + return numeric_limits::max(); +} -template <> -inline const char *NullValue() { - D_ASSERT(str_nil[0] == '\200' && str_nil[1] == '\0'); - return str_nil; +uint16_t NumericLimits::Minimum() { + return numeric_limits::lowest(); } -template <> -inline string_t NullValue() { - return string_t(NullValue()); +uint16_t NumericLimits::Maximum() { + return numeric_limits::max(); } -template <> -inline char *NullValue() { - return (char *)NullValue(); +uint32_t NumericLimits::Minimum() { + return numeric_limits::lowest(); } -template <> -inline string NullValue() { - return string(NullValue()); +uint32_t NumericLimits::Maximum() { + return numeric_limits::max(); } -template <> -inline interval_t NullValue() { - interval_t null_value; - null_value.days = NullValue(); - null_value.months = NullValue(); - null_value.micros = NullValue(); - return null_value; +uint64_t NumericLimits::Minimum() { + return numeric_limits::lowest(); } -template <> -inline hugeint_t NullValue() { - hugeint_t min; - min.lower = 0; - min.upper = std::numeric_limits::min(); - return min; +uint64_t NumericLimits::Maximum() { + return numeric_limits::max(); } -template <> -inline float NullValue() { - return NAN; +hugeint_t NumericLimits::Minimum() { + hugeint_t result; + result.lower = 1; + result.upper = numeric_limits::lowest(); + return result; } -template <> -inline double NullValue() { - return NAN; +hugeint_t NumericLimits::Maximum() { + hugeint_t result; + result.lower = numeric_limits::max(); + result.upper = numeric_limits::max(); + return result; } } // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/local_file_system.hpp +// +// +//===----------------------------------------------------------------------===// + + + namespace duckdb { -struct ValidityMask; -class Vector; -struct TryCast { - template - DUCKDB_API static inline bool Operation(SRC input, DST &result, bool strict = false) { - throw NotImplementedException("Unimplemented type for cast (%s -> %s)", GetTypeId(), GetTypeId()); +class LocalFileSystem : public FileSystem { +public: + unique_ptr OpenFile(const string &path, uint8_t flags, FileLockType lock = FileLockType::NO_LOCK, + FileCompressionType compression = FileCompressionType::UNCOMPRESSED, + FileOpener *opener = nullptr) override; + + //! Read exactly nr_bytes from the specified location in the file. Fails if nr_bytes could not be read. This is + //! equivalent to calling SetFilePointer(location) followed by calling Read(). + void Read(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) override; + //! Write exactly nr_bytes to the specified location in the file. Fails if nr_bytes could not be read. This is + //! equivalent to calling SetFilePointer(location) followed by calling Write(). + void Write(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) override; + //! Read nr_bytes from the specified file into the buffer, moving the file pointer forward by nr_bytes. Returns the + //! amount of bytes read. + int64_t Read(FileHandle &handle, void *buffer, int64_t nr_bytes) override; + //! Write nr_bytes from the buffer into the file, moving the file pointer forward by nr_bytes. + int64_t Write(FileHandle &handle, void *buffer, int64_t nr_bytes) override; + + //! Returns the file size of a file handle, returns -1 on error + int64_t GetFileSize(FileHandle &handle) override; + //! Returns the file last modified time of a file handle, returns timespec with zero on all attributes on error + time_t GetLastModifiedTime(FileHandle &handle) override; + //! Returns the file last modified time of a file handle, returns timespec with zero on all attributes on error + FileType GetFileType(FileHandle &handle) override; + //! Truncate a file to a maximum size of new_size, new_size should be smaller than or equal to the current size of + //! the file + void Truncate(FileHandle &handle, int64_t new_size) override; + + //! Check if a directory exists + bool DirectoryExists(const string &directory) override; + //! Create a directory if it does not exist + void CreateDirectory(const string &directory) override; + //! Recursively remove a directory and all files in it + void RemoveDirectory(const string &directory) override; + //! List files in a directory, invoking the callback method for each one with (filename, is_dir) + bool ListFiles(const string &directory, const std::function &callback) override; + //! Move a file from source path to the target, StorageManager relies on this being an atomic action for ACID + //! properties + void MoveFile(const string &source, const string &target) override; + //! Check if a file exists + bool FileExists(const string &filename) override; + + //! Check if path is a pipe + bool IsPipe(const string &filename) override; + //! Remove a file from disk + void RemoveFile(const string &filename) override; + //! Sync a file handle to disk + void FileSync(FileHandle &handle) override; + + //! Runs a glob on the file system, returning a list of matching files + vector Glob(const string &path, FileOpener *opener = nullptr) override; + + bool CanHandleFile(const string &fpath) override { + //! Whether or not a sub-system can handle a specific file path + return false; } -}; -struct TryCastErrorMessage { - template - DUCKDB_API static inline bool Operation(SRC input, DST &result, string *error_message, bool strict = false) { - throw NotImplementedException("Unimplemented type for cast (%s -> %s)", GetTypeId(), GetTypeId()); + //! Set the file pointer of a file handle to a specified location. Reads and writes will happen from this location + void Seek(FileHandle &handle, idx_t location) override; + //! Return the current seek posiiton in the file. + idx_t SeekPosition(FileHandle &handle) override; + + //! Whether or not we can seek into the file + bool CanSeek() override; + //! Whether or not the FS handles plain files on disk. This is relevant for certain optimizations, as random reads + //! in a file on-disk are much cheaper than e.g. random reads in a file over the network + bool OnDiskFile(FileHandle &handle) override; + + std::string GetName() const override { + return "LocalFileSystem"; } + + //! Returns the last Win32 error, in string format. Returns an empty string if there is no error, or on non-Windows + //! systems. + static std::string GetLastErrorAsString(); + +private: + //! Set the file pointer of a file handle to a specified location. Reads and writes will happen from this location + void SetFilePointer(FileHandle &handle, idx_t location); + idx_t GetFilePointer(FileHandle &handle); }; -template -static string CastExceptionText(SRC input) { - if (std::is_same()) { - return "Could not convert string '" + ConvertToString::Operation(input) + "' to " + - TypeIdToString(GetTypeId()); - } - if (TypeIsNumber() && TypeIsNumber()) { - return "Type " + TypeIdToString(GetTypeId()) + " with value " + ConvertToString::Operation(input) + - " can't be cast because the value is out of range for the destination type " + - TypeIdToString(GetTypeId()); +} // namespace duckdb + + + + + + + + + + + + +#include +#include +#include + +#ifndef _WIN32 +#include +#include +#include +#include +#include +#else +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/windows_util.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + + +namespace duckdb { + +#ifdef DUCKDB_WINDOWS +class WindowsUtil { +public: + //! Windows helper functions + static std::wstring UTF8ToUnicode(const char *input); + static string UnicodeToUTF8(LPCWSTR input); + static string UTF8ToMBCS(const char *input, bool use_ansi = false); +}; +#endif + +} // namespace duckdb + + +#include +#include + +#ifdef __MINGW32__ +// need to manually define this for mingw +extern "C" WINBASEAPI BOOL WINAPI GetPhysicallyInstalledSystemMemory(PULONGLONG); +#endif + +#undef FILE_CREATE // woo mingw +#endif + +namespace duckdb { + +static void AssertValidFileFlags(uint8_t flags) { +#ifdef DEBUG + bool is_read = flags & FileFlags::FILE_FLAGS_READ; + bool is_write = flags & FileFlags::FILE_FLAGS_WRITE; + // require either READ or WRITE (or both) + D_ASSERT(is_read || is_write); + // CREATE/Append flags require writing + D_ASSERT(is_write || !(flags & FileFlags::FILE_FLAGS_APPEND)); + D_ASSERT(is_write || !(flags & FileFlags::FILE_FLAGS_FILE_CREATE)); + D_ASSERT(is_write || !(flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW)); + // cannot combine CREATE and CREATE_NEW flags + D_ASSERT(!(flags & FileFlags::FILE_FLAGS_FILE_CREATE && flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW)); +#endif +} + +#ifndef _WIN32 +bool LocalFileSystem::FileExists(const string &filename) { + if (!filename.empty()) { + if (access(filename.c_str(), 0) == 0) { + struct stat status; + stat(filename.c_str(), &status); + if (S_ISREG(status.st_mode)) { + return true; + } + } } - return "Type " + TypeIdToString(GetTypeId()) + " with value " + ConvertToString::Operation(input) + - " can't be cast to the destination type " + TypeIdToString(GetTypeId()); + // if any condition fails + return false; } -struct Cast { - template - static inline DST Operation(SRC input) { - DST result; - if (!TryCast::Operation(input, result)) { - throw InvalidInputException(CastExceptionText(input)); +bool LocalFileSystem::IsPipe(const string &filename) { + if (!filename.empty()) { + if (access(filename.c_str(), 0) == 0) { + struct stat status; + stat(filename.c_str(), &status); + if (S_ISFIFO(status.st_mode)) { + return true; + } } - return result; } -}; + // if any condition fails + return false; +} -struct HandleCastError { - static void AssignError(string error_message, string *error_message_ptr) { - if (!error_message_ptr) { - throw ConversionException(error_message); +#else +bool LocalFileSystem::FileExists(const string &filename) { + auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str()); + const wchar_t *wpath = unicode_path.c_str(); + if (_waccess(wpath, 0) == 0) { + struct _stati64 status; + _wstati64(wpath, &status); + if (status.st_mode & S_IFREG) { + return true; } - if (error_message_ptr->empty()) { - *error_message_ptr = error_message; + } + return false; +} +bool LocalFileSystem::IsPipe(const string &filename) { + auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str()); + const wchar_t *wpath = unicode_path.c_str(); + if (_waccess(wpath, 0) == 0) { + struct _stati64 status; + _wstati64(wpath, &status); + if (status.st_mode & _S_IFCHR) { + return true; + } + } + return false; +} +#endif + +#ifndef _WIN32 +// somehow sometimes this is missing +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +// Solaris +#ifndef O_DIRECT +#define O_DIRECT 0 +#endif + +struct UnixFileHandle : public FileHandle { +public: + UnixFileHandle(FileSystem &file_system, string path, int fd) : FileHandle(file_system, move(path)), fd(fd) { + } + ~UnixFileHandle() override { + Close(); + } + + int fd; + +public: + void Close() override { + if (fd != -1) { + close(fd); + fd = -1; + } + }; +}; + +static FileType GetFileTypeInternal(int fd) { // LCOV_EXCL_START + struct stat s; + if (fstat(fd, &s) == -1) { + return FileType::FILE_TYPE_INVALID; + } + switch (s.st_mode & S_IFMT) { + case S_IFBLK: + return FileType::FILE_TYPE_BLOCKDEV; + case S_IFCHR: + return FileType::FILE_TYPE_CHARDEV; + case S_IFIFO: + return FileType::FILE_TYPE_FIFO; + case S_IFDIR: + return FileType::FILE_TYPE_DIR; + case S_IFLNK: + return FileType::FILE_TYPE_LINK; + case S_IFREG: + return FileType::FILE_TYPE_REGULAR; + case S_IFSOCK: + return FileType::FILE_TYPE_SOCKET; + default: + return FileType::FILE_TYPE_INVALID; + } +} // LCOV_EXCL_STOP + +unique_ptr LocalFileSystem::OpenFile(const string &path, uint8_t flags, FileLockType lock_type, + FileCompressionType compression, FileOpener *opener) { + if (compression != FileCompressionType::UNCOMPRESSED) { + throw NotImplementedException("Unsupported compression type for default file system"); + } + + AssertValidFileFlags(flags); + + int open_flags = 0; + int rc; + bool open_read = flags & FileFlags::FILE_FLAGS_READ; + bool open_write = flags & FileFlags::FILE_FLAGS_WRITE; + if (open_read && open_write) { + open_flags = O_RDWR; + } else if (open_read) { + open_flags = O_RDONLY; + } else if (open_write) { + open_flags = O_WRONLY; + } else { + throw InternalException("READ, WRITE or both should be specified when opening a file"); + } + if (open_write) { + // need Read or Write + D_ASSERT(flags & FileFlags::FILE_FLAGS_WRITE); + open_flags |= O_CLOEXEC; + if (flags & FileFlags::FILE_FLAGS_FILE_CREATE) { + open_flags |= O_CREAT; + } else if (flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW) { + open_flags |= O_CREAT | O_TRUNC; + } + if (flags & FileFlags::FILE_FLAGS_APPEND) { + open_flags |= O_APPEND; + } + } + if (flags & FileFlags::FILE_FLAGS_DIRECT_IO) { +#if defined(__sun) && defined(__SVR4) + throw Exception("DIRECT_IO not supported on Solaris"); +#endif +#if defined(__DARWIN__) || defined(__APPLE__) || defined(__OpenBSD__) + // OSX does not have O_DIRECT, instead we need to use fcntl afterwards to support direct IO + open_flags |= O_SYNC; +#else + open_flags |= O_DIRECT | O_SYNC; +#endif + } + int fd = open(path.c_str(), open_flags, 0666); + if (fd == -1) { + throw IOException("Cannot open file \"%s\": %s", path, strerror(errno)); + } + // #if defined(__DARWIN__) || defined(__APPLE__) + // if (flags & FileFlags::FILE_FLAGS_DIRECT_IO) { + // // OSX requires fcntl for Direct IO + // rc = fcntl(fd, F_NOCACHE, 1); + // if (fd == -1) { + // throw IOException("Could not enable direct IO for file \"%s\": %s", path, strerror(errno)); + // } + // } + // #endif + if (lock_type != FileLockType::NO_LOCK) { + // set lock on file + // but only if it is not an input/output stream + auto file_type = GetFileTypeInternal(fd); + if (file_type != FileType::FILE_TYPE_FIFO && file_type != FileType::FILE_TYPE_SOCKET) { + struct flock fl; + memset(&fl, 0, sizeof fl); + fl.l_type = lock_type == FileLockType::READ_LOCK ? F_RDLCK : F_WRLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + rc = fcntl(fd, F_SETLK, &fl); + if (rc == -1) { + throw IOException("Could not set lock on file \"%s\": %s", path, strerror(errno)); + } + } + } + return make_unique(*this, path, fd); +} + +void LocalFileSystem::SetFilePointer(FileHandle &handle, idx_t location) { + int fd = ((UnixFileHandle &)handle).fd; + off_t offset = lseek(fd, location, SEEK_SET); + if (offset == (off_t)-1) { + throw IOException("Could not seek to location %lld for file \"%s\": %s", location, handle.path, + strerror(errno)); + } +} + +idx_t LocalFileSystem::GetFilePointer(FileHandle &handle) { + int fd = ((UnixFileHandle &)handle).fd; + off_t position = lseek(fd, 0, SEEK_CUR); + if (position == (off_t)-1) { + throw IOException("Could not get file position file \"%s\": %s", handle.path, strerror(errno)); + } + return position; +} + +void LocalFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) { + int fd = ((UnixFileHandle &)handle).fd; + int64_t bytes_read = pread(fd, buffer, nr_bytes, location); + if (bytes_read == -1) { + throw IOException("Could not read from file \"%s\": %s", handle.path, strerror(errno)); + } + if (bytes_read != nr_bytes) { + throw IOException("Could not read all bytes from file \"%s\": wanted=%lld read=%lld", handle.path, nr_bytes, + bytes_read); + } +} + +int64_t LocalFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes) { + int fd = ((UnixFileHandle &)handle).fd; + int64_t bytes_read = read(fd, buffer, nr_bytes); + if (bytes_read == -1) { + throw IOException("Could not read from file \"%s\": %s", handle.path, strerror(errno)); + } + return bytes_read; +} + +void LocalFileSystem::Write(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) { + int fd = ((UnixFileHandle &)handle).fd; + int64_t bytes_written = pwrite(fd, buffer, nr_bytes, location); + if (bytes_written == -1) { + throw IOException("Could not write file \"%s\": %s", handle.path, strerror(errno)); + } + if (bytes_written != nr_bytes) { + throw IOException("Could not write all bytes to file \"%s\": wanted=%lld wrote=%lld", handle.path, nr_bytes, + bytes_written); + } +} + +int64_t LocalFileSystem::Write(FileHandle &handle, void *buffer, int64_t nr_bytes) { + int fd = ((UnixFileHandle &)handle).fd; + int64_t bytes_written = write(fd, buffer, nr_bytes); + if (bytes_written == -1) { + throw IOException("Could not write file \"%s\": %s", handle.path, strerror(errno)); + } + return bytes_written; +} + +int64_t LocalFileSystem::GetFileSize(FileHandle &handle) { + int fd = ((UnixFileHandle &)handle).fd; + struct stat s; + if (fstat(fd, &s) == -1) { + return -1; + } + return s.st_size; +} + +time_t LocalFileSystem::GetLastModifiedTime(FileHandle &handle) { + int fd = ((UnixFileHandle &)handle).fd; + struct stat s; + if (fstat(fd, &s) == -1) { + return -1; + } + return s.st_mtime; +} + +FileType LocalFileSystem::GetFileType(FileHandle &handle) { + int fd = ((UnixFileHandle &)handle).fd; + return GetFileTypeInternal(fd); +} + +void LocalFileSystem::Truncate(FileHandle &handle, int64_t new_size) { + int fd = ((UnixFileHandle &)handle).fd; + if (ftruncate(fd, new_size) != 0) { + throw IOException("Could not truncate file \"%s\": %s", handle.path, strerror(errno)); + } +} + +bool LocalFileSystem::DirectoryExists(const string &directory) { + if (!directory.empty()) { + if (access(directory.c_str(), 0) == 0) { + struct stat status; + stat(directory.c_str(), &status); + if (status.st_mode & S_IFDIR) { + return true; + } + } + } + // if any condition fails + return false; +} + +void LocalFileSystem::CreateDirectory(const string &directory) { + struct stat st; + + if (stat(directory.c_str(), &st) != 0) { + /* Directory does not exist. EEXIST for race condition */ + if (mkdir(directory.c_str(), 0755) != 0 && errno != EEXIST) { + throw IOException("Failed to create directory \"%s\"!", directory); + } + } else if (!S_ISDIR(st.st_mode)) { + throw IOException("Failed to create directory \"%s\": path exists but is not a directory!", directory); + } +} + +int RemoveDirectoryRecursive(const char *path) { + DIR *d = opendir(path); + idx_t path_len = (idx_t)strlen(path); + int r = -1; + + if (d) { + struct dirent *p; + r = 0; + while (!r && (p = readdir(d))) { + int r2 = -1; + char *buf; + idx_t len; + /* Skip the names "." and ".." as we don't want to recurse on them. */ + if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) { + continue; + } + len = path_len + (idx_t)strlen(p->d_name) + 2; + buf = new char[len]; + if (buf) { + struct stat statbuf; + snprintf(buf, len, "%s/%s", path, p->d_name); + if (!stat(buf, &statbuf)) { + if (S_ISDIR(statbuf.st_mode)) { + r2 = RemoveDirectoryRecursive(buf); + } else { + r2 = unlink(buf); + } + } + delete[] buf; + } + r = r2; + } + closedir(d); + } + if (!r) { + r = rmdir(path); + } + return r; +} + +void LocalFileSystem::RemoveDirectory(const string &directory) { + RemoveDirectoryRecursive(directory.c_str()); +} + +void LocalFileSystem::RemoveFile(const string &filename) { + if (std::remove(filename.c_str()) != 0) { + throw IOException("Could not remove file \"%s\": %s", filename, strerror(errno)); + } +} + +bool LocalFileSystem::ListFiles(const string &directory, const std::function &callback) { + if (!DirectoryExists(directory)) { + return false; + } + DIR *dir = opendir(directory.c_str()); + if (!dir) { + return false; + } + struct dirent *ent; + // loop over all files in the directory + while ((ent = readdir(dir)) != nullptr) { + string name = string(ent->d_name); + // skip . .. and empty files + if (name.empty() || name == "." || name == "..") { + continue; + } + // now stat the file to figure out if it is a regular file or directory + string full_path = JoinPath(directory, name); + if (access(full_path.c_str(), 0) != 0) { + continue; + } + struct stat status; + stat(full_path.c_str(), &status); + if (!(status.st_mode & S_IFREG) && !(status.st_mode & S_IFDIR)) { + // not a file or directory: skip + continue; + } + // invoke callback + callback(name, status.st_mode & S_IFDIR); + } + closedir(dir); + return true; +} + +void LocalFileSystem::FileSync(FileHandle &handle) { + int fd = ((UnixFileHandle &)handle).fd; + if (fsync(fd) != 0) { + throw FatalException("fsync failed!"); + } +} + +void LocalFileSystem::MoveFile(const string &source, const string &target) { + //! FIXME: rename does not guarantee atomicity or overwriting target file if it exists + if (rename(source.c_str(), target.c_str()) != 0) { + throw IOException("Could not rename file!"); + } +} + +std::string LocalFileSystem::GetLastErrorAsString() { + return string(); +} + +#else + +constexpr char PIPE_PREFIX[] = "\\\\.\\pipe\\"; + +// Returns the last Win32 error, in string format. Returns an empty string if there is no error. +std::string LocalFileSystem::GetLastErrorAsString() { + // Get the error message, if any. + DWORD errorMessageID = GetLastError(); + if (errorMessageID == 0) + return std::string(); // No error message has been recorded + + LPSTR messageBuffer = nullptr; + idx_t size = + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); + + std::string message(messageBuffer, size); + + // Free the buffer. + LocalFree(messageBuffer); + + return message; +} + +struct WindowsFileHandle : public FileHandle { +public: + WindowsFileHandle(FileSystem &file_system, string path, HANDLE fd) + : FileHandle(file_system, path), position(0), fd(fd) { + } + virtual ~WindowsFileHandle() { + Close(); + } + + idx_t position; + HANDLE fd; + +public: + void Close() override { + if (!fd) { + return; + } + CloseHandle(fd); + fd = nullptr; + }; +}; + +unique_ptr LocalFileSystem::OpenFile(const string &path, uint8_t flags, FileLockType lock_type, + FileCompressionType compression, FileOpener *opener) { + if (compression != FileCompressionType::UNCOMPRESSED) { + throw NotImplementedException("Unsupported compression type for default file system"); + } + AssertValidFileFlags(flags); + + DWORD desired_access; + DWORD share_mode; + DWORD creation_disposition = OPEN_EXISTING; + DWORD flags_and_attributes = FILE_ATTRIBUTE_NORMAL; + bool open_read = flags & FileFlags::FILE_FLAGS_READ; + bool open_write = flags & FileFlags::FILE_FLAGS_WRITE; + if (open_read && open_write) { + desired_access = GENERIC_READ | GENERIC_WRITE; + share_mode = 0; + } else if (open_read) { + desired_access = GENERIC_READ; + share_mode = FILE_SHARE_READ; + } else if (open_write) { + desired_access = GENERIC_WRITE; + share_mode = 0; + } else { + throw InternalException("READ, WRITE or both should be specified when opening a file"); + } + if (open_write) { + if (flags & FileFlags::FILE_FLAGS_FILE_CREATE) { + creation_disposition = OPEN_ALWAYS; + } else if (flags & FileFlags::FILE_FLAGS_FILE_CREATE_NEW) { + creation_disposition = CREATE_ALWAYS; + } + } + if (flags & FileFlags::FILE_FLAGS_DIRECT_IO) { + flags_and_attributes |= FILE_FLAG_NO_BUFFERING; + } + auto unicode_path = WindowsUtil::UTF8ToUnicode(path.c_str()); + HANDLE hFile = CreateFileW(unicode_path.c_str(), desired_access, share_mode, NULL, creation_disposition, + flags_and_attributes, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + auto error = LocalFileSystem::GetLastErrorAsString(); + throw IOException("Cannot open file \"%s\": %s", path.c_str(), error); + } + auto handle = make_unique(*this, path.c_str(), hFile); + if (flags & FileFlags::FILE_FLAGS_APPEND) { + auto file_size = GetFileSize(*handle); + SetFilePointer(*handle, file_size); + } + return move(handle); +} + +void LocalFileSystem::SetFilePointer(FileHandle &handle, idx_t location) { + auto &whandle = (WindowsFileHandle &)handle; + whandle.position = location; + LARGE_INTEGER wlocation; + wlocation.QuadPart = location; + SetFilePointerEx(whandle.fd, wlocation, NULL, FILE_BEGIN); +} + +idx_t LocalFileSystem::GetFilePointer(FileHandle &handle) { + return ((WindowsFileHandle &)handle).position; +} + +static DWORD FSInternalRead(FileHandle &handle, HANDLE hFile, void *buffer, int64_t nr_bytes, idx_t location) { + DWORD bytes_read = 0; + OVERLAPPED ov = {}; + ov.Internal = 0; + ov.InternalHigh = 0; + ov.Offset = location & 0xFFFFFFFF; + ov.OffsetHigh = location >> 32; + ov.hEvent = 0; + auto rc = ReadFile(hFile, buffer, (DWORD)nr_bytes, &bytes_read, &ov); + if (!rc) { + auto error = LocalFileSystem::GetLastErrorAsString(); + throw IOException("Could not read file \"%s\" (error in ReadFile(location: %llu, nr_bytes: %lld)): %s", + handle.path, location, nr_bytes, error); + } + return bytes_read; +} + +void LocalFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) { + HANDLE hFile = ((WindowsFileHandle &)handle).fd; + auto bytes_read = FSInternalRead(handle, hFile, buffer, nr_bytes, location); + if (bytes_read != nr_bytes) { + throw IOException("Could not read all bytes from file \"%s\": wanted=%lld read=%lld", handle.path, nr_bytes, + bytes_read); + } +} + +int64_t LocalFileSystem::Read(FileHandle &handle, void *buffer, int64_t nr_bytes) { + HANDLE hFile = ((WindowsFileHandle &)handle).fd; + auto &pos = ((WindowsFileHandle &)handle).position; + auto n = std::min(std::max(GetFileSize(handle), pos) - pos, nr_bytes); + auto bytes_read = FSInternalRead(handle, hFile, buffer, n, pos); + pos += bytes_read; + return bytes_read; +} + +static DWORD FSInternalWrite(FileHandle &handle, HANDLE hFile, void *buffer, int64_t nr_bytes, idx_t location) { + DWORD bytes_written = 0; + OVERLAPPED ov = {}; + ov.Internal = 0; + ov.InternalHigh = 0; + ov.Offset = location & 0xFFFFFFFF; + ov.OffsetHigh = location >> 32; + ov.hEvent = 0; + auto rc = WriteFile(hFile, buffer, (DWORD)nr_bytes, &bytes_written, &ov); + if (!rc) { + auto error = LocalFileSystem::GetLastErrorAsString(); + throw IOException("Could not write file \"%s\" (error in WriteFile): %s", handle.path, error); + } + return bytes_written; +} + +void LocalFileSystem::Write(FileHandle &handle, void *buffer, int64_t nr_bytes, idx_t location) { + HANDLE hFile = ((WindowsFileHandle &)handle).fd; + auto bytes_written = FSInternalWrite(handle, hFile, buffer, nr_bytes, location); + if (bytes_written != nr_bytes) { + throw IOException("Could not write all bytes from file \"%s\": wanted=%lld wrote=%lld", handle.path, nr_bytes, + bytes_written); + } +} + +int64_t LocalFileSystem::Write(FileHandle &handle, void *buffer, int64_t nr_bytes) { + HANDLE hFile = ((WindowsFileHandle &)handle).fd; + auto &pos = ((WindowsFileHandle &)handle).position; + auto bytes_written = FSInternalWrite(handle, hFile, buffer, nr_bytes, pos); + pos += bytes_written; + return bytes_written; +} + +int64_t LocalFileSystem::GetFileSize(FileHandle &handle) { + HANDLE hFile = ((WindowsFileHandle &)handle).fd; + LARGE_INTEGER result; + if (!GetFileSizeEx(hFile, &result)) { + return -1; + } + return result.QuadPart; +} + +time_t LocalFileSystem::GetLastModifiedTime(FileHandle &handle) { + HANDLE hFile = ((WindowsFileHandle &)handle).fd; + + // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getfiletime + FILETIME last_write; + if (GetFileTime(hFile, nullptr, nullptr, &last_write) == 0) { + return -1; + } + + // https://stackoverflow.com/questions/29266743/what-is-dwlowdatetime-and-dwhighdatetime + ULARGE_INTEGER ul; + ul.LowPart = last_write.dwLowDateTime; + ul.HighPart = last_write.dwHighDateTime; + int64_t fileTime64 = ul.QuadPart; + + // fileTime64 contains a 64-bit value representing the number of + // 100-nanosecond intervals since January 1, 1601 (UTC). + // https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime + + // Adapted from: https://stackoverflow.com/questions/6161776/convert-windows-filetime-to-second-in-unix-linux + const auto WINDOWS_TICK = 10000000; + const auto SEC_TO_UNIX_EPOCH = 11644473600LL; + time_t result = (fileTime64 / WINDOWS_TICK - SEC_TO_UNIX_EPOCH); + return result; +} + +void LocalFileSystem::Truncate(FileHandle &handle, int64_t new_size) { + HANDLE hFile = ((WindowsFileHandle &)handle).fd; + // seek to the location + SetFilePointer(handle, new_size); + // now set the end of file position + if (!SetEndOfFile(hFile)) { + auto error = LocalFileSystem::GetLastErrorAsString(); + throw IOException("Failure in SetEndOfFile call on file \"%s\": %s", handle.path, error); + } +} + +static DWORD WindowsGetFileAttributes(const string &filename) { + auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str()); + return GetFileAttributesW(unicode_path.c_str()); +} + +bool LocalFileSystem::DirectoryExists(const string &directory) { + DWORD attrs = WindowsGetFileAttributes(directory); + return (attrs != INVALID_FILE_ATTRIBUTES && (attrs & FILE_ATTRIBUTE_DIRECTORY)); +} + +void LocalFileSystem::CreateDirectory(const string &directory) { + if (DirectoryExists(directory)) { + return; + } + auto unicode_path = WindowsUtil::UTF8ToUnicode(directory.c_str()); + if (directory.empty() || !CreateDirectoryW(unicode_path.c_str(), NULL) || !DirectoryExists(directory)) { + throw IOException("Could not create directory!"); + } +} + +static void DeleteDirectoryRecursive(FileSystem &fs, string directory) { + fs.ListFiles(directory, [&](const string &fname, bool is_directory) { + if (is_directory) { + DeleteDirectoryRecursive(fs, fs.JoinPath(directory, fname)); + } else { + fs.RemoveFile(fs.JoinPath(directory, fname)); + } + }); + auto unicode_path = WindowsUtil::UTF8ToUnicode(directory.c_str()); + if (!RemoveDirectoryW(unicode_path.c_str())) { + auto error = LocalFileSystem::GetLastErrorAsString(); + throw IOException("Failed to delete directory \"%s\": %s", directory, error); + } +} + +void LocalFileSystem::RemoveDirectory(const string &directory) { + if (FileExists(directory)) { + throw IOException("Attempting to delete directory \"%s\", but it is a file and not a directory!", directory); + } + if (!DirectoryExists(directory)) { + return; + } + DeleteDirectoryRecursive(*this, directory.c_str()); +} + +void LocalFileSystem::RemoveFile(const string &filename) { + auto unicode_path = WindowsUtil::UTF8ToUnicode(filename.c_str()); + if (!DeleteFileW(unicode_path.c_str())) { + auto error = LocalFileSystem::GetLastErrorAsString(); + throw IOException("Failed to delete file \"%s\": %s", filename, error); + } +} + +bool LocalFileSystem::ListFiles(const string &directory, const std::function &callback) { + string search_dir = JoinPath(directory, "*"); + + auto unicode_path = WindowsUtil::UTF8ToUnicode(search_dir.c_str()); + + WIN32_FIND_DATAW ffd; + HANDLE hFind = FindFirstFileW(unicode_path.c_str(), &ffd); + if (hFind == INVALID_HANDLE_VALUE) { + return false; + } + do { + string cFileName = WindowsUtil::UnicodeToUTF8(ffd.cFileName); + if (cFileName == "." || cFileName == "..") { + continue; + } + callback(cFileName, ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + } while (FindNextFileW(hFind, &ffd) != 0); + + DWORD dwError = GetLastError(); + if (dwError != ERROR_NO_MORE_FILES) { + FindClose(hFind); + return false; + } + + FindClose(hFind); + return true; +} + +void LocalFileSystem::FileSync(FileHandle &handle) { + HANDLE hFile = ((WindowsFileHandle &)handle).fd; + if (FlushFileBuffers(hFile) == 0) { + throw IOException("Could not flush file handle to disk!"); + } +} + +void LocalFileSystem::MoveFile(const string &source, const string &target) { + auto source_unicode = WindowsUtil::UTF8ToUnicode(source.c_str()); + auto target_unicode = WindowsUtil::UTF8ToUnicode(target.c_str()); + if (!MoveFileW(source_unicode.c_str(), target_unicode.c_str())) { + throw IOException("Could not move file"); + } +} + +FileType LocalFileSystem::GetFileType(FileHandle &handle) { + auto path = ((WindowsFileHandle &)handle).path; + // pipes in windows are just files in '\\.\pipe\' folder + if (strncmp(path.c_str(), PIPE_PREFIX, strlen(PIPE_PREFIX)) == 0) { + return FileType::FILE_TYPE_FIFO; + } + DWORD attrs = WindowsGetFileAttributes(path.c_str()); + if (attrs != INVALID_FILE_ATTRIBUTES) { + if (attrs & FILE_ATTRIBUTE_DIRECTORY) { + return FileType::FILE_TYPE_DIR; + } else { + return FileType::FILE_TYPE_REGULAR; + } + } + return FileType::FILE_TYPE_INVALID; +} +#endif + +bool LocalFileSystem::CanSeek() { + return true; +} + +bool LocalFileSystem::OnDiskFile(FileHandle &handle) { + return true; +} + +void LocalFileSystem::Seek(FileHandle &handle, idx_t location) { + if (!CanSeek()) { + throw IOException("Cannot seek in files of this type"); + } + SetFilePointer(handle, location); +} + +idx_t LocalFileSystem::SeekPosition(FileHandle &handle) { + if (!CanSeek()) { + throw IOException("Cannot seek in files of this type"); + } + return GetFilePointer(handle); +} + +static bool HasGlob(const string &str) { + for (idx_t i = 0; i < str.size(); i++) { + switch (str[i]) { + case '*': + case '?': + case '[': + return true; + default: + break; + } + } + return false; +} + +static void GlobFiles(FileSystem &fs, const string &path, const string &glob, bool match_directory, + vector &result, bool join_path) { + fs.ListFiles(path, [&](const string &fname, bool is_directory) { + if (is_directory != match_directory) { + return; + } + if (LikeFun::Glob(fname.c_str(), fname.size(), glob.c_str(), glob.size())) { + if (join_path) { + result.push_back(fs.JoinPath(path, fname)); + } else { + result.push_back(fname); + } + } + }); +} + +vector LocalFileSystem::Glob(const string &path, FileOpener *opener) { + if (path.empty()) { + return vector(); + } + // split up the path into separate chunks + vector splits; + idx_t last_pos = 0; + for (idx_t i = 0; i < path.size(); i++) { + if (path[i] == '\\' || path[i] == '/') { + if (i == last_pos) { + // empty: skip this position + last_pos = i + 1; + continue; + } + if (splits.empty()) { + splits.push_back(path.substr(0, i)); + } else { + splits.push_back(path.substr(last_pos, i - last_pos)); + } + last_pos = i + 1; + } + } + splits.push_back(path.substr(last_pos, path.size() - last_pos)); + // handle absolute paths + bool absolute_path = false; + if (path[0] == '/') { + // first character is a slash - unix absolute path + absolute_path = true; + } else if (StringUtil::Contains(splits[0], ":")) { + // first split has a colon - windows absolute path + absolute_path = true; + } else if (splits[0] == "~") { + // starts with home directory + auto home_directory = GetHomeDirectory(opener); + if (!home_directory.empty()) { + absolute_path = true; + splits[0] = home_directory; + D_ASSERT(path[0] == '~'); + if (!HasGlob(path)) { + return Glob(home_directory + path.substr(1)); + } + } + } + // Check if the path has a glob at all + if (!HasGlob(path)) { + // no glob: return only the file (if it exists or is a pipe) + vector result; + if (FileExists(path) || IsPipe(path)) { + result.push_back(path); + } else if (!absolute_path) { + Value value; + if (opener->TryGetCurrentSetting("file_search_path", value)) { + auto search_paths_str = value.ToString(); + std::vector search_paths = StringUtil::Split(search_paths_str, ','); + for (const auto &search_path : search_paths) { + auto joined_path = JoinPath(search_path, path); + if (FileExists(joined_path) || IsPipe(joined_path)) { + result.push_back(joined_path); + } + } + } + } + return result; + } + vector previous_directories; + if (absolute_path) { + // for absolute paths, we don't start by scanning the current directory + previous_directories.push_back(splits[0]); + } + for (idx_t i = absolute_path ? 1 : 0; i < splits.size(); i++) { + bool is_last_chunk = i + 1 == splits.size(); + bool has_glob = HasGlob(splits[i]); + // if it's the last chunk we need to find files, otherwise we find directories + // not the last chunk: gather a list of all directories that match the glob pattern + vector result; + if (!has_glob) { + // no glob, just append as-is + if (previous_directories.empty()) { + result.push_back(splits[i]); + } else { + for (auto &prev_directory : previous_directories) { + result.push_back(JoinPath(prev_directory, splits[i])); + } + } + } else { + if (previous_directories.empty()) { + // no previous directories: list in the current path + GlobFiles(*this, ".", splits[i], !is_last_chunk, result, false); + } else { + // previous directories + // we iterate over each of the previous directories, and apply the glob of the current directory + for (auto &prev_directory : previous_directories) { + GlobFiles(*this, prev_directory, splits[i], !is_last_chunk, result, true); + } + } + } + if (is_last_chunk || result.empty()) { + return result; + } + previous_directories = move(result); + } + return vector(); +} + +unique_ptr FileSystem::CreateLocal() { + return make_unique(); +} + +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/operator/cast_operators.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/operator/convert_to_string.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + +namespace duckdb { + +struct ConvertToString { + template + static inline string Operation(SRC input) { + throw InternalException("Unrecognized type for ConvertToString %s", GetTypeId()); + } +}; + +template <> +string ConvertToString::Operation(bool input); +template <> +string ConvertToString::Operation(int8_t input); +template <> +string ConvertToString::Operation(int16_t input); +template <> +string ConvertToString::Operation(int32_t input); +template <> +string ConvertToString::Operation(int64_t input); +template <> +string ConvertToString::Operation(uint8_t input); +template <> +string ConvertToString::Operation(uint16_t input); +template <> +string ConvertToString::Operation(uint32_t input); +template <> +string ConvertToString::Operation(uint64_t input); +template <> +string ConvertToString::Operation(hugeint_t input); +template <> +string ConvertToString::Operation(float input); +template <> +string ConvertToString::Operation(double input); +template <> +string ConvertToString::Operation(interval_t input); +template <> +string ConvertToString::Operation(date_t input); +template <> +string ConvertToString::Operation(dtime_t input); +template <> +string ConvertToString::Operation(timestamp_t input); +template <> +string ConvertToString::Operation(string_t input); + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/types/null_value.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + + +#include +#include +#include + +namespace duckdb { + +//! Placeholder to insert in Vectors or to use for hashing NULLs +template +inline T NullValue() { + return std::numeric_limits::min(); +} + +constexpr const char str_nil[2] = {'\200', '\0'}; + +template <> +inline const char *NullValue() { + D_ASSERT(str_nil[0] == '\200' && str_nil[1] == '\0'); + return str_nil; +} + +template <> +inline string_t NullValue() { + return string_t(NullValue()); +} + +template <> +inline char *NullValue() { + return (char *)NullValue(); +} + +template <> +inline string NullValue() { + return string(NullValue()); +} + +template <> +inline interval_t NullValue() { + interval_t null_value; + null_value.days = NullValue(); + null_value.months = NullValue(); + null_value.micros = NullValue(); + return null_value; +} + +template <> +inline hugeint_t NullValue() { + hugeint_t min; + min.lower = 0; + min.upper = std::numeric_limits::min(); + return min; +} + +template <> +inline float NullValue() { + return NAN; +} + +template <> +inline double NullValue() { + return NAN; +} + +} // namespace duckdb + + +namespace duckdb { +struct ValidityMask; +class Vector; + +struct TryCast { + template + DUCKDB_API static inline bool Operation(SRC input, DST &result, bool strict = false) { + throw NotImplementedException("Unimplemented type for cast (%s -> %s)", GetTypeId(), GetTypeId()); + } +}; + +struct TryCastErrorMessage { + template + DUCKDB_API static inline bool Operation(SRC input, DST &result, string *error_message, bool strict = false) { + throw NotImplementedException("Unimplemented type for cast (%s -> %s)", GetTypeId(), GetTypeId()); + } +}; + +template +static string CastExceptionText(SRC input) { + if (std::is_same()) { + return "Could not convert string '" + ConvertToString::Operation(input) + "' to " + + TypeIdToString(GetTypeId()); + } + if (TypeIsNumber() && TypeIsNumber()) { + return "Type " + TypeIdToString(GetTypeId()) + " with value " + ConvertToString::Operation(input) + + " can't be cast because the value is out of range for the destination type " + + TypeIdToString(GetTypeId()); + } + return "Type " + TypeIdToString(GetTypeId()) + " with value " + ConvertToString::Operation(input) + + " can't be cast to the destination type " + TypeIdToString(GetTypeId()); +} + +struct Cast { + template + static inline DST Operation(SRC input) { + DST result; + if (!TryCast::Operation(input, result)) { + throw InvalidInputException(CastExceptionText(input)); + } + return result; + } +}; + +struct HandleCastError { + static void AssignError(string error_message, string *error_message_ptr) { + if (!error_message_ptr) { + throw ConversionException(error_message); + } + if (error_message_ptr->empty()) { + *error_message_ptr = error_message; } } }; @@ -23028,7 +26551,8 @@ namespace duckdb { //! NumericHelper is a static class that holds helper functions for integers/doubles class NumericHelper { public: - static const int64_t POWERS_OF_TEN[20]; + static constexpr uint8_t CACHED_POWERS_OF_TEN = 20; + static const int64_t POWERS_OF_TEN[CACHED_POWERS_OF_TEN]; static const double DOUBLE_POWERS_OF_TEN[40]; public: @@ -23099,7 +26623,7 @@ std::string NumericHelper::ToString(hugeint_t value); struct DecimalToString { template - static int DecimalLength(SIGNED value, uint8_t scale) { + static int DecimalLength(SIGNED value, uint8_t width, uint8_t scale) { if (scale == 0) { // scale is 0: regular number return NumericHelper::SignedLength(value); @@ -23111,11 +26635,13 @@ struct DecimalToString { // in that case we print "0.XXX", which is the scale, plus "0." (2 chars) // integer length + 1 happens when the number is outside of that range // in that case we print the integer number, but with one extra character ('.') - return MaxValue(scale + 2 + (value < 0 ? 1 : 0), NumericHelper::SignedLength(value) + 1); + auto extra_characters = width > scale ? 2 : 1; + return MaxValue(scale + extra_characters + (value < 0 ? 1 : 0), + NumericHelper::SignedLength(value) + 1); } template - static void FormatDecimal(SIGNED value, uint8_t scale, char *dst, idx_t len) { + static void FormatDecimal(SIGNED value, uint8_t width, uint8_t scale, char *dst, idx_t len) { char *end = dst + len; if (value < 0) { value = -value; @@ -23138,14 +26664,18 @@ struct DecimalToString { } *--dst = '.'; // now write the part before the decimal - dst = NumericHelper::FormatUnsigned(major, dst); + D_ASSERT(width > scale || major == 0); + if (width > scale) { + // there are numbers after the comma + dst = NumericHelper::FormatUnsigned(major, dst); + } } template - static string_t Format(SIGNED value, uint8_t scale, Vector &vector) { - int len = DecimalLength(value, scale); + static string_t Format(SIGNED value, uint8_t width, uint8_t scale, Vector &vector) { + int len = DecimalLength(value, width, scale); string_t result = StringVector::EmptyString(vector, len); - FormatDecimal(value, scale, result.GetDataWriteable(), len); + FormatDecimal(value, width, scale, result.GetDataWriteable(), len); result.Finalize(); return result; } @@ -23268,7 +26798,7 @@ struct HugeintToStringCast { return result; } - static int DecimalLength(hugeint_t value, uint8_t scale) { + static int DecimalLength(hugeint_t value, uint8_t width, uint8_t scale) { int negative; if (value.upper < 0) { Hugeint::NegateInPlace(value); @@ -23287,10 +26817,11 @@ struct HugeintToStringCast { // in that case we print "0.XXX", which is the scale, plus "0." (2 chars) // integer length + 1 happens when the number is outside of that range // in that case we print the integer number, but with one extra character ('.') - return MaxValue(scale + 2, UnsignedLength(value) + 1) + negative; + auto extra_numbers = width > scale ? 2 : 1; + return MaxValue(scale + extra_numbers, UnsignedLength(value) + 1) + negative; } - static void FormatDecimal(hugeint_t value, uint8_t scale, char *dst, int len) { + static void FormatDecimal(hugeint_t value, uint8_t width, uint8_t scale, char *dst, int len) { auto endptr = dst + len; int negative = value.upper < 0; @@ -23319,16 +26850,19 @@ struct HugeintToStringCast { } *--dst = '.'; // now write the part before the decimal - dst = FormatUnsigned(major, dst); + D_ASSERT(width > scale || major == 0); + if (width > scale) { + dst = FormatUnsigned(major, dst); + } } - static string_t FormatDecimal(hugeint_t value, uint8_t scale, Vector &vector) { - int length = DecimalLength(value, scale); + static string_t FormatDecimal(hugeint_t value, uint8_t width, uint8_t scale, Vector &vector) { + int length = DecimalLength(value, width, scale); string_t result = StringVector::EmptyString(vector, length); auto dst = result.GetDataWriteable(); - FormatDecimal(value, scale, dst, length); + FormatDecimal(value, width, scale, dst, length); result.Finalize(); return result; @@ -23561,8 +27095,9 @@ struct IntervalToStringCast { + // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #4 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 // See the end of this file for a list // duckdb_fast_float by Daniel Lemire @@ -26785,7 +30320,7 @@ struct IntegerCastOperation { return true; } - template + template static bool HandleDecimal(T &state, uint8_t digit) { if (state.seen_decimal) { return true; @@ -26811,7 +30346,7 @@ struct IntegerCastOperation { return true; } - template + template static bool Finalize(T &state) { return true; } @@ -26838,7 +30373,7 @@ static bool IntegerCastLoop(const char *buf, idx_t len, T &result, bool strict) if (!StringUtil::CharacterIsDigit(buf[pos])) { break; } - if (!OP::template HandleDecimal(result, buf[pos] - '0')) { + if (!OP::template HandleDecimal(result, buf[pos] - '0')) { return false; } pos++; @@ -26892,7 +30427,7 @@ static bool IntegerCastLoop(const char *buf, idx_t len, T &result, bool strict) return false; } } - if (!OP::template Finalize(result)) { + if (!OP::template Finalize(result)) { return false; } return pos > start_pos; @@ -27097,6 +30632,9 @@ bool TryCast::Operation(timestamp_t input, date_t &result, bool strict) { template <> bool TryCast::Operation(timestamp_t input, dtime_t &result, bool strict) { + if (!Timestamp::IsFinite(input)) { + return false; + } result = Timestamp::GetTime(input); return true; } @@ -27434,7 +30972,7 @@ struct HugeIntegerCastOperation { } } - template + template static bool HandleDecimal(T &result, uint8_t digit) { // Integer casts round if (!result.decimal) { @@ -27452,7 +30990,7 @@ struct HugeIntegerCastOperation { return true; } - template + template static bool Finalize(T &result) { return result.Flush(); } @@ -27479,6 +31017,9 @@ struct DecimalCastData { uint8_t scale; uint8_t digit_count; uint8_t decimal_count; + //! Only set when ALLOW_EXPONENT is enabled + uint8_t excessive_decimals; + bool positive_exponent; }; struct DecimalCastOperation { @@ -27501,16 +31042,47 @@ struct DecimalCastOperation { return true; } + template + static void RoundUpResult(T &state) { + if (NEGATIVE) { + state.result -= 1; + } else { + state.result += 1; + } + } + template static bool HandleExponent(T &state, int32_t exponent) { - Finalize(state); + auto decimal_excess = (state.decimal_count > state.scale) ? state.decimal_count - state.scale : 0; + if (exponent > 0) { + state.positive_exponent = true; + //! Positive exponents need up to 'exponent' amount of digits + //! Everything beyond that amount needs to be truncated + if (decimal_excess > exponent) { + //! We've allowed too many decimals + state.excessive_decimals = decimal_excess - exponent; + exponent = 0; + } else { + exponent -= decimal_excess; + } + D_ASSERT(exponent >= 0); + } + if (!Finalize(state)) { + return false; + } if (exponent < 0) { + bool round_up = false; for (idx_t i = 0; i < idx_t(-int64_t(exponent)); i++) { + auto mod = state.result % 10; + round_up = NEGATIVE ? mod <= -5 : mod >= 5; state.result /= 10; if (state.result == 0) { break; } } + if (round_up) { + RoundUpResult(state); + } return true; } else { // positive exponent: append 0's @@ -27523,14 +31095,19 @@ struct DecimalCastOperation { } } - template + template static bool HandleDecimal(T &state, uint8_t digit) { - if (state.decimal_count == state.scale) { + if (!ALLOW_EXPONENT && state.decimal_count == state.scale) { // we exceeded the amount of supported decimals // however, we don't throw an error here // we just truncate the decimal return true; } + //! If we expect an exponent, we need to preserve the decimals + //! But we don't want to overflow, so we prevent overflowing the result with this check + if (state.digit_count + state.decimal_count >= DecimalWidth::max) { + return true; + } state.decimal_count++; if (NEGATIVE) { state.result = state.result * 10 - digit; @@ -27540,11 +31117,36 @@ struct DecimalCastOperation { return true; } - template + template + static bool TruncateExcessiveDecimals(T &state) { + D_ASSERT(state.excessive_decimals); + bool round_up = false; + for (idx_t i = 0; i < state.excessive_decimals; i++) { + auto mod = state.result % 10; + round_up = NEGATIVE ? mod <= -5 : mod >= 5; + state.result /= 10.0; + } + //! Only round up when exponents are involved + if (state.positive_exponent && round_up) { + RoundUpResult(state); + } + D_ASSERT(state.decimal_count > state.scale); + state.decimal_count = state.scale; + return true; + } + + template static bool Finalize(T &state) { - // if we have not gotten exactly "scale" decimals, we need to multiply the result - // e.g. if we have a string "1.0" that is cast to a DECIMAL(9,3), the value needs to be 1000 - // but we have only gotten the value "10" so far, so we multiply by 1000 + if (!state.positive_exponent && state.decimal_count > state.scale) { + //! Did not encounter an exponent, but ALLOW_EXPONENT was on + state.excessive_decimals = state.decimal_count - state.scale; + } + if (state.excessive_decimals && !TruncateExcessiveDecimals(state)) { + return false; + } + // if we have not gotten exactly "scale" decimals, we need to multiply the result + // e.g. if we have a string "1.0" that is cast to a DECIMAL(9,3), the value needs to be 1000 + // but we have only gotten the value "10" so far, so we multiply by 1000 for (uint8_t i = state.decimal_count; i < state.scale; i++) { state.result *= 10; } @@ -27560,6 +31162,8 @@ bool TryDecimalStringCast(string_t input, T &result, string *error_message, uint state.scale = scale; state.digit_count = 0; state.decimal_count = 0; + state.excessive_decimals = 0; + state.positive_exponent = false; if (!TryIntegerCast, true, true, DecimalCastOperation, false>(input.GetDataUnsafe(), input.GetSize(), state, false)) { string error = StringUtil::Format("Could not convert string \"%s\" to DECIMAL(%d,%d)", input.GetString(), @@ -27594,22 +31198,22 @@ bool TryCastToDecimal::Operation(string_t input, hugeint_t &result, string *erro template <> string_t StringCastFromDecimal::Operation(int16_t input, uint8_t width, uint8_t scale, Vector &result) { - return DecimalToString::Format(input, scale, result); + return DecimalToString::Format(input, width, scale, result); } template <> string_t StringCastFromDecimal::Operation(int32_t input, uint8_t width, uint8_t scale, Vector &result) { - return DecimalToString::Format(input, scale, result); + return DecimalToString::Format(input, width, scale, result); } template <> string_t StringCastFromDecimal::Operation(int64_t input, uint8_t width, uint8_t scale, Vector &result) { - return DecimalToString::Format(input, scale, result); + return DecimalToString::Format(input, width, scale, result); } template <> string_t StringCastFromDecimal::Operation(hugeint_t input, uint8_t width, uint8_t scale, Vector &result) { - return HugeintToStringCast::FormatDecimal(input, scale, result); + return HugeintToStringCast::FormatDecimal(input, width, scale, result); } //===--------------------------------------------------------------------===// @@ -28380,7 +31984,6 @@ string ConvertToString::Operation(string_t input) { - namespace duckdb { //===--------------------------------------------------------------------===// @@ -28456,6 +32059,11 @@ duckdb::string_t StringCast::Operation(hugeint_t input, Vector &vector) { template <> duckdb::string_t StringCast::Operation(date_t input, Vector &vector) { + if (input == date_t::infinity()) { + return StringVector::AddString(vector, Date::PINF); + } else if (input == date_t::ninfinity()) { + return StringVector::AddString(vector, Date::NINF); + } int32_t date[3]; Date::Convert(input, date[0], date[1], date[2]); @@ -28491,6 +32099,11 @@ duckdb::string_t StringCast::Operation(dtime_t input, Vector &vector) { template <> duckdb::string_t StringCast::Operation(timestamp_t input, Vector &vector) { + if (input == timestamp_t::infinity()) { + return StringVector::AddString(vector, Date::PINF); + } else if (input == timestamp_t::ninfinity()) { + return StringVector::AddString(vector, Date::NINF); + } date_t date_entry; dtime_t time_entry; Timestamp::Convert(input, date_entry, time_entry); @@ -28549,6 +32162,11 @@ string_t StringCastTZ::Operation(dtime_t input, Vector &vector) { template <> string_t StringCastTZ::Operation(timestamp_t input, Vector &vector) { + if (input == timestamp_t::infinity()) { + return StringVector::AddString(vector, Date::PINF); + } else if (input == timestamp_t::ninfinity()) { + return StringVector::AddString(vector, Date::NINF); + } date_t date_entry; dtime_t time_entry; Timestamp::Convert(input, date_entry, time_entry); @@ -28681,6 +32299,71 @@ unique_ptr PipeFileSystem::OpenPipe(unique_ptr handle) { + + + +namespace duckdb { + +PreservedError::PreservedError() : initialized(false) { +} + +PreservedError::PreservedError(const Exception &exception) + : initialized(true), type(exception.type), raw_message(exception.RawMessage()) { +} + +PreservedError::PreservedError(const std::exception &exception) + : initialized(true), type(ExceptionType::INVALID), raw_message(exception.what()) { +} + +PreservedError::PreservedError(const string &message) + : initialized(true), type(ExceptionType::INVALID), raw_message(message) { +} + +const string &PreservedError::Message() { + if (final_message.empty()) { + final_message = Exception::ExceptionTypeToString(type) + " Error: " + raw_message; + } + return final_message; +} + +void PreservedError::Throw(const string &prepended_message) const { + D_ASSERT(initialized); + if (!prepended_message.empty()) { + string new_message = prepended_message + raw_message; + Exception::ThrowAsTypeWithMessage(type, new_message); + } + Exception::ThrowAsTypeWithMessage(type, raw_message); +} + +const ExceptionType &PreservedError::Type() const { + D_ASSERT(initialized); + return this->type; +} + +PreservedError &PreservedError::AddToMessage(const string &prepended_message) { + raw_message = prepended_message + raw_message; + return *this; +} + +PreservedError::operator bool() const { + return initialized; +} + +bool PreservedError::operator==(const PreservedError &other) const { + if (initialized != other.initialized) { + return false; + } + if (type != other.type) { + return false; + } + return raw_message == other.raw_message; +} + +} // namespace duckdb + + + + #include #ifndef DUCKDB_DISABLE_PRINT @@ -28783,245 +32466,1796 @@ void ProgressBar::Update(bool final) { //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/random_engine.hpp +// duckdb/common/radix_partitioning.hpp // // //===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/fast_mem.hpp +// +// +//===----------------------------------------------------------------------===// -#include -namespace duckdb { -class ClientContext; -struct RandomState; -struct RandomEngine { - RandomEngine(int64_t seed = -1); - ~RandomEngine(); -public: - //! Generate a random number between min and max - double NextRandom(double min, double max); - //! Generate a random number between 0 and 1 - double NextRandom(); - uint32_t NextRandomInteger(); +template +static inline void MemcpyFixed(void *dest, const void *src) { + memcpy(dest, src, SIZE); +} - void SetSeed(uint32_t seed); +template +static inline int MemcmpFixed(const void *str1, const void *str2) { + return memcmp(str1, str2, SIZE); +} - static RandomEngine &Get(ClientContext &context); +namespace duckdb { -private: - unique_ptr random_state; -}; +//! This templated memcpy is significantly faster than std::memcpy, +//! but only when you are calling memcpy with a const size in a loop. +//! For instance `while () { memcpy(, , const_size); ... }` +static inline void FastMemcpy(void *dest, const void *src, const size_t size) { + // LCOV_EXCL_START + switch (size) { + case 0: + return; + case 1: + return MemcpyFixed<1>(dest, src); + case 2: + return MemcpyFixed<2>(dest, src); + case 3: + return MemcpyFixed<3>(dest, src); + case 4: + return MemcpyFixed<4>(dest, src); + case 5: + return MemcpyFixed<5>(dest, src); + case 6: + return MemcpyFixed<6>(dest, src); + case 7: + return MemcpyFixed<7>(dest, src); + case 8: + return MemcpyFixed<8>(dest, src); + case 9: + return MemcpyFixed<9>(dest, src); + case 10: + return MemcpyFixed<10>(dest, src); + case 11: + return MemcpyFixed<11>(dest, src); + case 12: + return MemcpyFixed<12>(dest, src); + case 13: + return MemcpyFixed<13>(dest, src); + case 14: + return MemcpyFixed<14>(dest, src); + case 15: + return MemcpyFixed<15>(dest, src); + case 16: + return MemcpyFixed<16>(dest, src); + case 17: + return MemcpyFixed<17>(dest, src); + case 18: + return MemcpyFixed<18>(dest, src); + case 19: + return MemcpyFixed<19>(dest, src); + case 20: + return MemcpyFixed<20>(dest, src); + case 21: + return MemcpyFixed<21>(dest, src); + case 22: + return MemcpyFixed<22>(dest, src); + case 23: + return MemcpyFixed<23>(dest, src); + case 24: + return MemcpyFixed<24>(dest, src); + case 25: + return MemcpyFixed<25>(dest, src); + case 26: + return MemcpyFixed<26>(dest, src); + case 27: + return MemcpyFixed<27>(dest, src); + case 28: + return MemcpyFixed<28>(dest, src); + case 29: + return MemcpyFixed<29>(dest, src); + case 30: + return MemcpyFixed<30>(dest, src); + case 31: + return MemcpyFixed<31>(dest, src); + case 32: + return MemcpyFixed<32>(dest, src); + case 33: + return MemcpyFixed<33>(dest, src); + case 34: + return MemcpyFixed<34>(dest, src); + case 35: + return MemcpyFixed<35>(dest, src); + case 36: + return MemcpyFixed<36>(dest, src); + case 37: + return MemcpyFixed<37>(dest, src); + case 38: + return MemcpyFixed<38>(dest, src); + case 39: + return MemcpyFixed<39>(dest, src); + case 40: + return MemcpyFixed<40>(dest, src); + case 41: + return MemcpyFixed<41>(dest, src); + case 42: + return MemcpyFixed<42>(dest, src); + case 43: + return MemcpyFixed<43>(dest, src); + case 44: + return MemcpyFixed<44>(dest, src); + case 45: + return MemcpyFixed<45>(dest, src); + case 46: + return MemcpyFixed<46>(dest, src); + case 47: + return MemcpyFixed<47>(dest, src); + case 48: + return MemcpyFixed<48>(dest, src); + case 49: + return MemcpyFixed<49>(dest, src); + case 50: + return MemcpyFixed<50>(dest, src); + case 51: + return MemcpyFixed<51>(dest, src); + case 52: + return MemcpyFixed<52>(dest, src); + case 53: + return MemcpyFixed<53>(dest, src); + case 54: + return MemcpyFixed<54>(dest, src); + case 55: + return MemcpyFixed<55>(dest, src); + case 56: + return MemcpyFixed<56>(dest, src); + case 57: + return MemcpyFixed<57>(dest, src); + case 58: + return MemcpyFixed<58>(dest, src); + case 59: + return MemcpyFixed<59>(dest, src); + case 60: + return MemcpyFixed<60>(dest, src); + case 61: + return MemcpyFixed<61>(dest, src); + case 62: + return MemcpyFixed<62>(dest, src); + case 63: + return MemcpyFixed<63>(dest, src); + case 64: + return MemcpyFixed<64>(dest, src); + case 65: + return MemcpyFixed<65>(dest, src); + case 66: + return MemcpyFixed<66>(dest, src); + case 67: + return MemcpyFixed<67>(dest, src); + case 68: + return MemcpyFixed<68>(dest, src); + case 69: + return MemcpyFixed<69>(dest, src); + case 70: + return MemcpyFixed<70>(dest, src); + case 71: + return MemcpyFixed<71>(dest, src); + case 72: + return MemcpyFixed<72>(dest, src); + case 73: + return MemcpyFixed<73>(dest, src); + case 74: + return MemcpyFixed<74>(dest, src); + case 75: + return MemcpyFixed<75>(dest, src); + case 76: + return MemcpyFixed<76>(dest, src); + case 77: + return MemcpyFixed<77>(dest, src); + case 78: + return MemcpyFixed<78>(dest, src); + case 79: + return MemcpyFixed<79>(dest, src); + case 80: + return MemcpyFixed<80>(dest, src); + case 81: + return MemcpyFixed<81>(dest, src); + case 82: + return MemcpyFixed<82>(dest, src); + case 83: + return MemcpyFixed<83>(dest, src); + case 84: + return MemcpyFixed<84>(dest, src); + case 85: + return MemcpyFixed<85>(dest, src); + case 86: + return MemcpyFixed<86>(dest, src); + case 87: + return MemcpyFixed<87>(dest, src); + case 88: + return MemcpyFixed<88>(dest, src); + case 89: + return MemcpyFixed<89>(dest, src); + case 90: + return MemcpyFixed<90>(dest, src); + case 91: + return MemcpyFixed<91>(dest, src); + case 92: + return MemcpyFixed<92>(dest, src); + case 93: + return MemcpyFixed<93>(dest, src); + case 94: + return MemcpyFixed<94>(dest, src); + case 95: + return MemcpyFixed<95>(dest, src); + case 96: + return MemcpyFixed<96>(dest, src); + case 97: + return MemcpyFixed<97>(dest, src); + case 98: + return MemcpyFixed<98>(dest, src); + case 99: + return MemcpyFixed<99>(dest, src); + case 100: + return MemcpyFixed<100>(dest, src); + case 101: + return MemcpyFixed<101>(dest, src); + case 102: + return MemcpyFixed<102>(dest, src); + case 103: + return MemcpyFixed<103>(dest, src); + case 104: + return MemcpyFixed<104>(dest, src); + case 105: + return MemcpyFixed<105>(dest, src); + case 106: + return MemcpyFixed<106>(dest, src); + case 107: + return MemcpyFixed<107>(dest, src); + case 108: + return MemcpyFixed<108>(dest, src); + case 109: + return MemcpyFixed<109>(dest, src); + case 110: + return MemcpyFixed<110>(dest, src); + case 111: + return MemcpyFixed<111>(dest, src); + case 112: + return MemcpyFixed<112>(dest, src); + case 113: + return MemcpyFixed<113>(dest, src); + case 114: + return MemcpyFixed<114>(dest, src); + case 115: + return MemcpyFixed<115>(dest, src); + case 116: + return MemcpyFixed<116>(dest, src); + case 117: + return MemcpyFixed<117>(dest, src); + case 118: + return MemcpyFixed<118>(dest, src); + case 119: + return MemcpyFixed<119>(dest, src); + case 120: + return MemcpyFixed<120>(dest, src); + case 121: + return MemcpyFixed<121>(dest, src); + case 122: + return MemcpyFixed<122>(dest, src); + case 123: + return MemcpyFixed<123>(dest, src); + case 124: + return MemcpyFixed<124>(dest, src); + case 125: + return MemcpyFixed<125>(dest, src); + case 126: + return MemcpyFixed<126>(dest, src); + case 127: + return MemcpyFixed<127>(dest, src); + case 128: + return MemcpyFixed<128>(dest, src); + case 129: + return MemcpyFixed<129>(dest, src); + case 130: + return MemcpyFixed<130>(dest, src); + case 131: + return MemcpyFixed<131>(dest, src); + case 132: + return MemcpyFixed<132>(dest, src); + case 133: + return MemcpyFixed<133>(dest, src); + case 134: + return MemcpyFixed<134>(dest, src); + case 135: + return MemcpyFixed<135>(dest, src); + case 136: + return MemcpyFixed<136>(dest, src); + case 137: + return MemcpyFixed<137>(dest, src); + case 138: + return MemcpyFixed<138>(dest, src); + case 139: + return MemcpyFixed<139>(dest, src); + case 140: + return MemcpyFixed<140>(dest, src); + case 141: + return MemcpyFixed<141>(dest, src); + case 142: + return MemcpyFixed<142>(dest, src); + case 143: + return MemcpyFixed<143>(dest, src); + case 144: + return MemcpyFixed<144>(dest, src); + case 145: + return MemcpyFixed<145>(dest, src); + case 146: + return MemcpyFixed<146>(dest, src); + case 147: + return MemcpyFixed<147>(dest, src); + case 148: + return MemcpyFixed<148>(dest, src); + case 149: + return MemcpyFixed<149>(dest, src); + case 150: + return MemcpyFixed<150>(dest, src); + case 151: + return MemcpyFixed<151>(dest, src); + case 152: + return MemcpyFixed<152>(dest, src); + case 153: + return MemcpyFixed<153>(dest, src); + case 154: + return MemcpyFixed<154>(dest, src); + case 155: + return MemcpyFixed<155>(dest, src); + case 156: + return MemcpyFixed<156>(dest, src); + case 157: + return MemcpyFixed<157>(dest, src); + case 158: + return MemcpyFixed<158>(dest, src); + case 159: + return MemcpyFixed<159>(dest, src); + case 160: + return MemcpyFixed<160>(dest, src); + case 161: + return MemcpyFixed<161>(dest, src); + case 162: + return MemcpyFixed<162>(dest, src); + case 163: + return MemcpyFixed<163>(dest, src); + case 164: + return MemcpyFixed<164>(dest, src); + case 165: + return MemcpyFixed<165>(dest, src); + case 166: + return MemcpyFixed<166>(dest, src); + case 167: + return MemcpyFixed<167>(dest, src); + case 168: + return MemcpyFixed<168>(dest, src); + case 169: + return MemcpyFixed<169>(dest, src); + case 170: + return MemcpyFixed<170>(dest, src); + case 171: + return MemcpyFixed<171>(dest, src); + case 172: + return MemcpyFixed<172>(dest, src); + case 173: + return MemcpyFixed<173>(dest, src); + case 174: + return MemcpyFixed<174>(dest, src); + case 175: + return MemcpyFixed<175>(dest, src); + case 176: + return MemcpyFixed<176>(dest, src); + case 177: + return MemcpyFixed<177>(dest, src); + case 178: + return MemcpyFixed<178>(dest, src); + case 179: + return MemcpyFixed<179>(dest, src); + case 180: + return MemcpyFixed<180>(dest, src); + case 181: + return MemcpyFixed<181>(dest, src); + case 182: + return MemcpyFixed<182>(dest, src); + case 183: + return MemcpyFixed<183>(dest, src); + case 184: + return MemcpyFixed<184>(dest, src); + case 185: + return MemcpyFixed<185>(dest, src); + case 186: + return MemcpyFixed<186>(dest, src); + case 187: + return MemcpyFixed<187>(dest, src); + case 188: + return MemcpyFixed<188>(dest, src); + case 189: + return MemcpyFixed<189>(dest, src); + case 190: + return MemcpyFixed<190>(dest, src); + case 191: + return MemcpyFixed<191>(dest, src); + case 192: + return MemcpyFixed<192>(dest, src); + case 193: + return MemcpyFixed<193>(dest, src); + case 194: + return MemcpyFixed<194>(dest, src); + case 195: + return MemcpyFixed<195>(dest, src); + case 196: + return MemcpyFixed<196>(dest, src); + case 197: + return MemcpyFixed<197>(dest, src); + case 198: + return MemcpyFixed<198>(dest, src); + case 199: + return MemcpyFixed<199>(dest, src); + case 200: + return MemcpyFixed<200>(dest, src); + case 201: + return MemcpyFixed<201>(dest, src); + case 202: + return MemcpyFixed<202>(dest, src); + case 203: + return MemcpyFixed<203>(dest, src); + case 204: + return MemcpyFixed<204>(dest, src); + case 205: + return MemcpyFixed<205>(dest, src); + case 206: + return MemcpyFixed<206>(dest, src); + case 207: + return MemcpyFixed<207>(dest, src); + case 208: + return MemcpyFixed<208>(dest, src); + case 209: + return MemcpyFixed<209>(dest, src); + case 210: + return MemcpyFixed<210>(dest, src); + case 211: + return MemcpyFixed<211>(dest, src); + case 212: + return MemcpyFixed<212>(dest, src); + case 213: + return MemcpyFixed<213>(dest, src); + case 214: + return MemcpyFixed<214>(dest, src); + case 215: + return MemcpyFixed<215>(dest, src); + case 216: + return MemcpyFixed<216>(dest, src); + case 217: + return MemcpyFixed<217>(dest, src); + case 218: + return MemcpyFixed<218>(dest, src); + case 219: + return MemcpyFixed<219>(dest, src); + case 220: + return MemcpyFixed<220>(dest, src); + case 221: + return MemcpyFixed<221>(dest, src); + case 222: + return MemcpyFixed<222>(dest, src); + case 223: + return MemcpyFixed<223>(dest, src); + case 224: + return MemcpyFixed<224>(dest, src); + case 225: + return MemcpyFixed<225>(dest, src); + case 226: + return MemcpyFixed<226>(dest, src); + case 227: + return MemcpyFixed<227>(dest, src); + case 228: + return MemcpyFixed<228>(dest, src); + case 229: + return MemcpyFixed<229>(dest, src); + case 230: + return MemcpyFixed<230>(dest, src); + case 231: + return MemcpyFixed<231>(dest, src); + case 232: + return MemcpyFixed<232>(dest, src); + case 233: + return MemcpyFixed<233>(dest, src); + case 234: + return MemcpyFixed<234>(dest, src); + case 235: + return MemcpyFixed<235>(dest, src); + case 236: + return MemcpyFixed<236>(dest, src); + case 237: + return MemcpyFixed<237>(dest, src); + case 238: + return MemcpyFixed<238>(dest, src); + case 239: + return MemcpyFixed<239>(dest, src); + case 240: + return MemcpyFixed<240>(dest, src); + case 241: + return MemcpyFixed<241>(dest, src); + case 242: + return MemcpyFixed<242>(dest, src); + case 243: + return MemcpyFixed<243>(dest, src); + case 244: + return MemcpyFixed<244>(dest, src); + case 245: + return MemcpyFixed<245>(dest, src); + case 246: + return MemcpyFixed<246>(dest, src); + case 247: + return MemcpyFixed<247>(dest, src); + case 248: + return MemcpyFixed<248>(dest, src); + case 249: + return MemcpyFixed<249>(dest, src); + case 250: + return MemcpyFixed<250>(dest, src); + case 251: + return MemcpyFixed<251>(dest, src); + case 252: + return MemcpyFixed<252>(dest, src); + case 253: + return MemcpyFixed<253>(dest, src); + case 254: + return MemcpyFixed<254>(dest, src); + case 255: + return MemcpyFixed<255>(dest, src); + case 256: + return MemcpyFixed<256>(dest, src); + default: + memcpy(dest, src, size); + } + // LCOV_EXCL_STOP +} + +//! This templated memcmp is significantly faster than std::memcmp, +//! but only when you are calling memcmp with a const size in a loop. +//! For instance `while () { memcmp(, , const_size); ... }` +static inline int FastMemcmp(const void *str1, const void *str2, const size_t size) { + // LCOV_EXCL_START + switch (size) { + case 0: + return 0; + case 1: + return MemcmpFixed<1>(str1, str2); + case 2: + return MemcmpFixed<2>(str1, str2); + case 3: + return MemcmpFixed<3>(str1, str2); + case 4: + return MemcmpFixed<4>(str1, str2); + case 5: + return MemcmpFixed<5>(str1, str2); + case 6: + return MemcmpFixed<6>(str1, str2); + case 7: + return MemcmpFixed<7>(str1, str2); + case 8: + return MemcmpFixed<8>(str1, str2); + case 9: + return MemcmpFixed<9>(str1, str2); + case 10: + return MemcmpFixed<10>(str1, str2); + case 11: + return MemcmpFixed<11>(str1, str2); + case 12: + return MemcmpFixed<12>(str1, str2); + case 13: + return MemcmpFixed<13>(str1, str2); + case 14: + return MemcmpFixed<14>(str1, str2); + case 15: + return MemcmpFixed<15>(str1, str2); + case 16: + return MemcmpFixed<16>(str1, str2); + case 17: + return MemcmpFixed<17>(str1, str2); + case 18: + return MemcmpFixed<18>(str1, str2); + case 19: + return MemcmpFixed<19>(str1, str2); + case 20: + return MemcmpFixed<20>(str1, str2); + case 21: + return MemcmpFixed<21>(str1, str2); + case 22: + return MemcmpFixed<22>(str1, str2); + case 23: + return MemcmpFixed<23>(str1, str2); + case 24: + return MemcmpFixed<24>(str1, str2); + case 25: + return MemcmpFixed<25>(str1, str2); + case 26: + return MemcmpFixed<26>(str1, str2); + case 27: + return MemcmpFixed<27>(str1, str2); + case 28: + return MemcmpFixed<28>(str1, str2); + case 29: + return MemcmpFixed<29>(str1, str2); + case 30: + return MemcmpFixed<30>(str1, str2); + case 31: + return MemcmpFixed<31>(str1, str2); + case 32: + return MemcmpFixed<32>(str1, str2); + case 33: + return MemcmpFixed<33>(str1, str2); + case 34: + return MemcmpFixed<34>(str1, str2); + case 35: + return MemcmpFixed<35>(str1, str2); + case 36: + return MemcmpFixed<36>(str1, str2); + case 37: + return MemcmpFixed<37>(str1, str2); + case 38: + return MemcmpFixed<38>(str1, str2); + case 39: + return MemcmpFixed<39>(str1, str2); + case 40: + return MemcmpFixed<40>(str1, str2); + case 41: + return MemcmpFixed<41>(str1, str2); + case 42: + return MemcmpFixed<42>(str1, str2); + case 43: + return MemcmpFixed<43>(str1, str2); + case 44: + return MemcmpFixed<44>(str1, str2); + case 45: + return MemcmpFixed<45>(str1, str2); + case 46: + return MemcmpFixed<46>(str1, str2); + case 47: + return MemcmpFixed<47>(str1, str2); + case 48: + return MemcmpFixed<48>(str1, str2); + case 49: + return MemcmpFixed<49>(str1, str2); + case 50: + return MemcmpFixed<50>(str1, str2); + case 51: + return MemcmpFixed<51>(str1, str2); + case 52: + return MemcmpFixed<52>(str1, str2); + case 53: + return MemcmpFixed<53>(str1, str2); + case 54: + return MemcmpFixed<54>(str1, str2); + case 55: + return MemcmpFixed<55>(str1, str2); + case 56: + return MemcmpFixed<56>(str1, str2); + case 57: + return MemcmpFixed<57>(str1, str2); + case 58: + return MemcmpFixed<58>(str1, str2); + case 59: + return MemcmpFixed<59>(str1, str2); + case 60: + return MemcmpFixed<60>(str1, str2); + case 61: + return MemcmpFixed<61>(str1, str2); + case 62: + return MemcmpFixed<62>(str1, str2); + case 63: + return MemcmpFixed<63>(str1, str2); + case 64: + return MemcmpFixed<64>(str1, str2); + default: + return memcmp(str1, str2, size); + } + // LCOV_EXCL_STOP +} } // namespace duckdb +namespace duckdb { -// LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 -// See the end of this file for a list +class BufferManager; +class RowLayout; +class RowDataCollection; +class Vector; +struct UnifiedVectorFormat; +struct SelectionVector; -/* - * PCG Random Number Generation for C++ - * - * Copyright 2014-2019 Melissa O'Neill , - * and the PCG Project contributors. - * - * SPDX-License-Identifier: (Apache-2.0 OR MIT) - * - * Licensed under the Apache License, Version 2.0 (provided in - * LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0) - * or under the MIT license (provided in LICENSE-MIT.txt and at - * http://opensource.org/licenses/MIT), at your option. This file may not - * be copied, modified, or distributed except according to those terms. - * - * Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See your chosen license for details. - * - * For additional information about the PCG random number generation scheme, - * visit http://www.pcg-random.org/. - */ +//! Templated radix partitioning constants, can be templated to the number of radix bits +template +struct RadixPartitioningConstants { +public: + static constexpr const idx_t NUM_RADIX_BITS = radix_bits; + static constexpr const idx_t NUM_PARTITIONS = 1 << NUM_RADIX_BITS; + static constexpr const idx_t TMP_BUF_SIZE = 8; -/* - * This code provides the reference implementation of the PCG family of - * random number generators. The code is complex because it implements - * - * - several members of the PCG family, specifically members corresponding - * to the output functions: - * - XSH RR (good for 64-bit state, 32-bit output) - * - XSH RS (good for 64-bit state, 32-bit output) - * - XSL RR (good for 128-bit state, 64-bit output) - * - RXS M XS (statistically most powerful generator) - * - XSL RR RR (good for 128-bit state, 128-bit output) - * - and RXS, RXS M, XSH, XSL (mostly for testing) - * - at potentially *arbitrary* bit sizes - * - with four different techniques for random streams (MCG, one-stream - * LCG, settable-stream LCG, unique-stream LCG) - * - and the extended generation schemes allowing arbitrary periods - * - with all features of C++11 random number generation (and more), - * some of which are somewhat painful, including - * - initializing with a SeedSequence which writes 32-bit values - * to memory, even though the state of the generator may not - * use 32-bit values (it might use smaller or larger integers) - * - I/O for RNGs and a prescribed format, which needs to handle - * the issue that 8-bit and 128-bit integers don't have working - * I/O routines (e.g., normally 8-bit = char, not integer) - * - equality and inequality for RNGs - * - and a number of convenience typedefs to mask all the complexity - * - * The code employes a fairly heavy level of abstraction, and has to deal - * with various C++ minutia. If you're looking to learn about how the PCG - * scheme works, you're probably best of starting with one of the other - * codebases (see www.pcg-random.org). But if you're curious about the - * constants for the various output functions used in those other, simpler, - * codebases, this code shows how they are calculated. - * - * On the positive side, at least there are convenience typedefs so that you - * can say - * - * pcg32 myRNG; - * - * rather than: - * - * pcg_detail::engine< - * uint32_t, // Output Type - * uint64_t, // State Type - * pcg_detail::xsh_rr_mixin, true, // Output Func - * pcg_detail::specific_stream, // Stream Kind - * pcg_detail::default_multiplier // LCG Mult - * > myRNG; - * - */ +public: + //! Apply bitmask on the highest bits, and right shift to get a number between 0 and NUM_PARTITIONS + static inline hash_t ApplyMask(hash_t hash) { + return (hash & MASK) >> (sizeof(hash_t) * 8 - NUM_RADIX_BITS); + } -#ifndef PCG_RAND_HPP_INCLUDED -#define PCG_RAND_HPP_INCLUDED 1 +private: + //! Bitmask of the highest bits + static constexpr const hash_t MASK = hash_t(-1) ^ ((hash_t(1) << (sizeof(hash_t) * 8 - NUM_RADIX_BITS)) - 1); +}; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +//! Generic radix partitioning functions +struct RadixPartitioning { +public: + static idx_t NumberOfPartitions(idx_t radix_bits) { + return 1 << radix_bits; + } -#ifdef _MSC_VER - #pragma warning(disable:4146) -#endif + //! Partition the data in block_collection/string_heap to multiple partitions + static void Partition(BufferManager &buffer_manager, const RowLayout &layout, const idx_t hash_offset, + RowDataCollection &block_collection, RowDataCollection &string_heap, + vector> &partition_block_collections, + vector> &partition_string_heaps, idx_t radix_bits); + //! Select using a cutoff on the radix bits of the hash + static idx_t Select(Vector &hashes, const SelectionVector *sel, idx_t count, idx_t radix_bits, idx_t cutoff, + SelectionVector *true_sel, SelectionVector *false_sel); +}; -#ifdef _MSC_VER - #define PCG_ALWAYS_INLINE __forceinline -#elif __GNUC__ - #define PCG_ALWAYS_INLINE __attribute__((always_inline)) -#else - #define PCG_ALWAYS_INLINE inline -#endif +} // namespace duckdb -#ifdef min -#undef min -#endif -#ifdef max -#undef max -#endif +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/row_operations/row_operations.hpp +// +// +//===----------------------------------------------------------------------===// -/* - * The pcg_extras namespace contains some support code that is likley to - * be useful for a variety of RNGs, including: - * - 128-bit int support for platforms where it isn't available natively - * - bit twiddling operations - * - I/O of 128-bit and 8-bit integers - * - Handling the evilness of SeedSeq - * - Support for efficiently producing random numbers less than a given - * bound - */ -// LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 -// See the end of this file for a list -/* - * PCG Random Number Generation for C++ - * - * Copyright 2014-2017 Melissa O'Neill , - * and the PCG Project contributors. - * - * SPDX-License-Identifier: (Apache-2.0 OR MIT) - * - * Licensed under the Apache License, Version 2.0 (provided in - * LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0) - * or under the MIT license (provided in LICENSE-MIT.txt and at - * http://opensource.org/licenses/MIT), at your option. This file may not - * be copied, modified, or distributed except according to those terms. - * - * Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either - * express or implied. See your chosen license for details. - * - * For additional information about the PCG random number generation scheme, - * visit http://www.pcg-random.org/. - */ -/* - * This file provides support code that is useful for random-number generation - * but not specific to the PCG generation scheme, including: - * - 128-bit int support for platforms where it isn't available natively - * - bit twiddling operations - * - I/O of 128-bit and 8-bit integers - * - Handling the evilness of SeedSeq - * - Support for efficiently producing random numbers less than a given - * bound - */ +namespace duckdb { -#ifndef PCG_EXTRAS_HPP_INCLUDED -#define PCG_EXTRAS_HPP_INCLUDED 1 +struct AggregateObject; +struct AggregateFilterData; +class DataChunk; +class RowLayout; +class RowDataCollection; +struct SelectionVector; +class StringHeap; +class Vector; +struct UnifiedVectorFormat; -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +// RowOperations contains a set of operations that operate on data using a RowLayout +struct RowOperations { + //===--------------------------------------------------------------------===// + // Aggregation Operators + //===--------------------------------------------------------------------===// + //! initialize - unaligned addresses + static void InitializeStates(RowLayout &layout, Vector &addresses, const SelectionVector &sel, idx_t count); + //! destructor - unaligned addresses, updated + static void DestroyStates(RowLayout &layout, Vector &addresses, idx_t count); + //! update - aligned addresses + static void UpdateStates(AggregateObject &aggr, Vector &addresses, DataChunk &payload, idx_t arg_idx, idx_t count); + //! filtered update - aligned addresses + static void UpdateFilteredStates(AggregateFilterData &filter_data, AggregateObject &aggr, Vector &addresses, + DataChunk &payload, idx_t arg_idx); + //! combine - unaligned addresses, updated + static void CombineStates(RowLayout &layout, Vector &sources, Vector &targets, idx_t count); + //! finalize - unaligned addresses, updated + static void FinalizeStates(RowLayout &layout, Vector &addresses, DataChunk &result, idx_t aggr_idx); -#ifdef __GNUC__ - #include -#endif + //===--------------------------------------------------------------------===// + // Read/Write Operators + //===--------------------------------------------------------------------===// + //! Scatter group data to the rows. Initialises the ValidityMask. + static void Scatter(DataChunk &columns, UnifiedVectorFormat col_data[], const RowLayout &layout, Vector &rows, + RowDataCollection &string_heap, const SelectionVector &sel, idx_t count); + //! Gather a single column. + //! If heap_ptr is not null, then the data is assumed to contain swizzled pointers, + //! which will be unswizzled in memory. + static void Gather(Vector &rows, const SelectionVector &row_sel, Vector &col, const SelectionVector &col_sel, + const idx_t count, const RowLayout &layout, const idx_t col_no, const idx_t build_size = 0, + data_ptr_t heap_ptr = nullptr); + //! Full Scan an entire columns + static void FullScanColumn(const RowLayout &layout, Vector &rows, Vector &col, idx_t count, idx_t col_idx); -/* - * Abstractions for compiler-specific directives - */ + //===--------------------------------------------------------------------===// + // Comparison Operators + //===--------------------------------------------------------------------===// + //! Compare a block of key data against the row values to produce an updated selection that matches + //! and a second (optional) selection of non-matching values. + //! Returns the number of matches remaining in the selection. + using Predicates = vector; -#ifdef __GNUC__ - #define PCG_NOINLINE __attribute__((noinline)) -#else - #define PCG_NOINLINE -#endif + static idx_t Match(DataChunk &columns, UnifiedVectorFormat col_data[], const RowLayout &layout, Vector &rows, + const Predicates &predicates, SelectionVector &sel, idx_t count, SelectionVector *no_match, + idx_t &no_match_count); -/* - * Some members of the PCG library use 128-bit math. When compiling on 64-bit - * platforms, both GCC and Clang provide 128-bit integer types that are ideal - * for the job. - * - * On 32-bit platforms (or with other compilers), we fall back to a C++ - * class that provides 128-bit unsigned integers instead. It may seem - * like we're reinventing the wheel here, because libraries already exist + //===--------------------------------------------------------------------===// + // Heap Operators + //===--------------------------------------------------------------------===// + //! Compute the entry sizes of a vector with variable size type (used before building heap buffer space). + static void ComputeEntrySizes(Vector &v, idx_t entry_sizes[], idx_t vcount, idx_t ser_count, + const SelectionVector &sel, idx_t offset = 0); + //! Compute the entry sizes of vector data with variable size type (used before building heap buffer space). + static void ComputeEntrySizes(Vector &v, UnifiedVectorFormat &vdata, idx_t entry_sizes[], idx_t vcount, + idx_t ser_count, const SelectionVector &sel, idx_t offset = 0); + //! Scatter vector with variable size type to the heap. + static void HeapScatter(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, idx_t col_idx, + data_ptr_t *key_locations, data_ptr_t *validitymask_locations, idx_t offset = 0); + //! Scatter vector data with variable size type to the heap. + static void HeapScatterVData(UnifiedVectorFormat &vdata, PhysicalType type, const SelectionVector &sel, + idx_t ser_count, idx_t col_idx, data_ptr_t *key_locations, + data_ptr_t *validitymask_locations, idx_t offset = 0); + //! Gather a single column with variable size type from the heap. + static void HeapGather(Vector &v, const idx_t &vcount, const SelectionVector &sel, const idx_t &col_idx, + data_ptr_t key_locations[], data_ptr_t validitymask_locations[]); + + //===--------------------------------------------------------------------===// + // Sorting Operators + //===--------------------------------------------------------------------===// + //! Scatter vector data to the rows in radix-sortable format. + static void RadixScatter(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, + data_ptr_t key_locations[], bool desc, bool has_null, bool nulls_first, idx_t prefix_len, + idx_t width, idx_t offset = 0); + + //===--------------------------------------------------------------------===// + // Out-of-Core Operators + //===--------------------------------------------------------------------===// + //! Swizzles blob pointers to offset within heap row + static void SwizzleColumns(const RowLayout &layout, const data_ptr_t base_row_ptr, const idx_t count); + //! Swizzles the base pointer of each row to offset within heap block + static void SwizzleHeapPointer(const RowLayout &layout, data_ptr_t row_ptr, const data_ptr_t heap_base_ptr, + const idx_t count, const idx_t base_offset = 0); + //! Copies 'count' heap rows that are pointed to by the rows at 'row_ptr' to 'heap_ptr' and swizzles the pointers + static void CopyHeapAndSwizzle(const RowLayout &layout, data_ptr_t row_ptr, const data_ptr_t heap_base_ptr, + data_ptr_t heap_ptr, const idx_t count); + + //! Unswizzles the base offset within heap block the rows to pointers + static void UnswizzleHeapPointer(const RowLayout &layout, const data_ptr_t base_row_ptr, + const data_ptr_t base_heap_ptr, const idx_t count); + //! Unswizzles all offsets back to pointers + static void UnswizzlePointers(const RowLayout &layout, const data_ptr_t base_row_ptr, + const data_ptr_t base_heap_ptr, const idx_t count); +}; + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/types/row_data_collection.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + +namespace duckdb { + +struct RowDataBlock { +public: + RowDataBlock(BufferManager &buffer_manager, idx_t capacity, idx_t entry_size) + : capacity(capacity), entry_size(entry_size), count(0), byte_offset(0) { + block = buffer_manager.RegisterMemory(capacity * entry_size, false); + } + explicit RowDataBlock(idx_t entry_size) : entry_size(entry_size) { + } + //! The buffer block handle + shared_ptr block; + //! Capacity (number of entries) and entry size that fit in this block + idx_t capacity; + const idx_t entry_size; + //! Number of entries currently in this block + idx_t count; + //! Write offset (if variable size entries) + idx_t byte_offset; + +private: + //! Implicit copying is not allowed + RowDataBlock(const RowDataBlock &) = delete; + +public: + unique_ptr Copy() { + auto result = make_unique(entry_size); + result->block = block; + result->capacity = capacity; + result->count = count; + result->byte_offset = byte_offset; + return result; + } +}; + +struct BlockAppendEntry { + BlockAppendEntry(data_ptr_t baseptr, idx_t count) : baseptr(baseptr), count(count) { + } + data_ptr_t baseptr; + idx_t count; +}; + +class RowDataCollection { +public: + RowDataCollection(BufferManager &buffer_manager, idx_t block_capacity, idx_t entry_size, bool keep_pinned = false); + + unique_ptr CloneEmpty(bool keep_pinned = false) const { + return make_unique(buffer_manager, block_capacity, entry_size, keep_pinned); + } + + //! BufferManager + BufferManager &buffer_manager; + //! The total number of stored entries + idx_t count; + //! The number of entries per block + idx_t block_capacity; + //! Size of entries in the blocks + idx_t entry_size; + //! The blocks holding the main data + vector> blocks; + //! The blocks that this collection currently has pinned + vector pinned_blocks; + //! Whether the blocks should stay pinned (necessary for e.g. a heap) + const bool keep_pinned; + +public: + idx_t AppendToBlock(RowDataBlock &block, BufferHandle &handle, vector &append_entries, + idx_t remaining, idx_t entry_sizes[]); + RowDataBlock &CreateBlock(); + vector Build(idx_t added_count, data_ptr_t key_locations[], idx_t entry_sizes[], + const SelectionVector *sel = FlatVector::IncrementalSelectionVector()); + + void Merge(RowDataCollection &other); + + void Clear() { + blocks.clear(); + pinned_blocks.clear(); + count = 0; + } + + //! The size (in bytes) of this RowDataCollection if it were stored in a single block + idx_t SizeInBytes() const { + idx_t bytes = 0; + if (entry_size == 1) { + for (auto &block : blocks) { + bytes += block->byte_offset; + } + } else { + bytes = count * entry_size; + } + return bytes; + } + + static inline idx_t EntriesPerBlock(idx_t width) { + return (Storage::BLOCK_SIZE + width * STANDARD_VECTOR_SIZE - 1) / width; + } + +private: + mutex rdc_lock; + + //! Copying is not allowed + RowDataCollection(const RowDataCollection &) = delete; +}; + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/types/row_layout.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/operator/aggregate/aggregate_object.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +class BoundAggregateExpression; + +struct AggregateObject { + AggregateObject(AggregateFunction function, FunctionData *bind_data, idx_t child_count, idx_t payload_size, + bool distinct, PhysicalType return_type, Expression *filter = nullptr); + AggregateObject(BoundAggregateExpression *aggr); + + AggregateFunction function; + FunctionData *bind_data; + idx_t child_count; + idx_t payload_size; + bool distinct; + PhysicalType return_type; + Expression *filter = nullptr; + + static vector CreateAggregateObjects(const vector &bindings); +}; + +struct AggregateFilterData { + AggregateFilterData(Allocator &allocator, Expression &filter_expr, const vector &payload_types); + + idx_t ApplyFilter(DataChunk &payload); + + ExpressionExecutor filter_executor; + DataChunk filtered_payload; + SelectionVector true_sel; +}; + +struct AggregateFilterDataSet { + AggregateFilterDataSet(); + + vector> filter_data; + +public: + void Initialize(Allocator &allocator, const vector &aggregates, + const vector &payload_types); + + AggregateFilterData &GetFilterData(idx_t aggr_idx); +}; + +} // namespace duckdb + + +namespace duckdb { + +class RowLayout { +public: + using Aggregates = vector; + using ValidityBytes = TemplatedValidityMask; + + //! Creates an empty RowLayout + RowLayout(); + +public: + //! Initializes the RowLayout with the specified types and aggregates to an empty RowLayout + void Initialize(vector types_p, Aggregates aggregates_p, bool align = true); + //! Initializes the RowLayout with the specified types to an empty RowLayout + void Initialize(vector types, bool align = true); + //! Initializes the RowLayout with the specified aggregates to an empty RowLayout + void Initialize(Aggregates aggregates_p, bool align = true); + //! Returns the number of data columns + inline idx_t ColumnCount() const { + return types.size(); + } + //! Returns a list of the column types for this data chunk + inline const vector &GetTypes() const { + return types; + } + //! Returns the number of aggregates + inline idx_t AggregateCount() const { + return aggregates.size(); + } + //! Returns a list of the aggregates for this data chunk + inline Aggregates &GetAggregates() { + return aggregates; + } + //! Returns the total width required for each row, including padding + inline idx_t GetRowWidth() const { + return row_width; + } + //! Returns the offset to the start of the data + inline idx_t GetDataOffset() const { + return flag_width; + } + //! Returns the total width required for the data, including padding + inline idx_t GetDataWidth() const { + return data_width; + } + //! Returns the offset to the start of the aggregates + inline idx_t GetAggrOffset() const { + return flag_width + data_width; + } + //! Returns the total width required for the aggregates, including padding + inline idx_t GetAggrWidth() const { + return aggr_width; + } + //! Returns the column offsets into each row + inline const vector &GetOffsets() const { + return offsets; + } + //! Returns whether all columns in this layout are constant size + inline bool AllConstant() const { + return all_constant; + } + inline idx_t GetHeapOffset() const { + return heap_pointer_offset; + } + +private: + //! The types of the data columns + vector types; + //! The aggregate functions + Aggregates aggregates; + //! The width of the validity header + idx_t flag_width; + //! The width of the data portion + idx_t data_width; + //! The width of the aggregate state portion + idx_t aggr_width; + //! The width of the entire row + idx_t row_width; + //! The offsets to the columns and aggregate data in each row + vector offsets; + //! Whether all columns in this layout are constant size + bool all_constant; + //! Offset to the pointer to the heap for each row + idx_t heap_pointer_offset; +}; + +} // namespace duckdb + + + + +namespace duckdb { + +template +RETURN_TYPE RadixBitsSwitch(idx_t radix_bits, ARGS &&...args) { + D_ASSERT(radix_bits <= sizeof(hash_t) * 8); + switch (radix_bits) { + case 1: + return OP::template Operation<1>(std::forward(args)...); + case 2: + return OP::template Operation<2>(std::forward(args)...); + case 3: + return OP::template Operation<3>(std::forward(args)...); + case 4: + return OP::template Operation<4>(std::forward(args)...); + case 5: + return OP::template Operation<5>(std::forward(args)...); + case 6: + return OP::template Operation<6>(std::forward(args)...); + case 7: + return OP::template Operation<7>(std::forward(args)...); + case 8: + return OP::template Operation<8>(std::forward(args)...); + case 9: + return OP::template Operation<9>(std::forward(args)...); + case 10: + return OP::template Operation<10>(std::forward(args)...); + default: + throw InternalException("TODO"); + } +} + +template +RETURN_TYPE DoubleRadixBitsSwitch2(idx_t radix_bits_2, ARGS &&...args) { + D_ASSERT(radix_bits_2 <= sizeof(hash_t) * 8); + switch (radix_bits_2) { + case 1: + return OP::template Operation(std::forward(args)...); + case 2: + return OP::template Operation(std::forward(args)...); + case 3: + return OP::template Operation(std::forward(args)...); + case 4: + return OP::template Operation(std::forward(args)...); + case 5: + return OP::template Operation(std::forward(args)...); + case 6: + return OP::template Operation(std::forward(args)...); + case 7: + return OP::template Operation(std::forward(args)...); + case 8: + return OP::template Operation(std::forward(args)...); + case 9: + return OP::template Operation(std::forward(args)...); + case 10: + return OP::template Operation(std::forward(args)...); + default: + throw InternalException("TODO"); + } +} + +template +RETURN_TYPE DoubleRadixBitsSwitch1(idx_t radix_bits_1, idx_t radix_bits_2, ARGS &&...args) { + D_ASSERT(radix_bits_1 <= sizeof(hash_t) * 8); + switch (radix_bits_1) { + case 1: + return DoubleRadixBitsSwitch2(radix_bits_2, std::forward(args)...); + case 2: + return DoubleRadixBitsSwitch2(radix_bits_2, std::forward(args)...); + case 3: + return DoubleRadixBitsSwitch2(radix_bits_2, std::forward(args)...); + case 4: + return DoubleRadixBitsSwitch2(radix_bits_2, std::forward(args)...); + case 5: + return DoubleRadixBitsSwitch2(radix_bits_2, std::forward(args)...); + case 6: + return DoubleRadixBitsSwitch2(radix_bits_2, std::forward(args)...); + case 7: + return DoubleRadixBitsSwitch2(radix_bits_2, std::forward(args)...); + case 8: + return DoubleRadixBitsSwitch2(radix_bits_2, std::forward(args)...); + case 9: + return DoubleRadixBitsSwitch2(radix_bits_2, std::forward(args)...); + case 10: + return DoubleRadixBitsSwitch2(radix_bits_2, std::forward(args)...); + default: + throw InternalException("TODO"); + } +} + +template +static void InitPartitions(BufferManager &buffer_manager, vector> &partition_collections, + RowDataBlock *partition_blocks[], vector &partition_handles, + data_ptr_t partition_ptrs[], idx_t block_capacity, idx_t row_width) { + using CONSTANTS = RadixPartitioningConstants; + + partition_collections.reserve(CONSTANTS::NUM_PARTITIONS); + partition_handles.reserve(CONSTANTS::NUM_PARTITIONS); + for (idx_t i = 0; i < CONSTANTS::NUM_PARTITIONS; i++) { + partition_collections.push_back(make_unique(buffer_manager, block_capacity, row_width)); + partition_blocks[i] = &partition_collections[i]->CreateBlock(); + partition_handles.push_back(buffer_manager.Pin(partition_blocks[i]->block)); + if (partition_ptrs) { + partition_ptrs[i] = partition_handles[i].Ptr(); + } + } +} + +struct PartitionFunctor { + template + static void Operation(BufferManager &buffer_manager, const RowLayout &layout, const idx_t hash_offset, + RowDataCollection &block_collection, RowDataCollection &string_heap, + vector> &partition_block_collections, + vector> &partition_string_heaps) { + using CONSTANTS = RadixPartitioningConstants; + + const auto block_capacity = block_collection.block_capacity; + const auto row_width = layout.GetRowWidth(); + const auto has_heap = !layout.AllConstant(); + + // Fixed-size data + RowDataBlock *partition_data_blocks[CONSTANTS::NUM_PARTITIONS]; + vector partition_data_handles; + data_ptr_t partition_data_ptrs[CONSTANTS::NUM_PARTITIONS]; + InitPartitions(buffer_manager, partition_block_collections, partition_data_blocks, + partition_data_handles, partition_data_ptrs, block_capacity, row_width); + + // Variable-size data + RowDataBlock *partition_heap_blocks[CONSTANTS::NUM_PARTITIONS]; + vector partition_heap_handles; + if (has_heap) { + InitPartitions(buffer_manager, partition_string_heaps, partition_heap_blocks, + partition_heap_handles, nullptr, (idx_t)Storage::BLOCK_SIZE, 1); + } + + // We track the count of the current block for each partition in this array + uint32_t block_counts[CONSTANTS::NUM_PARTITIONS]; + memset(block_counts, 0, sizeof(block_counts)); + + // Allocate "SWWCB" temporary buffer + auto temp_buf_ptr = + unique_ptr(new data_t[CONSTANTS::TMP_BUF_SIZE * CONSTANTS::NUM_PARTITIONS * row_width]); + const auto tmp_buf = temp_buf_ptr.get(); + + // Initialize temporary buffer offsets + uint32_t pos[CONSTANTS::NUM_PARTITIONS]; + for (uint32_t idx = 0; idx < CONSTANTS::NUM_PARTITIONS; idx++) { + pos[idx] = idx * CONSTANTS::TMP_BUF_SIZE; + } + + auto &data_blocks = block_collection.blocks; + auto &heap_blocks = string_heap.blocks; + for (idx_t block_idx = 0; block_idx < data_blocks.size(); block_idx++) { + RowDataBlock *data_block; + BufferHandle data_handle; + data_ptr_t data_ptr; + PinAndSet(buffer_manager, *data_blocks[block_idx], &data_block, data_handle, data_ptr); + + // Pin the heap block (if necessary) + RowDataBlock *heap_block; + BufferHandle heap_handle; + if (has_heap) { + heap_block = heap_blocks[block_idx].get(); + heap_handle = buffer_manager.Pin(heap_block->block); + } + + idx_t remaining = data_block->count; + while (remaining != 0) { + const auto next = MinValue(remaining, STANDARD_VECTOR_SIZE); + + if (has_heap) { + // Unswizzle so that the rows that we copy have a pointer to their heap rows + RowOperations::UnswizzleHeapPointer(layout, data_ptr, heap_handle.Ptr(), next); + } + + for (idx_t i = 0; i < next; i++) { + const auto bin = CONSTANTS::ApplyMask(Load(data_ptr + hash_offset)); + + // Write entry to bin in temp buf + FastMemcpy(tmp_buf + pos[bin] * row_width, data_ptr, row_width); + data_ptr += row_width; + + if ((++pos[bin] & (CONSTANTS::TMP_BUF_SIZE - 1)) == 0) { + // Temp buf for this bin is full, flush temp buf to partition + auto &block_count = block_counts[bin]; + FlushTempBuf(partition_data_ptrs[bin], row_width, block_count, tmp_buf, pos[bin], + CONSTANTS::TMP_BUF_SIZE); + D_ASSERT(block_count <= block_capacity); + if (block_count + CONSTANTS::TMP_BUF_SIZE > block_capacity) { + // The block can't fit the next flush of the temp buf + partition_data_blocks[bin]->count = block_count; + if (has_heap) { + // Write last bit of heap data + PartitionHeap(buffer_manager, layout, *partition_string_heaps[bin], + *partition_data_blocks[bin], partition_data_ptrs[bin], + *partition_heap_blocks[bin], partition_heap_handles[bin]); + } + // Now we can create new blocks for this partition + CreateNewBlock(buffer_manager, has_heap, partition_block_collections, partition_data_blocks, + partition_data_handles, partition_data_ptrs, partition_string_heaps, + partition_heap_blocks, partition_heap_handles, block_counts, bin); + } + } + } + remaining -= next; + } + + // We are done with this input block + for (idx_t bin = 0; bin < CONSTANTS::NUM_PARTITIONS; bin++) { + auto count = pos[bin] & (CONSTANTS::TMP_BUF_SIZE - 1); + if (count != 0) { + // Clean up the temporary buffer + FlushTempBuf(partition_data_ptrs[bin], row_width, block_counts[bin], tmp_buf, pos[bin], count); + } + D_ASSERT(block_counts[bin] <= block_capacity); + partition_data_blocks[bin]->count = block_counts[bin]; + if (has_heap) { + // Write heap data so we can safely unpin the current input heap block + PartitionHeap(buffer_manager, layout, *partition_string_heaps[bin], *partition_data_blocks[bin], + partition_data_ptrs[bin], *partition_heap_blocks[bin], partition_heap_handles[bin]); + } + if (block_counts[bin] + CONSTANTS::TMP_BUF_SIZE > block_capacity) { + // The block can't fit the next flush of the temp buf + CreateNewBlock(buffer_manager, has_heap, partition_block_collections, partition_data_blocks, + partition_data_handles, partition_data_ptrs, partition_string_heaps, + partition_heap_blocks, partition_heap_handles, block_counts, bin); + } + } + + // Delete references to the input block we just finished processing to free up memory + data_blocks[block_idx] = nullptr; + if (has_heap) { + heap_blocks[block_idx] = nullptr; + } + } + + // Update counts + for (idx_t bin = 0; bin < CONSTANTS::NUM_PARTITIONS; bin++) { + partition_block_collections[bin]->count += block_counts[bin]; + if (has_heap) { + partition_string_heaps[bin]->count += block_counts[bin]; + } + } + + // Input data collections are empty, reset them + block_collection.Clear(); + string_heap.Clear(); + +#ifdef DEBUG + for (idx_t bin = 0; bin < CONSTANTS::NUM_PARTITIONS; bin++) { + auto &p_block_collection = *partition_block_collections[bin]; + idx_t p_count = 0; + for (idx_t b = 0; b < p_block_collection.blocks.size(); b++) { + auto &data_block = *p_block_collection.blocks[b]; + p_count += data_block.count; + if (!layout.AllConstant()) { + auto &p_string_heap = *partition_string_heaps[bin]; + D_ASSERT(p_block_collection.blocks.size() == p_string_heap.blocks.size()); + auto &heap_block = *p_string_heap.blocks[b]; + D_ASSERT(data_block.count == heap_block.count); + } + } + D_ASSERT(p_count == p_block_collection.count); + } +#endif + } + + static inline void FlushTempBuf(data_ptr_t &data_ptr, const idx_t &row_width, uint32_t &block_count, + const data_ptr_t &tmp_buf, uint32_t &pos, const idx_t count) { + pos -= count; + memcpy(data_ptr, tmp_buf + pos * row_width, count * row_width); + data_ptr += count * row_width; + block_count += count; + } + + static inline void CreateNewBlock(BufferManager &buffer_manager, const bool &has_heap, + vector> &partition_block_collections, + RowDataBlock *partition_data_blocks[], + vector &partition_data_handles, data_ptr_t partition_data_ptrs[], + vector> &partition_string_heaps, + RowDataBlock *partition_heap_blocks[], + vector &partition_heap_handles, uint32_t block_counts[], + const idx_t &bin) { + D_ASSERT(partition_data_blocks[bin]->count == block_counts[bin]); + partition_block_collections[bin]->count += block_counts[bin]; + PinAndSet(buffer_manager, partition_block_collections[bin]->CreateBlock(), &partition_data_blocks[bin], + partition_data_handles[bin], partition_data_ptrs[bin]); + + if (has_heap) { + partition_string_heaps[bin]->count += block_counts[bin]; + + auto &p_heap_block = *partition_heap_blocks[bin]; + // Set a new heap block + if (p_heap_block.byte_offset != p_heap_block.capacity) { + // More data fits on the heap block, just copy (reference) the block + partition_string_heaps[bin]->blocks.push_back(partition_heap_blocks[bin]->Copy()); + partition_string_heaps[bin]->blocks.back()->count = 0; + } else { + // Heap block is full, create a new one + partition_string_heaps[bin]->CreateBlock(); + } + + partition_heap_blocks[bin] = partition_string_heaps[bin]->blocks.back().get(); + partition_heap_handles[bin] = buffer_manager.Pin(partition_heap_blocks[bin]->block); + } + + block_counts[bin] = 0; + } + + static inline void PinAndSet(BufferManager &buffer_manager, RowDataBlock &block, RowDataBlock **block_ptr, + BufferHandle &handle, data_ptr_t &ptr) { + *block_ptr = █ + handle = buffer_manager.Pin(block.block); + ptr = handle.Ptr(); + } + + static inline void PartitionHeap(BufferManager &buffer_manager, const RowLayout &layout, + RowDataCollection &string_heap, RowDataBlock &data_block, + const data_ptr_t data_ptr, RowDataBlock &heap_block, BufferHandle &heap_handle) { + D_ASSERT(!layout.AllConstant()); + D_ASSERT(heap_block.block->BlockId() == heap_handle.GetBlockId()); + D_ASSERT(data_block.count >= heap_block.count); + const auto count = data_block.count - heap_block.count; + if (count == 0) { + return; + } + const auto row_width = layout.GetRowWidth(); + const auto base_row_ptr = data_ptr - count * row_width; + + // Compute size of remaining heap rows + idx_t size = 0; + auto row_ptr = base_row_ptr + layout.GetHeapOffset(); + for (idx_t i = 0; i < count; i++) { + size += Load(Load(row_ptr)); + row_ptr += row_width; + } + + // Resize block if it doesn't fit + auto required_size = heap_block.byte_offset + size; + if (required_size > heap_block.capacity) { + buffer_manager.ReAllocate(heap_block.block, required_size); + heap_block.capacity = required_size; + } + auto heap_ptr = heap_handle.Ptr() + heap_block.byte_offset; + +#ifdef DEBUG + if (data_block.count > count) { + auto previous_row_heap_offset = Load(base_row_ptr - layout.GetRowWidth() + layout.GetHeapOffset()); + auto previous_row_heap_ptr = heap_handle.Ptr() + previous_row_heap_offset; + auto current_heap_ptr = previous_row_heap_ptr + Load(previous_row_heap_ptr); + D_ASSERT(current_heap_ptr == heap_ptr); + } +#endif + + // Copy corresponding heap rows, swizzle, and update counts + RowOperations::CopyHeapAndSwizzle(layout, base_row_ptr, heap_handle.Ptr(), heap_ptr, count); + heap_block.count += count; + heap_block.byte_offset += size; + D_ASSERT(data_block.count == heap_block.count); + D_ASSERT(heap_ptr + size == heap_handle.Ptr() + heap_block.byte_offset); + D_ASSERT(heap_ptr <= heap_handle.Ptr() + heap_block.capacity); + } +}; + +void RadixPartitioning::Partition(BufferManager &buffer_manager, const RowLayout &layout, const idx_t hash_offset, + RowDataCollection &block_collection, RowDataCollection &string_heap, + vector> &partition_block_collections, + vector> &partition_string_heaps, idx_t radix_bits) { + return RadixBitsSwitch(radix_bits, buffer_manager, layout, hash_offset, block_collection, + string_heap, partition_block_collections, partition_string_heaps); +} + +template +struct RadixLessThan { + static inline bool Operation(hash_t hash, hash_t cutoff) { + using CONSTANTS = RadixPartitioningConstants; + return CONSTANTS::ApplyMask(hash) < cutoff; + } +}; + +struct SelectFunctor { + template + static idx_t Operation(Vector &hashes, const SelectionVector *sel, idx_t count, idx_t cutoff, + SelectionVector *true_sel, SelectionVector *false_sel) { + Vector cutoff_vector(Value::HASH(cutoff)); + return BinaryExecutor::Select>(hashes, cutoff_vector, sel, count, + true_sel, false_sel); + } +}; + +idx_t RadixPartitioning::Select(Vector &hashes, const SelectionVector *sel, idx_t count, idx_t radix_bits, idx_t cutoff, + SelectionVector *true_sel, SelectionVector *false_sel) { + return RadixBitsSwitch(radix_bits, hashes, sel, count, cutoff, true_sel, false_sel); +} + +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/random_engine.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +#include + +namespace duckdb { +class ClientContext; +struct RandomState; + +struct RandomEngine { + RandomEngine(int64_t seed = -1); + ~RandomEngine(); + +public: + //! Generate a random number between min and max + double NextRandom(double min, double max); + + //! Generate a random number between 0 and 1 + double NextRandom(); + uint32_t NextRandomInteger(); + + void SetSeed(uint32_t seed); + + static RandomEngine &Get(ClientContext &context); + +private: + unique_ptr random_state; +}; + +} // namespace duckdb + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7 +// See the end of this file for a list + +/* + * PCG Random Number Generation for C++ + * + * Copyright 2014-2019 Melissa O'Neill , + * and the PCG Project contributors. + * + * SPDX-License-Identifier: (Apache-2.0 OR MIT) + * + * Licensed under the Apache License, Version 2.0 (provided in + * LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0) + * or under the MIT license (provided in LICENSE-MIT.txt and at + * http://opensource.org/licenses/MIT), at your option. This file may not + * be copied, modified, or distributed except according to those terms. + * + * Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See your chosen license for details. + * + * For additional information about the PCG random number generation scheme, + * visit http://www.pcg-random.org/. + */ + +/* + * This code provides the reference implementation of the PCG family of + * random number generators. The code is complex because it implements + * + * - several members of the PCG family, specifically members corresponding + * to the output functions: + * - XSH RR (good for 64-bit state, 32-bit output) + * - XSH RS (good for 64-bit state, 32-bit output) + * - XSL RR (good for 128-bit state, 64-bit output) + * - RXS M XS (statistically most powerful generator) + * - XSL RR RR (good for 128-bit state, 128-bit output) + * - and RXS, RXS M, XSH, XSL (mostly for testing) + * - at potentially *arbitrary* bit sizes + * - with four different techniques for random streams (MCG, one-stream + * LCG, settable-stream LCG, unique-stream LCG) + * - and the extended generation schemes allowing arbitrary periods + * - with all features of C++11 random number generation (and more), + * some of which are somewhat painful, including + * - initializing with a SeedSequence which writes 32-bit values + * to memory, even though the state of the generator may not + * use 32-bit values (it might use smaller or larger integers) + * - I/O for RNGs and a prescribed format, which needs to handle + * the issue that 8-bit and 128-bit integers don't have working + * I/O routines (e.g., normally 8-bit = char, not integer) + * - equality and inequality for RNGs + * - and a number of convenience typedefs to mask all the complexity + * + * The code employes a fairly heavy level of abstraction, and has to deal + * with various C++ minutia. If you're looking to learn about how the PCG + * scheme works, you're probably best of starting with one of the other + * codebases (see www.pcg-random.org). But if you're curious about the + * constants for the various output functions used in those other, simpler, + * codebases, this code shows how they are calculated. + * + * On the positive side, at least there are convenience typedefs so that you + * can say + * + * pcg32 myRNG; + * + * rather than: + * + * pcg_detail::engine< + * uint32_t, // Output Type + * uint64_t, // State Type + * pcg_detail::xsh_rr_mixin, true, // Output Func + * pcg_detail::specific_stream, // Stream Kind + * pcg_detail::default_multiplier // LCG Mult + * > myRNG; + * + */ + +#ifndef PCG_RAND_HPP_INCLUDED +#define PCG_RAND_HPP_INCLUDED 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef _MSC_VER + #pragma warning(disable:4146) +#endif + +#ifdef _MSC_VER + #define PCG_ALWAYS_INLINE __forceinline +#elif __GNUC__ + #define PCG_ALWAYS_INLINE __attribute__((always_inline)) +#else + #define PCG_ALWAYS_INLINE inline +#endif + +#ifdef min +#undef min +#endif + +#ifdef max +#undef max +#endif + +/* + * The pcg_extras namespace contains some support code that is likley to + * be useful for a variety of RNGs, including: + * - 128-bit int support for platforms where it isn't available natively + * - bit twiddling operations + * - I/O of 128-bit and 8-bit integers + * - Handling the evilness of SeedSeq + * - Support for efficiently producing random numbers less than a given + * bound + */ + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7 +// See the end of this file for a list + +/* + * PCG Random Number Generation for C++ + * + * Copyright 2014-2017 Melissa O'Neill , + * and the PCG Project contributors. + * + * SPDX-License-Identifier: (Apache-2.0 OR MIT) + * + * Licensed under the Apache License, Version 2.0 (provided in + * LICENSE-APACHE.txt and at http://www.apache.org/licenses/LICENSE-2.0) + * or under the MIT license (provided in LICENSE-MIT.txt and at + * http://opensource.org/licenses/MIT), at your option. This file may not + * be copied, modified, or distributed except according to those terms. + * + * Distributed on an "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See your chosen license for details. + * + * For additional information about the PCG random number generation scheme, + * visit http://www.pcg-random.org/. + */ + +/* + * This file provides support code that is useful for random-number generation + * but not specific to the PCG generation scheme, including: + * - 128-bit int support for platforms where it isn't available natively + * - bit twiddling operations + * - I/O of 128-bit and 8-bit integers + * - Handling the evilness of SeedSeq + * - Support for efficiently producing random numbers less than a given + * bound + */ + +#ifndef PCG_EXTRAS_HPP_INCLUDED +#define PCG_EXTRAS_HPP_INCLUDED 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __GNUC__ + #include +#endif + +/* + * Abstractions for compiler-specific directives + */ + +#ifdef __GNUC__ + #define PCG_NOINLINE __attribute__((noinline)) +#else + #define PCG_NOINLINE +#endif + +/* + * Some members of the PCG library use 128-bit math. When compiling on 64-bit + * platforms, both GCC and Clang provide 128-bit integer types that are ideal + * for the job. + * + * On 32-bit platforms (or with other compilers), we fall back to a C++ + * class that provides 128-bit unsigned integers instead. It may seem + * like we're reinventing the wheel here, because libraries already exist * that support large integers, but most existing libraries provide a very * generic multiprecision code, but here we're operating at a fixed size. * Also, most other libraries are fairly heavyweight. So we use a direct @@ -29039,7 +34273,7 @@ struct RandomEngine { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7 // See the end of this file for a list /* @@ -32467,1759 +37701,2053 @@ DUCKDB_API std::vector RegexFindAll(const std::string &input, const Regex -// LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 -// See the end of this file for a list - -// Copyright 2003-2009 The RE2 Authors. All Rights Reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -#ifndef RE2_RE2_H_ -#define RE2_RE2_H_ - -// C++ interface to the re2 regular-expression library. -// RE2 supports Perl-style regular expressions (with extensions like -// \d, \w, \s, ...). -// -// ----------------------------------------------------------------------- -// REGEXP SYNTAX: -// -// This module uses the re2 library and hence supports -// its syntax for regular expressions, which is similar to Perl's with -// some of the more complicated things thrown away. In particular, -// backreferences and generalized assertions are not available, nor is \Z. -// -// See https://github.com/google/re2/wiki/Syntax for the syntax -// supported by RE2, and a comparison with PCRE and PERL regexps. -// -// For those not familiar with Perl's regular expressions, -// here are some examples of the most commonly used extensions: -// -// "hello (\\w+) world" -- \w matches a "word" character -// "version (\\d+)" -- \d matches a digit -// "hello\\s+world" -- \s matches any whitespace character -// "\\b(\\w+)\\b" -- \b matches non-empty string at word boundary -// "(?i)hello" -- (?i) turns on case-insensitive matching -// "/\\*(.*?)\\*/" -- .*? matches . minimum no. of times possible -// -// ----------------------------------------------------------------------- -// MATCHING INTERFACE: -// -// The "FullMatch" operation checks that supplied text matches a -// supplied pattern exactly. -// -// Example: successful match -// CHECK(RE2::FullMatch("hello", "h.*o")); -// -// Example: unsuccessful match (requires full match): -// CHECK(!RE2::FullMatch("hello", "e")); -// -// ----------------------------------------------------------------------- -// UTF-8 AND THE MATCHING INTERFACE: -// -// By default, the pattern and input text are interpreted as UTF-8. -// The RE2::Latin1 option causes them to be interpreted as Latin-1. -// -// Example: -// CHECK(RE2::FullMatch(utf8_string, RE2(utf8_pattern))); -// CHECK(RE2::FullMatch(latin1_string, RE2(latin1_pattern, RE2::Latin1))); -// -// ----------------------------------------------------------------------- -// MATCHING WITH SUBSTRING EXTRACTION: -// -// You can supply extra pointer arguments to extract matched substrings. -// On match failure, none of the pointees will have been modified. -// On match success, the substrings will be converted (as necessary) and -// their values will be assigned to their pointees until all conversions -// have succeeded or one conversion has failed. -// On conversion failure, the pointees will be in an indeterminate state -// because the caller has no way of knowing which conversion failed. -// However, conversion cannot fail for types like string and StringPiece -// that do not inspect the substring contents. Hence, in the common case -// where all of the pointees are of such types, failure is always due to -// match failure and thus none of the pointees will have been modified. -// -// Example: extracts "ruby" into "s" and 1234 into "i" -// int i; -// std::string s; -// CHECK(RE2::FullMatch("ruby:1234", "(\\w+):(\\d+)", &s, &i)); -// -// Example: fails because string cannot be stored in integer -// CHECK(!RE2::FullMatch("ruby", "(.*)", &i)); -// -// Example: fails because there aren't enough sub-patterns -// CHECK(!RE2::FullMatch("ruby:1234", "\\w+:\\d+", &s)); -// -// Example: does not try to extract any extra sub-patterns -// CHECK(RE2::FullMatch("ruby:1234", "(\\w+):(\\d+)", &s)); -// -// Example: does not try to extract into NULL -// CHECK(RE2::FullMatch("ruby:1234", "(\\w+):(\\d+)", NULL, &i)); -// -// Example: integer overflow causes failure -// CHECK(!RE2::FullMatch("ruby:1234567891234", "\\w+:(\\d+)", &i)); -// -// NOTE(rsc): Asking for substrings slows successful matches quite a bit. -// This may get a little faster in the future, but right now is slower -// than PCRE. On the other hand, failed matches run *very* fast (faster -// than PCRE), as do matches without substring extraction. -// -// ----------------------------------------------------------------------- -// PARTIAL MATCHES -// -// You can use the "PartialMatch" operation when you want the pattern -// to match any substring of the text. -// -// Example: simple search for a string: -// CHECK(RE2::PartialMatch("hello", "ell")); -// -// Example: find first number in a string -// int number; -// CHECK(RE2::PartialMatch("x*100 + 20", "(\\d+)", &number)); -// CHECK_EQ(number, 100); -// -// ----------------------------------------------------------------------- -// PRE-COMPILED REGULAR EXPRESSIONS -// -// RE2 makes it easy to use any string as a regular expression, without -// requiring a separate compilation step. -// -// If speed is of the essence, you can create a pre-compiled "RE2" -// object from the pattern and use it multiple times. If you do so, -// you can typically parse text faster than with sscanf. -// -// Example: precompile pattern for faster matching: -// RE2 pattern("h.*o"); -// while (ReadLine(&str)) { -// if (RE2::FullMatch(str, pattern)) ...; -// } -// -// ----------------------------------------------------------------------- -// SCANNING TEXT INCREMENTALLY -// -// The "Consume" operation may be useful if you want to repeatedly -// match regular expressions at the front of a string and skip over -// them as they match. This requires use of the "StringPiece" type, -// which represents a sub-range of a real string. -// -// Example: read lines of the form "var = value" from a string. -// std::string contents = ...; // Fill string somehow -// StringPiece input(contents); // Wrap a StringPiece around it -// -// std::string var; -// int value; -// while (RE2::Consume(&input, "(\\w+) = (\\d+)\n", &var, &value)) { -// ...; -// } -// -// Each successful call to "Consume" will set "var/value", and also -// advance "input" so it points past the matched text. Note that if the -// regular expression matches an empty string, input will advance -// by 0 bytes. If the regular expression being used might match -// an empty string, the loop body must check for this case and either -// advance the string or break out of the loop. -// -// The "FindAndConsume" operation is similar to "Consume" but does not -// anchor your match at the beginning of the string. For example, you -// could extract all words from a string by repeatedly calling -// RE2::FindAndConsume(&input, "(\\w+)", &word) -// -// ----------------------------------------------------------------------- -// USING VARIABLE NUMBER OF ARGUMENTS -// -// The above operations require you to know the number of arguments -// when you write the code. This is not always possible or easy (for -// example, the regular expression may be calculated at run time). -// You can use the "N" version of the operations when the number of -// match arguments are determined at run time. -// -// Example: -// const RE2::Arg* args[10]; -// int n; -// // ... populate args with pointers to RE2::Arg values ... -// // ... set n to the number of RE2::Arg objects ... -// bool match = RE2::FullMatchN(input, pattern, args, n); -// -// The last statement is equivalent to -// -// bool match = RE2::FullMatch(input, pattern, -// *args[0], *args[1], ..., *args[n - 1]); -// -// ----------------------------------------------------------------------- -// PARSING HEX/OCTAL/C-RADIX NUMBERS -// -// By default, if you pass a pointer to a numeric value, the -// corresponding text is interpreted as a base-10 number. You can -// instead wrap the pointer with a call to one of the operators Hex(), -// Octal(), or CRadix() to interpret the text in another base. The -// CRadix operator interprets C-style "0" (base-8) and "0x" (base-16) -// prefixes, but defaults to base-10. -// -// Example: -// int a, b, c, d; -// CHECK(RE2::FullMatch("100 40 0100 0x40", "(.*) (.*) (.*) (.*)", -// RE2::Octal(&a), RE2::Hex(&b), RE2::CRadix(&c), RE2::CRadix(&d)); -// will leave 64 in a, b, c, and d. +namespace duckdb_re2 { -#include -#include -#include -#include -#include -#include +Regex::Regex(const std::string &pattern, RegexOptions options) { + RE2::Options o; + o.set_case_sensitive(options == RegexOptions::CASE_INSENSITIVE); + regex = std::make_shared(StringPiece(pattern), o); +} +bool RegexSearchInternal(const char *input, Match &match, const Regex &r, RE2::Anchor anchor, size_t start, + size_t end) { + auto ®ex = r.GetRegex(); + std::vector target_groups; + auto group_count = regex.NumberOfCapturingGroups() + 1; + target_groups.resize(group_count); + match.groups.clear(); + if (!regex.Match(StringPiece(input), start, end, anchor, target_groups.data(), group_count)) { + return false; + } + for (auto &group : target_groups) { + GroupMatch group_match; + group_match.text = group.ToString(); + group_match.position = group.data() - input; + match.groups.emplace_back(group_match); + } + return true; +} +bool RegexSearch(const std::string &input, Match &match, const Regex ®ex) { + return RegexSearchInternal(input.c_str(), match, regex, RE2::UNANCHORED, 0, input.size()); +} -// LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 -// See the end of this file for a list +bool RegexMatch(const std::string &input, Match &match, const Regex ®ex) { + return RegexSearchInternal(input.c_str(), match, regex, RE2::ANCHOR_BOTH, 0, input.size()); +} -// Copyright 2001-2010 The RE2 Authors. All Rights Reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. +bool RegexMatch(const char *start, const char *end, Match &match, const Regex ®ex) { + return RegexSearchInternal(start, match, regex, RE2::ANCHOR_BOTH, 0, end - start); +} -#ifndef RE2_STRINGPIECE_H_ -#define RE2_STRINGPIECE_H_ +bool RegexMatch(const std::string &input, const Regex ®ex) { + Match nop_match; + return RegexSearchInternal(input.c_str(), nop_match, regex, RE2::ANCHOR_BOTH, 0, input.size()); +} -#ifdef min -#undef min -#endif +std::vector RegexFindAll(const std::string &input, const Regex ®ex) { + std::vector matches; + size_t position = 0; + Match match; + while (RegexSearchInternal(input.c_str(), match, regex, RE2::UNANCHORED, position, input.size())) { + position += match.position(0) + match.length(0); + matches.emplace_back(std::move(match)); + } + return matches; +} -// A string-like object that points to a sized piece of memory. -// -// Functions or methods may use const StringPiece& parameters to accept either -// a "const char*" or a "string" value that will be implicitly converted to -// a StringPiece. The implicit conversion means that it is often appropriate -// to include this .h file in other files rather than forward-declaring -// StringPiece as would be appropriate for most other Google classes. +} // namespace duckdb_re2 +//===----------------------------------------------------------------------===// +// DuckDB // -// Systematic usage of StringPiece is encouraged as it will reduce unnecessary -// conversions from "const char*" to "string" and back again. +// duckdb/common/types/row_operations/row_aggregate.cpp // // -// Arghh! I wish C++ literals were "string". +//===----------------------------------------------------------------------===// -// Doing this simplifies the logic below. -#ifndef __has_include -#define __has_include(x) 0 -#endif -#include -#include -#include -#include -#include -#include -#if __has_include() && __cplusplus >= 201703L -#include -#endif -namespace duckdb_re2 { -class StringPiece { - public: - typedef std::char_traits traits_type; - typedef char value_type; - typedef char* pointer; - typedef const char* const_pointer; - typedef char& reference; - typedef const char& const_reference; - typedef const char* const_iterator; - typedef const_iterator iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef const_reverse_iterator reverse_iterator; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - static const size_type npos = static_cast(-1); - // We provide non-explicit singleton constructors so users can pass - // in a "const char*" or a "string" wherever a "StringPiece" is - // expected. - StringPiece() - : data_(NULL), size_(0) {} -#if __has_include() && __cplusplus >= 201703L - StringPiece(const std::string_view& str) - : data_(str.data()), size_(str.size()) {} -#endif - StringPiece(const std::string& str) - : data_(str.data()), size_(str.size()) {} - StringPiece(const char* str) - : data_(str), size_(str == NULL ? 0 : strlen(str)) {} - StringPiece(const char* str, size_type len) - : data_(str), size_(len) {} - const_iterator begin() const { return data_; } - const_iterator end() const { return data_ + size_; } - const_reverse_iterator rbegin() const { - return const_reverse_iterator(data_ + size_); - } - const_reverse_iterator rend() const { - return const_reverse_iterator(data_); - } - size_type size() const { return size_; } - size_type length() const { return size_; } - bool empty() const { return size_ == 0; } +namespace duckdb { - const_reference operator[](size_type i) const { return data_[i]; } - const_pointer data() const { return data_; } +void RowOperations::InitializeStates(RowLayout &layout, Vector &addresses, const SelectionVector &sel, idx_t count) { + if (count == 0) { + return; + } + auto pointers = FlatVector::GetData(addresses); + auto &offsets = layout.GetOffsets(); + auto aggr_idx = layout.ColumnCount(); - void remove_prefix(size_type n) { - data_ += n; - size_ -= n; - } + for (auto &aggr : layout.GetAggregates()) { + for (idx_t i = 0; i < count; ++i) { + auto row_idx = sel.get_index(i); + auto row = pointers[row_idx]; + aggr.function.initialize(row + offsets[aggr_idx]); + } + ++aggr_idx; + } +} - void remove_suffix(size_type n) { - size_ -= n; - } +void RowOperations::DestroyStates(RowLayout &layout, Vector &addresses, idx_t count) { + if (count == 0) { + return; + } + // Move to the first aggregate state + VectorOperations::AddInPlace(addresses, layout.GetAggrOffset(), count); + for (auto &aggr : layout.GetAggregates()) { + if (aggr.function.destructor) { + aggr.function.destructor(addresses, count); + } + // Move to the next aggregate state + VectorOperations::AddInPlace(addresses, aggr.payload_size, count); + } +} - void set(const char* str) { - data_ = str; - size_ = str == NULL ? 0 : strlen(str); - } +void RowOperations::UpdateStates(AggregateObject &aggr, Vector &addresses, DataChunk &payload, idx_t arg_idx, + idx_t count) { + AggregateInputData aggr_input_data(aggr.bind_data, Allocator::DefaultAllocator()); + aggr.function.update(aggr.child_count == 0 ? nullptr : &payload.data[arg_idx], aggr_input_data, aggr.child_count, + addresses, count); +} - void set(const char* str, size_type len) { - data_ = str; - size_ = len; - } +void RowOperations::UpdateFilteredStates(AggregateFilterData &filter_data, AggregateObject &aggr, Vector &addresses, + DataChunk &payload, idx_t arg_idx) { + idx_t count = filter_data.ApplyFilter(payload); - // Converts to `std::basic_string`. - template - explicit operator std::basic_string() const { - if (!data_) return {}; - return std::basic_string(data_, size_); - } + Vector filtered_addresses(addresses, filter_data.true_sel, count); + filtered_addresses.Flatten(count); - std::string as_string() const { - return std::string(data_, size_); - } + UpdateStates(aggr, filtered_addresses, filter_data.filtered_payload, arg_idx, count); +} - // We also define ToString() here, since many other string-like - // interfaces name the routine that converts to a C++ string - // "ToString", and it's confusing to have the method that does that - // for a StringPiece be called "as_string()". We also leave the - // "as_string()" method defined here for existing code. - std::string ToString() const { - return std::string(data_, size_); - } +void RowOperations::CombineStates(RowLayout &layout, Vector &sources, Vector &targets, idx_t count) { + if (count == 0) { + return; + } - void CopyToString(std::string* target) const { - target->assign(data_, size_); - } + // Move to the first aggregate states + VectorOperations::AddInPlace(sources, layout.GetAggrOffset(), count); + VectorOperations::AddInPlace(targets, layout.GetAggrOffset(), count); + for (auto &aggr : layout.GetAggregates()) { + D_ASSERT(aggr.function.combine); + AggregateInputData aggr_input_data(aggr.bind_data, Allocator::DefaultAllocator()); + aggr.function.combine(sources, targets, aggr_input_data, count); - void AppendToString(std::string* target) const { - target->append(data_, size_); - } + // Move to the next aggregate states + VectorOperations::AddInPlace(sources, aggr.payload_size, count); + VectorOperations::AddInPlace(targets, aggr.payload_size, count); + } +} - size_type copy(char* buf, size_type n, size_type pos = 0) const; - StringPiece substr(size_type pos = 0, size_type n = npos) const; +void RowOperations::FinalizeStates(RowLayout &layout, Vector &addresses, DataChunk &result, idx_t aggr_idx) { + // Move to the first aggregate state + VectorOperations::AddInPlace(addresses, layout.GetAggrOffset(), result.size()); - int compare(const StringPiece& x) const { - size_type min_size = std::min(size(), x.size()); - if (min_size > 0) { - int r = memcmp(data(), x.data(), min_size); - if (r < 0) return -1; - if (r > 0) return 1; - } - if (size() < x.size()) return -1; - if (size() > x.size()) return 1; - return 0; - } + auto &aggregates = layout.GetAggregates(); + for (idx_t i = 0; i < aggregates.size(); i++) { + auto &target = result.data[aggr_idx + i]; + auto &aggr = aggregates[i]; + AggregateInputData aggr_input_data(aggr.bind_data, Allocator::DefaultAllocator()); + aggr.function.finalize(addresses, aggr_input_data, target, result.size(), 0); - // Does "this" start with "x"? - bool starts_with(const StringPiece& x) const { - return x.empty() || - (size() >= x.size() && memcmp(data(), x.data(), x.size()) == 0); - } + // Move to the next aggregate state + VectorOperations::AddInPlace(addresses, aggr.payload_size, result.size()); + } +} - // Does "this" end with "x"? - bool ends_with(const StringPiece& x) const { - return x.empty() || - (size() >= x.size() && - memcmp(data() + (size() - x.size()), x.data(), x.size()) == 0); - } +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/types/row_operations/row_external.cpp +// +// +//===----------------------------------------------------------------------===// - bool contains(const StringPiece& s) const { - return find(s) != npos; - } - size_type find(const StringPiece& s, size_type pos = 0) const; - size_type find(char c, size_type pos = 0) const; - size_type rfind(const StringPiece& s, size_type pos = npos) const; - size_type rfind(char c, size_type pos = npos) const; - private: - const_pointer data_; - size_type size_; -}; +namespace duckdb { -inline bool operator==(const StringPiece& x, const StringPiece& y) { - StringPiece::size_type len = x.size(); - if (len != y.size()) return false; - return x.data() == y.data() || len == 0 || - memcmp(x.data(), y.data(), len) == 0; +using ValidityBytes = RowLayout::ValidityBytes; + +void RowOperations::SwizzleColumns(const RowLayout &layout, const data_ptr_t base_row_ptr, const idx_t count) { + const idx_t row_width = layout.GetRowWidth(); + data_ptr_t heap_row_ptrs[STANDARD_VECTOR_SIZE]; + idx_t done = 0; + while (done != count) { + const idx_t next = MinValue(count - done, STANDARD_VECTOR_SIZE); + const data_ptr_t row_ptr = base_row_ptr + done * row_width; + // Load heap row pointers + data_ptr_t heap_ptr_ptr = row_ptr + layout.GetHeapOffset(); + for (idx_t i = 0; i < next; i++) { + heap_row_ptrs[i] = Load(heap_ptr_ptr); + heap_ptr_ptr += row_width; + } + // Loop through the blob columns + for (idx_t col_idx = 0; col_idx < layout.ColumnCount(); col_idx++) { + auto physical_type = layout.GetTypes()[col_idx].InternalType(); + if (TypeIsConstantSize(physical_type)) { + continue; + } + data_ptr_t col_ptr = row_ptr + layout.GetOffsets()[col_idx]; + if (physical_type == PhysicalType::VARCHAR) { + data_ptr_t string_ptr = col_ptr + sizeof(uint32_t) + string_t::PREFIX_LENGTH; + for (idx_t i = 0; i < next; i++) { + if (Load(col_ptr) > string_t::INLINE_LENGTH) { + // Overwrite the string pointer with the within-row offset (if not inlined) + Store(Load(string_ptr) - heap_row_ptrs[i], string_ptr); + } + col_ptr += row_width; + string_ptr += row_width; + } + } else { + // Non-varchar blob columns + for (idx_t i = 0; i < next; i++) { + // Overwrite the column data pointer with the within-row offset + Store(Load(col_ptr) - heap_row_ptrs[i], col_ptr); + col_ptr += row_width; + } + } + } + done += next; + } } -inline bool operator!=(const StringPiece& x, const StringPiece& y) { - return !(x == y); +void RowOperations::SwizzleHeapPointer(const RowLayout &layout, data_ptr_t row_ptr, const data_ptr_t heap_base_ptr, + const idx_t count, const idx_t base_offset) { + const idx_t row_width = layout.GetRowWidth(); + row_ptr += layout.GetHeapOffset(); + idx_t cumulative_offset = 0; + for (idx_t i = 0; i < count; i++) { + Store(base_offset + cumulative_offset, row_ptr); + cumulative_offset += Load(heap_base_ptr + cumulative_offset); + row_ptr += row_width; + } } -inline bool operator<(const StringPiece& x, const StringPiece& y) { - StringPiece::size_type min_size = std::min(x.size(), y.size()); - int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size); - return (r < 0) || (r == 0 && x.size() < y.size()); +void RowOperations::CopyHeapAndSwizzle(const RowLayout &layout, data_ptr_t row_ptr, const data_ptr_t heap_base_ptr, + data_ptr_t heap_ptr, const idx_t count) { + const auto row_width = layout.GetRowWidth(); + const auto heap_offset = layout.GetHeapOffset(); + for (idx_t i = 0; i < count; i++) { + // Figure out source and size + const auto source_heap_ptr = Load(row_ptr + heap_offset); + const auto size = Load(source_heap_ptr); + D_ASSERT(size >= sizeof(uint32_t)); + + // Copy and swizzle + memcpy(heap_ptr, source_heap_ptr, size); + Store(heap_ptr - heap_base_ptr, row_ptr + heap_offset); + + // Increment for next iteration + row_ptr += row_width; + heap_ptr += size; + } } -inline bool operator>(const StringPiece& x, const StringPiece& y) { - return y < x; +void RowOperations::UnswizzleHeapPointer(const RowLayout &layout, const data_ptr_t base_row_ptr, + const data_ptr_t base_heap_ptr, const idx_t count) { + const auto row_width = layout.GetRowWidth(); + data_ptr_t heap_ptr_ptr = base_row_ptr + layout.GetHeapOffset(); + for (idx_t i = 0; i < count; i++) { + Store(base_heap_ptr + Load(heap_ptr_ptr), heap_ptr_ptr); + heap_ptr_ptr += row_width; + } } -inline bool operator<=(const StringPiece& x, const StringPiece& y) { - return !(x > y); +static inline void VerifyUnswizzledString(const RowLayout &layout, const idx_t &col_idx, const data_ptr_t &row_ptr) { +#ifdef DEBUG + idx_t entry_idx; + idx_t idx_in_entry; + ValidityBytes::GetEntryIndex(col_idx, entry_idx, idx_in_entry); + + ValidityBytes row_mask(row_ptr); + if (row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry)) { + auto str = Load(row_ptr + layout.GetOffsets()[col_idx]); + str.Verify(); + } +#endif } -inline bool operator>=(const StringPiece& x, const StringPiece& y) { - return !(x < y); +void RowOperations::UnswizzlePointers(const RowLayout &layout, const data_ptr_t base_row_ptr, + const data_ptr_t base_heap_ptr, const idx_t count) { + const idx_t row_width = layout.GetRowWidth(); + data_ptr_t heap_row_ptrs[STANDARD_VECTOR_SIZE]; + idx_t done = 0; + while (done != count) { + const idx_t next = MinValue(count - done, STANDARD_VECTOR_SIZE); + const data_ptr_t row_ptr = base_row_ptr + done * row_width; + // Restore heap row pointers + data_ptr_t heap_ptr_ptr = row_ptr + layout.GetHeapOffset(); + for (idx_t i = 0; i < next; i++) { + heap_row_ptrs[i] = base_heap_ptr + Load(heap_ptr_ptr); + Store(heap_row_ptrs[i], heap_ptr_ptr); + heap_ptr_ptr += row_width; + } + // Loop through the blob columns + for (idx_t col_idx = 0; col_idx < layout.ColumnCount(); col_idx++) { + auto physical_type = layout.GetTypes()[col_idx].InternalType(); + if (TypeIsConstantSize(physical_type)) { + continue; + } + data_ptr_t col_ptr = row_ptr + layout.GetOffsets()[col_idx]; + if (physical_type == PhysicalType::VARCHAR) { + data_ptr_t string_ptr = col_ptr + sizeof(uint32_t) + string_t::PREFIX_LENGTH; + for (idx_t i = 0; i < next; i++) { + if (Load(col_ptr) > string_t::INLINE_LENGTH) { + // Overwrite the string offset with the pointer (if not inlined) + Store(heap_row_ptrs[i] + Load(string_ptr), string_ptr); + VerifyUnswizzledString(layout, col_idx, row_ptr + i * row_width); + } + col_ptr += row_width; + string_ptr += row_width; + } + } else { + // Non-varchar blob columns + for (idx_t i = 0; i < next; i++) { + // Overwrite the column data offset with the pointer + Store(heap_row_ptrs[i] + Load(col_ptr), col_ptr); + col_ptr += row_width; + } + } + } + done += next; + } } -// Allow StringPiece to be logged. -std::ostream& operator<<(std::ostream& o, const StringPiece& p); +} // namespace duckdb +//===--------------------------------------------------------------------===// +// row_gather.cpp +// Description: This file contains the implementation of the gather operators +//===--------------------------------------------------------------------===// -} // namespace duckdb_re2 -#endif // RE2_STRINGPIECE_H_ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/operator/constant_operators.hpp +// +// +//===----------------------------------------------------------------------===// -// LICENSE_CHANGE_END +namespace duckdb { -namespace duckdb_re2 { -class Prog; -class Regexp; -} // namespace duckdb_re2 +struct PickLeft { + template + static inline T Operation(T left, T right) { + return left; + } +}; -namespace duckdb_re2 { +struct PickRight { + template + static inline T Operation(T left, T right) { + return right; + } +}; -// Interface for regular expression matching. Also corresponds to a -// pre-compiled regular expression. An "RE2" object is safe for -// concurrent use by multiple threads. -class RE2 { - public: - // We convert user-passed pointers into special Arg objects - class Arg; - class Options; +struct NOP { + template + static inline T Operation(T left) { + return left; + } +}; - // Defined in set.h. - class Set; +struct ConstantZero { + template + static inline T Operation(T left, T right) { + return 0; + } +}; - enum ErrorCode { - NoError = 0, +struct ConstantOne { + template + static inline T Operation(T left, T right) { + return 1; + } +}; - // Unexpected error - ErrorInternal, +struct AddOne { + template + static inline T Operation(T left, T right) { + return right + 1; + } +}; - // Parse errors - ErrorBadEscape, // bad escape sequence - ErrorBadCharClass, // bad character class - ErrorBadCharRange, // bad character class range - ErrorMissingBracket, // missing closing ] - ErrorMissingParen, // missing closing ) - ErrorTrailingBackslash, // trailing \ at end of regexp - ErrorRepeatArgument, // repeat argument missing, e.g. "*" - ErrorRepeatSize, // bad repetition argument - ErrorRepeatOp, // bad repetition operator - ErrorBadPerlOp, // bad perl operator - ErrorBadUTF8, // invalid UTF-8 in regexp - ErrorBadNamedCapture, // bad named capture group - ErrorPatternTooLarge // pattern too large (compile failed) - }; +} // namespace duckdb - // Predefined common options. - // If you need more complicated things, instantiate - // an Option class, possibly passing one of these to - // the Option constructor, change the settings, and pass that - // Option class to the RE2 constructor. - enum CannedOptions { - DefaultOptions = 0, - Latin1, // treat input as Latin-1 (default UTF-8) - POSIX, // POSIX syntax, leftmost-longest match - Quiet // do not log about regexp parse errors - }; - // Need to have the const char* and const std::string& forms for implicit - // conversions when passing string literals to FullMatch and PartialMatch. - // Otherwise the StringPiece form would be sufficient. -#ifndef SWIG - RE2(const char* pattern); - RE2(const std::string& pattern); -#endif - RE2(const StringPiece& pattern); - RE2(const StringPiece& pattern, const Options& options); - ~RE2(); - // Returns whether RE2 was created properly. - bool ok() const { return error_code() == NoError; } - // The string specification for this RE2. E.g. - // RE2 re("ab*c?d+"); - // re.pattern(); // "ab*c?d+" - const std::string& pattern() const { return pattern_; } - // If RE2 could not be created properly, returns an error string. - // Else returns the empty string. - const std::string& error() const { return *error_; } +namespace duckdb { - // If RE2 could not be created properly, returns an error code. - // Else returns RE2::NoError (== 0). - ErrorCode error_code() const { return error_code_; } +using ValidityBytes = RowLayout::ValidityBytes; - // If RE2 could not be created properly, returns the offending - // portion of the regexp. - const std::string& error_arg() const { return error_arg_; } +template +static void TemplatedGatherLoop(Vector &rows, const SelectionVector &row_sel, Vector &col, + const SelectionVector &col_sel, idx_t count, const RowLayout &layout, idx_t col_no, + idx_t build_size) { + // Precompute mask indexes + const auto &offsets = layout.GetOffsets(); + const auto col_offset = offsets[col_no]; + idx_t entry_idx; + idx_t idx_in_entry; + ValidityBytes::GetEntryIndex(col_no, entry_idx, idx_in_entry); - // Returns the program size, a very approximate measure of a regexp's "cost". - // Larger numbers are more expensive than smaller numbers. - int ProgramSize() const; - int ReverseProgramSize() const; + auto ptrs = FlatVector::GetData(rows); + auto data = FlatVector::GetData(col); + auto &col_mask = FlatVector::Validity(col); - // EXPERIMENTAL! SUBJECT TO CHANGE! - // Outputs the program fanout as a histogram bucketed by powers of 2. - // Returns the number of the largest non-empty bucket. - int ProgramFanout(std::map* histogram) const; - int ReverseProgramFanout(std::map* histogram) const; + for (idx_t i = 0; i < count; i++) { + auto row_idx = row_sel.get_index(i); + auto row = ptrs[row_idx]; + auto col_idx = col_sel.get_index(i); + data[col_idx] = Load(row + col_offset); + ValidityBytes row_mask(row); + if (!row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry)) { + if (build_size > STANDARD_VECTOR_SIZE && col_mask.AllValid()) { + //! We need to initialize the mask with the vector size. + col_mask.Initialize(build_size); + } + col_mask.SetInvalid(col_idx); + } + } +} - // Returns the underlying Regexp; not for general use. - // Returns entire_regexp_ so that callers don't need - // to know about prefix_ and prefix_foldcase_. - duckdb_re2::Regexp* Regexp() const { return entire_regexp_; } +static void GatherVarchar(Vector &rows, const SelectionVector &row_sel, Vector &col, const SelectionVector &col_sel, + idx_t count, const RowLayout &layout, idx_t col_no, idx_t build_size, + data_ptr_t base_heap_ptr) { + // Precompute mask indexes + const auto &offsets = layout.GetOffsets(); + const auto col_offset = offsets[col_no]; + const auto heap_offset = layout.GetHeapOffset(); + idx_t entry_idx; + idx_t idx_in_entry; + ValidityBytes::GetEntryIndex(col_no, entry_idx, idx_in_entry); - /***** The array-based matching interface ******/ + auto ptrs = FlatVector::GetData(rows); + auto data = FlatVector::GetData(col); + auto &col_mask = FlatVector::Validity(col); - // The functions here have names ending in 'N' and are used to implement - // the functions whose names are the prefix before the 'N'. It is sometimes - // useful to invoke them directly, but the syntax is awkward, so the 'N'-less - // versions should be preferred. - static bool FullMatchN(const StringPiece& text, const RE2& re, - const Arg* const args[], int n); - static bool PartialMatchN(const StringPiece& text, const RE2& re, - const Arg* const args[], int n); - static bool ConsumeN(StringPiece* input, const RE2& re, - const Arg* const args[], int n); - static bool FindAndConsumeN(StringPiece* input, const RE2& re, - const Arg* const args[], int n); + for (idx_t i = 0; i < count; i++) { + auto row_idx = row_sel.get_index(i); + auto row = ptrs[row_idx]; + auto col_idx = col_sel.get_index(i); + auto col_ptr = row + col_offset; + data[col_idx] = Load(col_ptr); + ValidityBytes row_mask(row); + if (!row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry)) { + if (build_size > STANDARD_VECTOR_SIZE && col_mask.AllValid()) { + //! We need to initialize the mask with the vector size. + col_mask.Initialize(build_size); + } + col_mask.SetInvalid(col_idx); + } else if (base_heap_ptr && Load(col_ptr) > string_t::INLINE_LENGTH) { + // Not inline, so unswizzle the copied pointer the pointer + auto heap_ptr_ptr = row + heap_offset; + auto heap_row_ptr = base_heap_ptr + Load(heap_ptr_ptr); + auto string_ptr = data_ptr_t(data + col_idx) + sizeof(uint32_t) + string_t::PREFIX_LENGTH; + Store(heap_row_ptr + Load(string_ptr), string_ptr); +#ifdef DEBUG + data[col_idx].Verify(); +#endif + } + } +} -#ifndef SWIG - private: - template - static inline bool Apply(F f, SP sp, const RE2& re) { - return f(sp, re, NULL, 0); - } +static void GatherNestedVector(Vector &rows, const SelectionVector &row_sel, Vector &col, + const SelectionVector &col_sel, idx_t count, const RowLayout &layout, idx_t col_no, + data_ptr_t base_heap_ptr) { + const auto &offsets = layout.GetOffsets(); + const auto col_offset = offsets[col_no]; + const auto heap_offset = layout.GetHeapOffset(); + auto ptrs = FlatVector::GetData(rows); - template - static inline bool Apply(F f, SP sp, const RE2& re, const A&... a) { - const Arg* const args[] = {&a...}; - const int n = sizeof...(a); - return f(sp, re, args, n); - } + // Build the gather locations + auto data_locations = unique_ptr(new data_ptr_t[count]); + auto mask_locations = unique_ptr(new data_ptr_t[count]); + for (idx_t i = 0; i < count; i++) { + auto row_idx = row_sel.get_index(i); + auto row = ptrs[row_idx]; + mask_locations[i] = row; + auto col_ptr = ptrs[row_idx] + col_offset; + if (base_heap_ptr) { + auto heap_ptr_ptr = row + heap_offset; + auto heap_row_ptr = base_heap_ptr + Load(heap_ptr_ptr); + data_locations[i] = heap_row_ptr + Load(col_ptr); + } else { + data_locations[i] = Load(col_ptr); + } + } - public: - // In order to allow FullMatch() et al. to be called with a varying number - // of arguments of varying types, we use two layers of variadic templates. - // The first layer constructs the temporary Arg objects. The second layer - // (above) constructs the array of pointers to the temporary Arg objects. + // Deserialise into the selected locations + RowOperations::HeapGather(col, count, col_sel, col_no, data_locations.get(), mask_locations.get()); +} - /***** The useful part: the matching interface *****/ +void RowOperations::Gather(Vector &rows, const SelectionVector &row_sel, Vector &col, const SelectionVector &col_sel, + const idx_t count, const RowLayout &layout, const idx_t col_no, const idx_t build_size, + data_ptr_t heap_ptr) { + D_ASSERT(rows.GetVectorType() == VectorType::FLAT_VECTOR); + D_ASSERT(rows.GetType().id() == LogicalTypeId::POINTER); // "Cannot gather from non-pointer type!" - // Matches "text" against "re". If pointer arguments are - // supplied, copies matched sub-patterns into them. - // - // You can pass in a "const char*" or a "std::string" for "text". - // You can pass in a "const char*" or a "std::string" or a "RE2" for "re". - // - // The provided pointer arguments can be pointers to any scalar numeric - // type, or one of: - // std::string (matched piece is copied to string) - // StringPiece (StringPiece is mutated to point to matched piece) - // T (where "bool T::ParseFrom(const char*, size_t)" exists) - // (void*)NULL (the corresponding matched sub-pattern is not copied) - // - // Returns true iff all of the following conditions are satisfied: - // a. "text" matches "re" exactly - // b. The number of matched sub-patterns is >= number of supplied pointers - // c. The "i"th argument has a suitable type for holding the - // string captured as the "i"th sub-pattern. If you pass in - // NULL for the "i"th argument, or pass fewer arguments than - // number of sub-patterns, "i"th captured sub-pattern is - // ignored. - // - // CAVEAT: An optional sub-pattern that does not exist in the - // matched string is assigned the empty string. Therefore, the - // following will return false (because the empty string is not a - // valid number): - // int number; - // RE2::FullMatch("abc", "[a-z]+(\\d+)?", &number); - template - static bool FullMatch(const StringPiece& text, const RE2& re, A&&... a) { - return Apply(FullMatchN, text, re, Arg(std::forward(a))...); - } + col.SetVectorType(VectorType::FLAT_VECTOR); + switch (col.GetType().InternalType()) { + case PhysicalType::UINT8: + TemplatedGatherLoop(rows, row_sel, col, col_sel, count, layout, col_no, build_size); + break; + case PhysicalType::UINT16: + TemplatedGatherLoop(rows, row_sel, col, col_sel, count, layout, col_no, build_size); + break; + case PhysicalType::UINT32: + TemplatedGatherLoop(rows, row_sel, col, col_sel, count, layout, col_no, build_size); + break; + case PhysicalType::UINT64: + TemplatedGatherLoop(rows, row_sel, col, col_sel, count, layout, col_no, build_size); + break; + case PhysicalType::BOOL: + case PhysicalType::INT8: + TemplatedGatherLoop(rows, row_sel, col, col_sel, count, layout, col_no, build_size); + break; + case PhysicalType::INT16: + TemplatedGatherLoop(rows, row_sel, col, col_sel, count, layout, col_no, build_size); + break; + case PhysicalType::INT32: + TemplatedGatherLoop(rows, row_sel, col, col_sel, count, layout, col_no, build_size); + break; + case PhysicalType::INT64: + TemplatedGatherLoop(rows, row_sel, col, col_sel, count, layout, col_no, build_size); + break; + case PhysicalType::INT128: + TemplatedGatherLoop(rows, row_sel, col, col_sel, count, layout, col_no, build_size); + break; + case PhysicalType::FLOAT: + TemplatedGatherLoop(rows, row_sel, col, col_sel, count, layout, col_no, build_size); + break; + case PhysicalType::DOUBLE: + TemplatedGatherLoop(rows, row_sel, col, col_sel, count, layout, col_no, build_size); + break; + case PhysicalType::INTERVAL: + TemplatedGatherLoop(rows, row_sel, col, col_sel, count, layout, col_no, build_size); + break; + case PhysicalType::VARCHAR: + GatherVarchar(rows, row_sel, col, col_sel, count, layout, col_no, build_size, heap_ptr); + break; + case PhysicalType::LIST: + case PhysicalType::MAP: + case PhysicalType::STRUCT: + GatherNestedVector(rows, row_sel, col, col_sel, count, layout, col_no, heap_ptr); + break; + default: + throw InternalException("Unimplemented type for RowOperations::Gather"); + } +} - // Exactly like FullMatch(), except that "re" is allowed to match - // a substring of "text". - template - static bool PartialMatch(const StringPiece& text, const RE2& re, A&&... a) { - return Apply(PartialMatchN, text, re, Arg(std::forward(a))...); - } +template +static void TemplatedFullScanLoop(Vector &rows, Vector &col, idx_t count, idx_t col_offset, idx_t col_no) { + // Precompute mask indexes + idx_t entry_idx; + idx_t idx_in_entry; + ValidityBytes::GetEntryIndex(col_no, entry_idx, idx_in_entry); - // Like FullMatch() and PartialMatch(), except that "re" has to match - // a prefix of the text, and "input" is advanced past the matched - // text. Note: "input" is modified iff this routine returns true - // and "re" matched a non-empty substring of "text". - template - static bool Consume(StringPiece* input, const RE2& re, A&&... a) { - return Apply(ConsumeN, input, re, Arg(std::forward(a))...); - } + auto ptrs = FlatVector::GetData(rows); + auto data = FlatVector::GetData(col); + // auto &col_mask = FlatVector::Validity(col); - // Like Consume(), but does not anchor the match at the beginning of - // the text. That is, "re" need not start its match at the beginning - // of "input". For example, "FindAndConsume(s, "(\\w+)", &word)" finds - // the next word in "s" and stores it in "word". - template - static bool FindAndConsume(StringPiece* input, const RE2& re, A&&... a) { - return Apply(FindAndConsumeN, input, re, Arg(std::forward(a))...); - } -#endif + for (idx_t i = 0; i < count; i++) { + auto row = ptrs[i]; + data[i] = Load(row + col_offset); + ValidityBytes row_mask(row); + if (!row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry)) { + throw InternalException("Null value comparisons not implemented for perfect hash table yet"); + // col_mask.SetInvalid(i); + } + } +} - // Replace the first match of "re" in "str" with "rewrite". - // Within "rewrite", backslash-escaped digits (\1 to \9) can be - // used to insert text matching corresponding parenthesized group - // from the pattern. \0 in "rewrite" refers to the entire matching - // text. E.g., - // - // std::string s = "yabba dabba doo"; - // CHECK(RE2::Replace(&s, "b+", "d")); - // - // will leave "s" containing "yada dabba doo" - // - // Returns true if the pattern matches and a replacement occurs, - // false otherwise. - static bool Replace(std::string* str, - const RE2& re, - const StringPiece& rewrite); +void RowOperations::FullScanColumn(const RowLayout &layout, Vector &rows, Vector &col, idx_t count, idx_t col_no) { + const auto col_offset = layout.GetOffsets()[col_no]; + col.SetVectorType(VectorType::FLAT_VECTOR); + switch (col.GetType().InternalType()) { + case PhysicalType::UINT8: + TemplatedFullScanLoop(rows, col, count, col_offset, col_no); + break; + case PhysicalType::UINT16: + TemplatedFullScanLoop(rows, col, count, col_offset, col_no); + break; + case PhysicalType::UINT32: + TemplatedFullScanLoop(rows, col, count, col_offset, col_no); + break; + case PhysicalType::UINT64: + TemplatedFullScanLoop(rows, col, count, col_offset, col_no); + break; + case PhysicalType::INT8: + TemplatedFullScanLoop(rows, col, count, col_offset, col_no); + break; + case PhysicalType::INT16: + TemplatedFullScanLoop(rows, col, count, col_offset, col_no); + break; + case PhysicalType::INT32: + TemplatedFullScanLoop(rows, col, count, col_offset, col_no); + break; + case PhysicalType::INT64: + TemplatedFullScanLoop(rows, col, count, col_offset, col_no); + break; + default: + throw NotImplementedException("Unimplemented type for RowOperations::FullScanColumn"); + } +} - // Like Replace(), except replaces successive non-overlapping occurrences - // of the pattern in the string with the rewrite. E.g. - // - // std::string s = "yabba dabba doo"; - // CHECK(RE2::GlobalReplace(&s, "b+", "d")); - // - // will leave "s" containing "yada dada doo" - // Replacements are not subject to re-matching. - // - // Because GlobalReplace only replaces non-overlapping matches, - // replacing "ana" within "banana" makes only one replacement, not two. - // - // Returns the number of replacements made. - static int GlobalReplace(std::string* str, - const RE2& re, - const StringPiece& rewrite); +} // namespace duckdb - // Like Replace, except that if the pattern matches, "rewrite" - // is copied into "out" with substitutions. The non-matching - // portions of "text" are ignored. - // - // Returns true iff a match occurred and the extraction happened - // successfully; if no match occurs, the string is left unaffected. - // - // REQUIRES: "text" must not alias any part of "*out". - static bool Extract(const StringPiece& text, - const RE2& re, - const StringPiece& rewrite, - std::string* out); - // Escapes all potentially meaningful regexp characters in - // 'unquoted'. The returned string, used as a regular expression, - // will exactly match the original string. For example, - // 1.5-2.0? - // may become: - // 1\.5\-2\.0\? - static std::string QuoteMeta(const StringPiece& unquoted); - - // Computes range for any strings matching regexp. The min and max can in - // some cases be arbitrarily precise, so the caller gets to specify the - // maximum desired length of string returned. - // - // Assuming PossibleMatchRange(&min, &max, N) returns successfully, any - // string s that is an anchored match for this regexp satisfies - // min <= s && s <= max. - // - // Note that PossibleMatchRange() will only consider the first copy of an - // infinitely repeated element (i.e., any regexp element followed by a '*' or - // '+' operator). Regexps with "{N}" constructions are not affected, as those - // do not compile down to infinite repetitions. - // - // Returns true on success, false on error. - bool PossibleMatchRange(std::string* min, std::string* max, - int maxlen) const; - - // Generic matching interface - - // Type of match. - enum Anchor { - UNANCHORED, // No anchoring - ANCHOR_START, // Anchor at start only - ANCHOR_BOTH // Anchor at start and end - }; - - // Return the number of capturing subpatterns, or -1 if the - // regexp wasn't valid on construction. The overall match ($0) - // does not count: if the regexp is "(a)(b)", returns 2. - int NumberOfCapturingGroups() const { return num_captures_; } - - // Return a map from names to capturing indices. - // The map records the index of the leftmost group - // with the given name. - // Only valid until the re is deleted. - const std::map& NamedCapturingGroups() const; - - // Return a map from capturing indices to names. - // The map has no entries for unnamed groups. - // Only valid until the re is deleted. - const std::map& CapturingGroupNames() const; - - // General matching routine. - // Match against text starting at offset startpos - // and stopping the search at offset endpos. - // Returns true if match found, false if not. - // On a successful match, fills in submatch[] (up to nsubmatch entries) - // with information about submatches. - // I.e. matching RE2("(foo)|(bar)baz") on "barbazbla" will return true, with - // submatch[0] = "barbaz", submatch[1].data() = NULL, submatch[2] = "bar", - // submatch[3].data() = NULL, ..., up to submatch[nsubmatch-1].data() = NULL. - // Caveat: submatch[] may be clobbered even on match failure. - // - // Don't ask for more match information than you will use: - // runs much faster with nsubmatch == 1 than nsubmatch > 1, and - // runs even faster if nsubmatch == 0. - // Doesn't make sense to use nsubmatch > 1 + NumberOfCapturingGroups(), - // but will be handled correctly. - // - // Passing text == StringPiece(NULL, 0) will be handled like any other - // empty string, but note that on return, it will not be possible to tell - // whether submatch i matched the empty string or did not match: - // either way, submatch[i].data() == NULL. - bool Match(const StringPiece& text, - size_t startpos, - size_t endpos, - Anchor re_anchor, - StringPiece* submatch, - int nsubmatch) const; - - // Check that the given rewrite string is suitable for use with this - // regular expression. It checks that: - // * The regular expression has enough parenthesized subexpressions - // to satisfy all of the \N tokens in rewrite - // * The rewrite string doesn't have any syntax errors. E.g., - // '\' followed by anything other than a digit or '\'. - // A true return value guarantees that Replace() and Extract() won't - // fail because of a bad rewrite string. - bool CheckRewriteString(const StringPiece& rewrite, - std::string* error) const; - // Returns the maximum submatch needed for the rewrite to be done by - // Replace(). E.g. if rewrite == "foo \\2,\\1", returns 2. - static int MaxSubmatch(const StringPiece& rewrite); - // Append the "rewrite" string, with backslash subsitutions from "vec", - // to string "out". - // Returns true on success. This method can fail because of a malformed - // rewrite string. CheckRewriteString guarantees that the rewrite will - // be sucessful. - bool Rewrite(std::string* out, - const StringPiece& rewrite, - const StringPiece* vec, - int veclen) const; +namespace duckdb { - // Constructor options - class Options { - public: - // The options are (defaults in parentheses): - // - // utf8 (true) text and pattern are UTF-8; otherwise Latin-1 - // posix_syntax (false) restrict regexps to POSIX egrep syntax - // longest_match (false) search for longest match, not first match - // log_errors (true) log syntax and execution errors to ERROR - // max_mem (see below) approx. max memory footprint of RE2 - // literal (false) interpret string as literal, not regexp - // never_nl (false) never match \n, even if it is in regexp - // dot_nl (false) dot matches everything including new line - // never_capture (false) parse all parens as non-capturing - // case_sensitive (true) match is case-sensitive (regexp can override - // with (?i) unless in posix_syntax mode) - // - // The following options are only consulted when posix_syntax == true. - // When posix_syntax == false, these features are always enabled and - // cannot be turned off; to perform multi-line matching in that case, - // begin the regexp with (?m). - // perl_classes (false) allow Perl's \d \s \w \D \S \W - // word_boundary (false) allow Perl's \b \B (word boundary and not) - // one_line (false) ^ and $ only match beginning and end of text - // - // The max_mem option controls how much memory can be used - // to hold the compiled form of the regexp (the Prog) and - // its cached DFA graphs. Code Search placed limits on the number - // of Prog instructions and DFA states: 10,000 for both. - // In RE2, those limits would translate to about 240 KB per Prog - // and perhaps 2.5 MB per DFA (DFA state sizes vary by regexp; RE2 does a - // better job of keeping them small than Code Search did). - // Each RE2 has two Progs (one forward, one reverse), and each Prog - // can have two DFAs (one first match, one longest match). - // That makes 4 DFAs: - // - // forward, first-match - used for UNANCHORED or ANCHOR_START searches - // if opt.longest_match() == false - // forward, longest-match - used for all ANCHOR_BOTH searches, - // and the other two kinds if - // opt.longest_match() == true - // reverse, first-match - never used - // reverse, longest-match - used as second phase for unanchored searches - // - // The RE2 memory budget is statically divided between the two - // Progs and then the DFAs: two thirds to the forward Prog - // and one third to the reverse Prog. The forward Prog gives half - // of what it has left over to each of its DFAs. The reverse Prog - // gives it all to its longest-match DFA. - // - // Once a DFA fills its budget, it flushes its cache and starts over. - // If this happens too often, RE2 falls back on the NFA implementation. +using ValidityBytes = TemplatedValidityMask; - // For now, make the default budget something close to Code Search. - static const int kDefaultMaxMem = 8<<20; +template +static void TemplatedHeapGather(Vector &v, const idx_t count, const SelectionVector &sel, data_ptr_t *key_locations) { + auto target = FlatVector::GetData(v); - enum Encoding { - EncodingUTF8 = 1, - EncodingLatin1 - }; + for (idx_t i = 0; i < count; ++i) { + const auto col_idx = sel.get_index(i); + target[col_idx] = Load(key_locations[i]); + key_locations[i] += sizeof(T); + } +} - Options() : - encoding_(EncodingUTF8), - posix_syntax_(false), - longest_match_(false), - log_errors_(true), - max_mem_(kDefaultMaxMem), - literal_(false), - never_nl_(false), - dot_nl_(false), - never_capture_(false), - case_sensitive_(true), - perl_classes_(false), - word_boundary_(false), - one_line_(false) { - } +static void HeapGatherStringVector(Vector &v, const idx_t vcount, const SelectionVector &sel, + data_ptr_t *key_locations) { + const auto &validity = FlatVector::Validity(v); + auto target = FlatVector::GetData(v); - /*implicit*/ Options(CannedOptions); + for (idx_t i = 0; i < vcount; i++) { + const auto col_idx = sel.get_index(i); + if (!validity.RowIsValid(col_idx)) { + continue; + } + auto len = Load(key_locations[i]); + key_locations[i] += sizeof(uint32_t); + target[col_idx] = StringVector::AddStringOrBlob(v, string_t((const char *)key_locations[i], len)); + key_locations[i] += len; + } +} - Encoding encoding() const { return encoding_; } - void set_encoding(Encoding encoding) { encoding_ = encoding; } +static void HeapGatherStructVector(Vector &v, const idx_t vcount, const SelectionVector &sel, + data_ptr_t *key_locations) { + // struct must have a validitymask for its fields + auto &child_types = StructType::GetChildTypes(v.GetType()); + const idx_t struct_validitymask_size = (child_types.size() + 7) / 8; + data_ptr_t struct_validitymask_locations[STANDARD_VECTOR_SIZE]; + for (idx_t i = 0; i < vcount; i++) { + // use key_locations as the validitymask, and create struct_key_locations + struct_validitymask_locations[i] = key_locations[i]; + key_locations[i] += struct_validitymask_size; + } - // Legacy interface to encoding. - // TODO(rsc): Remove once clients have been converted. - bool utf8() const { return encoding_ == EncodingUTF8; } - void set_utf8(bool b) { - if (b) { - encoding_ = EncodingUTF8; - } else { - encoding_ = EncodingLatin1; - } - } + // now deserialize into the struct vectors + auto &children = StructVector::GetEntries(v); + for (idx_t i = 0; i < child_types.size(); i++) { + RowOperations::HeapGather(*children[i], vcount, sel, i, key_locations, struct_validitymask_locations); + } +} - bool posix_syntax() const { return posix_syntax_; } - void set_posix_syntax(bool b) { posix_syntax_ = b; } +static void HeapGatherListVector(Vector &v, const idx_t vcount, const SelectionVector &sel, data_ptr_t *key_locations) { + const auto &validity = FlatVector::Validity(v); - bool longest_match() const { return longest_match_; } - void set_longest_match(bool b) { longest_match_ = b; } + auto child_type = ListType::GetChildType(v.GetType()); + auto list_data = ListVector::GetData(v); + data_ptr_t list_entry_locations[STANDARD_VECTOR_SIZE]; - bool log_errors() const { return log_errors_; } - void set_log_errors(bool b) { log_errors_ = b; } + uint64_t entry_offset = ListVector::GetListSize(v); + for (idx_t i = 0; i < vcount; i++) { + const auto col_idx = sel.get_index(i); + if (!validity.RowIsValid(col_idx)) { + continue; + } + // read list length + auto entry_remaining = Load(key_locations[i]); + key_locations[i] += sizeof(uint64_t); + // set list entry attributes + list_data[col_idx].length = entry_remaining; + list_data[col_idx].offset = entry_offset; + // skip over the validity mask + data_ptr_t validitymask_location = key_locations[i]; + idx_t offset_in_byte = 0; + key_locations[i] += (entry_remaining + 7) / 8; + // entry sizes + data_ptr_t var_entry_size_ptr = nullptr; + if (!TypeIsConstantSize(child_type.InternalType())) { + var_entry_size_ptr = key_locations[i]; + key_locations[i] += entry_remaining * sizeof(idx_t); + } - int64_t max_mem() const { return max_mem_; } - void set_max_mem(int64_t m) { max_mem_ = m; } + // now read the list data + while (entry_remaining > 0) { + auto next = MinValue(entry_remaining, (idx_t)STANDARD_VECTOR_SIZE); - bool literal() const { return literal_; } - void set_literal(bool b) { literal_ = b; } + // initialize a new vector to append + Vector append_vector(v.GetType()); + append_vector.SetVectorType(v.GetVectorType()); - bool never_nl() const { return never_nl_; } - void set_never_nl(bool b) { never_nl_ = b; } + auto &list_vec_to_append = ListVector::GetEntry(append_vector); - bool dot_nl() const { return dot_nl_; } - void set_dot_nl(bool b) { dot_nl_ = b; } + // set validity + //! Since we are constructing the vector, this will always be a flat vector. + auto &append_validity = FlatVector::Validity(list_vec_to_append); + for (idx_t entry_idx = 0; entry_idx < next; entry_idx++) { + append_validity.Set(entry_idx, *(validitymask_location) & (1 << offset_in_byte)); + if (++offset_in_byte == 8) { + validitymask_location++; + offset_in_byte = 0; + } + } - bool never_capture() const { return never_capture_; } - void set_never_capture(bool b) { never_capture_ = b; } + // compute entry sizes and set locations where the list entries are + if (TypeIsConstantSize(child_type.InternalType())) { + // constant size list entries + const idx_t type_size = GetTypeIdSize(child_type.InternalType()); + for (idx_t entry_idx = 0; entry_idx < next; entry_idx++) { + list_entry_locations[entry_idx] = key_locations[i]; + key_locations[i] += type_size; + } + } else { + // variable size list entries + for (idx_t entry_idx = 0; entry_idx < next; entry_idx++) { + list_entry_locations[entry_idx] = key_locations[i]; + key_locations[i] += Load(var_entry_size_ptr); + var_entry_size_ptr += sizeof(idx_t); + } + } - bool case_sensitive() const { return case_sensitive_; } - void set_case_sensitive(bool b) { case_sensitive_ = b; } + // now deserialize and add to listvector + RowOperations::HeapGather(list_vec_to_append, next, *FlatVector::IncrementalSelectionVector(), 0, + list_entry_locations, nullptr); + ListVector::Append(v, list_vec_to_append, next); - bool perl_classes() const { return perl_classes_; } - void set_perl_classes(bool b) { perl_classes_ = b; } + // update for next iteration + entry_remaining -= next; + entry_offset += next; + } + } +} - bool word_boundary() const { return word_boundary_; } - void set_word_boundary(bool b) { word_boundary_ = b; } +void RowOperations::HeapGather(Vector &v, const idx_t &vcount, const SelectionVector &sel, const idx_t &col_no, + data_ptr_t *key_locations, data_ptr_t *validitymask_locations) { + v.SetVectorType(VectorType::FLAT_VECTOR); - bool one_line() const { return one_line_; } - void set_one_line(bool b) { one_line_ = b; } + auto &validity = FlatVector::Validity(v); + if (validitymask_locations) { + // Precompute mask indexes + idx_t entry_idx; + idx_t idx_in_entry; + ValidityBytes::GetEntryIndex(col_no, entry_idx, idx_in_entry); - void Copy(const Options& src) { - *this = src; - } + for (idx_t i = 0; i < vcount; i++) { + ValidityBytes row_mask(validitymask_locations[i]); + const auto valid = row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry); + const auto col_idx = sel.get_index(i); + validity.Set(col_idx, valid); + } + } - int ParseFlags() const; + auto type = v.GetType().InternalType(); + switch (type) { + case PhysicalType::BOOL: + case PhysicalType::INT8: + TemplatedHeapGather(v, vcount, sel, key_locations); + break; + case PhysicalType::INT16: + TemplatedHeapGather(v, vcount, sel, key_locations); + break; + case PhysicalType::INT32: + TemplatedHeapGather(v, vcount, sel, key_locations); + break; + case PhysicalType::INT64: + TemplatedHeapGather(v, vcount, sel, key_locations); + break; + case PhysicalType::UINT8: + TemplatedHeapGather(v, vcount, sel, key_locations); + break; + case PhysicalType::UINT16: + TemplatedHeapGather(v, vcount, sel, key_locations); + break; + case PhysicalType::UINT32: + TemplatedHeapGather(v, vcount, sel, key_locations); + break; + case PhysicalType::UINT64: + TemplatedHeapGather(v, vcount, sel, key_locations); + break; + case PhysicalType::INT128: + TemplatedHeapGather(v, vcount, sel, key_locations); + break; + case PhysicalType::FLOAT: + TemplatedHeapGather(v, vcount, sel, key_locations); + break; + case PhysicalType::DOUBLE: + TemplatedHeapGather(v, vcount, sel, key_locations); + break; + case PhysicalType::INTERVAL: + TemplatedHeapGather(v, vcount, sel, key_locations); + break; + case PhysicalType::VARCHAR: + HeapGatherStringVector(v, vcount, sel, key_locations); + break; + case PhysicalType::STRUCT: + HeapGatherStructVector(v, vcount, sel, key_locations); + break; + case PhysicalType::LIST: + HeapGatherListVector(v, vcount, sel, key_locations); + break; + default: + throw NotImplementedException("Unimplemented deserialize from row-format"); + } +} - private: - Encoding encoding_; - bool posix_syntax_; - bool longest_match_; - bool log_errors_; - int64_t max_mem_; - bool literal_; - bool never_nl_; - bool dot_nl_; - bool never_capture_; - bool case_sensitive_; - bool perl_classes_; - bool word_boundary_; - bool one_line_; - }; +} // namespace duckdb - // Returns the options set in the constructor. - const Options& options() const { return options_; } - // Argument converters; see below. - static inline Arg CRadix(short* x); - static inline Arg CRadix(unsigned short* x); - static inline Arg CRadix(int* x); - static inline Arg CRadix(unsigned int* x); - static inline Arg CRadix(long* x); - static inline Arg CRadix(unsigned long* x); - static inline Arg CRadix(long long* x); - static inline Arg CRadix(unsigned long long* x); - static inline Arg Hex(short* x); - static inline Arg Hex(unsigned short* x); - static inline Arg Hex(int* x); - static inline Arg Hex(unsigned int* x); - static inline Arg Hex(long* x); - static inline Arg Hex(unsigned long* x); - static inline Arg Hex(long long* x); - static inline Arg Hex(unsigned long long* x); - static inline Arg Octal(short* x); - static inline Arg Octal(unsigned short* x); - static inline Arg Octal(int* x); - static inline Arg Octal(unsigned int* x); - static inline Arg Octal(long* x); - static inline Arg Octal(unsigned long* x); - static inline Arg Octal(long long* x); - static inline Arg Octal(unsigned long long* x); +namespace duckdb { - private: - void Init(const StringPiece& pattern, const Options& options); +using ValidityBytes = TemplatedValidityMask; - bool DoMatch(const StringPiece& text, - Anchor re_anchor, - size_t* consumed, - const Arg* const args[], - int n) const; +static void ComputeStringEntrySizes(UnifiedVectorFormat &vdata, idx_t entry_sizes[], const idx_t ser_count, + const SelectionVector &sel, const idx_t offset) { + auto strings = (string_t *)vdata.data; + for (idx_t i = 0; i < ser_count; i++) { + auto idx = sel.get_index(i); + auto str_idx = vdata.sel->get_index(idx) + offset; + if (vdata.validity.RowIsValid(str_idx)) { + entry_sizes[i] += sizeof(uint32_t) + strings[str_idx].GetSize(); + } + } +} - duckdb_re2::Prog* ReverseProg() const; +static void ComputeStructEntrySizes(Vector &v, idx_t entry_sizes[], idx_t vcount, idx_t ser_count, + const SelectionVector &sel, idx_t offset) { + // obtain child vectors + idx_t num_children; + auto &children = StructVector::GetEntries(v); + num_children = children.size(); + // add struct validitymask size + const idx_t struct_validitymask_size = (num_children + 7) / 8; + for (idx_t i = 0; i < ser_count; i++) { + entry_sizes[i] += struct_validitymask_size; + } + // compute size of child vectors + for (auto &struct_vector : children) { + RowOperations::ComputeEntrySizes(*struct_vector, entry_sizes, vcount, ser_count, sel, offset); + } +} - std::string pattern_; // string regular expression - Options options_; // option flags - std::string prefix_; // required prefix (before regexp_) - bool prefix_foldcase_; // prefix is ASCII case-insensitive - duckdb_re2::Regexp* entire_regexp_; // parsed regular expression - duckdb_re2::Regexp* suffix_regexp_; // parsed regular expression, prefix removed - duckdb_re2::Prog* prog_; // compiled program for regexp - int num_captures_; // Number of capturing groups - bool is_one_pass_; // can use prog_->SearchOnePass? +static void ComputeListEntrySizes(Vector &v, UnifiedVectorFormat &vdata, idx_t entry_sizes[], idx_t ser_count, + const SelectionVector &sel, idx_t offset) { + auto list_data = ListVector::GetData(v); + auto &child_vector = ListVector::GetEntry(v); + idx_t list_entry_sizes[STANDARD_VECTOR_SIZE]; + for (idx_t i = 0; i < ser_count; i++) { + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; + if (vdata.validity.RowIsValid(source_idx)) { + auto list_entry = list_data[source_idx]; - mutable duckdb_re2::Prog* rprog_; // reverse program for regexp - mutable const std::string* error_; // Error indicator - // (or points to empty string) - mutable ErrorCode error_code_; // Error code - mutable std::string error_arg_; // Fragment of regexp showing error + // make room for list length, list validitymask + entry_sizes[i] += sizeof(list_entry.length); + entry_sizes[i] += (list_entry.length + 7) / 8; - // Map from capture names to indices - mutable const std::map* named_groups_; + // serialize size of each entry (if non-constant size) + if (!TypeIsConstantSize(ListType::GetChildType(v.GetType()).InternalType())) { + entry_sizes[i] += list_entry.length * sizeof(list_entry.length); + } - // Map from capture indices to names - mutable const std::map* group_names_; + // compute size of each the elements in list_entry and sum them + auto entry_remaining = list_entry.length; + auto entry_offset = list_entry.offset; + while (entry_remaining > 0) { + // the list entry can span multiple vectors + auto next = MinValue((idx_t)STANDARD_VECTOR_SIZE, entry_remaining); - // Onces for lazy computations. - mutable std::once_flag rprog_once_; - mutable std::once_flag named_groups_once_; - mutable std::once_flag group_names_once_; + // compute and add to the total + std::fill_n(list_entry_sizes, next, 0); + RowOperations::ComputeEntrySizes(child_vector, list_entry_sizes, next, next, + *FlatVector::IncrementalSelectionVector(), entry_offset); + for (idx_t list_idx = 0; list_idx < next; list_idx++) { + entry_sizes[i] += list_entry_sizes[list_idx]; + } - RE2(const RE2&) = delete; - RE2& operator=(const RE2&) = delete; -}; + // update for next iteration + entry_remaining -= next; + entry_offset += next; + } + } + } +} -/***** Implementation details *****/ +void RowOperations::ComputeEntrySizes(Vector &v, UnifiedVectorFormat &vdata, idx_t entry_sizes[], idx_t vcount, + idx_t ser_count, const SelectionVector &sel, idx_t offset) { + const auto physical_type = v.GetType().InternalType(); + if (TypeIsConstantSize(physical_type)) { + const auto type_size = GetTypeIdSize(physical_type); + for (idx_t i = 0; i < ser_count; i++) { + entry_sizes[i] += type_size; + } + } else { + switch (physical_type) { + case PhysicalType::VARCHAR: + ComputeStringEntrySizes(vdata, entry_sizes, ser_count, sel, offset); + break; + case PhysicalType::STRUCT: + ComputeStructEntrySizes(v, entry_sizes, vcount, ser_count, sel, offset); + break; + case PhysicalType::LIST: + ComputeListEntrySizes(v, vdata, entry_sizes, ser_count, sel, offset); + break; + default: + // LCOV_EXCL_START + throw NotImplementedException("Column with variable size type %s cannot be serialized to row-format", + v.GetType().ToString()); + // LCOV_EXCL_STOP + } + } +} -// Hex/Octal/Binary? +void RowOperations::ComputeEntrySizes(Vector &v, idx_t entry_sizes[], idx_t vcount, idx_t ser_count, + const SelectionVector &sel, idx_t offset) { + UnifiedVectorFormat vdata; + v.ToUnifiedFormat(vcount, vdata); + ComputeEntrySizes(v, vdata, entry_sizes, vcount, ser_count, sel, offset); +} -// Special class for parsing into objects that define a ParseFrom() method template -class _RE2_MatchObject { - public: - static inline bool Parse(const char* str, size_t n, void* dest) { - if (dest == NULL) return true; - T* object = reinterpret_cast(dest); - return object->ParseFrom(str, n); - } -}; +static void TemplatedHeapScatter(UnifiedVectorFormat &vdata, const SelectionVector &sel, idx_t count, idx_t col_idx, + data_ptr_t *key_locations, data_ptr_t *validitymask_locations, idx_t offset) { + auto source = (T *)vdata.data; + if (!validitymask_locations) { + for (idx_t i = 0; i < count; i++) { + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; -class RE2::Arg { - public: - // Empty constructor so we can declare arrays of RE2::Arg - Arg(); + auto target = (T *)key_locations[i]; + Store(source[source_idx], (data_ptr_t)target); + key_locations[i] += sizeof(T); + } + } else { + idx_t entry_idx; + idx_t idx_in_entry; + ValidityBytes::GetEntryIndex(col_idx, entry_idx, idx_in_entry); + const auto bit = ~(1UL << idx_in_entry); + for (idx_t i = 0; i < count; i++) { + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; - // Constructor specially designed for NULL arguments - Arg(void*); - Arg(std::nullptr_t); + auto target = (T *)key_locations[i]; + Store(source[source_idx], (data_ptr_t)target); + key_locations[i] += sizeof(T); - typedef bool (*Parser)(const char* str, size_t n, void* dest); + // set the validitymask + if (!vdata.validity.RowIsValid(source_idx)) { + *(validitymask_locations[i] + entry_idx) &= bit; + } + } + } +} -// Type-specific parsers -#define MAKE_PARSER(type, name) \ - Arg(type* p) : arg_(p), parser_(name) {} \ - Arg(type* p, Parser parser) : arg_(p), parser_(parser) {} +static void HeapScatterStringVector(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, idx_t col_idx, + data_ptr_t *key_locations, data_ptr_t *validitymask_locations, idx_t offset) { + UnifiedVectorFormat vdata; + v.ToUnifiedFormat(vcount, vdata); - MAKE_PARSER(char, parse_char) - MAKE_PARSER(signed char, parse_schar) - MAKE_PARSER(unsigned char, parse_uchar) - MAKE_PARSER(float, parse_float) - MAKE_PARSER(double, parse_double) - MAKE_PARSER(std::string, parse_string) - MAKE_PARSER(StringPiece, parse_stringpiece) + auto strings = (string_t *)vdata.data; + if (!validitymask_locations) { + for (idx_t i = 0; i < ser_count; i++) { + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; + if (vdata.validity.RowIsValid(source_idx)) { + auto &string_entry = strings[source_idx]; + // store string size + Store(string_entry.GetSize(), key_locations[i]); + key_locations[i] += sizeof(uint32_t); + // store the string + memcpy(key_locations[i], string_entry.GetDataUnsafe(), string_entry.GetSize()); + key_locations[i] += string_entry.GetSize(); + } + } + } else { + idx_t entry_idx; + idx_t idx_in_entry; + ValidityBytes::GetEntryIndex(col_idx, entry_idx, idx_in_entry); + const auto bit = ~(1UL << idx_in_entry); + for (idx_t i = 0; i < ser_count; i++) { + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; + if (vdata.validity.RowIsValid(source_idx)) { + auto &string_entry = strings[source_idx]; + // store string size + Store(string_entry.GetSize(), key_locations[i]); + key_locations[i] += sizeof(uint32_t); + // store the string + memcpy(key_locations[i], string_entry.GetDataUnsafe(), string_entry.GetSize()); + key_locations[i] += string_entry.GetSize(); + } else { + // set the validitymask + *(validitymask_locations[i] + entry_idx) &= bit; + } + } + } +} - MAKE_PARSER(short, parse_short) - MAKE_PARSER(unsigned short, parse_ushort) - MAKE_PARSER(int, parse_int) - MAKE_PARSER(unsigned int, parse_uint) - MAKE_PARSER(long, parse_long) - MAKE_PARSER(unsigned long, parse_ulong) - MAKE_PARSER(long long, parse_longlong) - MAKE_PARSER(unsigned long long, parse_ulonglong) +static void HeapScatterStructVector(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, idx_t col_idx, + data_ptr_t *key_locations, data_ptr_t *validitymask_locations, idx_t offset) { + UnifiedVectorFormat vdata; + v.ToUnifiedFormat(vcount, vdata); -#undef MAKE_PARSER + auto &children = StructVector::GetEntries(v); + idx_t num_children = children.size(); - // Generic constructor templates - template Arg(T* p) - : arg_(p), parser_(_RE2_MatchObject::Parse) { } - template Arg(T* p, Parser parser) - : arg_(p), parser_(parser) { } + // the whole struct itself can be NULL + idx_t entry_idx; + idx_t idx_in_entry; + ValidityBytes::GetEntryIndex(col_idx, entry_idx, idx_in_entry); + const auto bit = ~(1UL << idx_in_entry); - // Parse the data - bool Parse(const char* str, size_t n) const; + // struct must have a validitymask for its fields + const idx_t struct_validitymask_size = (num_children + 7) / 8; + data_ptr_t struct_validitymask_locations[STANDARD_VECTOR_SIZE]; + for (idx_t i = 0; i < ser_count; i++) { + // initialize the struct validity mask + struct_validitymask_locations[i] = key_locations[i]; + memset(struct_validitymask_locations[i], -1, struct_validitymask_size); + key_locations[i] += struct_validitymask_size; - private: - void* arg_; - Parser parser_; + // set whether the whole struct is null + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; + if (validitymask_locations && !vdata.validity.RowIsValid(source_idx)) { + *(validitymask_locations[i] + entry_idx) &= bit; + } + } - static bool parse_null (const char* str, size_t n, void* dest); - static bool parse_char (const char* str, size_t n, void* dest); - static bool parse_schar (const char* str, size_t n, void* dest); - static bool parse_uchar (const char* str, size_t n, void* dest); - static bool parse_float (const char* str, size_t n, void* dest); - static bool parse_double (const char* str, size_t n, void* dest); - static bool parse_string (const char* str, size_t n, void* dest); - static bool parse_stringpiece (const char* str, size_t n, void* dest); + // now serialize the struct vectors + for (idx_t i = 0; i < children.size(); i++) { + auto &struct_vector = *children[i]; + RowOperations::HeapScatter(struct_vector, vcount, sel, ser_count, i, key_locations, + struct_validitymask_locations, offset); + } +} -#define DECLARE_INTEGER_PARSER(name) \ - private: \ - static bool parse_##name(const char* str, size_t n, void* dest); \ - static bool parse_##name##_radix(const char* str, size_t n, void* dest, \ - int radix); \ - \ - public: \ - static bool parse_##name##_hex(const char* str, size_t n, void* dest); \ - static bool parse_##name##_octal(const char* str, size_t n, void* dest); \ - static bool parse_##name##_cradix(const char* str, size_t n, void* dest); +static void HeapScatterListVector(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, idx_t col_no, + data_ptr_t *key_locations, data_ptr_t *validitymask_locations, idx_t offset) { + UnifiedVectorFormat vdata; + v.ToUnifiedFormat(vcount, vdata); - DECLARE_INTEGER_PARSER(short) - DECLARE_INTEGER_PARSER(ushort) - DECLARE_INTEGER_PARSER(int) - DECLARE_INTEGER_PARSER(uint) - DECLARE_INTEGER_PARSER(long) - DECLARE_INTEGER_PARSER(ulong) - DECLARE_INTEGER_PARSER(longlong) - DECLARE_INTEGER_PARSER(ulonglong) + idx_t entry_idx; + idx_t idx_in_entry; + ValidityBytes::GetEntryIndex(col_no, entry_idx, idx_in_entry); -#undef DECLARE_INTEGER_PARSER + auto list_data = ListVector::GetData(v); -}; + auto &child_vector = ListVector::GetEntry(v); -inline RE2::Arg::Arg() : arg_(NULL), parser_(parse_null) { } -inline RE2::Arg::Arg(void* p) : arg_(p), parser_(parse_null) { } -inline RE2::Arg::Arg(std::nullptr_t p) : arg_(p), parser_(parse_null) { } + UnifiedVectorFormat list_vdata; + child_vector.ToUnifiedFormat(ListVector::GetListSize(v), list_vdata); + auto child_type = ListType::GetChildType(v.GetType()).InternalType(); -inline bool RE2::Arg::Parse(const char* str, size_t n) const { - return (*parser_)(str, n, arg_); -} + idx_t list_entry_sizes[STANDARD_VECTOR_SIZE]; + data_ptr_t list_entry_locations[STANDARD_VECTOR_SIZE]; -// This part of the parser, appropriate only for ints, deals with bases -#define MAKE_INTEGER_PARSER(type, name) \ - inline RE2::Arg RE2::Hex(type* ptr) { \ - return RE2::Arg(ptr, RE2::Arg::parse_##name##_hex); \ - } \ - inline RE2::Arg RE2::Octal(type* ptr) { \ - return RE2::Arg(ptr, RE2::Arg::parse_##name##_octal); \ - } \ - inline RE2::Arg RE2::CRadix(type* ptr) { \ - return RE2::Arg(ptr, RE2::Arg::parse_##name##_cradix); \ - } + for (idx_t i = 0; i < ser_count; i++) { + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; + if (!vdata.validity.RowIsValid(source_idx)) { + if (validitymask_locations) { + // set the row validitymask for this column to invalid + ValidityBytes row_mask(validitymask_locations[i]); + row_mask.SetInvalidUnsafe(entry_idx, idx_in_entry); + } + continue; + } + auto list_entry = list_data[source_idx]; -MAKE_INTEGER_PARSER(short, short) -MAKE_INTEGER_PARSER(unsigned short, ushort) -MAKE_INTEGER_PARSER(int, int) -MAKE_INTEGER_PARSER(unsigned int, uint) -MAKE_INTEGER_PARSER(long, long) -MAKE_INTEGER_PARSER(unsigned long, ulong) -MAKE_INTEGER_PARSER(long long, longlong) -MAKE_INTEGER_PARSER(unsigned long long, ulonglong) + // store list length + Store(list_entry.length, key_locations[i]); + key_locations[i] += sizeof(list_entry.length); -#undef MAKE_INTEGER_PARSER + // make room for the validitymask + data_ptr_t list_validitymask_location = key_locations[i]; + idx_t entry_offset_in_byte = 0; + idx_t validitymask_size = (list_entry.length + 7) / 8; + memset(list_validitymask_location, -1, validitymask_size); + key_locations[i] += validitymask_size; -#ifndef SWIG + // serialize size of each entry (if non-constant size) + data_ptr_t var_entry_size_ptr = nullptr; + if (!TypeIsConstantSize(child_type)) { + var_entry_size_ptr = key_locations[i]; + key_locations[i] += list_entry.length * sizeof(idx_t); + } + auto entry_remaining = list_entry.length; + auto entry_offset = list_entry.offset; + while (entry_remaining > 0) { + // the list entry can span multiple vectors + auto next = MinValue((idx_t)STANDARD_VECTOR_SIZE, entry_remaining); -// Helper for writing global or static RE2s safely. -// Write -// static LazyRE2 re = {".*"}; -// and then use *re instead of writing -// static RE2 re(".*"); -// The former is more careful about multithreaded -// situations than the latter. -// -// N.B. This class never deletes the RE2 object that -// it constructs: that's a feature, so that it can be used -// for global and function static variables. -class LazyRE2 { - private: - struct NoArg {}; + // serialize list validity + for (idx_t entry_idx = 0; entry_idx < next; entry_idx++) { + auto list_idx = list_vdata.sel->get_index(entry_idx) + entry_offset; + if (!list_vdata.validity.RowIsValid(list_idx)) { + *(list_validitymask_location) &= ~(1UL << entry_offset_in_byte); + } + if (++entry_offset_in_byte == 8) { + list_validitymask_location++; + entry_offset_in_byte = 0; + } + } - public: - typedef RE2 element_type; // support std::pointer_traits + if (TypeIsConstantSize(child_type)) { + // constant size list entries: set list entry locations + const idx_t type_size = GetTypeIdSize(child_type); + for (idx_t entry_idx = 0; entry_idx < next; entry_idx++) { + list_entry_locations[entry_idx] = key_locations[i]; + key_locations[i] += type_size; + } + } else { + // variable size list entries: compute entry sizes and set list entry locations + std::fill_n(list_entry_sizes, next, 0); + RowOperations::ComputeEntrySizes(child_vector, list_entry_sizes, next, next, + *FlatVector::IncrementalSelectionVector(), entry_offset); + for (idx_t entry_idx = 0; entry_idx < next; entry_idx++) { + list_entry_locations[entry_idx] = key_locations[i]; + key_locations[i] += list_entry_sizes[entry_idx]; + Store(list_entry_sizes[entry_idx], var_entry_size_ptr); + var_entry_size_ptr += sizeof(idx_t); + } + } - // Constructor omitted to preserve braced initialization in C++98. + // now serialize to the locations + RowOperations::HeapScatter(child_vector, ListVector::GetListSize(v), + *FlatVector::IncrementalSelectionVector(), next, 0, list_entry_locations, + nullptr, entry_offset); - // Pretend to be a pointer to Type (never NULL due to on-demand creation): - RE2& operator*() const { return *get(); } - RE2* operator->() const { return get(); } + // update for next iteration + entry_remaining -= next; + entry_offset += next; + } + } +} - // Named accessor/initializer: - RE2* get() const { - std::call_once(once_, &LazyRE2::Init, this); - return ptr_; - } +void RowOperations::HeapScatter(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, idx_t col_idx, + data_ptr_t *key_locations, data_ptr_t *validitymask_locations, idx_t offset) { + if (TypeIsConstantSize(v.GetType().InternalType())) { + UnifiedVectorFormat vdata; + v.ToUnifiedFormat(vcount, vdata); + RowOperations::HeapScatterVData(vdata, v.GetType().InternalType(), sel, ser_count, col_idx, key_locations, + validitymask_locations, offset); + } else { + switch (v.GetType().InternalType()) { + case PhysicalType::VARCHAR: + HeapScatterStringVector(v, vcount, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + case PhysicalType::STRUCT: + HeapScatterStructVector(v, vcount, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + case PhysicalType::LIST: + HeapScatterListVector(v, vcount, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + default: + // LCOV_EXCL_START + throw NotImplementedException("Serialization of variable length vector with type %s", + v.GetType().ToString()); + // LCOV_EXCL_STOP + } + } +} - // All data fields must be public to support {"foo"} initialization. - const char* pattern_; - RE2::CannedOptions options_; - NoArg barrier_against_excess_initializers_; +void RowOperations::HeapScatterVData(UnifiedVectorFormat &vdata, PhysicalType type, const SelectionVector &sel, + idx_t ser_count, idx_t col_idx, data_ptr_t *key_locations, + data_ptr_t *validitymask_locations, idx_t offset) { + switch (type) { + case PhysicalType::BOOL: + case PhysicalType::INT8: + TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + case PhysicalType::INT16: + TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + case PhysicalType::INT32: + TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + case PhysicalType::INT64: + TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + case PhysicalType::UINT8: + TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + case PhysicalType::UINT16: + TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + case PhysicalType::UINT32: + TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + case PhysicalType::UINT64: + TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + case PhysicalType::INT128: + TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + case PhysicalType::FLOAT: + TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + case PhysicalType::DOUBLE: + TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + case PhysicalType::INTERVAL: + TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); + break; + default: + throw NotImplementedException("FIXME: Serialize to of constant type column to row-format"); + } +} - mutable RE2* ptr_; - mutable std::once_flag once_; +} // namespace duckdb +//===--------------------------------------------------------------------===// +// row_match.cpp +// Description: This file contains the implementation of the match operators +//===--------------------------------------------------------------------===// - private: - static void Init(const LazyRE2* lazy_re2) { - lazy_re2->ptr_ = new RE2(lazy_re2->pattern_, lazy_re2->options_); - } - void operator=(const LazyRE2&); // disallowed -}; -#endif // SWIG -} // namespace duckdb_re2 -using duckdb_re2::RE2; -using duckdb_re2::LazyRE2; -#endif // RE2_RE2_H_ -// LICENSE_CHANGE_END +namespace duckdb { +using ValidityBytes = RowLayout::ValidityBytes; +using Predicates = RowOperations::Predicates; -namespace duckdb_re2 { +template +static idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, + SelectionVector *true_sel, SelectionVector *false_sel) { + throw NotImplementedException("Unsupported nested comparison operand for RowOperations::Match"); +} -Regex::Regex(const std::string &pattern, RegexOptions options) { - RE2::Options o; - o.set_case_sensitive(options == RegexOptions::CASE_INSENSITIVE); - regex = std::make_shared(StringPiece(pattern), o); +template <> +idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, + SelectionVector *true_sel, SelectionVector *false_sel) { + return VectorOperations::NestedEquals(left, right, sel, count, true_sel, false_sel); } -bool RegexSearchInternal(const char *input, Match &match, const Regex &r, RE2::Anchor anchor, size_t start, - size_t end) { - auto ®ex = r.GetRegex(); - std::vector target_groups; - auto group_count = regex.NumberOfCapturingGroups() + 1; - target_groups.resize(group_count); - match.groups.clear(); - if (!regex.Match(StringPiece(input), start, end, anchor, target_groups.data(), group_count)) { - return false; - } - for (auto &group : target_groups) { - GroupMatch group_match; - group_match.text = group.ToString(); - group_match.position = group.data() - input; - match.groups.emplace_back(group_match); - } - return true; +template <> +idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, + SelectionVector *true_sel, SelectionVector *false_sel) { + return VectorOperations::NestedNotEquals(left, right, sel, count, true_sel, false_sel); } -bool RegexSearch(const std::string &input, Match &match, const Regex ®ex) { - return RegexSearchInternal(input.c_str(), match, regex, RE2::UNANCHORED, 0, input.size()); +template <> +idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, + SelectionVector *true_sel, SelectionVector *false_sel) { + return VectorOperations::DistinctGreaterThan(left, right, &sel, count, true_sel, false_sel); } -bool RegexMatch(const std::string &input, Match &match, const Regex ®ex) { - return RegexSearchInternal(input.c_str(), match, regex, RE2::ANCHOR_BOTH, 0, input.size()); +template <> +idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, + SelectionVector *true_sel, SelectionVector *false_sel) { + return VectorOperations::DistinctGreaterThanEquals(left, right, &sel, count, true_sel, false_sel); } -bool RegexMatch(const char *start, const char *end, Match &match, const Regex ®ex) { - return RegexSearchInternal(start, match, regex, RE2::ANCHOR_BOTH, 0, end - start); +template <> +idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, + SelectionVector *true_sel, SelectionVector *false_sel) { + return VectorOperations::DistinctLessThan(left, right, &sel, count, true_sel, false_sel); } -bool RegexMatch(const std::string &input, const Regex ®ex) { - Match nop_match; - return RegexSearchInternal(input.c_str(), nop_match, regex, RE2::ANCHOR_BOTH, 0, input.size()); +template <> +idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, + SelectionVector *true_sel, SelectionVector *false_sel) { + return VectorOperations::DistinctLessThanEquals(left, right, &sel, count, true_sel, false_sel); } -std::vector RegexFindAll(const std::string &input, const Regex ®ex) { - std::vector matches; - size_t position = 0; - Match match; - while (RegexSearchInternal(input.c_str(), match, regex, RE2::UNANCHORED, position, input.size())) { - position += match.position(0) + match.length(0); - matches.emplace_back(std::move(match)); - } - return matches; -} +template +static void TemplatedMatchType(UnifiedVectorFormat &col, Vector &rows, SelectionVector &sel, idx_t &count, + idx_t col_offset, idx_t col_no, SelectionVector *no_match, idx_t &no_match_count) { + // Precompute row_mask indexes + idx_t entry_idx; + idx_t idx_in_entry; + ValidityBytes::GetEntryIndex(col_no, entry_idx, idx_in_entry); -} // namespace duckdb_re2//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/types/row_operations/row_aggregate.cpp -// -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/row_operations/row_operations.hpp -// -// -//===----------------------------------------------------------------------===// + auto data = (T *)col.data; + auto ptrs = FlatVector::GetData(rows); + idx_t match_count = 0; + if (!col.validity.AllValid()) { + for (idx_t i = 0; i < count; i++) { + auto idx = sel.get_index(i); + auto row = ptrs[idx]; + ValidityBytes row_mask(row); + auto isnull = !row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry); + auto col_idx = col.sel->get_index(idx); + if (!col.validity.RowIsValid(col_idx)) { + if (isnull) { + // match: move to next value to compare + sel.set_index(match_count++, idx); + } else { + if (NO_MATCH_SEL) { + no_match->set_index(no_match_count++, idx); + } + } + } else { + auto value = Load(row + col_offset); + if (!isnull && OP::template Operation(data[col_idx], value)) { + sel.set_index(match_count++, idx); + } else { + if (NO_MATCH_SEL) { + no_match->set_index(no_match_count++, idx); + } + } + } + } + } else { + for (idx_t i = 0; i < count; i++) { + auto idx = sel.get_index(i); + auto row = ptrs[idx]; + ValidityBytes row_mask(row); + auto isnull = !row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry); + auto col_idx = col.sel->get_index(idx); + auto value = Load(row + col_offset); + if (!isnull && OP::template Operation(data[col_idx], value)) { + sel.set_index(match_count++, idx); + } else { + if (NO_MATCH_SEL) { + no_match->set_index(no_match_count++, idx); + } + } + } + } + count = match_count; +} +template +static void TemplatedMatchNested(Vector &col, Vector &rows, SelectionVector &sel, idx_t &count, const RowLayout &layout, + const idx_t col_no, SelectionVector *no_match, idx_t &no_match_count) { + // Gather a dense Vector containing the column values being matched + Vector key(col.GetType()); + RowOperations::Gather(rows, sel, key, *FlatVector::IncrementalSelectionVector(), count, layout, col_no); -namespace duckdb { + // Densify the input column + Vector sliced(col, sel, count); -struct AggregateObject; -class DataChunk; -class RowLayout; -class RowDataCollection; -struct SelectionVector; -class StringHeap; -class Vector; -struct VectorData; + if (NO_MATCH_SEL) { + SelectionVector no_match_sel_offset(no_match->data() + no_match_count); + auto match_count = SelectComparison(sliced, key, sel, count, &sel, &no_match_sel_offset); + no_match_count += count - match_count; + count = match_count; + } else { + count = SelectComparison(sliced, key, sel, count, &sel, nullptr); + } +} -// RowOperations contains a set of operations that operate on data using a RowLayout -struct RowOperations { - //===--------------------------------------------------------------------===// - // Aggregation Operators - //===--------------------------------------------------------------------===// - //! initialize - unaligned addresses - static void InitializeStates(RowLayout &layout, Vector &addresses, const SelectionVector &sel, idx_t count); - //! destructor - unaligned addresses, updated - static void DestroyStates(RowLayout &layout, Vector &addresses, idx_t count); - //! update - aligned addresses - static void UpdateStates(AggregateObject &aggr, Vector &addresses, DataChunk &payload, idx_t arg_idx, idx_t count); - //! filtered update - aligned addresses - static void UpdateFilteredStates(AggregateObject &aggr, Vector &addresses, DataChunk &payload, idx_t arg_idx); - //! combine - unaligned addresses, updated - static void CombineStates(RowLayout &layout, Vector &sources, Vector &targets, idx_t count); - //! finalize - unaligned addresses, updated - static void FinalizeStates(RowLayout &layout, Vector &addresses, DataChunk &result, idx_t aggr_idx); +template +static void TemplatedMatchOp(Vector &vec, UnifiedVectorFormat &col, const RowLayout &layout, Vector &rows, + SelectionVector &sel, idx_t &count, idx_t col_no, SelectionVector *no_match, + idx_t &no_match_count) { + if (count == 0) { + return; + } + auto col_offset = layout.GetOffsets()[col_no]; + switch (layout.GetTypes()[col_no].InternalType()) { + case PhysicalType::BOOL: + case PhysicalType::INT8: + TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, + no_match_count); + break; + case PhysicalType::INT16: + TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, + no_match_count); + break; + case PhysicalType::INT32: + TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, + no_match_count); + break; + case PhysicalType::INT64: + TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, + no_match_count); + break; + case PhysicalType::UINT8: + TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, + no_match_count); + break; + case PhysicalType::UINT16: + TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, + no_match_count); + break; + case PhysicalType::UINT32: + TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, + no_match_count); + break; + case PhysicalType::UINT64: + TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, + no_match_count); + break; + case PhysicalType::INT128: + TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, + no_match_count); + break; + case PhysicalType::FLOAT: + TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, + no_match_count); + break; + case PhysicalType::DOUBLE: + TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, + no_match_count); + break; + case PhysicalType::INTERVAL: + TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, + no_match_count); + break; + case PhysicalType::VARCHAR: + TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, + no_match_count); + break; + case PhysicalType::LIST: + case PhysicalType::MAP: + case PhysicalType::STRUCT: + TemplatedMatchNested(vec, rows, sel, count, layout, col_no, no_match, no_match_count); + break; + default: + throw InternalException("Unsupported column type for RowOperations::Match"); + } +} - //===--------------------------------------------------------------------===// - // Read/Write Operators - //===--------------------------------------------------------------------===// - //! Scatter group data to the rows. Initialises the ValidityMask. - static void Scatter(DataChunk &columns, VectorData col_data[], const RowLayout &layout, Vector &rows, - RowDataCollection &string_heap, const SelectionVector &sel, idx_t count); - //! Gather a single column. - static void Gather(Vector &rows, const SelectionVector &row_sel, Vector &col, const SelectionVector &col_sel, - const idx_t count, const idx_t col_offset, const idx_t col_no, const idx_t build_size = 0); - //! Full Scan an entire columns - static void FullScanColumn(const RowLayout &layout, Vector &rows, Vector &col, idx_t count, idx_t col_idx); +template +static void TemplatedMatch(DataChunk &columns, UnifiedVectorFormat col_data[], const RowLayout &layout, Vector &rows, + const Predicates &predicates, SelectionVector &sel, idx_t &count, SelectionVector *no_match, + idx_t &no_match_count) { + for (idx_t col_no = 0; col_no < predicates.size(); ++col_no) { + auto &vec = columns.data[col_no]; + auto &col = col_data[col_no]; + switch (predicates[col_no]) { + case ExpressionType::COMPARE_EQUAL: + case ExpressionType::COMPARE_NOT_DISTINCT_FROM: + case ExpressionType::COMPARE_DISTINCT_FROM: + TemplatedMatchOp(vec, col, layout, rows, sel, count, col_no, no_match, + no_match_count); + break; + case ExpressionType::COMPARE_NOTEQUAL: + TemplatedMatchOp(vec, col, layout, rows, sel, count, col_no, no_match, + no_match_count); + break; + case ExpressionType::COMPARE_GREATERTHAN: + TemplatedMatchOp(vec, col, layout, rows, sel, count, col_no, no_match, + no_match_count); + break; + case ExpressionType::COMPARE_GREATERTHANOREQUALTO: + TemplatedMatchOp(vec, col, layout, rows, sel, count, col_no, no_match, + no_match_count); + break; + case ExpressionType::COMPARE_LESSTHAN: + TemplatedMatchOp(vec, col, layout, rows, sel, count, col_no, no_match, + no_match_count); + break; + case ExpressionType::COMPARE_LESSTHANOREQUALTO: + TemplatedMatchOp(vec, col, layout, rows, sel, count, col_no, no_match, + no_match_count); + break; + default: + throw InternalException("Unsupported comparison type for RowOperations::Match"); + } + } +} - //===--------------------------------------------------------------------===// - // Comparison Operators - //===--------------------------------------------------------------------===// - //! Compare a block of key data against the row values to produce an updated selection that matches - //! and a second (optional) selection of non-matching values. - //! Returns the number of matches remaining in the selection. - using Predicates = vector; +idx_t RowOperations::Match(DataChunk &columns, UnifiedVectorFormat col_data[], const RowLayout &layout, Vector &rows, + const Predicates &predicates, SelectionVector &sel, idx_t count, SelectionVector *no_match, + idx_t &no_match_count) { + if (no_match) { + TemplatedMatch(columns, col_data, layout, rows, predicates, sel, count, no_match, no_match_count); + } else { + TemplatedMatch(columns, col_data, layout, rows, predicates, sel, count, no_match, no_match_count); + } - static idx_t Match(DataChunk &columns, VectorData col_data[], const RowLayout &layout, Vector &rows, - const Predicates &predicates, SelectionVector &sel, idx_t count, SelectionVector *no_match, - idx_t &no_match_count); + return count; +} - //===--------------------------------------------------------------------===// - // Heap Operators - //===--------------------------------------------------------------------===// - //! Compute the entry sizes of a vector with variable size type (used before building heap buffer space). - static void ComputeEntrySizes(Vector &v, idx_t entry_sizes[], idx_t vcount, idx_t ser_count, - const SelectionVector &sel, idx_t offset = 0); - //! Compute the entry sizes of vector data with variable size type (used before building heap buffer space). - static void ComputeEntrySizes(Vector &v, VectorData &vdata, idx_t entry_sizes[], idx_t vcount, idx_t ser_count, - const SelectionVector &sel, idx_t offset = 0); - //! Scatter vector with variable size type to the heap. - static void HeapScatter(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, idx_t col_idx, - data_ptr_t *key_locations, data_ptr_t *validitymask_locations, idx_t offset = 0); - //! Scatter vector data with variable size type to the heap. - static void HeapScatterVData(VectorData &vdata, PhysicalType type, const SelectionVector &sel, idx_t ser_count, - idx_t col_idx, data_ptr_t *key_locations, data_ptr_t *validitymask_locations, - idx_t offset = 0); - //! Gather a single column with variable size type from the heap. - static void HeapGather(Vector &v, const idx_t &vcount, const SelectionVector &sel, const idx_t &col_idx, - data_ptr_t key_locations[], data_ptr_t validitymask_locations[]); +} // namespace duckdb - //===--------------------------------------------------------------------===// - // Sorting Operators - //===--------------------------------------------------------------------===// - //! Scatter vector data to the rows in radix-sortable format. - static void RadixScatter(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, - data_ptr_t key_locations[], bool desc, bool has_null, bool nulls_first, idx_t prefix_len, - idx_t width, idx_t offset = 0); - //===--------------------------------------------------------------------===// - // Out-of-Core Operators - //===--------------------------------------------------------------------===// - //! Swizzles blob pointers to offset within heap row - static void SwizzleColumns(const RowLayout &layout, const data_ptr_t base_row_ptr, const idx_t count); - //! Swizzles the base pointer of each row to offset within heap block - static void SwizzleHeapPointer(const RowLayout &layout, data_ptr_t row_ptr, const data_ptr_t heap_base_ptr, - const idx_t count); - //! Unswizzles all offsets back to pointers - static void UnswizzlePointers(const RowLayout &layout, const data_ptr_t base_row_ptr, - const data_ptr_t base_heap_ptr, const idx_t count); -}; -} // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/types/row_layout.hpp -// -// -//===----------------------------------------------------------------------===// +namespace duckdb { +template +void TemplatedRadixScatter(UnifiedVectorFormat &vdata, const SelectionVector &sel, idx_t add_count, + data_ptr_t *key_locations, const bool desc, const bool has_null, const bool nulls_first, + const idx_t offset) { + auto source = (T *)vdata.data; + if (has_null) { + auto &validity = vdata.validity; + const data_t valid = nulls_first ? 1 : 0; + const data_t invalid = 1 - valid; + for (idx_t i = 0; i < add_count; i++) { + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; + // write validity and according value + if (validity.RowIsValid(source_idx)) { + key_locations[i][0] = valid; + Radix::EncodeData(key_locations[i] + 1, source[source_idx]); + // invert bits if desc + if (desc) { + for (idx_t s = 1; s < sizeof(T) + 1; s++) { + *(key_locations[i] + s) = ~*(key_locations[i] + s); + } + } + } else { + key_locations[i][0] = invalid; + memset(key_locations[i] + 1, '\0', sizeof(T)); + } + key_locations[i] += sizeof(T) + 1; + } + } else { + for (idx_t i = 0; i < add_count; i++) { + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; + // write value + Radix::EncodeData(key_locations[i], source[source_idx]); + // invert bits if desc + if (desc) { + for (idx_t s = 0; s < sizeof(T); s++) { + *(key_locations[i] + s) = ~*(key_locations[i] + s); + } + } + key_locations[i] += sizeof(T); + } + } +} +void RadixScatterStringVector(UnifiedVectorFormat &vdata, const SelectionVector &sel, idx_t add_count, + data_ptr_t *key_locations, const bool desc, const bool has_null, const bool nulls_first, + const idx_t prefix_len, idx_t offset) { + auto source = (string_t *)vdata.data; + if (has_null) { + auto &validity = vdata.validity; + const data_t valid = nulls_first ? 1 : 0; + const data_t invalid = 1 - valid; + for (idx_t i = 0; i < add_count; i++) { + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; + // write validity and according value + if (validity.RowIsValid(source_idx)) { + key_locations[i][0] = valid; + Radix::EncodeStringDataPrefix(key_locations[i] + 1, source[source_idx], prefix_len); + // invert bits if desc + if (desc) { + for (idx_t s = 1; s < prefix_len + 1; s++) { + *(key_locations[i] + s) = ~*(key_locations[i] + s); + } + } + } else { + key_locations[i][0] = invalid; + memset(key_locations[i] + 1, '\0', prefix_len); + } + key_locations[i] += prefix_len + 1; + } + } else { + for (idx_t i = 0; i < add_count; i++) { + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; + // write value + Radix::EncodeStringDataPrefix(key_locations[i], source[source_idx], prefix_len); + // invert bits if desc + if (desc) { + for (idx_t s = 0; s < prefix_len; s++) { + *(key_locations[i] + s) = ~*(key_locations[i] + s); + } + } + key_locations[i] += prefix_len; + } + } +} +void RadixScatterListVector(Vector &v, UnifiedVectorFormat &vdata, const SelectionVector &sel, idx_t add_count, + data_ptr_t *key_locations, const bool desc, const bool has_null, const bool nulls_first, + const idx_t prefix_len, const idx_t width, const idx_t offset) { + auto list_data = ListVector::GetData(v); + auto &child_vector = ListVector::GetEntry(v); + auto list_size = ListVector::GetListSize(v); + // serialize null values + if (has_null) { + auto &validity = vdata.validity; + const data_t valid = nulls_first ? 1 : 0; + const data_t invalid = 1 - valid; + for (idx_t i = 0; i < add_count; i++) { + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; + data_ptr_t key_location = key_locations[i] + 1; + // write validity and according value + if (validity.RowIsValid(source_idx)) { + key_locations[i][0] = valid; + key_locations[i]++; + auto &list_entry = list_data[source_idx]; + if (list_entry.length > 0) { + // denote that the list is not empty with a 1 + key_locations[i][0] = 1; + key_locations[i]++; + RowOperations::RadixScatter(child_vector, list_size, *FlatVector::IncrementalSelectionVector(), 1, + key_locations + i, false, true, false, prefix_len, width - 1, + list_entry.offset); + } else { + // denote that the list is empty with a 0 + key_locations[i][0] = 0; + key_locations[i]++; + memset(key_locations[i], '\0', width - 2); + } + // invert bits if desc + if (desc) { + for (idx_t s = 0; s < width - 1; s++) { + *(key_location + s) = ~*(key_location + s); + } + } + } else { + key_locations[i][0] = invalid; + memset(key_locations[i] + 1, '\0', width - 1); + key_locations[i] += width; + } + } + } else { + for (idx_t i = 0; i < add_count; i++) { + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; + auto &list_entry = list_data[source_idx]; + data_ptr_t key_location = key_locations[i]; + if (list_entry.length > 0) { + // denote that the list is not empty with a 1 + key_locations[i][0] = 1; + key_locations[i]++; + RowOperations::RadixScatter(child_vector, list_size, *FlatVector::IncrementalSelectionVector(), 1, + key_locations + i, false, true, false, prefix_len, width - 1, + list_entry.offset); + } else { + // denote that the list is empty with a 0 + key_locations[i][0] = 0; + key_locations[i]++; + memset(key_locations[i], '\0', width - 1); + } + // invert bits if desc + if (desc) { + for (idx_t s = 0; s < width; s++) { + *(key_location + s) = ~*(key_location + s); + } + } + } + } +} -namespace duckdb { -class BoundAggregateExpression; +void RadixScatterStructVector(Vector &v, UnifiedVectorFormat &vdata, idx_t vcount, const SelectionVector &sel, + idx_t add_count, data_ptr_t *key_locations, const bool desc, const bool has_null, + const bool nulls_first, const idx_t prefix_len, idx_t width, const idx_t offset) { + // serialize null values + if (has_null) { + auto &validity = vdata.validity; + const data_t valid = nulls_first ? 1 : 0; + const data_t invalid = 1 - valid; -struct AggregateObject { - AggregateObject(AggregateFunction function, FunctionData *bind_data, idx_t child_count, idx_t payload_size, - bool distinct, PhysicalType return_type, Expression *filter = nullptr) - : function(move(function)), bind_data(bind_data), child_count(child_count), payload_size(payload_size), - distinct(distinct), return_type(return_type), filter(filter) { + for (idx_t i = 0; i < add_count; i++) { + auto idx = sel.get_index(i); + auto source_idx = vdata.sel->get_index(idx) + offset; + // write validity and according value + if (validity.RowIsValid(source_idx)) { + key_locations[i][0] = valid; + } else { + key_locations[i][0] = invalid; + } + key_locations[i]++; + } + width--; + } + // serialize the struct + auto &child_vector = *StructVector::GetEntries(v)[0]; + RowOperations::RadixScatter(child_vector, vcount, *FlatVector::IncrementalSelectionVector(), add_count, + key_locations, false, true, false, prefix_len, width, offset); + // invert bits if desc + if (desc) { + for (idx_t i = 0; i < add_count; i++) { + for (idx_t s = 0; s < width; s++) { + *(key_locations[i] - width + s) = ~*(key_locations[i] - width + s); + } + } } +} - AggregateFunction function; - FunctionData *bind_data; - idx_t child_count; - idx_t payload_size; - bool distinct; - PhysicalType return_type; - Expression *filter = nullptr; +void RowOperations::RadixScatter(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, + data_ptr_t *key_locations, bool desc, bool has_null, bool nulls_first, + idx_t prefix_len, idx_t width, idx_t offset) { + UnifiedVectorFormat vdata; + v.ToUnifiedFormat(vcount, vdata); + switch (v.GetType().InternalType()) { + case PhysicalType::BOOL: + case PhysicalType::INT8: + TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, offset); + break; + case PhysicalType::INT16: + TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, offset); + break; + case PhysicalType::INT32: + TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, offset); + break; + case PhysicalType::INT64: + TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, offset); + break; + case PhysicalType::UINT8: + TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, offset); + break; + case PhysicalType::UINT16: + TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, offset); + break; + case PhysicalType::UINT32: + TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, offset); + break; + case PhysicalType::UINT64: + TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, offset); + break; + case PhysicalType::INT128: + TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, offset); + break; + case PhysicalType::FLOAT: + TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, offset); + break; + case PhysicalType::DOUBLE: + TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, offset); + break; + case PhysicalType::INTERVAL: + TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, offset); + break; + case PhysicalType::VARCHAR: + RadixScatterStringVector(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, prefix_len, offset); + break; + case PhysicalType::LIST: + RadixScatterListVector(v, vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, prefix_len, width, + offset); + break; + case PhysicalType::STRUCT: + RadixScatterStructVector(v, vdata, vcount, sel, ser_count, key_locations, desc, has_null, nulls_first, + prefix_len, width, offset); + break; + default: + throw NotImplementedException("Cannot ORDER BY column with type %s", v.GetType().ToString()); + } +} + +} // namespace duckdb +//===--------------------------------------------------------------------===// +// row_scatter.cpp +// Description: This file contains the implementation of the row scattering +// operators +//===--------------------------------------------------------------------===// - static vector CreateAggregateObjects(const vector &bindings); -}; -class RowLayout { -public: - using Aggregates = vector; - using ValidityBytes = TemplatedValidityMask; - //! Creates an empty RowLayout - RowLayout(); -public: - //! Initializes the RowLayout with the specified types and aggregates to an empty RowLayout - void Initialize(vector types_p, Aggregates aggregates_p, bool align = true); - //! Initializes the RowLayout with the specified types to an empty RowLayout - void Initialize(vector types, bool align = true); - //! Initializes the RowLayout with the specified aggregates to an empty RowLayout - void Initialize(Aggregates aggregates_p, bool align = true); - //! Returns the number of data columns - inline idx_t ColumnCount() const { - return types.size(); - } - //! Returns a list of the column types for this data chunk - inline const vector &GetTypes() const { - return types; - } - //! Returns the number of aggregates - inline idx_t AggregateCount() const { - return aggregates.size(); - } - //! Returns a list of the aggregates for this data chunk - inline Aggregates &GetAggregates() { - return aggregates; - } - //! Returns the total width required for each row, including padding - inline idx_t GetRowWidth() const { - return row_width; - } - //! Returns the offset to the start of the data - inline idx_t GetDataOffset() const { - return flag_width; - } - //! Returns the total width required for the data, including padding - inline idx_t GetDataWidth() const { - return data_width; - } - //! Returns the offset to the start of the aggregates - inline idx_t GetAggrOffset() const { - return flag_width + data_width; - } - //! Returns the total width required for the aggregates, including padding - inline idx_t GetAggrWidth() const { - return aggr_width; - } - //! Returns the column offsets into each row - inline const vector &GetOffsets() const { - return offsets; - } - //! Returns whether all columns in this layout are constant size - inline bool AllConstant() const { - return all_constant; - } - inline idx_t GetHeapPointerOffset() const { - return heap_pointer_offset; - } -private: - //! The types of the data columns - vector types; - //! The aggregate functions - Aggregates aggregates; - //! The width of the validity header - idx_t flag_width; - //! The width of the data portion - idx_t data_width; - //! The width of the aggregate state portion - idx_t aggr_width; - //! The width of the entire row - idx_t row_width; - //! The offsets to the columns and aggregate data in each row - vector offsets; - //! Whether all columns in this layout are constant size - bool all_constant; - //! Offset to the pointer to the heap for each row - idx_t heap_pointer_offset; -}; -} // namespace duckdb namespace duckdb { -void RowOperations::InitializeStates(RowLayout &layout, Vector &addresses, const SelectionVector &sel, idx_t count) { - if (count == 0) { - return; - } - auto pointers = FlatVector::GetData(addresses); - auto &offsets = layout.GetOffsets(); - auto aggr_idx = layout.ColumnCount(); +using ValidityBytes = RowLayout::ValidityBytes; - for (auto &aggr : layout.GetAggregates()) { - for (idx_t i = 0; i < count; ++i) { - auto row_idx = sel.get_index(i); - auto row = pointers[row_idx]; - aggr.function.initialize(row + offsets[aggr_idx]); +template +static void TemplatedScatter(UnifiedVectorFormat &col, Vector &rows, const SelectionVector &sel, const idx_t count, + const idx_t col_offset, const idx_t col_no) { + auto data = (T *)col.data; + auto ptrs = FlatVector::GetData(rows); + + if (!col.validity.AllValid()) { + for (idx_t i = 0; i < count; i++) { + auto idx = sel.get_index(i); + auto col_idx = col.sel->get_index(idx); + auto row = ptrs[idx]; + + auto isnull = !col.validity.RowIsValid(col_idx); + T store_value = isnull ? NullValue() : data[col_idx]; + Store(store_value, row + col_offset); + if (isnull) { + ValidityBytes col_mask(ptrs[idx]); + col_mask.SetInvalidUnsafe(col_no); + } + } + } else { + for (idx_t i = 0; i < count; i++) { + auto idx = sel.get_index(i); + auto col_idx = col.sel->get_index(idx); + auto row = ptrs[idx]; + + Store(data[col_idx], row + col_offset); } - ++aggr_idx; } } -void RowOperations::DestroyStates(RowLayout &layout, Vector &addresses, idx_t count) { - if (count == 0) { - return; - } - // Move to the first aggregate state - VectorOperations::AddInPlace(addresses, layout.GetAggrOffset(), count); - for (auto &aggr : layout.GetAggregates()) { - if (aggr.function.destructor) { - aggr.function.destructor(addresses, count); +static void ComputeStringEntrySizes(const UnifiedVectorFormat &col, idx_t entry_sizes[], const SelectionVector &sel, + const idx_t count, const idx_t offset = 0) { + auto data = (const string_t *)col.data; + for (idx_t i = 0; i < count; i++) { + auto idx = sel.get_index(i); + auto col_idx = col.sel->get_index(idx) + offset; + const auto &str = data[col_idx]; + if (col.validity.RowIsValid(col_idx) && !str.IsInlined()) { + entry_sizes[i] += str.GetSize(); } - // Move to the next aggregate state - VectorOperations::AddInPlace(addresses, aggr.payload_size, count); } } -void RowOperations::UpdateStates(AggregateObject &aggr, Vector &addresses, DataChunk &payload, idx_t arg_idx, - idx_t count) { - aggr.function.update(aggr.child_count == 0 ? nullptr : &payload.data[arg_idx], aggr.bind_data, aggr.child_count, - addresses, count); -} +static void ScatterStringVector(UnifiedVectorFormat &col, Vector &rows, data_ptr_t str_locations[], + const SelectionVector &sel, const idx_t count, const idx_t col_offset, + const idx_t col_no) { + auto string_data = (string_t *)col.data; + auto ptrs = FlatVector::GetData(rows); -void RowOperations::UpdateFilteredStates(AggregateObject &aggr, Vector &addresses, DataChunk &payload, idx_t arg_idx) { - ExpressionExecutor filter_execution(aggr.filter); - SelectionVector true_sel(STANDARD_VECTOR_SIZE); - auto count = filter_execution.SelectExpression(payload, true_sel); + for (idx_t i = 0; i < count; i++) { + auto idx = sel.get_index(i); + auto col_idx = col.sel->get_index(idx); + auto row = ptrs[idx]; + if (!col.validity.RowIsValid(col_idx)) { + ValidityBytes col_mask(row); + col_mask.SetInvalidUnsafe(col_no); + Store(NullValue(), row + col_offset); + } else if (string_data[col_idx].IsInlined()) { + Store(string_data[col_idx], row + col_offset); + } else { + const auto &str = string_data[col_idx]; + string_t inserted((const char *)str_locations[i], str.GetSize()); + memcpy(inserted.GetDataWriteable(), str.GetDataUnsafe(), str.GetSize()); + str_locations[i] += str.GetSize(); + inserted.Finalize(); + Store(inserted, row + col_offset); + } + } +} - DataChunk filtered_payload; - auto pay_types = payload.GetTypes(); - filtered_payload.Initialize(pay_types); - filtered_payload.Slice(payload, true_sel, count); +static void ScatterNestedVector(Vector &vec, UnifiedVectorFormat &col, Vector &rows, data_ptr_t data_locations[], + const SelectionVector &sel, const idx_t count, const idx_t col_offset, + const idx_t col_no, const idx_t vcount) { + // Store pointers to the data in the row + // Do this first because SerializeVector destroys the locations + auto ptrs = FlatVector::GetData(rows); + data_ptr_t validitymask_locations[STANDARD_VECTOR_SIZE]; + for (idx_t i = 0; i < count; i++) { + auto idx = sel.get_index(i); + auto row = ptrs[idx]; + validitymask_locations[i] = row; - Vector filtered_addresses(addresses, true_sel, count); - filtered_addresses.Normalify(count); + Store(data_locations[i], row + col_offset); + } - UpdateStates(aggr, filtered_addresses, filtered_payload, arg_idx, filtered_payload.size()); + // Serialise the data + RowOperations::HeapScatter(vec, vcount, sel, count, col_no, data_locations, validitymask_locations); } -void RowOperations::CombineStates(RowLayout &layout, Vector &sources, Vector &targets, idx_t count) { +void RowOperations::Scatter(DataChunk &columns, UnifiedVectorFormat col_data[], const RowLayout &layout, Vector &rows, + RowDataCollection &string_heap, const SelectionVector &sel, idx_t count) { if (count == 0) { return; } - // Move to the first aggregate states - VectorOperations::AddInPlace(sources, layout.GetAggrOffset(), count); - VectorOperations::AddInPlace(targets, layout.GetAggrOffset(), count); - for (auto &aggr : layout.GetAggregates()) { - D_ASSERT(aggr.function.combine); - aggr.function.combine(sources, targets, aggr.bind_data, count); - - // Move to the next aggregate states - VectorOperations::AddInPlace(sources, aggr.payload_size, count); - VectorOperations::AddInPlace(targets, aggr.payload_size, count); - } -} - -void RowOperations::FinalizeStates(RowLayout &layout, Vector &addresses, DataChunk &result, idx_t aggr_idx) { - // Move to the first aggregate state - VectorOperations::AddInPlace(addresses, layout.GetAggrOffset(), result.size()); - - auto &aggregates = layout.GetAggregates(); - for (idx_t i = 0; i < aggregates.size(); i++) { - auto &target = result.data[aggr_idx + i]; - auto &aggr = aggregates[i]; - aggr.function.finalize(addresses, aggr.bind_data, target, result.size(), 0); - - // Move to the next aggregate state - VectorOperations::AddInPlace(addresses, aggr.payload_size, result.size()); + // Set the validity mask for each row before inserting data + auto ptrs = FlatVector::GetData(rows); + for (idx_t i = 0; i < count; ++i) { + auto row_idx = sel.get_index(i); + auto row = ptrs[row_idx]; + ValidityBytes(row).SetAllValid(layout.ColumnCount()); } -} -} // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/types/row_operations/row_external.cpp -// -// -//===----------------------------------------------------------------------===// - - - -namespace duckdb { + const auto vcount = columns.size(); + auto &offsets = layout.GetOffsets(); + auto &types = layout.GetTypes(); -void RowOperations::SwizzleColumns(const RowLayout &layout, const data_ptr_t base_row_ptr, const idx_t count) { - const idx_t row_width = layout.GetRowWidth(); - data_ptr_t heap_row_ptrs[STANDARD_VECTOR_SIZE]; - idx_t done = 0; - while (done != count) { - const idx_t next = MinValue(count - done, STANDARD_VECTOR_SIZE); - const data_ptr_t row_ptr = base_row_ptr + done * row_width; - // Load heap row pointers - data_ptr_t heap_ptr_ptr = row_ptr + layout.GetHeapPointerOffset(); - for (idx_t i = 0; i < next; i++) { - heap_row_ptrs[i] = Load(heap_ptr_ptr); - heap_ptr_ptr += row_width; - } - // Loop through the blob columns - for (idx_t col_idx = 0; col_idx < layout.ColumnCount(); col_idx++) { - auto physical_type = layout.GetTypes()[col_idx].InternalType(); - if (TypeIsConstantSize(physical_type)) { + // Compute the entry size of the variable size columns + vector handles; + data_ptr_t data_locations[STANDARD_VECTOR_SIZE]; + if (!layout.AllConstant()) { + idx_t entry_sizes[STANDARD_VECTOR_SIZE]; + std::fill_n(entry_sizes, count, sizeof(uint32_t)); + for (idx_t col_no = 0; col_no < types.size(); col_no++) { + if (TypeIsConstantSize(types[col_no].InternalType())) { continue; } - data_ptr_t col_ptr = row_ptr + layout.GetOffsets()[col_idx]; - if (physical_type == PhysicalType::VARCHAR) { - data_ptr_t string_ptr = col_ptr + sizeof(uint32_t) + string_t::PREFIX_LENGTH; - for (idx_t i = 0; i < next; i++) { - if (Load(col_ptr) > string_t::INLINE_LENGTH) { - // Overwrite the string pointer with the within-row offset (if not inlined) - Store(Load(string_ptr) - heap_row_ptrs[i], string_ptr); - } - col_ptr += row_width; - string_ptr += row_width; - } - } else { - // Non-varchar blob columns - for (idx_t i = 0; i < next; i++) { - // Overwrite the column data pointer with the within-row offset - Store(Load(col_ptr) - heap_row_ptrs[i], col_ptr); - col_ptr += row_width; - } + + auto &vec = columns.data[col_no]; + auto &col = col_data[col_no]; + switch (types[col_no].InternalType()) { + case PhysicalType::VARCHAR: + ComputeStringEntrySizes(col, entry_sizes, sel, count); + break; + case PhysicalType::LIST: + case PhysicalType::MAP: + case PhysicalType::STRUCT: + RowOperations::ComputeEntrySizes(vec, col, entry_sizes, vcount, count, sel); + break; + default: + throw InternalException("Unsupported type for RowOperations::Scatter"); } } - done += next; - } -} -void RowOperations::SwizzleHeapPointer(const RowLayout &layout, data_ptr_t row_ptr, const data_ptr_t heap_base_ptr, - const idx_t count) { - const idx_t row_width = layout.GetRowWidth(); - row_ptr += layout.GetHeapPointerOffset(); - idx_t cumulative_offset = 0; - for (idx_t i = 0; i < count; i++) { - Store(cumulative_offset, row_ptr); - cumulative_offset += Load(heap_base_ptr + cumulative_offset); - row_ptr += row_width; - } -} + // Build out the buffer space + string_heap.Build(count, data_locations, entry_sizes); -void RowOperations::UnswizzlePointers(const RowLayout &layout, const data_ptr_t base_row_ptr, - const data_ptr_t base_heap_ptr, const idx_t count) { - const idx_t row_width = layout.GetRowWidth(); - data_ptr_t heap_row_ptrs[STANDARD_VECTOR_SIZE]; - idx_t done = 0; - while (done != count) { - const idx_t next = MinValue(count - done, STANDARD_VECTOR_SIZE); - const data_ptr_t row_ptr = base_row_ptr + done * row_width; - // Restore heap row pointers - data_ptr_t heap_ptr_ptr = row_ptr + layout.GetHeapPointerOffset(); - for (idx_t i = 0; i < next; i++) { - heap_row_ptrs[i] = base_heap_ptr + Load(heap_ptr_ptr); - Store(heap_row_ptrs[i], heap_ptr_ptr); - heap_ptr_ptr += row_width; + // Serialize information that is needed for swizzling if the computation goes out-of-core + const idx_t heap_pointer_offset = layout.GetHeapOffset(); + for (idx_t i = 0; i < count; i++) { + auto row_idx = sel.get_index(i); + auto row = ptrs[row_idx]; + // Pointer to this row in the heap block + Store(data_locations[i], row + heap_pointer_offset); + // Row size is stored in the heap in front of each row + Store(entry_sizes[i], data_locations[i]); + data_locations[i] += sizeof(uint32_t); } - // Loop through the blob columns - for (idx_t col_idx = 0; col_idx < layout.ColumnCount(); col_idx++) { - auto physical_type = layout.GetTypes()[col_idx].InternalType(); - if (TypeIsConstantSize(physical_type)) { - continue; - } - data_ptr_t col_ptr = row_ptr + layout.GetOffsets()[col_idx]; - if (physical_type == PhysicalType::VARCHAR) { - data_ptr_t string_ptr = col_ptr + sizeof(uint32_t) + string_t::PREFIX_LENGTH; - for (idx_t i = 0; i < next; i++) { - if (Load(col_ptr) > string_t::INLINE_LENGTH) { - // Overwrite the string offset with the pointer (if not inlined) - Store(heap_row_ptrs[i] + Load(string_ptr), string_ptr); - } - col_ptr += row_width; - string_ptr += row_width; - } - } else { - // Non-varchar blob columns - for (idx_t i = 0; i < next; i++) { - // Overwrite the column data offset with the pointer - Store(heap_row_ptrs[i] + Load(col_ptr), col_ptr); - col_ptr += row_width; - } - } + } + + for (idx_t col_no = 0; col_no < types.size(); col_no++) { + auto &vec = columns.data[col_no]; + auto &col = col_data[col_no]; + auto col_offset = offsets[col_no]; + + switch (types[col_no].InternalType()) { + case PhysicalType::BOOL: + case PhysicalType::INT8: + TemplatedScatter(col, rows, sel, count, col_offset, col_no); + break; + case PhysicalType::INT16: + TemplatedScatter(col, rows, sel, count, col_offset, col_no); + break; + case PhysicalType::INT32: + TemplatedScatter(col, rows, sel, count, col_offset, col_no); + break; + case PhysicalType::INT64: + TemplatedScatter(col, rows, sel, count, col_offset, col_no); + break; + case PhysicalType::UINT8: + TemplatedScatter(col, rows, sel, count, col_offset, col_no); + break; + case PhysicalType::UINT16: + TemplatedScatter(col, rows, sel, count, col_offset, col_no); + break; + case PhysicalType::UINT32: + TemplatedScatter(col, rows, sel, count, col_offset, col_no); + break; + case PhysicalType::UINT64: + TemplatedScatter(col, rows, sel, count, col_offset, col_no); + break; + case PhysicalType::INT128: + TemplatedScatter(col, rows, sel, count, col_offset, col_no); + break; + case PhysicalType::FLOAT: + TemplatedScatter(col, rows, sel, count, col_offset, col_no); + break; + case PhysicalType::DOUBLE: + TemplatedScatter(col, rows, sel, count, col_offset, col_no); + break; + case PhysicalType::INTERVAL: + TemplatedScatter(col, rows, sel, count, col_offset, col_no); + break; + case PhysicalType::VARCHAR: + ScatterStringVector(col, rows, data_locations, sel, count, col_offset, col_no); + break; + case PhysicalType::LIST: + case PhysicalType::MAP: + case PhysicalType::STRUCT: + ScatterNestedVector(vec, col, rows, data_locations, sel, count, col_offset, col_no, vcount); + break; + default: + throw InternalException("Unsupported type for RowOperations::Scatter"); } - done += next; } } } // namespace duckdb -//===--------------------------------------------------------------------===// -// row_gather.cpp -// Description: This file contains the implementation of the gather operators -//===--------------------------------------------------------------------===// - - //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/operator/constant_operators.hpp +// duckdb/common/serializer/buffered_deserializer.hpp // // //===----------------------------------------------------------------------===// -namespace duckdb { -struct PickLeft { - template - static inline T Operation(T left, T right) { - return left; - } -}; -struct PickRight { - template - static inline T Operation(T left, T right) { - return right; - } -}; -struct NOP { - template - static inline T Operation(T left) { - return left; - } -}; +namespace duckdb { +class ClientContext; -struct ConstantZero { - template - static inline T Operation(T left, T right) { - return 0; - } -}; +class BufferedDeserializer : public Deserializer { +public: + BufferedDeserializer(data_ptr_t ptr, idx_t data_size); + explicit BufferedDeserializer(BufferedSerializer &serializer); -struct ConstantOne { - template - static inline T Operation(T left, T right) { - return 1; - } + data_ptr_t ptr; + data_ptr_t endptr; + +public: + void ReadData(data_ptr_t buffer, uint64_t read_size) override; }; -struct AddOne { - template - static inline T Operation(T left, T right) { - return right + 1; +class BufferentContextDeserializer : public BufferedDeserializer { +public: + BufferentContextDeserializer(ClientContext &context_p, data_ptr_t ptr, idx_t data_size) + : BufferedDeserializer(ptr, data_size), context(context_p) { } + +public: + ClientContext &context; }; } // namespace duckdb +#include + +namespace duckdb { + +BufferedDeserializer::BufferedDeserializer(data_ptr_t ptr, idx_t data_size) : ptr(ptr), endptr(ptr + data_size) { +} + +BufferedDeserializer::BufferedDeserializer(BufferedSerializer &serializer) + : BufferedDeserializer(serializer.data, serializer.maximum_size) { + SetVersion(serializer.GetVersion()); +} + +void BufferedDeserializer::ReadData(data_ptr_t buffer, idx_t read_size) { + if (ptr + read_size > endptr) { + throw SerializationException("Failed to deserialize: not enough data in buffer to fulfill read request"); + } + memcpy(buffer, ptr, read_size); + ptr += read_size; +} + +} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/types/row_data_collection.hpp +// duckdb/common/serializer/buffered_file_reader.hpp // // //===----------------------------------------------------------------------===// @@ -34228,2663 +39756,2093 @@ struct AddOne { - - namespace duckdb { -struct RowDataBlock { - RowDataBlock(BufferManager &buffer_manager, idx_t capacity, idx_t entry_size) - : capacity(capacity), entry_size(entry_size), count(0), byte_offset(0) { - block = buffer_manager.RegisterMemory(capacity * entry_size, false); - } - //! The buffer block handle - shared_ptr block; - //! Capacity (number of entries) and entry size that fit in this block - idx_t capacity; - const idx_t entry_size; - //! Number of entries currently in this block - idx_t count; - //! Write offset (if variable size entries) - idx_t byte_offset; -}; - -struct BlockAppendEntry { - BlockAppendEntry(data_ptr_t baseptr, idx_t count) : baseptr(baseptr), count(count) { - } - data_ptr_t baseptr; - idx_t count; -}; - -class RowDataCollection { +class BufferedFileReader : public Deserializer { public: - RowDataCollection(BufferManager &buffer_manager, idx_t block_capacity, idx_t entry_size, bool keep_pinned = false); + BufferedFileReader(FileSystem &fs, const char *path, FileOpener *opener = nullptr); - //! BufferManager - BufferManager &buffer_manager; - //! The total number of stored entries - idx_t count; - //! The number of entries per block - idx_t block_capacity; - //! Size of entries in the blocks - idx_t entry_size; - //! The blocks holding the main data - vector blocks; - //! The blocks that this collection currently has pinned - vector> pinned_blocks; + FileSystem &fs; + unique_ptr data; + idx_t offset; + idx_t read_data; + unique_ptr handle; public: - idx_t AppendToBlock(RowDataBlock &block, BufferHandle &handle, vector &append_entries, - idx_t remaining, idx_t entry_sizes[]); - vector> Build(idx_t added_count, data_ptr_t key_locations[], idx_t entry_sizes[], - const SelectionVector *sel = FlatVector::IncrementalSelectionVector()); - - void Merge(RowDataCollection &other); + void ReadData(data_ptr_t buffer, uint64_t read_size) override; + //! Returns true if the reader has finished reading the entire file + bool Finished(); - //! The size (in bytes) of this RowDataCollection if it were stored in a single block - idx_t SizeInBytes() const { - idx_t bytes = 0; - if (entry_size == 1) { - for (auto &block : blocks) { - bytes += block.byte_offset; - } - } else { - bytes = count * entry_size; - } - return MaxValue(bytes, (idx_t)Storage::BLOCK_SIZE); + idx_t FileSize() { + return file_size; } private: - mutex rdc_lock; - - //! Whether the blocks should stay pinned (necessary for e.g. a heap) - const bool keep_pinned; + idx_t file_size; + idx_t total_read; }; } // namespace duckdb -namespace duckdb { - -using ValidityBytes = RowLayout::ValidityBytes; - -template -static void TemplatedGatherLoop(Vector &rows, const SelectionVector &row_sel, Vector &col, - const SelectionVector &col_sel, idx_t count, idx_t col_offset, idx_t col_no, - idx_t build_size) { - // Precompute mask indexes - idx_t entry_idx; - idx_t idx_in_entry; - ValidityBytes::GetEntryIndex(col_no, entry_idx, idx_in_entry); - - auto ptrs = FlatVector::GetData(rows); - auto data = FlatVector::GetData(col); - auto &col_mask = FlatVector::Validity(col); - - for (idx_t i = 0; i < count; i++) { - auto row_idx = row_sel.get_index(i); - auto row = ptrs[row_idx]; - auto col_idx = col_sel.get_index(i); - data[col_idx] = Load(row + col_offset); - ValidityBytes row_mask(row); - if (!row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry)) { - if (build_size > STANDARD_VECTOR_SIZE && col_mask.AllValid()) { - //! We need to initialize the mask with the vector size. - col_mask.Initialize(build_size); - } - col_mask.SetInvalid(col_idx); - } - } -} - -static void GatherNestedVector(Vector &rows, const SelectionVector &row_sel, Vector &col, - const SelectionVector &col_sel, idx_t count, idx_t col_offset, idx_t col_no) { - auto ptrs = FlatVector::GetData(rows); - - // Build the gather locations - auto data_locations = unique_ptr(new data_ptr_t[count]); - auto mask_locations = unique_ptr(new data_ptr_t[count]); - for (idx_t i = 0; i < count; i++) { - auto row_idx = row_sel.get_index(i); - mask_locations[i] = ptrs[row_idx]; - data_locations[i] = Load(ptrs[row_idx] + col_offset); - } - // Deserialise into the selected locations - RowOperations::HeapGather(col, count, col_sel, col_no, data_locations.get(), mask_locations.get()); -} +#include +#include -void RowOperations::Gather(Vector &rows, const SelectionVector &row_sel, Vector &col, const SelectionVector &col_sel, - const idx_t count, const idx_t col_offset, const idx_t col_no, const idx_t build_size) { - D_ASSERT(rows.GetVectorType() == VectorType::FLAT_VECTOR); - D_ASSERT(rows.GetType().id() == LogicalTypeId::POINTER); // "Cannot gather from non-pointer type!" +namespace duckdb { - col.SetVectorType(VectorType::FLAT_VECTOR); - switch (col.GetType().InternalType()) { - case PhysicalType::UINT8: - TemplatedGatherLoop(rows, row_sel, col, col_sel, count, col_offset, col_no, build_size); - break; - case PhysicalType::UINT16: - TemplatedGatherLoop(rows, row_sel, col, col_sel, count, col_offset, col_no, build_size); - break; - case PhysicalType::UINT32: - TemplatedGatherLoop(rows, row_sel, col, col_sel, count, col_offset, col_no, build_size); - break; - case PhysicalType::UINT64: - TemplatedGatherLoop(rows, row_sel, col, col_sel, count, col_offset, col_no, build_size); - break; - case PhysicalType::BOOL: - case PhysicalType::INT8: - TemplatedGatherLoop(rows, row_sel, col, col_sel, count, col_offset, col_no, build_size); - break; - case PhysicalType::INT16: - TemplatedGatherLoop(rows, row_sel, col, col_sel, count, col_offset, col_no, build_size); - break; - case PhysicalType::INT32: - TemplatedGatherLoop(rows, row_sel, col, col_sel, count, col_offset, col_no, build_size); - break; - case PhysicalType::INT64: - TemplatedGatherLoop(rows, row_sel, col, col_sel, count, col_offset, col_no, build_size); - break; - case PhysicalType::INT128: - TemplatedGatherLoop(rows, row_sel, col, col_sel, count, col_offset, col_no, build_size); - break; - case PhysicalType::FLOAT: - TemplatedGatherLoop(rows, row_sel, col, col_sel, count, col_offset, col_no, build_size); - break; - case PhysicalType::DOUBLE: - TemplatedGatherLoop(rows, row_sel, col, col_sel, count, col_offset, col_no, build_size); - break; - case PhysicalType::INTERVAL: - TemplatedGatherLoop(rows, row_sel, col, col_sel, count, col_offset, col_no, build_size); - break; - case PhysicalType::VARCHAR: - TemplatedGatherLoop(rows, row_sel, col, col_sel, count, col_offset, col_no, build_size); - break; - case PhysicalType::LIST: - case PhysicalType::MAP: - case PhysicalType::STRUCT: - GatherNestedVector(rows, row_sel, col, col_sel, count, col_offset, col_no); - break; - default: - throw InternalException("Unimplemented type for RowOperations::Gather"); - } +BufferedFileReader::BufferedFileReader(FileSystem &fs, const char *path, FileOpener *opener) + : fs(fs), data(unique_ptr(new data_t[FILE_BUFFER_SIZE])), offset(0), read_data(0), total_read(0) { + handle = + fs.OpenFile(path, FileFlags::FILE_FLAGS_READ, FileLockType::READ_LOCK, FileSystem::DEFAULT_COMPRESSION, opener); + file_size = fs.GetFileSize(*handle); } -template -static void TemplatedFullScanLoop(Vector &rows, Vector &col, idx_t count, idx_t col_offset, idx_t col_no) { - // Precompute mask indexes - idx_t entry_idx; - idx_t idx_in_entry; - ValidityBytes::GetEntryIndex(col_no, entry_idx, idx_in_entry); - - auto ptrs = FlatVector::GetData(rows); - auto data = FlatVector::GetData(col); - // auto &col_mask = FlatVector::Validity(col); - - for (idx_t i = 0; i < count; i++) { - auto row = ptrs[i]; - data[i] = Load(row + col_offset); - ValidityBytes row_mask(row); - if (!row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry)) { - throw InternalException("Null value comparisons not implemented for perfect hash table yet"); - // col_mask.SetInvalid(i); +void BufferedFileReader::ReadData(data_ptr_t target_buffer, uint64_t read_size) { + // first copy anything we can from the buffer + data_ptr_t end_ptr = target_buffer + read_size; + while (true) { + idx_t to_read = MinValue(end_ptr - target_buffer, read_data - offset); + if (to_read > 0) { + memcpy(target_buffer, data.get() + offset, to_read); + offset += to_read; + target_buffer += to_read; + } + if (target_buffer < end_ptr) { + D_ASSERT(offset == read_data); + total_read += read_data; + // did not finish reading yet but exhausted buffer + // read data into buffer + offset = 0; + read_data = fs.Read(*handle, data.get(), FILE_BUFFER_SIZE); + if (read_data == 0) { + throw SerializationException("not enough data in file to deserialize result"); + } + } else { + return; } } } -void RowOperations::FullScanColumn(const RowLayout &layout, Vector &rows, Vector &col, idx_t count, idx_t col_no) { - const auto col_offset = layout.GetOffsets()[col_no]; - col.SetVectorType(VectorType::FLAT_VECTOR); - switch (col.GetType().InternalType()) { - case PhysicalType::UINT8: - TemplatedFullScanLoop(rows, col, count, col_offset, col_no); - break; - case PhysicalType::UINT16: - TemplatedFullScanLoop(rows, col, count, col_offset, col_no); - break; - case PhysicalType::UINT32: - TemplatedFullScanLoop(rows, col, count, col_offset, col_no); - break; - case PhysicalType::UINT64: - TemplatedFullScanLoop(rows, col, count, col_offset, col_no); - break; - case PhysicalType::INT8: - TemplatedFullScanLoop(rows, col, count, col_offset, col_no); - break; - case PhysicalType::INT16: - TemplatedFullScanLoop(rows, col, count, col_offset, col_no); - break; - case PhysicalType::INT32: - TemplatedFullScanLoop(rows, col, count, col_offset, col_no); - break; - case PhysicalType::INT64: - TemplatedFullScanLoop(rows, col, count, col_offset, col_no); - break; - default: - throw NotImplementedException("Unimplemented type for RowOperations::FullScanColumn"); - } +bool BufferedFileReader::Finished() { + return total_read + offset == file_size; } } // namespace duckdb +#include namespace duckdb { -using ValidityBytes = TemplatedValidityMask; +// Remove this when we switch C++17: https://stackoverflow.com/a/53350948 +constexpr uint8_t BufferedFileWriter::DEFAULT_OPEN_FLAGS; -template -static void TemplatedHeapGather(Vector &v, const idx_t count, const SelectionVector &sel, data_ptr_t *key_locations) { - auto target = FlatVector::GetData(v); +BufferedFileWriter::BufferedFileWriter(FileSystem &fs, const string &path_p, uint8_t open_flags, FileOpener *opener) + : fs(fs), path(path_p), data(unique_ptr(new data_t[FILE_BUFFER_SIZE])), offset(0), total_written(0) { + handle = fs.OpenFile(path, open_flags, FileLockType::WRITE_LOCK, FileSystem::DEFAULT_COMPRESSION, opener); +} - for (idx_t i = 0; i < count; ++i) { - const auto col_idx = sel.get_index(i); - target[col_idx] = Load(key_locations[i]); - key_locations[i] += sizeof(T); - } +int64_t BufferedFileWriter::GetFileSize() { + return fs.GetFileSize(*handle); } -static void HeapGatherStringVector(Vector &v, const idx_t vcount, const SelectionVector &sel, - data_ptr_t *key_locations) { - const auto &validity = FlatVector::Validity(v); - auto target = FlatVector::GetData(v); +idx_t BufferedFileWriter::GetTotalWritten() { + return total_written + offset; +} - for (idx_t i = 0; i < vcount; i++) { - const auto col_idx = sel.get_index(i); - if (!validity.RowIsValid(col_idx)) { - continue; +void BufferedFileWriter::WriteData(const_data_ptr_t buffer, uint64_t write_size) { + // first copy anything we can from the buffer + const_data_ptr_t end_ptr = buffer + write_size; + while (buffer < end_ptr) { + idx_t to_write = MinValue((end_ptr - buffer), FILE_BUFFER_SIZE - offset); + D_ASSERT(to_write > 0); + memcpy(data.get() + offset, buffer, to_write); + offset += to_write; + buffer += to_write; + if (offset == FILE_BUFFER_SIZE) { + Flush(); } - auto len = Load(key_locations[i]); - key_locations[i] += sizeof(uint32_t); - target[col_idx] = StringVector::AddStringOrBlob(v, string_t((const char *)key_locations[i], len)); - key_locations[i] += len; } } -static void HeapGatherStructVector(Vector &v, const idx_t vcount, const SelectionVector &sel, - data_ptr_t *key_locations) { - // struct must have a validitymask for its fields - auto &child_types = StructType::GetChildTypes(v.GetType()); - const idx_t struct_validitymask_size = (child_types.size() + 7) / 8; - data_ptr_t struct_validitymask_locations[STANDARD_VECTOR_SIZE]; - for (idx_t i = 0; i < vcount; i++) { - // use key_locations as the validitymask, and create struct_key_locations - struct_validitymask_locations[i] = key_locations[i]; - key_locations[i] += struct_validitymask_size; - } - - // now deserialize into the struct vectors - auto &children = StructVector::GetEntries(v); - for (idx_t i = 0; i < child_types.size(); i++) { - RowOperations::HeapGather(*children[i], vcount, sel, i, key_locations, struct_validitymask_locations); +void BufferedFileWriter::Flush() { + if (offset == 0) { + return; } + fs.Write(*handle, data.get(), offset); + total_written += offset; + offset = 0; } -static void HeapGatherListVector(Vector &v, const idx_t vcount, const SelectionVector &sel, data_ptr_t *key_locations) { - const auto &validity = FlatVector::Validity(v); - - auto child_type = ListType::GetChildType(v.GetType()); - auto list_data = ListVector::GetData(v); - data_ptr_t list_entry_locations[STANDARD_VECTOR_SIZE]; - - uint64_t entry_offset = ListVector::GetListSize(v); - for (idx_t i = 0; i < vcount; i++) { - const auto col_idx = sel.get_index(i); - if (!validity.RowIsValid(col_idx)) { - continue; - } - // read list length - auto entry_remaining = Load(key_locations[i]); - key_locations[i] += sizeof(uint64_t); - // set list entry attributes - list_data[col_idx].length = entry_remaining; - list_data[col_idx].offset = entry_offset; - // skip over the validity mask - data_ptr_t validitymask_location = key_locations[i]; - idx_t offset_in_byte = 0; - key_locations[i] += (entry_remaining + 7) / 8; - // entry sizes - data_ptr_t var_entry_size_ptr = nullptr; - if (!TypeIsConstantSize(child_type.InternalType())) { - var_entry_size_ptr = key_locations[i]; - key_locations[i] += entry_remaining * sizeof(idx_t); - } - - // now read the list data - while (entry_remaining > 0) { - auto next = MinValue(entry_remaining, (idx_t)STANDARD_VECTOR_SIZE); +void BufferedFileWriter::Sync() { + Flush(); + handle->Sync(); +} - // initialize a new vector to append - Vector append_vector(v.GetType()); - append_vector.SetVectorType(v.GetVectorType()); +void BufferedFileWriter::Truncate(int64_t size) { + // truncate the physical file on disk + handle->Truncate(size); + // reset anything written in the buffer + offset = 0; +} - auto &list_vec_to_append = ListVector::GetEntry(append_vector); +} // namespace duckdb - // set validity - //! Since we are constructing the vector, this will always be a flat vector. - auto &append_validity = FlatVector::Validity(list_vec_to_append); - for (idx_t entry_idx = 0; entry_idx < next; entry_idx++) { - append_validity.Set(entry_idx, *(validitymask_location) & (1 << offset_in_byte)); - if (++offset_in_byte == 8) { - validitymask_location++; - offset_in_byte = 0; - } - } - // compute entry sizes and set locations where the list entries are - if (TypeIsConstantSize(child_type.InternalType())) { - // constant size list entries - const idx_t type_size = GetTypeIdSize(child_type.InternalType()); - for (idx_t entry_idx = 0; entry_idx < next; entry_idx++) { - list_entry_locations[entry_idx] = key_locations[i]; - key_locations[i] += type_size; - } - } else { - // variable size list entries - for (idx_t entry_idx = 0; entry_idx < next; entry_idx++) { - list_entry_locations[entry_idx] = key_locations[i]; - key_locations[i] += Load(var_entry_size_ptr); - var_entry_size_ptr += sizeof(idx_t); - } - } +#include - // now deserialize and add to listvector - RowOperations::HeapGather(list_vec_to_append, next, *FlatVector::IncrementalSelectionVector(), 0, - list_entry_locations, nullptr); - ListVector::Append(v, list_vec_to_append, next); +namespace duckdb { - // update for next iteration - entry_remaining -= next; - entry_offset += next; - } - } +BufferedSerializer::BufferedSerializer(idx_t maximum_size) + : BufferedSerializer(unique_ptr(new data_t[maximum_size]), maximum_size) { } -void RowOperations::HeapGather(Vector &v, const idx_t &vcount, const SelectionVector &sel, const idx_t &col_no, - data_ptr_t *key_locations, data_ptr_t *validitymask_locations) { - v.SetVectorType(VectorType::FLAT_VECTOR); +BufferedSerializer::BufferedSerializer(unique_ptr data, idx_t size) : maximum_size(size), data(data.get()) { + blob.size = 0; + blob.data = move(data); +} - auto &validity = FlatVector::Validity(v); - if (validitymask_locations) { - // Precompute mask indexes - idx_t entry_idx; - idx_t idx_in_entry; - ValidityBytes::GetEntryIndex(col_no, entry_idx, idx_in_entry); +BufferedSerializer::BufferedSerializer(data_ptr_t data, idx_t size) : maximum_size(size), data(data) { + blob.size = 0; +} - for (idx_t i = 0; i < vcount; i++) { - ValidityBytes row_mask(validitymask_locations[i]); - const auto valid = row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry); - const auto col_idx = sel.get_index(i); - validity.Set(col_idx, valid); - } +void BufferedSerializer::WriteData(const_data_ptr_t buffer, idx_t write_size) { + if (blob.size + write_size >= maximum_size) { + do { + maximum_size *= 2; + } while (blob.size + write_size > maximum_size); + auto new_data = new data_t[maximum_size]; + memcpy(new_data, data, blob.size); + data = new_data; + blob.data = unique_ptr(new_data); } - auto type = v.GetType().InternalType(); - switch (type) { - case PhysicalType::BOOL: - case PhysicalType::INT8: - TemplatedHeapGather(v, vcount, sel, key_locations); - break; - case PhysicalType::INT16: - TemplatedHeapGather(v, vcount, sel, key_locations); - break; - case PhysicalType::INT32: - TemplatedHeapGather(v, vcount, sel, key_locations); - break; - case PhysicalType::INT64: - TemplatedHeapGather(v, vcount, sel, key_locations); - break; - case PhysicalType::UINT8: - TemplatedHeapGather(v, vcount, sel, key_locations); - break; - case PhysicalType::UINT16: - TemplatedHeapGather(v, vcount, sel, key_locations); - break; - case PhysicalType::UINT32: - TemplatedHeapGather(v, vcount, sel, key_locations); - break; - case PhysicalType::UINT64: - TemplatedHeapGather(v, vcount, sel, key_locations); - break; - case PhysicalType::INT128: - TemplatedHeapGather(v, vcount, sel, key_locations); - break; - case PhysicalType::FLOAT: - TemplatedHeapGather(v, vcount, sel, key_locations); - break; - case PhysicalType::DOUBLE: - TemplatedHeapGather(v, vcount, sel, key_locations); - break; - case PhysicalType::INTERVAL: - TemplatedHeapGather(v, vcount, sel, key_locations); - break; - case PhysicalType::VARCHAR: - HeapGatherStringVector(v, vcount, sel, key_locations); - break; - case PhysicalType::STRUCT: - HeapGatherStructVector(v, vcount, sel, key_locations); - break; - case PhysicalType::LIST: - HeapGatherListVector(v, vcount, sel, key_locations); - break; - default: - throw NotImplementedException("Unimplemented deserialize from row-format"); - } + memcpy(data + blob.size, buffer, write_size); + blob.size += write_size; } } // namespace duckdb - - namespace duckdb { -using ValidityBytes = TemplatedValidityMask; - -static void ComputeStringEntrySizes(VectorData &vdata, idx_t entry_sizes[], const idx_t ser_count, - const SelectionVector &sel, const idx_t offset) { - auto strings = (string_t *)vdata.data; - for (idx_t i = 0; i < ser_count; i++) { - auto idx = sel.get_index(i); - auto str_idx = vdata.sel->get_index(idx) + offset; - if (vdata.validity.RowIsValid(str_idx)) { - entry_sizes[i] += sizeof(uint32_t) + strings[str_idx].GetSize(); - } +template <> +string Deserializer::Read() { + uint32_t size = Read(); + if (size == 0) { + return string(); } + auto buffer = unique_ptr(new data_t[size]); + ReadData(buffer.get(), size); + return string((char *)buffer.get(), size); } -static void ComputeStructEntrySizes(Vector &v, idx_t entry_sizes[], idx_t vcount, idx_t ser_count, - const SelectionVector &sel, idx_t offset) { - // obtain child vectors - idx_t num_children; - auto &children = StructVector::GetEntries(v); - num_children = children.size(); - // add struct validitymask size - const idx_t struct_validitymask_size = (num_children + 7) / 8; - for (idx_t i = 0; i < ser_count; i++) { - entry_sizes[i] += struct_validitymask_size; - } - // compute size of child vectors - for (auto &struct_vector : children) { - RowOperations::ComputeEntrySizes(*struct_vector, entry_sizes, vcount, ser_count, sel, offset); +void Deserializer::ReadStringVector(vector &list) { + uint32_t sz = Read(); + list.resize(sz); + for (idx_t i = 0; i < sz; i++) { + list[i] = Read(); } } -static void ComputeListEntrySizes(Vector &v, VectorData &vdata, idx_t entry_sizes[], idx_t ser_count, - const SelectionVector &sel, idx_t offset) { - auto list_data = ListVector::GetData(v); - auto &child_vector = ListVector::GetEntry(v); - idx_t list_entry_sizes[STANDARD_VECTOR_SIZE]; - for (idx_t i = 0; i < ser_count; i++) { - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; - if (vdata.validity.RowIsValid(source_idx)) { - auto list_entry = list_data[source_idx]; +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/sort/comparators.hpp +// +// +//===----------------------------------------------------------------------===// - // make room for list length, list validitymask - entry_sizes[i] += sizeof(list_entry.length); - entry_sizes[i] += (list_entry.length + 7) / 8; - // serialize size of each entry (if non-constant size) - if (!TypeIsConstantSize(ListType::GetChildType(v.GetType()).InternalType())) { - entry_sizes[i] += list_entry.length * sizeof(list_entry.length); - } - // compute size of each the elements in list_entry and sum them - auto entry_remaining = list_entry.length; - auto entry_offset = list_entry.offset; - while (entry_remaining > 0) { - // the list entry can span multiple vectors - auto next = MinValue((idx_t)STANDARD_VECTOR_SIZE, entry_remaining); - // compute and add to the total - std::fill_n(list_entry_sizes, next, 0); - RowOperations::ComputeEntrySizes(child_vector, list_entry_sizes, next, next, - *FlatVector::IncrementalSelectionVector(), entry_offset); - for (idx_t list_idx = 0; list_idx < next; list_idx++) { - entry_sizes[i] += list_entry_sizes[list_idx]; - } - // update for next iteration - entry_remaining -= next; - entry_offset += next; - } - } - } -} -void RowOperations::ComputeEntrySizes(Vector &v, VectorData &vdata, idx_t entry_sizes[], idx_t vcount, idx_t ser_count, - const SelectionVector &sel, idx_t offset) { - const auto physical_type = v.GetType().InternalType(); - if (TypeIsConstantSize(physical_type)) { - const auto type_size = GetTypeIdSize(physical_type); - for (idx_t i = 0; i < ser_count; i++) { - entry_sizes[i] += type_size; - } - } else { - switch (physical_type) { - case PhysicalType::VARCHAR: - ComputeStringEntrySizes(vdata, entry_sizes, ser_count, sel, offset); - break; - case PhysicalType::STRUCT: - ComputeStructEntrySizes(v, entry_sizes, vcount, ser_count, sel, offset); - break; - case PhysicalType::LIST: - ComputeListEntrySizes(v, vdata, entry_sizes, ser_count, sel, offset); - break; - default: - // LCOV_EXCL_START - throw NotImplementedException("Column with variable size type %s cannot be serialized to row-format", - v.GetType().ToString()); - // LCOV_EXCL_STOP - } - } -} +namespace duckdb { -void RowOperations::ComputeEntrySizes(Vector &v, idx_t entry_sizes[], idx_t vcount, idx_t ser_count, - const SelectionVector &sel, idx_t offset) { - VectorData vdata; - v.Orrify(vcount, vdata); - ComputeEntrySizes(v, vdata, entry_sizes, vcount, ser_count, sel, offset); -} +struct SortLayout; +struct SBScanState; -template -static void TemplatedHeapScatter(VectorData &vdata, const SelectionVector &sel, idx_t count, idx_t col_idx, - data_ptr_t *key_locations, data_ptr_t *validitymask_locations, idx_t offset) { - auto source = (T *)vdata.data; - if (!validitymask_locations) { - for (idx_t i = 0; i < count; i++) { - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; +using ValidityBytes = RowLayout::ValidityBytes; - auto target = (T *)key_locations[i]; - Store(source[source_idx], (data_ptr_t)target); - key_locations[i] += sizeof(T); - } - } else { - idx_t entry_idx; - idx_t idx_in_entry; - ValidityBytes::GetEntryIndex(col_idx, entry_idx, idx_in_entry); - const auto bit = ~(1UL << idx_in_entry); - for (idx_t i = 0; i < count; i++) { - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; +struct Comparators { +public: + //! Whether a tie between two blobs can be broken + static bool TieIsBreakable(const idx_t &col_idx, const data_ptr_t row_ptr, const RowLayout &row_layout); + //! Compares the tuples that a being read from in the 'left' and 'right blocks during merge sort + //! (only in case we cannot simply 'memcmp' - if there are blob columns) + static int CompareTuple(const SBScanState &left, const SBScanState &right, const data_ptr_t &l_ptr, + const data_ptr_t &r_ptr, const SortLayout &sort_layout, const bool &external_sort); + //! Compare two blob values + static int CompareVal(const data_ptr_t l_ptr, const data_ptr_t r_ptr, const LogicalType &type); - auto target = (T *)key_locations[i]; - Store(source[source_idx], (data_ptr_t)target); - key_locations[i] += sizeof(T); +private: + //! Compares two blob values that were initially tied by their prefix + static int BreakBlobTie(const idx_t &tie_col, const SBScanState &left, const SBScanState &right, + const SortLayout &sort_layout, const bool &external); + //! Compare two fixed-size values + template + static int TemplatedCompareVal(const data_ptr_t &left_ptr, const data_ptr_t &right_ptr); - // set the validitymask - if (!vdata.validity.RowIsValid(source_idx)) { - *(validitymask_locations[i] + entry_idx) &= bit; - } - } - } -} + //! Compare two values at the pointers (can be recursive if nested type) + static int CompareValAndAdvance(data_ptr_t &l_ptr, data_ptr_t &r_ptr, const LogicalType &type); + //! Compares two fixed-size values at the given pointers + template + static int TemplatedCompareAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr); + //! Compares two string values at the given pointers + static int CompareStringAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr); + //! Compares two struct values at the given pointers (recursive) + static int CompareStructAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr, + const child_list_t &types); + //! Compare two list values at the pointers (can be recursive if nested type) + static int CompareListAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr, const LogicalType &type); + //! Compares a list of fixed-size values + template + static int TemplatedCompareListLoop(data_ptr_t &left_ptr, data_ptr_t &right_ptr, const ValidityBytes &left_validity, + const ValidityBytes &right_validity, const idx_t &count); -static void HeapScatterStringVector(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, idx_t col_idx, - data_ptr_t *key_locations, data_ptr_t *validitymask_locations, idx_t offset) { - VectorData vdata; - v.Orrify(vcount, vdata); + //! Unwizzles an offset into a pointer + static void UnswizzleSingleValue(data_ptr_t data_ptr, const data_ptr_t &heap_ptr, const LogicalType &type); + //! Swizzles a pointer into an offset + static void SwizzleSingleValue(data_ptr_t data_ptr, const data_ptr_t &heap_ptr, const LogicalType &type); +}; - auto strings = (string_t *)vdata.data; - if (!validitymask_locations) { - for (idx_t i = 0; i < ser_count; i++) { - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; - if (vdata.validity.RowIsValid(source_idx)) { - auto &string_entry = strings[source_idx]; - // store string size - Store(string_entry.GetSize(), key_locations[i]); - key_locations[i] += sizeof(uint32_t); - // store the string - memcpy(key_locations[i], string_entry.GetDataUnsafe(), string_entry.GetSize()); - key_locations[i] += string_entry.GetSize(); - } - } - } else { - idx_t entry_idx; - idx_t idx_in_entry; - ValidityBytes::GetEntryIndex(col_idx, entry_idx, idx_in_entry); - const auto bit = ~(1UL << idx_in_entry); - for (idx_t i = 0; i < ser_count; i++) { - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; - if (vdata.validity.RowIsValid(source_idx)) { - auto &string_entry = strings[source_idx]; - // store string size - Store(string_entry.GetSize(), key_locations[i]); - key_locations[i] += sizeof(uint32_t); - // store the string - memcpy(key_locations[i], string_entry.GetDataUnsafe(), string_entry.GetSize()); - key_locations[i] += string_entry.GetSize(); - } else { - // set the validitymask - *(validitymask_locations[i] + entry_idx) &= bit; - } - } - } -} +} // namespace duckdb -static void HeapScatterStructVector(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, idx_t col_idx, - data_ptr_t *key_locations, data_ptr_t *validitymask_locations, idx_t offset) { - VectorData vdata; - v.Orrify(vcount, vdata); - auto &children = StructVector::GetEntries(v); - idx_t num_children = children.size(); - // the whole struct itself can be NULL - idx_t entry_idx; - idx_t idx_in_entry; - ValidityBytes::GetEntryIndex(col_idx, entry_idx, idx_in_entry); - const auto bit = ~(1UL << idx_in_entry); +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/sort/sort.hpp +// +// +//===----------------------------------------------------------------------===// - // struct must have a validitymask for its fields - const idx_t struct_validitymask_size = (num_children + 7) / 8; - data_ptr_t struct_validitymask_locations[STANDARD_VECTOR_SIZE]; - for (idx_t i = 0; i < ser_count; i++) { - // initialize the struct validity mask - struct_validitymask_locations[i] = key_locations[i]; - memset(struct_validitymask_locations[i], -1, struct_validitymask_size); - key_locations[i] += struct_validitymask_size; - // set whether the whole struct is null - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; - if (validitymask_locations && !vdata.validity.RowIsValid(source_idx)) { - *(validitymask_locations[i] + entry_idx) &= bit; - } - } - // now serialize the struct vectors - for (idx_t i = 0; i < children.size(); i++) { - auto &struct_vector = *children[i]; - RowOperations::HeapScatter(struct_vector, vcount, sel, ser_count, i, key_locations, - struct_validitymask_locations, offset); - } -} +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/sort/sorted_block.hpp +// +// +//===----------------------------------------------------------------------===// -static void HeapScatterListVector(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, idx_t col_no, - data_ptr_t *key_locations, data_ptr_t *validitymask_locations, idx_t offset) { - VectorData vdata; - v.Orrify(vcount, vdata); - idx_t entry_idx; - idx_t idx_in_entry; - ValidityBytes::GetEntryIndex(col_no, entry_idx, idx_in_entry); - auto list_data = ListVector::GetData(v); - auto &child_vector = ListVector::GetEntry(v); - VectorData list_vdata; - child_vector.Orrify(ListVector::GetListSize(v), list_vdata); - auto child_type = ListType::GetChildType(v.GetType()).InternalType(); - idx_t list_entry_sizes[STANDARD_VECTOR_SIZE]; - data_ptr_t list_entry_locations[STANDARD_VECTOR_SIZE]; - for (idx_t i = 0; i < ser_count; i++) { - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; - if (!vdata.validity.RowIsValid(source_idx)) { - if (validitymask_locations) { - // set the row validitymask for this column to invalid - ValidityBytes row_mask(validitymask_locations[i]); - row_mask.SetInvalidUnsafe(entry_idx, idx_in_entry); - } - continue; - } - auto list_entry = list_data[source_idx]; +namespace duckdb { - // store list length - Store(list_entry.length, key_locations[i]); - key_locations[i] += sizeof(list_entry.length); +class BufferManager; +struct RowDataBlock; +struct SortLayout; +struct GlobalSortState; - // make room for the validitymask - data_ptr_t list_validitymask_location = key_locations[i]; - idx_t entry_offset_in_byte = 0; - idx_t validitymask_size = (list_entry.length + 7) / 8; - memset(list_validitymask_location, -1, validitymask_size); - key_locations[i] += validitymask_size; +enum class SortedDataType { BLOB, PAYLOAD }; - // serialize size of each entry (if non-constant size) - data_ptr_t var_entry_size_ptr = nullptr; - if (!TypeIsConstantSize(child_type)) { - var_entry_size_ptr = key_locations[i]; - key_locations[i] += list_entry.length * sizeof(idx_t); - } +//! Object that holds sorted rows, and an accompanying heap if there are blobs +struct SortedData { +public: + SortedData(SortedDataType type, const RowLayout &layout, BufferManager &buffer_manager, GlobalSortState &state); + //! Number of rows that this object holds + idx_t Count(); + //! Initialize new block to write to + void CreateBlock(); + //! Create a slice that holds the rows between the start and end indices + unique_ptr CreateSlice(idx_t start_block_index, idx_t end_block_index, idx_t end_entry_index); + //! Unswizzles all + void Unswizzle(); - auto entry_remaining = list_entry.length; - auto entry_offset = list_entry.offset; - while (entry_remaining > 0) { - // the list entry can span multiple vectors - auto next = MinValue((idx_t)STANDARD_VECTOR_SIZE, entry_remaining); +public: + const SortedDataType type; + //! Layout of this data + const RowLayout layout; + //! Data and heap blocks + vector> data_blocks; + vector> heap_blocks; + //! Whether the pointers in this sorted data are swizzled + bool swizzled; - // serialize list validity - for (idx_t entry_idx = 0; entry_idx < next; entry_idx++) { - auto list_idx = list_vdata.sel->get_index(entry_idx) + entry_offset; - if (!list_vdata.validity.RowIsValid(list_idx)) { - *(list_validitymask_location) &= ~(1UL << entry_offset_in_byte); - } - if (++entry_offset_in_byte == 8) { - list_validitymask_location++; - entry_offset_in_byte = 0; - } - } +private: + //! The buffer manager + BufferManager &buffer_manager; + //! The global state + GlobalSortState &state; +}; - if (TypeIsConstantSize(child_type)) { - // constant size list entries: set list entry locations - const idx_t type_size = GetTypeIdSize(child_type); - for (idx_t entry_idx = 0; entry_idx < next; entry_idx++) { - list_entry_locations[entry_idx] = key_locations[i]; - key_locations[i] += type_size; - } - } else { - // variable size list entries: compute entry sizes and set list entry locations - std::fill_n(list_entry_sizes, next, 0); - RowOperations::ComputeEntrySizes(child_vector, list_entry_sizes, next, next, - *FlatVector::IncrementalSelectionVector(), entry_offset); - for (idx_t entry_idx = 0; entry_idx < next; entry_idx++) { - list_entry_locations[entry_idx] = key_locations[i]; - key_locations[i] += list_entry_sizes[entry_idx]; - Store(list_entry_sizes[entry_idx], var_entry_size_ptr); - var_entry_size_ptr += sizeof(idx_t); - } - } +//! Block that holds sorted rows: radix, blob and payload data +struct SortedBlock { +public: + SortedBlock(BufferManager &buffer_manager, GlobalSortState &gstate); + //! Number of rows that this object holds + idx_t Count() const; + //! Initialize this block to write data to + void InitializeWrite(); + //! Init new block to write to + void CreateBlock(); + //! Fill this sorted block by appending the blocks held by a vector of sorted blocks + void AppendSortedBlocks(vector> &sorted_blocks); + //! Locate the block and entry index of a row in this block, + //! given an index between 0 and the total number of rows in this block + void GlobalToLocalIndex(const idx_t &global_idx, idx_t &local_block_index, idx_t &local_entry_index); + //! Create a slice that holds the rows between the start and end indices + unique_ptr CreateSlice(const idx_t start, const idx_t end, idx_t &entry_idx); - // now serialize to the locations - RowOperations::HeapScatter(child_vector, ListVector::GetListSize(v), - *FlatVector::IncrementalSelectionVector(), next, 0, list_entry_locations, - nullptr, entry_offset); + //! Size (in bytes) of the heap of this block + idx_t HeapSize() const; + //! Total size (in bytes) of this block + idx_t SizeInBytes() const; - // update for next iteration - entry_remaining -= next; - entry_offset += next; - } - } -} +public: + //! Radix/memcmp sortable data + vector> radix_sorting_data; + //! Variable sized sorting data + unique_ptr blob_sorting_data; + //! Payload data + unique_ptr payload_data; -void RowOperations::HeapScatter(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, idx_t col_idx, - data_ptr_t *key_locations, data_ptr_t *validitymask_locations, idx_t offset) { - if (TypeIsConstantSize(v.GetType().InternalType())) { - VectorData vdata; - v.Orrify(vcount, vdata); - RowOperations::HeapScatterVData(vdata, v.GetType().InternalType(), sel, ser_count, col_idx, key_locations, - validitymask_locations, offset); - } else { - switch (v.GetType().InternalType()) { - case PhysicalType::VARCHAR: - HeapScatterStringVector(v, vcount, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - case PhysicalType::STRUCT: - HeapScatterStructVector(v, vcount, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - case PhysicalType::LIST: - HeapScatterListVector(v, vcount, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - default: - // LCOV_EXCL_START - throw NotImplementedException("Serialization of variable length vector with type %s", - v.GetType().ToString()); - // LCOV_EXCL_STOP - } - } -} +private: + //! Buffer manager, global state, and sorting layout constants + BufferManager &buffer_manager; + GlobalSortState &state; + const SortLayout &sort_layout; + const RowLayout &payload_layout; +}; -void RowOperations::HeapScatterVData(VectorData &vdata, PhysicalType type, const SelectionVector &sel, idx_t ser_count, - idx_t col_idx, data_ptr_t *key_locations, data_ptr_t *validitymask_locations, - idx_t offset) { - switch (type) { - case PhysicalType::BOOL: - case PhysicalType::INT8: - TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - case PhysicalType::INT16: - TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - case PhysicalType::INT32: - TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - case PhysicalType::INT64: - TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - case PhysicalType::UINT8: - TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - case PhysicalType::UINT16: - TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - case PhysicalType::UINT32: - TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - case PhysicalType::UINT64: - TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - case PhysicalType::INT128: - TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - case PhysicalType::FLOAT: - TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - case PhysicalType::DOUBLE: - TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - case PhysicalType::INTERVAL: - TemplatedHeapScatter(vdata, sel, ser_count, col_idx, key_locations, validitymask_locations, offset); - break; - default: - throw NotImplementedException("FIXME: Serialize to of constant type column to row-format"); - } -} +//! State used to scan a SortedBlock e.g. during merge sort +struct SBScanState { +public: + SBScanState(BufferManager &buffer_manager, GlobalSortState &state); -} // namespace duckdb -//===--------------------------------------------------------------------===// -// row_match.cpp -// Description: This file contains the implementation of the match operators -//===--------------------------------------------------------------------===// + void PinRadix(idx_t block_idx_to); + void PinData(SortedData &sd); + data_ptr_t RadixPtr() const; + data_ptr_t DataPtr(SortedData &sd) const; + data_ptr_t HeapPtr(SortedData &sd) const; + data_ptr_t BaseHeapPtr(SortedData &sd) const; + idx_t Remaining() const; + void SetIndices(idx_t block_idx_to, idx_t entry_idx_to); +public: + BufferManager &buffer_manager; + const SortLayout &sort_layout; + GlobalSortState &state; + SortedBlock *sb; + idx_t block_idx; + idx_t entry_idx; -namespace duckdb { + BufferHandle radix_handle; -using ValidityBytes = RowLayout::ValidityBytes; -using Predicates = RowOperations::Predicates; + BufferHandle blob_sorting_data_handle; + BufferHandle blob_sorting_heap_handle; -template -static idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, - SelectionVector *true_sel, SelectionVector *false_sel) { - throw NotImplementedException("Unsupported nested comparison operand for RowOperations::Match"); -} + BufferHandle payload_data_handle; + BufferHandle payload_heap_handle; +}; -template <> -idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, - SelectionVector *true_sel, SelectionVector *false_sel) { - return VectorOperations::NestedEquals(left, right, sel, count, true_sel, false_sel); -} +//! Used to scan the data into DataChunks after sorting +struct PayloadScanner { +public: + PayloadScanner(SortedData &sorted_data, GlobalSortState &global_sort_state, bool flush = true); + explicit PayloadScanner(GlobalSortState &global_sort_state, bool flush = true); -template <> -idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, - SelectionVector *true_sel, SelectionVector *false_sel) { - return VectorOperations::NestedNotEquals(left, right, sel, count, true_sel, false_sel); -} + //! Scan a single block + PayloadScanner(GlobalSortState &global_sort_state, idx_t block_idx); -template <> -idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, - SelectionVector *true_sel, SelectionVector *false_sel) { - return VectorOperations::DistinctGreaterThan(left, right, &sel, count, true_sel, false_sel); -} + //! The type layout of the payload + inline const vector &GetPayloadTypes() const { + return sorted_data.layout.GetTypes(); + } -template <> -idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, - SelectionVector *true_sel, SelectionVector *false_sel) { - return VectorOperations::DistinctGreaterThanEquals(left, right, &sel, count, true_sel, false_sel); -} + //! The number of rows scanned so far + inline idx_t Scanned() const { + return total_scanned; + } -template <> -idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, - SelectionVector *true_sel, SelectionVector *false_sel) { - return VectorOperations::DistinctLessThan(left, right, &sel, count, true_sel, false_sel); -} + //! The number of remaining rows + inline idx_t Remaining() const { + return total_count - total_scanned; + } -template <> -idx_t SelectComparison(Vector &left, Vector &right, const SelectionVector &sel, idx_t count, - SelectionVector *true_sel, SelectionVector *false_sel) { - return VectorOperations::DistinctLessThanEquals(left, right, &sel, count, true_sel, false_sel); -} + //! Scans the next data chunk from the sorted data + void Scan(DataChunk &chunk); -template -static void TemplatedMatchType(VectorData &col, Vector &rows, SelectionVector &sel, idx_t &count, idx_t col_offset, - idx_t col_no, SelectionVector *no_match, idx_t &no_match_count) { - // Precompute row_mask indexes - idx_t entry_idx; - idx_t idx_in_entry; - ValidityBytes::GetEntryIndex(col_no, entry_idx, idx_in_entry); +private: + //! The sorted data being scanned + SortedData &sorted_data; + //! Read state + SBScanState read_state; + //! The total count of sorted_data + const idx_t total_count; + //! Addresses used to gather from the sorted data + Vector addresses = Vector(LogicalType::POINTER); + //! The number of rows scanned so far + idx_t total_scanned; + //! Whether to flush the blocks after scanning + const bool flush; + //! Whether we are unswizzling the blocks + const bool unswizzling; - auto data = (T *)col.data; - auto ptrs = FlatVector::GetData(rows); - idx_t match_count = 0; - if (!col.validity.AllValid()) { - for (idx_t i = 0; i < count; i++) { - auto idx = sel.get_index(i); + //! Checks that the newest block is valid + void ValidateUnscannedBlock() const; +}; - auto row = ptrs[idx]; - ValidityBytes row_mask(row); - auto isnull = !row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry); +struct SBIterator { + static int ComparisonValue(ExpressionType comparison); - auto col_idx = col.sel->get_index(idx); - if (!col.validity.RowIsValid(col_idx)) { - if (isnull) { - // match: move to next value to compare - sel.set_index(match_count++, idx); - } else { - if (NO_MATCH_SEL) { - no_match->set_index(no_match_count++, idx); - } - } - } else { - auto value = Load(row + col_offset); - if (!isnull && OP::template Operation(data[col_idx], value)) { - sel.set_index(match_count++, idx); - } else { - if (NO_MATCH_SEL) { - no_match->set_index(no_match_count++, idx); - } - } - } - } - } else { - for (idx_t i = 0; i < count; i++) { - auto idx = sel.get_index(i); + SBIterator(GlobalSortState &gss, ExpressionType comparison, idx_t entry_idx_p = 0); - auto row = ptrs[idx]; - ValidityBytes row_mask(row); - auto isnull = !row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry); + inline idx_t GetIndex() const { + return entry_idx; + } - auto col_idx = col.sel->get_index(idx); - auto value = Load(row + col_offset); - if (!isnull && OP::template Operation(data[col_idx], value)) { - sel.set_index(match_count++, idx); - } else { - if (NO_MATCH_SEL) { - no_match->set_index(no_match_count++, idx); + inline void SetIndex(idx_t entry_idx_p) { + const auto new_block_idx = entry_idx_p / block_capacity; + if (new_block_idx != scan.block_idx) { + scan.SetIndices(new_block_idx, 0); + if (new_block_idx < block_count) { + scan.PinRadix(scan.block_idx); + block_ptr = scan.RadixPtr(); + if (!all_constant) { + scan.PinData(*scan.sb->blob_sorting_data); } } } - } - count = match_count; -} -template -static void TemplatedMatchNested(Vector &col, Vector &rows, SelectionVector &sel, idx_t &count, const idx_t col_offset, - const idx_t col_no, SelectionVector *no_match, idx_t &no_match_count) { - // Gather a dense Vector containing the column values being matched - Vector key(col.GetType()); - RowOperations::Gather(rows, sel, key, *FlatVector::IncrementalSelectionVector(), count, col_offset, col_no); + scan.entry_idx = entry_idx_p % block_capacity; + entry_ptr = block_ptr + scan.entry_idx * entry_size; + entry_idx = entry_idx_p; + } - // Densify the input column - Vector sliced(col, sel, count); + inline SBIterator &operator++() { + if (++scan.entry_idx < block_capacity) { + entry_ptr += entry_size; + ++entry_idx; + } else { + SetIndex(entry_idx + 1); + } - if (NO_MATCH_SEL) { - SelectionVector no_match_sel_offset(no_match->data() + no_match_count); - auto match_count = SelectComparison(sliced, key, sel, count, &sel, &no_match_sel_offset); - no_match_count += count - match_count; - count = match_count; - } else { - count = SelectComparison(sliced, key, sel, count, &sel, nullptr); + return *this; } -} -template -static void TemplatedMatchOp(Vector &vec, VectorData &col, const RowLayout &layout, Vector &rows, SelectionVector &sel, - idx_t &count, idx_t col_no, SelectionVector *no_match, idx_t &no_match_count) { - if (count == 0) { - return; - } - auto col_offset = layout.GetOffsets()[col_no]; - switch (layout.GetTypes()[col_no].InternalType()) { - case PhysicalType::BOOL: - case PhysicalType::INT8: - TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, - no_match_count); - break; - case PhysicalType::INT16: - TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, - no_match_count); - break; - case PhysicalType::INT32: - TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, - no_match_count); - break; - case PhysicalType::INT64: - TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, - no_match_count); - break; - case PhysicalType::UINT8: - TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, - no_match_count); - break; - case PhysicalType::UINT16: - TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, - no_match_count); - break; - case PhysicalType::UINT32: - TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, - no_match_count); - break; - case PhysicalType::UINT64: - TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, - no_match_count); - break; - case PhysicalType::INT128: - TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, - no_match_count); - break; - case PhysicalType::FLOAT: - TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, - no_match_count); - break; - case PhysicalType::DOUBLE: - TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, - no_match_count); - break; - case PhysicalType::INTERVAL: - TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, - no_match_count); - break; - case PhysicalType::VARCHAR: - TemplatedMatchType(col, rows, sel, count, col_offset, col_no, no_match, - no_match_count); - break; - case PhysicalType::LIST: - case PhysicalType::MAP: - case PhysicalType::STRUCT: - TemplatedMatchNested(vec, rows, sel, count, col_offset, col_no, no_match, no_match_count); - break; - default: - throw InternalException("Unsupported column type for RowOperations::Match"); + inline SBIterator &operator--() { + if (scan.entry_idx) { + --scan.entry_idx; + --entry_idx; + entry_ptr -= entry_size; + } else { + SetIndex(entry_idx - 1); + } + + return *this; } -} -template -static void TemplatedMatch(DataChunk &columns, VectorData col_data[], const RowLayout &layout, Vector &rows, - const Predicates &predicates, SelectionVector &sel, idx_t &count, SelectionVector *no_match, - idx_t &no_match_count) { - for (idx_t col_no = 0; col_no < predicates.size(); ++col_no) { - auto &vec = columns.data[col_no]; - auto &col = col_data[col_no]; - switch (predicates[col_no]) { - case ExpressionType::COMPARE_EQUAL: - case ExpressionType::COMPARE_NOT_DISTINCT_FROM: - case ExpressionType::COMPARE_DISTINCT_FROM: - TemplatedMatchOp(vec, col, layout, rows, sel, count, col_no, no_match, - no_match_count); - break; - case ExpressionType::COMPARE_NOTEQUAL: - TemplatedMatchOp(vec, col, layout, rows, sel, count, col_no, no_match, - no_match_count); - break; - case ExpressionType::COMPARE_GREATERTHAN: - TemplatedMatchOp(vec, col, layout, rows, sel, count, col_no, no_match, - no_match_count); - break; - case ExpressionType::COMPARE_GREATERTHANOREQUALTO: - TemplatedMatchOp(vec, col, layout, rows, sel, count, col_no, no_match, - no_match_count); - break; - case ExpressionType::COMPARE_LESSTHAN: - TemplatedMatchOp(vec, col, layout, rows, sel, count, col_no, no_match, - no_match_count); - break; - case ExpressionType::COMPARE_LESSTHANOREQUALTO: - TemplatedMatchOp(vec, col, layout, rows, sel, count, col_no, no_match, - no_match_count); - break; - default: - throw InternalException("Unsupported comparison type for RowOperations::Match"); + inline bool Compare(const SBIterator &other) const { + int comp_res; + if (all_constant) { + comp_res = FastMemcmp(entry_ptr, other.entry_ptr, cmp_size); + } else { + comp_res = Comparators::CompareTuple(scan, other.scan, entry_ptr, other.entry_ptr, sort_layout, external); } - } -} -idx_t RowOperations::Match(DataChunk &columns, VectorData col_data[], const RowLayout &layout, Vector &rows, - const Predicates &predicates, SelectionVector &sel, idx_t count, SelectionVector *no_match, - idx_t &no_match_count) { - if (no_match) { - TemplatedMatch(columns, col_data, layout, rows, predicates, sel, count, no_match, no_match_count); - } else { - TemplatedMatch(columns, col_data, layout, rows, predicates, sel, count, no_match, no_match_count); + return comp_res <= cmp; } - return count; -} + // Fixed comparison parameters + const SortLayout &sort_layout; + const idx_t block_count; + const idx_t block_capacity; + const size_t cmp_size; + const size_t entry_size; + const bool all_constant; + const bool external; + const int cmp; -} // namespace duckdb + // Iteration state + SBScanState scan; + idx_t entry_idx; + data_ptr_t block_ptr; + data_ptr_t entry_ptr; +}; +} // namespace duckdb namespace duckdb { -template -void TemplatedRadixScatter(VectorData &vdata, const SelectionVector &sel, idx_t add_count, data_ptr_t *key_locations, - const bool desc, const bool has_null, const bool nulls_first, const bool is_little_endian, - const idx_t offset) { - auto source = (T *)vdata.data; - if (has_null) { - auto &validity = vdata.validity; - const data_t valid = nulls_first ? 1 : 0; - const data_t invalid = 1 - valid; +class RowLayout; +struct LocalSortState; - for (idx_t i = 0; i < add_count; i++) { - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; - // write validity and according value - if (validity.RowIsValid(source_idx)) { - key_locations[i][0] = valid; - Radix::EncodeData(key_locations[i] + 1, source[source_idx], is_little_endian); - // invert bits if desc - if (desc) { - for (idx_t s = 1; s < sizeof(T) + 1; s++) { - *(key_locations[i] + s) = ~*(key_locations[i] + s); - } - } - } else { - key_locations[i][0] = invalid; - memset(key_locations[i] + 1, '\0', sizeof(T)); - } - key_locations[i] += sizeof(T) + 1; - } - } else { - for (idx_t i = 0; i < add_count; i++) { - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; - // write value - Radix::EncodeData(key_locations[i], source[source_idx], is_little_endian); - // invert bits if desc - if (desc) { - for (idx_t s = 0; s < sizeof(T); s++) { - *(key_locations[i] + s) = ~*(key_locations[i] + s); - } - } - key_locations[i] += sizeof(T); - } - } -} +struct SortConstants { + static constexpr idx_t VALUES_PER_RADIX = 256; + static constexpr idx_t MSD_RADIX_LOCATIONS = VALUES_PER_RADIX + 1; + static constexpr idx_t INSERTION_SORT_THRESHOLD = 24; + static constexpr idx_t MSD_RADIX_SORT_SIZE_THRESHOLD = 4; +}; -void RadixScatterStringVector(VectorData &vdata, const SelectionVector &sel, idx_t add_count, data_ptr_t *key_locations, - const bool desc, const bool has_null, const bool nulls_first, const idx_t prefix_len, - idx_t offset) { - auto source = (string_t *)vdata.data; - if (has_null) { - auto &validity = vdata.validity; - const data_t valid = nulls_first ? 1 : 0; - const data_t invalid = 1 - valid; +struct SortLayout { +public: + explicit SortLayout(const vector &orders); - for (idx_t i = 0; i < add_count; i++) { - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; - // write validity and according value - if (validity.RowIsValid(source_idx)) { - key_locations[i][0] = valid; - Radix::EncodeStringDataPrefix(key_locations[i] + 1, source[source_idx], prefix_len); - // invert bits if desc - if (desc) { - for (idx_t s = 1; s < prefix_len + 1; s++) { - *(key_locations[i] + s) = ~*(key_locations[i] + s); - } - } - } else { - key_locations[i][0] = invalid; - memset(key_locations[i] + 1, '\0', prefix_len); - } - key_locations[i] += prefix_len + 1; - } - } else { - for (idx_t i = 0; i < add_count; i++) { - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; - // write value - Radix::EncodeStringDataPrefix(key_locations[i], source[source_idx], prefix_len); - // invert bits if desc - if (desc) { - for (idx_t s = 0; s < prefix_len; s++) { - *(key_locations[i] + s) = ~*(key_locations[i] + s); - } - } - key_locations[i] += prefix_len; - } - } -} +public: + idx_t column_count; + vector order_types; + vector order_by_null_types; + vector logical_types; -void RadixScatterListVector(Vector &v, VectorData &vdata, const SelectionVector &sel, idx_t add_count, - data_ptr_t *key_locations, const bool desc, const bool has_null, const bool nulls_first, - const idx_t prefix_len, const idx_t width, const idx_t offset) { - auto list_data = ListVector::GetData(v); - auto &child_vector = ListVector::GetEntry(v); - auto list_size = ListVector::GetListSize(v); + bool all_constant; + vector constant_size; + vector column_sizes; + vector prefix_lengths; + vector stats; + vector has_null; - // serialize null values - if (has_null) { - auto &validity = vdata.validity; - const data_t valid = nulls_first ? 1 : 0; - const data_t invalid = 1 - valid; + idx_t comparison_size; + idx_t entry_size; - for (idx_t i = 0; i < add_count; i++) { - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; - data_ptr_t key_location = key_locations[i] + 1; - // write validity and according value - if (validity.RowIsValid(source_idx)) { - key_locations[i][0] = valid; - key_locations[i]++; - auto &list_entry = list_data[source_idx]; - if (list_entry.length > 0) { - // denote that the list is not empty with a 1 - key_locations[i][0] = 1; - key_locations[i]++; - RowOperations::RadixScatter(child_vector, list_size, *FlatVector::IncrementalSelectionVector(), 1, - key_locations + i, false, true, false, prefix_len, width - 1, - list_entry.offset); - } else { - // denote that the list is empty with a 0 - key_locations[i][0] = 0; - key_locations[i]++; - memset(key_locations[i], '\0', width - 2); - } - // invert bits if desc - if (desc) { - for (idx_t s = 0; s < width - 1; s++) { - *(key_location + s) = ~*(key_location + s); - } - } - } else { - key_locations[i][0] = invalid; - memset(key_locations[i] + 1, '\0', width - 1); - key_locations[i] += width; - } - } - } else { - for (idx_t i = 0; i < add_count; i++) { - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; - auto &list_entry = list_data[source_idx]; - data_ptr_t key_location = key_locations[i]; - if (list_entry.length > 0) { - // denote that the list is not empty with a 1 - key_locations[i][0] = 1; - key_locations[i]++; - RowOperations::RadixScatter(child_vector, list_size, *FlatVector::IncrementalSelectionVector(), 1, - key_locations + i, false, true, false, prefix_len, width - 1, - list_entry.offset); - } else { - // denote that the list is empty with a 0 - key_locations[i][0] = 0; - key_locations[i]++; - memset(key_locations[i], '\0', width - 1); - } - // invert bits if desc - if (desc) { - for (idx_t s = 0; s < width; s++) { - *(key_location + s) = ~*(key_location + s); - } - } - } - } -} + RowLayout blob_layout; + unordered_map sorting_to_blob_col; +}; -void RadixScatterStructVector(Vector &v, VectorData &vdata, idx_t vcount, const SelectionVector &sel, idx_t add_count, - data_ptr_t *key_locations, const bool desc, const bool has_null, const bool nulls_first, - const idx_t prefix_len, idx_t width, const idx_t offset) { - // serialize null values - if (has_null) { - auto &validity = vdata.validity; - const data_t valid = nulls_first ? 1 : 0; - const data_t invalid = 1 - valid; +struct GlobalSortState { +public: + GlobalSortState(BufferManager &buffer_manager, const vector &orders, RowLayout &payload_layout); - for (idx_t i = 0; i < add_count; i++) { - auto idx = sel.get_index(i); - auto source_idx = vdata.sel->get_index(idx) + offset; - // write validity and according value - if (validity.RowIsValid(source_idx)) { - key_locations[i][0] = valid; - } else { - key_locations[i][0] = invalid; - } - key_locations[i]++; - } - width--; - } - // serialize the struct - auto &child_vector = *StructVector::GetEntries(v)[0]; - RowOperations::RadixScatter(child_vector, vcount, *FlatVector::IncrementalSelectionVector(), add_count, - key_locations, false, true, false, prefix_len, width, offset); - // invert bits if desc - if (desc) { - for (idx_t i = 0; i < add_count; i++) { - for (idx_t s = 0; s < width; s++) { - *(key_locations[i] - width + s) = ~*(key_locations[i] - width + s); - } - } - } -} + //! Add local state sorted data to this global state + void AddLocalState(LocalSortState &local_sort_state); + //! Prepares the GlobalSortState for the merge sort phase (after completing radix sort phase) + void PrepareMergePhase(); + //! Initializes the global sort state for another round of merging + void InitializeMergeRound(); + //! Completes the cascaded merge sort round. + //! Pass true if you wish to use the radix data for further comparisons. + void CompleteMergeRound(bool keep_radix_data = false); + //! Print the sorted data to the console. + void Print(); -void RowOperations::RadixScatter(Vector &v, idx_t vcount, const SelectionVector &sel, idx_t ser_count, - data_ptr_t *key_locations, bool desc, bool has_null, bool nulls_first, - idx_t prefix_len, idx_t width, idx_t offset) { - auto is_little_endian = Radix::IsLittleEndian(); +public: + //! The lock for updating the order global state + mutex lock; + //! The buffer manager + BufferManager &buffer_manager; - VectorData vdata; - v.Orrify(vcount, vdata); - switch (v.GetType().InternalType()) { - case PhysicalType::BOOL: - case PhysicalType::INT8: - TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, - is_little_endian, offset); - break; - case PhysicalType::INT16: - TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, - is_little_endian, offset); - break; - case PhysicalType::INT32: - TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, - is_little_endian, offset); - break; - case PhysicalType::INT64: - TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, - is_little_endian, offset); - break; - case PhysicalType::UINT8: - TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, - is_little_endian, offset); - break; - case PhysicalType::UINT16: - TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, - is_little_endian, offset); - break; - case PhysicalType::UINT32: - TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, - is_little_endian, offset); - break; - case PhysicalType::UINT64: - TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, - is_little_endian, offset); - break; - case PhysicalType::INT128: - TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, - is_little_endian, offset); - break; - case PhysicalType::FLOAT: - TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, - is_little_endian, offset); - break; - case PhysicalType::DOUBLE: - TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, - is_little_endian, offset); - break; - case PhysicalType::INTERVAL: - TemplatedRadixScatter(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, - is_little_endian, offset); - break; - case PhysicalType::VARCHAR: - RadixScatterStringVector(vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, prefix_len, offset); - break; - case PhysicalType::LIST: - RadixScatterListVector(v, vdata, sel, ser_count, key_locations, desc, has_null, nulls_first, prefix_len, width, - offset); - break; - case PhysicalType::STRUCT: - RadixScatterStructVector(v, vdata, vcount, sel, ser_count, key_locations, desc, has_null, nulls_first, - prefix_len, width, offset); - break; - default: - throw NotImplementedException("Cannot ORDER BY column with type %s", v.GetType().ToString()); - } -} + //! Sorting and payload layouts + const SortLayout sort_layout; + const RowLayout payload_layout; -} // namespace duckdb -//===--------------------------------------------------------------------===// -// row_scatter.cpp -// Description: This file contains the implementation of the row scattering -// operators -//===--------------------------------------------------------------------===// + //! Sorted data + vector> sorted_blocks; + vector>> sorted_blocks_temp; + unique_ptr odd_one_out; + //! Pinned heap data (if sorting in memory) + vector> heap_blocks; + vector pinned_blocks; + //! Capacity (number of rows) used to initialize blocks + idx_t block_capacity; + //! Whether we are doing an external sort + bool external; + //! Progress in merge path stage + idx_t pair_idx; + idx_t num_pairs; + idx_t l_start; + idx_t r_start; +}; +struct LocalSortState { +public: + LocalSortState(); + //! Initialize the layouts and RowDataCollections + void Initialize(GlobalSortState &global_sort_state, BufferManager &buffer_manager_p); + //! Sink one DataChunk into the local sort state + void SinkChunk(DataChunk &sort, DataChunk &payload); + //! Size of accumulated data in bytes + idx_t SizeInBytes() const; + //! Sort the data accumulated so far + void Sort(GlobalSortState &global_sort_state, bool reorder_heap); + //! Concatenate the blocks held by a RowDataCollection into a single block + static unique_ptr ConcatenateBlocks(RowDataCollection &row_data); +private: + //! Sorts the data in the newly created SortedBlock + void SortInMemory(); + //! Re-order the local state after sorting + void ReOrder(GlobalSortState &gstate, bool reorder_heap); + //! Re-order a SortedData object after sorting + void ReOrder(SortedData &sd, data_ptr_t sorting_ptr, RowDataCollection &heap, GlobalSortState &gstate, + bool reorder_heap); +public: + //! Whether this local state has been initialized + bool initialized; + //! The buffer manager + BufferManager *buffer_manager; + //! The sorting and payload layouts + const SortLayout *sort_layout; + const RowLayout *payload_layout; + //! Radix/memcmp sortable data + unique_ptr radix_sorting_data; + //! Variable sized sorting data and accompanying heap + unique_ptr blob_sorting_data; + unique_ptr blob_sorting_heap; + //! Payload data and accompanying heap + unique_ptr payload_data; + unique_ptr payload_heap; + //! Sorted data + vector> sorted_blocks; +private: + //! Selection vector and addresses for scattering the data to rows + const SelectionVector &sel_ptr = *FlatVector::IncrementalSelectionVector(); + Vector addresses = Vector(LogicalType::POINTER); +}; +struct MergeSorter { +public: + MergeSorter(GlobalSortState &state, BufferManager &buffer_manager); -namespace duckdb { + //! Finds and merges partitions until the current cascaded merge round is finished + void PerformInMergeRound(); -using ValidityBytes = RowLayout::ValidityBytes; +private: + //! The global sorting state + GlobalSortState &state; + //! The sorting and payload layouts + BufferManager &buffer_manager; + const SortLayout &sort_layout; -template -static void TemplatedScatter(VectorData &col, Vector &rows, const SelectionVector &sel, const idx_t count, - const idx_t col_offset, const idx_t col_no) { - auto data = (T *)col.data; - auto ptrs = FlatVector::GetData(rows); + //! The left and right reader + unique_ptr left; + unique_ptr right; - if (!col.validity.AllValid()) { - for (idx_t i = 0; i < count; i++) { - auto idx = sel.get_index(i); - auto col_idx = col.sel->get_index(idx); - auto row = ptrs[idx]; + //! Input and output blocks + unique_ptr left_input; + unique_ptr right_input; + SortedBlock *result; - auto isnull = !col.validity.RowIsValid(col_idx); - T store_value = isnull ? NullValue() : data[col_idx]; - Store(store_value, row + col_offset); - if (isnull) { - ValidityBytes col_mask(ptrs[idx]); - col_mask.SetInvalidUnsafe(col_no); - } - } - } else { - for (idx_t i = 0; i < count; i++) { - auto idx = sel.get_index(i); - auto col_idx = col.sel->get_index(idx); - auto row = ptrs[idx]; +private: + //! Computes the left and right block that will be merged next (Merge Path partition) + void GetNextPartition(); + //! Finds the boundary of the next partition using binary search + void GetIntersection(const idx_t diagonal, idx_t &l_idx, idx_t &r_idx); + //! Compare values within SortedBlocks using a global index + int CompareUsingGlobalIndex(SBScanState &l, SBScanState &r, const idx_t l_idx, const idx_t r_idx); - Store(data[col_idx], row + col_offset); + //! Finds the next partition and merges it + void MergePartition(); + + //! Computes how the next 'count' tuples should be merged by setting the 'left_smaller' array + void ComputeMerge(const idx_t &count, bool left_smaller[]); + + //! Merges the radix sorting blocks according to the 'left_smaller' array + void MergeRadix(const idx_t &count, const bool left_smaller[]); + //! Merges SortedData according to the 'left_smaller' array + void MergeData(SortedData &result_data, SortedData &l_data, SortedData &r_data, const idx_t &count, + const bool left_smaller[], idx_t next_entry_sizes[], bool reset_indices); + //! Merges constant size rows according to the 'left_smaller' array + void MergeRows(data_ptr_t &l_ptr, idx_t &l_entry_idx, const idx_t &l_count, data_ptr_t &r_ptr, idx_t &r_entry_idx, + const idx_t &r_count, RowDataBlock &target_block, data_ptr_t &target_ptr, const idx_t &entry_size, + const bool left_smaller[], idx_t &copied, const idx_t &count); + //! Flushes constant size rows into the result + void FlushRows(data_ptr_t &source_ptr, idx_t &source_entry_idx, const idx_t &source_count, + RowDataBlock &target_block, data_ptr_t &target_ptr, const idx_t &entry_size, idx_t &copied, + const idx_t &count); + //! Flushes blob rows and accompanying heap + void FlushBlobs(const RowLayout &layout, const idx_t &source_count, data_ptr_t &source_data_ptr, + idx_t &source_entry_idx, data_ptr_t &source_heap_ptr, RowDataBlock &target_data_block, + data_ptr_t &target_data_ptr, RowDataBlock &target_heap_block, BufferHandle &target_heap_handle, + data_ptr_t &target_heap_ptr, idx_t &copied, const idx_t &count); +}; + +} // namespace duckdb + + +namespace duckdb { + +bool Comparators::TieIsBreakable(const idx_t &col_idx, const data_ptr_t row_ptr, const RowLayout &row_layout) { + // Check if the blob is NULL + ValidityBytes row_mask(row_ptr); + idx_t entry_idx; + idx_t idx_in_entry; + ValidityBytes::GetEntryIndex(col_idx, entry_idx, idx_in_entry); + if (!row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry)) { + // Can't break a NULL tie + return false; + } + if (row_layout.GetTypes()[col_idx].InternalType() == PhysicalType::VARCHAR) { + const auto &tie_col_offset = row_layout.GetOffsets()[col_idx]; + string_t tie_string = Load(row_ptr + tie_col_offset); + if (tie_string.GetSize() < string_t::INLINE_LENGTH) { + // No need to break the tie - we already compared the full string + return false; } } + return true; } -static void ComputeStringEntrySizes(const VectorData &col, idx_t entry_sizes[], const SelectionVector &sel, - const idx_t count, const idx_t offset = 0) { - auto data = (const string_t *)col.data; - for (idx_t i = 0; i < count; i++) { - auto idx = sel.get_index(i); - auto col_idx = col.sel->get_index(idx) + offset; - const auto &str = data[col_idx]; - if (col.validity.RowIsValid(col_idx) && !str.IsInlined()) { - entry_sizes[i] += str.GetSize(); +int Comparators::CompareTuple(const SBScanState &left, const SBScanState &right, const data_ptr_t &l_ptr, + const data_ptr_t &r_ptr, const SortLayout &sort_layout, const bool &external_sort) { + // Compare the sorting columns one by one + int comp_res = 0; + data_ptr_t l_ptr_offset = l_ptr; + data_ptr_t r_ptr_offset = r_ptr; + for (idx_t col_idx = 0; col_idx < sort_layout.column_count; col_idx++) { + comp_res = FastMemcmp(l_ptr_offset, r_ptr_offset, sort_layout.column_sizes[col_idx]); + if (comp_res == 0 && !sort_layout.constant_size[col_idx]) { + comp_res = BreakBlobTie(col_idx, left, right, sort_layout, external_sort); + } + if (comp_res != 0) { + break; } + l_ptr_offset += sort_layout.column_sizes[col_idx]; + r_ptr_offset += sort_layout.column_sizes[col_idx]; } + return comp_res; } -static void ScatterStringVector(VectorData &col, Vector &rows, data_ptr_t str_locations[], const SelectionVector &sel, - const idx_t count, const idx_t col_offset, const idx_t col_no) { - auto string_data = (string_t *)col.data; - auto ptrs = FlatVector::GetData(rows); - - for (idx_t i = 0; i < count; i++) { - auto idx = sel.get_index(i); - auto col_idx = col.sel->get_index(idx); - auto row = ptrs[idx]; - if (!col.validity.RowIsValid(col_idx)) { - ValidityBytes col_mask(row); - col_mask.SetInvalidUnsafe(col_no); - Store(NullValue(), row + col_offset); - } else if (string_data[col_idx].IsInlined()) { - Store(string_data[col_idx], row + col_offset); - } else { - const auto &str = string_data[col_idx]; - string_t inserted((const char *)str_locations[i], str.GetSize()); - memcpy(inserted.GetDataWriteable(), str.GetDataUnsafe(), str.GetSize()); - str_locations[i] += str.GetSize(); - inserted.Finalize(); - Store(inserted, row + col_offset); - } +int Comparators::CompareVal(const data_ptr_t l_ptr, const data_ptr_t r_ptr, const LogicalType &type) { + switch (type.InternalType()) { + case PhysicalType::VARCHAR: + return TemplatedCompareVal(l_ptr, r_ptr); + case PhysicalType::LIST: + case PhysicalType::STRUCT: { + auto l_nested_ptr = Load(l_ptr); + auto r_nested_ptr = Load(r_ptr); + return CompareValAndAdvance(l_nested_ptr, r_nested_ptr, type); + } + default: + throw NotImplementedException("Unimplemented CompareVal for type %s", type.ToString()); } } -static void ScatterNestedVector(Vector &vec, VectorData &col, Vector &rows, data_ptr_t data_locations[], - const SelectionVector &sel, const idx_t count, const idx_t col_offset, - const idx_t col_no, const idx_t vcount) { - // Store pointers to the data in the row - // Do this first because SerializeVector destroys the locations - auto ptrs = FlatVector::GetData(rows); - data_ptr_t validitymask_locations[STANDARD_VECTOR_SIZE]; - for (idx_t i = 0; i < count; i++) { - auto idx = sel.get_index(i); - auto row = ptrs[idx]; - validitymask_locations[i] = row; - - Store(data_locations[i], row + col_offset); +int Comparators::BreakBlobTie(const idx_t &tie_col, const SBScanState &left, const SBScanState &right, + const SortLayout &sort_layout, const bool &external) { + const idx_t &col_idx = sort_layout.sorting_to_blob_col.at(tie_col); + data_ptr_t l_data_ptr = left.DataPtr(*left.sb->blob_sorting_data); + data_ptr_t r_data_ptr = right.DataPtr(*right.sb->blob_sorting_data); + if (!TieIsBreakable(col_idx, l_data_ptr, sort_layout.blob_layout)) { + // Quick check to see if ties can be broken + return 0; } - - // Serialise the data - RowOperations::HeapScatter(vec, vcount, sel, count, col_no, data_locations, validitymask_locations); + // Align the pointers + const auto &tie_col_offset = sort_layout.blob_layout.GetOffsets()[col_idx]; + l_data_ptr += tie_col_offset; + r_data_ptr += tie_col_offset; + // Do the comparison + const int order = sort_layout.order_types[tie_col] == OrderType::DESCENDING ? -1 : 1; + const auto &type = sort_layout.blob_layout.GetTypes()[col_idx]; + int result; + if (external) { + // Store heap pointers + data_ptr_t l_heap_ptr = left.HeapPtr(*left.sb->blob_sorting_data); + data_ptr_t r_heap_ptr = right.HeapPtr(*right.sb->blob_sorting_data); + // Unswizzle offset to pointer + UnswizzleSingleValue(l_data_ptr, l_heap_ptr, type); + UnswizzleSingleValue(r_data_ptr, r_heap_ptr, type); + // Compare + result = CompareVal(l_data_ptr, r_data_ptr, type); + // Swizzle the pointers back to offsets + SwizzleSingleValue(l_data_ptr, l_heap_ptr, type); + SwizzleSingleValue(r_data_ptr, r_heap_ptr, type); + } else { + result = CompareVal(l_data_ptr, r_data_ptr, type); + } + return order * result; } -void RowOperations::Scatter(DataChunk &columns, VectorData col_data[], const RowLayout &layout, Vector &rows, - RowDataCollection &string_heap, const SelectionVector &sel, idx_t count) { - if (count == 0) { - return; +template +int Comparators::TemplatedCompareVal(const data_ptr_t &left_ptr, const data_ptr_t &right_ptr) { + const auto left_val = Load(left_ptr); + const auto right_val = Load(right_ptr); + if (Equals::Operation(left_val, right_val)) { + return 0; + } else if (LessThan::Operation(left_val, right_val)) { + return -1; + } else { + return 1; } +} - // Set the validity mask for each row before inserting data - auto ptrs = FlatVector::GetData(rows); - for (idx_t i = 0; i < count; ++i) { - auto row_idx = sel.get_index(i); - auto row = ptrs[row_idx]; - ValidityBytes(row).SetAllValid(layout.ColumnCount()); +int Comparators::CompareValAndAdvance(data_ptr_t &l_ptr, data_ptr_t &r_ptr, const LogicalType &type) { + switch (type.InternalType()) { + case PhysicalType::BOOL: + case PhysicalType::INT8: + return TemplatedCompareAndAdvance(l_ptr, r_ptr); + case PhysicalType::INT16: + return TemplatedCompareAndAdvance(l_ptr, r_ptr); + case PhysicalType::INT32: + return TemplatedCompareAndAdvance(l_ptr, r_ptr); + case PhysicalType::INT64: + return TemplatedCompareAndAdvance(l_ptr, r_ptr); + case PhysicalType::UINT8: + return TemplatedCompareAndAdvance(l_ptr, r_ptr); + case PhysicalType::UINT16: + return TemplatedCompareAndAdvance(l_ptr, r_ptr); + case PhysicalType::UINT32: + return TemplatedCompareAndAdvance(l_ptr, r_ptr); + case PhysicalType::UINT64: + return TemplatedCompareAndAdvance(l_ptr, r_ptr); + case PhysicalType::INT128: + return TemplatedCompareAndAdvance(l_ptr, r_ptr); + case PhysicalType::FLOAT: + return TemplatedCompareAndAdvance(l_ptr, r_ptr); + case PhysicalType::DOUBLE: + return TemplatedCompareAndAdvance(l_ptr, r_ptr); + case PhysicalType::INTERVAL: + return TemplatedCompareAndAdvance(l_ptr, r_ptr); + case PhysicalType::VARCHAR: + return CompareStringAndAdvance(l_ptr, r_ptr); + case PhysicalType::LIST: + return CompareListAndAdvance(l_ptr, r_ptr, ListType::GetChildType(type)); + case PhysicalType::STRUCT: + return CompareStructAndAdvance(l_ptr, r_ptr, StructType::GetChildTypes(type)); + default: + throw NotImplementedException("Unimplemented CompareValAndAdvance for type %s", type.ToString()); } +} - const auto vcount = columns.size(); - auto &offsets = layout.GetOffsets(); - auto &types = layout.GetTypes(); +template +int Comparators::TemplatedCompareAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr) { + auto result = TemplatedCompareVal(left_ptr, right_ptr); + left_ptr += sizeof(T); + right_ptr += sizeof(T); + return result; +} - // Compute the entry size of the variable size columns - vector> handles; - data_ptr_t data_locations[STANDARD_VECTOR_SIZE]; - if (!layout.AllConstant()) { - idx_t entry_sizes[STANDARD_VECTOR_SIZE]; - std::fill_n(entry_sizes, count, sizeof(uint32_t)); - for (idx_t col_no = 0; col_no < types.size(); col_no++) { - if (TypeIsConstantSize(types[col_no].InternalType())) { - continue; - } +int Comparators::CompareStringAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr) { + // Construct the string_t + uint32_t left_string_size = Load(left_ptr); + uint32_t right_string_size = Load(right_ptr); + left_ptr += sizeof(uint32_t); + right_ptr += sizeof(uint32_t); + string_t left_val((const char *)left_ptr, left_string_size); + string_t right_val((const char *)right_ptr, right_string_size); + left_ptr += left_string_size; + right_ptr += right_string_size; + // Compare + return TemplatedCompareVal((data_ptr_t)&left_val, (data_ptr_t)&right_val); +} - auto &vec = columns.data[col_no]; - auto &col = col_data[col_no]; - switch (types[col_no].InternalType()) { - case PhysicalType::VARCHAR: - ComputeStringEntrySizes(col, entry_sizes, sel, count); - break; - case PhysicalType::LIST: - case PhysicalType::MAP: - case PhysicalType::STRUCT: - RowOperations::ComputeEntrySizes(vec, col, entry_sizes, vcount, count, sel); - break; - default: - throw InternalException("Unsupported type for RowOperations::Scatter"); - } +int Comparators::CompareStructAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr, + const child_list_t &types) { + idx_t count = types.size(); + // Load validity masks + ValidityBytes left_validity(left_ptr); + ValidityBytes right_validity(right_ptr); + left_ptr += (count + 7) / 8; + right_ptr += (count + 7) / 8; + // Initialize variables + bool left_valid; + bool right_valid; + idx_t entry_idx; + idx_t idx_in_entry; + // Compare + int comp_res = 0; + for (idx_t i = 0; i < count; i++) { + ValidityBytes::GetEntryIndex(i, entry_idx, idx_in_entry); + left_valid = left_validity.RowIsValid(left_validity.GetValidityEntry(entry_idx), idx_in_entry); + right_valid = right_validity.RowIsValid(right_validity.GetValidityEntry(entry_idx), idx_in_entry); + auto &type = types[i].second; + if ((left_valid && right_valid) || TypeIsConstantSize(type.InternalType())) { + comp_res = CompareValAndAdvance(left_ptr, right_ptr, types[i].second); } - - // Build out the buffer space - string_heap.Build(count, data_locations, entry_sizes); - - // Serialize information that is needed for swizzling if the computation goes out-of-core - const idx_t heap_pointer_offset = layout.GetHeapPointerOffset(); - for (idx_t i = 0; i < count; i++) { - auto row_idx = sel.get_index(i); - auto row = ptrs[row_idx]; - // Pointer to this row in the heap block - Store(data_locations[i], row + heap_pointer_offset); - // Row size is stored in the heap in front of each row - Store(entry_sizes[i], data_locations[i]); - data_locations[i] += sizeof(uint32_t); + if (!left_valid && !right_valid) { + comp_res = 0; + } else if (!left_valid) { + comp_res = 1; + } else if (!right_valid) { + comp_res = -1; + } + if (comp_res != 0) { + break; } } + return comp_res; +} - for (idx_t col_no = 0; col_no < types.size(); col_no++) { - auto &vec = columns.data[col_no]; - auto &col = col_data[col_no]; - auto col_offset = offsets[col_no]; - - switch (types[col_no].InternalType()) { +int Comparators::CompareListAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr, const LogicalType &type) { + // Load list lengths + auto left_len = Load(left_ptr); + auto right_len = Load(right_ptr); + left_ptr += sizeof(idx_t); + right_ptr += sizeof(idx_t); + // Load list validity masks + ValidityBytes left_validity(left_ptr); + ValidityBytes right_validity(right_ptr); + left_ptr += (left_len + 7) / 8; + right_ptr += (right_len + 7) / 8; + // Compare + int comp_res = 0; + idx_t count = MinValue(left_len, right_len); + if (TypeIsConstantSize(type.InternalType())) { + // Templated code for fixed-size types + switch (type.InternalType()) { case PhysicalType::BOOL: case PhysicalType::INT8: - TemplatedScatter(col, rows, sel, count, col_offset, col_no); + comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); break; case PhysicalType::INT16: - TemplatedScatter(col, rows, sel, count, col_offset, col_no); + comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); break; case PhysicalType::INT32: - TemplatedScatter(col, rows, sel, count, col_offset, col_no); + comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); break; case PhysicalType::INT64: - TemplatedScatter(col, rows, sel, count, col_offset, col_no); + comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); break; case PhysicalType::UINT8: - TemplatedScatter(col, rows, sel, count, col_offset, col_no); + comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); break; case PhysicalType::UINT16: - TemplatedScatter(col, rows, sel, count, col_offset, col_no); + comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); break; case PhysicalType::UINT32: - TemplatedScatter(col, rows, sel, count, col_offset, col_no); + comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); break; case PhysicalType::UINT64: - TemplatedScatter(col, rows, sel, count, col_offset, col_no); + comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); break; case PhysicalType::INT128: - TemplatedScatter(col, rows, sel, count, col_offset, col_no); + comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); break; case PhysicalType::FLOAT: - TemplatedScatter(col, rows, sel, count, col_offset, col_no); + comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); break; case PhysicalType::DOUBLE: - TemplatedScatter(col, rows, sel, count, col_offset, col_no); + comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); break; case PhysicalType::INTERVAL: - TemplatedScatter(col, rows, sel, count, col_offset, col_no); - break; - case PhysicalType::VARCHAR: - ScatterStringVector(col, rows, data_locations, sel, count, col_offset, col_no); - break; - case PhysicalType::LIST: - case PhysicalType::MAP: - case PhysicalType::STRUCT: - ScatterNestedVector(vec, col, rows, data_locations, sel, count, col_offset, col_no, vcount); + comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); break; default: - throw InternalException("Unsupported type for RowOperations::Scatter"); + throw NotImplementedException("CompareListAndAdvance for fixed-size type %s", type.ToString()); } - } -} - -} // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/serializer/buffered_deserializer.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { - -class BufferedDeserializer : public Deserializer { -public: - BufferedDeserializer(data_ptr_t ptr, idx_t data_size); - explicit BufferedDeserializer(BufferedSerializer &serializer); - - data_ptr_t ptr; - data_ptr_t endptr; - -public: - void ReadData(data_ptr_t buffer, uint64_t read_size) override; -}; - -} // namespace duckdb - - -#include - -namespace duckdb { + } else { + // Variable-sized list entries + bool left_valid; + bool right_valid; + idx_t entry_idx; + idx_t idx_in_entry; + // Size (in bytes) of all variable-sizes entries is stored before the entries begin, + // to make deserialization easier. We need to skip over them + left_ptr += left_len * sizeof(idx_t); + right_ptr += right_len * sizeof(idx_t); + for (idx_t i = 0; i < count; i++) { + ValidityBytes::GetEntryIndex(i, entry_idx, idx_in_entry); + left_valid = left_validity.RowIsValid(left_validity.GetValidityEntry(entry_idx), idx_in_entry); + right_valid = right_validity.RowIsValid(right_validity.GetValidityEntry(entry_idx), idx_in_entry); + if (left_valid && right_valid) { + switch (type.InternalType()) { + case PhysicalType::LIST: + comp_res = CompareListAndAdvance(left_ptr, right_ptr, ListType::GetChildType(type)); + break; + case PhysicalType::VARCHAR: + comp_res = CompareStringAndAdvance(left_ptr, right_ptr); + break; + case PhysicalType::STRUCT: + comp_res = CompareStructAndAdvance(left_ptr, right_ptr, StructType::GetChildTypes(type)); + break; + default: + throw NotImplementedException("CompareListAndAdvance for variable-size type %s", type.ToString()); + } + } else if (!left_valid && !right_valid) { + comp_res = 0; + } else if (left_valid) { + comp_res = -1; + } else { + comp_res = 1; + } + if (comp_res != 0) { + break; + } + } + } + // All values that we looped over were equal + if (comp_res == 0 && left_len != right_len) { + // Smaller lists first + if (left_len < right_len) { + comp_res = -1; + } else { + comp_res = 1; + } + } + return comp_res; +} -BufferedDeserializer::BufferedDeserializer(data_ptr_t ptr, idx_t data_size) : ptr(ptr), endptr(ptr + data_size) { +template +int Comparators::TemplatedCompareListLoop(data_ptr_t &left_ptr, data_ptr_t &right_ptr, + const ValidityBytes &left_validity, const ValidityBytes &right_validity, + const idx_t &count) { + int comp_res = 0; + bool left_valid; + bool right_valid; + idx_t entry_idx; + idx_t idx_in_entry; + for (idx_t i = 0; i < count; i++) { + ValidityBytes::GetEntryIndex(i, entry_idx, idx_in_entry); + left_valid = left_validity.RowIsValid(left_validity.GetValidityEntry(entry_idx), idx_in_entry); + right_valid = right_validity.RowIsValid(right_validity.GetValidityEntry(entry_idx), idx_in_entry); + comp_res = TemplatedCompareAndAdvance(left_ptr, right_ptr); + if (!left_valid && !right_valid) { + comp_res = 0; + } else if (!left_valid) { + comp_res = 1; + } else if (!right_valid) { + comp_res = -1; + } + if (comp_res != 0) { + break; + } + } + return comp_res; } -BufferedDeserializer::BufferedDeserializer(BufferedSerializer &serializer) - : BufferedDeserializer(serializer.data, serializer.maximum_size) { +void Comparators::UnswizzleSingleValue(data_ptr_t data_ptr, const data_ptr_t &heap_ptr, const LogicalType &type) { + if (type.InternalType() == PhysicalType::VARCHAR) { + data_ptr += sizeof(uint32_t) + string_t::PREFIX_LENGTH; + } + Store(heap_ptr + Load(data_ptr), data_ptr); } -void BufferedDeserializer::ReadData(data_ptr_t buffer, idx_t read_size) { - if (ptr + read_size > endptr) { - throw SerializationException("Failed to deserialize: not enough data in buffer to fulfill read request"); +void Comparators::SwizzleSingleValue(data_ptr_t data_ptr, const data_ptr_t &heap_ptr, const LogicalType &type) { + if (type.InternalType() == PhysicalType::VARCHAR) { + data_ptr += sizeof(uint32_t) + string_t::PREFIX_LENGTH; } - memcpy(buffer, ptr, read_size); - ptr += read_size; + Store(Load(data_ptr) - heap_ptr, data_ptr); } } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/serializer/buffered_file_reader.hpp -// -// -//===----------------------------------------------------------------------===// - namespace duckdb { -class BufferedFileReader : public Deserializer { -public: - BufferedFileReader(FileSystem &fs, const char *path, FileOpener *opener = nullptr); - - FileSystem &fs; - unique_ptr data; - idx_t offset; - idx_t read_data; - unique_ptr handle; - -public: - void ReadData(data_ptr_t buffer, uint64_t read_size) override; - //! Returns true if the reader has finished reading the entire file - bool Finished(); +MergeSorter::MergeSorter(GlobalSortState &state, BufferManager &buffer_manager) + : state(state), buffer_manager(buffer_manager), sort_layout(state.sort_layout) { +} - idx_t FileSize() { - return file_size; +void MergeSorter::PerformInMergeRound() { + while (true) { + { + lock_guard pair_guard(state.lock); + if (state.pair_idx == state.num_pairs) { + break; + } + GetNextPartition(); + } + MergePartition(); } +} -private: - idx_t file_size; - idx_t total_read; -}; - -} // namespace duckdb +void MergeSorter::MergePartition() { + auto &left_block = *left->sb; + auto &right_block = *right->sb; +#ifdef DEBUG + D_ASSERT(left_block.radix_sorting_data.size() == left_block.payload_data->data_blocks.size()); + D_ASSERT(right_block.radix_sorting_data.size() == right_block.payload_data->data_blocks.size()); + if (!state.payload_layout.AllConstant() && state.external) { + D_ASSERT(left_block.payload_data->data_blocks.size() == left_block.payload_data->heap_blocks.size()); + D_ASSERT(right_block.payload_data->data_blocks.size() == right_block.payload_data->heap_blocks.size()); + } + if (!sort_layout.all_constant) { + D_ASSERT(left_block.radix_sorting_data.size() == left_block.blob_sorting_data->data_blocks.size()); + D_ASSERT(right_block.radix_sorting_data.size() == right_block.blob_sorting_data->data_blocks.size()); + if (state.external) { + D_ASSERT(left_block.blob_sorting_data->data_blocks.size() == + left_block.blob_sorting_data->heap_blocks.size()); + D_ASSERT(right_block.blob_sorting_data->data_blocks.size() == + right_block.blob_sorting_data->heap_blocks.size()); + } + } +#endif + // Set up the write block + // Each merge task produces a SortedBlock with exactly state.block_capacity rows or less + result->InitializeWrite(); + // Initialize arrays to store merge data + bool left_smaller[STANDARD_VECTOR_SIZE]; + idx_t next_entry_sizes[STANDARD_VECTOR_SIZE]; + // Merge loop +#ifdef DEBUG + auto l_count = left->Remaining(); + auto r_count = right->Remaining(); +#endif + while (true) { + auto l_remaining = left->Remaining(); + auto r_remaining = right->Remaining(); + if (l_remaining + r_remaining == 0) { + // Done + break; + } + const idx_t next = MinValue(l_remaining + r_remaining, (idx_t)STANDARD_VECTOR_SIZE); + if (l_remaining != 0 && r_remaining != 0) { + // Compute the merge (not needed if one side is exhausted) + ComputeMerge(next, left_smaller); + } + // Actually merge the data (radix, blob, and payload) + MergeRadix(next, left_smaller); + if (!sort_layout.all_constant) { + MergeData(*result->blob_sorting_data, *left_block.blob_sorting_data, *right_block.blob_sorting_data, next, + left_smaller, next_entry_sizes, true); + D_ASSERT(result->radix_sorting_data.size() == result->blob_sorting_data->data_blocks.size()); + } + MergeData(*result->payload_data, *left_block.payload_data, *right_block.payload_data, next, left_smaller, + next_entry_sizes, false); + D_ASSERT(result->radix_sorting_data.size() == result->payload_data->data_blocks.size()); + } +#ifdef DEBUG + D_ASSERT(result->Count() == l_count + r_count); +#endif +} +void MergeSorter::GetNextPartition() { + // Create result block + state.sorted_blocks_temp[state.pair_idx].push_back(make_unique(buffer_manager, state)); + result = state.sorted_blocks_temp[state.pair_idx].back().get(); + // Determine which blocks must be merged + auto &left_block = *state.sorted_blocks[state.pair_idx * 2]; + auto &right_block = *state.sorted_blocks[state.pair_idx * 2 + 1]; + const idx_t l_count = left_block.Count(); + const idx_t r_count = right_block.Count(); + // Initialize left and right reader + left = make_unique(buffer_manager, state); + right = make_unique(buffer_manager, state); + // Compute the work that this thread must do using Merge Path + idx_t l_end; + idx_t r_end; + if (state.l_start + state.r_start + state.block_capacity < l_count + r_count) { + left->sb = state.sorted_blocks[state.pair_idx * 2].get(); + right->sb = state.sorted_blocks[state.pair_idx * 2 + 1].get(); + const idx_t intersection = state.l_start + state.r_start + state.block_capacity; + GetIntersection(intersection, l_end, r_end); + D_ASSERT(l_end <= l_count); + D_ASSERT(r_end <= r_count); + D_ASSERT(intersection == l_end + r_end); + } else { + l_end = l_count; + r_end = r_count; + } + // Create slices of the data that this thread must merge + left->SetIndices(0, 0); + right->SetIndices(0, 0); + left_input = left_block.CreateSlice(state.l_start, l_end, left->entry_idx); + right_input = right_block.CreateSlice(state.r_start, r_end, right->entry_idx); + left->sb = left_input.get(); + right->sb = right_input.get(); + state.l_start = l_end; + state.r_start = r_end; + D_ASSERT(left->Remaining() + right->Remaining() == state.block_capacity || (l_end == l_count && r_end == r_count)); + // Update global state + if (state.l_start == l_count && state.r_start == r_count) { + // Delete references to previous pair + state.sorted_blocks[state.pair_idx * 2] = nullptr; + state.sorted_blocks[state.pair_idx * 2 + 1] = nullptr; + // Advance pair + state.pair_idx++; + state.l_start = 0; + state.r_start = 0; + } +} +int MergeSorter::CompareUsingGlobalIndex(SBScanState &l, SBScanState &r, const idx_t l_idx, const idx_t r_idx) { + D_ASSERT(l_idx < l.sb->Count()); + D_ASSERT(r_idx < r.sb->Count()); + // Easy comparison using the previous result (intersections must increase monotonically) + if (l_idx < state.l_start) { + return -1; + } + if (r_idx < state.r_start) { + return 1; + } -#include -#include + l.sb->GlobalToLocalIndex(l_idx, l.block_idx, l.entry_idx); + r.sb->GlobalToLocalIndex(r_idx, r.block_idx, r.entry_idx); -namespace duckdb { + l.PinRadix(l.block_idx); + r.PinRadix(r.block_idx); + data_ptr_t l_ptr = l.radix_handle.Ptr() + l.entry_idx * sort_layout.entry_size; + data_ptr_t r_ptr = r.radix_handle.Ptr() + r.entry_idx * sort_layout.entry_size; -BufferedFileReader::BufferedFileReader(FileSystem &fs, const char *path, FileOpener *opener) - : fs(fs), data(unique_ptr(new data_t[FILE_BUFFER_SIZE])), offset(0), read_data(0), total_read(0) { - handle = - fs.OpenFile(path, FileFlags::FILE_FLAGS_READ, FileLockType::READ_LOCK, FileSystem::DEFAULT_COMPRESSION, opener); - file_size = fs.GetFileSize(*handle); + int comp_res; + if (sort_layout.all_constant) { + comp_res = FastMemcmp(l_ptr, r_ptr, sort_layout.comparison_size); + } else { + l.PinData(*l.sb->blob_sorting_data); + r.PinData(*r.sb->blob_sorting_data); + comp_res = Comparators::CompareTuple(l, r, l_ptr, r_ptr, sort_layout, state.external); + } + return comp_res; } -void BufferedFileReader::ReadData(data_ptr_t target_buffer, uint64_t read_size) { - // first copy anything we can from the buffer - data_ptr_t end_ptr = target_buffer + read_size; - while (true) { - idx_t to_read = MinValue(end_ptr - target_buffer, read_data - offset); - if (to_read > 0) { - memcpy(target_buffer, data.get() + offset, to_read); - offset += to_read; - target_buffer += to_read; - } - if (target_buffer < end_ptr) { - D_ASSERT(offset == read_data); - total_read += read_data; - // did not finish reading yet but exhausted buffer - // read data into buffer - offset = 0; - read_data = fs.Read(*handle, data.get(), FILE_BUFFER_SIZE); - if (read_data == 0) { - throw SerializationException("not enough data in file to deserialize result"); +void MergeSorter::GetIntersection(const idx_t diagonal, idx_t &l_idx, idx_t &r_idx) { + const idx_t l_count = left->sb->Count(); + const idx_t r_count = right->sb->Count(); + // Cover some edge cases + // Code coverage off because these edge cases cannot happen unless other code changes + // Edge cases have been tested extensively while developing Merge Path in a script + // LCOV_EXCL_START + if (diagonal >= l_count + r_count) { + l_idx = l_count; + r_idx = r_count; + return; + } else if (diagonal == 0) { + l_idx = 0; + r_idx = 0; + return; + } else if (l_count == 0) { + l_idx = 0; + r_idx = diagonal; + return; + } else if (r_count == 0) { + r_idx = 0; + l_idx = diagonal; + return; + } + // LCOV_EXCL_STOP + // Determine offsets for the binary search + const idx_t l_offset = MinValue(l_count, diagonal); + const idx_t r_offset = diagonal > l_count ? diagonal - l_count : 0; + D_ASSERT(l_offset + r_offset == diagonal); + const idx_t search_space = diagonal > MaxValue(l_count, r_count) ? l_count + r_count - diagonal + : MinValue(diagonal, MinValue(l_count, r_count)); + // Double binary search + idx_t li = 0; + idx_t ri = search_space - 1; + idx_t middle; + int comp_res; + while (li <= ri) { + middle = (li + ri) / 2; + l_idx = l_offset - middle; + r_idx = r_offset + middle; + if (l_idx == l_count || r_idx == 0) { + comp_res = CompareUsingGlobalIndex(*left, *right, l_idx - 1, r_idx); + if (comp_res > 0) { + l_idx--; + r_idx++; + } else { + return; + } + if (l_idx == 0 || r_idx == r_count) { + // This case is incredibly difficult to cover as it is dependent on parallelism randomness + // But it has been tested extensively during development in a script + // LCOV_EXCL_START + return; + // LCOV_EXCL_STOP + } else { + break; } + } + comp_res = CompareUsingGlobalIndex(*left, *right, l_idx, r_idx); + if (comp_res > 0) { + li = middle + 1; } else { - return; + ri = middle - 1; } } + int l_r_min1 = CompareUsingGlobalIndex(*left, *right, l_idx, r_idx - 1); + int l_min1_r = CompareUsingGlobalIndex(*left, *right, l_idx - 1, r_idx); + if (l_r_min1 > 0 && l_min1_r < 0) { + return; + } else if (l_r_min1 > 0) { + l_idx--; + r_idx++; + } else if (l_min1_r < 0) { + l_idx++; + r_idx--; + } } -bool BufferedFileReader::Finished() { - return total_read + offset == file_size; +void MergeSorter::ComputeMerge(const idx_t &count, bool left_smaller[]) { + auto &l = *left; + auto &r = *right; + auto &l_sorted_block = *l.sb; + auto &r_sorted_block = *r.sb; + // Save indices to restore afterwards + idx_t l_block_idx_before = l.block_idx; + idx_t l_entry_idx_before = l.entry_idx; + idx_t r_block_idx_before = r.block_idx; + idx_t r_entry_idx_before = r.entry_idx; + // Data pointers for both sides + data_ptr_t l_radix_ptr; + data_ptr_t r_radix_ptr; + // Compute the merge of the next 'count' tuples + idx_t compared = 0; + while (compared < count) { + // Move to the next block (if needed) + if (l.block_idx < l_sorted_block.radix_sorting_data.size() && + l.entry_idx == l_sorted_block.radix_sorting_data[l.block_idx]->count) { + l.block_idx++; + l.entry_idx = 0; + } + if (r.block_idx < r_sorted_block.radix_sorting_data.size() && + r.entry_idx == r_sorted_block.radix_sorting_data[r.block_idx]->count) { + r.block_idx++; + r.entry_idx = 0; + } + const bool l_done = l.block_idx == l_sorted_block.radix_sorting_data.size(); + const bool r_done = r.block_idx == r_sorted_block.radix_sorting_data.size(); + if (l_done || r_done) { + // One of the sides is exhausted, no need to compare + break; + } + // Pin the radix sorting data + if (!l_done) { + left->PinRadix(l.block_idx); + l_radix_ptr = left->RadixPtr(); + } + if (!r_done) { + right->PinRadix(r.block_idx); + r_radix_ptr = right->RadixPtr(); + } + const idx_t &l_count = !l_done ? l_sorted_block.radix_sorting_data[l.block_idx]->count : 0; + const idx_t &r_count = !r_done ? r_sorted_block.radix_sorting_data[r.block_idx]->count : 0; + // Compute the merge + if (sort_layout.all_constant) { + // All sorting columns are constant size + for (; compared < count && l.entry_idx < l_count && r.entry_idx < r_count; compared++) { + left_smaller[compared] = FastMemcmp(l_radix_ptr, r_radix_ptr, sort_layout.comparison_size) < 0; + const bool &l_smaller = left_smaller[compared]; + const bool r_smaller = !l_smaller; + // Use comparison bool (0 or 1) to increment entries and pointers + l.entry_idx += l_smaller; + r.entry_idx += r_smaller; + l_radix_ptr += l_smaller * sort_layout.entry_size; + r_radix_ptr += r_smaller * sort_layout.entry_size; + } + } else { + // Pin the blob data + if (!l_done) { + left->PinData(*l_sorted_block.blob_sorting_data); + } + if (!r_done) { + right->PinData(*r_sorted_block.blob_sorting_data); + } + // Merge with variable size sorting columns + for (; compared < count && l.entry_idx < l_count && r.entry_idx < r_count; compared++) { + left_smaller[compared] = + Comparators::CompareTuple(*left, *right, l_radix_ptr, r_radix_ptr, sort_layout, state.external) < 0; + const bool &l_smaller = left_smaller[compared]; + const bool r_smaller = !l_smaller; + // Use comparison bool (0 or 1) to increment entries and pointers + l.entry_idx += l_smaller; + r.entry_idx += r_smaller; + l_radix_ptr += l_smaller * sort_layout.entry_size; + r_radix_ptr += r_smaller * sort_layout.entry_size; + } + } + } + // Reset block indices + left->SetIndices(l_block_idx_before, l_entry_idx_before); + right->SetIndices(r_block_idx_before, r_entry_idx_before); } -} // namespace duckdb +void MergeSorter::MergeRadix(const idx_t &count, const bool left_smaller[]) { + auto &l = *left; + auto &r = *right; + // Save indices to restore afterwards + idx_t l_block_idx_before = l.block_idx; + idx_t l_entry_idx_before = l.entry_idx; + idx_t r_block_idx_before = r.block_idx; + idx_t r_entry_idx_before = r.entry_idx; + auto &l_blocks = l.sb->radix_sorting_data; + auto &r_blocks = r.sb->radix_sorting_data; + RowDataBlock *l_block; + RowDataBlock *r_block; + data_ptr_t l_ptr; + data_ptr_t r_ptr; -#include + RowDataBlock *result_block = result->radix_sorting_data.back().get(); + auto result_handle = buffer_manager.Pin(result_block->block); + data_ptr_t result_ptr = result_handle.Ptr() + result_block->count * sort_layout.entry_size; -namespace duckdb { + idx_t copied = 0; + while (copied < count) { + // Move to the next block (if needed) + if (l.block_idx < l_blocks.size() && l.entry_idx == l_blocks[l.block_idx]->count) { + // Delete reference to previous block + l_blocks[l.block_idx]->block = nullptr; + // Advance block + l.block_idx++; + l.entry_idx = 0; + } + if (r.block_idx < r_blocks.size() && r.entry_idx == r_blocks[r.block_idx]->count) { + // Delete reference to previous block + r_blocks[r.block_idx]->block = nullptr; + // Advance block + r.block_idx++; + r.entry_idx = 0; + } + const bool l_done = l.block_idx == l_blocks.size(); + const bool r_done = r.block_idx == r_blocks.size(); + // Pin the radix sortable blocks + if (!l_done) { + l_block = l_blocks[l.block_idx].get(); + left->PinRadix(l.block_idx); + l_ptr = l.RadixPtr(); + } + if (!r_done) { + r_block = r_blocks[r.block_idx].get(); + r.PinRadix(r.block_idx); + r_ptr = r.RadixPtr(); + } + const idx_t &l_count = !l_done ? l_block->count : 0; + const idx_t &r_count = !r_done ? r_block->count : 0; + // Copy using computed merge + if (!l_done && !r_done) { + // Both sides have data - merge + MergeRows(l_ptr, l.entry_idx, l_count, r_ptr, r.entry_idx, r_count, *result_block, result_ptr, + sort_layout.entry_size, left_smaller, copied, count); + } else if (r_done) { + // Right side is exhausted + FlushRows(l_ptr, l.entry_idx, l_count, *result_block, result_ptr, sort_layout.entry_size, copied, count); + } else { + // Left side is exhausted + FlushRows(r_ptr, r.entry_idx, r_count, *result_block, result_ptr, sort_layout.entry_size, copied, count); + } + } + // Reset block indices + left->SetIndices(l_block_idx_before, l_entry_idx_before); + right->SetIndices(r_block_idx_before, r_entry_idx_before); +} -// Remove this when we switch C++17: https://stackoverflow.com/a/53350948 -constexpr uint8_t BufferedFileWriter::DEFAULT_OPEN_FLAGS; +void MergeSorter::MergeData(SortedData &result_data, SortedData &l_data, SortedData &r_data, const idx_t &count, + const bool left_smaller[], idx_t next_entry_sizes[], bool reset_indices) { + auto &l = *left; + auto &r = *right; + // Save indices to restore afterwards + idx_t l_block_idx_before = l.block_idx; + idx_t l_entry_idx_before = l.entry_idx; + idx_t r_block_idx_before = r.block_idx; + idx_t r_entry_idx_before = r.entry_idx; -BufferedFileWriter::BufferedFileWriter(FileSystem &fs, const string &path_p, uint8_t open_flags, FileOpener *opener) - : fs(fs), path(path_p), data(unique_ptr(new data_t[FILE_BUFFER_SIZE])), offset(0), total_written(0) { - handle = fs.OpenFile(path, open_flags, FileLockType::WRITE_LOCK, FileSystem::DEFAULT_COMPRESSION, opener); -} + const auto &layout = result_data.layout; + const idx_t row_width = layout.GetRowWidth(); + const idx_t heap_pointer_offset = layout.GetHeapOffset(); -int64_t BufferedFileWriter::GetFileSize() { - return fs.GetFileSize(*handle); -} + // Left and right row data to merge + data_ptr_t l_ptr; + data_ptr_t r_ptr; + // Accompanying left and right heap data (if needed) + data_ptr_t l_heap_ptr; + data_ptr_t r_heap_ptr; -idx_t BufferedFileWriter::GetTotalWritten() { - return total_written + offset; -} + // Result rows to write to + RowDataBlock *result_data_block = result_data.data_blocks.back().get(); + auto result_data_handle = buffer_manager.Pin(result_data_block->block); + data_ptr_t result_data_ptr = result_data_handle.Ptr() + result_data_block->count * row_width; + // Result heap to write to (if needed) + RowDataBlock *result_heap_block; + BufferHandle result_heap_handle; + data_ptr_t result_heap_ptr; + if (!layout.AllConstant() && state.external) { + result_heap_block = result_data.heap_blocks.back().get(); + result_heap_handle = buffer_manager.Pin(result_heap_block->block); + result_heap_ptr = result_heap_handle.Ptr() + result_heap_block->byte_offset; + } -void BufferedFileWriter::WriteData(const_data_ptr_t buffer, uint64_t write_size) { - // first copy anything we can from the buffer - const_data_ptr_t end_ptr = buffer + write_size; - while (buffer < end_ptr) { - idx_t to_write = MinValue((end_ptr - buffer), FILE_BUFFER_SIZE - offset); - D_ASSERT(to_write > 0); - memcpy(data.get() + offset, buffer, to_write); - offset += to_write; - buffer += to_write; - if (offset == FILE_BUFFER_SIZE) { - Flush(); + idx_t copied = 0; + while (copied < count) { + // Move to new data blocks (if needed) + if (l.block_idx < l_data.data_blocks.size() && l.entry_idx == l_data.data_blocks[l.block_idx]->count) { + // Delete reference to previous block + l_data.data_blocks[l.block_idx]->block = nullptr; + if (!layout.AllConstant() && state.external) { + l_data.heap_blocks[l.block_idx]->block = nullptr; + } + // Advance block + l.block_idx++; + l.entry_idx = 0; + } + if (r.block_idx < r_data.data_blocks.size() && r.entry_idx == r_data.data_blocks[r.block_idx]->count) { + // Delete reference to previous block + r_data.data_blocks[r.block_idx]->block = nullptr; + if (!layout.AllConstant() && state.external) { + r_data.heap_blocks[r.block_idx]->block = nullptr; + } + // Advance block + r.block_idx++; + r.entry_idx = 0; + } + const bool l_done = l.block_idx == l_data.data_blocks.size(); + const bool r_done = r.block_idx == r_data.data_blocks.size(); + // Pin the row data blocks + if (!l_done) { + l.PinData(l_data); + l_ptr = l.DataPtr(l_data); + } + if (!r_done) { + r.PinData(r_data); + r_ptr = r.DataPtr(r_data); + } + const idx_t &l_count = !l_done ? l_data.data_blocks[l.block_idx]->count : 0; + const idx_t &r_count = !r_done ? r_data.data_blocks[r.block_idx]->count : 0; + // Perform the merge + if (layout.AllConstant() || !state.external) { + // If all constant size, or if we are doing an in-memory sort, we do not need to touch the heap + if (!l_done && !r_done) { + // Both sides have data - merge + MergeRows(l_ptr, l.entry_idx, l_count, r_ptr, r.entry_idx, r_count, *result_data_block, result_data_ptr, + row_width, left_smaller, copied, count); + } else if (r_done) { + // Right side is exhausted + FlushRows(l_ptr, l.entry_idx, l_count, *result_data_block, result_data_ptr, row_width, copied, count); + } else { + // Left side is exhausted + FlushRows(r_ptr, r.entry_idx, r_count, *result_data_block, result_data_ptr, row_width, copied, count); + } + } else { + // External sorting with variable size data. Pin the heap blocks too + if (!l_done) { + l_heap_ptr = l.BaseHeapPtr(l_data) + Load(l_ptr + heap_pointer_offset); + D_ASSERT(l_heap_ptr - l.BaseHeapPtr(l_data) >= 0); + D_ASSERT((idx_t)(l_heap_ptr - l.BaseHeapPtr(l_data)) < l_data.heap_blocks[l.block_idx]->byte_offset); + } + if (!r_done) { + r_heap_ptr = r.BaseHeapPtr(r_data) + Load(r_ptr + heap_pointer_offset); + D_ASSERT(r_heap_ptr - r.BaseHeapPtr(r_data) >= 0); + D_ASSERT((idx_t)(r_heap_ptr - r.BaseHeapPtr(r_data)) < r_data.heap_blocks[r.block_idx]->byte_offset); + } + // Both the row and heap data need to be dealt with + if (!l_done && !r_done) { + // Both sides have data - merge + idx_t l_idx_copy = l.entry_idx; + idx_t r_idx_copy = r.entry_idx; + data_ptr_t result_data_ptr_copy = result_data_ptr; + idx_t copied_copy = copied; + // Merge row data + MergeRows(l_ptr, l_idx_copy, l_count, r_ptr, r_idx_copy, r_count, *result_data_block, + result_data_ptr_copy, row_width, left_smaller, copied_copy, count); + const idx_t merged = copied_copy - copied; + // Compute the entry sizes and number of heap bytes that will be copied + idx_t copy_bytes = 0; + data_ptr_t l_heap_ptr_copy = l_heap_ptr; + data_ptr_t r_heap_ptr_copy = r_heap_ptr; + for (idx_t i = 0; i < merged; i++) { + // Store base heap offset in the row data + Store(result_heap_block->byte_offset + copy_bytes, result_data_ptr + heap_pointer_offset); + result_data_ptr += row_width; + // Compute entry size and add to total + const bool &l_smaller = left_smaller[copied + i]; + const bool r_smaller = !l_smaller; + auto &entry_size = next_entry_sizes[copied + i]; + entry_size = + l_smaller * Load(l_heap_ptr_copy) + r_smaller * Load(r_heap_ptr_copy); + D_ASSERT(entry_size >= sizeof(uint32_t)); + D_ASSERT(l_heap_ptr_copy - l.BaseHeapPtr(l_data) + l_smaller * entry_size <= + l_data.heap_blocks[l.block_idx]->byte_offset); + D_ASSERT(r_heap_ptr_copy - r.BaseHeapPtr(r_data) + r_smaller * entry_size <= + r_data.heap_blocks[r.block_idx]->byte_offset); + l_heap_ptr_copy += l_smaller * entry_size; + r_heap_ptr_copy += r_smaller * entry_size; + copy_bytes += entry_size; + } + // Reallocate result heap block size (if needed) + if (result_heap_block->byte_offset + copy_bytes > result_heap_block->capacity) { + idx_t new_capacity = result_heap_block->byte_offset + copy_bytes; + buffer_manager.ReAllocate(result_heap_block->block, new_capacity); + result_heap_block->capacity = new_capacity; + result_heap_ptr = result_heap_handle.Ptr() + result_heap_block->byte_offset; + } + D_ASSERT(result_heap_block->byte_offset + copy_bytes <= result_heap_block->capacity); + // Now copy the heap data + for (idx_t i = 0; i < merged; i++) { + const bool &l_smaller = left_smaller[copied + i]; + const bool r_smaller = !l_smaller; + const auto &entry_size = next_entry_sizes[copied + i]; + memcpy(result_heap_ptr, (data_ptr_t)(l_smaller * (idx_t)l_heap_ptr + r_smaller * (idx_t)r_heap_ptr), + entry_size); + D_ASSERT(Load(result_heap_ptr) == entry_size); + result_heap_ptr += entry_size; + l_heap_ptr += l_smaller * entry_size; + r_heap_ptr += r_smaller * entry_size; + l.entry_idx += l_smaller; + r.entry_idx += r_smaller; + } + // Update result indices and pointers + result_heap_block->count += merged; + result_heap_block->byte_offset += copy_bytes; + copied += merged; + } else if (r_done) { + // Right side is exhausted - flush left + FlushBlobs(layout, l_count, l_ptr, l.entry_idx, l_heap_ptr, *result_data_block, result_data_ptr, + *result_heap_block, result_heap_handle, result_heap_ptr, copied, count); + } else { + // Left side is exhausted - flush right + FlushBlobs(layout, r_count, r_ptr, r.entry_idx, r_heap_ptr, *result_data_block, result_data_ptr, + *result_heap_block, result_heap_handle, result_heap_ptr, copied, count); + } + D_ASSERT(result_data_block->count == result_heap_block->count); } } + if (reset_indices) { + left->SetIndices(l_block_idx_before, l_entry_idx_before); + right->SetIndices(r_block_idx_before, r_entry_idx_before); + } } -void BufferedFileWriter::Flush() { - if (offset == 0) { - return; +void MergeSorter::MergeRows(data_ptr_t &l_ptr, idx_t &l_entry_idx, const idx_t &l_count, data_ptr_t &r_ptr, + idx_t &r_entry_idx, const idx_t &r_count, RowDataBlock &target_block, + data_ptr_t &target_ptr, const idx_t &entry_size, const bool left_smaller[], idx_t &copied, + const idx_t &count) { + const idx_t next = MinValue(count - copied, target_block.capacity - target_block.count); + idx_t i; + for (i = 0; i < next && l_entry_idx < l_count && r_entry_idx < r_count; i++) { + const bool &l_smaller = left_smaller[copied + i]; + const bool r_smaller = !l_smaller; + // Use comparison bool (0 or 1) to copy an entry from either side + FastMemcpy(target_ptr, (data_ptr_t)(l_smaller * (idx_t)l_ptr + r_smaller * (idx_t)r_ptr), entry_size); + target_ptr += entry_size; + // Use the comparison bool to increment entries and pointers + l_entry_idx += l_smaller; + r_entry_idx += r_smaller; + l_ptr += l_smaller * entry_size; + r_ptr += r_smaller * entry_size; } - fs.Write(*handle, data.get(), offset); - total_written += offset; - offset = 0; + // Update counts + target_block.count += i; + copied += i; } -void BufferedFileWriter::Sync() { - Flush(); - handle->Sync(); +void MergeSorter::FlushRows(data_ptr_t &source_ptr, idx_t &source_entry_idx, const idx_t &source_count, + RowDataBlock &target_block, data_ptr_t &target_ptr, const idx_t &entry_size, idx_t &copied, + const idx_t &count) { + // Compute how many entries we can fit + idx_t next = MinValue(count - copied, target_block.capacity - target_block.count); + next = MinValue(next, source_count - source_entry_idx); + // Copy them all in a single memcpy + const idx_t copy_bytes = next * entry_size; + memcpy(target_ptr, source_ptr, copy_bytes); + target_ptr += copy_bytes; + source_ptr += copy_bytes; + // Update counts + source_entry_idx += next; + target_block.count += next; + copied += next; } -void BufferedFileWriter::Truncate(int64_t size) { - // truncate the physical file on disk - handle->Truncate(size); - // reset anything written in the buffer - offset = 0; +void MergeSorter::FlushBlobs(const RowLayout &layout, const idx_t &source_count, data_ptr_t &source_data_ptr, + idx_t &source_entry_idx, data_ptr_t &source_heap_ptr, RowDataBlock &target_data_block, + data_ptr_t &target_data_ptr, RowDataBlock &target_heap_block, + BufferHandle &target_heap_handle, data_ptr_t &target_heap_ptr, idx_t &copied, + const idx_t &count) { + const idx_t row_width = layout.GetRowWidth(); + const idx_t heap_pointer_offset = layout.GetHeapOffset(); + idx_t source_entry_idx_copy = source_entry_idx; + data_ptr_t target_data_ptr_copy = target_data_ptr; + idx_t copied_copy = copied; + // Flush row data + FlushRows(source_data_ptr, source_entry_idx_copy, source_count, target_data_block, target_data_ptr_copy, row_width, + copied_copy, count); + const idx_t flushed = copied_copy - copied; + // Compute the entry sizes and number of heap bytes that will be copied + idx_t copy_bytes = 0; + data_ptr_t source_heap_ptr_copy = source_heap_ptr; + for (idx_t i = 0; i < flushed; i++) { + // Store base heap offset in the row data + Store(target_heap_block.byte_offset + copy_bytes, target_data_ptr + heap_pointer_offset); + target_data_ptr += row_width; + // Compute entry size and add to total + auto entry_size = Load(source_heap_ptr_copy); + D_ASSERT(entry_size >= sizeof(uint32_t)); + source_heap_ptr_copy += entry_size; + copy_bytes += entry_size; + } + // Reallocate result heap block size (if needed) + if (target_heap_block.byte_offset + copy_bytes > target_heap_block.capacity) { + idx_t new_capacity = target_heap_block.byte_offset + copy_bytes; + buffer_manager.ReAllocate(target_heap_block.block, new_capacity); + target_heap_block.capacity = new_capacity; + target_heap_ptr = target_heap_handle.Ptr() + target_heap_block.byte_offset; + } + D_ASSERT(target_heap_block.byte_offset + copy_bytes <= target_heap_block.capacity); + // Copy the heap data in one go + memcpy(target_heap_ptr, source_heap_ptr, copy_bytes); + target_heap_ptr += copy_bytes; + source_heap_ptr += copy_bytes; + source_entry_idx += flushed; + copied += flushed; + // Update result indices and pointers + target_heap_block.count += flushed; + target_heap_block.byte_offset += copy_bytes; + D_ASSERT(target_heap_block.byte_offset <= target_heap_block.capacity); } } // namespace duckdb -#include + namespace duckdb { -BufferedSerializer::BufferedSerializer(idx_t maximum_size) - : BufferedSerializer(unique_ptr(new data_t[maximum_size]), maximum_size) { +//! Calls std::sort on strings that are tied by their prefix after the radix sort +static void SortTiedBlobs(BufferManager &buffer_manager, const data_ptr_t dataptr, const idx_t &start, const idx_t &end, + const idx_t &tie_col, bool *ties, const data_ptr_t blob_ptr, const SortLayout &sort_layout) { + const auto row_width = sort_layout.blob_layout.GetRowWidth(); + const idx_t &col_idx = sort_layout.sorting_to_blob_col.at(tie_col); + // Locate the first blob row in question + data_ptr_t row_ptr = dataptr + start * sort_layout.entry_size; + data_ptr_t blob_row_ptr = blob_ptr + Load(row_ptr + sort_layout.comparison_size) * row_width; + if (!Comparators::TieIsBreakable(col_idx, blob_row_ptr, sort_layout.blob_layout)) { + // Quick check to see if ties can be broken + return; + } + // Fill pointer array for sorting + auto ptr_block = unique_ptr(new data_ptr_t[end - start]); + auto entry_ptrs = (data_ptr_t *)ptr_block.get(); + for (idx_t i = start; i < end; i++) { + entry_ptrs[i - start] = row_ptr; + row_ptr += sort_layout.entry_size; + } + // Slow pointer-based sorting + const int order = sort_layout.order_types[tie_col] == OrderType::DESCENDING ? -1 : 1; + const auto &tie_col_offset = sort_layout.blob_layout.GetOffsets()[col_idx]; + auto logical_type = sort_layout.blob_layout.GetTypes()[col_idx]; + std::sort(entry_ptrs, entry_ptrs + end - start, + [&blob_ptr, &order, &sort_layout, &tie_col_offset, &row_width, &logical_type](const data_ptr_t l, + const data_ptr_t r) { + idx_t left_idx = Load(l + sort_layout.comparison_size); + idx_t right_idx = Load(r + sort_layout.comparison_size); + data_ptr_t left_ptr = blob_ptr + left_idx * row_width + tie_col_offset; + data_ptr_t right_ptr = blob_ptr + right_idx * row_width + tie_col_offset; + return order * Comparators::CompareVal(left_ptr, right_ptr, logical_type) < 0; + }); + // Re-order + auto temp_block = + buffer_manager.Allocate(MaxValue((end - start) * sort_layout.entry_size, (idx_t)Storage::BLOCK_SIZE)); + data_ptr_t temp_ptr = temp_block.Ptr(); + for (idx_t i = 0; i < end - start; i++) { + FastMemcpy(temp_ptr, entry_ptrs[i], sort_layout.entry_size); + temp_ptr += sort_layout.entry_size; + } + memcpy(dataptr + start * sort_layout.entry_size, temp_block.Ptr(), (end - start) * sort_layout.entry_size); + // Determine if there are still ties (if this is not the last column) + if (tie_col < sort_layout.column_count - 1) { + data_ptr_t idx_ptr = dataptr + start * sort_layout.entry_size + sort_layout.comparison_size; + // Load current entry + data_ptr_t current_ptr = blob_ptr + Load(idx_ptr) * row_width + tie_col_offset; + for (idx_t i = 0; i < end - start - 1; i++) { + // Load next entry and compare + idx_ptr += sort_layout.entry_size; + data_ptr_t next_ptr = blob_ptr + Load(idx_ptr) * row_width + tie_col_offset; + ties[start + i] = Comparators::CompareVal(current_ptr, next_ptr, logical_type) == 0; + current_ptr = next_ptr; + } + } } -BufferedSerializer::BufferedSerializer(unique_ptr data, idx_t size) : maximum_size(size), data(data.get()) { - blob.size = 0; - blob.data = move(data); -} +//! Identifies sequences of rows that are tied by the prefix of a blob column, and sorts them +static void SortTiedBlobs(BufferManager &buffer_manager, SortedBlock &sb, bool *ties, data_ptr_t dataptr, + const idx_t &count, const idx_t &tie_col, const SortLayout &sort_layout) { + D_ASSERT(!ties[count - 1]); + auto &blob_block = *sb.blob_sorting_data->data_blocks.back(); + auto blob_handle = buffer_manager.Pin(blob_block.block); + const data_ptr_t blob_ptr = blob_handle.Ptr(); -BufferedSerializer::BufferedSerializer(data_ptr_t data, idx_t size) : maximum_size(size), data(data) { - blob.size = 0; + for (idx_t i = 0; i < count; i++) { + if (!ties[i]) { + continue; + } + idx_t j; + for (j = i; j < count; j++) { + if (!ties[j]) { + break; + } + } + SortTiedBlobs(buffer_manager, dataptr, i, j + 1, tie_col, ties, blob_ptr, sort_layout); + i = j; + } } -void BufferedSerializer::WriteData(const_data_ptr_t buffer, idx_t write_size) { - if (blob.size + write_size >= maximum_size) { - do { - maximum_size *= 2; - } while (blob.size + write_size > maximum_size); - auto new_data = new data_t[maximum_size]; - memcpy(new_data, data, blob.size); - data = new_data; - blob.data = unique_ptr(new_data); +//! Returns whether there are any 'true' values in the ties[] array +static bool AnyTies(bool ties[], const idx_t &count) { + D_ASSERT(!ties[count - 1]); + bool any_ties = false; + for (idx_t i = 0; i < count - 1; i++) { + any_ties = any_ties || ties[i]; } - - memcpy(data + blob.size, buffer, write_size); - blob.size += write_size; + return any_ties; } -} // namespace duckdb - +//! Compares subsequent rows to check for ties +static void ComputeTies(data_ptr_t dataptr, const idx_t &count, const idx_t &col_offset, const idx_t &tie_size, + bool ties[], const SortLayout &sort_layout) { + D_ASSERT(!ties[count - 1]); + D_ASSERT(col_offset + tie_size <= sort_layout.comparison_size); + // Align dataptr + dataptr += col_offset; + for (idx_t i = 0; i < count - 1; i++) { + ties[i] = ties[i] && FastMemcmp(dataptr, dataptr + sort_layout.entry_size, tie_size) == 0; + dataptr += sort_layout.entry_size; + } +} -namespace duckdb { +//! Textbook LSD radix sort +void RadixSortLSD(BufferManager &buffer_manager, const data_ptr_t &dataptr, const idx_t &count, const idx_t &col_offset, + const idx_t &row_width, const idx_t &sorting_size) { + auto temp_block = buffer_manager.Allocate(MaxValue(count * row_width, (idx_t)Storage::BLOCK_SIZE)); + bool swap = false; -template <> -string Deserializer::Read() { - uint32_t size = Read(); - if (size == 0) { - return string(); + idx_t counts[SortConstants::VALUES_PER_RADIX]; + for (idx_t r = 1; r <= sorting_size; r++) { + // Init counts to 0 + memset(counts, 0, sizeof(counts)); + // Const some values for convenience + const data_ptr_t source_ptr = swap ? temp_block.Ptr() : dataptr; + const data_ptr_t target_ptr = swap ? dataptr : temp_block.Ptr(); + const idx_t offset = col_offset + sorting_size - r; + // Collect counts + data_ptr_t offset_ptr = source_ptr + offset; + for (idx_t i = 0; i < count; i++) { + counts[*offset_ptr]++; + offset_ptr += row_width; + } + // Compute offsets from counts + idx_t max_count = counts[0]; + for (idx_t val = 1; val < SortConstants::VALUES_PER_RADIX; val++) { + max_count = MaxValue(max_count, counts[val]); + counts[val] = counts[val] + counts[val - 1]; + } + if (max_count == count) { + continue; + } + // Re-order the data in temporary array + data_ptr_t row_ptr = source_ptr + (count - 1) * row_width; + for (idx_t i = 0; i < count; i++) { + idx_t &radix_offset = --counts[*(row_ptr + offset)]; + FastMemcpy(target_ptr + radix_offset * row_width, row_ptr, row_width); + row_ptr -= row_width; + } + swap = !swap; + } + // Move data back to original buffer (if it was swapped) + if (swap) { + memcpy(dataptr, temp_block.Ptr(), count * row_width); } - auto buffer = unique_ptr(new data_t[size]); - ReadData(buffer.get(), size); - return string((char *)buffer.get(), size); } -void Deserializer::ReadStringVector(vector &list) { - uint32_t sz = Read(); - list.resize(sz); - for (idx_t i = 0; i < sz; i++) { - list[i] = Read(); +//! Insertion sort, used when count of values is low +inline void InsertionSort(const data_ptr_t orig_ptr, const data_ptr_t temp_ptr, const idx_t &count, + const idx_t &col_offset, const idx_t &row_width, const idx_t &total_comp_width, + const idx_t &offset, bool swap) { + const data_ptr_t source_ptr = swap ? temp_ptr : orig_ptr; + const data_ptr_t target_ptr = swap ? orig_ptr : temp_ptr; + if (count > 1) { + const idx_t total_offset = col_offset + offset; + auto temp_val = unique_ptr(new data_t[row_width]); + const data_ptr_t val = temp_val.get(); + const auto comp_width = total_comp_width - offset; + for (idx_t i = 1; i < count; i++) { + FastMemcpy(val, source_ptr + i * row_width, row_width); + idx_t j = i; + while (j > 0 && + FastMemcmp(source_ptr + (j - 1) * row_width + total_offset, val + total_offset, comp_width) > 0) { + FastMemcpy(source_ptr + j * row_width, source_ptr + (j - 1) * row_width, row_width); + j--; + } + FastMemcpy(source_ptr + j * row_width, val, row_width); + } + } + if (swap) { + memcpy(target_ptr, source_ptr, count * row_width); } } -} // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/sort/comparators.hpp -// -// -//===----------------------------------------------------------------------===// - - - +//! MSD radix sort that switches to insertion sort with low bucket sizes +void RadixSortMSD(const data_ptr_t orig_ptr, const data_ptr_t temp_ptr, const idx_t &count, const idx_t &col_offset, + const idx_t &row_width, const idx_t &comp_width, const idx_t &offset, idx_t locations[], bool swap) { + const data_ptr_t source_ptr = swap ? temp_ptr : orig_ptr; + const data_ptr_t target_ptr = swap ? orig_ptr : temp_ptr; + // Init counts to 0 + memset(locations, 0, SortConstants::MSD_RADIX_LOCATIONS * sizeof(idx_t)); + idx_t *counts = locations + 1; + // Collect counts + const idx_t total_offset = col_offset + offset; + data_ptr_t offset_ptr = source_ptr + total_offset; + for (idx_t i = 0; i < count; i++) { + counts[*offset_ptr]++; + offset_ptr += row_width; + } + // Compute locations from counts + idx_t max_count = 0; + for (idx_t radix = 0; radix < SortConstants::VALUES_PER_RADIX; radix++) { + max_count = MaxValue(max_count, counts[radix]); + counts[radix] += locations[radix]; + } + if (max_count != count) { + // Re-order the data in temporary array + data_ptr_t row_ptr = source_ptr; + for (idx_t i = 0; i < count; i++) { + const idx_t &radix_offset = locations[*(row_ptr + total_offset)]++; + FastMemcpy(target_ptr + radix_offset * row_width, row_ptr, row_width); + row_ptr += row_width; + } + swap = !swap; + } + // Check if done + if (offset == comp_width - 1) { + if (swap) { + memcpy(orig_ptr, temp_ptr, count * row_width); + } + return; + } + if (max_count == count) { + RadixSortMSD(orig_ptr, temp_ptr, count, col_offset, row_width, comp_width, offset + 1, + locations + SortConstants::MSD_RADIX_LOCATIONS, swap); + return; + } + // Recurse + idx_t radix_count = locations[0]; + for (idx_t radix = 0; radix < SortConstants::VALUES_PER_RADIX; radix++) { + const idx_t loc = (locations[radix] - radix_count) * row_width; + if (radix_count > SortConstants::INSERTION_SORT_THRESHOLD) { + RadixSortMSD(orig_ptr + loc, temp_ptr + loc, radix_count, col_offset, row_width, comp_width, offset + 1, + locations + SortConstants::MSD_RADIX_LOCATIONS, swap); + } else if (radix_count != 0) { + InsertionSort(orig_ptr + loc, temp_ptr + loc, radix_count, col_offset, row_width, comp_width, offset + 1, + swap); + } + radix_count = locations[radix + 1] - locations[radix]; + } +} +//! Calls different sort functions, depending on the count and sorting sizes +void RadixSort(BufferManager &buffer_manager, const data_ptr_t &dataptr, const idx_t &count, const idx_t &col_offset, + const idx_t &sorting_size, const SortLayout &sort_layout) { + if (count <= SortConstants::INSERTION_SORT_THRESHOLD) { + InsertionSort(dataptr, nullptr, count, 0, sort_layout.entry_size, sort_layout.comparison_size, 0, false); + } else if (sorting_size <= SortConstants::MSD_RADIX_SORT_SIZE_THRESHOLD) { + RadixSortLSD(buffer_manager, dataptr, count, col_offset, sort_layout.entry_size, sorting_size); + } else { + auto temp_block = buffer_manager.Allocate(MaxValue(count * sort_layout.entry_size, (idx_t)Storage::BLOCK_SIZE)); + auto preallocated_array = unique_ptr(new idx_t[sorting_size * SortConstants::MSD_RADIX_LOCATIONS]); + RadixSortMSD(dataptr, temp_block.Ptr(), count, col_offset, sort_layout.entry_size, sorting_size, 0, + preallocated_array.get(), false); + } +} +//! Identifies sequences of rows that are tied, and calls radix sort on these +static void SubSortTiedTuples(BufferManager &buffer_manager, const data_ptr_t dataptr, const idx_t &count, + const idx_t &col_offset, const idx_t &sorting_size, bool ties[], + const SortLayout &sort_layout) { + D_ASSERT(!ties[count - 1]); + for (idx_t i = 0; i < count; i++) { + if (!ties[i]) { + continue; + } + idx_t j; + for (j = i + 1; j < count; j++) { + if (!ties[j]) { + break; + } + } + RadixSort(buffer_manager, dataptr + i * sort_layout.entry_size, j - i + 1, col_offset, sorting_size, + sort_layout); + i = j; + } +} -namespace duckdb { - -struct SortLayout; -struct SBScanState; - -using ValidityBytes = RowLayout::ValidityBytes; - -struct Comparators { -public: - //! Whether a tie between two blobs can be broken - static bool TieIsBreakable(const idx_t &col_idx, const data_ptr_t row_ptr, const RowLayout &row_layout); - //! Compares the tuples that a being read from in the 'left' and 'right blocks during merge sort - //! (only in case we cannot simply 'memcmp' - if there are blob columns) - static int CompareTuple(const SBScanState &left, const SBScanState &right, const data_ptr_t &l_ptr, - const data_ptr_t &r_ptr, const SortLayout &sort_layout, const bool &external_sort); - //! Compare two blob values - static int CompareVal(const data_ptr_t l_ptr, const data_ptr_t r_ptr, const LogicalType &type); - -private: - //! Compares two blob values that were initially tied by their prefix - static int BreakBlobTie(const idx_t &tie_col, const SBScanState &left, const SBScanState &right, - const SortLayout &sort_layout, const bool &external); - //! Compare two fixed-size values - template - static int TemplatedCompareVal(const data_ptr_t &left_ptr, const data_ptr_t &right_ptr); - - //! Compare two values at the pointers (can be recursive if nested type) - static int CompareValAndAdvance(data_ptr_t &l_ptr, data_ptr_t &r_ptr, const LogicalType &type); - //! Compares two fixed-size values at the given pointers - template - static int TemplatedCompareAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr); - //! Compares two string values at the given pointers - static int CompareStringAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr); - //! Compares two struct values at the given pointers (recursive) - static int CompareStructAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr, - const child_list_t &types); - //! Compare two list values at the pointers (can be recursive if nested type) - static int CompareListAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr, const LogicalType &type); - //! Compares a list of fixed-size values - template - static int TemplatedCompareListLoop(data_ptr_t &left_ptr, data_ptr_t &right_ptr, const ValidityBytes &left_validity, - const ValidityBytes &right_validity, const idx_t &count); - - //! Unwizzles an offset into a pointer - static void UnswizzleSingleValue(data_ptr_t data_ptr, const data_ptr_t &heap_ptr, const LogicalType &type); - //! Swizzles a pointer into an offset - static void SwizzleSingleValue(data_ptr_t data_ptr, const data_ptr_t &heap_ptr, const LogicalType &type); -}; - -} // namespace duckdb - - -// DuckDB -// -// duckdb/common/fast_mem.hpp -// -// -//===----------------------------------------------------------------------===// - - +void LocalSortState::SortInMemory() { + auto &sb = *sorted_blocks.back(); + auto &block = *sb.radix_sorting_data.back(); + const auto &count = block.count; + auto handle = buffer_manager->Pin(block.block); + const auto dataptr = handle.Ptr(); + // Assign an index to each row + data_ptr_t idx_dataptr = dataptr + sort_layout->comparison_size; + for (uint32_t i = 0; i < count; i++) { + Store(i, idx_dataptr); + idx_dataptr += sort_layout->entry_size; + } + // Radix sort and break ties until no more ties, or until all columns are sorted + idx_t sorting_size = 0; + idx_t col_offset = 0; + unique_ptr ties_ptr; + bool *ties = nullptr; + for (idx_t i = 0; i < sort_layout->column_count; i++) { + sorting_size += sort_layout->column_sizes[i]; + if (sort_layout->constant_size[i] && i < sort_layout->column_count - 1) { + // Add columns to the sorting size until we reach a variable size column, or the last column + continue; + } + if (!ties) { + // This is the first sort + RadixSort(*buffer_manager, dataptr, count, col_offset, sorting_size, *sort_layout); + ties_ptr = unique_ptr(new bool[count]); + ties = ties_ptr.get(); + std::fill_n(ties, count - 1, true); + ties[count - 1] = false; + } else { + // For subsequent sorts, we only have to subsort the tied tuples + SubSortTiedTuples(*buffer_manager, dataptr, count, col_offset, sorting_size, ties, *sort_layout); + } + if (sort_layout->constant_size[i] && i == sort_layout->column_count - 1) { + // All columns are sorted, no ties to break because last column is constant size + break; + } + ComputeTies(dataptr, count, col_offset, sorting_size, ties, *sort_layout); + if (!AnyTies(ties, count)) { + // No ties, stop sorting + break; + } -template -static inline void MemcpyFixed(void *dest, const void *src) { - memcpy(dest, src, SIZE); -} + if (!sort_layout->constant_size[i]) { + SortTiedBlobs(*buffer_manager, sb, ties, dataptr, count, i, *sort_layout); + if (!AnyTies(ties, count)) { + // No more ties after tie-breaking, stop + break; + } + } -template -static inline int MemcmpFixed(const void *str1, const void *str2) { - return memcmp(str1, str2, SIZE); + col_offset += sorting_size; + sorting_size = 0; + } } -namespace duckdb { +} // namespace duckdb -//! This templated memcpy is significantly faster than std::memcpy, -//! but only when you are calling memcpy with a const size in a loop. -//! For instance `while () { memcpy(, , const_size); ... }` -static inline void FastMemcpy(void *dest, const void *src, const size_t size) { - // LCOV_EXCL_START - switch (size) { - case 0: - return; - case 1: - return MemcpyFixed<1>(dest, src); - case 2: - return MemcpyFixed<2>(dest, src); - case 3: - return MemcpyFixed<3>(dest, src); - case 4: - return MemcpyFixed<4>(dest, src); - case 5: - return MemcpyFixed<5>(dest, src); - case 6: - return MemcpyFixed<6>(dest, src); - case 7: - return MemcpyFixed<7>(dest, src); - case 8: - return MemcpyFixed<8>(dest, src); - case 9: - return MemcpyFixed<9>(dest, src); - case 10: - return MemcpyFixed<10>(dest, src); - case 11: - return MemcpyFixed<11>(dest, src); - case 12: - return MemcpyFixed<12>(dest, src); - case 13: - return MemcpyFixed<13>(dest, src); - case 14: - return MemcpyFixed<14>(dest, src); - case 15: - return MemcpyFixed<15>(dest, src); - case 16: - return MemcpyFixed<16>(dest, src); - case 17: - return MemcpyFixed<17>(dest, src); - case 18: - return MemcpyFixed<18>(dest, src); - case 19: - return MemcpyFixed<19>(dest, src); - case 20: - return MemcpyFixed<20>(dest, src); - case 21: - return MemcpyFixed<21>(dest, src); - case 22: - return MemcpyFixed<22>(dest, src); - case 23: - return MemcpyFixed<23>(dest, src); - case 24: - return MemcpyFixed<24>(dest, src); - case 25: - return MemcpyFixed<25>(dest, src); - case 26: - return MemcpyFixed<26>(dest, src); - case 27: - return MemcpyFixed<27>(dest, src); - case 28: - return MemcpyFixed<28>(dest, src); - case 29: - return MemcpyFixed<29>(dest, src); - case 30: - return MemcpyFixed<30>(dest, src); - case 31: - return MemcpyFixed<31>(dest, src); - case 32: - return MemcpyFixed<32>(dest, src); - case 33: - return MemcpyFixed<33>(dest, src); - case 34: - return MemcpyFixed<34>(dest, src); - case 35: - return MemcpyFixed<35>(dest, src); - case 36: - return MemcpyFixed<36>(dest, src); - case 37: - return MemcpyFixed<37>(dest, src); - case 38: - return MemcpyFixed<38>(dest, src); - case 39: - return MemcpyFixed<39>(dest, src); - case 40: - return MemcpyFixed<40>(dest, src); - case 41: - return MemcpyFixed<41>(dest, src); - case 42: - return MemcpyFixed<42>(dest, src); - case 43: - return MemcpyFixed<43>(dest, src); - case 44: - return MemcpyFixed<44>(dest, src); - case 45: - return MemcpyFixed<45>(dest, src); - case 46: - return MemcpyFixed<46>(dest, src); - case 47: - return MemcpyFixed<47>(dest, src); - case 48: - return MemcpyFixed<48>(dest, src); - case 49: - return MemcpyFixed<49>(dest, src); - case 50: - return MemcpyFixed<50>(dest, src); - case 51: - return MemcpyFixed<51>(dest, src); - case 52: - return MemcpyFixed<52>(dest, src); - case 53: - return MemcpyFixed<53>(dest, src); - case 54: - return MemcpyFixed<54>(dest, src); - case 55: - return MemcpyFixed<55>(dest, src); - case 56: - return MemcpyFixed<56>(dest, src); - case 57: - return MemcpyFixed<57>(dest, src); - case 58: - return MemcpyFixed<58>(dest, src); - case 59: - return MemcpyFixed<59>(dest, src); - case 60: - return MemcpyFixed<60>(dest, src); - case 61: - return MemcpyFixed<61>(dest, src); - case 62: - return MemcpyFixed<62>(dest, src); - case 63: - return MemcpyFixed<63>(dest, src); - case 64: - return MemcpyFixed<64>(dest, src); - case 65: - return MemcpyFixed<65>(dest, src); - case 66: - return MemcpyFixed<66>(dest, src); - case 67: - return MemcpyFixed<67>(dest, src); - case 68: - return MemcpyFixed<68>(dest, src); - case 69: - return MemcpyFixed<69>(dest, src); - case 70: - return MemcpyFixed<70>(dest, src); - case 71: - return MemcpyFixed<71>(dest, src); - case 72: - return MemcpyFixed<72>(dest, src); - case 73: - return MemcpyFixed<73>(dest, src); - case 74: - return MemcpyFixed<74>(dest, src); - case 75: - return MemcpyFixed<75>(dest, src); - case 76: - return MemcpyFixed<76>(dest, src); - case 77: - return MemcpyFixed<77>(dest, src); - case 78: - return MemcpyFixed<78>(dest, src); - case 79: - return MemcpyFixed<79>(dest, src); - case 80: - return MemcpyFixed<80>(dest, src); - case 81: - return MemcpyFixed<81>(dest, src); - case 82: - return MemcpyFixed<82>(dest, src); - case 83: - return MemcpyFixed<83>(dest, src); - case 84: - return MemcpyFixed<84>(dest, src); - case 85: - return MemcpyFixed<85>(dest, src); - case 86: - return MemcpyFixed<86>(dest, src); - case 87: - return MemcpyFixed<87>(dest, src); - case 88: - return MemcpyFixed<88>(dest, src); - case 89: - return MemcpyFixed<89>(dest, src); - case 90: - return MemcpyFixed<90>(dest, src); - case 91: - return MemcpyFixed<91>(dest, src); - case 92: - return MemcpyFixed<92>(dest, src); - case 93: - return MemcpyFixed<93>(dest, src); - case 94: - return MemcpyFixed<94>(dest, src); - case 95: - return MemcpyFixed<95>(dest, src); - case 96: - return MemcpyFixed<96>(dest, src); - case 97: - return MemcpyFixed<97>(dest, src); - case 98: - return MemcpyFixed<98>(dest, src); - case 99: - return MemcpyFixed<99>(dest, src); - case 100: - return MemcpyFixed<100>(dest, src); - case 101: - return MemcpyFixed<101>(dest, src); - case 102: - return MemcpyFixed<102>(dest, src); - case 103: - return MemcpyFixed<103>(dest, src); - case 104: - return MemcpyFixed<104>(dest, src); - case 105: - return MemcpyFixed<105>(dest, src); - case 106: - return MemcpyFixed<106>(dest, src); - case 107: - return MemcpyFixed<107>(dest, src); - case 108: - return MemcpyFixed<108>(dest, src); - case 109: - return MemcpyFixed<109>(dest, src); - case 110: - return MemcpyFixed<110>(dest, src); - case 111: - return MemcpyFixed<111>(dest, src); - case 112: - return MemcpyFixed<112>(dest, src); - case 113: - return MemcpyFixed<113>(dest, src); - case 114: - return MemcpyFixed<114>(dest, src); - case 115: - return MemcpyFixed<115>(dest, src); - case 116: - return MemcpyFixed<116>(dest, src); - case 117: - return MemcpyFixed<117>(dest, src); - case 118: - return MemcpyFixed<118>(dest, src); - case 119: - return MemcpyFixed<119>(dest, src); - case 120: - return MemcpyFixed<120>(dest, src); - case 121: - return MemcpyFixed<121>(dest, src); - case 122: - return MemcpyFixed<122>(dest, src); - case 123: - return MemcpyFixed<123>(dest, src); - case 124: - return MemcpyFixed<124>(dest, src); - case 125: - return MemcpyFixed<125>(dest, src); - case 126: - return MemcpyFixed<126>(dest, src); - case 127: - return MemcpyFixed<127>(dest, src); - case 128: - return MemcpyFixed<128>(dest, src); - case 129: - return MemcpyFixed<129>(dest, src); - case 130: - return MemcpyFixed<130>(dest, src); - case 131: - return MemcpyFixed<131>(dest, src); - case 132: - return MemcpyFixed<132>(dest, src); - case 133: - return MemcpyFixed<133>(dest, src); - case 134: - return MemcpyFixed<134>(dest, src); - case 135: - return MemcpyFixed<135>(dest, src); - case 136: - return MemcpyFixed<136>(dest, src); - case 137: - return MemcpyFixed<137>(dest, src); - case 138: - return MemcpyFixed<138>(dest, src); - case 139: - return MemcpyFixed<139>(dest, src); - case 140: - return MemcpyFixed<140>(dest, src); - case 141: - return MemcpyFixed<141>(dest, src); - case 142: - return MemcpyFixed<142>(dest, src); - case 143: - return MemcpyFixed<143>(dest, src); - case 144: - return MemcpyFixed<144>(dest, src); - case 145: - return MemcpyFixed<145>(dest, src); - case 146: - return MemcpyFixed<146>(dest, src); - case 147: - return MemcpyFixed<147>(dest, src); - case 148: - return MemcpyFixed<148>(dest, src); - case 149: - return MemcpyFixed<149>(dest, src); - case 150: - return MemcpyFixed<150>(dest, src); - case 151: - return MemcpyFixed<151>(dest, src); - case 152: - return MemcpyFixed<152>(dest, src); - case 153: - return MemcpyFixed<153>(dest, src); - case 154: - return MemcpyFixed<154>(dest, src); - case 155: - return MemcpyFixed<155>(dest, src); - case 156: - return MemcpyFixed<156>(dest, src); - case 157: - return MemcpyFixed<157>(dest, src); - case 158: - return MemcpyFixed<158>(dest, src); - case 159: - return MemcpyFixed<159>(dest, src); - case 160: - return MemcpyFixed<160>(dest, src); - case 161: - return MemcpyFixed<161>(dest, src); - case 162: - return MemcpyFixed<162>(dest, src); - case 163: - return MemcpyFixed<163>(dest, src); - case 164: - return MemcpyFixed<164>(dest, src); - case 165: - return MemcpyFixed<165>(dest, src); - case 166: - return MemcpyFixed<166>(dest, src); - case 167: - return MemcpyFixed<167>(dest, src); - case 168: - return MemcpyFixed<168>(dest, src); - case 169: - return MemcpyFixed<169>(dest, src); - case 170: - return MemcpyFixed<170>(dest, src); - case 171: - return MemcpyFixed<171>(dest, src); - case 172: - return MemcpyFixed<172>(dest, src); - case 173: - return MemcpyFixed<173>(dest, src); - case 174: - return MemcpyFixed<174>(dest, src); - case 175: - return MemcpyFixed<175>(dest, src); - case 176: - return MemcpyFixed<176>(dest, src); - case 177: - return MemcpyFixed<177>(dest, src); - case 178: - return MemcpyFixed<178>(dest, src); - case 179: - return MemcpyFixed<179>(dest, src); - case 180: - return MemcpyFixed<180>(dest, src); - case 181: - return MemcpyFixed<181>(dest, src); - case 182: - return MemcpyFixed<182>(dest, src); - case 183: - return MemcpyFixed<183>(dest, src); - case 184: - return MemcpyFixed<184>(dest, src); - case 185: - return MemcpyFixed<185>(dest, src); - case 186: - return MemcpyFixed<186>(dest, src); - case 187: - return MemcpyFixed<187>(dest, src); - case 188: - return MemcpyFixed<188>(dest, src); - case 189: - return MemcpyFixed<189>(dest, src); - case 190: - return MemcpyFixed<190>(dest, src); - case 191: - return MemcpyFixed<191>(dest, src); - case 192: - return MemcpyFixed<192>(dest, src); - case 193: - return MemcpyFixed<193>(dest, src); - case 194: - return MemcpyFixed<194>(dest, src); - case 195: - return MemcpyFixed<195>(dest, src); - case 196: - return MemcpyFixed<196>(dest, src); - case 197: - return MemcpyFixed<197>(dest, src); - case 198: - return MemcpyFixed<198>(dest, src); - case 199: - return MemcpyFixed<199>(dest, src); - case 200: - return MemcpyFixed<200>(dest, src); - case 201: - return MemcpyFixed<201>(dest, src); - case 202: - return MemcpyFixed<202>(dest, src); - case 203: - return MemcpyFixed<203>(dest, src); - case 204: - return MemcpyFixed<204>(dest, src); - case 205: - return MemcpyFixed<205>(dest, src); - case 206: - return MemcpyFixed<206>(dest, src); - case 207: - return MemcpyFixed<207>(dest, src); - case 208: - return MemcpyFixed<208>(dest, src); - case 209: - return MemcpyFixed<209>(dest, src); - case 210: - return MemcpyFixed<210>(dest, src); - case 211: - return MemcpyFixed<211>(dest, src); - case 212: - return MemcpyFixed<212>(dest, src); - case 213: - return MemcpyFixed<213>(dest, src); - case 214: - return MemcpyFixed<214>(dest, src); - case 215: - return MemcpyFixed<215>(dest, src); - case 216: - return MemcpyFixed<216>(dest, src); - case 217: - return MemcpyFixed<217>(dest, src); - case 218: - return MemcpyFixed<218>(dest, src); - case 219: - return MemcpyFixed<219>(dest, src); - case 220: - return MemcpyFixed<220>(dest, src); - case 221: - return MemcpyFixed<221>(dest, src); - case 222: - return MemcpyFixed<222>(dest, src); - case 223: - return MemcpyFixed<223>(dest, src); - case 224: - return MemcpyFixed<224>(dest, src); - case 225: - return MemcpyFixed<225>(dest, src); - case 226: - return MemcpyFixed<226>(dest, src); - case 227: - return MemcpyFixed<227>(dest, src); - case 228: - return MemcpyFixed<228>(dest, src); - case 229: - return MemcpyFixed<229>(dest, src); - case 230: - return MemcpyFixed<230>(dest, src); - case 231: - return MemcpyFixed<231>(dest, src); - case 232: - return MemcpyFixed<232>(dest, src); - case 233: - return MemcpyFixed<233>(dest, src); - case 234: - return MemcpyFixed<234>(dest, src); - case 235: - return MemcpyFixed<235>(dest, src); - case 236: - return MemcpyFixed<236>(dest, src); - case 237: - return MemcpyFixed<237>(dest, src); - case 238: - return MemcpyFixed<238>(dest, src); - case 239: - return MemcpyFixed<239>(dest, src); - case 240: - return MemcpyFixed<240>(dest, src); - case 241: - return MemcpyFixed<241>(dest, src); - case 242: - return MemcpyFixed<242>(dest, src); - case 243: - return MemcpyFixed<243>(dest, src); - case 244: - return MemcpyFixed<244>(dest, src); - case 245: - return MemcpyFixed<245>(dest, src); - case 246: - return MemcpyFixed<246>(dest, src); - case 247: - return MemcpyFixed<247>(dest, src); - case 248: - return MemcpyFixed<248>(dest, src); - case 249: - return MemcpyFixed<249>(dest, src); - case 250: - return MemcpyFixed<250>(dest, src); - case 251: - return MemcpyFixed<251>(dest, src); - case 252: - return MemcpyFixed<252>(dest, src); - case 253: - return MemcpyFixed<253>(dest, src); - case 254: - return MemcpyFixed<254>(dest, src); - case 255: - return MemcpyFixed<255>(dest, src); - case 256: - return MemcpyFixed<256>(dest, src); - default: - memcpy(dest, src, size); - } - // LCOV_EXCL_STOP -} -//! This templated memcmp is significantly faster than std::memcmp, -//! but only when you are calling memcmp with a const size in a loop. -//! For instance `while () { memcmp(, , const_size); ... }` -static inline int FastMemcmp(const void *str1, const void *str2, const size_t size) { - // LCOV_EXCL_START - switch (size) { - case 0: - return 0; - case 1: - return MemcmpFixed<1>(str1, str2); - case 2: - return MemcmpFixed<2>(str1, str2); - case 3: - return MemcmpFixed<3>(str1, str2); - case 4: - return MemcmpFixed<4>(str1, str2); - case 5: - return MemcmpFixed<5>(str1, str2); - case 6: - return MemcmpFixed<6>(str1, str2); - case 7: - return MemcmpFixed<7>(str1, str2); - case 8: - return MemcmpFixed<8>(str1, str2); - case 9: - return MemcmpFixed<9>(str1, str2); - case 10: - return MemcmpFixed<10>(str1, str2); - case 11: - return MemcmpFixed<11>(str1, str2); - case 12: - return MemcmpFixed<12>(str1, str2); - case 13: - return MemcmpFixed<13>(str1, str2); - case 14: - return MemcmpFixed<14>(str1, str2); - case 15: - return MemcmpFixed<15>(str1, str2); - case 16: - return MemcmpFixed<16>(str1, str2); - case 17: - return MemcmpFixed<17>(str1, str2); - case 18: - return MemcmpFixed<18>(str1, str2); - case 19: - return MemcmpFixed<19>(str1, str2); - case 20: - return MemcmpFixed<20>(str1, str2); - case 21: - return MemcmpFixed<21>(str1, str2); - case 22: - return MemcmpFixed<22>(str1, str2); - case 23: - return MemcmpFixed<23>(str1, str2); - case 24: - return MemcmpFixed<24>(str1, str2); - case 25: - return MemcmpFixed<25>(str1, str2); - case 26: - return MemcmpFixed<26>(str1, str2); - case 27: - return MemcmpFixed<27>(str1, str2); - case 28: - return MemcmpFixed<28>(str1, str2); - case 29: - return MemcmpFixed<29>(str1, str2); - case 30: - return MemcmpFixed<30>(str1, str2); - case 31: - return MemcmpFixed<31>(str1, str2); - case 32: - return MemcmpFixed<32>(str1, str2); - case 33: - return MemcmpFixed<33>(str1, str2); - case 34: - return MemcmpFixed<34>(str1, str2); - case 35: - return MemcmpFixed<35>(str1, str2); - case 36: - return MemcmpFixed<36>(str1, str2); - case 37: - return MemcmpFixed<37>(str1, str2); - case 38: - return MemcmpFixed<38>(str1, str2); - case 39: - return MemcmpFixed<39>(str1, str2); - case 40: - return MemcmpFixed<40>(str1, str2); - case 41: - return MemcmpFixed<41>(str1, str2); - case 42: - return MemcmpFixed<42>(str1, str2); - case 43: - return MemcmpFixed<43>(str1, str2); - case 44: - return MemcmpFixed<44>(str1, str2); - case 45: - return MemcmpFixed<45>(str1, str2); - case 46: - return MemcmpFixed<46>(str1, str2); - case 47: - return MemcmpFixed<47>(str1, str2); - case 48: - return MemcmpFixed<48>(str1, str2); - case 49: - return MemcmpFixed<49>(str1, str2); - case 50: - return MemcmpFixed<50>(str1, str2); - case 51: - return MemcmpFixed<51>(str1, str2); - case 52: - return MemcmpFixed<52>(str1, str2); - case 53: - return MemcmpFixed<53>(str1, str2); - case 54: - return MemcmpFixed<54>(str1, str2); - case 55: - return MemcmpFixed<55>(str1, str2); - case 56: - return MemcmpFixed<56>(str1, str2); - case 57: - return MemcmpFixed<57>(str1, str2); - case 58: - return MemcmpFixed<58>(str1, str2); - case 59: - return MemcmpFixed<59>(str1, str2); - case 60: - return MemcmpFixed<60>(str1, str2); - case 61: - return MemcmpFixed<61>(str1, str2); - case 62: - return MemcmpFixed<62>(str1, str2); - case 63: - return MemcmpFixed<63>(str1, str2); - case 64: - return MemcmpFixed<64>(str1, str2); - default: - return memcmp(str1, str2, size); - } - // LCOV_EXCL_STOP -} -} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/sort/sort.hpp +// duckdb/storage/statistics/string_statistics.hpp // // //===----------------------------------------------------------------------===// + + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/sort/sorted_block.hpp +// duckdb/storage/statistics/validity_statistics.hpp // // //===----------------------------------------------------------------------===// @@ -36892,1709 +41850,1222 @@ static inline int FastMemcmp(const void *str1, const void *str2, const size_t si + namespace duckdb { +class Serializer; +class Deserializer; +class Vector; -class BufferManager; -struct RowDataBlock; -struct SortLayout; -struct GlobalSortState; +class ValidityStatistics : public BaseStatistics { +public: + DUCKDB_API explicit ValidityStatistics(bool has_null = false, bool has_no_null = true); -enum class SortedDataType { BLOB, PAYLOAD }; + //! Whether or not the segment can contain NULL values + bool has_null; + //! Whether or not the segment can contain values that are not null + bool has_no_null; -//! Object that holds sorted rows, and an accompanying heap if there are blobs -struct SortedData { public: - SortedData(SortedDataType type, const RowLayout &layout, BufferManager &buffer_manager, GlobalSortState &state); - //! Number of rows that this object holds - idx_t Count(); - //! Initialize new block to write to - void CreateBlock(); - //! Create a slice that holds the rows between the start and end indices - unique_ptr CreateSlice(idx_t start_block_index, idx_t end_block_index, idx_t end_entry_index); - //! Unswizzles all - void Unswizzle(); + DUCKDB_API void Merge(const BaseStatistics &other) override; -public: - const SortedDataType type; - //! Layout of this data - const RowLayout layout; - //! Data and heap blocks - vector data_blocks; - vector heap_blocks; - //! Whether the pointers in this sorted data are swizzled - bool swizzled; + DUCKDB_API bool IsConstant() const override; -private: - //! The buffer manager - BufferManager &buffer_manager; - //! The global state - GlobalSortState &state; -}; + unique_ptr Copy() const override; -//! Block that holds sorted rows: radix, blob and payload data -struct SortedBlock { -public: - SortedBlock(BufferManager &buffer_manager, GlobalSortState &gstate); - //! Number of rows that this object holds - idx_t Count() const; - //! Initialize this block to write data to - void InitializeWrite(); - //! Init new block to write to - void CreateBlock(); - //! Fill this sorted block by appending the blocks held by a vector of sorted blocks - void AppendSortedBlocks(vector> &sorted_blocks); - //! Locate the block and entry index of a row in this block, - //! given an index between 0 and the total number of rows in this block - void GlobalToLocalIndex(const idx_t &global_idx, idx_t &local_block_index, idx_t &local_entry_index); - //! Create a slice that holds the rows between the start and end indices - unique_ptr CreateSlice(const idx_t start, const idx_t end, idx_t &entry_idx); + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(FieldReader &reader); - //! Size (in bytes) of the heap of this block - idx_t HeapSize() const; - //! Total size (in bytes) of this block - idx_t SizeInBytes() const; + void Verify(Vector &vector, const SelectionVector &sel, idx_t count) const override; -public: - //! Radix/memcmp sortable data - vector radix_sorting_data; - //! Variable sized sorting data - unique_ptr blob_sorting_data; - //! Payload data - unique_ptr payload_data; + static unique_ptr Combine(const unique_ptr &lstats, + const unique_ptr &rstats); -private: - //! Buffer manager, global state, and sorting layout constants - BufferManager &buffer_manager; - GlobalSortState &state; - const SortLayout &sort_layout; - const RowLayout &payload_layout; + string ToString() const override; }; -//! State used to scan a SortedBlock e.g. during merge sort -struct SBScanState { -public: - SBScanState(BufferManager &buffer_manager, GlobalSortState &state); - - void PinRadix(idx_t block_idx_to); - void PinData(SortedData &sd); - - data_ptr_t RadixPtr() const; - data_ptr_t DataPtr(SortedData &sd) const; - data_ptr_t HeapPtr(SortedData &sd) const; - data_ptr_t BaseHeapPtr(SortedData &sd) const; +} // namespace duckdb - idx_t Remaining() const; - void SetIndices(idx_t block_idx_to, idx_t entry_idx_to); +namespace duckdb { +class StringStatistics : public BaseStatistics { public: - BufferManager &buffer_manager; - const SortLayout &sort_layout; - GlobalSortState &state; - - SortedBlock *sb; - - idx_t block_idx; - idx_t entry_idx; - - unique_ptr radix_handle = nullptr; - - unique_ptr blob_sorting_data_handle = nullptr; - unique_ptr blob_sorting_heap_handle = nullptr; - - unique_ptr payload_data_handle = nullptr; - unique_ptr payload_heap_handle = nullptr; -}; + constexpr static uint32_t MAX_STRING_MINMAX_SIZE = 8; -//! Used to scan the data into DataChunks after sorting -struct PayloadScanner { public: - PayloadScanner(SortedData &sorted_data, GlobalSortState &global_sort_state, bool flush = true); - explicit PayloadScanner(GlobalSortState &global_sort_state, bool flush = true); - - //! Scan a single block - PayloadScanner(GlobalSortState &global_sort_state, idx_t block_idx); + DUCKDB_API explicit StringStatistics(LogicalType type, StatisticsType stats_type); - //! The type layout of the payload - inline const vector &GetPayloadTypes() const { - return sorted_data.layout.GetTypes(); - } + //! The minimum value of the segment, potentially truncated + data_t min[MAX_STRING_MINMAX_SIZE]; + //! The maximum value of the segment, potentially truncated + data_t max[MAX_STRING_MINMAX_SIZE]; + //! Whether or not the column can contain unicode characters + bool has_unicode; + //! The maximum string length in bytes + uint32_t max_string_length; + //! Whether or not the segment contains any big strings in overflow blocks + bool has_overflow_strings; - //! The number of rows scanned so far - inline idx_t Scanned() const { - return total_scanned; - } +public: + DUCKDB_API void Update(const string_t &value); + DUCKDB_API void Merge(const BaseStatistics &other) override; - //! The number of remaining rows - inline idx_t Remaining() const { - return total_count - total_scanned; - } + unique_ptr Copy() const override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(FieldReader &reader, LogicalType type); + void Verify(Vector &vector, const SelectionVector &sel, idx_t count) const override; - //! Scans the next data chunk from the sorted data - void Scan(DataChunk &chunk); + FilterPropagateResult CheckZonemap(ExpressionType comparison_type, const string &value) const; -private: - //! The sorted data being scanned - SortedData &sorted_data; - //! Read state - SBScanState read_state; - //! The total count of sorted_data - const idx_t total_count; - //! The global sort state - GlobalSortState &global_sort_state; - //! Addresses used to gather from the sorted data - Vector addresses = Vector(LogicalType::POINTER); - //! The number of rows scanned so far - idx_t total_scanned; - //! Whether to flush the blocks after scanning - const bool flush; + string ToString() const override; }; } // namespace duckdb - +#include namespace duckdb { -class RowLayout; -struct LocalSortState; +idx_t GetNestedSortingColSize(idx_t &col_size, const LogicalType &type) { + auto physical_type = type.InternalType(); + if (TypeIsConstantSize(physical_type)) { + col_size += GetTypeIdSize(physical_type); + return 0; + } else { + switch (physical_type) { + case PhysicalType::VARCHAR: { + // Nested strings are between 4 and 11 chars long for alignment + auto size_before_str = col_size; + col_size += 11; + col_size -= (col_size - 12) % 8; + return col_size - size_before_str; + } + case PhysicalType::LIST: + // Lists get 2 bytes (null and empty list) + col_size += 2; + return GetNestedSortingColSize(col_size, ListType::GetChildType(type)); + case PhysicalType::MAP: + case PhysicalType::STRUCT: + // Structs get 1 bytes (null) + col_size++; + return GetNestedSortingColSize(col_size, StructType::GetChildType(type, 0)); + default: + throw NotImplementedException("Unable to order column with type %s", type.ToString()); + } + } +} -struct SortConstants { - static constexpr idx_t VALUES_PER_RADIX = 256; - static constexpr idx_t MSD_RADIX_LOCATIONS = VALUES_PER_RADIX + 1; - static constexpr idx_t INSERTION_SORT_THRESHOLD = 24; - static constexpr idx_t MSD_RADIX_SORT_SIZE_THRESHOLD = 4; -}; +SortLayout::SortLayout(const vector &orders) + : column_count(orders.size()), all_constant(true), comparison_size(0), entry_size(0) { + vector blob_layout_types; + for (idx_t i = 0; i < column_count; i++) { + const auto &order = orders[i]; -struct SortLayout { -public: - explicit SortLayout(const vector &orders); + order_types.push_back(order.type); + order_by_null_types.push_back(order.null_order); + auto &expr = *order.expression; + logical_types.push_back(expr.return_type); -public: - idx_t column_count; - vector order_types; - vector order_by_null_types; - vector logical_types; + auto physical_type = expr.return_type.InternalType(); + constant_size.push_back(TypeIsConstantSize(physical_type)); - bool all_constant; - vector constant_size; - vector column_sizes; - vector prefix_lengths; - vector stats; - vector has_null; + if (order.stats) { + stats.push_back(order.stats.get()); + has_null.push_back(stats.back()->CanHaveNull()); + } else { + stats.push_back(nullptr); + has_null.push_back(true); + } - idx_t comparison_size; - idx_t entry_size; + idx_t col_size = has_null.back() ? 1 : 0; + prefix_lengths.push_back(0); + if (!TypeIsConstantSize(physical_type) && physical_type != PhysicalType::VARCHAR) { + prefix_lengths.back() = GetNestedSortingColSize(col_size, expr.return_type); + } else if (physical_type == PhysicalType::VARCHAR) { + idx_t size_before = col_size; + if (stats.back()) { + auto &str_stats = (StringStatistics &)*stats.back(); + col_size += str_stats.max_string_length; + if (col_size > 12) { + col_size = 12; + } else { + constant_size.back() = true; + } + } else { + col_size = 12; + } + prefix_lengths.back() = col_size - size_before; + } else { + col_size += GetTypeIdSize(physical_type); + } - RowLayout blob_layout; - unordered_map sorting_to_blob_col; -}; + comparison_size += col_size; + column_sizes.push_back(col_size); + } + entry_size = comparison_size + sizeof(uint32_t); -struct GlobalSortState { -public: - GlobalSortState(BufferManager &buffer_manager, const vector &orders, RowLayout &payload_layout); + // 8-byte alignment + if (entry_size % 8 != 0) { + // First assign more bytes to strings instead of aligning + idx_t bytes_to_fill = 8 - (entry_size % 8); + for (idx_t col_idx = 0; col_idx < column_count; col_idx++) { + if (bytes_to_fill == 0) { + break; + } + if (logical_types[col_idx].InternalType() == PhysicalType::VARCHAR && stats[col_idx]) { + auto &str_stats = (StringStatistics &)*stats[col_idx]; + idx_t diff = str_stats.max_string_length - prefix_lengths[col_idx]; + if (diff > 0) { + // Increase all sizes accordingly + idx_t increase = MinValue(bytes_to_fill, diff); + column_sizes[col_idx] += increase; + prefix_lengths[col_idx] += increase; + constant_size[col_idx] = increase == diff; + comparison_size += increase; + entry_size += increase; + bytes_to_fill -= increase; + } + } + } + entry_size = AlignValue(entry_size); + } - //! Add local state sorted data to this global state - void AddLocalState(LocalSortState &local_sort_state); - //! Prepares the GlobalSortState for the merge sort phase (after completing radix sort phase) - void PrepareMergePhase(); - //! Initializes the global sort state for another round of merging - void InitializeMergeRound(); - //! Completes the cascaded merge sort round. - //! Pass true if you wish to use the radix data for further comparisons. - void CompleteMergeRound(bool keep_radix_data = false); - //! Print the sorted data to the console. - void Print(); + for (idx_t col_idx = 0; col_idx < column_count; col_idx++) { + all_constant = all_constant && constant_size[col_idx]; + if (!constant_size[col_idx]) { + sorting_to_blob_col[col_idx] = blob_layout_types.size(); + blob_layout_types.push_back(logical_types[col_idx]); + } + } -public: - //! The lock for updating the order global state - mutex lock; - //! The buffer manager - BufferManager &buffer_manager; + blob_layout.Initialize(blob_layout_types); +} - //! Sorting and payload layouts - const SortLayout sort_layout; - const RowLayout payload_layout; +LocalSortState::LocalSortState() : initialized(false) { +} - //! Sorted data - vector> sorted_blocks; - vector>> sorted_blocks_temp; - unique_ptr odd_one_out; +void LocalSortState::Initialize(GlobalSortState &global_sort_state, BufferManager &buffer_manager_p) { + sort_layout = &global_sort_state.sort_layout; + payload_layout = &global_sort_state.payload_layout; + buffer_manager = &buffer_manager_p; + // Radix sorting data + radix_sorting_data = make_unique( + *buffer_manager, RowDataCollection::EntriesPerBlock(sort_layout->entry_size), sort_layout->entry_size); + // Blob sorting data + if (!sort_layout->all_constant) { + auto blob_row_width = sort_layout->blob_layout.GetRowWidth(); + blob_sorting_data = make_unique( + *buffer_manager, RowDataCollection::EntriesPerBlock(blob_row_width), blob_row_width); + blob_sorting_heap = make_unique(*buffer_manager, (idx_t)Storage::BLOCK_SIZE, 1, true); + } + // Payload data + auto payload_row_width = payload_layout->GetRowWidth(); + payload_data = make_unique( + *buffer_manager, RowDataCollection::EntriesPerBlock(payload_row_width), payload_row_width); + payload_heap = make_unique(*buffer_manager, (idx_t)Storage::BLOCK_SIZE, 1, true); + // Init done + initialized = true; +} - //! Pinned heap data (if sorting in memory) - vector heap_blocks; - vector> pinned_blocks; +void LocalSortState::SinkChunk(DataChunk &sort, DataChunk &payload) { + D_ASSERT(sort.size() == payload.size()); + // Build and serialize sorting data to radix sortable rows + auto data_pointers = FlatVector::GetData(addresses); + auto handles = radix_sorting_data->Build(sort.size(), data_pointers, nullptr); + for (idx_t sort_col = 0; sort_col < sort.ColumnCount(); sort_col++) { + bool has_null = sort_layout->has_null[sort_col]; + bool nulls_first = sort_layout->order_by_null_types[sort_col] == OrderByNullType::NULLS_FIRST; + bool desc = sort_layout->order_types[sort_col] == OrderType::DESCENDING; + RowOperations::RadixScatter(sort.data[sort_col], sort.size(), sel_ptr, sort.size(), data_pointers, desc, + has_null, nulls_first, sort_layout->prefix_lengths[sort_col], + sort_layout->column_sizes[sort_col]); + } - //! Capacity (number of rows) used to initialize blocks - idx_t block_capacity; - //! Whether we are doing an external sort - bool external; + // Also fully serialize blob sorting columns (to be able to break ties + if (!sort_layout->all_constant) { + DataChunk blob_chunk; + blob_chunk.SetCardinality(sort.size()); + for (idx_t sort_col = 0; sort_col < sort.ColumnCount(); sort_col++) { + if (!sort_layout->constant_size[sort_col]) { + blob_chunk.data.emplace_back(sort.data[sort_col]); + } + } + handles = blob_sorting_data->Build(blob_chunk.size(), data_pointers, nullptr); + auto blob_data = blob_chunk.ToUnifiedFormat(); + RowOperations::Scatter(blob_chunk, blob_data.get(), sort_layout->blob_layout, addresses, *blob_sorting_heap, + sel_ptr, blob_chunk.size()); + D_ASSERT(blob_sorting_heap->keep_pinned); + } - //! Progress in merge path stage - idx_t pair_idx; - idx_t num_pairs; - idx_t l_start; - idx_t r_start; -}; + // Finally, serialize payload data + handles = payload_data->Build(payload.size(), data_pointers, nullptr); + auto input_data = payload.ToUnifiedFormat(); + RowOperations::Scatter(payload, input_data.get(), *payload_layout, addresses, *payload_heap, sel_ptr, + payload.size()); + D_ASSERT(payload_heap->keep_pinned); +} -struct LocalSortState { -public: - LocalSortState(); +idx_t LocalSortState::SizeInBytes() const { + idx_t size_in_bytes = radix_sorting_data->SizeInBytes() + payload_data->SizeInBytes(); + if (!sort_layout->all_constant) { + size_in_bytes += blob_sorting_data->SizeInBytes() + blob_sorting_heap->SizeInBytes(); + } + if (!payload_layout->AllConstant()) { + size_in_bytes += payload_heap->SizeInBytes(); + } + return size_in_bytes; +} - //! Initialize the layouts and RowDataCollections - void Initialize(GlobalSortState &global_sort_state, BufferManager &buffer_manager_p); - //! Sink one DataChunk into the local sort state - void SinkChunk(DataChunk &sort, DataChunk &payload); - //! Size of accumulated data in bytes - idx_t SizeInBytes() const; - //! Sort the data accumulated so far - void Sort(GlobalSortState &global_sort_state, bool reorder_heap); +void LocalSortState::Sort(GlobalSortState &global_sort_state, bool reorder_heap) { + D_ASSERT(radix_sorting_data->count == payload_data->count); + if (radix_sorting_data->count == 0) { + return; + } + // Move all data to a single SortedBlock + sorted_blocks.emplace_back(make_unique(*buffer_manager, global_sort_state)); + auto &sb = *sorted_blocks.back(); + // Fixed-size sorting data + auto sorting_block = ConcatenateBlocks(*radix_sorting_data); + sb.radix_sorting_data.push_back(move(sorting_block)); + // Variable-size sorting data + if (!sort_layout->all_constant) { + auto &blob_data = *blob_sorting_data; + auto new_block = ConcatenateBlocks(blob_data); + sb.blob_sorting_data->data_blocks.push_back(move(new_block)); + } + // Payload data + auto payload_block = ConcatenateBlocks(*payload_data); + sb.payload_data->data_blocks.push_back(move(payload_block)); + // Now perform the actual sort + SortInMemory(); + // Re-order before the merge sort + ReOrder(global_sort_state, reorder_heap); +} -private: - //! Concatenate the blocks held by a RowDataCollection into a single block - RowDataBlock ConcatenateBlocks(RowDataCollection &row_data); - //! Sorts the data in the newly created SortedBlock - void SortInMemory(); - //! Re-order the local state after sorting - void ReOrder(GlobalSortState &gstate, bool reorder_heap); - //! Re-order a SortedData object after sorting - void ReOrder(SortedData &sd, data_ptr_t sorting_ptr, RowDataCollection &heap, GlobalSortState &gstate, - bool reorder_heap); +unique_ptr LocalSortState::ConcatenateBlocks(RowDataCollection &row_data) { + // Don't copy and delete if there is only one block. + if (row_data.blocks.size() == 1) { + auto new_block = move(row_data.blocks[0]); + row_data.blocks.clear(); + row_data.count = 0; + return new_block; + } + // Create block with the correct capacity + auto buffer_manager = &row_data.buffer_manager; + const idx_t &entry_size = row_data.entry_size; + idx_t capacity = MaxValue(((idx_t)Storage::BLOCK_SIZE + entry_size - 1) / entry_size, row_data.count); + auto new_block = make_unique(*buffer_manager, capacity, entry_size); + new_block->count = row_data.count; + auto new_block_handle = buffer_manager->Pin(new_block->block); + data_ptr_t new_block_ptr = new_block_handle.Ptr(); + // Copy the data of the blocks into a single block + for (auto &block : row_data.blocks) { + auto block_handle = buffer_manager->Pin(block->block); + memcpy(new_block_ptr, block_handle.Ptr(), block->count * entry_size); + new_block_ptr += block->count * entry_size; + } + row_data.blocks.clear(); + row_data.count = 0; + return new_block; +} -public: - //! Whether this local state has been initialized - bool initialized; - //! The buffer manager - BufferManager *buffer_manager; - //! The sorting and payload layouts - const SortLayout *sort_layout; - const RowLayout *payload_layout; - //! Radix/memcmp sortable data - unique_ptr radix_sorting_data; - //! Variable sized sorting data and accompanying heap - unique_ptr blob_sorting_data; - unique_ptr blob_sorting_heap; - //! Payload data and accompanying heap - unique_ptr payload_data; - unique_ptr payload_heap; - //! Sorted data - vector> sorted_blocks; +void LocalSortState::ReOrder(SortedData &sd, data_ptr_t sorting_ptr, RowDataCollection &heap, GlobalSortState &gstate, + bool reorder_heap) { + sd.swizzled = reorder_heap; + auto &unordered_data_block = sd.data_blocks.back(); + const idx_t count = unordered_data_block->count; + auto unordered_data_handle = buffer_manager->Pin(unordered_data_block->block); + const data_ptr_t unordered_data_ptr = unordered_data_handle.Ptr(); + // Create new block that will hold re-ordered row data + auto ordered_data_block = + make_unique(*buffer_manager, unordered_data_block->capacity, unordered_data_block->entry_size); + ordered_data_block->count = count; + auto ordered_data_handle = buffer_manager->Pin(ordered_data_block->block); + data_ptr_t ordered_data_ptr = ordered_data_handle.Ptr(); + // Re-order fixed-size row layout + const idx_t row_width = sd.layout.GetRowWidth(); + const idx_t sorting_entry_size = gstate.sort_layout.entry_size; + for (idx_t i = 0; i < count; i++) { + auto index = Load(sorting_ptr); + FastMemcpy(ordered_data_ptr, unordered_data_ptr + index * row_width, row_width); + ordered_data_ptr += row_width; + sorting_ptr += sorting_entry_size; + } + ordered_data_block->block->SetSwizzling(sd.layout.AllConstant() ? nullptr : "LocalSortState::ReOrder.ordered_data"); + // Replace the unordered data block with the re-ordered data block + sd.data_blocks.clear(); + sd.data_blocks.push_back(move(ordered_data_block)); + // Deal with the heap (if necessary) + if (!sd.layout.AllConstant() && reorder_heap) { + // Swizzle the column pointers to offsets + RowOperations::SwizzleColumns(sd.layout, ordered_data_handle.Ptr(), count); + sd.data_blocks.back()->block->SetSwizzling(nullptr); + // Create a single heap block to store the ordered heap + idx_t total_byte_offset = + std::accumulate(heap.blocks.begin(), heap.blocks.end(), 0, + [](idx_t a, const unique_ptr &b) { return a + b->byte_offset; }); + idx_t heap_block_size = MaxValue(total_byte_offset, (idx_t)Storage::BLOCK_SIZE); + auto ordered_heap_block = make_unique(*buffer_manager, heap_block_size, 1); + ordered_heap_block->count = count; + ordered_heap_block->byte_offset = total_byte_offset; + auto ordered_heap_handle = buffer_manager->Pin(ordered_heap_block->block); + data_ptr_t ordered_heap_ptr = ordered_heap_handle.Ptr(); + // Fill the heap in order + ordered_data_ptr = ordered_data_handle.Ptr(); + const idx_t heap_pointer_offset = sd.layout.GetHeapOffset(); + for (idx_t i = 0; i < count; i++) { + auto heap_row_ptr = Load(ordered_data_ptr + heap_pointer_offset); + auto heap_row_size = Load(heap_row_ptr); + memcpy(ordered_heap_ptr, heap_row_ptr, heap_row_size); + ordered_heap_ptr += heap_row_size; + ordered_data_ptr += row_width; + } + // Swizzle the base pointer to the offset of each row in the heap + RowOperations::SwizzleHeapPointer(sd.layout, ordered_data_handle.Ptr(), ordered_heap_handle.Ptr(), count); + // Move the re-ordered heap to the SortedData, and clear the local heap + sd.heap_blocks.push_back(move(ordered_heap_block)); + heap.pinned_blocks.clear(); + heap.blocks.clear(); + heap.count = 0; + } +} -private: - //! Selection vector and addresses for scattering the data to rows - const SelectionVector &sel_ptr = *FlatVector::IncrementalSelectionVector(); - Vector addresses = Vector(LogicalType::POINTER); -}; +void LocalSortState::ReOrder(GlobalSortState &gstate, bool reorder_heap) { + auto &sb = *sorted_blocks.back(); + auto sorting_handle = buffer_manager->Pin(sb.radix_sorting_data.back()->block); + const data_ptr_t sorting_ptr = sorting_handle.Ptr() + gstate.sort_layout.comparison_size; + // Re-order variable size sorting columns + if (!gstate.sort_layout.all_constant) { + ReOrder(*sb.blob_sorting_data, sorting_ptr, *blob_sorting_heap, gstate, reorder_heap); + } + // And the payload + ReOrder(*sb.payload_data, sorting_ptr, *payload_heap, gstate, reorder_heap); +} -struct MergeSorter { -public: - MergeSorter(GlobalSortState &state, BufferManager &buffer_manager); +GlobalSortState::GlobalSortState(BufferManager &buffer_manager, const vector &orders, + RowLayout &payload_layout) + : buffer_manager(buffer_manager), sort_layout(SortLayout(orders)), payload_layout(payload_layout), + block_capacity(0), external(false) { +} - //! Finds and merges partitions until the current cascaded merge round is finished - void PerformInMergeRound(); +void GlobalSortState::AddLocalState(LocalSortState &local_sort_state) { + if (!local_sort_state.radix_sorting_data) { + return; + } -private: - //! The global sorting state - GlobalSortState &state; - //! The sorting and payload layouts - BufferManager &buffer_manager; - const SortLayout &sort_layout; + // Sort accumulated data + // we only re-order the heap when the data is expected to not fit in memory + // re-ordering the heap avoids random access when reading/merging but incurs a significant cost of shuffling data + // when data fits in memory, doing random access on reads is cheaper than re-shuffling + local_sort_state.Sort(*this, external || !local_sort_state.sorted_blocks.empty()); - //! The left and right reader - unique_ptr left; - unique_ptr right; + // Append local state sorted data to this global state + lock_guard append_guard(lock); + for (auto &sb : local_sort_state.sorted_blocks) { + sorted_blocks.push_back(move(sb)); + } + auto &payload_heap = local_sort_state.payload_heap; + for (idx_t i = 0; i < payload_heap->blocks.size(); i++) { + heap_blocks.push_back(move(payload_heap->blocks[i])); + pinned_blocks.push_back(move(payload_heap->pinned_blocks[i])); + } + if (!sort_layout.all_constant) { + auto &blob_heap = local_sort_state.blob_sorting_heap; + for (idx_t i = 0; i < blob_heap->blocks.size(); i++) { + heap_blocks.push_back(move(blob_heap->blocks[i])); + pinned_blocks.push_back(move(blob_heap->pinned_blocks[i])); + } + } +} - //! Input and output blocks - unique_ptr left_input; - unique_ptr right_input; - SortedBlock *result; +void GlobalSortState::PrepareMergePhase() { + // Determine if we need to use do an external sort + idx_t total_heap_size = + std::accumulate(sorted_blocks.begin(), sorted_blocks.end(), (idx_t)0, + [](idx_t a, const unique_ptr &b) { return a + b->HeapSize(); }); + if (external || (pinned_blocks.empty() && total_heap_size > 0.25 * buffer_manager.GetMaxMemory())) { + external = true; + } + // Use the data that we have to determine which partition size to use during the merge + if (external && total_heap_size > 0) { + // If we have variable size data we need to be conservative, as there might be skew + idx_t max_block_size = 0; + for (auto &sb : sorted_blocks) { + idx_t size_in_bytes = sb->SizeInBytes(); + if (size_in_bytes > max_block_size) { + max_block_size = size_in_bytes; + block_capacity = sb->Count(); + } + } + } else { + for (auto &sb : sorted_blocks) { + block_capacity = MaxValue(block_capacity, sb->Count()); + } + } + // Unswizzle and pin heap blocks if we can fit everything in memory + if (!external) { + for (auto &sb : sorted_blocks) { + sb->blob_sorting_data->Unswizzle(); + sb->payload_data->Unswizzle(); + } + } +} -private: - //! Computes the left and right block that will be merged next (Merge Path partition) - void GetNextPartition(); - //! Finds the boundary of the next partition using binary search - void GetIntersection(const idx_t diagonal, idx_t &l_idx, idx_t &r_idx); - //! Compare values within SortedBlocks using a global index - int CompareUsingGlobalIndex(SBScanState &l, SBScanState &r, const idx_t l_idx, const idx_t r_idx); +void GlobalSortState::InitializeMergeRound() { + D_ASSERT(sorted_blocks_temp.empty()); + // If we reverse this list, the blocks that were merged last will be merged first in the next round + // These are still in memory, therefore this reduces the amount of read/write to disk! + std::reverse(sorted_blocks.begin(), sorted_blocks.end()); + // Uneven number of blocks - keep one on the side + if (sorted_blocks.size() % 2 == 1) { + odd_one_out = move(sorted_blocks.back()); + sorted_blocks.pop_back(); + } + // Init merge path path indices + pair_idx = 0; + num_pairs = sorted_blocks.size() / 2; + l_start = 0; + r_start = 0; + // Allocate room for merge results + for (idx_t p_idx = 0; p_idx < num_pairs; p_idx++) { + sorted_blocks_temp.emplace_back(); + } +} - //! Finds the next partition and merges it - void MergePartition(); +void GlobalSortState::CompleteMergeRound(bool keep_radix_data) { + sorted_blocks.clear(); + for (auto &sorted_block_vector : sorted_blocks_temp) { + sorted_blocks.push_back(make_unique(buffer_manager, *this)); + sorted_blocks.back()->AppendSortedBlocks(sorted_block_vector); + } + sorted_blocks_temp.clear(); + if (odd_one_out) { + sorted_blocks.push_back(move(odd_one_out)); + odd_one_out = nullptr; + } + // Only one block left: Done! + if (sorted_blocks.size() == 1 && !keep_radix_data) { + sorted_blocks[0]->radix_sorting_data.clear(); + sorted_blocks[0]->blob_sorting_data = nullptr; + } +} +void GlobalSortState::Print() { + PayloadScanner scanner(*this, false); + DataChunk chunk; + chunk.Initialize(Allocator::DefaultAllocator(), scanner.GetPayloadTypes()); + for (;;) { + scanner.Scan(chunk); + const auto count = chunk.size(); + if (!count) { + break; + } + chunk.Print(); + } +} - //! Computes how the next 'count' tuples should be merged by setting the 'left_smaller' array - void ComputeMerge(const idx_t &count, bool left_smaller[]); +} // namespace duckdb - //! Merges the radix sorting blocks according to the 'left_smaller' array - void MergeRadix(const idx_t &count, const bool left_smaller[]); - //! Merges SortedData according to the 'left_smaller' array - void MergeData(SortedData &result_data, SortedData &l_data, SortedData &r_data, const idx_t &count, - const bool left_smaller[], idx_t next_entry_sizes[], bool reset_indices); - //! Merges constant size rows according to the 'left_smaller' array - void MergeRows(data_ptr_t &l_ptr, idx_t &l_entry_idx, const idx_t &l_count, data_ptr_t &r_ptr, idx_t &r_entry_idx, - const idx_t &r_count, RowDataBlock *target_block, data_ptr_t &target_ptr, const idx_t &entry_size, - const bool left_smaller[], idx_t &copied, const idx_t &count); - //! Flushes constant size rows into the result - void FlushRows(data_ptr_t &source_ptr, idx_t &source_entry_idx, const idx_t &source_count, - RowDataBlock *target_block, data_ptr_t &target_ptr, const idx_t &entry_size, idx_t &copied, - const idx_t &count); - //! Flushes blob rows and accompanying heap - void FlushBlobs(const RowLayout &layout, const idx_t &source_count, data_ptr_t &source_data_ptr, - idx_t &source_entry_idx, data_ptr_t &source_heap_ptr, RowDataBlock *target_data_block, - data_ptr_t &target_data_ptr, RowDataBlock *target_heap_block, BufferHandle &target_heap_handle, - data_ptr_t &target_heap_ptr, idx_t &copied, const idx_t &count); -}; -} // namespace duckdb + + +#include + namespace duckdb { -bool Comparators::TieIsBreakable(const idx_t &col_idx, const data_ptr_t row_ptr, const RowLayout &row_layout) { - // Check if the blob is NULL - ValidityBytes row_mask(row_ptr); - idx_t entry_idx; - idx_t idx_in_entry; - ValidityBytes::GetEntryIndex(col_idx, entry_idx, idx_in_entry); - if (!row_mask.RowIsValid(row_mask.GetValidityEntry(entry_idx), idx_in_entry)) { - // Can't break a NULL tie - return false; - } - if (row_layout.GetTypes()[col_idx].InternalType() == PhysicalType::VARCHAR) { - const auto &tie_col_offset = row_layout.GetOffsets()[col_idx]; - string_t tie_string = Load(row_ptr + tie_col_offset); - if (tie_string.GetSize() < string_t::INLINE_LENGTH) { - // No need to break the tie - we already compared the full string - return false; - } +SortedData::SortedData(SortedDataType type, const RowLayout &layout, BufferManager &buffer_manager, + GlobalSortState &state) + : type(type), layout(layout), swizzled(false), buffer_manager(buffer_manager), state(state) { +} + +idx_t SortedData::Count() { + idx_t count = std::accumulate(data_blocks.begin(), data_blocks.end(), (idx_t)0, + [](idx_t a, const unique_ptr &b) { return a + b->count; }); + if (!layout.AllConstant() && state.external) { + D_ASSERT(count == std::accumulate(heap_blocks.begin(), heap_blocks.end(), (idx_t)0, + [](idx_t a, const unique_ptr &b) { return a + b->count; })); } - return true; + return count; } -int Comparators::CompareTuple(const SBScanState &left, const SBScanState &right, const data_ptr_t &l_ptr, - const data_ptr_t &r_ptr, const SortLayout &sort_layout, const bool &external_sort) { - // Compare the sorting columns one by one - int comp_res = 0; - data_ptr_t l_ptr_offset = l_ptr; - data_ptr_t r_ptr_offset = r_ptr; - for (idx_t col_idx = 0; col_idx < sort_layout.column_count; col_idx++) { - comp_res = FastMemcmp(l_ptr_offset, r_ptr_offset, sort_layout.column_sizes[col_idx]); - if (comp_res == 0 && !sort_layout.constant_size[col_idx]) { - comp_res = BreakBlobTie(col_idx, left, right, sort_layout, external_sort); - } - if (comp_res != 0) { - break; - } - l_ptr_offset += sort_layout.column_sizes[col_idx]; - r_ptr_offset += sort_layout.column_sizes[col_idx]; +void SortedData::CreateBlock() { + auto capacity = + MaxValue(((idx_t)Storage::BLOCK_SIZE + layout.GetRowWidth() - 1) / layout.GetRowWidth(), state.block_capacity); + data_blocks.push_back(make_unique(buffer_manager, capacity, layout.GetRowWidth())); + if (!layout.AllConstant() && state.external) { + heap_blocks.push_back(make_unique(buffer_manager, (idx_t)Storage::BLOCK_SIZE, 1)); + D_ASSERT(data_blocks.size() == heap_blocks.size()); } - return comp_res; } -int Comparators::CompareVal(const data_ptr_t l_ptr, const data_ptr_t r_ptr, const LogicalType &type) { - switch (type.InternalType()) { - case PhysicalType::VARCHAR: - return TemplatedCompareVal(l_ptr, r_ptr); - case PhysicalType::LIST: - case PhysicalType::STRUCT: { - auto l_nested_ptr = Load(l_ptr); - auto r_nested_ptr = Load(r_ptr); - return CompareValAndAdvance(l_nested_ptr, r_nested_ptr, type); +unique_ptr SortedData::CreateSlice(idx_t start_block_index, idx_t end_block_index, idx_t end_entry_index) { + // Add the corresponding blocks to the result + auto result = make_unique(type, layout, buffer_manager, state); + for (idx_t i = start_block_index; i <= end_block_index; i++) { + result->data_blocks.push_back(data_blocks[i]->Copy()); + if (!layout.AllConstant() && state.external) { + result->heap_blocks.push_back(heap_blocks[i]->Copy()); + } } - default: - throw NotImplementedException("Unimplemented CompareVal for type %s", type.ToString()); + // All of the blocks that come before block with idx = start_block_idx can be reset (other references exist) + for (idx_t i = 0; i < start_block_index; i++) { + data_blocks[i]->block = nullptr; + if (!layout.AllConstant() && state.external) { + heap_blocks[i]->block = nullptr; + } + } + // Use start and end entry indices to set the boundaries + D_ASSERT(end_entry_index <= result->data_blocks.back()->count); + result->data_blocks.back()->count = end_entry_index; + if (!layout.AllConstant() && state.external) { + result->heap_blocks.back()->count = end_entry_index; } + return result; } -int Comparators::BreakBlobTie(const idx_t &tie_col, const SBScanState &left, const SBScanState &right, - const SortLayout &sort_layout, const bool &external) { - const idx_t &col_idx = sort_layout.sorting_to_blob_col.at(tie_col); - data_ptr_t l_data_ptr = left.DataPtr(*left.sb->blob_sorting_data); - data_ptr_t r_data_ptr = right.DataPtr(*right.sb->blob_sorting_data); - if (!TieIsBreakable(col_idx, l_data_ptr, sort_layout.blob_layout)) { - // Quick check to see if ties can be broken - return 0; +void SortedData::Unswizzle() { + if (layout.AllConstant() || !swizzled) { + return; } - // Align the pointers - const auto &tie_col_offset = sort_layout.blob_layout.GetOffsets()[col_idx]; - l_data_ptr += tie_col_offset; - r_data_ptr += tie_col_offset; - // Do the comparison - const int order = sort_layout.order_types[tie_col] == OrderType::DESCENDING ? -1 : 1; - const auto &type = sort_layout.blob_layout.GetTypes()[col_idx]; - int result; - if (external) { - // Store heap pointers - data_ptr_t l_heap_ptr = left.HeapPtr(*left.sb->blob_sorting_data); - data_ptr_t r_heap_ptr = right.HeapPtr(*right.sb->blob_sorting_data); - // Unswizzle offset to pointer - UnswizzleSingleValue(l_data_ptr, l_heap_ptr, type); - UnswizzleSingleValue(r_data_ptr, r_heap_ptr, type); - // Compare - result = CompareVal(l_data_ptr, r_data_ptr, type); - // Swizzle the pointers back to offsets - SwizzleSingleValue(l_data_ptr, l_heap_ptr, type); - SwizzleSingleValue(r_data_ptr, r_heap_ptr, type); - } else { - result = CompareVal(l_data_ptr, r_data_ptr, type); + for (idx_t i = 0; i < data_blocks.size(); i++) { + auto &data_block = data_blocks[i]; + auto &heap_block = heap_blocks[i]; + D_ASSERT(data_block->block->IsSwizzled()); + auto data_handle_p = buffer_manager.Pin(data_block->block); + auto heap_handle_p = buffer_manager.Pin(heap_block->block); + RowOperations::UnswizzlePointers(layout, data_handle_p.Ptr(), heap_handle_p.Ptr(), data_block->count); + data_block->block->SetSwizzling("SortedData::Unswizzle"); + state.heap_blocks.push_back(move(heap_block)); + state.pinned_blocks.push_back(move(heap_handle_p)); } - return order * result; + heap_blocks.clear(); } -template -int Comparators::TemplatedCompareVal(const data_ptr_t &left_ptr, const data_ptr_t &right_ptr) { - const auto left_val = Load(left_ptr); - const auto right_val = Load(right_ptr); - if (Equals::Operation(left_val, right_val)) { - return 0; - } else if (LessThan::Operation(left_val, right_val)) { - return -1; - } else { - return 1; - } +SortedBlock::SortedBlock(BufferManager &buffer_manager, GlobalSortState &state) + : buffer_manager(buffer_manager), state(state), sort_layout(state.sort_layout), + payload_layout(state.payload_layout) { + blob_sorting_data = make_unique(SortedDataType::BLOB, sort_layout.blob_layout, buffer_manager, state); + payload_data = make_unique(SortedDataType::PAYLOAD, payload_layout, buffer_manager, state); } -int Comparators::CompareValAndAdvance(data_ptr_t &l_ptr, data_ptr_t &r_ptr, const LogicalType &type) { - switch (type.InternalType()) { - case PhysicalType::BOOL: - case PhysicalType::INT8: - return TemplatedCompareAndAdvance(l_ptr, r_ptr); - case PhysicalType::INT16: - return TemplatedCompareAndAdvance(l_ptr, r_ptr); - case PhysicalType::INT32: - return TemplatedCompareAndAdvance(l_ptr, r_ptr); - case PhysicalType::INT64: - return TemplatedCompareAndAdvance(l_ptr, r_ptr); - case PhysicalType::UINT8: - return TemplatedCompareAndAdvance(l_ptr, r_ptr); - case PhysicalType::UINT16: - return TemplatedCompareAndAdvance(l_ptr, r_ptr); - case PhysicalType::UINT32: - return TemplatedCompareAndAdvance(l_ptr, r_ptr); - case PhysicalType::UINT64: - return TemplatedCompareAndAdvance(l_ptr, r_ptr); - case PhysicalType::INT128: - return TemplatedCompareAndAdvance(l_ptr, r_ptr); - case PhysicalType::FLOAT: - return TemplatedCompareAndAdvance(l_ptr, r_ptr); - case PhysicalType::DOUBLE: - return TemplatedCompareAndAdvance(l_ptr, r_ptr); - case PhysicalType::INTERVAL: - return TemplatedCompareAndAdvance(l_ptr, r_ptr); - case PhysicalType::VARCHAR: - return CompareStringAndAdvance(l_ptr, r_ptr); - case PhysicalType::LIST: - return CompareListAndAdvance(l_ptr, r_ptr, ListType::GetChildType(type)); - case PhysicalType::STRUCT: - return CompareStructAndAdvance(l_ptr, r_ptr, StructType::GetChildTypes(type)); - default: - throw NotImplementedException("Unimplemented CompareValAndAdvance for type %s", type.ToString()); +idx_t SortedBlock::Count() const { + idx_t count = std::accumulate(radix_sorting_data.begin(), radix_sorting_data.end(), 0, + [](idx_t a, const unique_ptr &b) { return a + b->count; }); + if (!sort_layout.all_constant) { + D_ASSERT(count == blob_sorting_data->Count()); } + D_ASSERT(count == payload_data->Count()); + return count; } -template -int Comparators::TemplatedCompareAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr) { - auto result = TemplatedCompareVal(left_ptr, right_ptr); - left_ptr += sizeof(T); - right_ptr += sizeof(T); - return result; +void SortedBlock::InitializeWrite() { + CreateBlock(); + if (!sort_layout.all_constant) { + blob_sorting_data->CreateBlock(); + } + payload_data->CreateBlock(); } -int Comparators::CompareStringAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr) { - // Construct the string_t - uint32_t left_string_size = Load(left_ptr); - uint32_t right_string_size = Load(right_ptr); - left_ptr += sizeof(uint32_t); - right_ptr += sizeof(uint32_t); - string_t left_val((const char *)left_ptr, left_string_size); - string_t right_val((const char *)right_ptr, right_string_size); - left_ptr += left_string_size; - right_ptr += right_string_size; - // Compare - return TemplatedCompareVal((data_ptr_t)&left_val, (data_ptr_t)&right_val); +void SortedBlock::CreateBlock() { + auto capacity = MaxValue(((idx_t)Storage::BLOCK_SIZE + sort_layout.entry_size - 1) / sort_layout.entry_size, + state.block_capacity); + radix_sorting_data.push_back(make_unique(buffer_manager, capacity, sort_layout.entry_size)); } -int Comparators::CompareStructAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr, - const child_list_t &types) { - idx_t count = types.size(); - // Load validity masks - ValidityBytes left_validity(left_ptr); - ValidityBytes right_validity(right_ptr); - left_ptr += (count + 7) / 8; - right_ptr += (count + 7) / 8; - // Initialize variables - bool left_valid; - bool right_valid; - idx_t entry_idx; - idx_t idx_in_entry; - // Compare - int comp_res = 0; - for (idx_t i = 0; i < count; i++) { - ValidityBytes::GetEntryIndex(i, entry_idx, idx_in_entry); - left_valid = left_validity.RowIsValid(left_validity.GetValidityEntry(entry_idx), idx_in_entry); - right_valid = right_validity.RowIsValid(right_validity.GetValidityEntry(entry_idx), idx_in_entry); - auto &type = types[i].second; - if ((left_valid && right_valid) || TypeIsConstantSize(type.InternalType())) { - comp_res = CompareValAndAdvance(left_ptr, right_ptr, types[i].second); +void SortedBlock::AppendSortedBlocks(vector> &sorted_blocks) { + D_ASSERT(Count() == 0); + for (auto &sb : sorted_blocks) { + for (auto &radix_block : sb->radix_sorting_data) { + radix_sorting_data.push_back(move(radix_block)); } - if (!left_valid && !right_valid) { - comp_res = 0; - } else if (!left_valid) { - comp_res = 1; - } else if (!right_valid) { - comp_res = -1; + if (!sort_layout.all_constant) { + for (auto &blob_block : sb->blob_sorting_data->data_blocks) { + blob_sorting_data->data_blocks.push_back(move(blob_block)); + } + for (auto &heap_block : sb->blob_sorting_data->heap_blocks) { + blob_sorting_data->heap_blocks.push_back(move(heap_block)); + } } - if (comp_res != 0) { - break; + for (auto &payload_data_block : sb->payload_data->data_blocks) { + payload_data->data_blocks.push_back(move(payload_data_block)); + } + if (!payload_data->layout.AllConstant()) { + for (auto &payload_heap_block : sb->payload_data->heap_blocks) { + payload_data->heap_blocks.push_back(move(payload_heap_block)); + } } } - return comp_res; } -int Comparators::CompareListAndAdvance(data_ptr_t &left_ptr, data_ptr_t &right_ptr, const LogicalType &type) { - // Load list lengths - auto left_len = Load(left_ptr); - auto right_len = Load(right_ptr); - left_ptr += sizeof(idx_t); - right_ptr += sizeof(idx_t); - // Load list validity masks - ValidityBytes left_validity(left_ptr); - ValidityBytes right_validity(right_ptr); - left_ptr += (left_len + 7) / 8; - right_ptr += (right_len + 7) / 8; - // Compare - int comp_res = 0; - idx_t count = MinValue(left_len, right_len); - if (TypeIsConstantSize(type.InternalType())) { - // Templated code for fixed-size types - switch (type.InternalType()) { - case PhysicalType::BOOL: - case PhysicalType::INT8: - comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); - break; - case PhysicalType::INT16: - comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); - break; - case PhysicalType::INT32: - comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); - break; - case PhysicalType::INT64: - comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); - break; - case PhysicalType::UINT8: - comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); - break; - case PhysicalType::UINT16: - comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); - break; - case PhysicalType::UINT32: - comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); - break; - case PhysicalType::UINT64: - comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); - break; - case PhysicalType::INT128: - comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); - break; - case PhysicalType::FLOAT: - comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); - break; - case PhysicalType::DOUBLE: - comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); - break; - case PhysicalType::INTERVAL: - comp_res = TemplatedCompareListLoop(left_ptr, right_ptr, left_validity, right_validity, count); +void SortedBlock::GlobalToLocalIndex(const idx_t &global_idx, idx_t &local_block_index, idx_t &local_entry_index) { + if (global_idx == Count()) { + local_block_index = radix_sorting_data.size() - 1; + local_entry_index = radix_sorting_data.back()->count; + return; + } + D_ASSERT(global_idx < Count()); + local_entry_index = global_idx; + for (local_block_index = 0; local_block_index < radix_sorting_data.size(); local_block_index++) { + const idx_t &block_count = radix_sorting_data[local_block_index]->count; + if (local_entry_index >= block_count) { + local_entry_index -= block_count; + } else { break; - default: - throw NotImplementedException("CompareListAndAdvance for fixed-size type %s", type.ToString()); } - } else { - // Variable-sized list entries - bool left_valid; - bool right_valid; - idx_t entry_idx; - idx_t idx_in_entry; - // Size (in bytes) of all variable-sizes entries is stored before the entries begin, - // to make deserialization easier. We need to skip over them - left_ptr += left_len * sizeof(idx_t); - right_ptr += right_len * sizeof(idx_t); - for (idx_t i = 0; i < count; i++) { - ValidityBytes::GetEntryIndex(i, entry_idx, idx_in_entry); - left_valid = left_validity.RowIsValid(left_validity.GetValidityEntry(entry_idx), idx_in_entry); - right_valid = right_validity.RowIsValid(right_validity.GetValidityEntry(entry_idx), idx_in_entry); - if (left_valid && right_valid) { - switch (type.InternalType()) { - case PhysicalType::LIST: - comp_res = CompareListAndAdvance(left_ptr, right_ptr, ListType::GetChildType(type)); - break; - case PhysicalType::VARCHAR: - comp_res = CompareStringAndAdvance(left_ptr, right_ptr); - break; - case PhysicalType::STRUCT: - comp_res = CompareStructAndAdvance(left_ptr, right_ptr, StructType::GetChildTypes(type)); - break; - default: - throw NotImplementedException("CompareListAndAdvance for variable-size type %s", type.ToString()); - } - } else if (!left_valid && !right_valid) { - comp_res = 0; - } else if (left_valid) { - comp_res = -1; - } else { - comp_res = 1; - } - if (comp_res != 0) { - break; - } + } + D_ASSERT(local_entry_index < radix_sorting_data[local_block_index]->count); +} + +unique_ptr SortedBlock::CreateSlice(const idx_t start, const idx_t end, idx_t &entry_idx) { + // Identify blocks/entry indices of this slice + idx_t start_block_index; + idx_t start_entry_index; + GlobalToLocalIndex(start, start_block_index, start_entry_index); + idx_t end_block_index; + idx_t end_entry_index; + GlobalToLocalIndex(end, end_block_index, end_entry_index); + // Add the corresponding blocks to the result + auto result = make_unique(buffer_manager, state); + for (idx_t i = start_block_index; i <= end_block_index; i++) { + result->radix_sorting_data.push_back(radix_sorting_data[i]->Copy()); + } + // Reset all blocks that come before block with idx = start_block_idx (slice holds new reference) + for (idx_t i = 0; i < start_block_index; i++) { + radix_sorting_data[i]->block = nullptr; + } + // Use start and end entry indices to set the boundaries + entry_idx = start_entry_index; + D_ASSERT(end_entry_index <= result->radix_sorting_data.back()->count); + result->radix_sorting_data.back()->count = end_entry_index; + // Same for the var size sorting data + if (!sort_layout.all_constant) { + result->blob_sorting_data = blob_sorting_data->CreateSlice(start_block_index, end_block_index, end_entry_index); + } + // And the payload data + result->payload_data = payload_data->CreateSlice(start_block_index, end_block_index, end_entry_index); + return result; +} + +idx_t SortedBlock::HeapSize() const { + idx_t result = 0; + if (!sort_layout.all_constant) { + for (auto &block : blob_sorting_data->heap_blocks) { + result += block->capacity; } } - // All values that we looped over were equal - if (comp_res == 0 && left_len != right_len) { - // Smaller lists first - if (left_len < right_len) { - comp_res = -1; - } else { - comp_res = 1; + if (!payload_layout.AllConstant()) { + for (auto &block : payload_data->heap_blocks) { + result += block->capacity; } } - return comp_res; + return result; } -template -int Comparators::TemplatedCompareListLoop(data_ptr_t &left_ptr, data_ptr_t &right_ptr, - const ValidityBytes &left_validity, const ValidityBytes &right_validity, - const idx_t &count) { - int comp_res = 0; - bool left_valid; - bool right_valid; - idx_t entry_idx; - idx_t idx_in_entry; - for (idx_t i = 0; i < count; i++) { - ValidityBytes::GetEntryIndex(i, entry_idx, idx_in_entry); - left_valid = left_validity.RowIsValid(left_validity.GetValidityEntry(entry_idx), idx_in_entry); - right_valid = right_validity.RowIsValid(right_validity.GetValidityEntry(entry_idx), idx_in_entry); - comp_res = TemplatedCompareAndAdvance(left_ptr, right_ptr); - if (!left_valid && !right_valid) { - comp_res = 0; - } else if (!left_valid) { - comp_res = 1; - } else if (!right_valid) { - comp_res = -1; +idx_t SortedBlock::SizeInBytes() const { + idx_t bytes = 0; + for (idx_t i = 0; i < radix_sorting_data.size(); i++) { + bytes += radix_sorting_data[i]->capacity * sort_layout.entry_size; + if (!sort_layout.all_constant) { + bytes += blob_sorting_data->data_blocks[i]->capacity * sort_layout.blob_layout.GetRowWidth(); + bytes += blob_sorting_data->heap_blocks[i]->capacity; } - if (comp_res != 0) { - break; + bytes += payload_data->data_blocks[i]->capacity * payload_layout.GetRowWidth(); + if (!payload_layout.AllConstant()) { + bytes += payload_data->heap_blocks[i]->capacity; } } - return comp_res; + return bytes; } -void Comparators::UnswizzleSingleValue(data_ptr_t data_ptr, const data_ptr_t &heap_ptr, const LogicalType &type) { - if (type.InternalType() == PhysicalType::VARCHAR) { - data_ptr += sizeof(uint32_t) + string_t::PREFIX_LENGTH; - } - Store(heap_ptr + Load(data_ptr), data_ptr); +SBScanState::SBScanState(BufferManager &buffer_manager, GlobalSortState &state) + : buffer_manager(buffer_manager), sort_layout(state.sort_layout), state(state), block_idx(0), entry_idx(0) { } -void Comparators::SwizzleSingleValue(data_ptr_t data_ptr, const data_ptr_t &heap_ptr, const LogicalType &type) { - if (type.InternalType() == PhysicalType::VARCHAR) { - data_ptr += sizeof(uint32_t) + string_t::PREFIX_LENGTH; +void SBScanState::PinRadix(idx_t block_idx_to) { + auto &radix_sorting_data = sb->radix_sorting_data; + D_ASSERT(block_idx_to < radix_sorting_data.size()); + auto &block = radix_sorting_data[block_idx_to]; + if (!radix_handle.IsValid() || radix_handle.GetBlockId() != block->block->BlockId()) { + radix_handle = buffer_manager.Pin(block->block); } - Store(Load(data_ptr) - heap_ptr, data_ptr); } -} // namespace duckdb +void SBScanState::PinData(SortedData &sd) { + D_ASSERT(block_idx < sd.data_blocks.size()); + auto &data_handle = sd.type == SortedDataType::BLOB ? blob_sorting_data_handle : payload_data_handle; + auto &heap_handle = sd.type == SortedDataType::BLOB ? blob_sorting_heap_handle : payload_heap_handle; + auto &data_block = sd.data_blocks[block_idx]; + if (!data_handle.IsValid() || data_handle.GetBlockId() != data_block->block->BlockId()) { + data_handle = buffer_manager.Pin(data_block->block); + } + if (sd.layout.AllConstant() || !state.external) { + return; + } + auto &heap_block = sd.heap_blocks[block_idx]; + if (!heap_handle.IsValid() || heap_handle.GetBlockId() != heap_block->block->BlockId()) { + heap_handle = buffer_manager.Pin(heap_block->block); + } +} +data_ptr_t SBScanState::RadixPtr() const { + return radix_handle.Ptr() + entry_idx * sort_layout.entry_size; +} +data_ptr_t SBScanState::DataPtr(SortedData &sd) const { + auto &data_handle = sd.type == SortedDataType::BLOB ? blob_sorting_data_handle : payload_data_handle; + D_ASSERT(sd.data_blocks[block_idx]->block->Readers() != 0 && + data_handle.GetBlockId() == sd.data_blocks[block_idx]->block->BlockId()); + return data_handle.Ptr() + entry_idx * sd.layout.GetRowWidth(); +} -namespace duckdb { +data_ptr_t SBScanState::HeapPtr(SortedData &sd) const { + return BaseHeapPtr(sd) + Load(DataPtr(sd) + sd.layout.GetHeapOffset()); +} -MergeSorter::MergeSorter(GlobalSortState &state, BufferManager &buffer_manager) - : state(state), buffer_manager(buffer_manager), sort_layout(state.sort_layout) { +data_ptr_t SBScanState::BaseHeapPtr(SortedData &sd) const { + auto &heap_handle = sd.type == SortedDataType::BLOB ? blob_sorting_heap_handle : payload_heap_handle; + D_ASSERT(!sd.layout.AllConstant() && state.external); + D_ASSERT(sd.heap_blocks[block_idx]->block->Readers() != 0 && + heap_handle.GetBlockId() == sd.heap_blocks[block_idx]->block->BlockId()); + return heap_handle.Ptr(); } -void MergeSorter::PerformInMergeRound() { - while (true) { - { - lock_guard pair_guard(state.lock); - if (state.pair_idx == state.num_pairs) { - break; - } - GetNextPartition(); +idx_t SBScanState::Remaining() const { + const auto &blocks = sb->radix_sorting_data; + idx_t remaining = 0; + if (block_idx < blocks.size()) { + remaining += blocks[block_idx]->count - entry_idx; + for (idx_t i = block_idx + 1; i < blocks.size(); i++) { + remaining += blocks[i]->count; } - MergePartition(); } + return remaining; } -void MergeSorter::MergePartition() { - auto &left_block = *left->sb; - auto &right_block = *right->sb; -#ifdef DEBUG - D_ASSERT(left_block.radix_sorting_data.size() == left_block.payload_data->data_blocks.size()); - D_ASSERT(right_block.radix_sorting_data.size() == right_block.payload_data->data_blocks.size()); - if (!state.payload_layout.AllConstant() && state.external) { - D_ASSERT(left_block.payload_data->data_blocks.size() == left_block.payload_data->heap_blocks.size()); - D_ASSERT(right_block.payload_data->data_blocks.size() == right_block.payload_data->heap_blocks.size()); +void SBScanState::SetIndices(idx_t block_idx_to, idx_t entry_idx_to) { + block_idx = block_idx_to; + entry_idx = entry_idx_to; +} + +PayloadScanner::PayloadScanner(SortedData &sorted_data, GlobalSortState &global_sort_state, bool flush_p) + : sorted_data(sorted_data), read_state(global_sort_state.buffer_manager, global_sort_state), + total_count(sorted_data.Count()), total_scanned(0), flush(flush_p), + unswizzling(!sorted_data.layout.AllConstant() && global_sort_state.external) { + ValidateUnscannedBlock(); +} + +PayloadScanner::PayloadScanner(GlobalSortState &global_sort_state, bool flush_p) + : PayloadScanner(*global_sort_state.sorted_blocks[0]->payload_data, global_sort_state, flush_p) { +} + +PayloadScanner::PayloadScanner(GlobalSortState &global_sort_state, idx_t block_idx) + : sorted_data(*global_sort_state.sorted_blocks[0]->payload_data), + read_state(global_sort_state.buffer_manager, global_sort_state), + total_count(sorted_data.data_blocks[block_idx]->count), total_scanned(0), flush(false), + unswizzling(!sorted_data.layout.AllConstant() && global_sort_state.external) { + read_state.SetIndices(block_idx, 0); + ValidateUnscannedBlock(); +} + +void PayloadScanner::ValidateUnscannedBlock() const { + if (unswizzling && read_state.block_idx < sorted_data.data_blocks.size()) { + D_ASSERT(sorted_data.data_blocks[read_state.block_idx]->block->IsSwizzled()); } - if (!sort_layout.all_constant) { - D_ASSERT(left_block.radix_sorting_data.size() == left_block.blob_sorting_data->data_blocks.size()); - D_ASSERT(right_block.radix_sorting_data.size() == right_block.blob_sorting_data->data_blocks.size()); - if (state.external) { - D_ASSERT(left_block.blob_sorting_data->data_blocks.size() == - left_block.blob_sorting_data->heap_blocks.size()); - D_ASSERT(right_block.blob_sorting_data->data_blocks.size() == - right_block.blob_sorting_data->heap_blocks.size()); - } +} + +void PayloadScanner::Scan(DataChunk &chunk) { + auto count = MinValue((idx_t)STANDARD_VECTOR_SIZE, total_count - total_scanned); + if (count == 0) { + chunk.SetCardinality(count); + return; } -#endif - // Set up the write block - // Each merge task produces a SortedBlock with exactly state.block_capacity rows or less - result->InitializeWrite(); - // Initialize arrays to store merge data - bool left_smaller[STANDARD_VECTOR_SIZE]; - idx_t next_entry_sizes[STANDARD_VECTOR_SIZE]; - // Merge loop -#ifdef DEBUG - auto l_count = left->Remaining(); - auto r_count = right->Remaining(); -#endif - while (true) { - auto l_remaining = left->Remaining(); - auto r_remaining = right->Remaining(); - if (l_remaining + r_remaining == 0) { - // Done - break; - } - const idx_t next = MinValue(l_remaining + r_remaining, (idx_t)STANDARD_VECTOR_SIZE); - if (l_remaining != 0 && r_remaining != 0) { - // Compute the merge (not needed if one side is exhausted) - ComputeMerge(next, left_smaller); + // Eagerly delete references to blocks that we've passed + if (flush) { + for (idx_t i = 0; i < read_state.block_idx; i++) { + sorted_data.data_blocks[i]->block = nullptr; + if (unswizzling) { + sorted_data.heap_blocks[i]->block = nullptr; + } } - // Actually merge the data (radix, blob, and payload) - MergeRadix(next, left_smaller); - if (!sort_layout.all_constant) { - MergeData(*result->blob_sorting_data, *left_block.blob_sorting_data, *right_block.blob_sorting_data, next, - left_smaller, next_entry_sizes, true); - D_ASSERT(result->radix_sorting_data.size() == result->blob_sorting_data->data_blocks.size()); - } - MergeData(*result->payload_data, *left_block.payload_data, *right_block.payload_data, next, left_smaller, - next_entry_sizes, false); - D_ASSERT(result->radix_sorting_data.size() == result->payload_data->data_blocks.size()); } -#ifdef DEBUG - D_ASSERT(result->Count() == l_count + r_count); -#endif -} - -void MergeSorter::GetNextPartition() { - // Create result block - state.sorted_blocks_temp[state.pair_idx].push_back(make_unique(buffer_manager, state)); - result = state.sorted_blocks_temp[state.pair_idx].back().get(); - // Determine which blocks must be merged - auto &left_block = *state.sorted_blocks[state.pair_idx * 2]; - auto &right_block = *state.sorted_blocks[state.pair_idx * 2 + 1]; - const idx_t l_count = left_block.Count(); - const idx_t r_count = right_block.Count(); - // Initialize left and right reader - left = make_unique(buffer_manager, state); - right = make_unique(buffer_manager, state); - // Compute the work that this thread must do using Merge Path - idx_t l_end; - idx_t r_end; - if (state.l_start + state.r_start + state.block_capacity < l_count + r_count) { - left->sb = state.sorted_blocks[state.pair_idx * 2].get(); - right->sb = state.sorted_blocks[state.pair_idx * 2 + 1].get(); - const idx_t intersection = state.l_start + state.r_start + state.block_capacity; - GetIntersection(intersection, l_end, r_end); - D_ASSERT(l_end <= l_count); - D_ASSERT(r_end <= r_count); - D_ASSERT(intersection == l_end + r_end); - } else { - l_end = l_count; - r_end = r_count; + const idx_t &row_width = sorted_data.layout.GetRowWidth(); + // Set up a batch of pointers to scan data from + idx_t scanned = 0; + auto data_pointers = FlatVector::GetData(addresses); + while (scanned < count) { + read_state.PinData(sorted_data); + auto &data_block = *sorted_data.data_blocks[read_state.block_idx]; + idx_t next = MinValue(data_block.count - read_state.entry_idx, count - scanned); + const data_ptr_t data_ptr = read_state.payload_data_handle.Ptr() + read_state.entry_idx * row_width; + // Set up the next pointers + data_ptr_t row_ptr = data_ptr; + for (idx_t i = 0; i < next; i++) { + data_pointers[scanned + i] = row_ptr; + row_ptr += row_width; + } + // Unswizzle the offsets back to pointers (if needed) + if (unswizzling) { + RowOperations::UnswizzlePointers(sorted_data.layout, data_ptr, read_state.payload_heap_handle.Ptr(), next); + sorted_data.data_blocks[read_state.block_idx]->block->SetSwizzling("PayloadScanner::Scan"); + } + // Update state indices + read_state.entry_idx += next; + if (read_state.entry_idx == data_block.count) { + read_state.block_idx++; + read_state.entry_idx = 0; + ValidateUnscannedBlock(); + } + scanned += next; } - // Create slices of the data that this thread must merge - left->SetIndices(0, 0); - right->SetIndices(0, 0); - left_input = left_block.CreateSlice(state.l_start, l_end, left->entry_idx); - right_input = right_block.CreateSlice(state.r_start, r_end, right->entry_idx); - left->sb = left_input.get(); - right->sb = right_input.get(); - state.l_start = l_end; - state.r_start = r_end; - D_ASSERT(left->Remaining() + right->Remaining() == state.block_capacity || (l_end == l_count && r_end == r_count)); - // Update global state - if (state.l_start == l_count && state.r_start == r_count) { - // Delete references to previous pair - state.sorted_blocks[state.pair_idx * 2] = nullptr; - state.sorted_blocks[state.pair_idx * 2 + 1] = nullptr; - // Advance pair - state.pair_idx++; - state.l_start = 0; - state.r_start = 0; + D_ASSERT(scanned == count); + // Deserialize the payload data + for (idx_t col_no = 0; col_no < sorted_data.layout.ColumnCount(); col_no++) { + RowOperations::Gather(addresses, *FlatVector::IncrementalSelectionVector(), chunk.data[col_no], + *FlatVector::IncrementalSelectionVector(), count, sorted_data.layout, col_no); } + chunk.SetCardinality(count); + chunk.Verify(); + total_scanned += scanned; } -int MergeSorter::CompareUsingGlobalIndex(SBScanState &l, SBScanState &r, const idx_t l_idx, const idx_t r_idx) { - D_ASSERT(l_idx < l.sb->Count()); - D_ASSERT(r_idx < r.sb->Count()); - - // Easy comparison using the previous result (intersections must increase monotonically) - if (l_idx < state.l_start) { +int SBIterator::ComparisonValue(ExpressionType comparison) { + switch (comparison) { + case ExpressionType::COMPARE_LESSTHAN: + case ExpressionType::COMPARE_GREATERTHAN: return -1; + case ExpressionType::COMPARE_LESSTHANOREQUALTO: + case ExpressionType::COMPARE_GREATERTHANOREQUALTO: + return 0; + default: + throw InternalException("Unimplemented comparison type for IEJoin!"); } - if (r_idx < state.r_start) { - return 1; - } - - l.sb->GlobalToLocalIndex(l_idx, l.block_idx, l.entry_idx); - r.sb->GlobalToLocalIndex(r_idx, r.block_idx, r.entry_idx); +} - l.PinRadix(l.block_idx); - r.PinRadix(r.block_idx); - data_ptr_t l_ptr = l.radix_handle->Ptr() + l.entry_idx * sort_layout.entry_size; - data_ptr_t r_ptr = r.radix_handle->Ptr() + r.entry_idx * sort_layout.entry_size; +SBIterator::SBIterator(GlobalSortState &gss, ExpressionType comparison, idx_t entry_idx_p) + : sort_layout(gss.sort_layout), block_count(gss.sorted_blocks[0]->radix_sorting_data.size()), + block_capacity(gss.block_capacity), cmp_size(sort_layout.comparison_size), entry_size(sort_layout.entry_size), + all_constant(sort_layout.all_constant), external(gss.external), cmp(ComparisonValue(comparison)), + scan(gss.buffer_manager, gss), block_ptr(nullptr), entry_ptr(nullptr) { - int comp_res; - if (sort_layout.all_constant) { - comp_res = FastMemcmp(l_ptr, r_ptr, sort_layout.comparison_size); - } else { - l.PinData(*l.sb->blob_sorting_data); - r.PinData(*r.sb->blob_sorting_data); - comp_res = Comparators::CompareTuple(l, r, l_ptr, r_ptr, sort_layout, state.external); - } - return comp_res; + scan.sb = gss.sorted_blocks[0].get(); + scan.block_idx = block_count; + SetIndex(entry_idx_p); } -void MergeSorter::GetIntersection(const idx_t diagonal, idx_t &l_idx, idx_t &r_idx) { - const idx_t l_count = left->sb->Count(); - const idx_t r_count = right->sb->Count(); - // Cover some edge cases - // Code coverage off because these edge cases cannot happen unless other code changes - // Edge cases have been tested extensively while developing Merge Path in a script - // LCOV_EXCL_START - if (diagonal >= l_count + r_count) { - l_idx = l_count; - r_idx = r_count; - return; - } else if (diagonal == 0) { - l_idx = 0; - r_idx = 0; - return; - } else if (l_count == 0) { - l_idx = 0; - r_idx = diagonal; - return; - } else if (r_count == 0) { - r_idx = 0; - l_idx = diagonal; - return; - } - // LCOV_EXCL_STOP - // Determine offsets for the binary search - const idx_t l_offset = MinValue(l_count, diagonal); - const idx_t r_offset = diagonal > l_count ? diagonal - l_count : 0; - D_ASSERT(l_offset + r_offset == diagonal); - const idx_t search_space = diagonal > MaxValue(l_count, r_count) ? l_count + r_count - diagonal - : MinValue(diagonal, MinValue(l_count, r_count)); - // Double binary search - idx_t li = 0; - idx_t ri = search_space - 1; - idx_t middle; - int comp_res; - while (li <= ri) { - middle = (li + ri) / 2; - l_idx = l_offset - middle; - r_idx = r_offset + middle; - if (l_idx == l_count || r_idx == 0) { - comp_res = CompareUsingGlobalIndex(*left, *right, l_idx - 1, r_idx); - if (comp_res > 0) { - l_idx--; - r_idx++; - } else { - return; - } - if (l_idx == 0 || r_idx == r_count) { - // This case is incredibly difficult to cover as it is dependent on parallelism randomness - // But it has been tested extensively during development in a script - // LCOV_EXCL_START - return; - // LCOV_EXCL_STOP - } else { - break; - } - } - comp_res = CompareUsingGlobalIndex(*left, *right, l_idx, r_idx); - if (comp_res > 0) { - li = middle + 1; - } else { - ri = middle - 1; - } - } - int l_r_min1 = CompareUsingGlobalIndex(*left, *right, l_idx, r_idx - 1); - int l_min1_r = CompareUsingGlobalIndex(*left, *right, l_idx - 1, r_idx); - if (l_r_min1 > 0 && l_min1_r < 0) { - return; - } else if (l_r_min1 > 0) { - l_idx--; - r_idx++; - } else if (l_min1_r < 0) { - l_idx++; - r_idx--; - } -} +} // namespace duckdb -void MergeSorter::ComputeMerge(const idx_t &count, bool left_smaller[]) { - auto &l = *left; - auto &r = *right; - auto &l_sorted_block = *l.sb; - auto &r_sorted_block = *r.sb; - // Save indices to restore afterwards - idx_t l_block_idx_before = l.block_idx; - idx_t l_entry_idx_before = l.entry_idx; - idx_t r_block_idx_before = r.block_idx; - idx_t r_entry_idx_before = r.entry_idx; - // Data pointers for both sides - data_ptr_t l_radix_ptr; - data_ptr_t r_radix_ptr; - // Compute the merge of the next 'count' tuples - idx_t compared = 0; - while (compared < count) { - // Move to the next block (if needed) - if (l.block_idx < l_sorted_block.radix_sorting_data.size() && - l.entry_idx == l_sorted_block.radix_sorting_data[l.block_idx].count) { - l.block_idx++; - l.entry_idx = 0; - } - if (r.block_idx < r_sorted_block.radix_sorting_data.size() && - r.entry_idx == r_sorted_block.radix_sorting_data[r.block_idx].count) { - r.block_idx++; - r.entry_idx = 0; - } - const bool l_done = l.block_idx == l_sorted_block.radix_sorting_data.size(); - const bool r_done = r.block_idx == r_sorted_block.radix_sorting_data.size(); - if (l_done || r_done) { - // One of the sides is exhausted, no need to compare - break; - } - // Pin the radix sorting data - if (!l_done) { - left->PinRadix(l.block_idx); - l_radix_ptr = left->RadixPtr(); - } - if (!r_done) { - right->PinRadix(r.block_idx); - r_radix_ptr = right->RadixPtr(); - } - const idx_t &l_count = !l_done ? l_sorted_block.radix_sorting_data[l.block_idx].count : 0; - const idx_t &r_count = !r_done ? r_sorted_block.radix_sorting_data[r.block_idx].count : 0; - // Compute the merge - if (sort_layout.all_constant) { - // All sorting columns are constant size - for (; compared < count && l.entry_idx < l_count && r.entry_idx < r_count; compared++) { - left_smaller[compared] = FastMemcmp(l_radix_ptr, r_radix_ptr, sort_layout.comparison_size) < 0; - const bool &l_smaller = left_smaller[compared]; - const bool r_smaller = !l_smaller; - // Use comparison bool (0 or 1) to increment entries and pointers - l.entry_idx += l_smaller; - r.entry_idx += r_smaller; - l_radix_ptr += l_smaller * sort_layout.entry_size; - r_radix_ptr += r_smaller * sort_layout.entry_size; - } - } else { - // Pin the blob data - if (!l_done) { - left->PinData(*l_sorted_block.blob_sorting_data); - } - if (!r_done) { - right->PinData(*r_sorted_block.blob_sorting_data); - } - // Merge with variable size sorting columns - for (; compared < count && l.entry_idx < l_count && r.entry_idx < r_count; compared++) { - left_smaller[compared] = - Comparators::CompareTuple(*left, *right, l_radix_ptr, r_radix_ptr, sort_layout, state.external) < 0; - const bool &l_smaller = left_smaller[compared]; - const bool r_smaller = !l_smaller; - // Use comparison bool (0 or 1) to increment entries and pointers - l.entry_idx += l_smaller; - r.entry_idx += r_smaller; - l_radix_ptr += l_smaller * sort_layout.entry_size; - r_radix_ptr += r_smaller * sort_layout.entry_size; - } - } - } - // Reset block indices - left->SetIndices(l_block_idx_before, l_entry_idx_before); - right->SetIndices(r_block_idx_before, r_entry_idx_before); -} -void MergeSorter::MergeRadix(const idx_t &count, const bool left_smaller[]) { - auto &l = *left; - auto &r = *right; - // Save indices to restore afterwards - idx_t l_block_idx_before = l.block_idx; - idx_t l_entry_idx_before = l.entry_idx; - idx_t r_block_idx_before = r.block_idx; - idx_t r_entry_idx_before = r.entry_idx; - auto &l_blocks = l.sb->radix_sorting_data; - auto &r_blocks = r.sb->radix_sorting_data; - RowDataBlock *l_block; - RowDataBlock *r_block; - data_ptr_t l_ptr; - data_ptr_t r_ptr; - RowDataBlock *result_block = &result->radix_sorting_data.back(); - auto result_handle = buffer_manager.Pin(result_block->block); - data_ptr_t result_ptr = result_handle->Ptr() + result_block->count * sort_layout.entry_size; +#include +#include +#include +#include +#include +#include +#include - idx_t copied = 0; - while (copied < count) { - // Move to the next block (if needed) - if (l.block_idx < l_blocks.size() && l.entry_idx == l_blocks[l.block_idx].count) { - // Delete reference to previous block - l_blocks[l.block_idx].block = nullptr; - // Advance block - l.block_idx++; - l.entry_idx = 0; - } - if (r.block_idx < r_blocks.size() && r.entry_idx == r_blocks[r.block_idx].count) { - // Delete reference to previous block - r_blocks[r.block_idx].block = nullptr; - // Advance block - r.block_idx++; - r.entry_idx = 0; - } - const bool l_done = l.block_idx == l_blocks.size(); - const bool r_done = r.block_idx == r_blocks.size(); - // Pin the radix sortable blocks - if (!l_done) { - l_block = &l_blocks[l.block_idx]; - left->PinRadix(l.block_idx); - l_ptr = l.RadixPtr(); - } - if (!r_done) { - r_block = &r_blocks[r.block_idx]; - r.PinRadix(r.block_idx); - r_ptr = r.RadixPtr(); - } - const idx_t &l_count = !l_done ? l_block->count : 0; - const idx_t &r_count = !r_done ? r_block->count : 0; - // Copy using computed merge - if (!l_done && !r_done) { - // Both sides have data - merge - MergeRows(l_ptr, l.entry_idx, l_count, r_ptr, r.entry_idx, r_count, result_block, result_ptr, - sort_layout.entry_size, left_smaller, copied, count); - } else if (r_done) { - // Right side is exhausted - FlushRows(l_ptr, l.entry_idx, l_count, result_block, result_ptr, sort_layout.entry_size, copied, count); - } else { - // Left side is exhausted - FlushRows(r_ptr, r.entry_idx, r_count, result_block, result_ptr, sort_layout.entry_size, copied, count); - } - } - // Reset block indices - left->SetIndices(l_block_idx_before, l_entry_idx_before); - right->SetIndices(r_block_idx_before, r_entry_idx_before); +namespace duckdb { + +bool StringUtil::Contains(const string &haystack, const string &needle) { + return (haystack.find(needle) != string::npos); } -void MergeSorter::MergeData(SortedData &result_data, SortedData &l_data, SortedData &r_data, const idx_t &count, - const bool left_smaller[], idx_t next_entry_sizes[], bool reset_indices) { - auto &l = *left; - auto &r = *right; - // Save indices to restore afterwards - idx_t l_block_idx_before = l.block_idx; - idx_t l_entry_idx_before = l.entry_idx; - idx_t r_block_idx_before = r.block_idx; - idx_t r_entry_idx_before = r.entry_idx; +void StringUtil::LTrim(string &str) { + auto it = str.begin(); + while (CharacterIsSpace(*it)) { + it++; + } + str.erase(str.begin(), it); +} - const auto &layout = result_data.layout; - const idx_t row_width = layout.GetRowWidth(); - const idx_t heap_pointer_offset = layout.GetHeapPointerOffset(); +// Remove trailing ' ', '\f', '\n', '\r', '\t', '\v' +void StringUtil::RTrim(string &str) { + str.erase(find_if(str.rbegin(), str.rend(), [](int ch) { return ch > 0 && !CharacterIsSpace(ch); }).base(), + str.end()); +} - // Left and right row data to merge - data_ptr_t l_ptr; - data_ptr_t r_ptr; - // Accompanying left and right heap data (if needed) - data_ptr_t l_heap_ptr; - data_ptr_t r_heap_ptr; +void StringUtil::Trim(string &str) { + StringUtil::LTrim(str); + StringUtil::RTrim(str); +} - // Result rows to write to - RowDataBlock *result_data_block = &result_data.data_blocks.back(); - auto result_data_handle = buffer_manager.Pin(result_data_block->block); - data_ptr_t result_data_ptr = result_data_handle->Ptr() + result_data_block->count * row_width; - // Result heap to write to (if needed) - RowDataBlock *result_heap_block; - unique_ptr result_heap_handle; - data_ptr_t result_heap_ptr; - if (!layout.AllConstant() && state.external) { - result_heap_block = &result_data.heap_blocks.back(); - result_heap_handle = buffer_manager.Pin(result_heap_block->block); - result_heap_ptr = result_heap_handle->Ptr() + result_heap_block->byte_offset; +bool StringUtil::StartsWith(string str, string prefix) { + if (prefix.size() > str.size()) { + return false; } + return equal(prefix.begin(), prefix.end(), str.begin()); +} - idx_t copied = 0; - while (copied < count) { - // Move to new data blocks (if needed) - if (l.block_idx < l_data.data_blocks.size() && l.entry_idx == l_data.data_blocks[l.block_idx].count) { - // Delete reference to previous block - l_data.data_blocks[l.block_idx].block = nullptr; - if (!layout.AllConstant() && state.external) { - l_data.heap_blocks[l.block_idx].block = nullptr; - } - // Advance block - l.block_idx++; - l.entry_idx = 0; - } - if (r.block_idx < r_data.data_blocks.size() && r.entry_idx == r_data.data_blocks[r.block_idx].count) { - // Delete reference to previous block - r_data.data_blocks[r.block_idx].block = nullptr; - if (!layout.AllConstant() && state.external) { - r_data.heap_blocks[r.block_idx].block = nullptr; - } - // Advance block - r.block_idx++; - r.entry_idx = 0; - } - const bool l_done = l.block_idx == l_data.data_blocks.size(); - const bool r_done = r.block_idx == r_data.data_blocks.size(); - // Pin the row data blocks - if (!l_done) { - l.PinData(l_data); - l_ptr = l.DataPtr(l_data); - } - if (!r_done) { - r.PinData(r_data); - r_ptr = r.DataPtr(r_data); - } - const idx_t &l_count = !l_done ? l_data.data_blocks[l.block_idx].count : 0; - const idx_t &r_count = !r_done ? r_data.data_blocks[r.block_idx].count : 0; - // Perform the merge - if (layout.AllConstant() || !state.external) { - // If all constant size, or if we are doing an in-memory sort, we do not need to touch the heap - if (!l_done && !r_done) { - // Both sides have data - merge - MergeRows(l_ptr, l.entry_idx, l_count, r_ptr, r.entry_idx, r_count, result_data_block, result_data_ptr, - row_width, left_smaller, copied, count); - } else if (r_done) { - // Right side is exhausted - FlushRows(l_ptr, l.entry_idx, l_count, result_data_block, result_data_ptr, row_width, copied, count); - } else { - // Left side is exhausted - FlushRows(r_ptr, r.entry_idx, r_count, result_data_block, result_data_ptr, row_width, copied, count); - } - } else { - // External sorting with variable size data. Pin the heap blocks too - if (!l_done) { - l_heap_ptr = l.BaseHeapPtr(l_data) + Load(l_ptr + heap_pointer_offset); - D_ASSERT(l_heap_ptr - l.BaseHeapPtr(l_data) >= 0); - D_ASSERT((idx_t)(l_heap_ptr - l.BaseHeapPtr(l_data)) < l_data.heap_blocks[l.block_idx].byte_offset); - } - if (!r_done) { - r_heap_ptr = r.BaseHeapPtr(r_data) + Load(r_ptr + heap_pointer_offset); - D_ASSERT(r_heap_ptr - r.BaseHeapPtr(r_data) >= 0); - D_ASSERT((idx_t)(r_heap_ptr - r.BaseHeapPtr(r_data)) < r_data.heap_blocks[r.block_idx].byte_offset); - } - // Both the row and heap data need to be dealt with - if (!l_done && !r_done) { - // Both sides have data - merge - idx_t l_idx_copy = l.entry_idx; - idx_t r_idx_copy = r.entry_idx; - data_ptr_t result_data_ptr_copy = result_data_ptr; - idx_t copied_copy = copied; - // Merge row data - MergeRows(l_ptr, l_idx_copy, l_count, r_ptr, r_idx_copy, r_count, result_data_block, - result_data_ptr_copy, row_width, left_smaller, copied_copy, count); - const idx_t merged = copied_copy - copied; - // Compute the entry sizes and number of heap bytes that will be copied - idx_t copy_bytes = 0; - data_ptr_t l_heap_ptr_copy = l_heap_ptr; - data_ptr_t r_heap_ptr_copy = r_heap_ptr; - for (idx_t i = 0; i < merged; i++) { - // Store base heap offset in the row data - Store(result_heap_block->byte_offset + copy_bytes, result_data_ptr + heap_pointer_offset); - result_data_ptr += row_width; - // Compute entry size and add to total - const bool &l_smaller = left_smaller[copied + i]; - const bool r_smaller = !l_smaller; - auto &entry_size = next_entry_sizes[copied + i]; - entry_size = - l_smaller * Load(l_heap_ptr_copy) + r_smaller * Load(r_heap_ptr_copy); - D_ASSERT(entry_size >= sizeof(uint32_t)); - D_ASSERT(l_heap_ptr_copy - l.BaseHeapPtr(l_data) + l_smaller * entry_size <= - l_data.heap_blocks[l.block_idx].byte_offset); - D_ASSERT(r_heap_ptr_copy - r.BaseHeapPtr(r_data) + r_smaller * entry_size <= - r_data.heap_blocks[r.block_idx].byte_offset); - l_heap_ptr_copy += l_smaller * entry_size; - r_heap_ptr_copy += r_smaller * entry_size; - copy_bytes += entry_size; - } - // Reallocate result heap block size (if needed) - if (result_heap_block->byte_offset + copy_bytes > result_heap_block->capacity) { - idx_t new_capacity = result_heap_block->byte_offset + copy_bytes; - buffer_manager.ReAllocate(result_heap_block->block, new_capacity); - result_heap_block->capacity = new_capacity; - result_heap_ptr = result_heap_handle->Ptr() + result_heap_block->byte_offset; - } - D_ASSERT(result_heap_block->byte_offset + copy_bytes <= result_heap_block->capacity); - // Now copy the heap data - for (idx_t i = 0; i < merged; i++) { - const bool &l_smaller = left_smaller[copied + i]; - const bool r_smaller = !l_smaller; - const auto &entry_size = next_entry_sizes[copied + i]; - memcpy(result_heap_ptr, (data_ptr_t)(l_smaller * (idx_t)l_heap_ptr + r_smaller * (idx_t)r_heap_ptr), - entry_size); - D_ASSERT(Load(result_heap_ptr) == entry_size); - result_heap_ptr += entry_size; - l_heap_ptr += l_smaller * entry_size; - r_heap_ptr += r_smaller * entry_size; - l.entry_idx += l_smaller; - r.entry_idx += r_smaller; - } - // Update result indices and pointers - result_heap_block->count += merged; - result_heap_block->byte_offset += copy_bytes; - copied += merged; - } else if (r_done) { - // Right side is exhausted - flush left - FlushBlobs(layout, l_count, l_ptr, l.entry_idx, l_heap_ptr, result_data_block, result_data_ptr, - result_heap_block, *result_heap_handle, result_heap_ptr, copied, count); - } else { - // Left side is exhausted - flush right - FlushBlobs(layout, r_count, r_ptr, r.entry_idx, r_heap_ptr, result_data_block, result_data_ptr, - result_heap_block, *result_heap_handle, result_heap_ptr, copied, count); - } - D_ASSERT(result_data_block->count == result_heap_block->count); - } +bool StringUtil::EndsWith(const string &str, const string &suffix) { + if (suffix.size() > str.size()) { + return false; } - if (reset_indices) { - left->SetIndices(l_block_idx_before, l_entry_idx_before); - right->SetIndices(r_block_idx_before, r_entry_idx_before); + return equal(suffix.rbegin(), suffix.rend(), str.rbegin()); +} + +string StringUtil::Repeat(const string &str, idx_t n) { + std::ostringstream os; + for (idx_t i = 0; i < n; i++) { + os << str; } + return (os.str()); } -void MergeSorter::MergeRows(data_ptr_t &l_ptr, idx_t &l_entry_idx, const idx_t &l_count, data_ptr_t &r_ptr, - idx_t &r_entry_idx, const idx_t &r_count, RowDataBlock *target_block, - data_ptr_t &target_ptr, const idx_t &entry_size, const bool left_smaller[], idx_t &copied, - const idx_t &count) { - const idx_t next = MinValue(count - copied, target_block->capacity - target_block->count); - idx_t i; - for (i = 0; i < next && l_entry_idx < l_count && r_entry_idx < r_count; i++) { - const bool &l_smaller = left_smaller[copied + i]; - const bool r_smaller = !l_smaller; - // Use comparison bool (0 or 1) to copy an entry from either side - FastMemcpy(target_ptr, (data_ptr_t)(l_smaller * (idx_t)l_ptr + r_smaller * (idx_t)r_ptr), entry_size); - target_ptr += entry_size; - // Use the comparison bool to increment entries and pointers - l_entry_idx += l_smaller; - r_entry_idx += r_smaller; - l_ptr += l_smaller * entry_size; - r_ptr += r_smaller * entry_size; +vector StringUtil::Split(const string &str, char delimiter) { + std::stringstream ss(str); + vector lines; + string temp; + while (getline(ss, temp, delimiter)) { + lines.push_back(temp); } - // Update counts - target_block->count += i; - copied += i; + return (lines); } -void MergeSorter::FlushRows(data_ptr_t &source_ptr, idx_t &source_entry_idx, const idx_t &source_count, - RowDataBlock *target_block, data_ptr_t &target_ptr, const idx_t &entry_size, idx_t &copied, - const idx_t &count) { - // Compute how many entries we can fit - idx_t next = MinValue(count - copied, target_block->capacity - target_block->count); - next = MinValue(next, source_count - source_entry_idx); - // Copy them all in a single memcpy - const idx_t copy_bytes = next * entry_size; - memcpy(target_ptr, source_ptr, copy_bytes); - target_ptr += copy_bytes; - source_ptr += copy_bytes; - // Update counts - source_entry_idx += next; - target_block->count += next; - copied += next; +namespace string_util_internal { + +inline void SkipSpaces(const string &str, idx_t &index) { + while (index < str.size() && std::isspace(str[index])) { + index++; + } } -void MergeSorter::FlushBlobs(const RowLayout &layout, const idx_t &source_count, data_ptr_t &source_data_ptr, - idx_t &source_entry_idx, data_ptr_t &source_heap_ptr, RowDataBlock *target_data_block, - data_ptr_t &target_data_ptr, RowDataBlock *target_heap_block, - BufferHandle &target_heap_handle, data_ptr_t &target_heap_ptr, idx_t &copied, - const idx_t &count) { - const idx_t row_width = layout.GetRowWidth(); - const idx_t heap_pointer_offset = layout.GetHeapPointerOffset(); - idx_t source_entry_idx_copy = source_entry_idx; - data_ptr_t target_data_ptr_copy = target_data_ptr; - idx_t copied_copy = copied; - // Flush row data - FlushRows(source_data_ptr, source_entry_idx_copy, source_count, target_data_block, target_data_ptr_copy, row_width, - copied_copy, count); - const idx_t flushed = copied_copy - copied; - // Compute the entry sizes and number of heap bytes that will be copied - idx_t copy_bytes = 0; - data_ptr_t source_heap_ptr_copy = source_heap_ptr; - for (idx_t i = 0; i < flushed; i++) { - // Store base heap offset in the row data - Store(target_heap_block->byte_offset + copy_bytes, target_data_ptr + heap_pointer_offset); - target_data_ptr += row_width; - // Compute entry size and add to total - auto entry_size = Load(source_heap_ptr_copy); - D_ASSERT(entry_size >= sizeof(uint32_t)); - source_heap_ptr_copy += entry_size; - copy_bytes += entry_size; +inline void ConsumeLetter(const string &str, idx_t &index, char expected) { + if (index >= str.size() || str[index] != expected) { + throw ParserException("Invalid quoted list: %s", str); } - // Reallocate result heap block size (if needed) - if (target_heap_block->byte_offset + copy_bytes > target_heap_block->capacity) { - idx_t new_capacity = target_heap_block->byte_offset + copy_bytes; - buffer_manager.ReAllocate(target_heap_block->block, new_capacity); - target_heap_block->capacity = new_capacity; - target_heap_ptr = target_heap_handle.Ptr() + target_heap_block->byte_offset; + + index++; +} + +template +inline void TakeWhile(const string &str, idx_t &index, const F &cond, string &taker) { + while (index < str.size() && cond(str[index])) { + taker.push_back(str[index]); + index++; } - D_ASSERT(target_heap_block->byte_offset + copy_bytes <= target_heap_block->capacity); - // Copy the heap data in one go - memcpy(target_heap_ptr, source_heap_ptr, copy_bytes); - target_heap_ptr += copy_bytes; - source_heap_ptr += copy_bytes; - source_entry_idx += flushed; - copied += flushed; - // Update result indices and pointers - target_heap_block->count += flushed; - target_heap_block->byte_offset += copy_bytes; - D_ASSERT(target_heap_block->byte_offset <= target_heap_block->capacity); } -} // namespace duckdb +inline string TakePossiblyQuotedItem(const string &str, idx_t &index, char delimiter, char quote) { + string entry; + if (str[index] == quote) { + index++; + TakeWhile( + str, index, [quote](char c) { return c != quote; }, entry); + ConsumeLetter(str, index, quote); + } else { + TakeWhile( + str, index, [delimiter, quote](char c) { return c != delimiter && c != quote && !std::isspace(c); }, entry); + } + return entry; +} +} // namespace string_util_internal -namespace duckdb { +vector StringUtil::SplitWithQuote(const string &str, char delimiter, char quote) { + vector entries; + idx_t i = 0; -//! Calls std::sort on strings that are tied by their prefix after the radix sort -static void SortTiedBlobs(BufferManager &buffer_manager, const data_ptr_t dataptr, const idx_t &start, const idx_t &end, - const idx_t &tie_col, bool *ties, const data_ptr_t blob_ptr, const SortLayout &sort_layout) { - const auto row_width = sort_layout.blob_layout.GetRowWidth(); - const idx_t &col_idx = sort_layout.sorting_to_blob_col.at(tie_col); - // Locate the first blob row in question - data_ptr_t row_ptr = dataptr + start * sort_layout.entry_size; - data_ptr_t blob_row_ptr = blob_ptr + Load(row_ptr + sort_layout.comparison_size) * row_width; - if (!Comparators::TieIsBreakable(col_idx, blob_row_ptr, sort_layout.blob_layout)) { - // Quick check to see if ties can be broken - return; - } - // Fill pointer array for sorting - auto ptr_block = unique_ptr(new data_ptr_t[end - start]); - auto entry_ptrs = (data_ptr_t *)ptr_block.get(); - for (idx_t i = start; i < end; i++) { - entry_ptrs[i - start] = row_ptr; - row_ptr += sort_layout.entry_size; - } - // Slow pointer-based sorting - const int order = sort_layout.order_types[tie_col] == OrderType::DESCENDING ? -1 : 1; - const auto &tie_col_offset = sort_layout.blob_layout.GetOffsets()[col_idx]; - auto logical_type = sort_layout.blob_layout.GetTypes()[col_idx]; - std::sort(entry_ptrs, entry_ptrs + end - start, - [&blob_ptr, &order, &sort_layout, &tie_col_offset, &row_width, &logical_type](const data_ptr_t l, - const data_ptr_t r) { - idx_t left_idx = Load(l + sort_layout.comparison_size); - idx_t right_idx = Load(r + sort_layout.comparison_size); - data_ptr_t left_ptr = blob_ptr + left_idx * row_width + tie_col_offset; - data_ptr_t right_ptr = blob_ptr + right_idx * row_width + tie_col_offset; - return order * Comparators::CompareVal(left_ptr, right_ptr, logical_type) < 0; - }); - // Re-order - auto temp_block = - buffer_manager.Allocate(MaxValue((end - start) * sort_layout.entry_size, (idx_t)Storage::BLOCK_SIZE)); - data_ptr_t temp_ptr = temp_block->Ptr(); - for (idx_t i = 0; i < end - start; i++) { - FastMemcpy(temp_ptr, entry_ptrs[i], sort_layout.entry_size); - temp_ptr += sort_layout.entry_size; - } - memcpy(dataptr + start * sort_layout.entry_size, temp_block->Ptr(), (end - start) * sort_layout.entry_size); - // Determine if there are still ties (if this is not the last column) - if (tie_col < sort_layout.column_count - 1) { - data_ptr_t idx_ptr = dataptr + start * sort_layout.entry_size + sort_layout.comparison_size; - // Load current entry - data_ptr_t current_ptr = blob_ptr + Load(idx_ptr) * row_width + tie_col_offset; - for (idx_t i = 0; i < end - start - 1; i++) { - // Load next entry and compare - idx_ptr += sort_layout.entry_size; - data_ptr_t next_ptr = blob_ptr + Load(idx_ptr) * row_width + tie_col_offset; - ties[start + i] = Comparators::CompareVal(current_ptr, next_ptr, logical_type) == 0; - current_ptr = next_ptr; + string_util_internal::SkipSpaces(str, i); + while (i < str.size()) { + if (!entries.empty()) { + string_util_internal::ConsumeLetter(str, i, delimiter); } + + entries.emplace_back(string_util_internal::TakePossiblyQuotedItem(str, i, delimiter, quote)); + string_util_internal::SkipSpaces(str, i); } + + return entries; } -//! Identifies sequences of rows that are tied by the prefix of a blob column, and sorts them -static void SortTiedBlobs(BufferManager &buffer_manager, SortedBlock &sb, bool *ties, data_ptr_t dataptr, - const idx_t &count, const idx_t &tie_col, const SortLayout &sort_layout) { - D_ASSERT(!ties[count - 1]); - auto &blob_block = sb.blob_sorting_data->data_blocks.back(); - auto blob_handle = buffer_manager.Pin(blob_block.block); - const data_ptr_t blob_ptr = blob_handle->Ptr(); +string StringUtil::Join(const vector &input, const string &separator) { + return StringUtil::Join(input, input.size(), separator, [](const string &s) { return s; }); +} - for (idx_t i = 0; i < count; i++) { - if (!ties[i]) { - continue; - } - idx_t j; - for (j = i; j < count; j++) { - if (!ties[j]) { - break; - } - } - SortTiedBlobs(buffer_manager, dataptr, i, j + 1, tie_col, ties, blob_ptr, sort_layout); - i = j; +string StringUtil::BytesToHumanReadableString(idx_t bytes) { + string db_size; + auto kilobytes = bytes / 1000; + auto megabytes = kilobytes / 1000; + kilobytes -= megabytes * 1000; + auto gigabytes = megabytes / 1000; + megabytes -= gigabytes * 1000; + auto terabytes = gigabytes / 1000; + gigabytes -= terabytes * 1000; + if (terabytes > 0) { + return to_string(terabytes) + "." + to_string(gigabytes / 100) + "TB"; + } else if (gigabytes > 0) { + return to_string(gigabytes) + "." + to_string(megabytes / 100) + "GB"; + } else if (megabytes > 0) { + return to_string(megabytes) + "." + to_string(kilobytes / 100) + "MB"; + } else if (kilobytes > 0) { + return to_string(kilobytes) + "KB"; + } else { + return to_string(bytes) + " bytes"; } } -//! Returns whether there are any 'true' values in the ties[] array -static bool AnyTies(bool ties[], const idx_t &count) { - D_ASSERT(!ties[count - 1]); - bool any_ties = false; - for (idx_t i = 0; i < count - 1; i++) { - any_ties = any_ties || ties[i]; - } - return any_ties; +string StringUtil::Upper(const string &str) { + string copy(str); + transform(copy.begin(), copy.end(), copy.begin(), [](unsigned char c) { return std::toupper(c); }); + return (copy); } -//! Compares subsequent rows to check for ties -static void ComputeTies(data_ptr_t dataptr, const idx_t &count, const idx_t &col_offset, const idx_t &tie_size, - bool ties[], const SortLayout &sort_layout) { - D_ASSERT(!ties[count - 1]); - D_ASSERT(col_offset + tie_size <= sort_layout.comparison_size); - // Align dataptr - dataptr += col_offset; - for (idx_t i = 0; i < count - 1; i++) { - ties[i] = ties[i] && FastMemcmp(dataptr, dataptr + sort_layout.entry_size, tie_size) == 0; - dataptr += sort_layout.entry_size; - } +string StringUtil::Lower(const string &str) { + string copy(str); + transform(copy.begin(), copy.end(), copy.begin(), [](unsigned char c) { return std::tolower(c); }); + return (copy); } -//! Textbook LSD radix sort -void RadixSortLSD(BufferManager &buffer_manager, const data_ptr_t &dataptr, const idx_t &count, const idx_t &col_offset, - const idx_t &row_width, const idx_t &sorting_size) { - auto temp_block = buffer_manager.Allocate(MaxValue(count * row_width, (idx_t)Storage::BLOCK_SIZE)); - bool swap = false; +vector StringUtil::Split(const string &input, const string &split) { + vector splits; - idx_t counts[SortConstants::VALUES_PER_RADIX]; - for (idx_t r = 1; r <= sorting_size; r++) { - // Init counts to 0 - memset(counts, 0, sizeof(counts)); - // Const some values for convenience - const data_ptr_t source_ptr = swap ? temp_block->Ptr() : dataptr; - const data_ptr_t target_ptr = swap ? dataptr : temp_block->Ptr(); - const idx_t offset = col_offset + sorting_size - r; - // Collect counts - data_ptr_t offset_ptr = source_ptr + offset; - for (idx_t i = 0; i < count; i++) { - counts[*offset_ptr]++; - offset_ptr += row_width; - } - // Compute offsets from counts - idx_t max_count = counts[0]; - for (idx_t val = 1; val < SortConstants::VALUES_PER_RADIX; val++) { - max_count = MaxValue(max_count, counts[val]); - counts[val] = counts[val] + counts[val - 1]; - } - if (max_count == count) { - continue; + idx_t last = 0; + idx_t input_len = input.size(); + idx_t split_len = split.size(); + while (last <= input_len) { + idx_t next = input.find(split, last); + if (next == string::npos) { + next = input_len; } - // Re-order the data in temporary array - data_ptr_t row_ptr = source_ptr + (count - 1) * row_width; - for (idx_t i = 0; i < count; i++) { - idx_t &radix_offset = --counts[*(row_ptr + offset)]; - FastMemcpy(target_ptr + radix_offset * row_width, row_ptr, row_width); - row_ptr -= row_width; + + // Push the substring [last, next) on to splits + string substr = input.substr(last, next - last); + if (substr.empty() == false) { + splits.push_back(substr); } - swap = !swap; + last = next + split_len; } - // Move data back to original buffer (if it was swapped) - if (swap) { - memcpy(dataptr, temp_block->Ptr(), count * row_width); + return splits; +} + +string StringUtil::Replace(string source, const string &from, const string &to) { + idx_t start_pos = 0; + while ((start_pos = source.find(from, start_pos)) != string::npos) { + source.replace(start_pos, from.length(), to); + start_pos += to.length(); // In case 'to' contains 'from', like + // replacing 'x' with 'yx' } + return source; } -//! Insertion sort, used when count of values is low -inline void InsertionSort(const data_ptr_t orig_ptr, const data_ptr_t temp_ptr, const idx_t &count, - const idx_t &col_offset, const idx_t &row_width, const idx_t &total_comp_width, - const idx_t &offset, bool swap) { - const data_ptr_t source_ptr = swap ? temp_ptr : orig_ptr; - const data_ptr_t target_ptr = swap ? orig_ptr : temp_ptr; - if (count > 1) { - const idx_t total_offset = col_offset + offset; - auto temp_val = unique_ptr(new data_t[row_width]); - const data_ptr_t val = temp_val.get(); - const auto comp_width = total_comp_width - offset; - for (idx_t i = 1; i < count; i++) { - FastMemcpy(val, source_ptr + i * row_width, row_width); - idx_t j = i; - while (j > 0 && - FastMemcmp(source_ptr + (j - 1) * row_width + total_offset, val + total_offset, comp_width) > 0) { - FastMemcpy(source_ptr + j * row_width, source_ptr + (j - 1) * row_width, row_width); - j--; - } - FastMemcpy(source_ptr + j * row_width, val, row_width); - } +vector StringUtil::TopNStrings(vector> scores, idx_t n, idx_t threshold) { + if (scores.empty()) { + return vector(); } - if (swap) { - memcpy(target_ptr, source_ptr, count * row_width); + sort(scores.begin(), scores.end(), + [](const pair &a, const pair &b) -> bool { return a.second < b.second; }); + vector result; + result.push_back(scores[0].first); + for (idx_t i = 1; i < MinValue(scores.size(), n); i++) { + if (scores[i].second > threshold) { + break; + } + result.push_back(scores[i].first); } + return result; } -//! MSD radix sort that switches to insertion sort with low bucket sizes -void RadixSortMSD(const data_ptr_t orig_ptr, const data_ptr_t temp_ptr, const idx_t &count, const idx_t &col_offset, - const idx_t &row_width, const idx_t &comp_width, const idx_t &offset, idx_t locations[], bool swap) { - const data_ptr_t source_ptr = swap ? temp_ptr : orig_ptr; - const data_ptr_t target_ptr = swap ? orig_ptr : temp_ptr; - // Init counts to 0 - memset(locations, 0, SortConstants::MSD_RADIX_LOCATIONS * sizeof(idx_t)); - idx_t *counts = locations + 1; - // Collect counts - const idx_t total_offset = col_offset + offset; - data_ptr_t offset_ptr = source_ptr + total_offset; - for (idx_t i = 0; i < count; i++) { - counts[*offset_ptr]++; - offset_ptr += row_width; +struct LevenshteinArray { + LevenshteinArray(idx_t len1, idx_t len2) : len1(len1) { + dist = unique_ptr(new idx_t[len1 * len2]); } - // Compute locations from counts - idx_t max_count = 0; - for (idx_t radix = 0; radix < SortConstants::VALUES_PER_RADIX; radix++) { - max_count = MaxValue(max_count, counts[radix]); - counts[radix] += locations[radix]; + + idx_t &Score(idx_t i, idx_t j) { + return dist[GetIndex(i, j)]; } - if (max_count != count) { - // Re-order the data in temporary array - data_ptr_t row_ptr = source_ptr; - for (idx_t i = 0; i < count; i++) { - const idx_t &radix_offset = locations[*(row_ptr + total_offset)]++; - FastMemcpy(target_ptr + radix_offset * row_width, row_ptr, row_width); - row_ptr += row_width; - } - swap = !swap; + +private: + idx_t len1; + unique_ptr dist; + + idx_t GetIndex(idx_t i, idx_t j) { + return j * len1 + i; } - // Check if done - if (offset == comp_width - 1) { - if (swap) { - memcpy(orig_ptr, temp_ptr, count * row_width); - } - return; +}; + +// adapted from https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C++ +idx_t StringUtil::LevenshteinDistance(const string &s1_p, const string &s2_p) { + auto s1 = StringUtil::Lower(s1_p); + auto s2 = StringUtil::Lower(s2_p); + idx_t len1 = s1.size(); + idx_t len2 = s2.size(); + if (len1 == 0) { + return len2; } - if (max_count == count) { - RadixSortMSD(orig_ptr, temp_ptr, count, col_offset, row_width, comp_width, offset + 1, - locations + SortConstants::MSD_RADIX_LOCATIONS, swap); - return; + if (len2 == 0) { + return len1; } - // Recurse - idx_t radix_count = locations[0]; - for (idx_t radix = 0; radix < SortConstants::VALUES_PER_RADIX; radix++) { - const idx_t loc = (locations[radix] - radix_count) * row_width; - if (radix_count > SortConstants::INSERTION_SORT_THRESHOLD) { - RadixSortMSD(orig_ptr + loc, temp_ptr + loc, radix_count, col_offset, row_width, comp_width, offset + 1, - locations + SortConstants::MSD_RADIX_LOCATIONS, swap); - } else if (radix_count != 0) { - InsertionSort(orig_ptr + loc, temp_ptr + loc, radix_count, col_offset, row_width, comp_width, offset + 1, - swap); + LevenshteinArray array(len1 + 1, len2 + 1); + array.Score(0, 0) = 0; + for (idx_t i = 0; i <= len1; i++) { + array.Score(i, 0) = i; + } + for (idx_t j = 0; j <= len2; j++) { + array.Score(0, j) = j; + } + for (idx_t i = 1; i <= len1; i++) { + for (idx_t j = 1; j <= len2; j++) { + // d[i][j] = std::min({ d[i - 1][j] + 1, + // d[i][j - 1] + 1, + // d[i - 1][j - 1] + (s1[i - 1] == s2[j - 1] ? 0 : 1) }); + int equal = s1[i - 1] == s2[j - 1] ? 0 : 1; + idx_t adjacent_score1 = array.Score(i - 1, j) + 1; + idx_t adjacent_score2 = array.Score(i, j - 1) + 1; + idx_t adjacent_score3 = array.Score(i - 1, j - 1) + equal; + + idx_t t = MinValue(adjacent_score1, adjacent_score2); + array.Score(i, j) = MinValue(t, adjacent_score3); } - radix_count = locations[radix + 1] - locations[radix]; } + return array.Score(len1, len2); } -//! Calls different sort functions, depending on the count and sorting sizes -void RadixSort(BufferManager &buffer_manager, const data_ptr_t &dataptr, const idx_t &count, const idx_t &col_offset, - const idx_t &sorting_size, const SortLayout &sort_layout) { - if (count <= SortConstants::INSERTION_SORT_THRESHOLD) { - InsertionSort(dataptr, nullptr, count, 0, sort_layout.entry_size, sort_layout.comparison_size, 0, false); - } else if (sorting_size <= SortConstants::MSD_RADIX_SORT_SIZE_THRESHOLD) { - RadixSortLSD(buffer_manager, dataptr, count, col_offset, sort_layout.entry_size, sorting_size); - } else { - auto temp_block = buffer_manager.Allocate(MaxValue(count * sort_layout.entry_size, (idx_t)Storage::BLOCK_SIZE)); - auto preallocated_array = unique_ptr(new idx_t[sorting_size * SortConstants::MSD_RADIX_LOCATIONS]); - RadixSortMSD(dataptr, temp_block->Ptr(), count, col_offset, sort_layout.entry_size, sorting_size, 0, - preallocated_array.get(), false); +vector StringUtil::TopNLevenshtein(const vector &strings, const string &target, idx_t n, + idx_t threshold) { + vector> scores; + scores.reserve(strings.size()); + for (auto &str : strings) { + scores.emplace_back(str, LevenshteinDistance(str, target)); } + return TopNStrings(scores, n, threshold); } -//! Identifies sequences of rows that are tied, and calls radix sort on these -static void SubSortTiedTuples(BufferManager &buffer_manager, const data_ptr_t dataptr, const idx_t &count, - const idx_t &col_offset, const idx_t &sorting_size, bool ties[], - const SortLayout &sort_layout) { - D_ASSERT(!ties[count - 1]); - for (idx_t i = 0; i < count; i++) { - if (!ties[i]) { - continue; - } - idx_t j; - for (j = i + 1; j < count; j++) { - if (!ties[j]) { - break; +string StringUtil::CandidatesMessage(const vector &candidates, const string &candidate) { + string result_str; + if (!candidates.empty()) { + result_str = "\n" + candidate + ": "; + for (idx_t i = 0; i < candidates.size(); i++) { + if (i > 0) { + result_str += ", "; } + result_str += "\"" + candidates[i] + "\""; } - RadixSort(buffer_manager, dataptr + i * sort_layout.entry_size, j - i + 1, col_offset, sorting_size, - sort_layout); - i = j; } + return result_str; } -void LocalSortState::SortInMemory() { - auto &sb = *sorted_blocks.back(); - auto &block = sb.radix_sorting_data.back(); - const auto &count = block.count; - auto handle = buffer_manager->Pin(block.block); - const auto dataptr = handle->Ptr(); - // Assign an index to each row - data_ptr_t idx_dataptr = dataptr + sort_layout->comparison_size; - for (uint32_t i = 0; i < count; i++) { - Store(i, idx_dataptr); - idx_dataptr += sort_layout->entry_size; - } - // Radix sort and break ties until no more ties, or until all columns are sorted - idx_t sorting_size = 0; - idx_t col_offset = 0; - unique_ptr ties_ptr; - bool *ties = nullptr; - for (idx_t i = 0; i < sort_layout->column_count; i++) { - sorting_size += sort_layout->column_sizes[i]; - if (sort_layout->constant_size[i] && i < sort_layout->column_count - 1) { - // Add columns to the sorting size until we reach a variable size column, or the last column - continue; - } +string StringUtil::CandidatesErrorMessage(const vector &strings, const string &target, + const string &message_prefix, idx_t n) { + auto closest_strings = StringUtil::TopNLevenshtein(strings, target, n); + return StringUtil::CandidatesMessage(closest_strings, message_prefix); +} - if (!ties) { - // This is the first sort - RadixSort(*buffer_manager, dataptr, count, col_offset, sorting_size, *sort_layout); - ties_ptr = unique_ptr(new bool[count]); - ties = ties_ptr.get(); - std::fill_n(ties, count - 1, true); - ties[count - 1] = false; - } else { - // For subsequent sorts, we only have to subsort the tied tuples - SubSortTiedTuples(*buffer_manager, dataptr, count, col_offset, sorting_size, ties, *sort_layout); - } +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/tree_renderer.hpp +// +// +//===----------------------------------------------------------------------===// - if (sort_layout->constant_size[i] && i == sort_layout->column_count - 1) { - // All columns are sorted, no ties to break because last column is constant size - break; - } - - ComputeTies(dataptr, count, col_offset, sorting_size, ties, *sort_layout); - if (!AnyTies(ties, count)) { - // No ties, stop sorting - break; - } - - if (!sort_layout->constant_size[i]) { - SortTiedBlobs(*buffer_manager, sb, ties, dataptr, count, i, *sort_layout); - if (!AnyTies(ties, count)) { - // No more ties after tie-breaking, stop - break; - } - } - - col_offset += sorting_size; - sorting_size = 0; - } -} - -} // namespace duckdb @@ -38602,7 +43073,7 @@ void LocalSortState::SortInMemory() { //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/storage/statistics/string_statistics.hpp +// duckdb/main/query_profiler.hpp // // //===----------------------------------------------------------------------===// @@ -38610,1671 +43081,459 @@ void LocalSortState::SortInMemory() { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/enums/filter_propagate_result.hpp -// -// -//===----------------------------------------------------------------------===// - - -namespace duckdb { -enum class FilterPropagateResult : uint8_t { - NO_PRUNING_POSSIBLE = 0, - FILTER_ALWAYS_TRUE = 1, - FILTER_ALWAYS_FALSE = 2, - FILTER_TRUE_OR_NULL = 3, - FILTER_FALSE_OR_NULL = 4 -}; -} // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/storage/statistics/validity_statistics.hpp -// -// -//===----------------------------------------------------------------------===// +#include namespace duckdb { -class Serializer; -class Deserializer; -class Vector; - -class ValidityStatistics : public BaseStatistics { -public: - explicit ValidityStatistics(bool has_null = false, bool has_no_null = true); +class ClientContext; +class ExpressionExecutor; +class PhysicalOperator; +class SQLStatement; - //! Whether or not the segment can contain NULL values - bool has_null; - //! Whether or not the segment can contain values that are not null - bool has_no_null; +//! The ExpressionInfo keeps information related to an expression +struct ExpressionInfo { + explicit ExpressionInfo() : hasfunction(false) { + } + // A vector of children + vector> children; + // Extract ExpressionInformation from a given expression state + void ExtractExpressionsRecursive(unique_ptr &state); -public: - void Merge(const BaseStatistics &other) override; + //! Whether or not expression has function + bool hasfunction; + //! The function Name + string function_name; + //! The function time + uint64_t function_time = 0; + //! Count the number of ALL tuples + uint64_t tuples_count = 0; + //! Count the number of tuples sampled + uint64_t sample_tuples_count = 0; +}; - bool IsConstant() const override; +//! The ExpressionRootInfo keeps information related to the root of an expression tree +struct ExpressionRootInfo { + ExpressionRootInfo(ExpressionExecutorState &executor, string name); - unique_ptr Copy() const override; + //! Count the number of time the executor called + uint64_t total_count = 0; + //! Count the number of time the executor called since last sampling + uint64_t current_count = 0; + //! Count the number of samples + uint64_t sample_count = 0; + //! Count the number of tuples in all samples + uint64_t sample_tuples_count = 0; + //! Count the number of tuples processed by this executor + uint64_t tuples_count = 0; + //! A vector which contain the pointer to root of each expression tree + unique_ptr root; + //! Name + string name; + //! Elapsed time + double time; + //! Extra Info + string extra_info; +}; - void Serialize(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader); +struct ExpressionExecutorInfo { + explicit ExpressionExecutorInfo() {}; + explicit ExpressionExecutorInfo(ExpressionExecutor &executor, const string &name, int id); - void Verify(Vector &vector, const SelectionVector &sel, idx_t count) const override; + //! A vector which contain the pointer to all ExpressionRootInfo + vector> roots; + //! Id, it will be used as index for executors_info vector + int id; +}; - static unique_ptr Combine(const unique_ptr &lstats, - const unique_ptr &rstats); +struct OperatorInformation { + explicit OperatorInformation(double time_ = 0, idx_t elements_ = 0) : time(time_), elements(elements_) { + } - string ToString() const override; + double time = 0; + idx_t elements = 0; + string name; + //! A vector of Expression Executor Info + vector> executors_info; }; -} // namespace duckdb +//! The OperatorProfiler measures timings of individual operators +class OperatorProfiler { + friend class QueryProfiler; +public: + DUCKDB_API explicit OperatorProfiler(bool enabled); -namespace duckdb { + DUCKDB_API void StartOperator(const PhysicalOperator *phys_op); + DUCKDB_API void EndOperator(DataChunk *chunk); + DUCKDB_API void Flush(const PhysicalOperator *phys_op, ExpressionExecutor *expression_executor, const string &name, + int id); -class StringStatistics : public BaseStatistics { -public: - constexpr static uint32_t MAX_STRING_MINMAX_SIZE = 8; + ~OperatorProfiler() { + } -public: - explicit StringStatistics(LogicalType type, StatisticsType stats_type); +private: + void AddTiming(const PhysicalOperator *op, double time, idx_t elements); - //! The minimum value of the segment, potentially truncated - data_t min[MAX_STRING_MINMAX_SIZE]; - //! The maximum value of the segment, potentially truncated - data_t max[MAX_STRING_MINMAX_SIZE]; - //! Whether or not the column can contain unicode characters - bool has_unicode; - //! The maximum string length in bytes - uint32_t max_string_length; - //! Whether or not the segment contains any big strings in overflow blocks - bool has_overflow_strings; + //! Whether or not the profiler is enabled + bool enabled; + //! The timer used to time the execution time of the individual Physical Operators + Profiler op; + //! The stack of Physical Operators that are currently active + const PhysicalOperator *active_operator; + //! A mapping of physical operators to recorded timings + unordered_map timings; +}; +//! The QueryProfiler can be used to measure timings of queries +class QueryProfiler { public: - void Update(const string_t &value); - void Merge(const BaseStatistics &other) override; + DUCKDB_API QueryProfiler(ClientContext &context); - unique_ptr Copy() const override; - void Serialize(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader, LogicalType type); - void Verify(Vector &vector, const SelectionVector &sel, idx_t count) const override; +public: + struct TreeNode { + PhysicalOperatorType type; + string name; + string extra_info; + OperatorInformation info; + vector> children; + idx_t depth = 0; + }; - FilterPropagateResult CheckZonemap(ExpressionType comparison_type, const string &value) const; + // Propagate save_location, enabled, detailed_enabled and automatic_print_format. + void Propagate(QueryProfiler &qp); - string ToString() const override; -}; + using TreeMap = unordered_map; -} // namespace duckdb +private: + unique_ptr CreateTree(PhysicalOperator *root, idx_t depth = 0); + void Render(const TreeNode &node, std::ostream &str) const; +public: + DUCKDB_API bool IsEnabled() const; + DUCKDB_API bool IsDetailedEnabled() const; + DUCKDB_API ProfilerPrintFormat GetPrintFormat() const; + DUCKDB_API bool PrintOptimizerOutput() const; + DUCKDB_API string GetSaveLocation() const; -#include + DUCKDB_API static QueryProfiler &Get(ClientContext &context); -namespace duckdb { + DUCKDB_API void StartQuery(string query, bool is_explain_analyze = false, bool start_at_optimizer = false); + DUCKDB_API void EndQuery(); -idx_t GetNestedSortingColSize(idx_t &col_size, const LogicalType &type) { - auto physical_type = type.InternalType(); - if (TypeIsConstantSize(physical_type)) { - col_size += GetTypeIdSize(physical_type); - return 0; - } else { - switch (physical_type) { - case PhysicalType::VARCHAR: { - // Nested strings are between 4 and 11 chars long for alignment - auto size_before_str = col_size; - col_size += 11; - col_size -= (col_size - 12) % 8; - return col_size - size_before_str; - } - case PhysicalType::LIST: - // Lists get 2 bytes (null and empty list) - col_size += 2; - return GetNestedSortingColSize(col_size, ListType::GetChildType(type)); - case PhysicalType::MAP: - case PhysicalType::STRUCT: - // Structs get 1 bytes (null) - col_size++; - return GetNestedSortingColSize(col_size, StructType::GetChildType(type, 0)); - default: - throw NotImplementedException("Unable to order column with type %s", type.ToString()); - } - } -} + DUCKDB_API void StartExplainAnalyze(); -SortLayout::SortLayout(const vector &orders) - : column_count(orders.size()), all_constant(true), comparison_size(0), entry_size(0) { - vector blob_layout_types; - for (idx_t i = 0; i < column_count; i++) { - const auto &order = orders[i]; + //! Adds the timings gathered by an OperatorProfiler to this query profiler + DUCKDB_API void Flush(OperatorProfiler &profiler); - order_types.push_back(order.type); - order_by_null_types.push_back(order.null_order); - auto &expr = *order.expression; - logical_types.push_back(expr.return_type); + DUCKDB_API void StartPhase(string phase); + DUCKDB_API void EndPhase(); - auto physical_type = expr.return_type.InternalType(); - constant_size.push_back(TypeIsConstantSize(physical_type)); + DUCKDB_API void Initialize(PhysicalOperator *root); - if (order.stats) { - stats.push_back(order.stats.get()); - has_null.push_back(stats.back()->CanHaveNull()); - } else { - stats.push_back(nullptr); - has_null.push_back(true); - } + DUCKDB_API string QueryTreeToString() const; + DUCKDB_API void QueryTreeToStream(std::ostream &str) const; + DUCKDB_API void Print(); - idx_t col_size = has_null.back() ? 1 : 0; - prefix_lengths.push_back(0); - if (!TypeIsConstantSize(physical_type) && physical_type != PhysicalType::VARCHAR) { - prefix_lengths.back() = GetNestedSortingColSize(col_size, expr.return_type); - } else if (physical_type == PhysicalType::VARCHAR) { - idx_t size_before = col_size; - if (stats.back()) { - auto &str_stats = (StringStatistics &)*stats.back(); - col_size += str_stats.max_string_length; - if (col_size > 12) { - col_size = 12; - } else { - constant_size.back() = true; - } - } else { - col_size = 12; - } - prefix_lengths.back() = col_size - size_before; - } else { - col_size += GetTypeIdSize(physical_type); - } + //! return the printed as a string. Unlike ToString, which is always formatted as a string, + //! the return value is formatted based on the current print format (see GetPrintFormat()). + DUCKDB_API string ToString() const; - comparison_size += col_size; - column_sizes.push_back(col_size); - } - entry_size = comparison_size + sizeof(uint32_t); + DUCKDB_API string ToJSON() const; + DUCKDB_API void WriteToFile(const char *path, string &info) const; - // 8-byte alignment - if (entry_size % 8 != 0) { - // First assign more bytes to strings instead of aligning - idx_t bytes_to_fill = 8 - (entry_size % 8); - for (idx_t col_idx = 0; col_idx < column_count; col_idx++) { - if (bytes_to_fill == 0) { - break; - } - if (logical_types[col_idx].InternalType() == PhysicalType::VARCHAR && stats[col_idx]) { - auto &str_stats = (StringStatistics &)*stats[col_idx]; - idx_t diff = str_stats.max_string_length - prefix_lengths[col_idx]; - if (diff > 0) { - // Increase all sizes accordingly - idx_t increase = MinValue(bytes_to_fill, diff); - column_sizes[col_idx] += increase; - prefix_lengths[col_idx] += increase; - constant_size[col_idx] = increase == diff; - comparison_size += increase; - entry_size += increase; - bytes_to_fill -= increase; - } - } - } - entry_size = AlignValue(entry_size); + idx_t OperatorSize() { + return tree_map.size(); } - for (idx_t col_idx = 0; col_idx < column_count; col_idx++) { - all_constant = all_constant && constant_size[col_idx]; - if (!constant_size[col_idx]) { - sorting_to_blob_col[col_idx] = blob_layout_types.size(); - blob_layout_types.push_back(logical_types[col_idx]); - } - } + void Finalize(TreeNode &node); - blob_layout.Initialize(blob_layout_types); -} +private: + ClientContext &context; -LocalSortState::LocalSortState() : initialized(false) { -} + //! Whether or not the query profiler is running + bool running; + //! The lock used for flushing information from a thread into the global query profiler + mutex flush_lock; -static idx_t EntriesPerBlock(idx_t width) { - return (Storage::BLOCK_SIZE + width * STANDARD_VECTOR_SIZE - 1) / width; -} + //! Whether or not the query requires profiling + bool query_requires_profiling; -void LocalSortState::Initialize(GlobalSortState &global_sort_state, BufferManager &buffer_manager_p) { - sort_layout = &global_sort_state.sort_layout; - payload_layout = &global_sort_state.payload_layout; - buffer_manager = &buffer_manager_p; - // Radix sorting data - radix_sorting_data = make_unique(*buffer_manager, EntriesPerBlock(sort_layout->entry_size), - sort_layout->entry_size); - // Blob sorting data - if (!sort_layout->all_constant) { - auto blob_row_width = sort_layout->blob_layout.GetRowWidth(); - blob_sorting_data = - make_unique(*buffer_manager, EntriesPerBlock(blob_row_width), blob_row_width); - blob_sorting_heap = make_unique(*buffer_manager, (idx_t)Storage::BLOCK_SIZE, 1, true); - } - // Payload data - auto payload_row_width = payload_layout->GetRowWidth(); - payload_data = - make_unique(*buffer_manager, EntriesPerBlock(payload_row_width), payload_row_width); - payload_heap = make_unique(*buffer_manager, (idx_t)Storage::BLOCK_SIZE, 1, true); - // Init done - initialized = true; -} + //! The root of the query tree + unique_ptr root; + //! The query string + string query; + //! The timer used to time the execution time of the entire query + Profiler main_query; + //! A map of a Physical Operator pointer to a tree node + TreeMap tree_map; + //! Whether or not we are running as part of a explain_analyze query + bool is_explain_analyze; -void LocalSortState::SinkChunk(DataChunk &sort, DataChunk &payload) { - D_ASSERT(sort.size() == payload.size()); - // Build and serialize sorting data to radix sortable rows - auto data_pointers = FlatVector::GetData(addresses); - auto handles = radix_sorting_data->Build(sort.size(), data_pointers, nullptr); - for (idx_t sort_col = 0; sort_col < sort.ColumnCount(); sort_col++) { - bool has_null = sort_layout->has_null[sort_col]; - bool nulls_first = sort_layout->order_by_null_types[sort_col] == OrderByNullType::NULLS_FIRST; - bool desc = sort_layout->order_types[sort_col] == OrderType::DESCENDING; - RowOperations::RadixScatter(sort.data[sort_col], sort.size(), sel_ptr, sort.size(), data_pointers, desc, - has_null, nulls_first, sort_layout->prefix_lengths[sort_col], - sort_layout->column_sizes[sort_col]); +public: + const TreeMap &GetTreeMap() const { + return tree_map; } - // Also fully serialize blob sorting columns (to be able to break ties - if (!sort_layout->all_constant) { - DataChunk blob_chunk; - blob_chunk.SetCardinality(sort.size()); - for (idx_t sort_col = 0; sort_col < sort.ColumnCount(); sort_col++) { - if (!sort_layout->constant_size[sort_col]) { - blob_chunk.data.emplace_back(sort.data[sort_col]); - } - } - handles = blob_sorting_data->Build(blob_chunk.size(), data_pointers, nullptr); - auto blob_data = blob_chunk.Orrify(); - RowOperations::Scatter(blob_chunk, blob_data.get(), sort_layout->blob_layout, addresses, *blob_sorting_heap, - sel_ptr, blob_chunk.size()); - } +private: + //! The timer used to time the individual phases of the planning process + Profiler phase_profiler; + //! A mapping of the phase names to the timings + using PhaseTimingStorage = unordered_map; + PhaseTimingStorage phase_timings; + using PhaseTimingItem = PhaseTimingStorage::value_type; + //! The stack of currently active phases + vector phase_stack; - // Finally, serialize payload data - handles = payload_data->Build(payload.size(), data_pointers, nullptr); - auto input_data = payload.Orrify(); - RowOperations::Scatter(payload, input_data.get(), *payload_layout, addresses, *payload_heap, sel_ptr, - payload.size()); -} +private: + vector GetOrderedPhaseTimings() const; -idx_t LocalSortState::SizeInBytes() const { - idx_t size_in_bytes = radix_sorting_data->SizeInBytes() + payload_data->SizeInBytes(); - if (!sort_layout->all_constant) { - size_in_bytes += blob_sorting_data->SizeInBytes() + blob_sorting_heap->SizeInBytes(); + //! Check whether or not an operator type requires query profiling. If none of the ops in a query require profiling + //! no profiling information is output. + bool OperatorRequiresProfiling(PhysicalOperatorType op_type); +}; + +//! The QueryProfilerHistory can be used to access the profiler of previous queries +class QueryProfilerHistory { +private: + //! Previous Query profilers + deque>> prev_profilers; + //! Previous Query profilers size + uint64_t prev_profilers_size = 20; + +public: + deque>> &GetPrevProfilers() { + return prev_profilers; } - if (!payload_layout->AllConstant()) { - size_in_bytes += payload_heap->SizeInBytes(); + QueryProfilerHistory() { } - return size_in_bytes; -} -void LocalSortState::Sort(GlobalSortState &global_sort_state, bool reorder_heap) { - D_ASSERT(radix_sorting_data->count == payload_data->count); - if (radix_sorting_data->count == 0) { - return; + void SetPrevProfilersSize(uint64_t prevProfilersSize) { + prev_profilers_size = prevProfilersSize; } - // Move all data to a single SortedBlock - sorted_blocks.emplace_back(make_unique(*buffer_manager, global_sort_state)); - auto &sb = *sorted_blocks.back(); - // Fixed-size sorting data - auto sorting_block = ConcatenateBlocks(*radix_sorting_data); - sb.radix_sorting_data.push_back(move(sorting_block)); - // Variable-size sorting data - if (!sort_layout->all_constant) { - auto &blob_data = *blob_sorting_data; - auto new_block = ConcatenateBlocks(blob_data); - sb.blob_sorting_data->data_blocks.push_back(move(new_block)); + uint64_t GetPrevProfilersSize() const { + return prev_profilers_size; } - // Payload data - auto payload_block = ConcatenateBlocks(*payload_data); - sb.payload_data->data_blocks.push_back(move(payload_block)); - // Now perform the actual sort - SortInMemory(); - // Re-order before the merge sort - ReOrder(global_sort_state, reorder_heap); -} -RowDataBlock LocalSortState::ConcatenateBlocks(RowDataCollection &row_data) { - // Create block with the correct capacity - const idx_t &entry_size = row_data.entry_size; - idx_t capacity = MaxValue(((idx_t)Storage::BLOCK_SIZE + entry_size - 1) / entry_size, row_data.count); - RowDataBlock new_block(*buffer_manager, capacity, entry_size); - new_block.count = row_data.count; - auto new_block_handle = buffer_manager->Pin(new_block.block); - data_ptr_t new_block_ptr = new_block_handle->Ptr(); - // Copy the data of the blocks into a single block - for (auto &block : row_data.blocks) { - auto block_handle = buffer_manager->Pin(block.block); - memcpy(new_block_ptr, block_handle->Ptr(), block.count * entry_size); - new_block_ptr += block.count * entry_size; +public: + void SetProfilerHistorySize(uint64_t size) { + this->prev_profilers_size = size; } - row_data.blocks.clear(); - row_data.count = 0; - return new_block; -} +}; +} // namespace duckdb -void LocalSortState::ReOrder(SortedData &sd, data_ptr_t sorting_ptr, RowDataCollection &heap, GlobalSortState &gstate, - bool reorder_heap) { - sd.swizzled = reorder_heap; - auto &unordered_data_block = sd.data_blocks.back(); - const idx_t &count = unordered_data_block.count; - auto unordered_data_handle = buffer_manager->Pin(unordered_data_block.block); - const data_ptr_t unordered_data_ptr = unordered_data_handle->Ptr(); - // Create new block that will hold re-ordered row data - RowDataBlock ordered_data_block(*buffer_manager, unordered_data_block.capacity, unordered_data_block.entry_size); - ordered_data_block.count = count; - auto ordered_data_handle = buffer_manager->Pin(ordered_data_block.block); - data_ptr_t ordered_data_ptr = ordered_data_handle->Ptr(); - // Re-order fixed-size row layout - const idx_t row_width = sd.layout.GetRowWidth(); - const idx_t sorting_entry_size = gstate.sort_layout.entry_size; - for (idx_t i = 0; i < count; i++) { - auto index = Load(sorting_ptr); - FastMemcpy(ordered_data_ptr, unordered_data_ptr + index * row_width, row_width); - ordered_data_ptr += row_width; - sorting_ptr += sorting_entry_size; - } - // Replace the unordered data block with the re-ordered data block - sd.data_blocks.clear(); - sd.data_blocks.push_back(move(ordered_data_block)); - // Deal with the heap (if necessary) - if (!sd.layout.AllConstant() && reorder_heap) { - // Swizzle the column pointers to offsets - RowOperations::SwizzleColumns(sd.layout, ordered_data_handle->Ptr(), count); - // Create a single heap block to store the ordered heap - idx_t total_byte_offset = std::accumulate(heap.blocks.begin(), heap.blocks.end(), 0, - [](idx_t a, const RowDataBlock &b) { return a + b.byte_offset; }); - idx_t heap_block_size = MaxValue(total_byte_offset, (idx_t)Storage::BLOCK_SIZE); - RowDataBlock ordered_heap_block(*buffer_manager, heap_block_size, 1); - ordered_heap_block.count = count; - ordered_heap_block.byte_offset = total_byte_offset; - auto ordered_heap_handle = buffer_manager->Pin(ordered_heap_block.block); - data_ptr_t ordered_heap_ptr = ordered_heap_handle->Ptr(); - // Fill the heap in order - ordered_data_ptr = ordered_data_handle->Ptr(); - const idx_t heap_pointer_offset = sd.layout.GetHeapPointerOffset(); - for (idx_t i = 0; i < count; i++) { - auto heap_row_ptr = Load(ordered_data_ptr + heap_pointer_offset); - auto heap_row_size = Load(heap_row_ptr); - memcpy(ordered_heap_ptr, heap_row_ptr, heap_row_size); - ordered_heap_ptr += heap_row_size; - ordered_data_ptr += row_width; - } - // Swizzle the base pointer to the offset of each row in the heap - RowOperations::SwizzleHeapPointer(sd.layout, ordered_data_handle->Ptr(), ordered_heap_handle->Ptr(), count); - // Move the re-ordered heap to the SortedData, and clear the local heap - sd.heap_blocks.push_back(move(ordered_heap_block)); - heap.pinned_blocks.clear(); - heap.blocks.clear(); - heap.count = 0; - } -} -void LocalSortState::ReOrder(GlobalSortState &gstate, bool reorder_heap) { - auto &sb = *sorted_blocks.back(); - auto sorting_handle = buffer_manager->Pin(sb.radix_sorting_data.back().block); - const data_ptr_t sorting_ptr = sorting_handle->Ptr() + gstate.sort_layout.comparison_size; - // Re-order variable size sorting columns - if (!gstate.sort_layout.all_constant) { - ReOrder(*sb.blob_sorting_data, sorting_ptr, *blob_sorting_heap, gstate, reorder_heap); - } - // And the payload - ReOrder(*sb.payload_data, sorting_ptr, *payload_heap, gstate, reorder_heap); -} +namespace duckdb { +class LogicalOperator; +class PhysicalOperator; +class Pipeline; +struct PipelineRenderNode; -GlobalSortState::GlobalSortState(BufferManager &buffer_manager, const vector &orders, - RowLayout &payload_layout) - : buffer_manager(buffer_manager), sort_layout(SortLayout(orders)), payload_layout(payload_layout), - block_capacity(0), external(false) { -} +struct RenderTreeNode { + string name; + string extra_text; +}; -void GlobalSortState::AddLocalState(LocalSortState &local_sort_state) { - if (!local_sort_state.radix_sorting_data) { - return; - } +struct RenderTree { + RenderTree(idx_t width, idx_t height); - // Sort accumulated data - // we only re-order the heap when the data is expected to not fit in memory - // re-ordering the heap avoids random access when reading/merging but incurs a significant cost of shuffling data - // when data fits in memory, doing random access on reads is cheaper than re-shuffling - local_sort_state.Sort(*this, external || !local_sort_state.sorted_blocks.empty()); + unique_ptr[]> nodes; + idx_t width; + idx_t height; - // Append local state sorted data to this global state - lock_guard append_guard(lock); - for (auto &sb : local_sort_state.sorted_blocks) { - sorted_blocks.push_back(move(sb)); - } - auto &payload_heap = local_sort_state.payload_heap; - for (idx_t i = 0; i < payload_heap->blocks.size(); i++) { - heap_blocks.push_back(move(payload_heap->blocks[i])); - pinned_blocks.push_back(move(payload_heap->pinned_blocks[i])); - } - if (!sort_layout.all_constant) { - auto &blob_heap = local_sort_state.blob_sorting_heap; - for (idx_t i = 0; i < blob_heap->blocks.size(); i++) { - heap_blocks.push_back(move(blob_heap->blocks[i])); - pinned_blocks.push_back(move(blob_heap->pinned_blocks[i])); - } - } -} +public: + RenderTreeNode *GetNode(idx_t x, idx_t y); + void SetNode(idx_t x, idx_t y, unique_ptr node); + bool HasNode(idx_t x, idx_t y); -void GlobalSortState::PrepareMergePhase() { - // Determine if we need to use do an external sort - idx_t total_heap_size = - std::accumulate(sorted_blocks.begin(), sorted_blocks.end(), (idx_t)0, - [](idx_t a, const unique_ptr &b) { return a + b->HeapSize(); }); - if (external || (pinned_blocks.empty() && total_heap_size > 0.25 * buffer_manager.GetMaxMemory())) { - external = true; - } - // Use the data that we have to determine which partition size to use during the merge - if (external && total_heap_size > 0) { - // If we have variable size data we need to be conservative, as there might be skew - idx_t max_block_size = 0; - for (auto &sb : sorted_blocks) { - idx_t size_in_bytes = sb->SizeInBytes(); - if (size_in_bytes > max_block_size) { - max_block_size = size_in_bytes; - block_capacity = sb->Count(); - } - } - } else { - for (auto &sb : sorted_blocks) { - block_capacity = MaxValue(block_capacity, sb->Count()); - } - } - // Unswizzle and pin heap blocks if we can fit everything in memory - if (!external) { - for (auto &sb : sorted_blocks) { - sb->blob_sorting_data->Unswizzle(); - sb->payload_data->Unswizzle(); - } - } -} + idx_t GetPosition(idx_t x, idx_t y); +}; -void GlobalSortState::InitializeMergeRound() { - D_ASSERT(sorted_blocks_temp.empty()); - // If we reverse this list, the blocks that were merged last will be merged first in the next round - // These are still in memory, therefore this reduces the amount of read/write to disk! - std::reverse(sorted_blocks.begin(), sorted_blocks.end()); - // Uneven number of blocks - keep one on the side - if (sorted_blocks.size() % 2 == 1) { - odd_one_out = move(sorted_blocks.back()); - sorted_blocks.pop_back(); - } - // Init merge path path indices - pair_idx = 0; - num_pairs = sorted_blocks.size() / 2; - l_start = 0; - r_start = 0; - // Allocate room for merge results - for (idx_t p_idx = 0; p_idx < num_pairs; p_idx++) { - sorted_blocks_temp.emplace_back(); +struct TreeRendererConfig { + void enable_detailed() { + MAX_EXTRA_LINES = 1000; + detailed = true; } -} -void GlobalSortState::CompleteMergeRound(bool keep_radix_data) { - sorted_blocks.clear(); - for (auto &sorted_block_vector : sorted_blocks_temp) { - sorted_blocks.push_back(make_unique(buffer_manager, *this)); - sorted_blocks.back()->AppendSortedBlocks(sorted_block_vector); - } - sorted_blocks_temp.clear(); - if (odd_one_out) { - sorted_blocks.push_back(move(odd_one_out)); - odd_one_out = nullptr; - } - // Only one block left: Done! - if (sorted_blocks.size() == 1 && !keep_radix_data) { - sorted_blocks[0]->radix_sorting_data.clear(); - sorted_blocks[0]->blob_sorting_data = nullptr; - } -} -void GlobalSortState::Print() { - PayloadScanner scanner(*this, false); - DataChunk chunk; - chunk.Initialize(scanner.GetPayloadTypes()); - for (;;) { - scanner.Scan(chunk); - const auto count = chunk.size(); - if (!count) { - break; - } - chunk.Print(); + void enable_standard() { + MAX_EXTRA_LINES = 30; + detailed = false; } -} - -} // namespace duckdb + idx_t MAXIMUM_RENDER_WIDTH = 240; + idx_t NODE_RENDER_WIDTH = 29; + idx_t MINIMUM_RENDER_WIDTH = 15; + idx_t MAX_EXTRA_LINES = 30; + bool detailed = false; +#ifndef DUCKDB_ASCII_TREE_RENDERER + const char *LTCORNER = "\342\224\214"; // "┌"; + const char *RTCORNER = "\342\224\220"; // "┐"; + const char *LDCORNER = "\342\224\224"; // "└"; + const char *RDCORNER = "\342\224\230"; // "┘"; + const char *MIDDLE = "\342\224\274"; // "┼"; + const char *TMIDDLE = "\342\224\254"; // "┬"; + const char *LMIDDLE = "\342\224\234"; // "├"; + const char *RMIDDLE = "\342\224\244"; // "┤"; + const char *DMIDDLE = "\342\224\264"; // "┴"; + const char *VERTICAL = "\342\224\202"; // "│"; + const char *HORIZONTAL = "\342\224\200"; // "─"; +#else + // ASCII version + const char *LTCORNER = "<"; + const char *RTCORNER = ">"; + const char *LDCORNER = "<"; + const char *RDCORNER = ">"; + const char *MIDDLE = "+"; + const char *TMIDDLE = "+"; + const char *LMIDDLE = "+"; + const char *RMIDDLE = "+"; + const char *DMIDDLE = "+"; -#include + const char *VERTICAL = "|"; + const char *HORIZONTAL = "-"; +#endif +}; -namespace duckdb { +class TreeRenderer { +public: + explicit TreeRenderer(TreeRendererConfig config_p = TreeRendererConfig()) : config(move(config_p)) { + } -SortedData::SortedData(SortedDataType type, const RowLayout &layout, BufferManager &buffer_manager, - GlobalSortState &state) - : type(type), layout(layout), swizzled(false), buffer_manager(buffer_manager), state(state) { -} + string ToString(const LogicalOperator &op); + string ToString(const PhysicalOperator &op); + string ToString(const QueryProfiler::TreeNode &op); + string ToString(const Pipeline &op); -idx_t SortedData::Count() { - idx_t count = std::accumulate(data_blocks.begin(), data_blocks.end(), (idx_t)0, - [](idx_t a, const RowDataBlock &b) { return a + b.count; }); - if (!layout.AllConstant() && state.external) { - D_ASSERT(count == std::accumulate(heap_blocks.begin(), heap_blocks.end(), (idx_t)0, - [](idx_t a, const RowDataBlock &b) { return a + b.count; })); - } - return count; -} + void Render(const LogicalOperator &op, std::ostream &ss); + void Render(const PhysicalOperator &op, std::ostream &ss); + void Render(const QueryProfiler::TreeNode &op, std::ostream &ss); + void Render(const Pipeline &op, std::ostream &ss); -void SortedData::CreateBlock() { - auto capacity = - MaxValue(((idx_t)Storage::BLOCK_SIZE + layout.GetRowWidth() - 1) / layout.GetRowWidth(), state.block_capacity); - data_blocks.emplace_back(buffer_manager, capacity, layout.GetRowWidth()); - if (!layout.AllConstant() && state.external) { - heap_blocks.emplace_back(buffer_manager, (idx_t)Storage::BLOCK_SIZE, 1); - D_ASSERT(data_blocks.size() == heap_blocks.size()); - } -} + void ToStream(RenderTree &root, std::ostream &ss); -unique_ptr SortedData::CreateSlice(idx_t start_block_index, idx_t end_block_index, idx_t end_entry_index) { - // Add the corresponding blocks to the result - auto result = make_unique(type, layout, buffer_manager, state); - for (idx_t i = start_block_index; i <= end_block_index; i++) { - result->data_blocks.push_back(data_blocks[i]); - if (!layout.AllConstant() && state.external) { - result->heap_blocks.push_back(heap_blocks[i]); - } - } - // All of the blocks that come before block with idx = start_block_idx can be reset (other references exist) - for (idx_t i = 0; i < start_block_index; i++) { - data_blocks[i].block = nullptr; - if (!layout.AllConstant() && state.external) { - heap_blocks[i].block = nullptr; - } + void EnableDetailed() { + config.enable_detailed(); } - // Use start and end entry indices to set the boundaries - D_ASSERT(end_entry_index <= result->data_blocks.back().count); - result->data_blocks.back().count = end_entry_index; - if (!layout.AllConstant() && state.external) { - result->heap_blocks.back().count = end_entry_index; + void EnableStandard() { + config.enable_standard(); } - return result; -} -void SortedData::Unswizzle() { - if (layout.AllConstant() || !swizzled) { - return; - } - for (idx_t i = 0; i < data_blocks.size(); i++) { - auto &data_block = data_blocks[i]; - auto &heap_block = heap_blocks[i]; - auto data_handle_p = buffer_manager.Pin(data_block.block); - auto heap_handle_p = buffer_manager.Pin(heap_block.block); - RowOperations::UnswizzlePointers(layout, data_handle_p->Ptr(), heap_handle_p->Ptr(), data_block.count); - state.heap_blocks.push_back(move(heap_block)); - state.pinned_blocks.push_back(move(heap_handle_p)); - } - heap_blocks.clear(); -} +private: + unique_ptr CreateTree(const LogicalOperator &op); + unique_ptr CreateTree(const PhysicalOperator &op); + unique_ptr CreateTree(const QueryProfiler::TreeNode &op); + unique_ptr CreateTree(const Pipeline &op); -SortedBlock::SortedBlock(BufferManager &buffer_manager, GlobalSortState &state) - : buffer_manager(buffer_manager), state(state), sort_layout(state.sort_layout), - payload_layout(state.payload_layout) { - blob_sorting_data = make_unique(SortedDataType::BLOB, sort_layout.blob_layout, buffer_manager, state); - payload_data = make_unique(SortedDataType::PAYLOAD, payload_layout, buffer_manager, state); -} + string ExtraInfoSeparator(); + unique_ptr CreateRenderNode(string name, string extra_info); + unique_ptr CreateNode(const LogicalOperator &op); + unique_ptr CreateNode(const PhysicalOperator &op); + unique_ptr CreateNode(const QueryProfiler::TreeNode &op); + unique_ptr CreateNode(const PipelineRenderNode &op); -idx_t SortedBlock::Count() const { - idx_t count = std::accumulate(radix_sorting_data.begin(), radix_sorting_data.end(), 0, - [](idx_t a, const RowDataBlock &b) { return a + b.count; }); - if (!sort_layout.all_constant) { - D_ASSERT(count == blob_sorting_data->Count()); - } - D_ASSERT(count == payload_data->Count()); - return count; -} +private: + //! The configuration used for rendering + TreeRendererConfig config; -void SortedBlock::InitializeWrite() { - CreateBlock(); - if (!sort_layout.all_constant) { - blob_sorting_data->CreateBlock(); - } - payload_data->CreateBlock(); -} +private: + void RenderTopLayer(RenderTree &root, std::ostream &ss, idx_t y); + void RenderBoxContent(RenderTree &root, std::ostream &ss, idx_t y); + void RenderBottomLayer(RenderTree &root, std::ostream &ss, idx_t y); -void SortedBlock::CreateBlock() { - auto capacity = MaxValue(((idx_t)Storage::BLOCK_SIZE + sort_layout.entry_size - 1) / sort_layout.entry_size, - state.block_capacity); - radix_sorting_data.emplace_back(buffer_manager, capacity, sort_layout.entry_size); -} + bool CanSplitOnThisChar(char l); + bool IsPadding(char l); + string RemovePadding(string l); + void SplitUpExtraInfo(const string &extra_info, vector &result); + void SplitStringBuffer(const string &source, vector &result); -void SortedBlock::AppendSortedBlocks(vector> &sorted_blocks) { - D_ASSERT(Count() == 0); - for (auto &sb : sorted_blocks) { - for (auto &radix_block : sb->radix_sorting_data) { - radix_sorting_data.push_back(move(radix_block)); - } - if (!sort_layout.all_constant) { - for (auto &blob_block : sb->blob_sorting_data->data_blocks) { - blob_sorting_data->data_blocks.push_back(move(blob_block)); - } - for (auto &heap_block : sb->blob_sorting_data->heap_blocks) { - blob_sorting_data->heap_blocks.push_back(move(heap_block)); - } - } - for (auto &payload_data_block : sb->payload_data->data_blocks) { - payload_data->data_blocks.push_back(move(payload_data_block)); - } - if (!payload_data->layout.AllConstant()) { - for (auto &payload_heap_block : sb->payload_data->heap_blocks) { - payload_data->heap_blocks.push_back(move(payload_heap_block)); - } - } - } -} + template + idx_t CreateRenderTreeRecursive(RenderTree &result, const T &op, idx_t x, idx_t y); -void SortedBlock::GlobalToLocalIndex(const idx_t &global_idx, idx_t &local_block_index, idx_t &local_entry_index) { - if (global_idx == Count()) { - local_block_index = radix_sorting_data.size() - 1; - local_entry_index = radix_sorting_data.back().count; - return; - } - D_ASSERT(global_idx < Count()); - local_entry_index = global_idx; - for (local_block_index = 0; local_block_index < radix_sorting_data.size(); local_block_index++) { - const idx_t &block_count = radix_sorting_data[local_block_index].count; - if (local_entry_index >= block_count) { - local_entry_index -= block_count; - } else { - break; - } - } - D_ASSERT(local_entry_index < radix_sorting_data[local_block_index].count); -} + template + unique_ptr CreateRenderTree(const T &op); + string ExtractExpressionsRecursive(ExpressionInfo &states); +}; -unique_ptr SortedBlock::CreateSlice(const idx_t start, const idx_t end, idx_t &entry_idx) { - // Identify blocks/entry indices of this slice - idx_t start_block_index; - idx_t start_entry_index; - GlobalToLocalIndex(start, start_block_index, start_entry_index); - idx_t end_block_index; - idx_t end_entry_index; - GlobalToLocalIndex(end, end_block_index, end_entry_index); - // Add the corresponding blocks to the result - auto result = make_unique(buffer_manager, state); - for (idx_t i = start_block_index; i <= end_block_index; i++) { - result->radix_sorting_data.push_back(radix_sorting_data[i]); - } - // Reset all blocks that come before block with idx = start_block_idx (slice holds new reference) - for (idx_t i = 0; i < start_block_index; i++) { - radix_sorting_data[i].block = nullptr; - } - // Use start and end entry indices to set the boundaries - entry_idx = start_entry_index; - D_ASSERT(end_entry_index <= result->radix_sorting_data.back().count); - result->radix_sorting_data.back().count = end_entry_index; - // Same for the var size sorting data - if (!sort_layout.all_constant) { - result->blob_sorting_data = blob_sorting_data->CreateSlice(start_block_index, end_block_index, end_entry_index); - } - // And the payload data - result->payload_data = payload_data->CreateSlice(start_block_index, end_block_index, end_entry_index); - return result; -} +} // namespace duckdb -idx_t SortedBlock::HeapSize() const { - idx_t result = 0; - if (!sort_layout.all_constant) { - for (auto &block : blob_sorting_data->heap_blocks) { - result += block.capacity; - } - } - if (!payload_layout.AllConstant()) { - for (auto &block : payload_data->heap_blocks) { - result += block.capacity; - } - } - return result; -} -idx_t SortedBlock::SizeInBytes() const { - idx_t bytes = 0; - for (idx_t i = 0; i < radix_sorting_data.size(); i++) { - bytes += radix_sorting_data[i].capacity * sort_layout.entry_size; - if (!sort_layout.all_constant) { - bytes += blob_sorting_data->data_blocks[i].capacity * sort_layout.blob_layout.GetRowWidth(); - bytes += blob_sorting_data->heap_blocks[i].capacity; - } - bytes += payload_data->data_blocks[i].capacity * payload_layout.GetRowWidth(); - if (!payload_layout.AllConstant()) { - bytes += payload_data->heap_blocks[i].capacity; - } - } - return bytes; -} -SBScanState::SBScanState(BufferManager &buffer_manager, GlobalSortState &state) - : buffer_manager(buffer_manager), sort_layout(state.sort_layout), state(state), block_idx(0), entry_idx(0) { -} -void SBScanState::PinRadix(idx_t block_idx_to) { - auto &radix_sorting_data = sb->radix_sorting_data; - D_ASSERT(block_idx_to < radix_sorting_data.size()); - auto &block = radix_sorting_data[block_idx_to]; - if (!radix_handle || radix_handle->handle->BlockId() != block.block->BlockId()) { - radix_handle = buffer_manager.Pin(block.block); - } -} -void SBScanState::PinData(SortedData &sd) { - D_ASSERT(block_idx < sd.data_blocks.size()); - auto &data_handle = sd.type == SortedDataType::BLOB ? blob_sorting_data_handle : payload_data_handle; - auto &heap_handle = sd.type == SortedDataType::BLOB ? blob_sorting_heap_handle : payload_heap_handle; - auto &data_block = sd.data_blocks[block_idx]; - if (!data_handle || data_handle->handle->BlockId() != data_block.block->BlockId()) { - data_handle = buffer_manager.Pin(data_block.block); - } - if (sd.layout.AllConstant() || !state.external) { - return; - } - auto &heap_block = sd.heap_blocks[block_idx]; - if (!heap_handle || heap_handle->handle->BlockId() != heap_block.block->BlockId()) { - heap_handle = buffer_manager.Pin(heap_block.block); - } -} +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/operator/join/physical_delim_join.hpp +// +// +//===----------------------------------------------------------------------===// -data_ptr_t SBScanState::RadixPtr() const { - return radix_handle->Ptr() + entry_idx * sort_layout.entry_size; -} -data_ptr_t SBScanState::DataPtr(SortedData &sd) const { - auto &data_handle = sd.type == SortedDataType::BLOB ? *blob_sorting_data_handle : *payload_data_handle; - D_ASSERT(sd.data_blocks[block_idx].block->Readers() != 0 && - data_handle.handle->BlockId() == sd.data_blocks[block_idx].block->BlockId()); - return data_handle.Ptr() + entry_idx * sd.layout.GetRowWidth(); -} -data_ptr_t SBScanState::HeapPtr(SortedData &sd) const { - return BaseHeapPtr(sd) + Load(DataPtr(sd) + sd.layout.GetHeapPointerOffset()); -} -data_ptr_t SBScanState::BaseHeapPtr(SortedData &sd) const { - auto &heap_handle = sd.type == SortedDataType::BLOB ? *blob_sorting_heap_handle : *payload_heap_handle; - D_ASSERT(!sd.layout.AllConstant() && state.external); - D_ASSERT(sd.heap_blocks[block_idx].block->Readers() != 0 && - heap_handle.handle->BlockId() == sd.heap_blocks[block_idx].block->BlockId()); - return heap_handle.Ptr(); -} -idx_t SBScanState::Remaining() const { - const auto &blocks = sb->radix_sorting_data; - idx_t remaining = 0; - if (block_idx < blocks.size()) { - remaining += blocks[block_idx].count - entry_idx; - for (idx_t i = block_idx + 1; i < blocks.size(); i++) { - remaining += blocks[i].count; - } - } - return remaining; -} -void SBScanState::SetIndices(idx_t block_idx_to, idx_t entry_idx_to) { - block_idx = block_idx_to; - entry_idx = entry_idx_to; -} +namespace duckdb { +class PhysicalHashAggregate; -PayloadScanner::PayloadScanner(SortedData &sorted_data, GlobalSortState &global_sort_state, bool flush_p) - : sorted_data(sorted_data), read_state(global_sort_state.buffer_manager, global_sort_state), - total_count(sorted_data.Count()), global_sort_state(global_sort_state), total_scanned(0), flush(flush_p) { -} +//! PhysicalDelimJoin represents a join where the LHS will be duplicate eliminated and pushed into a +//! PhysicalColumnDataScan in the RHS. +class PhysicalDelimJoin : public PhysicalOperator { +public: + PhysicalDelimJoin(vector types, unique_ptr original_join, + vector delim_scans, idx_t estimated_cardinality); -PayloadScanner::PayloadScanner(GlobalSortState &global_sort_state, bool flush_p) - : PayloadScanner(*global_sort_state.sorted_blocks[0]->payload_data, global_sort_state, flush_p) { -} + unique_ptr join; + unique_ptr distinct; + vector delim_scans; -PayloadScanner::PayloadScanner(GlobalSortState &global_sort_state, idx_t block_idx) - : sorted_data(*global_sort_state.sorted_blocks[0]->payload_data), - read_state(global_sort_state.buffer_manager, global_sort_state), - total_count(sorted_data.data_blocks[block_idx].count), global_sort_state(global_sort_state), total_scanned(0), - flush(false) { - read_state.SetIndices(block_idx, 0); -} +public: + vector GetChildren() const override; -void PayloadScanner::Scan(DataChunk &chunk) { - auto count = MinValue((idx_t)STANDARD_VECTOR_SIZE, total_count - total_scanned); - if (count == 0) { - chunk.SetCardinality(count); - return; - } - // Eagerly delete references to blocks that we've passed - if (flush) { - for (idx_t i = 0; i < read_state.block_idx; i++) { - sorted_data.data_blocks[i].block = nullptr; - } - } - const idx_t &row_width = sorted_data.layout.GetRowWidth(); - // Set up a batch of pointers to scan data from - idx_t scanned = 0; - auto data_pointers = FlatVector::GetData(addresses); - while (scanned < count) { - read_state.PinData(sorted_data); - auto &data_block = sorted_data.data_blocks[read_state.block_idx]; - idx_t next = MinValue(data_block.count - read_state.entry_idx, count - scanned); - const data_ptr_t data_ptr = read_state.payload_data_handle->Ptr() + read_state.entry_idx * row_width; - // Set up the next pointers - data_ptr_t row_ptr = data_ptr; - for (idx_t i = 0; i < next; i++) { - data_pointers[scanned + i] = row_ptr; - row_ptr += row_width; - } - // Unswizzle the offsets back to pointers (if needed) - if (!sorted_data.layout.AllConstant() && global_sort_state.external) { - RowOperations::UnswizzlePointers(sorted_data.layout, data_ptr, read_state.payload_heap_handle->Ptr(), next); - } - // Update state indices - read_state.entry_idx += next; - if (read_state.entry_idx == data_block.count) { - read_state.block_idx++; - read_state.entry_idx = 0; - } - scanned += next; +public: + unique_ptr GetGlobalSinkState(ClientContext &context) const override; + unique_ptr GetLocalSinkState(ExecutionContext &context) const override; + SinkResultType Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, + DataChunk &input) const override; + void Combine(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate) const override; + SinkFinalizeType Finalize(Pipeline &pipeline, Event &event, ClientContext &context, + GlobalSinkState &gstate) const override; + + bool IsSink() const override { + return true; } - D_ASSERT(scanned == count); - // Deserialize the payload data - for (idx_t col_idx = 0; col_idx < sorted_data.layout.ColumnCount(); col_idx++) { - const auto col_offset = sorted_data.layout.GetOffsets()[col_idx]; - RowOperations::Gather(addresses, *FlatVector::IncrementalSelectionVector(), chunk.data[col_idx], - *FlatVector::IncrementalSelectionVector(), count, col_offset, col_idx); + bool ParallelSink() const override { + return true; } - chunk.SetCardinality(count); - chunk.Verify(); - total_scanned += scanned; -} + + string ParamsToString() const override; + +public: + void BuildPipelines(Executor &executor, Pipeline ¤t, PipelineBuildState &state) override; +}; } // namespace duckdb - - - - - -#include -#include -#include -#include -#include -#include -#include - -namespace duckdb { - -bool StringUtil::Contains(const string &haystack, const string &needle) { - return (haystack.find(needle) != string::npos); -} - -void StringUtil::LTrim(string &str) { - auto it = str.begin(); - while (CharacterIsSpace(*it)) { - it++; - } - str.erase(str.begin(), it); -} - -// Remove trailing ' ', '\f', '\n', '\r', '\t', '\v' -void StringUtil::RTrim(string &str) { - str.erase(find_if(str.rbegin(), str.rend(), [](int ch) { return ch > 0 && !CharacterIsSpace(ch); }).base(), - str.end()); -} - -void StringUtil::Trim(string &str) { - StringUtil::LTrim(str); - StringUtil::RTrim(str); -} - -bool StringUtil::StartsWith(string str, string prefix) { - if (prefix.size() > str.size()) { - return false; - } - return equal(prefix.begin(), prefix.end(), str.begin()); -} - -bool StringUtil::EndsWith(const string &str, const string &suffix) { - if (suffix.size() > str.size()) { - return false; - } - return equal(suffix.rbegin(), suffix.rend(), str.rbegin()); -} - -string StringUtil::Repeat(const string &str, idx_t n) { - std::ostringstream os; - for (idx_t i = 0; i < n; i++) { - os << str; - } - return (os.str()); -} - -vector StringUtil::Split(const string &str, char delimiter) { - std::stringstream ss(str); - vector lines; - string temp; - while (getline(ss, temp, delimiter)) { - lines.push_back(temp); - } - return (lines); -} - -namespace string_util_internal { - -inline void SkipSpaces(const string &str, idx_t &index) { - while (index < str.size() && std::isspace(str[index])) { - index++; - } -} - -inline void ConsumeLetter(const string &str, idx_t &index, char expected) { - if (index >= str.size() || str[index] != expected) { - throw ParserException("Invalid quoted list: %s", str); - } - - index++; -} - -template -inline void TakeWhile(const string &str, idx_t &index, const F &cond, string &taker) { - while (index < str.size() && cond(str[index])) { - taker.push_back(str[index]); - index++; - } -} - -inline string TakePossiblyQuotedItem(const string &str, idx_t &index, char delimiter, char quote) { - string entry; - - if (str[index] == quote) { - index++; - TakeWhile( - str, index, [quote](char c) { return c != quote; }, entry); - ConsumeLetter(str, index, quote); - } else { - TakeWhile( - str, index, [delimiter, quote](char c) { return c != delimiter && c != quote && !std::isspace(c); }, entry); - } - - return entry; -} - -} // namespace string_util_internal - -vector StringUtil::SplitWithQuote(const string &str, char delimiter, char quote) { - vector entries; - idx_t i = 0; - - string_util_internal::SkipSpaces(str, i); - while (i < str.size()) { - if (!entries.empty()) { - string_util_internal::ConsumeLetter(str, i, delimiter); - } - - entries.emplace_back(string_util_internal::TakePossiblyQuotedItem(str, i, delimiter, quote)); - string_util_internal::SkipSpaces(str, i); - } - - return entries; -} - -string StringUtil::Join(const vector &input, const string &separator) { - return StringUtil::Join(input, input.size(), separator, [](const string &s) { return s; }); -} - -string StringUtil::BytesToHumanReadableString(idx_t bytes) { - string db_size; - auto kilobytes = bytes / 1000; - auto megabytes = kilobytes / 1000; - kilobytes -= megabytes * 1000; - auto gigabytes = megabytes / 1000; - megabytes -= gigabytes * 1000; - auto terabytes = gigabytes / 1000; - gigabytes -= terabytes * 1000; - if (terabytes > 0) { - return to_string(terabytes) + "." + to_string(gigabytes / 100) + "TB"; - } else if (gigabytes > 0) { - return to_string(gigabytes) + "." + to_string(megabytes / 100) + "GB"; - } else if (megabytes > 0) { - return to_string(megabytes) + "." + to_string(kilobytes / 100) + "MB"; - } else if (kilobytes > 0) { - return to_string(kilobytes) + "KB"; - } else { - return to_string(bytes) + " bytes"; - } -} - -string StringUtil::Upper(const string &str) { - string copy(str); - transform(copy.begin(), copy.end(), copy.begin(), [](unsigned char c) { return std::toupper(c); }); - return (copy); -} - -string StringUtil::Lower(const string &str) { - string copy(str); - transform(copy.begin(), copy.end(), copy.begin(), [](unsigned char c) { return std::tolower(c); }); - return (copy); -} - -vector StringUtil::Split(const string &input, const string &split) { - vector splits; - - idx_t last = 0; - idx_t input_len = input.size(); - idx_t split_len = split.size(); - while (last <= input_len) { - idx_t next = input.find(split, last); - if (next == string::npos) { - next = input_len; - } - - // Push the substring [last, next) on to splits - string substr = input.substr(last, next - last); - if (substr.empty() == false) { - splits.push_back(substr); - } - last = next + split_len; - } - return splits; -} - -string StringUtil::Replace(string source, const string &from, const string &to) { - idx_t start_pos = 0; - while ((start_pos = source.find(from, start_pos)) != string::npos) { - source.replace(start_pos, from.length(), to); - start_pos += to.length(); // In case 'to' contains 'from', like - // replacing 'x' with 'yx' - } - return source; -} - -vector StringUtil::TopNStrings(vector> scores, idx_t n, idx_t threshold) { - if (scores.empty()) { - return vector(); - } - sort(scores.begin(), scores.end(), - [](const pair &a, const pair &b) -> bool { return a.second < b.second; }); - vector result; - result.push_back(scores[0].first); - for (idx_t i = 1; i < MinValue(scores.size(), n); i++) { - if (scores[i].second > threshold) { - break; - } - result.push_back(scores[i].first); - } - return result; -} - -struct LevenshteinArray { - LevenshteinArray(idx_t len1, idx_t len2) : len1(len1) { - dist = unique_ptr(new idx_t[len1 * len2]); - } - - idx_t &Score(idx_t i, idx_t j) { - return dist[GetIndex(i, j)]; - } - -private: - idx_t len1; - unique_ptr dist; - - idx_t GetIndex(idx_t i, idx_t j) { - return j * len1 + i; - } -}; - -// adapted from https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C++ -idx_t StringUtil::LevenshteinDistance(const string &s1_p, const string &s2_p) { - auto s1 = StringUtil::Lower(s1_p); - auto s2 = StringUtil::Lower(s2_p); - idx_t len1 = s1.size(); - idx_t len2 = s2.size(); - if (len1 == 0) { - return len2; - } - if (len2 == 0) { - return len1; - } - LevenshteinArray array(len1 + 1, len2 + 1); - array.Score(0, 0) = 0; - for (idx_t i = 0; i <= len1; i++) { - array.Score(i, 0) = i; - } - for (idx_t j = 0; j <= len2; j++) { - array.Score(0, j) = j; - } - for (idx_t i = 1; i <= len1; i++) { - for (idx_t j = 1; j <= len2; j++) { - // d[i][j] = std::min({ d[i - 1][j] + 1, - // d[i][j - 1] + 1, - // d[i - 1][j - 1] + (s1[i - 1] == s2[j - 1] ? 0 : 1) }); - int equal = s1[i - 1] == s2[j - 1] ? 0 : 1; - idx_t adjacent_score1 = array.Score(i - 1, j) + 1; - idx_t adjacent_score2 = array.Score(i, j - 1) + 1; - idx_t adjacent_score3 = array.Score(i - 1, j - 1) + equal; - - idx_t t = MinValue(adjacent_score1, adjacent_score2); - array.Score(i, j) = MinValue(t, adjacent_score3); - } - } - return array.Score(len1, len2); -} - -vector StringUtil::TopNLevenshtein(const vector &strings, const string &target, idx_t n, - idx_t threshold) { - vector> scores; - scores.reserve(strings.size()); - for (auto &str : strings) { - scores.emplace_back(str, LevenshteinDistance(str, target)); - } - return TopNStrings(scores, n, threshold); -} - -string StringUtil::CandidatesMessage(const vector &candidates, const string &candidate) { - string result_str; - if (!candidates.empty()) { - result_str = "\n" + candidate + ": "; - for (idx_t i = 0; i < candidates.size(); i++) { - if (i > 0) { - result_str += ", "; - } - result_str += "\"" + candidates[i] + "\""; - } - } - return result_str; -} - -string StringUtil::CandidatesErrorMessage(const vector &strings, const string &target, - const string &message_prefix, idx_t n) { - auto closest_strings = StringUtil::TopNLevenshtein(strings, target, n); - return StringUtil::CandidatesMessage(closest_strings, message_prefix); -} - -} // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/tree_renderer.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/main/query_profiler.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - - - - - - -#include - - - -namespace duckdb { -class ClientContext; -class ExpressionExecutor; -class PhysicalOperator; -class SQLStatement; - -//! The ExpressionInfo keeps information related to an expression -struct ExpressionInfo { - explicit ExpressionInfo() : hasfunction(false) { - } - // A vector of children - vector> children; - // Extract ExpressionInformation from a given expression state - void ExtractExpressionsRecursive(unique_ptr &state); - - //! Whether or not expression has function - bool hasfunction; - //! The function Name - string function_name; - //! The function time - uint64_t function_time = 0; - //! Count the number of ALL tuples - uint64_t tuples_count = 0; - //! Count the number of tuples sampled - uint64_t sample_tuples_count = 0; -}; - -//! The ExpressionRootInfo keeps information related to the root of an expression tree -struct ExpressionRootInfo { - ExpressionRootInfo(ExpressionExecutorState &executor, string name); - - //! Count the number of time the executor called - uint64_t total_count = 0; - //! Count the number of time the executor called since last sampling - uint64_t current_count = 0; - //! Count the number of samples - uint64_t sample_count = 0; - //! Count the number of tuples in all samples - uint64_t sample_tuples_count = 0; - //! Count the number of tuples processed by this executor - uint64_t tuples_count = 0; - //! A vector which contain the pointer to root of each expression tree - unique_ptr root; - //! Name - string name; - //! Elapsed time - double time; - //! Extra Info - string extra_info; -}; - -struct ExpressionExecutorInfo { - explicit ExpressionExecutorInfo() {}; - explicit ExpressionExecutorInfo(ExpressionExecutor &executor, const string &name, int id); - - //! A vector which contain the pointer to all ExpressionRootInfo - vector> roots; - //! Id, it will be used as index for executors_info vector - int id; -}; - -struct OperatorInformation { - explicit OperatorInformation(double time_ = 0, idx_t elements_ = 0) : time(time_), elements(elements_) { - } - - double time = 0; - idx_t elements = 0; - string name; - //! A vector of Expression Executor Info - vector> executors_info; -}; - -//! The OperatorProfiler measures timings of individual operators -class OperatorProfiler { - friend class QueryProfiler; - -public: - DUCKDB_API explicit OperatorProfiler(bool enabled); - - DUCKDB_API void StartOperator(const PhysicalOperator *phys_op); - DUCKDB_API void EndOperator(DataChunk *chunk); - DUCKDB_API void Flush(const PhysicalOperator *phys_op, ExpressionExecutor *expression_executor, const string &name, - int id); - - ~OperatorProfiler() { - } - -private: - void AddTiming(const PhysicalOperator *op, double time, idx_t elements); - - //! Whether or not the profiler is enabled - bool enabled; - //! The timer used to time the execution time of the individual Physical Operators - Profiler op; - //! The stack of Physical Operators that are currently active - const PhysicalOperator *active_operator; - //! A mapping of physical operators to recorded timings - unordered_map timings; -}; - -//! The QueryProfiler can be used to measure timings of queries -class QueryProfiler { -public: - DUCKDB_API QueryProfiler(ClientContext &context); - -public: - struct TreeNode { - PhysicalOperatorType type; - string name; - string extra_info; - OperatorInformation info; - vector> children; - idx_t depth = 0; - }; - - // Propagate save_location, enabled, detailed_enabled and automatic_print_format. - void Propagate(QueryProfiler &qp); - - using TreeMap = unordered_map; - -private: - unique_ptr CreateTree(PhysicalOperator *root, idx_t depth = 0); - void Render(const TreeNode &node, std::ostream &str) const; - -public: - DUCKDB_API bool IsEnabled() const; - DUCKDB_API bool IsDetailedEnabled() const; - DUCKDB_API ProfilerPrintFormat GetPrintFormat() const; - DUCKDB_API string GetSaveLocation() const; - - DUCKDB_API static QueryProfiler &Get(ClientContext &context); - - DUCKDB_API void StartQuery(string query, bool is_explain_analyze = false); - DUCKDB_API void EndQuery(); - - DUCKDB_API void StartExplainAnalyze(); - - //! Adds the timings gathered by an OperatorProfiler to this query profiler - DUCKDB_API void Flush(OperatorProfiler &profiler); - - DUCKDB_API void StartPhase(string phase); - DUCKDB_API void EndPhase(); - - DUCKDB_API void Initialize(PhysicalOperator *root); - - DUCKDB_API string ToString(bool print_optimizer_output = false) const; - DUCKDB_API void ToStream(std::ostream &str, bool print_optimizer_output = false) const; - DUCKDB_API void Print(); - - DUCKDB_API string ToJSON() const; - DUCKDB_API void WriteToFile(const char *path, string &info) const; - - idx_t OperatorSize() { - return tree_map.size(); - } - - void Finalize(TreeNode &node); - -private: - ClientContext &context; - - //! Whether or not the query profiler is running - bool running; - //! The lock used for flushing information from a thread into the global query profiler - mutex flush_lock; - - //! Whether or not the query requires profiling - bool query_requires_profiling; - - //! The root of the query tree - unique_ptr root; - //! The query string - string query; - //! The timer used to time the execution time of the entire query - Profiler main_query; - //! A map of a Physical Operator pointer to a tree node - TreeMap tree_map; - //! Whether or not we are running as part of a explain_analyze query - bool is_explain_analyze; - -public: - const TreeMap &GetTreeMap() const { - return tree_map; - } - -private: - //! The timer used to time the individual phases of the planning process - Profiler phase_profiler; - //! A mapping of the phase names to the timings - using PhaseTimingStorage = unordered_map; - PhaseTimingStorage phase_timings; - using PhaseTimingItem = PhaseTimingStorage::value_type; - //! The stack of currently active phases - vector phase_stack; - -private: - vector GetOrderedPhaseTimings() const; - - //! Check whether or not an operator type requires query profiling. If none of the ops in a query require profiling - //! no profiling information is output. - bool OperatorRequiresProfiling(PhysicalOperatorType op_type); -}; - -//! The QueryProfilerHistory can be used to access the profiler of previous queries -class QueryProfilerHistory { -private: - //! Previous Query profilers - deque>> prev_profilers; - //! Previous Query profilers size - uint64_t prev_profilers_size = 20; - -public: - deque>> &GetPrevProfilers() { - return prev_profilers; - } - QueryProfilerHistory() { - } - - void SetPrevProfilersSize(uint64_t prevProfilersSize) { - prev_profilers_size = prevProfilersSize; - } - uint64_t GetPrevProfilersSize() const { - return prev_profilers_size; - } - -public: - void SetProfilerHistorySize(uint64_t size) { - this->prev_profilers_size = size; - } -}; -} // namespace duckdb - - -namespace duckdb { -class LogicalOperator; -class PhysicalOperator; -class Pipeline; -struct PipelineRenderNode; - -struct RenderTreeNode { - string name; - string extra_text; -}; - -struct RenderTree { - RenderTree(idx_t width, idx_t height); - - unique_ptr[]> nodes; - idx_t width; - idx_t height; - -public: - RenderTreeNode *GetNode(idx_t x, idx_t y); - void SetNode(idx_t x, idx_t y, unique_ptr node); - bool HasNode(idx_t x, idx_t y); - - idx_t GetPosition(idx_t x, idx_t y); -}; - -struct TreeRendererConfig { - void enable_detailed() { - MAX_EXTRA_LINES = 1000; - detailed = true; - } - - void enable_standard() { - MAX_EXTRA_LINES = 30; - detailed = false; - } - - idx_t MAXIMUM_RENDER_WIDTH = 240; - idx_t NODE_RENDER_WIDTH = 29; - idx_t MINIMUM_RENDER_WIDTH = 15; - idx_t MAX_EXTRA_LINES = 30; - bool detailed = false; - -#ifndef DUCKDB_ASCII_TREE_RENDERER - const char *LTCORNER = "\342\224\214"; // "┌"; - const char *RTCORNER = "\342\224\220"; // "┐"; - const char *LDCORNER = "\342\224\224"; // "└"; - const char *RDCORNER = "\342\224\230"; // "┘"; - - const char *MIDDLE = "\342\224\274"; // "┼"; - const char *TMIDDLE = "\342\224\254"; // "┬"; - const char *LMIDDLE = "\342\224\234"; // "├"; - const char *RMIDDLE = "\342\224\244"; // "┤"; - const char *DMIDDLE = "\342\224\264"; // "┴"; - - const char *VERTICAL = "\342\224\202"; // "│"; - const char *HORIZONTAL = "\342\224\200"; // "─"; -#else - // ASCII version - const char *LTCORNER = "<"; - const char *RTCORNER = ">"; - const char *LDCORNER = "<"; - const char *RDCORNER = ">"; - - const char *MIDDLE = "+"; - const char *TMIDDLE = "+"; - const char *LMIDDLE = "+"; - const char *RMIDDLE = "+"; - const char *DMIDDLE = "+"; - - const char *VERTICAL = "|"; - const char *HORIZONTAL = "-"; -#endif -}; - -class TreeRenderer { -public: - explicit TreeRenderer(TreeRendererConfig config_p = TreeRendererConfig()) : config(move(config_p)) { - } - - string ToString(const LogicalOperator &op); - string ToString(const PhysicalOperator &op); - string ToString(const QueryProfiler::TreeNode &op); - string ToString(const Pipeline &op); - - void Render(const LogicalOperator &op, std::ostream &ss); - void Render(const PhysicalOperator &op, std::ostream &ss); - void Render(const QueryProfiler::TreeNode &op, std::ostream &ss); - void Render(const Pipeline &op, std::ostream &ss); - - void ToStream(RenderTree &root, std::ostream &ss); - - void EnableDetailed() { - config.enable_detailed(); - } - void EnableStandard() { - config.enable_standard(); - } - -private: - unique_ptr CreateTree(const LogicalOperator &op); - unique_ptr CreateTree(const PhysicalOperator &op); - unique_ptr CreateTree(const QueryProfiler::TreeNode &op); - unique_ptr CreateTree(const Pipeline &op); - - string ExtraInfoSeparator(); - unique_ptr CreateRenderNode(string name, string extra_info); - unique_ptr CreateNode(const LogicalOperator &op); - unique_ptr CreateNode(const PhysicalOperator &op); - unique_ptr CreateNode(const QueryProfiler::TreeNode &op); - unique_ptr CreateNode(const PipelineRenderNode &op); - -private: - //! The configuration used for rendering - TreeRendererConfig config; - -private: - void RenderTopLayer(RenderTree &root, std::ostream &ss, idx_t y); - void RenderBoxContent(RenderTree &root, std::ostream &ss, idx_t y); - void RenderBottomLayer(RenderTree &root, std::ostream &ss, idx_t y); - - bool CanSplitOnThisChar(char l); - bool IsPadding(char l); - string RemovePadding(string l); - void SplitUpExtraInfo(const string &extra_info, vector &result); - void SplitStringBuffer(const string &source, vector &result); - - template - idx_t CreateRenderTreeRecursive(RenderTree &result, const T &op, idx_t x, idx_t y); - - template - unique_ptr CreateRenderTree(const T &op); - string ExtractExpressionsRecursive(ExpressionInfo &states); -}; - -} // namespace duckdb - - - - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/operator/join/physical_delim_join.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { -class PhysicalHashAggregate; - -//! PhysicalDelimJoin represents a join where the LHS will be duplicate eliminated and pushed into a -//! PhysicalChunkCollectionScan in the RHS. -class PhysicalDelimJoin : public PhysicalOperator { -public: - PhysicalDelimJoin(vector types, unique_ptr original_join, - vector delim_scans, idx_t estimated_cardinality); - - unique_ptr join; - unique_ptr distinct; - vector delim_scans; - -public: - vector GetChildren() const override; - -public: - unique_ptr GetGlobalSinkState(ClientContext &context) const override; - unique_ptr GetLocalSinkState(ExecutionContext &context) const override; - SinkResultType Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, - DataChunk &input) const override; - void Combine(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate) const override; - SinkFinalizeType Finalize(Pipeline &pipeline, Event &event, ClientContext &context, - GlobalSinkState &gstate) const override; - - bool IsSink() const override { - return true; - } - bool ParallelSink() const override { - return true; - } - - string ParamsToString() const override; - -public: - void BuildPipelines(Executor &executor, Pipeline ¤t, PipelineBuildState &state) override; -}; - -} // namespace duckdb - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/operator/aggregate/physical_hash_aggregate.hpp -// -// -//===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/operator/aggregate/physical_hash_aggregate.hpp +// +// +//===----------------------------------------------------------------------===// @@ -40352,31 +43611,39 @@ class GroupByNode { + namespace duckdb { class BufferManager; class BaseAggregateHashTable { public: - BaseAggregateHashTable(BufferManager &buffer_manager, vector payload_types); + BaseAggregateHashTable(Allocator &allocator, const vector &aggregates, + BufferManager &buffer_manager, vector payload_types); virtual ~BaseAggregateHashTable() { } protected: + Allocator &allocator; BufferManager &buffer_manager; //! A helper for managing offsets into the data buffers RowLayout layout; //! The types of the payload columns stored in the hashtable vector payload_types; + //! Intermediate structures and data for aggregate filters + AggregateFilterDataSet filter_set; }; } // namespace duckdb + namespace duckdb { class BlockHandle; class BufferHandle; class RowDataCollection; +struct FlushMoveState; + //! GroupedAggregateHashTable is a linear probing HT that is used for computing //! aggregates /*! @@ -40418,15 +43685,24 @@ enum HtEntryType { HT_WIDTH_32, HT_WIDTH_64 }; class GroupedAggregateHashTable : public BaseAggregateHashTable { public: - GroupedAggregateHashTable(BufferManager &buffer_manager, vector group_types, + //! The hash table load factor, when a resize is triggered + constexpr static float LOAD_FACTOR = 1.5; + constexpr static uint8_t HASH_WIDTH = sizeof(hash_t); + +public: + GroupedAggregateHashTable(Allocator &allocator, BufferManager &buffer_manager, vector group_types, vector payload_types, const vector &aggregates, HtEntryType entry_type = HtEntryType::HT_WIDTH_64); - GroupedAggregateHashTable(BufferManager &buffer_manager, vector group_types, + GroupedAggregateHashTable(Allocator &allocator, BufferManager &buffer_manager, vector group_types, vector payload_types, vector aggregates, HtEntryType entry_type = HtEntryType::HT_WIDTH_64); - GroupedAggregateHashTable(BufferManager &buffer_manager, vector group_types); + GroupedAggregateHashTable(Allocator &allocator, BufferManager &buffer_manager, vector group_types); ~GroupedAggregateHashTable() override; + //! The stringheap of the AggregateHashTable + unique_ptr string_heap; + +public: //! Add the given data to the HT, computing the aggregates grouped by the //! data in the group chunk. When resize = true, aggregates will not be //! computed but instead just assigned. @@ -40462,13 +43738,6 @@ class GroupedAggregateHashTable : public BaseAggregateHashTable { void Finalize(); - //! The stringheap of the AggregateHashTable - unique_ptr string_heap; - - //! The hash table load factor, when a resize is triggered - constexpr static float LOAD_FACTOR = 1.5; - constexpr static uint8_t HASH_WIDTH = sizeof(hash_t); - private: HtEntryType entry_type; @@ -40482,11 +43751,11 @@ class GroupedAggregateHashTable : public BaseAggregateHashTable { //! The amount of entries stored in the HT currently idx_t entries; //! The data of the HT - vector> payload_hds; + vector payload_hds; vector payload_hds_ptrs; //! The hashes of the HT - unique_ptr hashes_hdl; + BufferHandle hashes_hdl; data_ptr_t hashes_hdl_ptr; data_ptr_t hashes_end_ptr; // of hashes idx_t hash_offset; // Offset into the layout of the hash column @@ -40518,7 +43787,7 @@ class GroupedAggregateHashTable : public BaseAggregateHashTable { void Verify(); - void FlushMove(Vector &source_addresses, Vector &source_hashes, idx_t count); + void FlushMove(FlushMoveState &state, Vector &source_addresses, Vector &source_hashes, idx_t count); void NewBlock(); template @@ -40539,18 +43808,22 @@ class GroupedAggregateHashTable : public BaseAggregateHashTable { namespace duckdb { struct RadixPartitionInfo { - explicit RadixPartitionInfo(idx_t _n_partitions_upper_bound); + explicit RadixPartitionInfo(idx_t n_partitions_upper_bound); const idx_t n_partitions; const idx_t radix_bits; const hash_t radix_mask; constexpr static idx_t RADIX_SHIFT = 40; + + inline hash_t GetHashPartition(hash_t hash) const { + return (hash & radix_mask) >> RADIX_SHIFT; + } }; -typedef vector> HashTableList; +typedef vector> HashTableList; // NOLINT class PartitionableHashTable { public: - PartitionableHashTable(BufferManager &buffer_manager_p, RadixPartitionInfo &partition_info_p, + PartitionableHashTable(Allocator &allocator, BufferManager &buffer_manager_p, RadixPartitionInfo &partition_info_p, vector group_types_p, vector payload_types_p, vector bindings_p); @@ -40564,6 +43837,7 @@ class PartitionableHashTable { void Finalize(); private: + Allocator &allocator; BufferManager &buffer_manager; vector group_types; vector payload_types; @@ -40586,6 +43860,124 @@ class PartitionableHashTable { +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/operator/aggregate/grouped_aggregate_data.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + +namespace duckdb { + +class GroupedAggregateData { +public: + GroupedAggregateData() { + } + //! The groups + vector> groups; + //! The set of GROUPING functions + vector> grouping_functions; + //! The group types + vector group_types; + + //! The aggregates that have to be computed + vector> aggregates; + //! Whether or not any aggregation is DISTINCT + bool any_distinct = false; + //! The payload types + vector payload_types; + //! The aggregate return types + vector aggregate_return_types; + //! Pointers to the aggregates + vector bindings; + +public: + idx_t GroupCount() const { + return groups.size(); + } + + const vector> &GetGroupingFunctions() const { + return grouping_functions; + } + + void InitializeGroupby(vector> groups, vector> expressions, + vector> grouping_functions) { + InitializeGroupbyGroups(move(groups)); + vector payload_types_filters; + + SetGroupingFunctions(grouping_functions); + + for (auto &expr : expressions) { + D_ASSERT(expr->expression_class == ExpressionClass::BOUND_AGGREGATE); + D_ASSERT(expr->IsAggregate()); + auto &aggr = (BoundAggregateExpression &)*expr; + bindings.push_back(&aggr); + + if (aggr.distinct) { + any_distinct = true; + } + + aggregate_return_types.push_back(aggr.return_type); + for (auto &child : aggr.children) { + payload_types.push_back(child->return_type); + } + if (aggr.filter) { + payload_types_filters.push_back(aggr.filter->return_type); + } + if (!aggr.function.combine) { + throw InternalException("Aggregate function %s is missing a combine method", aggr.function.name); + } + aggregates.push_back(move(expr)); + } + for (const auto &pay_filters : payload_types_filters) { + payload_types.push_back(pay_filters); + } + } + //! Initialize a GroupedAggregateData object for use with distinct aggregates + void InitializeDistinct(const unique_ptr &aggregate) { + auto &aggr = (BoundAggregateExpression &)*aggregate; + D_ASSERT(aggr.distinct); + any_distinct = false; //! This is done to stop the radixHT from enforcing ForceSingleHT + + vector payload_types_filters; + aggregate_return_types.push_back(aggr.return_type); + for (idx_t i = 0; i < aggr.children.size(); i++) { + auto &child = aggr.children[i]; + group_types.push_back(child->return_type); + groups.push_back(child->Copy()); + } + if (!aggr.function.combine) { + throw InternalException("Aggregate function %s is missing a combine method", aggr.function.name); + } + } + +private: + void InitializeGroupbyGroups(vector> groups) { + // Add all the expressions of the group by clause + for (auto &expr : groups) { + group_types.push_back(expr->return_type); + } + this->groups = move(groups); + } + + void SetGroupingFunctions(vector> &functions) { + grouping_functions.reserve(functions.size()); + for (idx_t i = 0; i < functions.size(); i++) { + grouping_functions.push_back(move(functions[i])); + } + } +}; + +} // namespace duckdb + namespace duckdb { class BufferManager; @@ -40596,11 +43988,11 @@ class Task; class RadixPartitionedHashTable { public: - RadixPartitionedHashTable(GroupingSet &grouping_set, const PhysicalHashAggregate &op); + RadixPartitionedHashTable(GroupingSet &grouping_set, const GroupedAggregateData &op); GroupingSet &grouping_set; vector null_groups; - const PhysicalHashAggregate &op; + const GroupedAggregateData &op; vector group_types; //! how many groups can we have in the operator before we switch to radix partitioning @@ -40623,17 +44015,23 @@ class RadixPartitionedHashTable { vector> &tasks) const; //! Source interface - unique_ptr GetGlobalSourceState() const; - void GetData(ExecutionContext &context, DataChunk &chunk, GlobalSinkState &sink_state, - GlobalSourceState &gstate_p) const; + idx_t Size(GlobalSinkState &sink_state) const; + unique_ptr GetGlobalSourceState(ClientContext &context) const; + unique_ptr GetLocalSourceState(ExecutionContext &context) const; + void GetData(ExecutionContext &context, DataChunk &chunk, GlobalSinkState &sink_state, GlobalSourceState &gstate_p, + LocalSourceState &lstate_p) const; static void SetMultiScan(GlobalSinkState &state); bool ForceSingleHT(GlobalSinkState &state) const; + +private: + void SetGroupingValues(); }; } // namespace duckdb + namespace duckdb { class ClientContext; @@ -40653,39 +44051,31 @@ class PhysicalHashAggregate : public PhysicalOperator { vector> grouping_functions, idx_t estimated_cardinality, PhysicalOperatorType type = PhysicalOperatorType::HASH_GROUP_BY); - //! The groups - vector> groups; //! The grouping sets vector grouping_sets; - //! The aggregates that have to be computed - vector> aggregates; - //! The set of GROUPING functions - vector> grouping_functions; - - //! Whether or not any aggregation is DISTINCT - bool any_distinct; - - //! The group types - vector group_types; - //! The payload types - vector payload_types; - //! The aggregate return types - vector aggregate_return_types; + GroupedAggregateData grouped_aggregate_data; //! The radix partitioned hash tables (one per grouping set) vector radix_tables; - //! Pointers to the aggregates - vector bindings; - unordered_map filter_indexes; public: // Source interface unique_ptr GetGlobalSourceState(ClientContext &context) const override; + unique_ptr GetLocalSourceState(ExecutionContext &context, + GlobalSourceState &gstate) const override; void GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, LocalSourceState &lstate) const override; + bool ParallelSource() const override { + return true; + } + + bool IsOrderPreserving() const override { + return false; + } + public: // Sink interface SinkResultType Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, @@ -40719,7 +44109,7 @@ class PhysicalHashAggregate : public PhysicalOperator { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3 // See the end of this file for a list @@ -41294,7 +44684,8 @@ unique_ptr TreeRenderer::CreateTree(const Pipeline &op) { return CreateRenderTree(*node); } -} // namespace duckdb//===----------------------------------------------------------------------===// +} // namespace duckdb +//===----------------------------------------------------------------------===// // DuckDB // // duckdb/common/types/batched_chunk_collection.hpp @@ -41308,23 +44699,25 @@ unique_ptr TreeRenderer::CreateTree(const Pipeline &op) { namespace duckdb { +class BufferManager; +class ClientContext; struct BatchedChunkScanState { - map>::iterator iterator; - idx_t chunk_index; + map>::iterator iterator; + ColumnDataScanState scan_state; }; -//! A BatchedChunkCollection holds a number of data entries that are partitioned by batch index -//! Scans over a BatchedChunkCollection are ordered by batch index -class BatchedChunkCollection { +//! A BatchedDataCollection holds a number of data entries that are partitioned by batch index +//! Scans over a BatchedDataCollection are ordered by batch index +class BatchedDataCollection { public: - DUCKDB_API BatchedChunkCollection(); + DUCKDB_API BatchedDataCollection(vector types); //! Appends a datachunk with the given batch index to the batched collection DUCKDB_API void Append(DataChunk &input, idx_t batch_index); //! Merge the other batched chunk collection into this batched collection - DUCKDB_API void Merge(BatchedChunkCollection &other); + DUCKDB_API void Merge(BatchedDataCollection &other); //! Initialize a scan over the batched chunk collection DUCKDB_API void InitializeScan(BatchedChunkScanState &state); @@ -41332,41 +44725,64 @@ class BatchedChunkCollection { //! Scan a chunk from the batched chunk collection, in-order of batch index DUCKDB_API void Scan(BatchedChunkScanState &state, DataChunk &output); + //! Fetch a column data collection from the batched data collection - this consumes all of the data stored within + DUCKDB_API unique_ptr FetchCollection(); + DUCKDB_API string ToString() const; DUCKDB_API void Print() const; private: - //! The data of the batched chunk collection - a set of batch_index -> ChunkCollection pointers - map> data; + struct CachedCollection { + idx_t batch_index = DConstants::INVALID_INDEX; + ColumnDataCollection *collection = nullptr; + ColumnDataAppendState append_state; + }; + + vector types; + //! The data of the batched chunk collection - a set of batch_index -> ColumnDataCollection pointers + map> data; + //! The last batch collection that was inserted into + CachedCollection last_collection; }; } // namespace duckdb + namespace duckdb { -BatchedChunkCollection::BatchedChunkCollection() { +BatchedDataCollection::BatchedDataCollection(vector types_p) : types(move(types_p)) { } -void BatchedChunkCollection::Append(DataChunk &input, idx_t batch_index) { +void BatchedDataCollection::Append(DataChunk &input, idx_t batch_index) { D_ASSERT(batch_index != DConstants::INVALID_INDEX); - auto entry = data.find(batch_index); - ChunkCollection *collection; - if (entry == data.end()) { - auto new_collection = make_unique(); + ColumnDataCollection *collection; + if (last_collection.collection && last_collection.batch_index == batch_index) { + // we are inserting into the same collection as before: use it directly + collection = last_collection.collection; + } else { + // new collection: check if there is already an entry + D_ASSERT(data.find(batch_index) == data.end()); + unique_ptr new_collection; + if (last_collection.collection) { + new_collection = make_unique(*last_collection.collection); + } else { + new_collection = make_unique(Allocator::DefaultAllocator(), types); + } + last_collection.collection = new_collection.get(); + last_collection.batch_index = batch_index; + new_collection->InitializeAppend(last_collection.append_state); collection = new_collection.get(); data.insert(make_pair(batch_index, move(new_collection))); - } else { - collection = entry->second.get(); } - collection->Append(input); + collection->Append(last_collection.append_state, input); } -void BatchedChunkCollection::Merge(BatchedChunkCollection &other) { +void BatchedDataCollection::Merge(BatchedDataCollection &other) { for (auto &entry : other.data) { if (data.find(entry.first) != data.end()) { throw InternalException( - "BatchChunkCollection::Merge error - batch index %d is present in both collections. This occurs when " + "BatchedDataCollection::Merge error - batch index %d is present in both collections. This occurs when " "batch indexes are not uniquely distributed over threads", entry.first); } @@ -41375,30 +44791,51 @@ void BatchedChunkCollection::Merge(BatchedChunkCollection &other) { other.data.clear(); } -void BatchedChunkCollection::InitializeScan(BatchedChunkScanState &state) { +void BatchedDataCollection::InitializeScan(BatchedChunkScanState &state) { state.iterator = data.begin(); - state.chunk_index = 0; + if (state.iterator == data.end()) { + return; + } + state.iterator->second->InitializeScan(state.scan_state); } -void BatchedChunkCollection::Scan(BatchedChunkScanState &state, DataChunk &output) { +void BatchedDataCollection::Scan(BatchedChunkScanState &state, DataChunk &output) { while (state.iterator != data.end()) { // check if there is a chunk remaining in this collection auto collection = state.iterator->second.get(); - if (state.chunk_index < collection->ChunkCount()) { - // there is! increment the chunk count - output.Reference(collection->GetChunk(state.chunk_index)); - state.chunk_index++; + collection->Scan(state.scan_state, output); + if (output.size() > 0) { return; } // there isn't! move to the next collection state.iterator++; - state.chunk_index = 0; + if (state.iterator == data.end()) { + return; + } + state.iterator->second->InitializeScan(state.scan_state); } } -string BatchedChunkCollection::ToString() const { +unique_ptr BatchedDataCollection::FetchCollection() { + unique_ptr result; + for (auto &entry : data) { + if (!result) { + result = move(entry.second); + } else { + result->Combine(*entry.second); + } + } + data.clear(); + if (!result) { + // empty result + return make_unique(Allocator::DefaultAllocator(), types); + } + return result; +} + +string BatchedDataCollection::ToString() const { string result; - result += "Batched Chunk Collection\n"; + result += "Batched Data Collection\n"; for (auto &entry : data) { result += "Batch Index - " + to_string(entry.first) + "\n"; result += entry.second->ToString() + "\n\n"; @@ -41406,7 +44843,7 @@ string BatchedChunkCollection::ToString() const { return result; } -void BatchedChunkCollection::Print() const { +void BatchedDataCollection::Print() const { Printer::Print(ToString()); } @@ -41845,6 +45282,12 @@ struct ValueOperations { namespace duckdb { +ChunkCollection::ChunkCollection(Allocator &allocator) : allocator(allocator), count(0) { +} + +ChunkCollection::ChunkCollection(ClientContext &context) : ChunkCollection(Allocator::Get(context)) { +} + void ChunkCollection::Verify() { #ifdef DEBUG for (auto &chunk : chunks) { @@ -41929,7 +45372,7 @@ void ChunkCollection::Append(DataChunk &new_chunk) { idx_t added_data = MinValue(remaining_data, STANDARD_VECTOR_SIZE - last_chunk.size()); if (added_data > 0) { // copy elements to the last chunk - new_chunk.Normalify(); + new_chunk.Flatten(); // have to be careful here: setting the cardinality without calling normalify can cause incorrect partial // decompression idx_t old_count = new_chunk.size(); @@ -41946,7 +45389,7 @@ void ChunkCollection::Append(DataChunk &new_chunk) { if (remaining_data > 0) { // create a new chunk and fill it with the remainder auto chunk = make_unique(); - chunk->Initialize(types); + chunk->Initialize(allocator, types); new_chunk.Copy(*chunk, offset); chunks.push_back(move(chunk)); } @@ -42286,6 +45729,12 @@ bool ChunkCollection::Equals(ChunkCollection &other) { if (compare_equals) { return true; } + for (auto &type : types) { + // sort not supported + if (type.InternalType() == PhysicalType::LIST || type.InternalType() == PhysicalType::STRUCT) { + return false; + } + } // if the results are not equal, // sort both chunk collections to ensure the comparison is not order insensitive vector desc(ColumnCount(), OrderType::DESCENDING); @@ -42310,37 +45759,82 @@ bool ChunkCollection::Equals(ChunkCollection &other) { } } // namespace duckdb - - //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/array.hpp +// duckdb/common/types/column_data_allocator.hpp // // //===----------------------------------------------------------------------===// -#include + namespace duckdb { -using std::array; -} +struct ChunkMetaData; +struct BlockMetaData { + //! The underlying block handle + shared_ptr handle; + //! How much space is currently used within the block + uint32_t size; + //! How much space is available in the block + uint32_t capacity; + uint32_t Capacity(); +}; +class ColumnDataAllocator { +public: + ColumnDataAllocator(Allocator &allocator); + ColumnDataAllocator(BufferManager &buffer_manager); + ColumnDataAllocator(ClientContext &context, ColumnDataAllocatorType allocator_type); + + //! Returns an allocator object to allocate with. This returns the allocator in IN_MEMORY_ALLOCATOR, and a buffer + //! allocator in case of BUFFER_MANAGER_ALLOCATOR. + Allocator &GetAllocator(); + //! Returns the allocator type + ColumnDataAllocatorType GetType() { + return type; + } + +public: + void AllocateData(idx_t size, uint32_t &block_id, uint32_t &offset, ChunkManagementState *chunk_state); + void Initialize(ColumnDataAllocator &other); + void InitializeChunkState(ChunkManagementState &state, ChunkMetaData &meta_data); + data_ptr_t GetDataPointer(ChunkManagementState &state, uint32_t block_id, uint32_t offset); +private: + void AllocateBlock(); + BufferHandle Pin(uint32_t block_id); + bool HasBlocks() { + return !blocks.empty(); + } +private: + ColumnDataAllocatorType type; + union { + //! The allocator object (if this is a IN_MEMORY_ALLOCATOR) + Allocator *allocator; + //! The buffer manager (if this is a BUFFER_MANAGER_ALLOCATOR) + BufferManager *buffer_manager; + } alloc; + //! The set of blocks used by the column data collection + vector blocks; + //! The set of allocated data + vector allocated_data; +}; +} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/types/sel_cache.hpp +// duckdb/common/types/column_data_collection_segment.hpp // // //===----------------------------------------------------------------------===// @@ -42352,21 +45846,256 @@ using std::array; namespace duckdb { -//! Selection vector cache used for caching vector slices -struct SelCache { - unordered_map> cache; +struct VectorChildIndex { + explicit VectorChildIndex(idx_t index = DConstants::INVALID_INDEX) : index(index) { + } + + idx_t index; + + bool IsValid() { + return index != DConstants::INVALID_INDEX; + } +}; + +struct VectorDataIndex { + explicit VectorDataIndex(idx_t index = DConstants::INVALID_INDEX) : index(index) { + } + + idx_t index; + + bool IsValid() { + return index != DConstants::INVALID_INDEX; + } +}; + +struct VectorMetaData { + //! Where the vector data lives + uint32_t block_id; + uint32_t offset; + //! The number of entries present in this vector + uint16_t count; + + //! Child data of this vector (used only for lists and structs) + //! Note: child indices are stored with one layer of indirection + //! The child_index here refers to the `child_indices` array in the ColumnDataCollectionSegment + //! The entry in the child_indices array then refers to the actual `VectorMetaData` index + //! In case of structs, the child_index refers to the FIRST child in the `child_indices` array + //! Subsequent children are stored consecutively, i.e. + //! first child: segment.child_indices[child_index + 0] + //! nth child : segment.child_indices[child_index + (n - 1)] + VectorChildIndex child_index; + //! Next vector entry (in case there is more data - used only in case of children of lists) + VectorDataIndex next_data; +}; + +struct ChunkMetaData { + //! The set of vectors of the chunk + vector vector_data; + //! The block ids referenced by the chunk + unordered_set block_ids; + //! The number of entries in the chunk + uint16_t count; +}; + +class ColumnDataCollectionSegment { +public: + ColumnDataCollectionSegment(shared_ptr allocator, vector types_p); + + shared_ptr allocator; + //! The types of the chunks + vector types; + //! The number of entries in the internal column data + idx_t count; + //! Set of chunk meta data + vector chunk_data; + //! Set of vector meta data + vector vector_data; + //! The set of child indices + vector child_indices; + //! The string heap for the column data collection + // FIXME: we should get rid of the string heap and store strings as LIST + StringHeap heap; + +public: + void AllocateNewChunk(); + //! Allocate space for a vector of a specific type in the segment + VectorDataIndex AllocateVector(const LogicalType &type, ChunkMetaData &chunk_data, + ChunkManagementState *chunk_state = nullptr, + VectorDataIndex prev_index = VectorDataIndex()); + //! Allocate space for a vector during append, + VectorDataIndex AllocateVector(const LogicalType &type, ChunkMetaData &chunk_data, + ColumnDataAppendState &append_state, VectorDataIndex prev_index = VectorDataIndex()); + + void InitializeChunkState(idx_t chunk_index, ChunkManagementState &state); + void ReadChunk(idx_t chunk_index, ChunkManagementState &state, DataChunk &chunk, + const vector &column_ids); + + idx_t ReadVector(ChunkManagementState &state, VectorDataIndex vector_index, Vector &result); + + VectorDataIndex GetChildIndex(VectorChildIndex index, idx_t child_entry = 0); + VectorChildIndex AddChildIndex(VectorDataIndex index); + VectorChildIndex ReserveChildren(idx_t child_count); + void SetChildIndex(VectorChildIndex base_idx, idx_t child_number, VectorDataIndex index); + + VectorMetaData &GetVectorData(VectorDataIndex index) { + D_ASSERT(index.index < vector_data.size()); + return vector_data[index.index]; + } + + idx_t ChunkCount() const; + void FetchChunk(idx_t chunk_idx, DataChunk &result); + void FetchChunk(idx_t chunk_idx, DataChunk &result, const vector &column_ids); + + void Verify(); + + static idx_t GetDataSize(idx_t type_size); + static validity_t *GetValidityPointer(data_ptr_t base_ptr, idx_t type_size); + +private: + idx_t ReadVectorInternal(ChunkManagementState &state, VectorDataIndex vector_index, Vector &result); + VectorDataIndex AllocateVectorInternal(const LogicalType &type, ChunkMetaData &chunk_meta, + ChunkManagementState *chunk_state); }; } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/types/vector_cache.hpp -// -// -//===----------------------------------------------------------------------===// +namespace duckdb { + +ColumnDataAllocator::ColumnDataAllocator(Allocator &allocator) : type(ColumnDataAllocatorType::IN_MEMORY_ALLOCATOR) { + alloc.allocator = &allocator; +} + +ColumnDataAllocator::ColumnDataAllocator(BufferManager &buffer_manager) + : type(ColumnDataAllocatorType::BUFFER_MANAGER_ALLOCATOR) { + alloc.buffer_manager = &buffer_manager; +} + +ColumnDataAllocator::ColumnDataAllocator(ClientContext &context, ColumnDataAllocatorType allocator_type) + : type(allocator_type) { + switch (type) { + case ColumnDataAllocatorType::BUFFER_MANAGER_ALLOCATOR: + alloc.buffer_manager = &BufferManager::GetBufferManager(context); + break; + case ColumnDataAllocatorType::IN_MEMORY_ALLOCATOR: + alloc.allocator = &Allocator::Get(context); + break; + default: + throw InternalException("Unrecognized column data allocator type"); + } +} + +BufferHandle ColumnDataAllocator::Pin(uint32_t block_id) { + D_ASSERT(type == ColumnDataAllocatorType::BUFFER_MANAGER_ALLOCATOR); + return alloc.buffer_manager->Pin(blocks[block_id].handle); +} + +void ColumnDataAllocator::AllocateBlock() { + D_ASSERT(type == ColumnDataAllocatorType::BUFFER_MANAGER_ALLOCATOR); + BlockMetaData data; + data.size = 0; + data.capacity = Storage::BLOCK_ALLOC_SIZE; + data.handle = alloc.buffer_manager->RegisterMemory(Storage::BLOCK_ALLOC_SIZE, false); + blocks.push_back(move(data)); +} + +void ColumnDataAllocator::AllocateData(idx_t size, uint32_t &block_id, uint32_t &offset, + ChunkManagementState *chunk_state) { + if (type == ColumnDataAllocatorType::IN_MEMORY_ALLOCATOR) { + // in-memory allocator + auto allocated = alloc.allocator->Allocate(size); + auto pointer_value = uintptr_t(allocated.get()); + if (sizeof(uintptr_t) == sizeof(uint32_t)) { + block_id = uint32_t(pointer_value); + } else if (sizeof(uintptr_t) == sizeof(uint64_t)) { + block_id = uint32_t(pointer_value & 0xFFFFFFFF); + offset = uint32_t(pointer_value >> 32); + } else { + throw InternalException("ColumnDataCollection: Architecture not supported!?"); + } + allocated_data.push_back(move(allocated)); + return; + } + if (blocks.empty() || blocks.back().Capacity() < size) { + AllocateBlock(); + if (chunk_state && !blocks.empty()) { + auto &last_block = blocks.back(); + auto new_block_id = blocks.size() - 1; + auto pinned_block = alloc.buffer_manager->Pin(last_block.handle); + chunk_state->handles[new_block_id] = move(pinned_block); + } + } + auto &block = blocks.back(); + D_ASSERT(size <= block.capacity - block.size); + block_id = blocks.size() - 1; + offset = block.size; + block.size += size; +} + +void ColumnDataAllocator::Initialize(ColumnDataAllocator &other) { + D_ASSERT(other.HasBlocks()); + blocks.push_back(other.blocks.back()); +} + +data_ptr_t ColumnDataAllocator::GetDataPointer(ChunkManagementState &state, uint32_t block_id, uint32_t offset) { + if (type == ColumnDataAllocatorType::IN_MEMORY_ALLOCATOR) { + // in-memory allocator: construct pointer from block_id and offset + if (sizeof(uintptr_t) == sizeof(uint32_t)) { + uintptr_t pointer_value = uintptr_t(block_id); + return (data_ptr_t)pointer_value; + } else if (sizeof(uintptr_t) == sizeof(uint64_t)) { + uintptr_t pointer_value = (uintptr_t(offset) << 32) | uintptr_t(block_id); + return (data_ptr_t)pointer_value; + } else { + throw InternalException("ColumnDataCollection: Architecture not supported!?"); + } + } + D_ASSERT(state.handles.find(block_id) != state.handles.end()); + return state.handles[block_id].Ptr() + offset; +} + +Allocator &ColumnDataAllocator::GetAllocator() { + return type == ColumnDataAllocatorType::IN_MEMORY_ALLOCATOR ? *alloc.allocator + : alloc.buffer_manager->GetBufferAllocator(); +} + +void ColumnDataAllocator::InitializeChunkState(ChunkManagementState &state, ChunkMetaData &chunk) { + if (type != ColumnDataAllocatorType::BUFFER_MANAGER_ALLOCATOR) { + // nothing to pin + return; + } + // release any handles that are no longer required + bool found_handle; + do { + found_handle = false; + for (auto it = state.handles.begin(); it != state.handles.end(); it++) { + if (chunk.block_ids.find(it->first) != chunk.block_ids.end()) { + // still required: do not release + continue; + } + state.handles.erase(it); + found_handle = true; + break; + } + } while (found_handle); + + // grab any handles that are now required + for (auto &block_id : chunk.block_ids) { + if (state.handles.find(block_id) != state.handles.end()) { + // already pinned: don't need to do anything + continue; + } + state.handles[block_id] = Pin(block_id); + } +} + +uint32_t BlockMetaData::Capacity() { + D_ASSERT(size <= capacity); + return capacity - size; +} + +} // namespace duckdb + @@ -42375,25 +46104,1051 @@ struct SelCache { namespace duckdb { -class Vector; -//! The VectorCache holds cached data that allows for re-use of the same memory by vectors -class VectorCache { -public: - //! Instantiate a vector cache with the given type - explicit VectorCache(const LogicalType &type); +struct ColumnDataMetaData; - buffer_ptr buffer; +typedef void (*column_data_copy_function_t)(ColumnDataMetaData &meta_data, const UnifiedVectorFormat &source_data, + Vector &source, idx_t offset, idx_t copy_count); -public: - void ResetFromCache(Vector &result) const; +struct ColumnDataCopyFunction { + column_data_copy_function_t function; + vector child_functions; +}; - const LogicalType &GetType() const; +struct ColumnDataMetaData { + ColumnDataMetaData(ColumnDataCopyFunction ©_function, ColumnDataCollectionSegment &segment, + ColumnDataAppendState &state, ChunkMetaData &chunk_data, VectorDataIndex vector_data_index) + : copy_function(copy_function), segment(segment), state(state), chunk_data(chunk_data), + vector_data_index(vector_data_index) { + } + ColumnDataMetaData(ColumnDataCopyFunction ©_function, ColumnDataMetaData &parent, + VectorDataIndex vector_data_index) + : copy_function(copy_function), segment(parent.segment), state(parent.state), chunk_data(parent.chunk_data), + vector_data_index(vector_data_index) { + } + + ColumnDataCopyFunction ©_function; + ColumnDataCollectionSegment &segment; + ColumnDataAppendState &state; + ChunkMetaData &chunk_data; + VectorDataIndex vector_data_index; + idx_t child_list_size = DConstants::INVALID_INDEX; + + VectorMetaData &GetVectorMetaData() { + return segment.GetVectorData(vector_data_index); + } }; +//! Explicitly initialized without types +ColumnDataCollection::ColumnDataCollection(Allocator &allocator_p) { + types.clear(); + count = 0; + this->finished_append = false; + allocator = make_shared(allocator_p); +} + +ColumnDataCollection::ColumnDataCollection(Allocator &allocator_p, vector types_p) { + Initialize(move(types_p)); + allocator = make_shared(allocator_p); +} + +ColumnDataCollection::ColumnDataCollection(BufferManager &buffer_manager, vector types_p) { + Initialize(move(types_p)); + allocator = make_shared(buffer_manager); +} + +ColumnDataCollection::ColumnDataCollection(shared_ptr allocator_p, vector types_p) { + Initialize(move(types_p)); + this->allocator = move(allocator_p); +} + +ColumnDataCollection::ColumnDataCollection(ClientContext &context, vector types_p, + ColumnDataAllocatorType type) + : ColumnDataCollection(make_shared(context, type), move(types_p)) { + D_ASSERT(!types.empty()); +} + +ColumnDataCollection::ColumnDataCollection(ColumnDataCollection &other) + : ColumnDataCollection(other.allocator, other.types) { + other.finished_append = true; + D_ASSERT(!types.empty()); +} + +ColumnDataCollection::~ColumnDataCollection() { +} + +void ColumnDataCollection::Initialize(vector types_p) { + this->types = move(types_p); + this->count = 0; + this->finished_append = false; + D_ASSERT(!types.empty()); + copy_functions.reserve(types.size()); + for (auto &type : types) { + copy_functions.push_back(GetCopyFunction(type)); + } +} + +void ColumnDataCollection::CreateSegment() { + segments.emplace_back(make_unique(allocator, types)); +} + +//===--------------------------------------------------------------------===// +// ColumnDataRow +//===--------------------------------------------------------------------===// +ColumnDataRow::ColumnDataRow(DataChunk &chunk_p, idx_t row_index, idx_t base_index) + : chunk(chunk_p), row_index(row_index), base_index(base_index) { +} + +Value ColumnDataRow::GetValue(idx_t column_index) const { + D_ASSERT(column_index < chunk.ColumnCount()); + D_ASSERT(row_index < chunk.size()); + return chunk.data[column_index].GetValue(row_index); +} + +idx_t ColumnDataRow::RowIndex() const { + return base_index + row_index; +} + +//===--------------------------------------------------------------------===// +// ColumnDataRowCollection +//===--------------------------------------------------------------------===// +ColumnDataRowCollection::ColumnDataRowCollection(const ColumnDataCollection &collection) { + if (collection.Count() == 0) { + return; + } + // read all the chunks + ColumnDataScanState scan_state; + collection.InitializeScan(scan_state); + while (true) { + auto chunk = make_unique(); + collection.InitializeScanChunk(*chunk); + if (!collection.Scan(scan_state, *chunk)) { + break; + } + chunks.push_back(move(chunk)); + } + // now create all of the column data rows + rows.reserve(collection.Count()); + idx_t base_row = 0; + for (auto &chunk : chunks) { + for (idx_t row_idx = 0; row_idx < chunk->size(); row_idx++) { + rows.emplace_back(*chunk, row_idx, base_row); + } + base_row += chunk->size(); + } +} + +ColumnDataRow &ColumnDataRowCollection::operator[](idx_t i) { + return rows[i]; +} + +const ColumnDataRow &ColumnDataRowCollection::operator[](idx_t i) const { + return rows[i]; +} + +Value ColumnDataRowCollection::GetValue(idx_t column, idx_t index) const { + return rows[index].GetValue(column); +} + +//===--------------------------------------------------------------------===// +// ColumnDataChunkIterator +//===--------------------------------------------------------------------===// +ColumnDataChunkIterationHelper ColumnDataCollection::Chunks() const { + vector column_ids; + for (idx_t i = 0; i < ColumnCount(); i++) { + column_ids.push_back(i); + } + return Chunks(column_ids); +} + +ColumnDataChunkIterationHelper ColumnDataCollection::Chunks(vector column_ids) const { + return ColumnDataChunkIterationHelper(*this, move(column_ids)); +} + +ColumnDataChunkIterationHelper::ColumnDataChunkIterationHelper(const ColumnDataCollection &collection_p, + vector column_ids_p) + : collection(collection_p), column_ids(move(column_ids_p)) { +} + +ColumnDataChunkIterationHelper::ColumnDataChunkIterator::ColumnDataChunkIterator( + const ColumnDataCollection *collection_p, vector column_ids_p) + : collection(collection_p), scan_chunk(make_shared()), row_index(0) { + if (!collection) { + return; + } + collection->InitializeScan(scan_state, move(column_ids_p)); + collection->InitializeScanChunk(scan_state, *scan_chunk); + collection->Scan(scan_state, *scan_chunk); +} + +void ColumnDataChunkIterationHelper::ColumnDataChunkIterator::Next() { + if (!collection) { + return; + } + if (!collection->Scan(scan_state, *scan_chunk)) { + collection = nullptr; + row_index = 0; + } else { + row_index += scan_chunk->size(); + } +} + +ColumnDataChunkIterationHelper::ColumnDataChunkIterator & +ColumnDataChunkIterationHelper::ColumnDataChunkIterator::operator++() { + Next(); + return *this; +} + +bool ColumnDataChunkIterationHelper::ColumnDataChunkIterator::operator!=(const ColumnDataChunkIterator &other) const { + return collection != other.collection || row_index != other.row_index; +} + +DataChunk &ColumnDataChunkIterationHelper::ColumnDataChunkIterator::operator*() const { + return *scan_chunk; +} + +//===--------------------------------------------------------------------===// +// ColumnDataRowIterator +//===--------------------------------------------------------------------===// +ColumnDataRowIterationHelper ColumnDataCollection::Rows() const { + return ColumnDataRowIterationHelper(*this); +} + +ColumnDataRowIterationHelper::ColumnDataRowIterationHelper(const ColumnDataCollection &collection_p) + : collection(collection_p) { +} + +ColumnDataRowIterationHelper::ColumnDataRowIterator::ColumnDataRowIterator(const ColumnDataCollection *collection_p) + : collection(collection_p), scan_chunk(make_shared()), current_row(*scan_chunk, 0, 0) { + if (!collection) { + return; + } + collection->InitializeScan(scan_state); + collection->InitializeScanChunk(*scan_chunk); + collection->Scan(scan_state, *scan_chunk); +} + +void ColumnDataRowIterationHelper::ColumnDataRowIterator::Next() { + if (!collection) { + return; + } + current_row.row_index++; + if (current_row.row_index >= scan_chunk->size()) { + current_row.base_index += scan_chunk->size(); + current_row.row_index = 0; + if (!collection->Scan(scan_state, *scan_chunk)) { + // exhausted collection: move iterator to nop state + current_row.base_index = 0; + collection = nullptr; + } + } +} + +ColumnDataRowIterationHelper::ColumnDataRowIterator ColumnDataRowIterationHelper::begin() { // NOLINT + return ColumnDataRowIterationHelper::ColumnDataRowIterator(collection.Count() == 0 ? nullptr : &collection); +} +ColumnDataRowIterationHelper::ColumnDataRowIterator ColumnDataRowIterationHelper::end() { // NOLINT + return ColumnDataRowIterationHelper::ColumnDataRowIterator(nullptr); +} + +ColumnDataRowIterationHelper::ColumnDataRowIterator &ColumnDataRowIterationHelper::ColumnDataRowIterator::operator++() { + Next(); + return *this; +} + +bool ColumnDataRowIterationHelper::ColumnDataRowIterator::operator!=(const ColumnDataRowIterator &other) const { + return collection != other.collection || current_row.row_index != other.current_row.row_index || + current_row.base_index != other.current_row.base_index; +} + +const ColumnDataRow &ColumnDataRowIterationHelper::ColumnDataRowIterator::operator*() const { + return current_row; +} + +//===--------------------------------------------------------------------===// +// Append +//===--------------------------------------------------------------------===// +void ColumnDataCollection::InitializeAppend(ColumnDataAppendState &state) { + D_ASSERT(!finished_append); + state.vector_data.resize(types.size()); + if (segments.empty()) { + CreateSegment(); + } + auto &segment = *segments.back(); + if (segment.chunk_data.empty()) { + segment.AllocateNewChunk(); + } + segment.InitializeChunkState(segment.chunk_data.size() - 1, state.current_chunk_state); +} + +void ColumnDataCopyValidity(const UnifiedVectorFormat &source_data, validity_t *target, idx_t source_offset, + idx_t target_offset, idx_t copy_count) { + ValidityMask validity(target); + if (target_offset == 0) { + // first time appending to this vector + // all data here is still uninitialized + // initialize the validity mask to set all to valid + validity.SetAllValid(STANDARD_VECTOR_SIZE); + } + // FIXME: we can do something more optimized here using bitshifts & bitwise ors + if (!source_data.validity.AllValid()) { + for (idx_t i = 0; i < copy_count; i++) { + auto idx = source_data.sel->get_index(source_offset + i); + if (!source_data.validity.RowIsValid(idx)) { + validity.SetInvalid(target_offset + i); + } + } + } +} + +template +struct BaseValueCopy { + static idx_t TypeSize() { + return sizeof(T); + } + + template + static void Assign(ColumnDataMetaData &meta_data, data_ptr_t target, data_ptr_t source, idx_t target_idx, + idx_t source_idx) { + auto result_data = (T *)target; + auto source_data = (T *)source; + result_data[target_idx] = OP::Operation(meta_data, source_data[source_idx]); + } +}; + +template +struct StandardValueCopy : public BaseValueCopy { + static T Operation(ColumnDataMetaData &, T input) { + return input; + } +}; + +struct StringValueCopy : public BaseValueCopy { + static string_t Operation(ColumnDataMetaData &meta_data, string_t input) { + return input.IsInlined() ? input : meta_data.segment.heap.AddBlob(input); + } +}; + +struct ListValueCopy : public BaseValueCopy { + using TYPE = list_entry_t; + + static TYPE Operation(ColumnDataMetaData &meta_data, TYPE input) { + input.offset += meta_data.child_list_size; + return input; + } +}; + +struct StructValueCopy { + static idx_t TypeSize() { + return 0; + } + + template + static void Assign(ColumnDataMetaData &meta_data, data_ptr_t target, data_ptr_t source, idx_t target_idx, + idx_t source_idx) { + } +}; + +template +static void TemplatedColumnDataCopy(ColumnDataMetaData &meta_data, const UnifiedVectorFormat &source_data, + Vector &source, idx_t offset, idx_t count) { + auto &segment = meta_data.segment; + auto &append_state = meta_data.state; + + auto current_index = meta_data.vector_data_index; + idx_t remaining = count; + while (remaining > 0) { + auto ¤t_segment = segment.GetVectorData(current_index); + idx_t append_count = MinValue(STANDARD_VECTOR_SIZE - current_segment.count, remaining); + + auto base_ptr = meta_data.segment.allocator->GetDataPointer(append_state.current_chunk_state, + current_segment.block_id, current_segment.offset); + auto validity_data = ColumnDataCollectionSegment::GetValidityPointer(base_ptr, OP::TypeSize()); + + ValidityMask result_validity(validity_data); + if (current_segment.count == 0) { + // first time appending to this vector + // all data here is still uninitialized + // initialize the validity mask to set all to valid + result_validity.SetAllValid(STANDARD_VECTOR_SIZE); + } + for (idx_t i = 0; i < append_count; i++) { + auto source_idx = source_data.sel->get_index(offset + i); + if (source_data.validity.RowIsValid(source_idx)) { + OP::template Assign(meta_data, base_ptr, source_data.data, current_segment.count + i, source_idx); + } else { + result_validity.SetInvalid(current_segment.count + i); + } + } + current_segment.count += append_count; + offset += append_count; + remaining -= append_count; + if (remaining > 0) { + // need to append more, check if we need to allocate a new vector or not + if (!current_segment.next_data.IsValid()) { + segment.AllocateVector(source.GetType(), meta_data.chunk_data, meta_data.state, current_index); + } + D_ASSERT(segment.GetVectorData(current_index).next_data.IsValid()); + current_index = segment.GetVectorData(current_index).next_data; + } + } +} + +template +static void ColumnDataCopy(ColumnDataMetaData &meta_data, const UnifiedVectorFormat &source_data, Vector &source, + idx_t offset, idx_t copy_count) { + TemplatedColumnDataCopy>(meta_data, source_data, source, offset, copy_count); +} + +template <> +void ColumnDataCopy(ColumnDataMetaData &meta_data, const UnifiedVectorFormat &source_data, Vector &source, + idx_t offset, idx_t copy_count) { + TemplatedColumnDataCopy(meta_data, source_data, source, offset, copy_count); +} + +template <> +void ColumnDataCopy(ColumnDataMetaData &meta_data, const UnifiedVectorFormat &source_data, Vector &source, + idx_t offset, idx_t copy_count) { + auto &segment = meta_data.segment; + + // first append the child entries of the list + auto &child_vector = ListVector::GetEntry(source); + idx_t child_list_size = ListVector::GetListSize(source); + auto &child_type = child_vector.GetType(); + + UnifiedVectorFormat child_vector_data; + child_vector.ToUnifiedFormat(child_list_size, child_vector_data); + + if (!meta_data.GetVectorMetaData().child_index.IsValid()) { + auto child_index = segment.AllocateVector(child_type, meta_data.chunk_data, meta_data.state); + meta_data.GetVectorMetaData().child_index = meta_data.segment.AddChildIndex(child_index); + } + auto &child_function = meta_data.copy_function.child_functions[0]; + auto child_index = segment.GetChildIndex(meta_data.GetVectorMetaData().child_index); + // figure out the current list size by traversing the set of child entries + idx_t current_list_size = 0; + auto current_child_index = child_index; + while (current_child_index.IsValid()) { + auto &child_vdata = segment.GetVectorData(current_child_index); + current_list_size += child_vdata.count; + current_child_index = child_vdata.next_data; + } + ColumnDataMetaData child_meta_data(child_function, meta_data, child_index); + // FIXME: appending the entire child list here is not required + // We can also scan the actual list entries required per the offset/copy_count + child_function.function(child_meta_data, child_vector_data, child_vector, 0, child_list_size); + + // now copy the list entries + meta_data.child_list_size = current_list_size; + TemplatedColumnDataCopy(meta_data, source_data, source, offset, copy_count); +} + +void ColumnDataCopyStruct(ColumnDataMetaData &meta_data, const UnifiedVectorFormat &source_data, Vector &source, + idx_t offset, idx_t copy_count) { + auto &segment = meta_data.segment; + + // copy the NULL values for the main struct vector + TemplatedColumnDataCopy(meta_data, source_data, source, offset, copy_count); + + auto &child_types = StructType::GetChildTypes(source.GetType()); + // now copy all the child vectors + D_ASSERT(meta_data.GetVectorMetaData().child_index.IsValid()); + auto &child_vectors = StructVector::GetEntries(source); + for (idx_t child_idx = 0; child_idx < child_types.size(); child_idx++) { + auto &child_function = meta_data.copy_function.child_functions[child_idx]; + auto child_index = segment.GetChildIndex(meta_data.GetVectorMetaData().child_index, child_idx); + ColumnDataMetaData child_meta_data(child_function, meta_data, child_index); + + UnifiedVectorFormat child_data; + child_vectors[child_idx]->ToUnifiedFormat(copy_count, child_data); + + child_function.function(child_meta_data, child_data, *child_vectors[child_idx], offset, copy_count); + } +} + +ColumnDataCopyFunction ColumnDataCollection::GetCopyFunction(const LogicalType &type) { + ColumnDataCopyFunction result; + column_data_copy_function_t function; + switch (type.InternalType()) { + case PhysicalType::BOOL: + function = ColumnDataCopy; + break; + case PhysicalType::INT8: + function = ColumnDataCopy; + break; + case PhysicalType::INT16: + function = ColumnDataCopy; + break; + case PhysicalType::INT32: + function = ColumnDataCopy; + break; + case PhysicalType::INT64: + function = ColumnDataCopy; + break; + case PhysicalType::INT128: + function = ColumnDataCopy; + break; + case PhysicalType::UINT8: + function = ColumnDataCopy; + break; + case PhysicalType::UINT16: + function = ColumnDataCopy; + break; + case PhysicalType::UINT32: + function = ColumnDataCopy; + break; + case PhysicalType::UINT64: + function = ColumnDataCopy; + break; + case PhysicalType::FLOAT: + function = ColumnDataCopy; + break; + case PhysicalType::DOUBLE: + function = ColumnDataCopy; + break; + case PhysicalType::INTERVAL: + function = ColumnDataCopy; + break; + case PhysicalType::VARCHAR: + function = ColumnDataCopy; + break; + case PhysicalType::STRUCT: { + function = ColumnDataCopyStruct; + auto &child_types = StructType::GetChildTypes(type); + for (auto &kv : child_types) { + result.child_functions.push_back(GetCopyFunction(kv.second)); + } + break; + } + case PhysicalType::LIST: { + function = ColumnDataCopy; + auto child_function = GetCopyFunction(ListType::GetChildType(type)); + result.child_functions.push_back(child_function); + break; + } + default: + throw InternalException("Unsupported type for ColumnDataCollection::GetCopyFunction"); + } + result.function = function; + return result; +} + +static bool IsComplexType(const LogicalType &type) { + switch (type.InternalType()) { + case PhysicalType::STRUCT: + case PhysicalType::LIST: + return true; + default: + return false; + }; +} + +void ColumnDataCollection::Append(ColumnDataAppendState &state, DataChunk &input) { + D_ASSERT(!finished_append); + D_ASSERT(types == input.GetTypes()); + + auto &segment = *segments.back(); + for (idx_t vector_idx = 0; vector_idx < types.size(); vector_idx++) { + if (IsComplexType(input.data[vector_idx].GetType())) { + input.data[vector_idx].Flatten(input.size()); + } + input.data[vector_idx].ToUnifiedFormat(input.size(), state.vector_data[vector_idx]); + } + + idx_t remaining = input.size(); + while (remaining > 0) { + auto &chunk_data = segment.chunk_data.back(); + idx_t append_amount = MinValue(remaining, STANDARD_VECTOR_SIZE - chunk_data.count); + if (append_amount > 0) { + idx_t offset = input.size() - remaining; + for (idx_t vector_idx = 0; vector_idx < types.size(); vector_idx++) { + ColumnDataMetaData meta_data(copy_functions[vector_idx], segment, state, chunk_data, + chunk_data.vector_data[vector_idx]); + copy_functions[vector_idx].function(meta_data, state.vector_data[vector_idx], input.data[vector_idx], + offset, append_amount); + } + chunk_data.count += append_amount; + } + remaining -= append_amount; + if (remaining > 0) { + // more to do + // allocate a new chunk + segment.AllocateNewChunk(); + segment.InitializeChunkState(segment.chunk_data.size() - 1, state.current_chunk_state); + } + } + segment.count += input.size(); + count += input.size(); +} + +void ColumnDataCollection::Append(DataChunk &input) { + ColumnDataAppendState state; + InitializeAppend(state); + Append(state, input); +} + +//===--------------------------------------------------------------------===// +// Scan +//===--------------------------------------------------------------------===// +void ColumnDataCollection::InitializeScan(ColumnDataScanState &state, ColumnDataScanProperties properties) const { + vector column_ids; + column_ids.reserve(types.size()); + for (idx_t i = 0; i < types.size(); i++) { + column_ids.push_back(i); + } + InitializeScan(state, move(column_ids), properties); +} + +void ColumnDataCollection::InitializeScan(ColumnDataScanState &state, vector column_ids, + ColumnDataScanProperties properties) const { + state.chunk_index = 0; + state.segment_index = 0; + state.current_row_index = 0; + state.next_row_index = 0; + state.current_chunk_state.handles.clear(); + state.properties = properties; + state.column_ids = move(column_ids); +} + +void ColumnDataCollection::InitializeScan(ColumnDataParallelScanState &state, + ColumnDataScanProperties properties) const { + InitializeScan(state.scan_state, properties); +} + +void ColumnDataCollection::InitializeScan(ColumnDataParallelScanState &state, vector column_ids, + ColumnDataScanProperties properties) const { + InitializeScan(state.scan_state, move(column_ids), properties); +} + +bool ColumnDataCollection::Scan(ColumnDataParallelScanState &state, ColumnDataLocalScanState &lstate, + DataChunk &result) const { + result.Reset(); + + idx_t chunk_index; + idx_t segment_index; + idx_t row_index; + { + lock_guard l(state.lock); + if (!NextScanIndex(state.scan_state, chunk_index, segment_index, row_index)) { + return false; + } + } + ScanAtIndex(state, lstate, result, chunk_index, segment_index, row_index); + return true; +} + +void ColumnDataCollection::InitializeScanChunk(DataChunk &chunk) const { + chunk.Initialize(allocator->GetAllocator(), types); +} + +void ColumnDataCollection::InitializeScanChunk(ColumnDataScanState &state, DataChunk &chunk) const { + D_ASSERT(!state.column_ids.empty()); + vector chunk_types; + chunk_types.reserve(state.column_ids.size()); + for (idx_t i = 0; i < state.column_ids.size(); i++) { + auto column_idx = state.column_ids[i]; + D_ASSERT(column_idx < types.size()); + chunk_types.push_back(types[column_idx]); + } + chunk.Initialize(allocator->GetAllocator(), chunk_types); +} + +bool ColumnDataCollection::NextScanIndex(ColumnDataScanState &state, idx_t &chunk_index, idx_t &segment_index, + idx_t &row_index) const { + row_index = state.current_row_index = state.next_row_index; + // check if we still have collections to scan + if (state.segment_index >= segments.size()) { + // no more data left in the scan + return false; + } + // check within the current collection if we still have chunks to scan + while (state.chunk_index >= segments[state.segment_index]->chunk_data.size()) { + // exhausted all chunks for this internal data structure: move to the next one + state.chunk_index = 0; + state.segment_index++; + state.current_chunk_state.handles.clear(); + if (state.segment_index >= segments.size()) { + return false; + } + } + state.next_row_index += segments[state.segment_index]->chunk_data[state.chunk_index].count; + segment_index = state.segment_index; + chunk_index = state.chunk_index++; + return true; +} + +void ColumnDataCollection::ScanAtIndex(ColumnDataParallelScanState &state, ColumnDataLocalScanState &lstate, + DataChunk &result, idx_t chunk_index, idx_t segment_index, + idx_t row_index) const { + if (segment_index != lstate.current_segment_index) { + lstate.current_chunk_state.handles.clear(); + lstate.current_segment_index = segment_index; + } + auto &segment = *segments[segment_index]; + lstate.current_chunk_state.properties = state.scan_state.properties; + segment.ReadChunk(chunk_index, lstate.current_chunk_state, result, state.scan_state.column_ids); + lstate.current_row_index = row_index; + result.Verify(); +} + +bool ColumnDataCollection::Scan(ColumnDataScanState &state, DataChunk &result) const { + result.Reset(); + + idx_t chunk_index; + idx_t segment_index; + idx_t row_index; + if (!NextScanIndex(state, chunk_index, segment_index, row_index)) { + return false; + } + + // found a chunk to scan -> scan it + auto &segment = *segments[segment_index]; + state.current_chunk_state.properties = state.properties; + segment.ReadChunk(chunk_index, state.current_chunk_state, result, state.column_ids); + result.Verify(); + return true; +} + +ColumnDataRowCollection ColumnDataCollection::GetRows() const { + return ColumnDataRowCollection(*this); +} + +//===--------------------------------------------------------------------===// +// Combine +//===--------------------------------------------------------------------===// +void ColumnDataCollection::Combine(ColumnDataCollection &other) { + if (other.count == 0) { + return; + } + if (types != other.types) { + throw InternalException("Attempting to combine ColumnDataCollections with mismatching types"); + } + this->count += other.count; + this->segments.reserve(segments.size() + other.segments.size()); + for (auto &other_seg : other.segments) { + segments.push_back(move(other_seg)); + } + Verify(); +} + +//===--------------------------------------------------------------------===// +// Fetch +//===--------------------------------------------------------------------===// +idx_t ColumnDataCollection::ChunkCount() const { + idx_t chunk_count = 0; + for (auto &segment : segments) { + chunk_count += segment->ChunkCount(); + } + return chunk_count; +} + +void ColumnDataCollection::FetchChunk(idx_t chunk_idx, DataChunk &result) const { + D_ASSERT(chunk_idx < ChunkCount()); + for (auto &segment : segments) { + if (chunk_idx >= segment->ChunkCount()) { + chunk_idx -= segment->ChunkCount(); + } else { + segment->FetchChunk(chunk_idx, result); + return; + } + } + throw InternalException("Failed to find chunk in ColumnDataCollection"); +} + +//===--------------------------------------------------------------------===// +// Helpers +//===--------------------------------------------------------------------===// +void ColumnDataCollection::Verify() { +#ifdef DEBUG + // verify counts + idx_t total_segment_count = 0; + for (auto &segment : segments) { + segment->Verify(); + total_segment_count += segment->count; + } + D_ASSERT(total_segment_count == this->count); +#endif +} + +string ColumnDataCollection::ToString() const { + return "Column Data Collection"; +} + +void ColumnDataCollection::Print() const { + Printer::Print(ToString()); +} + +void ColumnDataCollection::Reset() { + count = 0; + segments.clear(); +} + +bool ColumnDataCollection::ResultEquals(const ColumnDataCollection &left, const ColumnDataCollection &right, + string &error_message) { + if (left.ColumnCount() != right.ColumnCount()) { + error_message = "Column count mismatch"; + return false; + } + if (left.Count() != right.Count()) { + error_message = "Row count mismatch"; + return false; + } + auto left_rows = left.GetRows(); + auto right_rows = right.GetRows(); + for (idx_t r = 0; r < left.Count(); r++) { + for (idx_t c = 0; c < left.ColumnCount(); c++) { + auto lvalue = left_rows.GetValue(c, r); + auto rvalue = left_rows.GetValue(c, r); + if (!Value::ValuesAreEqual(lvalue, rvalue)) { + error_message = + StringUtil::Format("%s <> %s (row: %lld, col: %lld)\n", lvalue.ToString(), rvalue.ToString(), r, c); + return false; + } + } + } + return true; +} + } // namespace duckdb +namespace duckdb { + +ColumnDataCollectionSegment::ColumnDataCollectionSegment(shared_ptr allocator_p, + vector types_p) + : allocator(move(allocator_p)), types(move(types_p)), count(0) { +} + +idx_t ColumnDataCollectionSegment::GetDataSize(idx_t type_size) { + return AlignValue(type_size * STANDARD_VECTOR_SIZE); +} + +validity_t *ColumnDataCollectionSegment::GetValidityPointer(data_ptr_t base_ptr, idx_t type_size) { + return (validity_t *)(base_ptr + GetDataSize(type_size)); +} + +VectorDataIndex ColumnDataCollectionSegment::AllocateVectorInternal(const LogicalType &type, ChunkMetaData &chunk_meta, + ChunkManagementState *chunk_state) { + VectorMetaData meta_data; + meta_data.count = 0; + + auto internal_type = type.InternalType(); + auto type_size = internal_type == PhysicalType::STRUCT ? 0 : GetTypeIdSize(internal_type); + allocator->AllocateData(GetDataSize(type_size) + ValidityMask::STANDARD_MASK_SIZE, meta_data.block_id, + meta_data.offset, chunk_state); + if (allocator->GetType() == ColumnDataAllocatorType::BUFFER_MANAGER_ALLOCATOR) { + chunk_meta.block_ids.insert(meta_data.block_id); + } + + auto index = vector_data.size(); + vector_data.push_back(meta_data); + return VectorDataIndex(index); +} + +VectorDataIndex ColumnDataCollectionSegment::AllocateVector(const LogicalType &type, ChunkMetaData &chunk_meta, + ChunkManagementState *chunk_state, + VectorDataIndex prev_index) { + auto index = AllocateVectorInternal(type, chunk_meta, chunk_state); + if (prev_index.IsValid()) { + GetVectorData(prev_index).next_data = index; + } + if (type.InternalType() == PhysicalType::STRUCT) { + // initialize the struct children + auto &child_types = StructType::GetChildTypes(type); + auto base_child_index = ReserveChildren(child_types.size()); + for (idx_t child_idx = 0; child_idx < child_types.size(); child_idx++) { + VectorDataIndex prev_child_index; + if (prev_index.IsValid()) { + prev_child_index = GetChildIndex(GetVectorData(prev_index).child_index, child_idx); + } + auto child_index = AllocateVector(child_types[child_idx].second, chunk_meta, chunk_state, prev_child_index); + SetChildIndex(base_child_index, child_idx, child_index); + } + GetVectorData(index).child_index = base_child_index; + } + return index; +} + +VectorDataIndex ColumnDataCollectionSegment::AllocateVector(const LogicalType &type, ChunkMetaData &chunk_meta, + ColumnDataAppendState &append_state, + VectorDataIndex prev_index) { + return AllocateVector(type, chunk_meta, &append_state.current_chunk_state, prev_index); +} + +void ColumnDataCollectionSegment::AllocateNewChunk() { + ChunkMetaData meta_data; + meta_data.count = 0; + meta_data.vector_data.reserve(types.size()); + for (idx_t i = 0; i < types.size(); i++) { + auto vector_idx = AllocateVector(types[i], meta_data); + meta_data.vector_data.push_back(vector_idx); + } + chunk_data.push_back(move(meta_data)); +} + +void ColumnDataCollectionSegment::InitializeChunkState(idx_t chunk_index, ChunkManagementState &state) { + auto &chunk = chunk_data[chunk_index]; + allocator->InitializeChunkState(state, chunk); +} + +VectorDataIndex ColumnDataCollectionSegment::GetChildIndex(VectorChildIndex index, idx_t child_entry) { + D_ASSERT(index.IsValid()); + D_ASSERT(index.index + child_entry < child_indices.size()); + return VectorDataIndex(child_indices[index.index + child_entry]); +} + +VectorChildIndex ColumnDataCollectionSegment::AddChildIndex(VectorDataIndex index) { + auto result = child_indices.size(); + child_indices.push_back(index); + return VectorChildIndex(result); +} + +VectorChildIndex ColumnDataCollectionSegment::ReserveChildren(idx_t child_count) { + auto result = child_indices.size(); + for (idx_t i = 0; i < child_count; i++) { + child_indices.emplace_back(); + } + return VectorChildIndex(result); +} + +void ColumnDataCollectionSegment::SetChildIndex(VectorChildIndex base_idx, idx_t child_number, VectorDataIndex index) { + D_ASSERT(base_idx.IsValid()); + D_ASSERT(index.IsValid()); + D_ASSERT(base_idx.index + child_number < child_indices.size()); + child_indices[base_idx.index + child_number] = index; +} + +idx_t ColumnDataCollectionSegment::ReadVectorInternal(ChunkManagementState &state, VectorDataIndex vector_index, + Vector &result) { + auto &vector_type = result.GetType(); + auto internal_type = vector_type.InternalType(); + auto type_size = GetTypeIdSize(internal_type); + auto &vdata = GetVectorData(vector_index); + + auto base_ptr = allocator->GetDataPointer(state, vdata.block_id, vdata.offset); + auto validity_data = GetValidityPointer(base_ptr, type_size); + if (!vdata.next_data.IsValid() && state.properties != ColumnDataScanProperties::DISALLOW_ZERO_COPY) { + // no next data, we can do a zero-copy read of this vector + FlatVector::SetData(result, base_ptr); + FlatVector::Validity(result).Initialize(validity_data); + return vdata.count; + } + + // the data for this vector is spread over multiple vector data entries + // we need to copy over the data for each of the vectors + // first figure out how many rows we need to copy by looping over all of the child vector indexes + idx_t vector_count = 0; + auto next_index = vector_index; + while (next_index.IsValid()) { + auto ¤t_vdata = GetVectorData(next_index); + vector_count += current_vdata.count; + next_index = current_vdata.next_data; + } + // resize the result vector + result.Resize(0, vector_count); + next_index = vector_index; + // now perform the copy of each of the vectors + auto target_data = FlatVector::GetData(result); + auto &target_validity = FlatVector::Validity(result); + idx_t current_offset = 0; + while (next_index.IsValid()) { + auto ¤t_vdata = GetVectorData(next_index); + base_ptr = allocator->GetDataPointer(state, current_vdata.block_id, current_vdata.offset); + validity_data = GetValidityPointer(base_ptr, type_size); + if (type_size > 0) { + memcpy(target_data + current_offset * type_size, base_ptr, current_vdata.count * type_size); + } + // FIXME: use bitwise operations here + ValidityMask current_validity(validity_data); + for (idx_t k = 0; k < current_vdata.count; k++) { + target_validity.Set(current_offset + k, current_validity.RowIsValid(k)); + } + current_offset += current_vdata.count; + next_index = current_vdata.next_data; + } + return vector_count; +} + +idx_t ColumnDataCollectionSegment::ReadVector(ChunkManagementState &state, VectorDataIndex vector_index, + Vector &result) { + auto &vector_type = result.GetType(); + auto internal_type = vector_type.InternalType(); + auto &vdata = GetVectorData(vector_index); + if (vdata.count == 0) { + return 0; + } + auto count = ReadVectorInternal(state, vector_index, result); + if (internal_type == PhysicalType::LIST) { + // list: copy child + auto &child_vector = ListVector::GetEntry(result); + auto child_count = ReadVector(state, GetChildIndex(vdata.child_index), child_vector); + ListVector::SetListSize(result, child_count); + } else if (internal_type == PhysicalType::STRUCT) { + auto &child_vectors = StructVector::GetEntries(result); + for (idx_t child_idx = 0; child_idx < child_vectors.size(); child_idx++) { + auto child_count = + ReadVector(state, GetChildIndex(vdata.child_index, child_idx), *child_vectors[child_idx]); + if (child_count != count) { + throw InternalException("Column Data Collection: mismatch in struct child sizes"); + } + } + } + return count; +} + +void ColumnDataCollectionSegment::ReadChunk(idx_t chunk_index, ChunkManagementState &state, DataChunk &chunk, + const vector &column_ids) { + D_ASSERT(chunk.ColumnCount() == column_ids.size()); + D_ASSERT(state.properties != ColumnDataScanProperties::INVALID); + InitializeChunkState(chunk_index, state); + auto &chunk_meta = chunk_data[chunk_index]; + for (idx_t i = 0; i < column_ids.size(); i++) { + auto vector_idx = column_ids[i]; + D_ASSERT(vector_idx < chunk_meta.vector_data.size()); + ReadVector(state, chunk_meta.vector_data[vector_idx], chunk.data[i]); + } + chunk.SetCardinality(chunk_meta.count); +} + +idx_t ColumnDataCollectionSegment::ChunkCount() const { + return chunk_data.size(); +} + +void ColumnDataCollectionSegment::FetchChunk(idx_t chunk_idx, DataChunk &result) { + vector column_ids; + column_ids.reserve(types.size()); + for (idx_t i = 0; i < types.size(); i++) { + column_ids.push_back(i); + } + FetchChunk(chunk_idx, result, column_ids); +} + +void ColumnDataCollectionSegment::FetchChunk(idx_t chunk_idx, DataChunk &result, const vector &column_ids) { + D_ASSERT(chunk_idx < chunk_data.size()); + ChunkManagementState state; + InitializeChunkState(chunk_idx, state); + state.properties = ColumnDataScanProperties::DISALLOW_ZERO_COPY; + ReadChunk(chunk_idx, state, result, column_ids); +} + +void ColumnDataCollectionSegment::Verify() { +#ifdef DEBUG + idx_t total_count = 0; + for (idx_t i = 0; i < chunk_data.size(); i++) { + total_count += chunk_data[i].count; + } + D_ASSERT(total_count == this->count); +#endif +} + +} // namespace duckdb + + + + + + + //===----------------------------------------------------------------------===// @@ -42424,6 +47179,17 @@ struct ArrowAuxiliaryData : VectorAuxiliaryData { } // namespace duckdb + + + + + + + + + + + namespace duckdb { DataChunk::DataChunk() : count(0), capacity(STANDARD_VECTOR_SIZE) { @@ -42441,17 +47207,21 @@ void DataChunk::InitializeEmpty(const vector &types) { } } -void DataChunk::Initialize(const vector &types) { +void DataChunk::Initialize(Allocator &allocator, const vector &types) { D_ASSERT(data.empty()); // can only be initialized once D_ASSERT(!types.empty()); // empty chunk not allowed capacity = STANDARD_VECTOR_SIZE; for (idx_t i = 0; i < types.size(); i++) { - VectorCache cache(types[i]); + VectorCache cache(allocator, types[i]); data.emplace_back(cache); vector_caches.push_back(move(cache)); } } +void DataChunk::Initialize(ClientContext &context, const vector &types) { + Initialize(Allocator::Get(context), types); +} + void DataChunk::Reset() { if (data.empty()) { return; @@ -42482,6 +47252,15 @@ void DataChunk::SetValue(idx_t col_idx, idx_t index, const Value &val) { data[col_idx].SetValue(index, val); } +bool DataChunk::AllConstant() const { + for (auto &v : data) { + if (v.GetVectorType() != VectorType::CONSTANT_VECTOR) { + return false; + } + } + return true; +} + void DataChunk::Reference(DataChunk &chunk) { D_ASSERT(chunk.ColumnCount() <= ColumnCount()); SetCardinality(chunk); @@ -42550,6 +47329,18 @@ void DataChunk::Fuse(DataChunk &other) { other.Destroy(); } +void DataChunk::ReferenceColumns(DataChunk &other, vector column_ids) { + D_ASSERT(ColumnCount() == column_ids.size()); + Reset(); + for (idx_t col_idx = 0; col_idx < ColumnCount(); col_idx++) { + auto &other_col = other.data[column_ids[col_idx]]; + auto &this_col = data[col_idx]; + D_ASSERT(other_col.GetType() == this_col.GetType()); + this_col.Reference(other_col); + } + SetCardinality(other.size()); +} + void DataChunk::Append(const DataChunk &other, bool resize, SelectionVector *sel, idx_t sel_count) { idx_t new_size = sel ? size() + sel_count : size() + other.size(); if (other.size() == 0) { @@ -42560,10 +47351,11 @@ void DataChunk::Append(const DataChunk &other, bool resize, SelectionVector *sel } if (new_size > capacity) { if (resize) { + auto new_capacity = NextPowerOfTwo(new_size); for (idx_t i = 0; i < ColumnCount(); i++) { - data[i].Resize(size(), new_size); + data[i].Resize(size(), new_capacity); } - capacity = new_size; + capacity = new_capacity; } else { throw InternalException("Can't append chunk to other chunk without resizing"); } @@ -42579,9 +47371,9 @@ void DataChunk::Append(const DataChunk &other, bool resize, SelectionVector *sel SetCardinality(new_size); } -void DataChunk::Normalify() { +void DataChunk::Flatten() { for (idx_t i = 0; i < ColumnCount(); i++) { - data[i].Normalify(size()); + data[i].Flatten(size()); } } @@ -42623,7 +47415,7 @@ void DataChunk::Deserialize(Deserializer &source) { for (idx_t i = 0; i < column_count; i++) { types.push_back(LogicalType::Deserialize(source)); } - Initialize(types); + Initialize(Allocator::DefaultAllocator(), types); // now load the column data SetCardinality(rows); for (idx_t i = 0; i < column_count; i++) { @@ -42655,16 +47447,16 @@ void DataChunk::Slice(DataChunk &other, const SelectionVector &sel, idx_t count_ } } -unique_ptr DataChunk::Orrify() { - auto orrified_data = unique_ptr(new VectorData[ColumnCount()]); +unique_ptr DataChunk::ToUnifiedFormat() { + auto orrified_data = unique_ptr(new UnifiedVectorFormat[ColumnCount()]); for (idx_t col_idx = 0; col_idx < ColumnCount(); col_idx++) { - data[col_idx].Orrify(size(), orrified_data[col_idx]); + data[col_idx].ToUnifiedFormat(size(), orrified_data[col_idx]); } return orrified_data; } void DataChunk::Hash(Vector &result) { - D_ASSERT(result.GetType().id() == LogicalTypeId::HASH); + D_ASSERT(result.GetType().id() == LogicalType::HASH); VectorOperations::Hash(data[0], result, size()); for (idx_t i = 1; i < ColumnCount(); i++) { VectorOperations::CombineHash(result, data[i], size()); @@ -42685,467 +47477,6 @@ void DataChunk::Print() { Printer::Print(ToString()); } -struct DuckDBArrowArrayChildHolder { - ArrowArray array; - //! need max three pointers for strings - duckdb::array buffers = {{nullptr, nullptr, nullptr}}; - unique_ptr vector; - unique_ptr offsets; - unique_ptr data; - //! Children of nested structures - ::duckdb::vector children; - ::duckdb::vector children_ptrs; -}; - -struct DuckDBArrowArrayHolder { - vector children = {}; - vector children_ptrs = {}; - array buffers = {{nullptr}}; - vector> arrow_original_array; -}; - -static void ReleaseDuckDBArrowArray(ArrowArray *array) { - if (!array || !array->release) { - return; - } - array->release = nullptr; - auto holder = static_cast(array->private_data); - delete holder; -} - -void InitializeChild(DuckDBArrowArrayChildHolder &child_holder, idx_t size) { - auto &child = child_holder.array; - child.private_data = nullptr; - child.release = ReleaseDuckDBArrowArray; - child.n_children = 0; - child.null_count = 0; - child.offset = 0; - child.dictionary = nullptr; - child.buffers = child_holder.buffers.data(); - - child.length = size; -} - -void SetChildValidityMask(Vector &vector, ArrowArray &child) { - D_ASSERT(vector.GetVectorType() == VectorType::FLAT_VECTOR); - auto &mask = FlatVector::Validity(vector); - if (!mask.AllValid()) { - //! any bits are set: might have nulls - child.null_count = -1; - } else { - //! no bits are set; we know there are no nulls - child.null_count = 0; - } - child.buffers[0] = (void *)mask.GetData(); -} - -void SetArrowChild(DuckDBArrowArrayChildHolder &child_holder, const LogicalType &type, Vector &data, idx_t size); - -void SetList(DuckDBArrowArrayChildHolder &child_holder, const LogicalType &type, Vector &data, idx_t size) { - auto &child = child_holder.array; - child_holder.vector = make_unique(data); - - //! Lists have two buffers - child.n_buffers = 2; - //! Second Buffer is the list offsets - child_holder.offsets = unique_ptr(new data_t[sizeof(uint32_t) * (size + 1)]); - child.buffers[1] = child_holder.offsets.get(); - auto offset_ptr = (uint32_t *)child.buffers[1]; - auto list_data = FlatVector::GetData(data); - auto list_mask = FlatVector::Validity(data); - idx_t offset = 0; - offset_ptr[0] = 0; - for (idx_t i = 0; i < size; i++) { - auto &le = list_data[i]; - - if (list_mask.RowIsValid(i)) { - offset += le.length; - } - - offset_ptr[i + 1] = offset; - } - auto list_size = ListVector::GetListSize(data); - child_holder.children.resize(1); - InitializeChild(child_holder.children[0], list_size); - child.n_children = 1; - child_holder.children_ptrs.push_back(&child_holder.children[0].array); - child.children = &child_holder.children_ptrs[0]; - auto &child_vector = ListVector::GetEntry(data); - auto &child_type = ListType::GetChildType(type); - SetArrowChild(child_holder.children[0], child_type, child_vector, list_size); - SetChildValidityMask(child_vector, child_holder.children[0].array); -} - -void SetStruct(DuckDBArrowArrayChildHolder &child_holder, const LogicalType &type, Vector &data, idx_t size) { - auto &child = child_holder.array; - child_holder.vector = make_unique(data); - - //! Structs only have validity buffers - child.n_buffers = 1; - auto &children = StructVector::GetEntries(*child_holder.vector); - child.n_children = children.size(); - child_holder.children.resize(child.n_children); - for (auto &struct_child : child_holder.children) { - InitializeChild(struct_child, size); - child_holder.children_ptrs.push_back(&struct_child.array); - } - child.children = &child_holder.children_ptrs[0]; - for (idx_t child_idx = 0; child_idx < child_holder.children.size(); child_idx++) { - SetArrowChild(child_holder.children[child_idx], StructType::GetChildType(type, child_idx), *children[child_idx], - size); - SetChildValidityMask(*children[child_idx], child_holder.children[child_idx].array); - } -} - -void SetStructMap(DuckDBArrowArrayChildHolder &child_holder, const LogicalType &type, Vector &data, idx_t size) { - auto &child = child_holder.array; - child_holder.vector = make_unique(data); - - //! Structs only have validity buffers - child.n_buffers = 1; - auto &children = StructVector::GetEntries(*child_holder.vector); - child.n_children = children.size(); - child_holder.children.resize(child.n_children); - auto list_size = ListVector::GetListSize(*children[0]); - child.length = list_size; - for (auto &struct_child : child_holder.children) { - InitializeChild(struct_child, list_size); - child_holder.children_ptrs.push_back(&struct_child.array); - } - child.children = &child_holder.children_ptrs[0]; - auto &child_types = StructType::GetChildTypes(type); - for (idx_t child_idx = 0; child_idx < child_holder.children.size(); child_idx++) { - auto &list_vector_child = ListVector::GetEntry(*children[child_idx]); - if (child_idx == 0) { - VectorData list_data; - children[child_idx]->Orrify(size, list_data); - auto list_child_validity = FlatVector::Validity(list_vector_child); - if (!list_child_validity.AllValid()) { - //! Get the offsets to check from the selection vector - auto list_offsets = FlatVector::GetData(*children[child_idx]); - for (idx_t list_idx = 0; list_idx < size; list_idx++) { - auto offset = list_offsets[list_data.sel->get_index(list_idx)]; - if (!list_child_validity.CheckAllValid(offset.length + offset.offset, offset.offset)) { - throw std::runtime_error("Arrow doesnt accept NULL keys on Maps"); - } - } - } - } else { - SetChildValidityMask(list_vector_child, child_holder.children[child_idx].array); - } - SetArrowChild(child_holder.children[child_idx], ListType::GetChildType(child_types[child_idx].second), - list_vector_child, list_size); - } -} - -struct ArrowUUIDConversion { - using internal_type_t = hugeint_t; - - static unique_ptr InitializeVector(Vector &data, idx_t size) { - return make_unique(LogicalType::VARCHAR, size); - } - - static idx_t GetStringLength(hugeint_t value) { - return UUID::STRING_SIZE; - } - - static string_t ConvertValue(Vector &tgt_vec, string_t *tgt_ptr, internal_type_t *src_ptr, idx_t row) { - auto str_value = UUID::ToString(src_ptr[row]); - // Have to store this string - tgt_ptr[row] = StringVector::AddStringOrBlob(tgt_vec, str_value); - return tgt_ptr[row]; - } -}; - -struct ArrowVarcharConversion { - using internal_type_t = string_t; - - static unique_ptr InitializeVector(Vector &data, idx_t size) { - return make_unique(data); - } - static idx_t GetStringLength(string_t value) { - return value.GetSize(); - } - - static string_t ConvertValue(Vector &tgt_vec, string_t *tgt_ptr, internal_type_t *src_ptr, idx_t row) { - return src_ptr[row]; - } -}; - -template -void SetVarchar(DuckDBArrowArrayChildHolder &child_holder, const LogicalType &type, Vector &data, idx_t size) { - auto &child = child_holder.array; - child_holder.vector = CONVERT::InitializeVector(data, size); - auto target_data_ptr = FlatVector::GetData(data); - child.n_buffers = 3; - child_holder.offsets = unique_ptr(new data_t[sizeof(uint32_t) * (size + 1)]); - child.buffers[1] = child_holder.offsets.get(); - D_ASSERT(child.buffers[1]); - //! step 1: figure out total string length: - idx_t total_string_length = 0; - auto source_ptr = FlatVector::GetData(data); - auto &mask = FlatVector::Validity(data); - for (idx_t row_idx = 0; row_idx < size; row_idx++) { - if (!mask.RowIsValid(row_idx)) { - continue; - } - total_string_length += CONVERT::GetStringLength(source_ptr[row_idx]); - } - //! step 2: allocate this much - child_holder.data = unique_ptr(new data_t[total_string_length]); - child.buffers[2] = child_holder.data.get(); - D_ASSERT(child.buffers[2]); - //! step 3: assign buffers - idx_t current_heap_offset = 0; - auto target_ptr = (uint32_t *)child.buffers[1]; - - for (idx_t row_idx = 0; row_idx < size; row_idx++) { - target_ptr[row_idx] = current_heap_offset; - if (!mask.RowIsValid(row_idx)) { - continue; - } - string_t str = CONVERT::ConvertValue(*child_holder.vector, target_data_ptr, source_ptr, row_idx); - memcpy((void *)((uint8_t *)child.buffers[2] + current_heap_offset), str.GetDataUnsafe(), str.GetSize()); - current_heap_offset += str.GetSize(); - } - target_ptr[size] = current_heap_offset; //! need to terminate last string! -} - -void SetArrowChild(DuckDBArrowArrayChildHolder &child_holder, const LogicalType &type, Vector &data, idx_t size) { - auto &child = child_holder.array; - switch (type.id()) { - case LogicalTypeId::BOOLEAN: { - //! Gotta bitpack these booleans - child_holder.vector = make_unique(data); - child.n_buffers = 2; - idx_t num_bytes = (size + 8 - 1) / 8; - child_holder.data = unique_ptr(new data_t[sizeof(uint8_t) * num_bytes]); - child.buffers[1] = child_holder.data.get(); - auto source_ptr = FlatVector::GetData(*child_holder.vector); - auto target_ptr = (uint8_t *)child.buffers[1]; - idx_t target_pos = 0; - idx_t cur_bit = 0; - for (idx_t row_idx = 0; row_idx < size; row_idx++) { - if (cur_bit == 8) { - target_pos++; - cur_bit = 0; - } - if (source_ptr[row_idx] == 0) { - //! We set the bit to 0 - target_ptr[target_pos] &= ~(1 << cur_bit); - } else { - //! We set the bit to 1 - target_ptr[target_pos] |= 1 << cur_bit; - } - cur_bit++; - } - break; - } - case LogicalTypeId::TINYINT: - case LogicalTypeId::SMALLINT: - case LogicalTypeId::INTEGER: - case LogicalTypeId::BIGINT: - case LogicalTypeId::UTINYINT: - case LogicalTypeId::USMALLINT: - case LogicalTypeId::UINTEGER: - case LogicalTypeId::UBIGINT: - case LogicalTypeId::FLOAT: - case LogicalTypeId::DOUBLE: - case LogicalTypeId::HUGEINT: - case LogicalTypeId::DATE: - case LogicalTypeId::TIMESTAMP: - case LogicalTypeId::TIMESTAMP_MS: - case LogicalTypeId::TIMESTAMP_NS: - case LogicalTypeId::TIMESTAMP_SEC: - case LogicalTypeId::TIME: - case LogicalTypeId::TIMESTAMP_TZ: - case LogicalTypeId::TIME_TZ: - child_holder.vector = make_unique(data); - child.n_buffers = 2; - child.buffers[1] = (void *)FlatVector::GetData(*child_holder.vector); - break; - case LogicalTypeId::SQLNULL: - child.n_buffers = 1; - break; - case LogicalTypeId::DECIMAL: { - child.n_buffers = 2; - child_holder.vector = make_unique(data); - - //! We have to convert to INT128 - switch (type.InternalType()) { - - case PhysicalType::INT16: { - child_holder.data = unique_ptr(new data_t[sizeof(hugeint_t) * (size)]); - child.buffers[1] = child_holder.data.get(); - auto source_ptr = FlatVector::GetData(*child_holder.vector); - auto target_ptr = (hugeint_t *)child.buffers[1]; - for (idx_t row_idx = 0; row_idx < size; row_idx++) { - target_ptr[row_idx] = source_ptr[row_idx]; - } - break; - } - case PhysicalType::INT32: { - child_holder.data = unique_ptr(new data_t[sizeof(hugeint_t) * (size)]); - child.buffers[1] = child_holder.data.get(); - auto source_ptr = FlatVector::GetData(*child_holder.vector); - auto target_ptr = (hugeint_t *)child.buffers[1]; - for (idx_t row_idx = 0; row_idx < size; row_idx++) { - target_ptr[row_idx] = source_ptr[row_idx]; - } - break; - } - case PhysicalType::INT64: { - child_holder.data = unique_ptr(new data_t[sizeof(hugeint_t) * (size)]); - child.buffers[1] = child_holder.data.get(); - auto source_ptr = FlatVector::GetData(*child_holder.vector); - auto target_ptr = (hugeint_t *)child.buffers[1]; - for (idx_t row_idx = 0; row_idx < size; row_idx++) { - target_ptr[row_idx] = source_ptr[row_idx]; - } - break; - } - case PhysicalType::INT128: { - child.buffers[1] = (void *)FlatVector::GetData(*child_holder.vector); - break; - } - default: - throw std::runtime_error("Unsupported physical type for Decimal" + TypeIdToString(type.InternalType())); - } - break; - } - case LogicalTypeId::BLOB: - case LogicalTypeId::JSON: - case LogicalTypeId::VARCHAR: { - SetVarchar(child_holder, type, data, size); - break; - } - case LogicalTypeId::UUID: { - SetVarchar(child_holder, type, data, size); - break; - } - case LogicalTypeId::LIST: { - SetList(child_holder, type, data, size); - break; - } - case LogicalTypeId::STRUCT: { - SetStruct(child_holder, type, data, size); - break; - } - case LogicalTypeId::MAP: { - child_holder.vector = make_unique(data); - - auto &map_mask = FlatVector::Validity(*child_holder.vector); - child.n_buffers = 2; - //! Maps have one child - child.n_children = 1; - child_holder.children.resize(1); - InitializeChild(child_holder.children[0], size); - child_holder.children_ptrs.push_back(&child_holder.children[0].array); - //! Second Buffer is the offsets - child_holder.offsets = unique_ptr(new data_t[sizeof(uint32_t) * (size + 1)]); - child.buffers[1] = child_holder.offsets.get(); - auto &struct_children = StructVector::GetEntries(data); - auto offset_ptr = (uint32_t *)child.buffers[1]; - auto list_data = FlatVector::GetData(*struct_children[0]); - idx_t offset = 0; - offset_ptr[0] = 0; - for (idx_t i = 0; i < size; i++) { - auto &le = list_data[i]; - if (map_mask.RowIsValid(i)) { - offset += le.length; - } - offset_ptr[i + 1] = offset; - } - child.children = &child_holder.children_ptrs[0]; - //! We need to set up a struct - auto struct_type = LogicalType::STRUCT(StructType::GetChildTypes(type)); - - SetStructMap(child_holder.children[0], struct_type, *child_holder.vector, size); - break; - } - case LogicalTypeId::INTERVAL: { - //! convert interval from month/days/ucs to milliseconds - child_holder.vector = make_unique(data); - child.n_buffers = 2; - child_holder.data = unique_ptr(new data_t[sizeof(int64_t) * (size)]); - child.buffers[1] = child_holder.data.get(); - auto source_ptr = FlatVector::GetData(*child_holder.vector); - auto target_ptr = (int64_t *)child.buffers[1]; - for (idx_t row_idx = 0; row_idx < size; row_idx++) { - target_ptr[row_idx] = Interval::GetMilli(source_ptr[row_idx]); - } - break; - } - case LogicalTypeId::ENUM: { - // We need to initialize our dictionary - child_holder.children.resize(1); - idx_t dict_size = EnumType::GetSize(type); - InitializeChild(child_holder.children[0], dict_size); - Vector dictionary(EnumType::GetValuesInsertOrder(type)); - SetArrowChild(child_holder.children[0], dictionary.GetType(), dictionary, dict_size); - child_holder.children_ptrs.push_back(&child_holder.children[0].array); - - // now we set the data - child.dictionary = child_holder.children_ptrs[0]; - child_holder.vector = make_unique(data); - child.n_buffers = 2; - child.buffers[1] = (void *)FlatVector::GetData(*child_holder.vector); - - break; - } - default: - throw std::runtime_error("Unsupported type " + type.ToString()); - } -} - -void DataChunk::ToArrowArray(ArrowArray *out_array) { - Normalify(); - D_ASSERT(out_array); - - // Allocate as unique_ptr first to cleanup properly on error - auto root_holder = make_unique(); - - // Allocate the children - root_holder->children.resize(ColumnCount()); - root_holder->children_ptrs.resize(ColumnCount(), nullptr); - for (size_t i = 0; i < ColumnCount(); ++i) { - root_holder->children_ptrs[i] = &root_holder->children[i].array; - } - out_array->children = root_holder->children_ptrs.data(); - out_array->n_children = ColumnCount(); - - // Configure root array - out_array->length = size(); - out_array->n_children = ColumnCount(); - out_array->n_buffers = 1; - out_array->buffers = root_holder->buffers.data(); // there is no actual buffer there since we don't have NULLs - out_array->offset = 0; - out_array->null_count = 0; // needs to be 0 - out_array->dictionary = nullptr; - - //! Configure child arrays - for (idx_t col_idx = 0; col_idx < ColumnCount(); col_idx++) { - auto &child_holder = root_holder->children[col_idx]; - InitializeChild(child_holder, size()); - auto &vector = child_holder.vector; - auto &child = child_holder.array; - auto vec_buffer = data[col_idx].GetBuffer(); - if (vec_buffer->GetAuxiliaryData() && - vec_buffer->GetAuxiliaryDataType() == VectorAuxiliaryDataType::ARROW_AUXILIARY) { - auto arrow_aux_data = (ArrowAuxiliaryData *)vec_buffer->GetAuxiliaryData(); - root_holder->arrow_original_array.push_back(arrow_aux_data->arrow_array); - } - //! We could, in theory, output other types of vectors here, currently only FLAT Vectors - SetArrowChild(child_holder, GetTypes()[col_idx], data[col_idx], size()); - SetChildValidityMask(*vector, child); - out_array->children[col_idx] = &child; - } - - // Release ownership to caller - out_array->private_data = root_holder.release(); - out_array->release = ReleaseDuckDBArrowArray; -} - } // namespace duckdb @@ -43164,6 +47495,10 @@ namespace duckdb { static_assert(sizeof(date_t) == sizeof(int32_t), "date_t was padded"); +const char *Date::PINF = "infinity"; // NOLINT +const char *Date::NINF = "-infinity"; // NOLINT +const char *Date::EPOCH = "epoch"; // NOLINT + const string_t Date::MONTH_NAMES_ABBREVIATED[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; const string_t Date::MONTH_NAMES[] = {"January", "February", "March", "April", "May", "June", @@ -43375,9 +47710,9 @@ bool Date::TryConvertDate(const char *buf, idx_t len, idx_t &pos, date_t &result } if (!StringUtil::CharacterIsDigit(buf[pos])) { // Check for special values - if (TryConvertDateSpecial(buf, len, pos, "infinity")) { + if (TryConvertDateSpecial(buf, len, pos, PINF)) { result = yearneg ? date_t::ninfinity() : date_t::infinity(); - } else if (TryConvertDateSpecial(buf, len, pos, "epoch")) { + } else if (TryConvertDateSpecial(buf, len, pos, EPOCH)) { result = date_t::epoch(); } else { return false; @@ -43490,9 +47825,9 @@ string Date::ToString(date_t date) { // PG displays temporal infinities in lowercase, // but numerics in Titlecase. if (date == date_t::infinity()) { - return "infinity"; + return PINF; } else if (date == date_t::ninfinity()) { - return "-infinity"; + return NINF; } int32_t date_units[3]; idx_t year_length; @@ -43717,29 +48052,29 @@ date_t Date::GetMondayOfCurrentWeek(date_t date) { namespace duckdb { template -string TemplatedDecimalToString(SIGNED value, uint8_t scale) { - auto len = DecimalToString::DecimalLength(value, scale); +string TemplatedDecimalToString(SIGNED value, uint8_t width, uint8_t scale) { + auto len = DecimalToString::DecimalLength(value, width, scale); auto data = unique_ptr(new char[len + 1]); - DecimalToString::FormatDecimal(value, scale, data.get(), len); + DecimalToString::FormatDecimal(value, width, scale, data.get(), len); return string(data.get(), len); } -string Decimal::ToString(int16_t value, uint8_t scale) { - return TemplatedDecimalToString(value, scale); +string Decimal::ToString(int16_t value, uint8_t width, uint8_t scale) { + return TemplatedDecimalToString(value, width, scale); } -string Decimal::ToString(int32_t value, uint8_t scale) { - return TemplatedDecimalToString(value, scale); +string Decimal::ToString(int32_t value, uint8_t width, uint8_t scale) { + return TemplatedDecimalToString(value, width, scale); } -string Decimal::ToString(int64_t value, uint8_t scale) { - return TemplatedDecimalToString(value, scale); +string Decimal::ToString(int64_t value, uint8_t width, uint8_t scale) { + return TemplatedDecimalToString(value, width, scale); } -string Decimal::ToString(hugeint_t value, uint8_t scale) { - auto len = HugeintToStringCast::DecimalLength(value, scale); +string Decimal::ToString(hugeint_t value, uint8_t width, uint8_t scale) { + auto len = HugeintToStringCast::DecimalLength(value, width, scale); auto data = unique_ptr(new char[len + 1]); - HugeintToStringCast::FormatDecimal(value, scale, data.get(), len); + HugeintToStringCast::FormatDecimal(value, width, scale, data.get(), len); return string(data.get(), len); } @@ -44619,133 +48954,7 @@ string hugeint_t::ToString() const { } } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/types/hyperloglog.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -// LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7 -// See the end of this file for a list - -//===----------------------------------------------------------------------===// -// DuckDB -// -// third_party/hyperloglog/hyperloglog.hpp -// -// -//===----------------------------------------------------------------------===// - - - -#include -#include - -namespace duckdb_hll { - -/* Error codes */ -#define HLL_C_OK 0 -#define HLL_C_ERR -1 - -typedef struct { - void *ptr; -} robj; - -//! Create a new empty HyperLogLog object -robj *hll_create(void); -//! Convert hll from sparse to dense -int hllSparseToDense(robj *o); -//! Destroy the specified HyperLogLog object -void hll_destroy(robj *obj); -//! Add an element with the specified amount of bytes to the HyperLogLog. Returns C_ERR on failure, otherwise returns 0 -//! if the cardinality did not change, and 1 otherwise. -int hll_add(robj *o, unsigned char *ele, size_t elesize); -//! Returns the estimated amount of unique elements seen by the HyperLogLog. Returns C_OK on success, or C_ERR on -//! failure. -int hll_count(robj *o, size_t *result); -//! Merge hll_count HyperLogLog objects into a single one. Returns NULL on failure, or the new HLL object on success. -robj *hll_merge(robj **hlls, size_t hll_count); -//! Get size (in bytes) of the HLL -uint64_t get_size(); - -uint64_t MurmurHash64A(const void *key, int len, unsigned int seed); - -} // namespace duckdb_hll - -namespace duckdb { - -void AddToLogsInternal(VectorData &vdata, idx_t count, uint64_t indices[], uint8_t counts[], void ***logs[], - const SelectionVector *log_sel); - -void AddToSingleLogInternal(VectorData &vdata, idx_t count, uint64_t indices[], uint8_t counts[], void *log); - -} // namespace duckdb - - -// LICENSE_CHANGE_END - - -namespace duckdb { - -enum class HLLStorageType { UNCOMPRESSED = 1 }; - -class FieldWriter; -class FieldReader; - -//! The HyperLogLog class holds a HyperLogLog counter for approximate cardinality counting -class HyperLogLog { -public: - HyperLogLog(); - ~HyperLogLog(); - // implicit copying of HyperLogLog is not allowed - HyperLogLog(const HyperLogLog &) = delete; - - //! Adds an element of the specified size to the HyperLogLog counter - void Add(data_ptr_t element, idx_t size); - //! Return the count of this HyperLogLog counter - idx_t Count() const; - //! Merge this HyperLogLog counter with another counter to create a new one - unique_ptr Merge(HyperLogLog &other); - HyperLogLog *MergePointer(HyperLogLog &other); - //! Merge a set of HyperLogLogs to create one big one - static unique_ptr Merge(HyperLogLog logs[], idx_t count); - //! Get the size (in bytes) of a HLL - static idx_t GetSize(); - //! Get pointer to the HLL - data_ptr_t GetPtr() const; - //! Get copy of the HLL - unique_ptr Copy(); - //! (De)Serialize the HLL - void Serialize(FieldWriter &writer) const; - static unique_ptr Deserialize(FieldReader &reader); - -public: - //! Compute HLL hashes over vdata, and store them in 'hashes' - //! Then, compute register indices and prefix lengths, and also store them in 'hashes' as a pair of uint32_t - static void ProcessEntries(VectorData &vdata, const LogicalType &type, uint64_t hashes[], uint8_t counts[], - idx_t count); - //! Add the indices and counts to the logs - static void AddToLogs(VectorData &vdata, idx_t count, uint64_t indices[], uint8_t counts[], HyperLogLog **logs[], - const SelectionVector *log_sel); - //! Add the indices and counts to THIS log - void AddToLog(VectorData &vdata, idx_t count, uint64_t indices[], uint8_t counts[]); - -private: - explicit HyperLogLog(void *hll); - - void *hll; - mutex lock; -}; -} // namespace duckdb @@ -44940,7 +49149,7 @@ inline uint64_t TemplatedHash(const string_t &elem) { } template -void TemplatedComputeHashes(VectorData &vdata, const idx_t &count, uint64_t hashes[]) { +void TemplatedComputeHashes(UnifiedVectorFormat &vdata, const idx_t &count, uint64_t hashes[]) { T *data = (T *)vdata.data; for (idx_t i = 0; i < count; i++) { auto idx = vdata.sel->get_index(i); @@ -44952,7 +49161,7 @@ void TemplatedComputeHashes(VectorData &vdata, const idx_t &count, uint64_t hash } } -static void ComputeHashes(VectorData &vdata, const LogicalType &type, uint64_t hashes[], idx_t count) { +static void ComputeHashes(UnifiedVectorFormat &vdata, const LogicalType &type, uint64_t hashes[], idx_t count) { switch (type.InternalType()) { case PhysicalType::BOOL: case PhysicalType::INT8: @@ -44999,20 +49208,20 @@ static inline void ComputeIndexAndCount(uint64_t &hash, uint8_t &prefix) { hash = index; } -void HyperLogLog::ProcessEntries(VectorData &vdata, const LogicalType &type, uint64_t hashes[], uint8_t counts[], - idx_t count) { +void HyperLogLog::ProcessEntries(UnifiedVectorFormat &vdata, const LogicalType &type, uint64_t hashes[], + uint8_t counts[], idx_t count) { ComputeHashes(vdata, type, hashes, count); for (idx_t i = 0; i < count; i++) { ComputeIndexAndCount(hashes[i], counts[i]); } } -void HyperLogLog::AddToLogs(VectorData &vdata, idx_t count, uint64_t indices[], uint8_t counts[], HyperLogLog **logs[], - const SelectionVector *log_sel) { +void HyperLogLog::AddToLogs(UnifiedVectorFormat &vdata, idx_t count, uint64_t indices[], uint8_t counts[], + HyperLogLog **logs[], const SelectionVector *log_sel) { AddToLogsInternal(vdata, count, indices, counts, (void ****)logs, log_sel); } -void HyperLogLog::AddToLog(VectorData &vdata, idx_t count, uint64_t indices[], uint8_t counts[]) { +void HyperLogLog::AddToLog(UnifiedVectorFormat &vdata, idx_t count, uint64_t indices[], uint8_t counts[]) { lock_guard guard(lock); AddToSingleLogInternal(vdata, count, indices, counts, hll); } @@ -45197,6 +49406,126 @@ dtime_t AddTimeOperator::Operation(interval_t left, dtime_t right); } // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/operator/subtract.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +struct SubtractOperator { + template + static inline TR Operation(TA left, TB right) { + return left - right; + } +}; + +template <> +float SubtractOperator::Operation(float left, float right); +template <> +double SubtractOperator::Operation(double left, double right); +template <> +interval_t SubtractOperator::Operation(interval_t left, interval_t right); +template <> +int64_t SubtractOperator::Operation(date_t left, date_t right); +template <> +date_t SubtractOperator::Operation(date_t left, int32_t right); +template <> +date_t SubtractOperator::Operation(date_t left, interval_t right); +template <> +timestamp_t SubtractOperator::Operation(timestamp_t left, interval_t right); +template <> +interval_t SubtractOperator::Operation(timestamp_t left, timestamp_t right); + +struct TrySubtractOperator { + template + static inline bool Operation(TA left, TB right, TR &result) { + throw InternalException("Unimplemented type for TrySubtractOperator"); + } +}; + +template <> +bool TrySubtractOperator::Operation(uint8_t left, uint8_t right, uint8_t &result); +template <> +bool TrySubtractOperator::Operation(uint16_t left, uint16_t right, uint16_t &result); +template <> +bool TrySubtractOperator::Operation(uint32_t left, uint32_t right, uint32_t &result); +template <> +bool TrySubtractOperator::Operation(uint64_t left, uint64_t right, uint64_t &result); + +template <> +bool TrySubtractOperator::Operation(int8_t left, int8_t right, int8_t &result); +template <> +bool TrySubtractOperator::Operation(int16_t left, int16_t right, int16_t &result); +template <> +bool TrySubtractOperator::Operation(int32_t left, int32_t right, int32_t &result); +template <> +bool TrySubtractOperator::Operation(int64_t left, int64_t right, int64_t &result); +template <> +bool TrySubtractOperator::Operation(hugeint_t left, hugeint_t right, hugeint_t &result); + +struct SubtractOperatorOverflowCheck { + template + static inline TR Operation(TA left, TB right) { + TR result; + if (!TrySubtractOperator::Operation(left, right, result)) { + throw OutOfRangeException("Overflow in subtraction of %s (%d - %d)!", TypeIdToString(GetTypeId()), left, + right); + } + return result; + } +}; + +struct TryDecimalSubtract { + template + static inline bool Operation(TA left, TB right, TR &result) { + throw InternalException("Unimplemented type for TryDecimalSubtract"); + } +}; + +template <> +bool TryDecimalSubtract::Operation(int16_t left, int16_t right, int16_t &result); +template <> +bool TryDecimalSubtract::Operation(int32_t left, int32_t right, int32_t &result); +template <> +bool TryDecimalSubtract::Operation(int64_t left, int64_t right, int64_t &result); +template <> +bool TryDecimalSubtract::Operation(hugeint_t left, hugeint_t right, hugeint_t &result); + +struct DecimalSubtractOverflowCheck { + template + static inline TR Operation(TA left, TB right) { + TR result; + if (!TryDecimalSubtract::Operation(left, right, result)) { + throw OutOfRangeException("Overflow in subtract of DECIMAL(18) (%d - %d). You might want to add an " + "explicit cast to a bigger decimal.", + left, right); + } + return result; + } +}; + +template <> +hugeint_t DecimalSubtractOverflowCheck::Operation(hugeint_t left, hugeint_t right); + +struct SubtractTimeOperator { + template + static TR Operation(TA left, TB right); +}; + +template <> +dtime_t SubtractTimeOperator::Operation(dtime_t left, interval_t right); + +} // namespace duckdb + namespace duckdb { @@ -45474,6 +49803,7 @@ int64_t Interval::GetNanoseconds(const interval_t &val) { } interval_t Interval::GetAge(timestamp_t timestamp_1, timestamp_t timestamp_2) { + D_ASSERT(Timestamp::IsFinite(timestamp_1) && Timestamp::IsFinite(timestamp_2)); date_t date1, date2; dtime_t time1, time2; @@ -45563,9 +49893,15 @@ interval_t Interval::GetAge(timestamp_t timestamp_1, timestamp_t timestamp_2) { } interval_t Interval::GetDifference(timestamp_t timestamp_1, timestamp_t timestamp_2) { + if (!Timestamp::IsFinite(timestamp_1) || !Timestamp::IsFinite(timestamp_2)) { + throw InvalidInputException("Cannot subtract infinite timestamps"); + } const auto us_1 = Timestamp::GetEpochMicroSeconds(timestamp_1); const auto us_2 = Timestamp::GetEpochMicroSeconds(timestamp_2); - const auto delta_us = us_1 - us_2; + int64_t delta_us; + if (!TrySubtractOperator::Operation(us_1, us_2, delta_us)) { + throw ConversionException("Timestamp difference is out of bounds"); + } return FromMicro(delta_us); } @@ -45619,6 +49955,13 @@ bool Interval::GreaterThanEquals(interval_t left, interval_t right) { return GreaterThan(left, right) || Equals(left, right); } +interval_t Interval::Invert(interval_t interval) { + interval.days = -interval.days; + interval.micros = -interval.micros; + interval.months = -interval.months; + return interval; +} + date_t Interval::Add(date_t left, interval_t right) { if (!Date::IsFinite(left)) { return left; @@ -45728,9 +50071,14 @@ idx_t RowDataCollection::AppendToBlock(RowDataBlock &block, BufferHandle &handle return append_count; } -vector> RowDataCollection::Build(idx_t added_count, data_ptr_t key_locations[], - idx_t entry_sizes[], const SelectionVector *sel) { - vector> handles; +RowDataBlock &RowDataCollection::CreateBlock() { + blocks.push_back(make_unique(buffer_manager, block_capacity, entry_size)); + return *blocks.back(); +} + +vector RowDataCollection::Build(idx_t added_count, data_ptr_t key_locations[], idx_t entry_sizes[], + const SelectionVector *sel) { + vector handles; vector append_entries; // first allocate space of where to serialize the keys and payload columns @@ -45741,29 +50089,28 @@ vector> RowDataCollection::Build(idx_t added_count, dat count += added_count; if (!blocks.empty()) { - auto &last_block = blocks.back(); + auto &last_block = *blocks.back(); if (last_block.count < last_block.capacity) { // last block has space: pin the buffer of this block auto handle = buffer_manager.Pin(last_block.block); // now append to the block - idx_t append_count = AppendToBlock(last_block, *handle, append_entries, remaining, entry_sizes); + idx_t append_count = AppendToBlock(last_block, handle, append_entries, remaining, entry_sizes); remaining -= append_count; handles.push_back(move(handle)); } } while (remaining > 0) { // now for the remaining data, allocate new buffers to store the data and append there - RowDataBlock new_block(buffer_manager, block_capacity, entry_size); + auto &new_block = CreateBlock(); auto handle = buffer_manager.Pin(new_block.block); // offset the entry sizes array if we have added entries already idx_t *offset_entry_sizes = entry_sizes ? entry_sizes + added_count - remaining : nullptr; - idx_t append_count = AppendToBlock(new_block, *handle, append_entries, remaining, offset_entry_sizes); + idx_t append_count = AppendToBlock(new_block, handle, append_entries, remaining, offset_entry_sizes); D_ASSERT(new_block.count > 0); remaining -= append_count; - blocks.push_back(move(new_block)); if (keep_pinned) { pinned_blocks.push_back(move(handle)); } else { @@ -45793,6 +50140,9 @@ vector> RowDataCollection::Build(idx_t added_count, dat } void RowDataCollection::Merge(RowDataCollection &other) { + if (other.count == 0) { + return; + } RowDataCollection temp(buffer_manager, Storage::BLOCK_SIZE, 1); { // One lock at a time to avoid deadlocks @@ -45801,8 +50151,8 @@ void RowDataCollection::Merge(RowDataCollection &other) { temp.block_capacity = other.block_capacity; temp.entry_size = other.entry_size; temp.blocks = move(other.blocks); - other.count = 0; } + other.Clear(); lock_guard write_lock(rdc_lock); count += temp.count; @@ -45820,7 +50170,7 @@ void RowDataCollection::Merge(RowDataCollection &other) { //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/types/row_layout.cpp +// duckdb/common/types/row_data_collection_scanner.hpp // // //===----------------------------------------------------------------------===// @@ -45829,21 +50179,386 @@ void RowDataCollection::Merge(RowDataCollection &other) { + namespace duckdb { -vector AggregateObject::CreateAggregateObjects(const vector &bindings) { - vector aggregates; - for (auto &binding : bindings) { - auto payload_size = binding->function.state_size(); -#ifndef DUCKDB_ALLOW_UNDEFINED - payload_size = AlignValue(payload_size); -#endif - aggregates.emplace_back(binding->function, binding->bind_info.get(), binding->children.size(), payload_size, - binding->distinct, binding->return_type.InternalType(), binding->filter.get()); +class BufferHandle; +class RowDataCollection; +struct RowDataBlock; +class DataChunk; + +//! Used to scan the data into DataChunks after sorting +struct RowDataCollectionScanner { +public: + using Types = vector; + + struct ScanState { + explicit ScanState(const RowDataCollectionScanner &scanner_p) : scanner(scanner_p), block_idx(0), entry_idx(0) { + } + + void PinData(); + + //! The data layout + const RowDataCollectionScanner &scanner; + + idx_t block_idx; + idx_t entry_idx; + + BufferHandle data_handle; + BufferHandle heap_handle; + + // We must pin ALL blocks we are going to gather from + vector pinned_blocks; + }; + + //! Ensure that heap blocks correspond to row blocks + static void AlignHeapBlocks(RowDataCollection &dst_block_collection, RowDataCollection &dst_string_heap, + RowDataCollection &src_block_collection, RowDataCollection &src_string_heap, + const RowLayout &layout); + + RowDataCollectionScanner(RowDataCollection &rows, RowDataCollection &heap, const RowLayout &layout, bool external, + bool flush = true); + + //! The type layout of the payload + inline const vector &GetTypes() const { + return layout.GetTypes(); } - return aggregates; + + //! The number of rows scanned so far + inline idx_t Scanned() const { + return total_scanned; + } + + //! The number of remaining rows + inline idx_t Remaining() const { + return total_count - total_scanned; + } + + //! Swizzle the blocks for external scanning + //! Swizzling is all or nothing, so if we have scanned previously, + //! we need to re-swizzle. + void ReSwizzle(); + + void SwizzleBlock(RowDataBlock &data_block, RowDataBlock &heap_block); + + //! Scans the next data chunk from the sorted data + void Scan(DataChunk &chunk); + +private: + //! The row data being scanned + RowDataCollection &rows; + //! The row heap being scanned + RowDataCollection &heap; + //! The data layout + const RowLayout layout; + //! Read state + ScanState read_state; + //! The total count of sorted_data + const idx_t total_count; + //! The number of rows scanned so far + idx_t total_scanned; + //! Addresses used to gather from the sorted data + Vector addresses = Vector(LogicalType::POINTER); + //! Whether the blocks can be flushed to disk + const bool external; + //! Whether to flush the blocks after scanning + const bool flush; + //! Whether we are unswizzling the blocks + const bool unswizzling; + + //! Checks that the newest block is valid + void ValidateUnscannedBlock() const; +}; + +} // namespace duckdb + + + + + + +namespace duckdb { + +void RowDataCollectionScanner::AlignHeapBlocks(RowDataCollection &swizzled_block_collection, + RowDataCollection &swizzled_string_heap, + RowDataCollection &block_collection, RowDataCollection &string_heap, + const RowLayout &layout) { + if (block_collection.count == 0) { + return; + } + + if (layout.AllConstant()) { + // No heap blocks! Just merge fixed-size data + swizzled_block_collection.Merge(block_collection); + return; + } + + // We create one heap block per data block and swizzle the pointers + D_ASSERT(string_heap.keep_pinned == swizzled_string_heap.keep_pinned); + auto &buffer_manager = block_collection.buffer_manager; + auto &heap_blocks = string_heap.blocks; + idx_t heap_block_idx = 0; + idx_t heap_block_remaining = heap_blocks[heap_block_idx]->count; + for (auto &data_block : block_collection.blocks) { + if (heap_block_remaining == 0) { + heap_block_remaining = heap_blocks[++heap_block_idx]->count; + } + + // Pin the data block and swizzle the pointers within the rows + auto data_handle = buffer_manager.Pin(data_block->block); + auto data_ptr = data_handle.Ptr(); + if (!string_heap.keep_pinned) { + D_ASSERT(!data_block->block->IsSwizzled()); + RowOperations::SwizzleColumns(layout, data_ptr, data_block->count); + data_block->block->SetSwizzling(nullptr); + } + // At this point the data block is pinned and the heap pointer is valid + // so we can copy heap data as needed + + // We want to copy as little of the heap data as possible, check how the data and heap blocks line up + if (heap_block_remaining >= data_block->count) { + // Easy: current heap block contains all strings for this data block, just copy (reference) the block + swizzled_string_heap.blocks.emplace_back(heap_blocks[heap_block_idx]->Copy()); + swizzled_string_heap.blocks.back()->count = data_block->count; + + // Swizzle the heap pointer if we are not pinning the heap + auto &heap_block = swizzled_string_heap.blocks.back()->block; + auto heap_handle = buffer_manager.Pin(heap_block); + if (!swizzled_string_heap.keep_pinned) { + auto heap_ptr = Load(data_ptr + layout.GetHeapOffset()); + auto heap_offset = heap_ptr - heap_handle.Ptr(); + RowOperations::SwizzleHeapPointer(layout, data_ptr, heap_ptr, data_block->count, heap_offset); + } else { + swizzled_string_heap.pinned_blocks.emplace_back(move(heap_handle)); + } + + // Update counter + heap_block_remaining -= data_block->count; + } else { + // Strings for this data block are spread over the current heap block and the next (and possibly more) + if (string_heap.keep_pinned) { + // The heap is changing underneath the data block, + // so swizzle the string pointers to make them portable. + RowOperations::SwizzleColumns(layout, data_ptr, data_block->count); + } + idx_t data_block_remaining = data_block->count; + vector> ptrs_and_sizes; + idx_t total_size = 0; + const auto base_row_ptr = data_ptr; + while (data_block_remaining > 0) { + if (heap_block_remaining == 0) { + heap_block_remaining = heap_blocks[++heap_block_idx]->count; + } + auto next = MinValue(data_block_remaining, heap_block_remaining); + + // Figure out where to start copying strings, and how many bytes we need to copy + auto heap_start_ptr = Load(data_ptr + layout.GetHeapOffset()); + auto heap_end_ptr = + Load(data_ptr + layout.GetHeapOffset() + (next - 1) * layout.GetRowWidth()); + idx_t size = heap_end_ptr - heap_start_ptr + Load(heap_end_ptr); + ptrs_and_sizes.emplace_back(heap_start_ptr, size); + D_ASSERT(size <= heap_blocks[heap_block_idx]->byte_offset); + + // Swizzle the heap pointer + RowOperations::SwizzleHeapPointer(layout, data_ptr, heap_start_ptr, next, total_size); + total_size += size; + + // Update where we are in the data and heap blocks + data_ptr += next * layout.GetRowWidth(); + data_block_remaining -= next; + heap_block_remaining -= next; + } + + // Finally, we allocate a new heap block and copy data to it + swizzled_string_heap.blocks.emplace_back( + make_unique(buffer_manager, MaxValue(total_size, (idx_t)Storage::BLOCK_SIZE), 1)); + auto new_heap_handle = buffer_manager.Pin(swizzled_string_heap.blocks.back()->block); + auto new_heap_ptr = new_heap_handle.Ptr(); + if (swizzled_string_heap.keep_pinned) { + // Since the heap blocks are pinned, we can unswizzle the data again. + swizzled_string_heap.pinned_blocks.emplace_back(move(new_heap_handle)); + RowOperations::UnswizzlePointers(layout, base_row_ptr, new_heap_ptr, data_block->count); + RowOperations::UnswizzleHeapPointer(layout, base_row_ptr, new_heap_ptr, data_block->count); + } + for (auto &ptr_and_size : ptrs_and_sizes) { + memcpy(new_heap_ptr, ptr_and_size.first, ptr_and_size.second); + new_heap_ptr += ptr_and_size.second; + } + } + } + + // We're done with variable-sized data, now just merge the fixed-size data + swizzled_block_collection.Merge(block_collection); + D_ASSERT(swizzled_block_collection.blocks.size() == swizzled_string_heap.blocks.size()); + + // Update counts and cleanup + swizzled_string_heap.count = string_heap.count; + string_heap.Clear(); +} + +void RowDataCollectionScanner::ScanState::PinData() { + auto &rows = scanner.rows; + D_ASSERT(block_idx < rows.blocks.size()); + auto &data_block = rows.blocks[block_idx]; + if (!data_handle.IsValid() || data_handle.GetBlockId() != data_block->block->BlockId()) { + data_handle = rows.buffer_manager.Pin(data_block->block); + } + if (scanner.layout.AllConstant() || !scanner.external) { + return; + } + + auto &heap = scanner.heap; + D_ASSERT(block_idx < heap.blocks.size()); + auto &heap_block = heap.blocks[block_idx]; + if (!heap_handle.IsValid() || heap_handle.GetBlockId() != heap_block->block->BlockId()) { + heap_handle = heap.buffer_manager.Pin(heap_block->block); + } +} + +RowDataCollectionScanner::RowDataCollectionScanner(RowDataCollection &rows_p, RowDataCollection &heap_p, + const RowLayout &layout_p, bool external_p, bool flush_p) + : rows(rows_p), heap(heap_p), layout(layout_p), read_state(*this), total_count(rows.count), total_scanned(0), + external(external_p), flush(flush_p), unswizzling(!layout.AllConstant() && external && !heap.keep_pinned) { + + if (unswizzling) { + D_ASSERT(rows.blocks.size() == heap.blocks.size()); + } + + ValidateUnscannedBlock(); +} + +void RowDataCollectionScanner::SwizzleBlock(RowDataBlock &data_block, RowDataBlock &heap_block) { + // Pin the data block and swizzle the pointers within the rows + D_ASSERT(!data_block.block->IsSwizzled()); + auto data_handle = rows.buffer_manager.Pin(data_block.block); + auto data_ptr = data_handle.Ptr(); + RowOperations::SwizzleColumns(layout, data_ptr, data_block.count); + data_block.block->SetSwizzling(nullptr); + + // Swizzle the heap pointers + auto heap_handle = heap.buffer_manager.Pin(heap_block.block); + auto heap_ptr = Load(data_ptr + layout.GetHeapOffset()); + auto heap_offset = heap_ptr - heap_handle.Ptr(); + RowOperations::SwizzleHeapPointer(layout, data_ptr, heap_ptr, data_block.count, heap_offset); } +void RowDataCollectionScanner::ReSwizzle() { + if (rows.count == 0) { + return; + } + + if (!unswizzling) { + // No swizzled blocks! + return; + } + + D_ASSERT(rows.blocks.size() == heap.blocks.size()); + for (idx_t i = 0; i < rows.blocks.size(); ++i) { + auto &data_block = rows.blocks[i]; + if (data_block->block && !data_block->block->IsSwizzled()) { + SwizzleBlock(*data_block, *heap.blocks[i]); + } + } +} + +void RowDataCollectionScanner::ValidateUnscannedBlock() const { + if (unswizzling && read_state.block_idx < rows.blocks.size()) { + D_ASSERT(rows.blocks[read_state.block_idx]->block->IsSwizzled()); + } +} + +void RowDataCollectionScanner::Scan(DataChunk &chunk) { + auto count = MinValue((idx_t)STANDARD_VECTOR_SIZE, total_count - total_scanned); + if (count == 0) { + chunk.SetCardinality(count); + return; + } + + const idx_t &row_width = layout.GetRowWidth(); + // Set up a batch of pointers to scan data from + idx_t scanned = 0; + auto data_pointers = FlatVector::GetData(addresses); + + // We must pin ALL blocks we are going to gather from + vector pinned_blocks; + while (scanned < count) { + read_state.PinData(); + auto &data_block = rows.blocks[read_state.block_idx]; + idx_t next = MinValue(data_block->count - read_state.entry_idx, count - scanned); + const data_ptr_t data_ptr = read_state.data_handle.Ptr() + read_state.entry_idx * row_width; + // Set up the next pointers + data_ptr_t row_ptr = data_ptr; + for (idx_t i = 0; i < next; i++) { + data_pointers[scanned + i] = row_ptr; + row_ptr += row_width; + } + // Unswizzle the offsets back to pointers (if needed) + if (unswizzling) { + RowOperations::UnswizzlePointers(layout, data_ptr, read_state.heap_handle.Ptr(), next); + rows.blocks[read_state.block_idx]->block->SetSwizzling("RowDataCollectionScanner::Scan"); + } + // Update state indices + read_state.entry_idx += next; + if (read_state.entry_idx == data_block->count) { + // Pin completed blocks so we don't lose them + pinned_blocks.emplace_back(rows.buffer_manager.Pin(data_block->block)); + if (unswizzling) { + auto &heap_block = heap.blocks[read_state.block_idx]; + pinned_blocks.emplace_back(heap.buffer_manager.Pin(heap_block->block)); + } + read_state.block_idx++; + read_state.entry_idx = 0; + ValidateUnscannedBlock(); + } + scanned += next; + } + D_ASSERT(scanned == count); + // Deserialize the payload data + for (idx_t col_no = 0; col_no < layout.ColumnCount(); col_no++) { + RowOperations::Gather(addresses, *FlatVector::IncrementalSelectionVector(), chunk.data[col_no], + *FlatVector::IncrementalSelectionVector(), count, layout, col_no); + } + chunk.SetCardinality(count); + chunk.Verify(); + total_scanned += scanned; + + // Switch to a new set of pinned blocks + read_state.pinned_blocks.swap(pinned_blocks); + + if (flush) { + // Release blocks we have passed. + for (idx_t i = 0; i < read_state.block_idx; ++i) { + rows.blocks[i]->block = nullptr; + if (unswizzling) { + heap.blocks[i]->block = nullptr; + } + } + } else if (unswizzling) { + // Reswizzle blocks we have passed so they can be flushed safely. + for (idx_t i = 0; i < read_state.block_idx; ++i) { + auto &data_block = rows.blocks[i]; + if (data_block->block && !data_block->block->IsSwizzled()) { + SwizzleBlock(*data_block, *heap.blocks[i]); + } + } + } +} + +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/types/row_layout.cpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { + RowLayout::RowLayout() : flag_width(0), data_width(0), aggr_width(0), row_width(0), all_constant(true), heap_pointer_offset(0) { } @@ -45977,9 +50692,15 @@ buffer_ptr SelectionVector::Slice(const SelectionVector &sel, idx namespace duckdb { -#define MINIMUM_HEAP_SIZE 4096 +StringHeap::StringHeap() : allocator(Allocator::DefaultAllocator()) { +} + +void StringHeap::Destroy() { + allocator.Destroy(); +} -StringHeap::StringHeap() : tail(nullptr) { +void StringHeap::Move(StringHeap &other) { + other.allocator.Move(allocator); } string_t StringHeap::AddString(const char *data, idx_t len) { @@ -46007,19 +50728,13 @@ string_t StringHeap::AddBlob(const char *data, idx_t len) { return insert_string; } +string_t StringHeap::AddBlob(const string_t &data) { + return AddBlob(data.GetDataUnsafe(), data.GetSize()); +} + string_t StringHeap::EmptyString(idx_t len) { D_ASSERT(len >= string_t::INLINE_LENGTH); - if (!chunk || chunk->current_position + len >= chunk->maximum_size) { - // have to make a new entry - auto new_chunk = make_unique(MaxValue(len, MINIMUM_HEAP_SIZE)); - new_chunk->prev = move(chunk); - chunk = move(new_chunk); - if (!tail) { - tail = chunk.get(); - } - } - auto insert_pos = chunk->data.get() + chunk->current_position; - chunk->current_position += len; + auto insert_pos = (const char *)allocator.Allocate(len); return string_t(insert_pos, len); } @@ -46031,7 +50746,7 @@ string_t StringHeap::EmptyString(idx_t len) { namespace duckdb { -void string_t::Verify() { +void string_t::Verify() const { auto dataptr = GetDataUnsafe(); (void)dataptr; D_ASSERT(dataptr); @@ -46051,7 +50766,7 @@ void string_t::Verify() { } } -void string_t::VerifyNull() { +void string_t::VerifyNull() const { for (idx_t i = 0; i < GetSize(); i++) { D_ASSERT(GetDataUnsafe()[i] != '\0'); } @@ -46429,9 +51144,9 @@ timestamp_t Timestamp::FromString(const string &str) { string Timestamp::ToString(timestamp_t timestamp) { if (timestamp == timestamp_t::infinity()) { - return "infinity"; + return Date::PINF; } else if (timestamp == timestamp_t::ninfinity()) { - return "-infinity"; + return Date::NINF; } date_t date; dtime_t time; @@ -46449,6 +51164,9 @@ date_t Timestamp::GetDate(timestamp_t timestamp) { } dtime_t Timestamp::GetTime(timestamp_t timestamp) { + if (!IsFinite(timestamp)) { + throw ConversionException("Can't get TIME of infinite TIMESTAMP"); + } date_t date = Timestamp::GetDate(timestamp); return dtime_t(timestamp.value - (int64_t(date.days) * int64_t(Interval::MICROS_PER_DAY))); } @@ -46536,6 +51254,7 @@ int64_t Timestamp::GetEpochNanoSeconds(timestamp_t timestamp) { } // namespace duckdb + namespace duckdb { bool UUID::FromString(string str, hugeint_t &result) { @@ -46620,6 +51339,45 @@ void UUID::ToString(hugeint_t input, char *buf) { byte_to_hex(input.lower & 0xFF, buf, pos); } +hugeint_t UUID::GenerateRandomUUID(RandomEngine &engine) { + uint8_t bytes[16]; + for (int i = 0; i < 16; i += 4) { + *reinterpret_cast(bytes + i) = engine.NextRandomInteger(); + } + // variant must be 10xxxxxx + bytes[8] &= 0xBF; + bytes[8] |= 0x80; + // version must be 0100xxxx + bytes[6] &= 0x4F; + bytes[6] |= 0x40; + + hugeint_t result; + result.upper = 0; + result.upper |= ((int64_t)bytes[0] << 56); + result.upper |= ((int64_t)bytes[1] << 48); + result.upper |= ((int64_t)bytes[3] << 40); + result.upper |= ((int64_t)bytes[4] << 32); + result.upper |= ((int64_t)bytes[5] << 24); + result.upper |= ((int64_t)bytes[6] << 16); + result.upper |= ((int64_t)bytes[7] << 8); + result.upper |= bytes[8]; + result.lower = 0; + result.lower |= ((uint64_t)bytes[8] << 56); + result.lower |= ((uint64_t)bytes[9] << 48); + result.lower |= ((uint64_t)bytes[10] << 40); + result.lower |= ((uint64_t)bytes[11] << 32); + result.lower |= ((uint64_t)bytes[12] << 24); + result.lower |= ((uint64_t)bytes[13] << 16); + result.lower |= ((uint64_t)bytes[14] << 8); + result.lower |= bytes[15]; + return result; +} + +hugeint_t UUID::GenerateRandomUUID() { + RandomEngine engine; + return GenerateRandomUUID(engine); +} + } // namespace duckdb @@ -46672,17 +51430,19 @@ string ValidityMask::ToString(idx_t count) const { // LCOV_EXCL_STOP void ValidityMask::Resize(idx_t old_size, idx_t new_size) { + D_ASSERT(new_size >= old_size); if (validity_mask) { auto new_size_count = EntryCount(new_size); auto old_size_count = EntryCount(old_size); - auto new_owned_data = unique_ptr(new validity_t[new_size_count]); + auto new_validity_data = make_buffer(new_size); + auto new_owned_data = new_validity_data->owned_data.get(); for (idx_t entry_idx = 0; entry_idx < old_size_count; entry_idx++) { new_owned_data[entry_idx] = validity_mask[entry_idx]; } for (idx_t entry_idx = old_size_count; entry_idx < new_size_count; entry_idx++) { new_owned_data[entry_idx] = ValidityData::MAX_ENTRY; } - validity_data->owned_data = move(new_owned_data); + validity_data = move(new_validity_data); validity_mask = validity_data->owned_data.get(); } else { Initialize(new_size); @@ -47577,7 +52337,7 @@ Value Value::CreateValue(Value value) { template T Value::GetValueInternal() const { if (IsNull()) { - return NullValue(); + throw InternalException("Calling GetValueInternal on a value that is NULL"); } switch (type_.id()) { case LogicalTypeId::BOOLEAN: @@ -47634,7 +52394,6 @@ T Value::GetValueInternal() const { throw InternalException("Invalid Internal Type for ENUMs"); } } - default: throw NotImplementedException("Unimplemented type \"%s\" for GetValue()", type_.ToString()); } @@ -47661,6 +52420,9 @@ int32_t Value::GetValue() const { } template <> int64_t Value::GetValue() const { + if (IsNull()) { + throw InternalException("Calling GetValue on a value that is NULL"); + } switch (type_.id()) { case LogicalTypeId::TIMESTAMP: case LogicalTypeId::TIMESTAMP_SEC: @@ -47770,8 +52532,6 @@ Value Value::Numeric(const LogicalType &type, int64_t value) { return Value((float)value); case LogicalTypeId::DOUBLE: return Value((double)value); - case LogicalTypeId::HASH: - return Value::HASH(value); case LogicalTypeId::POINTER: return Value::POINTER(value); case LogicalTypeId::DATE: @@ -48114,21 +52874,22 @@ string Value::ToString() const { case LogicalTypeId::UUID: return UUID::ToString(value_.hugeint); case LogicalTypeId::FLOAT: - return to_string(value_.float_); + return duckdb_fmt::format("{}", value_.float_); case LogicalTypeId::DOUBLE: - return to_string(value_.double_); + return duckdb_fmt::format("{}", value_.double_); case LogicalTypeId::DECIMAL: { auto internal_type = type_.InternalType(); + auto width = DecimalType::GetWidth(type_); auto scale = DecimalType::GetScale(type_); if (internal_type == PhysicalType::INT16) { - return Decimal::ToString(value_.smallint, scale); + return Decimal::ToString(value_.smallint, width, scale); } else if (internal_type == PhysicalType::INT32) { - return Decimal::ToString(value_.integer, scale); + return Decimal::ToString(value_.integer, width, scale); } else if (internal_type == PhysicalType::INT64) { - return Decimal::ToString(value_.bigint, scale); + return Decimal::ToString(value_.bigint, width, scale); } else { D_ASSERT(internal_type == PhysicalType::INT128); - return Decimal::ToString(value_.hugeint, scale); + return Decimal::ToString(value_.hugeint, width, scale); } } case LogicalTypeId::DATE: @@ -48162,8 +52923,6 @@ string Value::ToString() const { return Blob::ToString(string_t(str_value)); case LogicalTypeId::POINTER: return to_string(value_.pointer); - case LogicalTypeId::HASH: - return to_string(value_.hash); case LogicalTypeId::STRUCT: { string ret = "{"; auto &child_types = StructType::GetChildTypes(type_); @@ -48694,6 +53453,7 @@ bool Value::ValuesAreEqual(const Value &result_value, const Value &value) { + namespace duckdb { enum class MapInvalidReason : uint8_t { VALID, NULL_KEY_LIST, NULL_KEY, DUPLICATE_KEY }; @@ -48701,7 +53461,7 @@ enum class MapInvalidReason : uint8_t { VALID, NULL_KEY_LIST, NULL_KEY, DUPLICAT struct VariableReturnBindData : public FunctionData { LogicalType stype; - explicit VariableReturnBindData(const LogicalType &stype_p) : stype(stype_p) { + explicit VariableReturnBindData(LogicalType stype_p) : stype(move(stype_p)) { } unique_ptr Copy() const override { @@ -48711,6 +53471,18 @@ struct VariableReturnBindData : public FunctionData { auto &other = (const VariableReturnBindData &)other_p; return stype == other.stype; } + + static void Serialize(FieldWriter &writer, const FunctionData *bind_data_p, const ScalarFunction &function) { + D_ASSERT(bind_data_p); + auto &info = (VariableReturnBindData &)*bind_data_p; + writer.WriteSerializable(info.stype); + } + + static unique_ptr Deserialize(ClientContext &context, FieldReader &reader, + ScalarFunction &bound_function) { + auto stype = reader.ReadRequiredSerializable(); + return make_unique(move(stype)); + } }; template > @@ -48726,6 +53498,10 @@ struct StructPackFun { static void RegisterFunction(BuiltinFunctions &set); }; +struct StructInsertFun { + static void RegisterFunction(BuiltinFunctions &set); +}; + struct ListValueFun { static void RegisterFunction(BuiltinFunctions &set); }; @@ -48738,6 +53514,10 @@ struct MapFun { static void RegisterFunction(BuiltinFunctions &set); }; +struct MapFromEntriesFun { + static void RegisterFunction(BuiltinFunctions &set); +}; + struct MapExtractFun { static void RegisterFunction(BuiltinFunctions &set); }; @@ -48746,6 +53526,16 @@ struct ListExtractFun { static void RegisterFunction(BuiltinFunctions &set); }; +struct ListTransformFun { + static ScalarFunction GetFunction(); + static void RegisterFunction(BuiltinFunctions &set); +}; + +struct ListFilterFun { + static ScalarFunction GetFunction(); + static void RegisterFunction(BuiltinFunctions &set); +}; + struct ListConcatFun { static ScalarFunction GetFunction(); static void RegisterFunction(BuiltinFunctions &set); @@ -48796,6 +53586,7 @@ struct StructExtractFun { MapInvalidReason CheckMapValidity(Vector &map, idx_t count, const SelectionVector &sel = *FlatVector::IncrementalSelectionVector()); +void MapConversionVerify(Vector &vector, idx_t count); } // namespace duckdb @@ -48816,7 +53607,7 @@ Vector::Vector(LogicalType type_p, idx_t capacity) : Vector(move(type_p), true, Vector::Vector(LogicalType type_p, data_ptr_t dataptr) : vector_type(VectorType::FLAT_VECTOR), type(move(type_p)), data(dataptr) { - if (dataptr && type.id() == LogicalTypeId::INVALID) { + if (dataptr && !type.IsValid()) { throw InternalException("Cannot create a vector of type INVALID!"); } } @@ -49077,6 +53868,19 @@ void Vector::Resize(idx_t cur_size, idx_t new_size) { } } +// FIXME Just like DECIMAL, it's important that type_info gets considered when determining whether or not to cast +// just comparing internal type is not always enough +static bool ValueShouldBeCast(const LogicalType &incoming, const LogicalType &target) { + if (incoming.InternalType() != target.InternalType()) { + return true; + } + if (incoming.id() == LogicalTypeId::DECIMAL && incoming.id() == target.id()) { + //! Compare the type_info + return incoming != target; + } + return false; +} + void Vector::SetValue(idx_t index, const Value &val) { if (GetVectorType() == VectorType::DICTIONARY_VECTOR) { // dictionary: apply dictionary and forward to child @@ -49084,7 +53888,7 @@ void Vector::SetValue(idx_t index, const Value &val) { auto &child = DictionaryVector::Child(*this); return child.SetValue(sel_vector.get_index(index), val); } - if (val.type().InternalType() != GetType().InternalType()) { + if (ValueShouldBeCast(val.type(), GetType())) { SetValue(index, val.CastAs(GetType())); return; } @@ -49176,7 +53980,7 @@ void Vector::SetValue(idx_t index, const Value &val) { } } -Value Vector::GetValue(const Vector &v_p, idx_t index_p) { +Value Vector::GetValueInternal(const Vector &v_p, idx_t index_p) { const Vector *vector = &v_p; idx_t index = index_p; bool finished = false; @@ -49265,7 +54069,8 @@ Value Vector::GetValue(const Vector &v_p, idx_t index_p) { case PhysicalType::INT128: return Value::DECIMAL(((hugeint_t *)data)[index], width, scale); default: - throw InternalException("Widths bigger than 38 are not supported"); + throw InternalException("Physical type '%s' has a width bigger than 38, which is not supported", + TypeIdToString(type.InternalType())); } } case LogicalTypeId::ENUM: { @@ -49282,8 +54087,6 @@ Value Vector::GetValue(const Vector &v_p, idx_t index_p) { throw InternalException("ENUM can only have unsigned integers as physical types"); } } - case LogicalTypeId::HASH: - return Value::HASH(((hash_t *)data)[index]); case LogicalTypeId::POINTER: return Value::POINTER(((uintptr_t *)data)[index]); case LogicalTypeId::FLOAT: @@ -49335,6 +54138,15 @@ Value Vector::GetValue(const Vector &v_p, idx_t index_p) { } } +Value Vector::GetValue(const Vector &v_p, idx_t index_p) { + auto value = GetValueInternal(v_p, index_p); + // set the alias of the type to the correct value, if there is a type alias + if (v_p.GetType().HasAlias()) { + value.type().SetAlias(v_p.GetType().GetAlias()); + } + return value; +} + Value Vector::GetValue(idx_t index) const { return GetValue(*this, index); } @@ -49422,7 +54234,7 @@ static void TemplatedFlattenConstantVector(data_ptr_t data, data_ptr_t old_data, } } -void Vector::Normalify(idx_t count) { +void Vector::Flatten(idx_t count) { switch (GetVectorType()) { case VectorType::FLAT_VECTOR: // already a flat vector @@ -49507,13 +54319,13 @@ void Vector::Normalify(idx_t count) { for (auto &child : child_entries) { D_ASSERT(child->GetVectorType() == VectorType::CONSTANT_VECTOR); auto vector = make_unique(*child); - vector->Normalify(count); + vector->Flatten(count); new_children.push_back(move(vector)); } auxiliary = move(normalified_buffer); } break; default: - throw InternalException("Unimplemented type for VectorOperations::Normalify"); + throw InternalException("Unimplemented type for VectorOperations::Flatten"); } break; } @@ -49531,7 +54343,7 @@ void Vector::Normalify(idx_t count) { } } -void Vector::Normalify(const SelectionVector &sel, idx_t count) { +void Vector::Flatten(const SelectionVector &sel, idx_t count) { switch (GetVectorType()) { case VectorType::FLAT_VECTOR: // already a flat vector @@ -49550,7 +54362,7 @@ void Vector::Normalify(const SelectionVector &sel, idx_t count) { } } -void Vector::Orrify(idx_t count, VectorData &data) { +void Vector::ToUnifiedFormat(idx_t count, UnifiedVectorFormat &data) { switch (GetVectorType()) { case VectorType::DICTIONARY_VECTOR: { auto &sel = DictionaryVector::SelVector(*this); @@ -49562,7 +54374,7 @@ void Vector::Orrify(idx_t count, VectorData &data) { } else { // dictionary with non-flat child: create a new reference to the child and normalify it Vector child_vector(child); - child_vector.Normalify(sel, count); + child_vector.Flatten(sel, count); auto new_aux = make_buffer(move(child_vector)); data.sel = &sel; @@ -49578,7 +54390,7 @@ void Vector::Orrify(idx_t count, VectorData &data) { data.validity = ConstantVector::Validity(*this); break; default: - Normalify(count); + Flatten(count); data.sel = FlatVector::IncrementalSelectionVector(); data.data = FlatVector::GetData(*this); data.validity = FlatVector::Validity(*this); @@ -49599,8 +54411,8 @@ void Vector::Sequence(int64_t start, int64_t increment) { void Vector::Serialize(idx_t count, Serializer &serializer) { auto &type = GetType(); - VectorData vdata; - Orrify(count, vdata); + UnifiedVectorFormat vdata; + ToUnifiedFormat(count, vdata); const auto write_validity = (count > 0) && !vdata.validity.AllValid(); serializer.Write(write_validity); @@ -49630,7 +54442,7 @@ void Vector::Serialize(idx_t count, Serializer &serializer) { break; } case PhysicalType::STRUCT: { - Normalify(count); + Flatten(count); auto &entries = StructVector::GetEntries(*this); for (auto &entry : entries) { entry->Serialize(count, serializer); @@ -49839,7 +54651,7 @@ void Vector::Verify(Vector &vector_p, const SelectionVector &sel_p, idx_t count) D_ASSERT(child_types.size() == children.size()); for (idx_t child_idx = 0; child_idx < children.size(); child_idx++) { D_ASSERT(children[child_idx]->GetType() == child_types[child_idx].second); - children[child_idx]->Verify(count); + Vector::Verify(*children[child_idx], sel_p, count); if (vtype == VectorType::CONSTANT_VECTOR) { D_ASSERT(children[child_idx]->GetVectorType() == VectorType::CONSTANT_VECTOR); if (ConstantVector::IsNull(*vector)) { @@ -49974,8 +54786,8 @@ void ConstantVector::Reference(Vector &vector, Vector &source, idx_t position, i switch (source_type.InternalType()) { case PhysicalType::LIST: { // retrieve the list entry from the source vector - VectorData vdata; - source.Orrify(count, vdata); + UnifiedVectorFormat vdata; + source.ToUnifiedFormat(count, vdata); auto list_index = vdata.sel->get_index(position); if (!vdata.validity.RowIsValid(list_index)) { @@ -50002,8 +54814,8 @@ void ConstantVector::Reference(Vector &vector, Vector &source, idx_t position, i break; } case PhysicalType::STRUCT: { - VectorData vdata; - source.Orrify(count, vdata); + UnifiedVectorFormat vdata; + source.ToUnifiedFormat(count, vdata); auto struct_index = vdata.sel->get_index(position); if (!vdata.validity.RowIsValid(struct_index)) { @@ -50089,7 +54901,7 @@ string_t StringVector::EmptyString(Vector &vector, idx_t len) { return string_buffer.EmptyString(len); } -void StringVector::AddHandle(Vector &vector, unique_ptr handle) { +void StringVector::AddHandle(Vector &vector, BufferHandle handle) { D_ASSERT(vector.GetType().InternalType() == PhysicalType::VARCHAR); if (!vector.auxiliary) { vector.auxiliary = make_buffer(); @@ -50170,8 +54982,8 @@ void ListVector::Reserve(Vector &vector, idx_t required_capacity) { template void TemplatedSearchInMap(Vector &list, T key, vector &offsets, bool is_key_null, idx_t offset, idx_t length) { auto &list_vector = ListVector::GetEntry(list); - VectorData vector_data; - list_vector.Orrify(ListVector::GetListSize(list), vector_data); + UnifiedVectorFormat vector_data; + list_vector.ToUnifiedFormat(ListVector::GetListSize(list), vector_data); auto data = (T *)vector_data.data; auto validity_mask = vector_data.validity; @@ -50202,8 +55014,8 @@ void TemplatedSearchInMap(Vector &list, const Value &key, vector &offsets void SearchStringInMap(Vector &list, const string &key, vector &offsets, bool is_key_null, idx_t offset, idx_t length) { auto &list_vector = ListVector::GetEntry(list); - VectorData vector_data; - list_vector.Orrify(ListVector::GetListSize(list), vector_data); + UnifiedVectorFormat vector_data; + list_vector.ToUnifiedFormat(ListVector::GetListSize(list), vector_data); auto data = (string_t *)vector_data.data; auto validity_mask = vector_data.validity; if (is_key_null) { @@ -50229,7 +55041,7 @@ vector ListVector::Search(Vector &list, const Value &key, idx_t row) { vector offsets; auto &list_vector = ListVector::GetEntry(list); - auto &entry = ((list_entry_t *)list.GetData())[row]; + auto &entry = ListVector::GetData(list)[row]; switch (list_vector.GetType().InternalType()) { case PhysicalType::BOOL: @@ -50431,7 +55243,7 @@ void VectorListBuffer::PushBack(const Value &insert) { VectorListBuffer::~VectorListBuffer() { } -ManagedVectorBuffer::ManagedVectorBuffer(unique_ptr handle) +ManagedVectorBuffer::ManagedVectorBuffer(BufferHandle handle) : VectorBuffer(VectorBufferType::MANAGED_BUFFER), handle(move(handle)) { } @@ -50442,20 +55254,21 @@ ManagedVectorBuffer::~ManagedVectorBuffer() { + namespace duckdb { class VectorCacheBuffer : public VectorBuffer { public: - explicit VectorCacheBuffer(const LogicalType &type_p) + explicit VectorCacheBuffer(Allocator &allocator, const LogicalType &type_p) : VectorBuffer(VectorBufferType::OPAQUE_BUFFER), type(type_p) { auto internal_type = type.InternalType(); switch (internal_type) { case PhysicalType::LIST: { // memory for the list offsets - owned_data = unique_ptr(new data_t[STANDARD_VECTOR_SIZE * GetTypeIdSize(internal_type)]); + owned_data = allocator.Allocate(STANDARD_VECTOR_SIZE * GetTypeIdSize(internal_type)); // child data of the list auto &child_type = ListType::GetChildType(type); - child_caches.push_back(make_buffer(child_type)); + child_caches.push_back(make_buffer(allocator, child_type)); auto child_vector = make_unique(child_type, false, false); auxiliary = make_unique(move(child_vector)); break; @@ -50463,14 +55276,14 @@ class VectorCacheBuffer : public VectorBuffer { case PhysicalType::STRUCT: { auto &child_types = StructType::GetChildTypes(type); for (auto &child_type : child_types) { - child_caches.push_back(make_buffer(child_type.second)); + child_caches.push_back(make_buffer(allocator, child_type.second)); } auto struct_buffer = make_unique(type); auxiliary = move(struct_buffer); break; } default: - owned_data = unique_ptr(new data_t[STANDARD_VECTOR_SIZE * GetTypeIdSize(internal_type)]); + owned_data = allocator.Allocate(STANDARD_VECTOR_SIZE * GetTypeIdSize(internal_type)); break; } } @@ -50490,6 +55303,7 @@ class VectorCacheBuffer : public VectorBuffer { auto &list_buffer = (VectorListBuffer &)*result.auxiliary; list_buffer.capacity = STANDARD_VECTOR_SIZE; list_buffer.size = 0; + list_buffer.SetAuxiliaryData(nullptr); auto &list_child = list_buffer.GetChild(); auto &child_cache = (VectorCacheBuffer &)*child_caches[0]; @@ -50500,6 +55314,7 @@ class VectorCacheBuffer : public VectorBuffer { // struct does not have data result.data = nullptr; // reinitialize the VectorStructBuffer + auxiliary->SetAuxiliaryData(nullptr); AssignSharedPointer(result.auxiliary, auxiliary); // propagate through children auto &children = ((VectorStructBuffer &)*result.auxiliary).GetChildren(); @@ -50525,15 +55340,15 @@ class VectorCacheBuffer : public VectorBuffer { //! The type of the vector cache LogicalType type; //! Owned data - unique_ptr owned_data; + AllocatedData owned_data; //! Child caches (if any). Used for nested types. vector> child_caches; //! Aux data for the vector (if any) buffer_ptr auxiliary; }; -VectorCache::VectorCache(const LogicalType &type_p) { - buffer = make_unique(type_p); +VectorCache::VectorCache(Allocator &allocator, const LogicalType &type_p) { + buffer = make_unique(allocator, type_p); } void VectorCache::ResetFromCache(Vector &result) const { @@ -50583,6 +55398,29 @@ const sel_t ConstantVector::ZERO_VECTOR[STANDARD_VECTOR_SIZE] = {0}; +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/function/cast_rules.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { +//! Contains a list of rules for casting +class CastRules { +public: + //! Returns the cost of performing an implicit cost from "from" to "to", or -1 if an implicit cast is not possible + static int64_t ImplicitCast(const LogicalType &from, const LogicalType &to); +}; + +} // namespace duckdb + + #include namespace duckdb { @@ -50660,7 +55498,8 @@ PhysicalType LogicalType::GetInternalType() { } else if (width <= Decimal::MAX_WIDTH_INT128) { return PhysicalType::INT128; } else { - throw InternalException("Widths bigger than 38 are not supported"); + throw InternalException("Decimal has a width of %d which is bigger than the maximum supported width of %d", + width, DecimalType::MaxWidth()); } } case LogicalTypeId::VARCHAR: @@ -50675,9 +55514,6 @@ PhysicalType LogicalType::GetInternalType() { return PhysicalType::STRUCT; case LogicalTypeId::LIST: return PhysicalType::LIST; - case LogicalTypeId::HASH: - static_assert(sizeof(hash_t) == sizeof(uint64_t), "Hash must be uint64_t"); - return PhysicalType::UINT64; case LogicalTypeId::POINTER: // LCOV_EXCL_START if (sizeof(uintptr_t) == sizeof(uint32_t)) { @@ -50695,6 +55531,7 @@ PhysicalType LogicalType::GetInternalType() { return EnumType::GetPhysicalType(*this); } case LogicalTypeId::TABLE: + case LogicalTypeId::LAMBDA: case LogicalTypeId::ANY: case LogicalTypeId::INVALID: case LogicalTypeId::UNKNOWN: @@ -50747,6 +55584,7 @@ constexpr const LogicalTypeId LogicalType::ROW_TYPE; // TODO these are incomplete and should maybe not exist as such constexpr const LogicalTypeId LogicalType::TABLE; +constexpr const LogicalTypeId LogicalType::LAMBDA; constexpr const LogicalTypeId LogicalType::ANY; @@ -50818,44 +55656,8 @@ string TypeIdToString(PhysicalType type) { return "INVALID"; case PhysicalType::BIT: return "BIT"; - case PhysicalType::NA: - return "NA"; - case PhysicalType::HALF_FLOAT: - return "HALF_FLOAT"; - case PhysicalType::STRING: - return "ARROW_STRING"; - case PhysicalType::BINARY: - return "BINARY"; - case PhysicalType::FIXED_SIZE_BINARY: - return "FIXED_SIZE_BINARY"; - case PhysicalType::DATE32: - return "DATE32"; - case PhysicalType::DATE64: - return "DATE64"; - case PhysicalType::TIMESTAMP: - return "TIMESTAMP"; - case PhysicalType::TIME32: - return "TIME32"; - case PhysicalType::TIME64: - return "TIME64"; - case PhysicalType::UNION: - return "UNION"; - case PhysicalType::DICTIONARY: - return "DICTIONARY"; case PhysicalType::MAP: return "MAP"; - case PhysicalType::EXTENSION: - return "EXTENSION"; - case PhysicalType::FIXED_SIZE_LIST: - return "FIXED_SIZE_LIST"; - case PhysicalType::DURATION: - return "DURATION"; - case PhysicalType::LARGE_STRING: - return "LARGE_STRING"; - case PhysicalType::LARGE_BINARY: - return "LARGE_BINARY"; - case PhysicalType::LARGE_LIST: - return "LARGE_LIST"; case PhysicalType::UNKNOWN: return "UNKNOWN"; } @@ -50905,9 +55707,8 @@ idx_t GetTypeIdSize(PhysicalType type) { } bool TypeIsConstantSize(PhysicalType type) { - return (type >= PhysicalType::BOOL && type <= PhysicalType::DOUBLE) || - (type >= PhysicalType::FIXED_SIZE_BINARY && type <= PhysicalType::INTERVAL) || - type == PhysicalType::INTERVAL || type == PhysicalType::INT128; + return (type >= PhysicalType::BOOL && type <= PhysicalType::DOUBLE) || type == PhysicalType::INTERVAL || + type == PhysicalType::INT128; } bool TypeIsIntegral(PhysicalType type) { return (type >= PhysicalType::UINT8 && type <= PhysicalType::INT64) || type == PhysicalType::INT128; @@ -50986,12 +55787,12 @@ string LogicalTypeIdToString(LogicalTypeId id) { return "LIST"; case LogicalTypeId::MAP: return "MAP"; - case LogicalTypeId::HASH: - return "HASH"; case LogicalTypeId::POINTER: return "POINTER"; case LogicalTypeId::TABLE: return "TABLE"; + case LogicalTypeId::LAMBDA: + return "LAMBDA"; case LogicalTypeId::INVALID: return "INVALID"; case LogicalTypeId::UNKNOWN: @@ -51129,6 +55930,10 @@ bool LogicalType::IsNumeric() const { } } +bool LogicalType::IsValid() const { + return id() != LogicalTypeId::INVALID && id() != LogicalTypeId::UNKNOWN; +} + bool LogicalType::GetDecimalProperties(uint8_t &width, uint8_t &scale) const { switch (id_) { case LogicalTypeId::SQLNULL: @@ -51195,54 +56000,147 @@ bool LogicalType::GetDecimalProperties(uint8_t &width, uint8_t &scale) const { return true; } +//! Grows Decimal width/scale when appropriate +static LogicalType DecimalSizeCheck(const LogicalType &left, const LogicalType &right) { + D_ASSERT(left.id() == LogicalTypeId::DECIMAL || right.id() == LogicalTypeId::DECIMAL); + D_ASSERT(left.id() != right.id()); + + //! Make sure the 'right' is the DECIMAL type + if (left.id() == LogicalTypeId::DECIMAL) { + return DecimalSizeCheck(right, left); + } + auto width = DecimalType::GetWidth(right); + auto scale = DecimalType::GetScale(right); + + uint8_t other_width; + uint8_t other_scale; + bool success = left.GetDecimalProperties(other_width, other_scale); + if (!success) { + throw InternalException("Type provided to DecimalSizeCheck was not a numeric type"); + } + D_ASSERT(other_scale == 0); + const auto effective_width = width - scale; + if (other_width > effective_width) { + auto new_width = other_width + scale; + //! Cap the width at max, if an actual value exceeds this, an exception will be thrown later + if (new_width > DecimalType::MaxWidth()) { + new_width = DecimalType::MaxWidth(); + } + return LogicalType::DECIMAL(new_width, scale); + } + return right; +} + +static LogicalType CombineNumericTypes(const LogicalType &left, const LogicalType &right) { + D_ASSERT(left.id() != right.id()); + if (left.id() > right.id()) { + // this method is symmetric + // arrange it so the left type is smaller to limit the number of options we need to check + return CombineNumericTypes(right, left); + } + if (CastRules::ImplicitCast(left, right) >= 0) { + // we can implicitly cast left to right, return right + //! Depending on the type, we might need to grow the `width` of the DECIMAL type + if (right.id() == LogicalTypeId::DECIMAL) { + return DecimalSizeCheck(left, right); + } + return right; + } + if (CastRules::ImplicitCast(right, left) >= 0) { + // we can implicitly cast right to left, return left + //! Depending on the type, we might need to grow the `width` of the DECIMAL type + if (left.id() == LogicalTypeId::DECIMAL) { + return DecimalSizeCheck(right, left); + } + return left; + } + // we can't cast implicitly either way and types are not equal + // this happens when left is signed and right is unsigned + // e.g. INTEGER and UINTEGER + // in this case we need to upcast to make sure the types fit + + if (left.id() == LogicalTypeId::BIGINT || right.id() == LogicalTypeId::UBIGINT) { + return LogicalType::HUGEINT; + } + if (left.id() == LogicalTypeId::INTEGER || right.id() == LogicalTypeId::UINTEGER) { + return LogicalType::BIGINT; + } + if (left.id() == LogicalTypeId::SMALLINT || right.id() == LogicalTypeId::USMALLINT) { + return LogicalType::INTEGER; + } + if (left.id() == LogicalTypeId::TINYINT || right.id() == LogicalTypeId::UTINYINT) { + return LogicalType::SMALLINT; + } + throw InternalException("Cannot combine these numeric types!?"); +} + LogicalType LogicalType::MaxLogicalType(const LogicalType &left, const LogicalType &right) { - if (left.id() < right.id()) { + if (left.id() != right.id() && left.IsNumeric() && right.IsNumeric()) { + return CombineNumericTypes(left, right); + } else if (left.id() == LogicalTypeId::UNKNOWN) { return right; - } else if (right.id() < left.id()) { + } else if (right.id() == LogicalTypeId::UNKNOWN) { return left; - } else { - // Since both left and right are equal we get the left type as our type_id for checks - auto type_id = left.id(); - if (type_id == LogicalTypeId::ENUM) { - // If both types are different ENUMs we do a string comparison. - return left == right ? left : LogicalType::VARCHAR; - } - if (type_id == LogicalTypeId::VARCHAR) { - // varchar: use type that has collation (if any) - if (StringType::GetCollation(right).empty()) { - return left; - } else { - return right; - } - } else if (type_id == LogicalTypeId::DECIMAL) { - // use max width/scale of the two types - auto width = MaxValue(DecimalType::GetWidth(left), DecimalType::GetWidth(right)); - auto scale = MaxValue(DecimalType::GetScale(left), DecimalType::GetScale(right)); - return LogicalType::DECIMAL(width, scale); - } else if (type_id == LogicalTypeId::LIST) { - // list: perform max recursively on child type - auto new_child = MaxLogicalType(ListType::GetChildType(left), ListType::GetChildType(right)); - return LogicalType::LIST(move(new_child)); - } else if (type_id == LogicalTypeId::STRUCT) { - // struct: perform recursively - auto &left_child_types = StructType::GetChildTypes(left); - auto &right_child_types = StructType::GetChildTypes(right); - if (left_child_types.size() != right_child_types.size()) { - // child types are not of equal size, we can't cast anyway - // just return the left child - return left; - } - child_list_t child_types; - for (idx_t i = 0; i < left_child_types.size(); i++) { - auto child_type = MaxLogicalType(left_child_types[i].second, right_child_types[i].second); - child_types.push_back(make_pair(left_child_types[i].first, move(child_type))); - } - return LogicalType::STRUCT(move(child_types)); - } else { - // types are equal but no extra specifier: just return the type + } else if (left.id() < right.id()) { + return right; + } + if (right.id() < left.id()) { + return left; + } + // Since both left and right are equal we get the left type as our type_id for checks + auto type_id = left.id(); + if (type_id == LogicalTypeId::ENUM) { + // If both types are different ENUMs we do a string comparison. + return left == right ? left : LogicalType::VARCHAR; + } + if (type_id == LogicalTypeId::VARCHAR) { + // varchar: use type that has collation (if any) + if (StringType::GetCollation(right).empty()) { return left; } + return right; + } + if (type_id == LogicalTypeId::DECIMAL) { + // unify the width/scale so that the resulting decimal always fits + // "width - scale" gives us the number of digits on the left side of the decimal point + // "scale" gives us the number of digits allowed on the right of the decimal point + // using the max of these of the two types gives us the new decimal size + auto extra_width_left = DecimalType::GetWidth(left) - DecimalType::GetScale(left); + auto extra_width_right = DecimalType::GetWidth(right) - DecimalType::GetScale(right); + auto extra_width = MaxValue(extra_width_left, extra_width_right); + auto scale = MaxValue(DecimalType::GetScale(left), DecimalType::GetScale(right)); + auto width = extra_width + scale; + if (width > DecimalType::MaxWidth()) { + // if the resulting decimal does not fit, we truncate the scale + width = DecimalType::MaxWidth(); + scale = width - extra_width; + } + return LogicalType::DECIMAL(width, scale); } + if (type_id == LogicalTypeId::LIST) { + // list: perform max recursively on child type + auto new_child = MaxLogicalType(ListType::GetChildType(left), ListType::GetChildType(right)); + return LogicalType::LIST(move(new_child)); + } + if (type_id == LogicalTypeId::STRUCT || type_id == LogicalTypeId::MAP) { + // struct: perform recursively + auto &left_child_types = StructType::GetChildTypes(left); + auto &right_child_types = StructType::GetChildTypes(right); + if (left_child_types.size() != right_child_types.size()) { + // child types are not of equal size, we can't cast anyway + // just return the left child + return left; + } + child_list_t child_types; + for (idx_t i = 0; i < left_child_types.size(); i++) { + auto child_type = MaxLogicalType(left_child_types[i].second, right_child_types[i].second); + child_types.push_back(make_pair(left_child_types[i].first, move(child_type))); + } + return type_id == LogicalTypeId::STRUCT ? LogicalType::STRUCT(move(child_types)) + : LogicalType::MAP(move(child_types)); + } + // types are equal but no extra specifier: just return the type + return left; } void LogicalType::Verify() const { @@ -51261,7 +56159,7 @@ bool ApproxEqual(float ldecimal, float rdecimal) { if (!Value::FloatIsFinite(ldecimal) || !Value::FloatIsFinite(rdecimal)) { return ldecimal == rdecimal; } - float epsilon = std::fabs(rdecimal) * 0.01; + float epsilon = std::fabs(rdecimal) * 0.01 + 0.00000001; return std::fabs(ldecimal - rdecimal) <= epsilon; } @@ -51272,7 +56170,7 @@ bool ApproxEqual(double ldecimal, double rdecimal) { if (!Value::DoubleIsFinite(ldecimal) || !Value::DoubleIsFinite(rdecimal)) { return ldecimal == rdecimal; } - double epsilon = std::fabs(rdecimal) * 0.01; + double epsilon = std::fabs(rdecimal) * 0.01 + 0.00000001; return std::fabs(ldecimal - rdecimal) <= epsilon; } @@ -51341,11 +56239,11 @@ struct ExtraTypeInfo { } }; -void LogicalType::SetAlias(string &alias) { +void LogicalType::SetAlias(string alias) { if (!type_info_) { - type_info_ = make_shared(ExtraTypeInfoType::GENERIC_TYPE_INFO, alias); + type_info_ = make_shared(ExtraTypeInfoType::GENERIC_TYPE_INFO, move(alias)); } else { - type_info_->alias = alias; + type_info_->alias = move(alias); } } @@ -51357,6 +56255,13 @@ string LogicalType::GetAlias() const { } } +bool LogicalType::HasAlias() const { + if (!type_info_) { + return false; + } + return !type_info_->alias.empty(); +} + void LogicalType::SetCatalog(LogicalType &type, TypeCatalogEntry *catalog_entry) { auto info = type.AuxInfo(); D_ASSERT(info); @@ -51376,6 +56281,7 @@ TypeCatalogEntry *LogicalType::GetCatalog(const LogicalType &type) { struct DecimalTypeInfo : public ExtraTypeInfo { DecimalTypeInfo(uint8_t width_p, uint8_t scale_p) : ExtraTypeInfo(ExtraTypeInfoType::DECIMAL_TYPE_INFO), width(width_p), scale(scale_p) { + D_ASSERT(width_p >= scale_p); } uint8_t width; @@ -51414,7 +56320,12 @@ uint8_t DecimalType::GetScale(const LogicalType &type) { return ((DecimalTypeInfo &)*info).scale; } +uint8_t DecimalType::MaxWidth() { + return DecimalWidth::max; +} + LogicalType LogicalType::DECIMAL(int width, int scale) { + D_ASSERT(width >= scale); auto type_info = make_shared(width, scale); return LogicalType(LogicalTypeId::DECIMAL, move(type_info)); } @@ -52292,9 +57203,9 @@ static void TemplatedBooleanNullmask(Vector &left, Vector &right, Vector &result ConstantVector::SetNull(result, is_null); } else { // perform generic loop - VectorData ldata, rdata; - left.Orrify(count, ldata); - right.Orrify(count, rdata); + UnifiedVectorFormat ldata, rdata; + left.ToUnifiedFormat(count, ldata); + right.ToUnifiedFormat(count, rdata); result.SetVectorType(VectorType::FLAT_VECTOR); auto left_data = (uint8_t *)ldata.data; // we use uint8 to avoid load of gunk bools @@ -52594,7 +57505,8 @@ inline idx_t ComparisonSelector::Select(Vector &left, Ve return VectorOperations::LessThanEquals(left, right, sel, count, true_sel, false_sel); } -static void ComparesNotNull(VectorData &ldata, VectorData &rdata, ValidityMask &vresult, idx_t count) { +static void ComparesNotNull(UnifiedVectorFormat &ldata, UnifiedVectorFormat &rdata, ValidityMask &vresult, + idx_t count) { for (idx_t i = 0; i < count; ++i) { auto lidx = ldata.sel->get_index(i); auto ridx = rdata.sel->get_index(i); @@ -52630,9 +57542,9 @@ static void NestedComparisonExecutor(Vector &left, Vector &right, Vector &result auto result_data = FlatVector::GetData(result); auto &result_validity = FlatVector::Validity(result); - VectorData leftv, rightv; - left.Orrify(count, leftv); - right.Orrify(count, rightv); + UnifiedVectorFormat leftv, rightv; + left.ToUnifiedFormat(count, leftv); + right.ToUnifiedFormat(count, rightv); if (!leftv.validity.AllValid() || !rightv.validity.AllValid()) { ComparesNotNull(leftv, rightv, result_validity, count); } @@ -52886,10 +57798,10 @@ static void DistinctExecuteGeneric(Vector &left, Vector &right, Vector &result, if (left.GetVectorType() == VectorType::CONSTANT_VECTOR && right.GetVectorType() == VectorType::CONSTANT_VECTOR) { DistinctExecuteConstant(left, right, result); } else { - VectorData ldata, rdata; + UnifiedVectorFormat ldata, rdata; - left.Orrify(count, ldata); - right.Orrify(count, rdata); + left.ToUnifiedFormat(count, ldata); + right.ToUnifiedFormat(count, rdata); result.SetVectorType(VectorType::FLAT_VECTOR); auto result_data = FlatVector::GetData(result); @@ -52985,10 +57897,10 @@ DistinctSelectGenericLoopSwitch(LEFT_TYPE *__restrict ldata, RIGHT_TYPE *__restr template static idx_t DistinctSelectGeneric(Vector &left, Vector &right, const SelectionVector *sel, idx_t count, SelectionVector *true_sel, SelectionVector *false_sel) { - VectorData ldata, rdata; + UnifiedVectorFormat ldata, rdata; - left.Orrify(count, ldata); - right.Orrify(count, rdata); + left.ToUnifiedFormat(count, ldata); + right.ToUnifiedFormat(count, rdata); return DistinctSelectGenericLoopSwitch((LEFT_TYPE *)ldata.data, (RIGHT_TYPE *)rdata.data, ldata.sel, rdata.sel, sel, count, ldata.validity, @@ -53124,9 +58036,9 @@ template static idx_t DistinctSelectNotNull(Vector &left, Vector &right, const idx_t count, idx_t &true_count, const SelectionVector &sel, SelectionVector &maybe_vec, OptionalSelection &true_opt, OptionalSelection &false_opt) { - VectorData lvdata, rvdata; - left.Orrify(count, lvdata); - right.Orrify(count, rvdata); + UnifiedVectorFormat lvdata, rvdata; + left.ToUnifiedFormat(count, lvdata); + right.ToUnifiedFormat(count, rvdata); auto &lmask = lvdata.validity; auto &rmask = rvdata.validity; @@ -53334,11 +58246,11 @@ static idx_t DistinctSelectStruct(Vector &left, Vector &right, idx_t count, cons for (idx_t col_no = 0; col_no < lchildren.size(); ++col_no) { // Slice the children to maintain density Vector lchild(*lchildren[col_no]); - lchild.Normalify(vcount); + lchild.Flatten(vcount); lchild.Slice(slice_sel, count); Vector rchild(*rchildren[col_no]); - rchild.Normalify(vcount); + rchild.Flatten(vcount); rchild.Slice(slice_sel, count); // Find everything that definitely matches @@ -53386,7 +58298,7 @@ static idx_t DistinctSelectStruct(Vector &left, Vector &right, idx_t count, cons return match_count; } -static void PositionListCursor(SelectionVector &cursor, VectorData &vdata, const idx_t pos, +static void PositionListCursor(SelectionVector &cursor, UnifiedVectorFormat &vdata, const idx_t pos, const SelectionVector &slice_sel, const idx_t count) { const auto data = (const list_entry_t *)vdata.data; for (idx_t i = 0; i < count; ++i) { @@ -53409,8 +58321,8 @@ static idx_t DistinctSelectList(Vector &left, Vector &right, idx_t count, const SelectionVector lcursor(count); SelectionVector rcursor(count); - ListVector::GetEntry(left).Normalify(count); - ListVector::GetEntry(right).Normalify(count); + ListVector::GetEntry(left).Flatten(count); + ListVector::GetEntry(right).Flatten(count); Vector lchild(ListVector::GetEntry(left), lcursor, count); Vector rchild(ListVector::GetEntry(right), rcursor, count); @@ -53429,12 +58341,12 @@ static idx_t DistinctSelectList(Vector &left, Vector &right, idx_t count, const // } // Get pointers to the list entries - VectorData lvdata; - left.Orrify(count, lvdata); + UnifiedVectorFormat lvdata; + left.ToUnifiedFormat(count, lvdata); const auto ldata = (const list_entry_t *)lvdata.data; - VectorData rvdata; - right.Orrify(count, rvdata); + UnifiedVectorFormat rvdata; + right.ToUnifiedFormat(count, rvdata); const auto rdata = (const list_entry_t *)rvdata.data; // In order to reuse the comparators, we have to track what passed and failed internally. @@ -53790,8 +58702,8 @@ void IsNullLoop(Vector &input, Vector &result, idx_t count) { auto result_data = ConstantVector::GetData(result); *result_data = INVERSE ? !ConstantVector::IsNull(input) : ConstantVector::IsNull(input); } else { - VectorData data; - input.Orrify(count, data); + UnifiedVectorFormat data; + input.ToUnifiedFormat(count, data); result.SetVectorType(VectorType::FLAT_VECTOR); auto result_data = FlatVector::GetData(result); @@ -53817,8 +58729,8 @@ bool VectorOperations::HasNotNull(Vector &input, idx_t count) { if (input.GetVectorType() == VectorType::CONSTANT_VECTOR) { return !ConstantVector::IsNull(input); } else { - VectorData data; - input.Orrify(count, data); + UnifiedVectorFormat data; + input.ToUnifiedFormat(count, data); if (data.validity.AllValid()) { return true; @@ -53840,8 +58752,8 @@ bool VectorOperations::HasNull(Vector &input, idx_t count) { if (input.GetVectorType() == VectorType::CONSTANT_VECTOR) { return ConstantVector::IsNull(input); } else { - VectorData data; - input.Orrify(count, data); + UnifiedVectorFormat data; + input.ToUnifiedFormat(count, data); if (data.validity.AllValid()) { return false; @@ -53859,8 +58771,8 @@ bool VectorOperations::HasNull(Vector &input, idx_t count) { idx_t VectorOperations::CountNotNull(Vector &input, const idx_t count) { idx_t valid = 0; - VectorData vdata; - input.Orrify(count, vdata); + UnifiedVectorFormat vdata; + input.ToUnifiedFormat(count, vdata); if (vdata.validity.AllValid()) { return count; } @@ -54076,9 +58988,9 @@ struct DecimalScaleInput { DecimalScaleInput(Vector &result_p, FACTOR_TYPE factor_p) : result(result_p), factor(factor_p) { } DecimalScaleInput(Vector &result_p, LIMIT_TYPE limit_p, FACTOR_TYPE factor_p, string *error_message_p, - uint8_t source_scale_p) + uint8_t source_width_p, uint8_t source_scale_p) : result(result_p), limit(limit_p), factor(factor_p), error_message(error_message_p), - source_scale(source_scale_p) { + source_width(source_width_p), source_scale(source_scale_p) { } Vector &result; @@ -54086,6 +58998,7 @@ struct DecimalScaleInput { FACTOR_TYPE factor; bool all_converted = true; string *error_message; + uint8_t source_width; uint8_t source_scale; }; @@ -54102,9 +59015,9 @@ struct DecimalScaleUpCheckOperator { static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) { auto data = (DecimalScaleInput *)dataptr; if (input >= data->limit || input <= -data->limit) { - auto error = - StringUtil::Format("Casting value \"%s\" to type %s failed: value is out of range!", - Decimal::ToString(input, data->source_scale), data->result.GetType().ToString()); + auto error = StringUtil::Format("Casting value \"%s\" to type %s failed: value is out of range!", + Decimal::ToString(input, data->source_width, data->source_scale), + data->result.GetType().ToString()); return HandleVectorCastError::Operation(move(error), mask, idx, data->error_message, data->all_converted); } @@ -54130,7 +59043,8 @@ bool TemplatedDecimalScaleUp(Vector &source, Vector &result, idx_t count, string } else { // type might not fit: check limit auto limit = POWERS_SOURCE::POWERS_OF_TEN[target_width]; - DecimalScaleInput input(result, limit, multiply_factor, error_message, source_scale); + DecimalScaleInput input(result, limit, multiply_factor, error_message, source_width, + source_scale); UnaryExecutor::GenericExecute(source, result, count, &input, error_message); return input.all_converted; @@ -54150,9 +59064,9 @@ struct DecimalScaleDownCheckOperator { static RESULT_TYPE Operation(INPUT_TYPE input, ValidityMask &mask, idx_t idx, void *dataptr) { auto data = (DecimalScaleInput *)dataptr; if (input >= data->limit || input <= -data->limit) { - auto error = - StringUtil::Format("Casting value \"%s\" to type %s failed: value is out of range!", - Decimal::ToString(input, data->source_scale), data->result.GetType().ToString()); + auto error = StringUtil::Format("Casting value \"%s\" to type %s failed: value is out of range!", + Decimal::ToString(input, data->source_width, data->source_scale), + data->result.GetType().ToString()); return HandleVectorCastError::Operation(move(error), mask, idx, data->error_message, data->all_converted); } @@ -54178,7 +59092,7 @@ bool TemplatedDecimalScaleDown(Vector &source, Vector &result, idx_t count, stri } else { // type might not fit: check limit auto limit = POWERS_SOURCE::POWERS_OF_TEN[target_width]; - DecimalScaleInput input(result, limit, divide_factor, error_message, source_scale); + DecimalScaleInput input(result, limit, divide_factor, error_message, source_width, source_scale); UnaryExecutor::GenericExecute(source, result, count, &input, error_message); return input.all_converted; @@ -54530,8 +59444,8 @@ bool TransformEnum(Vector &source, Vector &result, idx_t count, string *error_me error_message, nullptr); } default: { - VectorData vdata; - source.Orrify(count, vdata); + UnifiedVectorFormat vdata; + source.ToUnifiedFormat(count, vdata); result.SetVectorType(VectorType::FLAT_VECTOR); @@ -54894,14 +59808,14 @@ static bool ListCastSwitch(Vector &source, Vector &result, idx_t count, string * case LogicalTypeId::LIST: { // only handle constant and flat vectors here for now if (source.GetVectorType() == VectorType::CONSTANT_VECTOR) { - result.SetVectorType(source.GetVectorType()); + result.SetVectorType(VectorType::CONSTANT_VECTOR); ConstantVector::SetNull(result, ConstantVector::IsNull(source)); auto ldata = ConstantVector::GetData(source); auto tdata = ConstantVector::GetData(result); *tdata = *ldata; } else { - source.Normalify(count); + source.Flatten(count); result.SetVectorType(VectorType::FLAT_VECTOR); FlatVector::SetValidity(result, FlatVector::Validity(source)); @@ -54937,8 +59851,8 @@ bool FillEnum(Vector &source, Vector &result, idx_t count, string *error_message auto res_enum_type = result.GetType(); - VectorData vdata; - source.Orrify(count, vdata); + UnifiedVectorFormat vdata; + source.ToUnifiedFormat(count, vdata); auto source_data = (SRC_TYPE *)vdata.data; auto source_sel = vdata.sel; @@ -55095,7 +60009,7 @@ static bool StructCastSwitch(Vector &source, Vector &result, idx_t count, string result.SetVectorType(VectorType::CONSTANT_VECTOR); ConstantVector::SetNull(result, ConstantVector::IsNull(source)); } else { - source.Normalify(count); + source.Flatten(count); FlatVector::Validity(result) = FlatVector::Validity(source); } return true; @@ -55504,8 +60418,8 @@ static inline void TemplatedLoopHash(Vector &input, Vector &result, const Select } else { result.SetVectorType(VectorType::FLAT_VECTOR); - VectorData idata; - input.Orrify(count, idata); + UnifiedVectorFormat idata; + input.ToUnifiedFormat(count, idata); TightLoopHash((T *)idata.data, FlatVector::GetData(result), rsel, count, idata.sel, idata.validity); @@ -55514,7 +60428,6 @@ static inline void TemplatedLoopHash(Vector &input, Vector &result, const Select template static inline void StructLoopHash(Vector &input, Vector &hashes, const SelectionVector *rsel, idx_t count) { - input.Normalify(count); auto &children = StructVector::GetEntries(input); D_ASSERT(!children.empty()); @@ -55544,8 +60457,8 @@ template static inline void ListLoopHash(Vector &input, Vector &hashes, const SelectionVector *rsel, idx_t count) { auto hdata = FlatVector::GetData(hashes); - VectorData idata; - input.Orrify(count, idata); + UnifiedVectorFormat idata; + input.ToUnifiedFormat(count, idata); const auto ldata = (const list_entry_t *)idata.data; // Hash the children into a temporary @@ -55628,7 +60541,7 @@ static inline void ListLoopHash(Vector &input, Vector &hashes, const SelectionVe template static inline void HashTypeSwitch(Vector &input, Vector &result, const SelectionVector *rsel, idx_t count) { - D_ASSERT(result.GetType().id() == LogicalTypeId::HASH); + D_ASSERT(result.GetType().id() == LogicalType::HASH); switch (input.GetType().InternalType()) { case PhysicalType::BOOL: case PhysicalType::INT8: @@ -55740,8 +60653,8 @@ void TemplatedLoopCombineHash(Vector &input, Vector &hashes, const SelectionVect auto other_hash = HashOp::Operation(*ldata, ConstantVector::IsNull(input)); *hash_data = CombineHashScalar(*hash_data, other_hash); } else { - VectorData idata; - input.Orrify(count, idata); + UnifiedVectorFormat idata; + input.ToUnifiedFormat(count, idata); if (hashes.GetVectorType() == VectorType::CONSTANT_VECTOR) { // mix constant with non-constant, first get the constant value auto constant_hash = *ConstantVector::GetData(hashes); @@ -55760,7 +60673,7 @@ void TemplatedLoopCombineHash(Vector &input, Vector &hashes, const SelectionVect template static inline void CombineHashTypeSwitch(Vector &hashes, Vector &input, const SelectionVector *rsel, idx_t count) { - D_ASSERT(hashes.GetType().id() == LogicalTypeId::HASH); + D_ASSERT(hashes.GetType().id() == LogicalType::HASH); switch (input.GetType().InternalType()) { case PhysicalType::BOOL: case PhysicalType::INT8: @@ -55830,7 +60743,7 @@ void VectorOperations::CombineHash(Vector &hashes, Vector &input, const Selectio namespace duckdb { template -static void CopyToStorageLoop(VectorData &vdata, idx_t count, data_ptr_t target) { +static void CopyToStorageLoop(UnifiedVectorFormat &vdata, idx_t count, data_ptr_t target) { auto ldata = (T *)vdata.data; auto result_data = (T *)target; for (idx_t i = 0; i < count; i++) { @@ -55847,8 +60760,8 @@ void VectorOperations::WriteToStorage(Vector &source, idx_t count, data_ptr_t ta if (count == 0) { return; } - VectorData vdata; - source.Orrify(count, vdata); + UnifiedVectorFormat vdata; + source.ToUnifiedFormat(count, vdata); switch (source.GetType().InternalType()) { case PhysicalType::BOOL: @@ -56166,85 +61079,6 @@ string WindowsUtil::UTF8ToMBCS(const char *input, bool use_ansi) { } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/table_filter.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - - -namespace duckdb { -class BaseStatistics; - -enum class TableFilterType : uint8_t { - CONSTANT_COMPARISON = 0, // constant comparison (e.g. =C, >C, >=C, > filters; - -public: - void PushFilter(idx_t table_index, unique_ptr filter); - - bool Equals(TableFilterSet &other) { - if (filters.size() != other.filters.size()) { - return false; - } - for (auto &entry : filters) { - auto other_entry = other.filters.find(entry.first); - if (other_entry == other.filters.end()) { - return false; - } - if (!entry.second->Equals(*other_entry->second)) { - return false; - } - } - return true; - } - static bool Equals(TableFilterSet *left, TableFilterSet *right) { - if (left == right) { - return true; - } - if (!left || !right) { - return false; - } - return left->Equals(*right); - } -}; - -} // namespace duckdb #include @@ -56353,26 +61187,29 @@ namespace duckdb { using ValidityBytes = RowLayout::ValidityBytes; -GroupedAggregateHashTable::GroupedAggregateHashTable(BufferManager &buffer_manager, vector group_types, - vector payload_types, +GroupedAggregateHashTable::GroupedAggregateHashTable(Allocator &allocator, BufferManager &buffer_manager, + vector group_types, vector payload_types, const vector &bindings, HtEntryType entry_type) - : GroupedAggregateHashTable(buffer_manager, move(group_types), move(payload_types), + : GroupedAggregateHashTable(allocator, buffer_manager, move(group_types), move(payload_types), AggregateObject::CreateAggregateObjects(bindings), entry_type) { } -GroupedAggregateHashTable::GroupedAggregateHashTable(BufferManager &buffer_manager, vector group_types) - : GroupedAggregateHashTable(buffer_manager, move(group_types), {}, vector()) { +GroupedAggregateHashTable::GroupedAggregateHashTable(Allocator &allocator, BufferManager &buffer_manager, + vector group_types) + : GroupedAggregateHashTable(allocator, buffer_manager, move(group_types), {}, vector()) { } -GroupedAggregateHashTable::GroupedAggregateHashTable(BufferManager &buffer_manager, vector group_types_p, +GroupedAggregateHashTable::GroupedAggregateHashTable(Allocator &allocator, BufferManager &buffer_manager, + vector group_types_p, vector payload_types_p, vector aggregate_objects_p, HtEntryType entry_type) - : BaseAggregateHashTable(buffer_manager, move(payload_types_p)), entry_type(entry_type), capacity(0), entries(0), - payload_page_offset(0), is_finalized(false), ht_offsets(LogicalTypeId::BIGINT), - hash_salts(LogicalTypeId::SMALLINT), group_compare_vector(STANDARD_VECTOR_SIZE), - no_match_vector(STANDARD_VECTOR_SIZE), empty_vector(STANDARD_VECTOR_SIZE) { + : BaseAggregateHashTable(allocator, aggregate_objects_p, buffer_manager, move(payload_types_p)), + entry_type(entry_type), capacity(0), entries(0), payload_page_offset(0), is_finalized(false), + ht_offsets(LogicalTypeId::BIGINT), hash_salts(LogicalTypeId::SMALLINT), + group_compare_vector(STANDARD_VECTOR_SIZE), no_match_vector(STANDARD_VECTOR_SIZE), + empty_vector(STANDARD_VECTOR_SIZE) { // Append hash column to the end and initialise the row layout group_types_p.emplace_back(LogicalType::HASH); @@ -56386,17 +61223,17 @@ GroupedAggregateHashTable::GroupedAggregateHashTable(BufferManager &buffer_manag D_ASSERT(tuple_size <= Storage::BLOCK_SIZE); tuples_per_block = Storage::BLOCK_SIZE / tuple_size; hashes_hdl = buffer_manager.Allocate(Storage::BLOCK_SIZE); - hashes_hdl_ptr = hashes_hdl->Ptr(); + hashes_hdl_ptr = hashes_hdl.Ptr(); switch (entry_type) { case HtEntryType::HT_WIDTH_64: { hash_prefix_shift = (HASH_WIDTH - sizeof(aggr_ht_entry_64::salt)) * 8; - Resize(STANDARD_VECTOR_SIZE * 2); + Resize(STANDARD_VECTOR_SIZE * 2L); break; } case HtEntryType::HT_WIDTH_32: { hash_prefix_shift = (HASH_WIDTH - sizeof(aggr_ht_entry_32::salt)) * 8; - Resize(STANDARD_VECTOR_SIZE * 2); + Resize(STANDARD_VECTOR_SIZE * 2L); break; } default: @@ -56417,7 +61254,8 @@ GroupedAggregateHashTable::GroupedAggregateHashTable(BufferManager &buffer_manag for (idx_t child_idx = 0; child_idx < aggr.child_count; child_idx++) { distinct_group_types.push_back(payload_types[payload_idx + child_idx]); } - distinct_hashes[i] = make_unique(buffer_manager, distinct_group_types); + distinct_hashes[i] = + make_unique(allocator, buffer_manager, distinct_group_types); } payload_idx += aggr.child_count; } @@ -56454,7 +61292,7 @@ void GroupedAggregateHashTable::PayloadApply(FUNC fun) { void GroupedAggregateHashTable::NewBlock() { auto pin = buffer_manager.Allocate(Storage::BLOCK_SIZE); payload_hds.push_back(move(pin)); - payload_hds_ptrs.push_back(payload_hds.back()->Ptr()); + payload_hds_ptrs.push_back(payload_hds.back().Ptr()); payload_page_offset = 0; } @@ -56554,7 +61392,7 @@ void GroupedAggregateHashTable::Resize(idx_t size) { auto byte_size = size * sizeof(ENTRY); if (byte_size > (idx_t)Storage::BLOCK_SIZE) { hashes_hdl = buffer_manager.Allocate(byte_size); - hashes_hdl_ptr = hashes_hdl->Ptr(); + hashes_hdl_ptr = hashes_hdl.Ptr(); } memset(hashes_hdl_ptr, 0, byte_size); hashes_end_ptr = hashes_hdl_ptr + byte_size; @@ -56624,7 +61462,7 @@ idx_t GroupedAggregateHashTable::AddChunk(DataChunk &groups, Vector &group_hashe probe_types.push_back(payload_types[payload_idx + i]); } DataChunk probe_chunk; - probe_chunk.Initialize(probe_types); + probe_chunk.Initialize(Allocator::DefaultAllocator(), probe_types); for (idx_t group_idx = 0; group_idx < groups.ColumnCount(); group_idx++) { probe_chunk.data[group_idx].Reference(groups.data[group_idx]); } @@ -56643,7 +61481,7 @@ idx_t GroupedAggregateHashTable::AddChunk(DataChunk &groups, Vector &group_hashe // now fix up the payload and addresses accordingly by creating // a selection vector DataChunk distinct_payload; - distinct_payload.Initialize(payload.GetTypes()); + distinct_payload.Initialize(Allocator::DefaultAllocator(), payload.GetTypes()); distinct_payload.Slice(payload, new_groups, new_group_count); distinct_payload.Verify(); @@ -56651,15 +61489,17 @@ idx_t GroupedAggregateHashTable::AddChunk(DataChunk &groups, Vector &group_hashe distinct_addresses.Verify(new_group_count); if (aggr.filter) { - distinct_addresses.Normalify(new_group_count); - RowOperations::UpdateFilteredStates(aggr, distinct_addresses, distinct_payload, payload_idx); + distinct_addresses.Flatten(new_group_count); + RowOperations::UpdateFilteredStates(filter_set.GetFilterData(aggr_idx), aggr, distinct_addresses, + distinct_payload, payload_idx); } else { RowOperations::UpdateStates(aggr, distinct_addresses, distinct_payload, payload_idx, new_group_count); } } } else if (aggr.filter) { - RowOperations::UpdateFilteredStates(aggr, addresses, payload, payload_idx); + RowOperations::UpdateFilteredStates(filter_set.GetFilterData(aggr_idx), aggr, addresses, payload, + payload_idx); } else { RowOperations::UpdateStates(aggr, addresses, payload, payload_idx, payload.size()); } @@ -56711,14 +61551,14 @@ idx_t GroupedAggregateHashTable::FindOrCreateGroupsInternal(DataChunk &groups, V D_ASSERT(capacity - entries >= groups.size()); D_ASSERT(group_hashes.GetType() == LogicalType::HASH); - group_hashes.Normalify(groups.size()); + group_hashes.Flatten(groups.size()); auto group_hashes_ptr = FlatVector::GetData(group_hashes); D_ASSERT(ht_offsets.GetVectorType() == VectorType::FLAT_VECTOR); D_ASSERT(ht_offsets.GetType() == LogicalType::BIGINT); D_ASSERT(addresses.GetType() == LogicalType::POINTER); - addresses.Normalify(groups.size()); + addresses.Flatten(groups.size()); auto addresses_ptr = FlatVector::GetData(addresses); // now compute the entry in the table based on the hash using a modulo @@ -56748,8 +61588,8 @@ idx_t GroupedAggregateHashTable::FindOrCreateGroupsInternal(DataChunk &groups, V group_chunk.data[groups.ColumnCount()].Reference(group_hashes); group_chunk.SetCardinality(groups); - // orrify all the groups - auto group_data = group_chunk.Orrify(); + // convert all vectors to unified format + auto group_data = group_chunk.ToUnifiedFormat(); idx_t new_group_count = 0; while (remaining_entries > 0) { @@ -56856,31 +61696,39 @@ idx_t GroupedAggregateHashTable::FindOrCreateGroups(DataChunk &groups, Vector &a return FindOrCreateGroups(groups, hashes, addresses_out, new_groups_out); } -void GroupedAggregateHashTable::FlushMove(Vector &source_addresses, Vector &source_hashes, idx_t count) { +struct FlushMoveState { + FlushMoveState(Allocator &allocator, RowLayout &layout) + : new_groups(STANDARD_VECTOR_SIZE), group_addresses(LogicalType::POINTER), + new_groups_sel(STANDARD_VECTOR_SIZE) { + vector group_types(layout.GetTypes().begin(), layout.GetTypes().end() - 1); + groups.Initialize(allocator, group_types); + } + + DataChunk groups; + SelectionVector new_groups; + Vector group_addresses; + SelectionVector new_groups_sel; +}; + +void GroupedAggregateHashTable::FlushMove(FlushMoveState &state, Vector &source_addresses, Vector &source_hashes, + idx_t count) { D_ASSERT(source_addresses.GetType() == LogicalType::POINTER); D_ASSERT(source_hashes.GetType() == LogicalType::HASH); - DataChunk groups; - groups.Initialize(vector(layout.GetTypes().begin(), layout.GetTypes().end() - 1)); - groups.SetCardinality(count); - for (idx_t i = 0; i < groups.ColumnCount(); i++) { - auto &column = groups.data[i]; - const auto col_offset = layout.GetOffsets()[i]; + state.groups.Reset(); + state.groups.SetCardinality(count); + for (idx_t col_no = 0; col_no < state.groups.ColumnCount(); col_no++) { + auto &column = state.groups.data[col_no]; RowOperations::Gather(source_addresses, *FlatVector::IncrementalSelectionVector(), column, - *FlatVector::IncrementalSelectionVector(), count, col_offset, i); + *FlatVector::IncrementalSelectionVector(), count, layout, col_no); } - SelectionVector new_groups(STANDARD_VECTOR_SIZE); - Vector group_addresses(LogicalType::POINTER); - SelectionVector new_groups_sel(STANDARD_VECTOR_SIZE); - - FindOrCreateGroups(groups, source_hashes, group_addresses, new_groups_sel); + FindOrCreateGroups(state.groups, source_hashes, state.group_addresses, state.new_groups_sel); - RowOperations::CombineStates(layout, source_addresses, group_addresses, count); + RowOperations::CombineStates(layout, source_addresses, state.group_addresses, count); } void GroupedAggregateHashTable::Combine(GroupedAggregateHashTable &other) { - D_ASSERT(!is_finalized); D_ASSERT(other.layout.GetAggrWidth() == layout.GetAggrWidth()); @@ -56900,6 +61748,7 @@ void GroupedAggregateHashTable::Combine(GroupedAggregateHashTable &other) { idx_t group_idx = 0; + FlushMoveState state(allocator, layout); other.PayloadApply([&](idx_t page_nr, idx_t page_offset, data_ptr_t ptr) { auto hash = Load(ptr + hash_offset); @@ -56907,11 +61756,11 @@ void GroupedAggregateHashTable::Combine(GroupedAggregateHashTable &other) { addresses_ptr[group_idx] = ptr; group_idx++; if (group_idx == STANDARD_VECTOR_SIZE) { - FlushMove(addresses, hashes, group_idx); + FlushMove(state, addresses, hashes, group_idx); group_idx = 0; } }); - FlushMove(addresses, hashes, group_idx); + FlushMove(state, addresses, hashes, group_idx); string_heap->Merge(*other.string_heap); Verify(); } @@ -56933,6 +61782,7 @@ void GroupedAggregateHashTable::Partition(vector &p D_ASSERT(partition_hts.size() > 1); vector partition_info(partition_hts.size()); + FlushMoveState state(allocator, layout); PayloadApply([&](idx_t page_nr, idx_t page_offset, data_ptr_t ptr) { auto hash = Load(ptr + hash_offset); @@ -56946,7 +61796,7 @@ void GroupedAggregateHashTable::Partition(vector &p info.group_count++; if (info.group_count == STANDARD_VECTOR_SIZE) { D_ASSERT(partition_hts[partition]); - partition_hts[partition]->FlushMove(info.addresses, info.hashes, info.group_count); + partition_hts[partition]->FlushMove(state, info.addresses, info.hashes, info.group_count); info.group_count = 0; } }); @@ -56955,7 +61805,7 @@ void GroupedAggregateHashTable::Partition(vector &p idx_t total_count = 0; for (auto &partition_entry : partition_hts) { auto &info = partition_info[info_idx++]; - partition_entry->FlushMove(info.addresses, info.hashes, info.group_count); + partition_entry->FlushMove(state, info.addresses, info.hashes, info.group_count); partition_entry->string_heap->Merge(*string_heap); partition_entry->Verify(); @@ -56965,15 +61815,15 @@ void GroupedAggregateHashTable::Partition(vector &p } idx_t GroupedAggregateHashTable::Scan(idx_t &scan_position, DataChunk &result) { - Vector addresses(LogicalType::POINTER); - auto data_pointers = FlatVector::GetData(addresses); - - auto remaining = entries - scan_position; - if (remaining == 0) { + if (scan_position >= entries) { return 0; } + auto remaining = entries - scan_position; auto this_n = MinValue((idx_t)STANDARD_VECTOR_SIZE, remaining); + Vector addresses(LogicalType::POINTER); + auto data_pointers = FlatVector::GetData(addresses); + auto chunk_idx = scan_position / tuples_per_block; auto chunk_offset = (scan_position % tuples_per_block) * tuple_size; D_ASSERT(chunk_offset + tuple_size <= Storage::BLOCK_SIZE); @@ -56991,11 +61841,10 @@ idx_t GroupedAggregateHashTable::Scan(idx_t &scan_position, DataChunk &result) { result.SetCardinality(this_n); // fetch the group columns (ignoring the final hash column const auto group_cols = layout.ColumnCount() - 1; - for (idx_t i = 0; i < group_cols; i++) { - auto &column = result.data[i]; - const auto col_offset = layout.GetOffsets()[i]; + for (idx_t col_no = 0; col_no < group_cols; col_no++) { + auto &column = result.data[col_no]; RowOperations::Gather(addresses, *FlatVector::IncrementalSelectionVector(), column, - *FlatVector::IncrementalSelectionVector(), result.size(), col_offset, i); + *FlatVector::IncrementalSelectionVector(), result.size(), layout, col_no); } RowOperations::FinalizeStates(layout, addresses, result, group_cols); @@ -57010,7 +61859,7 @@ void GroupedAggregateHashTable::Finalize() { } // early release hashes, not needed for partition/scan - hashes_hdl.reset(); + hashes_hdl.Destroy(); is_finalized = true; } @@ -57020,8 +61869,10 @@ void GroupedAggregateHashTable::Finalize() { namespace duckdb { -BaseAggregateHashTable::BaseAggregateHashTable(BufferManager &buffer_manager, vector payload_types_p) - : buffer_manager(buffer_manager), payload_types(move(payload_types_p)) { +BaseAggregateHashTable::BaseAggregateHashTable(Allocator &allocator, const vector &aggregates, + BufferManager &buffer_manager, vector payload_types_p) + : allocator(allocator), buffer_manager(buffer_manager), payload_types(move(payload_types_p)) { + filter_set.Initialize(allocator, aggregates, payload_types); } } // namespace duckdb @@ -57036,41 +61887,6 @@ BaseAggregateHashTable::BaseAggregateHashTable(BufferManager &buffer_manager, ve -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/column_binding_map.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - - -namespace duckdb { - -struct ColumnBindingHashFunction { - uint64_t operator()(const ColumnBinding &a) const { - return CombineHash(Hash(a.table_index), Hash(a.column_index)); - } -}; - -struct ColumnBindingEquality { - bool operator()(const ColumnBinding &a, const ColumnBinding &b) const { - return a == b; - } -}; - -template -using column_binding_map_t = unordered_map; - -using column_binding_set_t = unordered_set; - -} // namespace duckdb @@ -57129,6 +61945,12 @@ struct JoinCondition { //! Turns the JoinCondition into an expression; note that this destroys the JoinCondition as the expression inherits //! the left/right expressions static unique_ptr CreateExpression(JoinCondition cond); + static unique_ptr CreateExpression(vector conditions); + + //! Serializes a JoinCondition to a stand-alone binary blob + void Serialize(Serializer &serializer) const; + //! Deserializes a blob back into a JoinCondition + static JoinCondition Deserialize(Deserializer &source, PlanDeserializationState &state); public: unique_ptr left; @@ -57204,6 +62026,8 @@ class LogicalJoin : public LogicalOperator { public: vector GetColumnBindings() override; + void Serialize(FieldWriter &writer) const override; + static void Deserialize(LogicalJoin &join, LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override; @@ -57227,6 +62051,10 @@ class LogicalComparisonJoin : public LogicalJoin { public: string ParamsToString() const override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + static void Deserialize(LogicalComparisonJoin &comparison_join, LogicalDeserializationState &state, + FieldReader &reader); public: static unique_ptr CreateJoin(JoinType type, unique_ptr left_child, @@ -57274,6 +62102,10 @@ class LogicalCreateIndex : public LogicalOperator { //! Unbound expressions to be used in the optimizer vector> unbound_expressions; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { types.emplace_back(LogicalType::BIGINT); @@ -57299,11 +62131,14 @@ namespace duckdb { //! flattening, and involves performing duplicate elimination on the LEFT side which is then pushed into the RIGHT side. class LogicalDelimJoin : public LogicalComparisonJoin { public: - explicit LogicalDelimJoin(JoinType type) : LogicalComparisonJoin(type, LogicalOperatorType::LOGICAL_DELIM_JOIN) { - } + explicit LogicalDelimJoin(JoinType type); //! The set of columns that will be duplicate eliminated from the LHS and pushed into the RHS vector> duplicate_eliminated_columns; + +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -57655,8 +62490,8 @@ void TemplatedFillLoop(Vector &vector, Vector &result, const SelectionVector &se } } } else { - VectorData vdata; - vector.Orrify(count, vdata); + UnifiedVectorFormat vdata; + vector.ToUnifiedFormat(count, vdata); auto data = (T *)vdata.data; for (idx_t i = 0; i < count; i++) { auto source_idx = vdata.sel->get_index(i); @@ -57678,8 +62513,8 @@ void ValidityFillLoop(Vector &vector, Vector &result, const SelectionVector &sel } } } else { - VectorData vdata; - vector.Orrify(count, vdata); + UnifiedVectorFormat vdata; + vector.ToUnifiedFormat(count, vdata); if (vdata.validity.AllValid()) { return; } @@ -57960,9 +62795,9 @@ idx_t NestedSelector::Select(Vector &left, Vector &ri static inline idx_t SelectNotNull(Vector &left, Vector &right, const idx_t count, const SelectionVector &sel, SelectionVector &maybe_vec, OptionalSelection &false_opt) { - VectorData lvdata, rvdata; - left.Orrify(count, lvdata); - right.Orrify(count, rvdata); + UnifiedVectorFormat lvdata, rvdata; + left.ToUnifiedFormat(count, lvdata); + right.ToUnifiedFormat(count, rvdata); auto &lmask = lvdata.validity; auto &rmask = rvdata.validity; @@ -58305,6 +63140,39 @@ unique_ptr ExpressionExecutor::InitializeState(const BoundFunct return move(result); } +static void VerifyNullHandling(const BoundFunctionExpression &expr, DataChunk &args, Vector &result) { +#ifdef DEBUG + if (args.data.empty() || expr.function.null_handling != FunctionNullHandling::DEFAULT_NULL_HANDLING) { + return; + } + + // Combine all the argument validity masks into a flat validity mask + idx_t count = args.size(); + ValidityMask combined_mask(count); + for (auto &arg : args.data) { + UnifiedVectorFormat arg_data; + arg.ToUnifiedFormat(count, arg_data); + + for (idx_t i = 0; i < count; i++) { + auto idx = arg_data.sel->get_index(i); + if (!arg_data.validity.RowIsValid(idx)) { + combined_mask.SetInvalid(i); + } + } + } + + // Default is that if any of the arguments are NULL, the result is also NULL + UnifiedVectorFormat result_data; + result.ToUnifiedFormat(count, result_data); + for (idx_t i = 0; i < count; i++) { + if (!combined_mask.RowIsValid(i)) { + auto idx = result_data.sel->get_index(i); + D_ASSERT(!result_data.validity.RowIsValid(idx)); + } + } +#endif +} + void ExpressionExecutor::Execute(const BoundFunctionExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, Vector &result) { state->intermediate_chunk.Reset(); @@ -58322,9 +63190,13 @@ void ExpressionExecutor::Execute(const BoundFunctionExpression &expr, Expression arguments.Verify(); } arguments.SetCardinality(count); + state->profiler.BeginSample(); + D_ASSERT(expr.function.function); expr.function.function(arguments, *state, result); state->profiler.EndSample(count); + + VerifyNullHandling(expr, arguments, result); D_ASSERT(result.GetType() == expr.return_type); } @@ -58404,8 +63276,8 @@ void ExpressionExecutor::Execute(const BoundOperatorExpression &expr, Expression Execute(*expr.children[child], state->child_states[child].get(), current_sel, remaining_count, vector_to_check); - VectorData vdata; - vector_to_check.Orrify(remaining_count, vdata); + UnifiedVectorFormat vdata; + vector_to_check.ToUnifiedFormat(remaining_count, vdata); idx_t result_count = 0; next_count = 0; @@ -58482,9 +63354,10 @@ unique_ptr ExpressionExecutor::InitializeState(const BoundParam void ExpressionExecutor::Execute(const BoundParameterExpression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, Vector &result) { - D_ASSERT(expr.value); - D_ASSERT(expr.value->type() == expr.return_type); - result.Reference(*expr.value); + D_ASSERT(expr.parameter_data); + D_ASSERT(expr.parameter_data->return_type == expr.return_type); + D_ASSERT(expr.parameter_data->value.type() == expr.return_type); + result.Reference(expr.parameter_data->value); } } // namespace duckdb @@ -58504,6 +63377,7 @@ void ExpressionExecutor::Execute(const BoundReferenceExpression &expr, Expressio const SelectionVector *sel, idx_t count, Vector &result) { D_ASSERT(expr.index != DConstants::INVALID_INDEX); D_ASSERT(expr.index < chunk->ColumnCount()); + if (sel) { result.Slice(chunk->data[expr.index], *sel, count); } else { @@ -58520,19 +63394,22 @@ void ExpressionExecutor::Execute(const BoundReferenceExpression &expr, Expressio namespace duckdb { -ExpressionExecutor::ExpressionExecutor() { +ExpressionExecutor::ExpressionExecutor(Allocator &allocator) : allocator(allocator) { } -ExpressionExecutor::ExpressionExecutor(const Expression *expression) : ExpressionExecutor() { +ExpressionExecutor::ExpressionExecutor(Allocator &allocator, const Expression *expression) + : ExpressionExecutor(allocator) { D_ASSERT(expression); AddExpression(*expression); } -ExpressionExecutor::ExpressionExecutor(const Expression &expression) : ExpressionExecutor() { +ExpressionExecutor::ExpressionExecutor(Allocator &allocator, const Expression &expression) + : ExpressionExecutor(allocator) { AddExpression(expression); } -ExpressionExecutor::ExpressionExecutor(const vector> &exprs) : ExpressionExecutor() { +ExpressionExecutor::ExpressionExecutor(Allocator &allocator, const vector> &exprs) + : ExpressionExecutor(allocator) { D_ASSERT(exprs.size() > 0); for (auto &expr : exprs) { AddExpression(*expr); @@ -58547,8 +63424,8 @@ void ExpressionExecutor::AddExpression(const Expression &expr) { } void ExpressionExecutor::Initialize(const Expression &expression, ExpressionExecutorState &state) { - state.root_state = InitializeState(expression, state); state.executor = this; + state.root_state = InitializeState(expression, state); } void ExpressionExecutor::Execute(DataChunk *input, DataChunk &result) { @@ -58590,16 +63467,16 @@ void ExpressionExecutor::ExecuteExpression(idx_t expr_idx, Vector &result) { states[expr_idx]->profiler.EndSample(chunk ? chunk->size() : 0); } -Value ExpressionExecutor::EvaluateScalar(const Expression &expr) { - D_ASSERT(expr.IsFoldable()); +Value ExpressionExecutor::EvaluateScalar(const Expression &expr, bool allow_unfoldable) { + D_ASSERT(allow_unfoldable || expr.IsFoldable()); D_ASSERT(expr.IsScalar()); // use an ExpressionExecutor to execute the expression - ExpressionExecutor executor(expr); + ExpressionExecutor executor(Allocator::DefaultAllocator(), expr); Vector result(expr.return_type); executor.ExecuteExpression(result); - D_ASSERT(result.GetVectorType() == VectorType::CONSTANT_VECTOR); + D_ASSERT(allow_unfoldable || result.GetVectorType() == VectorType::CONSTANT_VECTOR); auto result_value = result.GetValue(0); D_ASSERT(result_value.type().InternalType() == expr.return_type.InternalType()); return result_value; @@ -58609,6 +63486,8 @@ bool ExpressionExecutor::TryEvaluateScalar(const Expression &expr, Value &result try { result = EvaluateScalar(expr); return true; + } catch (InternalException &ex) { + throw ex; } catch (...) { return false; } @@ -58653,6 +63532,7 @@ unique_ptr ExpressionExecutor::InitializeState(const Expression void ExpressionExecutor::Execute(const Expression &expr, ExpressionState *state, const SelectionVector *sel, idx_t count, Vector &result) { #ifdef DEBUG + //! The result Vector must be "clean" if (result.GetVectorType() == VectorType::FLAT_VECTOR) { D_ASSERT(FlatVector::Validity(result).CheckAllValid(count)); } @@ -58743,7 +63623,7 @@ static inline idx_t DefaultSelectLoop(const SelectionVector *bsel, uint8_t *__re } template -static inline idx_t DefaultSelectSwitch(VectorData &idata, const SelectionVector *sel, idx_t count, +static inline idx_t DefaultSelectSwitch(UnifiedVectorFormat &idata, const SelectionVector *sel, idx_t count, SelectionVector *true_sel, SelectionVector *false_sel) { if (true_sel && false_sel) { return DefaultSelectLoop(idata.sel, (uint8_t *)idata.data, idata.validity, sel, count, @@ -58767,8 +63647,8 @@ idx_t ExpressionExecutor::DefaultSelect(const Expression &expr, ExpressionState Vector intermediate(LogicalType::BOOLEAN, (data_ptr_t)intermediate_bools); Execute(expr, state, sel, count, intermediate); - VectorData idata; - intermediate.Orrify(count, idata); + UnifiedVectorFormat idata; + intermediate.ToUnifiedFormat(count, idata); if (!sel) { sel = FlatVector::IncrementalSelectionVector(); @@ -58798,7 +63678,7 @@ void ExpressionState::AddChild(Expression *expr) { void ExpressionState::Finalize() { if (!types.empty()) { - intermediate_chunk.Initialize(types); + intermediate_chunk.Initialize(root.executor->allocator, types); } } ExpressionState::ExpressionState(const Expression &expr, ExpressionExecutorState &root) @@ -58821,11 +63701,13 @@ ExpressionExecutorState::ExpressionExecutorState(const string &name) : profiler( namespace duckdb { ART::ART(const vector &column_ids, const vector> &unbound_expressions, - IndexConstraintType constraint_type) - : Index(IndexType::ART, column_ids, unbound_expressions, constraint_type) { - tree = nullptr; - expression_result.Initialize(logical_types); - is_little_endian = Radix::IsLittleEndian(); + IndexConstraintType constraint_type, DatabaseInstance &db, idx_t block_id, idx_t block_offset) + : Index(IndexType::ART, column_ids, unbound_expressions, constraint_type), db(db) { + if (block_id != DConstants::INVALID_INDEX) { + tree = Node::Deserialize(*this, block_id, block_offset); + } else { + tree = nullptr; + } for (idx_t i = 0; i < types.size(); i++) { switch (types[i]) { case PhysicalType::BOOL: @@ -58849,18 +63731,10 @@ ART::ART(const vector &column_ids, const vector } ART::~ART() { -} - -bool ART::LeafMatches(Node *node, Key &key, unsigned depth) { - auto leaf = static_cast(node); - Key &leaf_key = *leaf->value; - for (idx_t i = depth; i < leaf_key.len; i++) { - if (leaf_key[i] != key[i]) { - return false; - } + if (tree) { + delete tree; + tree = nullptr; } - - return true; } unique_ptr ART::InitializeScanSinglePredicate(Transaction &transaction, Value value, @@ -58886,15 +63760,15 @@ unique_ptr ART::InitializeScanTwoPredicates(Transaction &transac // Insert //===--------------------------------------------------------------------===// template -static void TemplatedGenerateKeys(Vector &input, idx_t count, vector> &keys, bool is_little_endian) { - VectorData idata; - input.Orrify(count, idata); +static void TemplatedGenerateKeys(Vector &input, idx_t count, vector> &keys) { + UnifiedVectorFormat idata; + input.ToUnifiedFormat(count, idata); auto input_data = (T *)idata.data; for (idx_t i = 0; i < count; i++) { auto idx = idata.sel->get_index(i); if (idata.validity.RowIsValid(idx)) { - keys.push_back(Key::CreateKey(input_data[idx], is_little_endian)); + keys.push_back(Key::CreateKey(input_data[idx])); } else { keys.push_back(nullptr); } @@ -58902,9 +63776,9 @@ static void TemplatedGenerateKeys(Vector &input, idx_t count, vector -static void ConcatenateKeys(Vector &input, idx_t count, vector> &keys, bool is_little_endian) { - VectorData idata; - input.Orrify(count, idata); +static void ConcatenateKeys(Vector &input, idx_t count, vector> &keys) { + UnifiedVectorFormat idata; + input.ToUnifiedFormat(count, idata); auto input_data = (T *)idata.data; for (idx_t i = 0; i < count; i++) { @@ -58915,7 +63789,7 @@ static void ConcatenateKeys(Vector &input, idx_t count, vector> } else { // concatenate the keys auto old_key = move(keys[i]); - auto new_key = Key::CreateKey(input_data[idx], is_little_endian); + auto new_key = Key::CreateKey(input_data[idx]); auto key_len = old_key->len + new_key->len; auto compound_data = unique_ptr(new data_t[key_len]); memcpy(compound_data.get(), old_key->data.get(), old_key->len); @@ -58930,43 +63804,43 @@ void ART::GenerateKeys(DataChunk &input, vector> &keys) { // generate keys for the first input column switch (input.data[0].GetType().InternalType()) { case PhysicalType::BOOL: - TemplatedGenerateKeys(input.data[0], input.size(), keys, is_little_endian); + TemplatedGenerateKeys(input.data[0], input.size(), keys); break; case PhysicalType::INT8: - TemplatedGenerateKeys(input.data[0], input.size(), keys, is_little_endian); + TemplatedGenerateKeys(input.data[0], input.size(), keys); break; case PhysicalType::INT16: - TemplatedGenerateKeys(input.data[0], input.size(), keys, is_little_endian); + TemplatedGenerateKeys(input.data[0], input.size(), keys); break; case PhysicalType::INT32: - TemplatedGenerateKeys(input.data[0], input.size(), keys, is_little_endian); + TemplatedGenerateKeys(input.data[0], input.size(), keys); break; case PhysicalType::INT64: - TemplatedGenerateKeys(input.data[0], input.size(), keys, is_little_endian); + TemplatedGenerateKeys(input.data[0], input.size(), keys); break; case PhysicalType::INT128: - TemplatedGenerateKeys(input.data[0], input.size(), keys, is_little_endian); + TemplatedGenerateKeys(input.data[0], input.size(), keys); break; case PhysicalType::UINT8: - TemplatedGenerateKeys(input.data[0], input.size(), keys, is_little_endian); + TemplatedGenerateKeys(input.data[0], input.size(), keys); break; case PhysicalType::UINT16: - TemplatedGenerateKeys(input.data[0], input.size(), keys, is_little_endian); + TemplatedGenerateKeys(input.data[0], input.size(), keys); break; case PhysicalType::UINT32: - TemplatedGenerateKeys(input.data[0], input.size(), keys, is_little_endian); + TemplatedGenerateKeys(input.data[0], input.size(), keys); break; case PhysicalType::UINT64: - TemplatedGenerateKeys(input.data[0], input.size(), keys, is_little_endian); + TemplatedGenerateKeys(input.data[0], input.size(), keys); break; case PhysicalType::FLOAT: - TemplatedGenerateKeys(input.data[0], input.size(), keys, is_little_endian); + TemplatedGenerateKeys(input.data[0], input.size(), keys); break; case PhysicalType::DOUBLE: - TemplatedGenerateKeys(input.data[0], input.size(), keys, is_little_endian); + TemplatedGenerateKeys(input.data[0], input.size(), keys); break; case PhysicalType::VARCHAR: - TemplatedGenerateKeys(input.data[0], input.size(), keys, is_little_endian); + TemplatedGenerateKeys(input.data[0], input.size(), keys); break; default: throw InternalException("Invalid type for index"); @@ -58976,43 +63850,43 @@ void ART::GenerateKeys(DataChunk &input, vector> &keys) { // for each of the remaining columns, concatenate switch (input.data[i].GetType().InternalType()) { case PhysicalType::BOOL: - ConcatenateKeys(input.data[i], input.size(), keys, is_little_endian); + ConcatenateKeys(input.data[i], input.size(), keys); break; case PhysicalType::INT8: - ConcatenateKeys(input.data[i], input.size(), keys, is_little_endian); + ConcatenateKeys(input.data[i], input.size(), keys); break; case PhysicalType::INT16: - ConcatenateKeys(input.data[i], input.size(), keys, is_little_endian); + ConcatenateKeys(input.data[i], input.size(), keys); break; case PhysicalType::INT32: - ConcatenateKeys(input.data[i], input.size(), keys, is_little_endian); + ConcatenateKeys(input.data[i], input.size(), keys); break; case PhysicalType::INT64: - ConcatenateKeys(input.data[i], input.size(), keys, is_little_endian); + ConcatenateKeys(input.data[i], input.size(), keys); break; case PhysicalType::INT128: - ConcatenateKeys(input.data[i], input.size(), keys, is_little_endian); + ConcatenateKeys(input.data[i], input.size(), keys); break; case PhysicalType::UINT8: - ConcatenateKeys(input.data[i], input.size(), keys, is_little_endian); + ConcatenateKeys(input.data[i], input.size(), keys); break; case PhysicalType::UINT16: - ConcatenateKeys(input.data[i], input.size(), keys, is_little_endian); + ConcatenateKeys(input.data[i], input.size(), keys); break; case PhysicalType::UINT32: - ConcatenateKeys(input.data[i], input.size(), keys, is_little_endian); + ConcatenateKeys(input.data[i], input.size(), keys); break; case PhysicalType::UINT64: - ConcatenateKeys(input.data[i], input.size(), keys, is_little_endian); + ConcatenateKeys(input.data[i], input.size(), keys); break; case PhysicalType::FLOAT: - ConcatenateKeys(input.data[i], input.size(), keys, is_little_endian); + ConcatenateKeys(input.data[i], input.size(), keys); break; case PhysicalType::DOUBLE: - ConcatenateKeys(input.data[i], input.size(), keys, is_little_endian); + ConcatenateKeys(input.data[i], input.size(), keys); break; case PhysicalType::VARCHAR: - ConcatenateKeys(input.data[i], input.size(), keys, is_little_endian); + ConcatenateKeys(input.data[i], input.size(), keys); break; default: throw InternalException("Invalid type for index"); @@ -59029,7 +63903,7 @@ bool ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) { GenerateKeys(input, keys); // now insert the elements into the index - row_ids.Normalify(input.size()); + row_ids.Flatten(input.size()); auto row_identifiers = FlatVector::GetData(row_ids); idx_t failed_index = DConstants::INVALID_INDEX; for (idx_t i = 0; i < input.size(); i++) { @@ -59066,7 +63940,7 @@ bool ART::Insert(IndexLock &lock, DataChunk &input, Vector &row_ids) { bool ART::Append(IndexLock &lock, DataChunk &appended_data, Vector &row_identifiers) { DataChunk expression_result; - expression_result.Initialize(logical_types); + expression_result.Initialize(Allocator::DefaultAllocator(), logical_types); // first resolve the expressions for the index ExecuteExpressions(appended_data, expression_result); @@ -59088,78 +63962,84 @@ void ART::VerifyDeleteForeignKey(DataChunk &chunk, string *err_msg_ptr) { } bool ART::InsertToLeaf(Leaf &leaf, row_t row_id) { - if (IsUnique() && leaf.num_elements != 0) { +#ifdef DEBUG + for (idx_t k = 0; k < leaf.count; k++) { + D_ASSERT(leaf.GetRowId(k) != row_id); + } +#endif + if (IsUnique() && leaf.count != 0) { return false; } leaf.Insert(row_id); return true; } -bool ART::Insert(unique_ptr &node, unique_ptr value, unsigned depth, row_t row_id) { +bool ART::Insert(Node *&node, unique_ptr value, unsigned depth, row_t row_id) { Key &key = *value; if (!node) { // node is currently empty, create a leaf here with the key - node = make_unique(*this, move(value), row_id); + node = new Leaf(*value, depth, row_id); return true; } if (node->type == NodeType::NLeaf) { // Replace leaf with Node4 and store both leaves in it - auto leaf = static_cast(node.get()); + auto leaf = (Leaf *)node; - Key &existing_key = *leaf->value; + auto &leaf_prefix = leaf->prefix; uint32_t new_prefix_length = 0; // Leaf node is already there, update row_id vector - if (depth + new_prefix_length == existing_key.len && existing_key.len == key.len) { + if (new_prefix_length == leaf->prefix.Size() && depth + leaf->prefix.Size() == key.len) { return InsertToLeaf(*leaf, row_id); } - while (existing_key[depth + new_prefix_length] == key[depth + new_prefix_length]) { + while (leaf_prefix[new_prefix_length] == key[depth + new_prefix_length]) { new_prefix_length++; // Leaf node is already there, update row_id vector - if (depth + new_prefix_length == existing_key.len && existing_key.len == key.len) { + if (new_prefix_length == leaf->prefix.Size() && depth + leaf->prefix.Size() == key.len) { return InsertToLeaf(*leaf, row_id); } } - unique_ptr new_node = make_unique(*this, new_prefix_length); - new_node->prefix_length = new_prefix_length; - memcpy(new_node->prefix.get(), &key[depth], new_prefix_length); - Node4::Insert(*this, new_node, existing_key[depth + new_prefix_length], node); - unique_ptr leaf_node = make_unique(*this, move(value), row_id); - Node4::Insert(*this, new_node, key[depth + new_prefix_length], leaf_node); - node = move(new_node); + Node *new_node = new Node4(); + new_node->prefix = Prefix(key, depth, new_prefix_length); + auto key_byte = node->prefix.Reduce(new_prefix_length); + Node4::Insert(new_node, key_byte, node); + Node *leaf_node = new Leaf(*value, depth + new_prefix_length + 1, row_id); + Node4::Insert(new_node, key[depth + new_prefix_length], leaf_node); + node = new_node; return true; } // Handle prefix of inner node - if (node->prefix_length) { - uint32_t mismatch_pos = Node::PrefixMismatch(*this, node.get(), key, depth); - if (mismatch_pos != node->prefix_length) { + if (node->prefix.Size()) { + uint32_t mismatch_pos = node->prefix.KeyMismatchPosition(key, depth); + if (mismatch_pos != node->prefix.Size()) { // Prefix differs, create new node - unique_ptr new_node = make_unique(*this, mismatch_pos); - new_node->prefix_length = mismatch_pos; - memcpy(new_node->prefix.get(), node->prefix.get(), mismatch_pos); + Node *new_node = new Node4(); + new_node->prefix = Prefix(key, depth, mismatch_pos); // Break up prefix - auto node_ptr = node.get(); - Node4::Insert(*this, new_node, node->prefix[mismatch_pos], node); - node_ptr->prefix_length -= (mismatch_pos + 1); - memmove(node_ptr->prefix.get(), node_ptr->prefix.get() + mismatch_pos + 1, node_ptr->prefix_length); - unique_ptr leaf_node = make_unique(*this, move(value), row_id); - Node4::Insert(*this, new_node, key[depth + mismatch_pos], leaf_node); - node = move(new_node); + auto key_byte = node->prefix.Reduce(mismatch_pos); + Node4::Insert(new_node, key_byte, node); + + Node *leaf_node = new Leaf(*value, depth + mismatch_pos + 1, row_id); + Node4::Insert(new_node, key[depth + mismatch_pos], leaf_node); + node = new_node; return true; } - depth += node->prefix_length; + depth += node->prefix.Size(); } // Recurse + D_ASSERT(depth < key.len); idx_t pos = node->GetChildPos(key[depth]); if (pos != DConstants::INVALID_INDEX) { - auto child = node->GetChild(pos); - return Insert(*child, move(value), depth + 1, row_id); + auto child = node->GetChild(*this, pos); + bool insertion_result = Insert(child, move(value), depth + 1, row_id); + node->ReplaceChildPointer(pos, child); + return insertion_result; } - unique_ptr new_node = make_unique(*this, move(value), row_id); - Node::InsertLeaf(*this, node, key[depth], new_node); + Node *new_node = new Leaf(*value, depth + 1, row_id); + Node::InsertLeaf(node, key[depth], new_node); return true; } @@ -59167,18 +64047,18 @@ bool ART::Insert(unique_ptr &node, unique_ptr value, unsigned depth, // Delete //===--------------------------------------------------------------------===// void ART::Delete(IndexLock &state, DataChunk &input, Vector &row_ids) { - DataChunk expression_result; - expression_result.Initialize(logical_types); + DataChunk expression; + expression.Initialize(Allocator::DefaultAllocator(), logical_types); // first resolve the expressions - ExecuteExpressions(input, expression_result); + ExecuteExpressions(input, expression); // then generate the keys for the given input vector> keys; - GenerateKeys(expression_result, keys); + GenerateKeys(expression, keys); // now erase the elements from the database - row_ids.Normalify(input.size()); + row_ids.Flatten(input.size()); auto row_identifiers = FlatVector::GetData(row_ids); for (idx_t i = 0; i < input.size(); i++) { @@ -59190,7 +64070,7 @@ void ART::Delete(IndexLock &state, DataChunk &input, Vector &row_ids) { auto node = Lookup(tree, *keys[i], 0); if (node) { auto leaf = static_cast(node); - for (idx_t k = 0; k < leaf->num_elements; k++) { + for (idx_t k = 0; k < leaf->count; k++) { D_ASSERT(leaf->GetRowId(k) != row_identifiers[i]); } } @@ -59198,47 +64078,47 @@ void ART::Delete(IndexLock &state, DataChunk &input, Vector &row_ids) { } } -void ART::Erase(unique_ptr &node, Key &key, unsigned depth, row_t row_id) { +void ART::Erase(Node *&node, Key &key, unsigned depth, row_t row_id) { if (!node) { return; } // Delete a leaf from a tree if (node->type == NodeType::NLeaf) { // Make sure we have the right leaf - if (ART::LeafMatches(node.get(), key, depth)) { - auto leaf = static_cast(node.get()); - leaf->Remove(row_id); - if (leaf->num_elements == 0) { - node.reset(); - } + auto leaf = static_cast(node); + leaf->Remove(row_id); + if (leaf->count == 0) { + delete node; + node = nullptr; } + return; } // Handle prefix - if (node->prefix_length) { - if (Node::PrefixMismatch(*this, node.get(), key, depth) != node->prefix_length) { + if (node->prefix.Size()) { + if (node->prefix.KeyMismatchPosition(key, depth) != node->prefix.Size()) { return; } - depth += node->prefix_length; + depth += node->prefix.Size(); } idx_t pos = node->GetChildPos(key[depth]); if (pos != DConstants::INVALID_INDEX) { - auto child = node->GetChild(pos); + auto child = node->GetChild(*this, pos); D_ASSERT(child); - unique_ptr &child_ref = *child; - if (child_ref->type == NodeType::NLeaf && LeafMatches(child_ref.get(), key, depth)) { + if (child->type == NodeType::NLeaf) { // Leaf found, remove entry - auto leaf = static_cast(child_ref.get()); + auto leaf = (Leaf *)child; leaf->Remove(row_id); - if (leaf->num_elements == 0) { + if (leaf->count == 0) { // Leaf is empty, delete leaf, decrement node counter and maybe shrink node - Node::Erase(*this, node, pos); + Node::Erase(node, pos, *this); } } else { // Recurse - Erase(*child, key, depth + 1, row_id); + Erase(child, key, depth + 1, row_id); + node->ReplaceChildPointer(pos, child); } } } @@ -59250,31 +64130,31 @@ static unique_ptr CreateKey(ART &art, PhysicalType type, Value &value) { D_ASSERT(type == value.type().InternalType()); switch (type) { case PhysicalType::BOOL: - return Key::CreateKey(value, art.is_little_endian); + return Key::CreateKey(value); case PhysicalType::INT8: - return Key::CreateKey(value, art.is_little_endian); + return Key::CreateKey(value); case PhysicalType::INT16: - return Key::CreateKey(value, art.is_little_endian); + return Key::CreateKey(value); case PhysicalType::INT32: - return Key::CreateKey(value, art.is_little_endian); + return Key::CreateKey(value); case PhysicalType::INT64: - return Key::CreateKey(value, art.is_little_endian); + return Key::CreateKey(value); case PhysicalType::UINT8: - return Key::CreateKey(value, art.is_little_endian); + return Key::CreateKey(value); case PhysicalType::UINT16: - return Key::CreateKey(value, art.is_little_endian); + return Key::CreateKey(value); case PhysicalType::UINT32: - return Key::CreateKey(value, art.is_little_endian); + return Key::CreateKey(value); case PhysicalType::UINT64: - return Key::CreateKey(value, art.is_little_endian); + return Key::CreateKey(value); case PhysicalType::INT128: - return Key::CreateKey(value, art.is_little_endian); + return Key::CreateKey(value); case PhysicalType::FLOAT: - return Key::CreateKey(value, art.is_little_endian); + return Key::CreateKey(value); case PhysicalType::DOUBLE: - return Key::CreateKey(value, art.is_little_endian); + return Key::CreateKey(value); case PhysicalType::VARCHAR: - return Key::CreateKey(value, art.is_little_endian); + return Key::CreateKey(value); default: throw InternalException("Invalid type for index"); } @@ -59286,10 +64166,10 @@ bool ART::SearchEqual(ARTIndexScanState *state, idx_t max_count, vector & if (!leaf) { return true; } - if (leaf->num_elements > max_count) { + if (leaf->count > max_count) { return false; } - for (idx_t i = 0; i < leaf->num_elements; i++) { + for (idx_t i = 0; i < leaf->count; i++) { row_t row_id = leaf->GetRowId(i); result_ids.push_back(row_id); } @@ -59299,263 +64179,71 @@ bool ART::SearchEqual(ARTIndexScanState *state, idx_t max_count, vector & void ART::SearchEqualJoinNoFetch(Value &equal_value, idx_t &result_size) { //! We need to look for a leaf auto key = CreateKey(*this, types[0], equal_value); - auto leaf = static_cast(Lookup(tree, *key, 0)); + auto leaf = (Leaf *)(Lookup(tree, *key, 0)); if (!leaf) { return; } - result_size = leaf->num_elements; + result_size = leaf->count; } -Node *ART::Lookup(unique_ptr &node, Key &key, unsigned depth) { - auto node_val = node.get(); - - while (node_val) { - if (node_val->type == NodeType::NLeaf) { - auto leaf = static_cast(node_val); - Key &leaf_key = *leaf->value; +Node *ART::Lookup(Node *node, Key &key, unsigned depth) { + while (node) { + if (node->type == NodeType::NLeaf) { + auto leaf = (Leaf *)node; + auto &leaf_prefix = leaf->prefix; //! Check leaf - for (idx_t i = depth; i < leaf_key.len; i++) { - if (leaf_key[i] != key[i]) { + for (idx_t i = 0; i < leaf->prefix.Size(); i++) { + if (leaf_prefix[i] != key[i + depth]) { return nullptr; } } - return node_val; + return node; } - if (node_val->prefix_length) { - for (idx_t pos = 0; pos < node_val->prefix_length; pos++) { - if (key[depth + pos] != node_val->prefix[pos]) { + if (node->prefix.Size()) { + for (idx_t pos = 0; pos < node->prefix.Size(); pos++) { + if (key[depth + pos] != node->prefix[pos]) { return nullptr; } } - depth += node_val->prefix_length; + depth += node->prefix.Size(); } - idx_t pos = node_val->GetChildPos(key[depth]); + idx_t pos = node->GetChildPos(key[depth]); if (pos == DConstants::INVALID_INDEX) { return nullptr; } - node_val = node_val->GetChild(pos)->get(); - D_ASSERT(node_val); - + node = node->GetChild(*this, pos); + D_ASSERT(node); depth++; } - return nullptr; } -//===--------------------------------------------------------------------===// -// Iterator scans -//===--------------------------------------------------------------------===// -template -bool ART::IteratorScan(ARTIndexScanState *state, Iterator *it, Key *bound, idx_t max_count, vector &result_ids) { - bool has_next; - do { - if (HAS_BOUND) { - D_ASSERT(bound); - if (INCLUSIVE) { - if (*it->node->value > *bound) { - break; - } - } else { - if (*it->node->value >= *bound) { - break; - } - } - } - if (result_ids.size() + it->node->num_elements > max_count) { - // adding these elements would exceed the max count - return false; - } - for (idx_t i = 0; i < it->node->num_elements; i++) { - row_t row_id = it->node->GetRowId(i); - result_ids.push_back(row_id); - } - has_next = ART::IteratorNext(*it); - } while (has_next); - return true; -} - -void Iterator::SetEntry(idx_t entry_depth, IteratorEntry entry) { - if (stack.size() < entry_depth + 1) { - stack.resize(MaxValue(8, MaxValue(entry_depth + 1, stack.size() * 2))); - } - stack[entry_depth] = entry; -} - -bool ART::IteratorNext(Iterator &it) { - // Skip leaf - if ((it.depth) && ((it.stack[it.depth - 1].node)->type == NodeType::NLeaf)) { - it.depth--; - } - - // Look for the next leaf - while (it.depth > 0) { - auto &top = it.stack[it.depth - 1]; - Node *node = top.node; - - if (node->type == NodeType::NLeaf) { - // found a leaf: move to next node - it.node = (Leaf *)node; - return true; - } - - // Find next node - top.pos = node->GetNextPos(top.pos); - if (top.pos != DConstants::INVALID_INDEX) { - // next node found: go there - it.SetEntry(it.depth, IteratorEntry(node->GetChild(top.pos)->get(), DConstants::INVALID_INDEX)); - it.depth++; - } else { - // no node found: move up the tree - it.depth--; - } - } - return false; -} - //===--------------------------------------------------------------------===// // Greater Than // Returns: True (If found leaf >= key) // False (Otherwise) //===--------------------------------------------------------------------===// -bool ART::Bound(unique_ptr &n, Key &key, Iterator &it, bool inclusive) { - it.depth = 0; - bool equal = false; - if (!n) { - return false; - } - Node *node = n.get(); - - idx_t depth = 0; - while (true) { - it.SetEntry(it.depth, IteratorEntry(node, 0)); - auto &top = it.stack[it.depth]; - it.depth++; - if (!equal) { - while (node->type != NodeType::NLeaf) { - node = node->GetChild(node->GetMin())->get(); - auto &c_top = it.stack[it.depth]; - c_top.node = node; - it.depth++; - } - } - if (node->type == NodeType::NLeaf) { - // found a leaf node: check if it is bigger or equal than the current key - auto leaf = static_cast(node); - it.node = leaf; - // if the search is not inclusive the leaf node could still be equal to the current value - // check if leaf is equal to the current key - if (*leaf->value == key) { - // if its not inclusive check if there is a next leaf - if (!inclusive && !IteratorNext(it)) { - return false; - } else { - return true; - } - } - - if (*leaf->value > key) { - return true; - } - // Leaf is lower than key - // Check if next leaf is still lower than key - while (IteratorNext(it)) { - if (*it.node->value == key) { - // if its not inclusive check if there is a next leaf - if (!inclusive && !IteratorNext(it)) { - return false; - } else { - return true; - } - } else if (*it.node->value > key) { - // if its not inclusive check if there is a next leaf - return true; - } - } - return false; - } - uint32_t mismatch_pos = Node::PrefixMismatch(*this, node, key, depth); - if (mismatch_pos != node->prefix_length) { - if (node->prefix[mismatch_pos] < key[depth + mismatch_pos]) { - // Less - it.depth--; - return IteratorNext(it); - } else { - // Greater - top.pos = DConstants::INVALID_INDEX; - return IteratorNext(it); - } - } - // prefix matches, search inside the child for the key - depth += node->prefix_length; - - top.pos = node->GetChildGreaterEqual(key[depth], equal); - if (top.pos == DConstants::INVALID_INDEX) { - // Find min leaf - top.pos = node->GetMin(); - } - node = node->GetChild(top.pos)->get(); - //! This means all children of this node qualify as geq - - depth++; - } -} - bool ART::SearchGreater(ARTIndexScanState *state, bool inclusive, idx_t max_count, vector &result_ids) { Iterator *it = &state->iterator; auto key = CreateKey(*this, types[0], state->values[0]); // greater than scan: first set the iterator to the node at which we will start our scan by finding the lowest node // that satisfies our requirement - if (!it->start) { - bool found = ART::Bound(tree, *key, *it, inclusive); + if (!it->art) { + it->art = this; + bool found = it->LowerBound(tree, *key, inclusive); if (!found) { return true; } - it->start = true; } // after that we continue the scan; we don't need to check the bounds as any value following this value is // automatically bigger and hence satisfies our predicate - return IteratorScan(state, it, nullptr, max_count, result_ids); + return it->Scan(nullptr, max_count, result_ids, false); } //===--------------------------------------------------------------------===// // Less Than //===--------------------------------------------------------------------===// -static Leaf &FindMinimum(Iterator &it, Node &node) { - Node *next = nullptr; - idx_t pos = 0; - switch (node.type) { - case NodeType::NLeaf: - it.node = (Leaf *)&node; - return (Leaf &)node; - case NodeType::N4: - next = ((Node4 &)node).child[0].get(); - break; - case NodeType::N16: - next = ((Node16 &)node).child[0].get(); - break; - case NodeType::N48: { - auto &n48 = (Node48 &)node; - while (n48.child_index[pos] == Node::EMPTY_MARKER) { - pos++; - } - next = n48.child[n48.child_index[pos]].get(); - break; - } - case NodeType::N256: { - auto &n256 = (Node256 &)node; - while (!n256.child[pos]) { - pos++; - } - next = n256.child[pos].get(); - break; - } - } - it.SetEntry(it.depth, IteratorEntry(&node, pos)); - it.depth++; - return FindMinimum(it, *next); -} - bool ART::SearchLess(ARTIndexScanState *state, bool inclusive, idx_t max_count, vector &result_ids) { if (!tree) { return true; @@ -59564,21 +64252,17 @@ bool ART::SearchLess(ARTIndexScanState *state, bool inclusive, idx_t max_count, Iterator *it = &state->iterator; auto upper_bound = CreateKey(*this, types[0], state->values[0]); - if (!it->start) { + if (!it->art) { + it->art = this; // first find the minimum value in the ART: we start scanning from this value - auto &minimum = FindMinimum(state->iterator, *tree); + it->FindMinimum(*tree); // early out min value higher than upper bound query - if (*minimum.value > *upper_bound) { + if (it->cur_key > *upper_bound) { return true; } - it->start = true; } // now continue the scan until we reach the upper bound - if (inclusive) { - return IteratorScan(state, it, upper_bound.get(), max_count, result_ids); - } else { - return IteratorScan(state, it, upper_bound.get(), max_count, result_ids); - } + return it->Scan(upper_bound.get(), max_count, result_ids, inclusive); } //===--------------------------------------------------------------------===// @@ -59590,19 +64274,15 @@ bool ART::SearchCloseRange(ARTIndexScanState *state, bool left_inclusive, bool r auto upper_bound = CreateKey(*this, types[0], state->values[1]); Iterator *it = &state->iterator; // first find the first node that satisfies the left predicate - if (!it->start) { - bool found = ART::Bound(tree, *lower_bound, *it, left_inclusive); + if (!it->art) { + it->art = this; + bool found = it->LowerBound(tree, *lower_bound, left_inclusive); if (!found) { return true; } - it->start = true; } // now continue the scan until we reach the upper bound - if (right_inclusive) { - return IteratorScan(state, it, upper_bound.get(), max_count, result_ids); - } else { - return IteratorScan(state, it, upper_bound.get(), max_count, result_ids); - } + return it->Scan(upper_bound.get(), max_count, result_ids, right_inclusive); } bool ART::Scan(Transaction &transaction, DataTable &table, IndexScanState &table_state, idx_t max_count, @@ -59612,7 +64292,7 @@ bool ART::Scan(Transaction &transaction, DataTable &table, IndexScanState &table D_ASSERT(state->values[0].type().InternalType() == types[0]); vector row_ids; - bool success = true; + bool success; if (state->values[1].IsNull()) { lock_guard l(lock); // single predicate @@ -59668,17 +64348,17 @@ void ART::VerifyExistence(DataChunk &chunk, VerifyExistenceType verify_type, str return; } - DataChunk expression_result; - expression_result.Initialize(logical_types); + DataChunk expression_chunk; + expression_chunk.Initialize(Allocator::DefaultAllocator(), logical_types); // unique index, check lock_guard l(lock); // first resolve the expressions for the index - ExecuteExpressions(chunk, expression_result); + ExecuteExpressions(chunk, expression_chunk); // generate the keys for the given input vector> keys; - GenerateKeys(expression_result, keys); + GenerateKeys(expression_chunk, keys); for (idx_t i = 0; i < chunk.size(); i++) { if (!keys[i]) { @@ -59691,11 +64371,11 @@ void ART::VerifyExistence(DataChunk &chunk, VerifyExistenceType verify_type, str continue; } string key_name; - for (idx_t k = 0; k < expression_result.ColumnCount(); k++) { + for (idx_t k = 0; k < expression_chunk.ColumnCount(); k++) { if (k > 0) { key_name += ", "; } - key_name += unbound_expressions[k]->GetName() + ": " + expression_result.data[k].GetValue(i).ToString(); + key_name += unbound_expressions[k]->GetName() + ": " + expression_chunk.data[k].GetValue(i).ToString(); } string exception_msg; switch (verify_type) { @@ -59727,6 +64407,14 @@ void ART::VerifyExistence(DataChunk &chunk, VerifyExistenceType verify_type, str } } +BlockPointer ART::Serialize(duckdb::MetaBlockWriter &writer) { + lock_guard l(lock); + if (tree) { + return tree->Serialize(*this, writer); + } + return {(block_id_t)DConstants::INVALID_INDEX, (uint32_t)DConstants::INVALID_INDEX}; +} + } // namespace duckdb @@ -59737,8 +64425,12 @@ namespace duckdb { Key::Key(unique_ptr data, idx_t len) : len(len), data(move(data)) { } +Key::Key(idx_t len) : len(len) { + data = unique_ptr(new data_t[len]); +} + template <> -unique_ptr Key::CreateKey(string_t value, bool is_little_endian) { +unique_ptr Key::CreateKey(string_t value) { idx_t len = value.GetSize() + 1; auto data = unique_ptr(new data_t[len]); memcpy(data.get(), value.GetDataUnsafe(), len - 1); @@ -59747,8 +64439,8 @@ unique_ptr Key::CreateKey(string_t value, bool is_little_endian) { } template <> -unique_ptr Key::CreateKey(const char *value, bool is_little_endian) { - return Key::CreateKey(string_t(value, strlen(value)), is_little_endian); +unique_ptr Key::CreateKey(const char *value) { + return Key::CreateKey(string_t(value, strlen(value))); } bool Key::operator>(const Key &k) const { @@ -59799,32 +64491,350 @@ bool Key::operator==(const Key &k) const { +namespace duckdb { +uint8_t &IteratorCurrentKey::operator[](idx_t idx) { + if (idx >= key.size()) { + key.push_back(0); + } + D_ASSERT(idx < key.size()); + return key[idx]; +} + +//! Push Byte +void IteratorCurrentKey::Push(uint8_t byte) { + if (cur_key_pos == key.size()) { + key.push_back(byte); + } + D_ASSERT(cur_key_pos < key.size()); + key[cur_key_pos++] = byte; +} +//! Pops n elements +void IteratorCurrentKey::Pop(idx_t n) { + cur_key_pos -= n; + D_ASSERT(cur_key_pos <= key.size()); +} + +bool IteratorCurrentKey::operator>(const Key &k) const { + for (idx_t i = 0; i < MinValue(cur_key_pos, k.len); i++) { + if (key[i] > k.data[i]) { + return true; + } else if (key[i] < k.data[i]) { + return false; + } + } + return cur_key_pos > k.len; +} + +bool IteratorCurrentKey::operator>=(const Key &k) const { + for (idx_t i = 0; i < MinValue(cur_key_pos, k.len); i++) { + if (key[i] > k.data[i]) { + return true; + } else if (key[i] < k.data[i]) { + return false; + } + } + return cur_key_pos >= k.len; +} + +bool IteratorCurrentKey::operator==(const Key &k) const { + if (cur_key_pos != k.len) { + return false; + } + for (idx_t i = 0; i < cur_key_pos; i++) { + if (key[i] != k.data[i]) { + return false; + } + } + return true; +} + +void Iterator::FindMinimum(Node &node) { + Node *next = nullptr; + idx_t pos = 0; + // reconstruct the prefix + for (idx_t i = 0; i < node.prefix.Size(); i++) { + cur_key.Push(node.prefix[i]); + } + switch (node.type) { + case NodeType::NLeaf: + last_leaf = (Leaf *)&node; + return; + case NodeType::N4: { + next = ((Node4 &)node).children[0].Unswizzle(*art); + cur_key.Push(((Node4 &)node).key[0]); + break; + } + case NodeType::N16: { + next = ((Node16 &)node).children[0].Unswizzle(*art); + cur_key.Push(((Node16 &)node).key[0]); + break; + } + case NodeType::N48: { + auto &n48 = (Node48 &)node; + while (n48.child_index[pos] == Node::EMPTY_MARKER) { + pos++; + } + cur_key.Push(pos); + next = n48.children[n48.child_index[pos]].Unswizzle(*art); + break; + } + case NodeType::N256: { + auto &n256 = (Node256 &)node; + while (!n256.children[pos].pointer) { + pos++; + } + cur_key.Push(pos); + next = (Node *)n256.children[pos].Unswizzle(*art); + break; + } + } + nodes.push(IteratorEntry(&node, pos)); + FindMinimum(*next); +} + +void Iterator::PushKey(Node *cur_node, uint16_t pos) { + switch (cur_node->type) { + case NodeType::N4: + cur_key.Push(((Node4 *)cur_node)->key[pos]); + break; + case NodeType::N16: + cur_key.Push(((Node16 *)cur_node)->key[pos]); + break; + case NodeType::N48: + case NodeType::N256: + cur_key.Push(pos); + break; + case NodeType::NLeaf: + break; + } +} + +bool Iterator::Scan(Key *bound, idx_t max_count, vector &result_ids, bool is_inclusive) { + bool has_next; + do { + if (bound) { + if (is_inclusive) { + if (cur_key > *bound) { + break; + } + } else { + if (cur_key >= *bound) { + break; + } + } + } + if (result_ids.size() + last_leaf->count > max_count) { + // adding these elements would exceed the max count + return false; + } + for (idx_t i = 0; i < last_leaf->count; i++) { + row_t row_id = last_leaf->GetRowId(i); + result_ids.push_back(row_id); + } + has_next = Next(); + } while (has_next); + return true; +} + +bool Iterator::Next() { + if (!nodes.empty()) { + auto cur_node = nodes.top().node; + if (cur_node->type == NodeType::NLeaf) { + // Pop Leaf (We must pop the prefix size + the key to the node (unless we are popping the root) + idx_t elements_to_pop = cur_node->prefix.Size() + (nodes.size() != 1); + cur_key.Pop(elements_to_pop); + nodes.pop(); + } + } + + // Look for the next leaf + while (!nodes.empty()) { + // cur_node + auto &top = nodes.top(); + Node *node = top.node; + if (node->type == NodeType::NLeaf) { + // found a leaf: move to next node + last_leaf = (Leaf *)node; + return true; + } + // Find next node + top.pos = node->GetNextPos(top.pos); + if (top.pos != DConstants::INVALID_INDEX) { + // add key-byte of the new node + PushKey(node, top.pos); + auto next_node = node->GetChild(*art, top.pos); + // add prefix of new node + for (idx_t i = 0; i < next_node->prefix.Size(); i++) { + cur_key.Push(next_node->prefix[i]); + } + // next node found: push it + nodes.push(IteratorEntry(next_node, DConstants::INVALID_INDEX)); + } else { + // no node found: move up the tree and Pop prefix and key of current node + auto cur_node = nodes.top().node; + idx_t elements_to_pop = cur_node->prefix.Size() + (nodes.size() != 1); + cur_key.Pop(elements_to_pop); + nodes.pop(); + } + } + return false; +} + +bool Iterator::LowerBound(Node *node, Key &key, bool inclusive) { + bool equal = false; + if (!node) { + return false; + } + idx_t depth = 0; + while (true) { + nodes.push(IteratorEntry(node, 0)); + auto &top = nodes.top(); + // reconstruct the prefix + for (idx_t i = 0; i < top.node->prefix.Size(); i++) { + cur_key.Push(top.node->prefix[i]); + } + if (!equal) { + while (node->type != NodeType::NLeaf) { + auto min_pos = node->GetMin(); + PushKey(node, min_pos); + nodes.push(IteratorEntry(node, min_pos)); + node = node->GetChild(*art, min_pos); + // reconstruct the prefix + for (idx_t i = 0; i < node->prefix.Size(); i++) { + cur_key.Push(node->prefix[i]); + } + auto &c_top = nodes.top(); + c_top.node = node; + } + } + if (node->type == NodeType::NLeaf) { + // found a leaf node: check if it is bigger or equal than the current key + auto leaf = static_cast(node); + last_leaf = leaf; + // if the search is not inclusive the leaf node could still be equal to the current value + // check if leaf is equal to the current key + if (cur_key == key) { + // if it's not inclusive check if there is a next leaf + if (!inclusive && !Next()) { + return false; + } else { + return true; + } + } + + if (cur_key > key) { + return true; + } + // Leaf is lower than key + // Check if next leaf is still lower than key + while (Next()) { + if (cur_key == key) { + // if it's not inclusive check if there is a next leaf + if (!inclusive && !Next()) { + return false; + } else { + return true; + } + } else if (cur_key > key) { + // if it's not inclusive check if there is a next leaf + return true; + } + } + return false; + } + uint32_t mismatch_pos = node->prefix.KeyMismatchPosition(key, depth); + if (mismatch_pos != node->prefix.Size()) { + if (node->prefix[mismatch_pos] < key[depth + mismatch_pos]) { + // Less + nodes.pop(); + return Next(); + } else { + // Greater + top.pos = DConstants::INVALID_INDEX; + return Next(); + } + } + // prefix matches, search inside the child for the key + depth += node->prefix.Size(); + + top.pos = node->GetChildGreaterEqual(key[depth], equal); + if (top.pos == DConstants::INVALID_INDEX) { + // Find min leaf + top.pos = node->GetMin(); + } + node = node->GetChild(*art, top.pos); + // This means all children of this node qualify as geq + depth++; + } +} + +} // namespace duckdb + + + + #include namespace duckdb { -Leaf::Leaf(ART &art, unique_ptr value, row_t row_id) : Node(art, NodeType::NLeaf, 0) { - this->value = move(value); - this->capacity = 1; - this->row_ids = unique_ptr(new row_t[this->capacity]); - this->row_ids[0] = row_id; - this->num_elements = 1; +Leaf::Leaf(Key &value, unsigned depth, row_t row_id) : Node(NodeType::NLeaf) { + capacity = 1; + row_ids = unique_ptr(new row_t[capacity]); + row_ids[0] = row_id; + count = 1; + D_ASSERT(value.len >= depth); + prefix = Prefix(value, depth, value.len - depth); +} + +Leaf::Leaf(unique_ptr row_ids_p, idx_t num_elements_p, Prefix &prefix_p) : Node(NodeType::NLeaf) { + capacity = num_elements_p; + row_ids = move(row_ids_p); + count = num_elements_p; + prefix = prefix_p; } void Leaf::Insert(row_t row_id) { // Grow array - if (num_elements == capacity) { + if (count == capacity) { auto new_row_id = unique_ptr(new row_t[capacity * 2]); memcpy(new_row_id.get(), row_ids.get(), capacity * sizeof(row_t)); capacity *= 2; row_ids = move(new_row_id); } - row_ids[num_elements++] = row_id; + row_ids[count++] = row_id; +} + +BlockPointer Leaf::Serialize(duckdb::MetaBlockWriter &writer) { + auto block_id = writer.block->id; + uint32_t offset = writer.offset; + // Write Node Type + writer.Write(type); + // Write compression Info + prefix.Serialize(writer); + // Write Row Ids + // Length + writer.Write(count); + // Actual Row Ids + for (idx_t i = 0; i < count; i++) { + writer.Write(row_ids[i]); + } + return {block_id, offset}; +} + +Leaf *Leaf::Deserialize(MetaBlockReader &reader) { + Prefix prefix; + prefix.Deserialize(reader); + auto num_elements = reader.Read(); + auto elements = unique_ptr(new row_t[num_elements]); + for (idx_t i = 0; i < num_elements; i++) { + elements[i] = reader.Read(); + } + return new Leaf(move(elements), num_elements, prefix); } void Leaf::Remove(row_t row_id) { idx_t entry_offset = DConstants::INVALID_INDEX; - for (idx_t i = 0; i < num_elements; i++) { + for (idx_t i = 0; i < count; i++) { if (row_ids[i] == row_id) { entry_offset = i; break; @@ -59833,18 +64843,18 @@ void Leaf::Remove(row_t row_id) { if (entry_offset == DConstants::INVALID_INDEX) { return; } - num_elements--; - if (capacity > 2 && num_elements < capacity / 2) { + count--; + if (capacity > 2 && count < capacity / 2) { // Shrink array, if less than half full auto new_row_id = unique_ptr(new row_t[capacity / 2]); memcpy(new_row_id.get(), row_ids.get(), entry_offset * sizeof(row_t)); memcpy(new_row_id.get() + entry_offset, row_ids.get() + entry_offset + 1, - (num_elements - entry_offset) * sizeof(row_t)); + (count - entry_offset) * sizeof(row_t)); capacity /= 2; row_ids = move(new_row_id); } else { // Copy the rest - for (idx_t j = entry_offset; j < num_elements; j++) { + for (idx_t j = entry_offset; j < count; j++) { row_ids[j] = row_ids[j + 1]; } } @@ -59857,72 +64867,182 @@ void Leaf::Remove(row_t row_id) { namespace duckdb { -Node::Node(ART &art, NodeType type, size_t compressed_prefix_size) : prefix_length(0), count(0), type(type) { - this->prefix = unique_ptr(new uint8_t[compressed_prefix_size]); -} - -void Node::CopyPrefix(ART &art, Node *src, Node *dst) { - dst->prefix_length = src->prefix_length; - memcpy(dst->prefix.get(), src->prefix.get(), src->prefix_length); +Node::Node(NodeType type) : count(0), type(type) { } // LCOV_EXCL_START -unique_ptr *Node::GetChild(idx_t pos) { +Node *Node::GetChild(ART &art, idx_t pos) { D_ASSERT(0); return nullptr; } +void Node::ReplaceChildPointer(idx_t pos, Node *node) { + D_ASSERT(0); +} + idx_t Node::GetMin() { D_ASSERT(0); return 0; } // LCOV_EXCL_STOP -uint32_t Node::PrefixMismatch(ART &art, Node *node, Key &key, uint64_t depth) { - uint64_t pos; - for (pos = 0; pos < node->prefix_length; pos++) { - if (key[depth + pos] != node->prefix[pos]) { - return pos; - } +void InternalType::Set(uint8_t *key_p, uint16_t key_size_p, SwizzleablePointer *children_p, uint16_t children_size_p) { + key = key_p; + key_size = key_size_p; + children = children_p; + children_size = children_size_p; +} + +InternalType::InternalType(Node *n) { + switch (n->type) { + case NodeType::N4: { + auto n4 = (Node4 *)n; + Set(n4->key, 4, n4->children, 4); + break; + } + case NodeType::N16: { + auto n16 = (Node16 *)n; + Set(n16->key, 16, n16->children, 16); + break; + } + case NodeType::N48: { + auto n48 = (Node48 *)n; + Set(n48->child_index, 256, n48->children, 48); + break; + } + case NodeType::N256: { + auto n256 = (Node256 *)n; + Set(nullptr, 0, n256->children, 256); + break; + } + default: + throw InternalException("This is not an Internal ART Node Type"); } - return pos; } -void Node::InsertLeaf(ART &art, unique_ptr &node, uint8_t key, unique_ptr &new_node) { +BlockPointer Node::SerializeInternal(ART &art, duckdb::MetaBlockWriter &writer, InternalType &internal_type) { + // Iterate through children and annotate their offsets + vector child_offsets; + for (idx_t i = 0; i < internal_type.children_size; i++) { + child_offsets.emplace_back(internal_type.children[i].Serialize(art, writer)); + } + auto block_id = writer.block->id; + uint32_t offset = writer.offset; + // Write Node Type + writer.Write(type); + // Write count + writer.Write(count); + // Write Prefix + prefix.Serialize(writer); + // Write Key values + for (idx_t i = 0; i < internal_type.key_size; i++) { + writer.Write(internal_type.key[i]); + } + // Write child offsets + for (auto &offsets : child_offsets) { + writer.Write(offsets.block_id); + writer.Write(offsets.offset); + } + return {block_id, offset}; +} + +BlockPointer Node::Serialize(ART &art, duckdb::MetaBlockWriter &writer) { + switch (type) { + case NodeType::N4: + case NodeType::N16: + case NodeType::N48: + case NodeType::N256: { + InternalType internal_type(this); + return SerializeInternal(art, writer, internal_type); + } + case NodeType::NLeaf: { + auto leaf = (Leaf *)this; + return leaf->Serialize(writer); + } + default: + throw InternalException("Invalid ART Node"); + } +} + +void Node::DeserializeInternal(duckdb::MetaBlockReader &reader) { + InternalType internal_type(this); + count = reader.Read(); + prefix.Deserialize(reader); + // Get Key values + for (idx_t i = 0; i < internal_type.key_size; i++) { + internal_type.key[i] = reader.Read(); + } + // Get Child offsets + for (idx_t i = 0; i < internal_type.children_size; i++) { + internal_type.children[i] = SwizzleablePointer(reader); + } +} + +Node *Node::Deserialize(ART &art, idx_t block_id, idx_t offset) { + MetaBlockReader reader(art.db, block_id); + reader.offset = offset; + auto n = reader.Read(); + NodeType node_type(static_cast(n)); + Node *deserialized_node; + switch (node_type) { + case NodeType::NLeaf: + return Leaf::Deserialize(reader); + case NodeType::N4: { + deserialized_node = (Node *)new Node4(); + break; + } + case NodeType::N16: { + deserialized_node = (Node *)new Node16(); + break; + } + case NodeType::N48: { + deserialized_node = (Node *)new Node48(); + break; + } + case NodeType::N256: { + deserialized_node = (Node *)new Node256(); + break; + } + } + deserialized_node->DeserializeInternal(reader); + return deserialized_node; +} + +void Node::InsertLeaf(Node *&node, uint8_t key, Node *new_node) { switch (node->type) { case NodeType::N4: - Node4::Insert(art, node, key, new_node); + Node4::Insert(node, key, new_node); break; case NodeType::N16: - Node16::Insert(art, node, key, new_node); + Node16::Insert(node, key, new_node); break; case NodeType::N48: - Node48::Insert(art, node, key, new_node); + Node48::Insert(node, key, new_node); break; case NodeType::N256: - Node256::Insert(art, node, key, new_node); + Node256::Insert(node, key, new_node); break; default: throw InternalException("Unrecognized leaf type for insert"); } } -void Node::Erase(ART &art, unique_ptr &node, idx_t pos) { +void Node::Erase(Node *&node, idx_t pos, ART &art) { switch (node->type) { case NodeType::N4: { - Node4::Erase(art, node, pos); + Node4::Erase(node, pos, art); break; } case NodeType::N16: { - Node16::Erase(art, node, pos); + Node16::Erase(node, pos, art); break; } case NodeType::N48: { - Node48::Erase(art, node, pos); + Node48::Erase(node, pos, art); break; } case NodeType::N256: - Node256::Erase(art, node, pos); + Node256::Erase(node, pos, art); break; default: throw InternalException("Unrecognized leaf type for erase"); @@ -59938,7 +65058,7 @@ void Node::Erase(ART &art, unique_ptr &node, idx_t pos) { namespace duckdb { -Node16::Node16(ART &art, size_t compression_length) : Node(art, NodeType::N16, compression_length) { +Node16::Node16() : Node(NodeType::N16) { memset(key, 16, sizeof(key)); } @@ -59974,17 +65094,21 @@ idx_t Node16::GetNextPos(idx_t pos) { return pos < count ? pos : DConstants::INVALID_INDEX; } -unique_ptr *Node16::GetChild(idx_t pos) { +Node *Node16::GetChild(ART &art, idx_t pos) { D_ASSERT(pos < count); - return &child[pos]; + return children[pos].Unswizzle(art); } idx_t Node16::GetMin() { return 0; } -void Node16::Insert(ART &art, unique_ptr &node, uint8_t key_byte, unique_ptr &child) { - Node16 *n = static_cast(node.get()); +void Node16::ReplaceChildPointer(idx_t pos, Node *node) { + children[pos] = node; +} + +void Node16::Insert(Node *&node, uint8_t key_byte, Node *child) { + Node16 *n = (Node16 *)node; if (n->count < 16) { // Insert element @@ -59992,49 +65116,61 @@ void Node16::Insert(ART &art, unique_ptr &node, uint8_t key_byte, unique_p while (pos < node->count && n->key[pos] < key_byte) { pos++; } - if (n->child[pos] != nullptr) { + if (n->children[pos] != 0) { for (idx_t i = n->count; i > pos; i--) { n->key[i] = n->key[i - 1]; - n->child[i] = move(n->child[i - 1]); + n->children[i] = n->children[i - 1]; } } n->key[pos] = key_byte; - n->child[pos] = move(child); + n->children[pos] = child; n->count++; } else { // Grow to Node48 - auto new_node = make_unique(art, n->prefix_length); + auto new_node = new Node48(); for (idx_t i = 0; i < node->count; i++) { new_node->child_index[n->key[i]] = i; - new_node->child[i] = move(n->child[i]); + new_node->children[i] = n->children[i]; + n->children[i] = nullptr; } - CopyPrefix(art, n, new_node.get()); + new_node->prefix = move(n->prefix); new_node->count = node->count; - node = move(new_node); + delete node; + node = new_node; - Node48::Insert(art, node, key_byte, child); + Node48::Insert(node, key_byte, child); } } -void Node16::Erase(ART &art, unique_ptr &node, int pos) { - Node16 *n = static_cast(node.get()); +void Node16::Erase(Node *&node, int pos, ART &art) { + auto n = (Node16 *)node; // erase the child and decrease the count - n->child[pos].reset(); + n->children[pos].Reset(); n->count--; // potentially move any children backwards for (; pos < n->count; pos++) { n->key[pos] = n->key[pos + 1]; - n->child[pos] = move(n->child[pos + 1]); + n->children[pos] = n->children[pos + 1]; + } + // set any remaining nodes as nullptr + for (; pos < 16; pos++) { + if (!n->children[pos].pointer) { + break; + } + n->children[pos] = nullptr; } + if (node->count <= 3) { // Shrink node - auto new_node = make_unique(art, n->prefix_length); + auto new_node = new Node4(); for (unsigned i = 0; i < n->count; i++) { new_node->key[new_node->count] = n->key[i]; - new_node->child[new_node->count++] = move(n->child[i]); + new_node->children[new_node->count++] = n->children[i]; + n->children[i] = nullptr; } - CopyPrefix(art, n, new_node.get()); - node = move(new_node); + new_node->prefix = move(n->prefix); + delete node; + node = new_node; } } @@ -60044,11 +65180,11 @@ void Node16::Erase(ART &art, unique_ptr &node, int pos) { namespace duckdb { -Node256::Node256(ART &art, size_t compression_length) : Node(art, NodeType::N256, compression_length) { +Node256::Node256() : Node(NodeType::N256) { } idx_t Node256::GetChildPos(uint8_t k) { - if (child[k]) { + if (children[k].pointer) { return k; } else { return DConstants::INVALID_INDEX; @@ -60057,7 +65193,7 @@ idx_t Node256::GetChildPos(uint8_t k) { idx_t Node256::GetChildGreaterEqual(uint8_t k, bool &equal) { for (idx_t pos = k; pos < 256; pos++) { - if (child[pos]) { + if (children[pos].pointer) { if (pos == k) { equal = true; } else { @@ -60071,50 +65207,54 @@ idx_t Node256::GetChildGreaterEqual(uint8_t k, bool &equal) { idx_t Node256::GetMin() { for (idx_t i = 0; i < 256; i++) { - if (child[i]) { + if (children[i].pointer) { return i; } } return DConstants::INVALID_INDEX; } +void Node256::ReplaceChildPointer(idx_t pos, Node *node) { + children[pos] = node; +} + idx_t Node256::GetNextPos(idx_t pos) { for (pos == DConstants::INVALID_INDEX ? pos = 0 : pos++; pos < 256; pos++) { - if (child[pos]) { + if (children[pos].pointer) { return pos; } } return Node::GetNextPos(pos); } -unique_ptr *Node256::GetChild(idx_t pos) { - D_ASSERT(child[pos]); - return &child[pos]; +Node *Node256::GetChild(ART &art, idx_t pos) { + return children[pos].Unswizzle(art); } -void Node256::Insert(ART &art, unique_ptr &node, uint8_t key_byte, unique_ptr &child) { - Node256 *n = static_cast(node.get()); +void Node256::Insert(Node *&node, uint8_t key_byte, Node *child) { + auto n = (Node256 *)(node); n->count++; - n->child[key_byte] = move(child); + n->children[key_byte] = child; } -void Node256::Erase(ART &art, unique_ptr &node, int pos) { - Node256 *n = static_cast(node.get()); - - n->child[pos].reset(); +void Node256::Erase(Node *&node, int pos, ART &art) { + auto n = (Node256 *)(node); + n->children[pos].Reset(); n->count--; if (node->count <= 36) { - auto new_node = make_unique(art, n->prefix_length); - CopyPrefix(art, n, new_node.get()); + auto new_node = new Node48(); + new_node->prefix = move(n->prefix); for (idx_t i = 0; i < 256; i++) { - if (n->child[i]) { + if (n->children[i].pointer) { new_node->child_index[i] = new_node->count; - new_node->child[new_node->count] = move(n->child[i]); + new_node->children[new_node->count] = n->children[i]; + n->children[i] = nullptr; new_node->count++; } } - node = move(new_node); + delete node; + node = new_node; } } @@ -60123,12 +65263,17 @@ void Node256::Erase(ART &art, unique_ptr &node, int pos) { + namespace duckdb { -Node4::Node4(ART &art, size_t compression_length) : Node(art, NodeType::N4, compression_length) { +Node4::Node4() : Node(NodeType::N4) { memset(key, 0, sizeof(key)); } +void Node4::ReplaceChildPointer(idx_t pos, Node *node) { + children[pos] = node; +} + idx_t Node4::GetChildPos(uint8_t k) { for (idx_t pos = 0; pos < count; pos++) { if (key[pos] == k) { @@ -60164,13 +65309,13 @@ idx_t Node4::GetNextPos(idx_t pos) { return pos < count ? pos : DConstants::INVALID_INDEX; } -unique_ptr *Node4::GetChild(idx_t pos) { +Node *Node4::GetChild(ART &art, idx_t pos) { D_ASSERT(pos < count); - return &child[pos]; + return children[pos].Unswizzle(art); } -void Node4::Insert(ART &art, unique_ptr &node, uint8_t key_byte, unique_ptr &child) { - Node4 *n = static_cast(node.get()); +void Node4::Insert(Node *&node, uint8_t key_byte, Node *new_child) { + Node4 *n = (Node4 *)node; // Insert leaf into inner node if (node->count < 4) { @@ -60179,64 +65324,56 @@ void Node4::Insert(ART &art, unique_ptr &node, uint8_t key_byte, unique_pt while ((pos < node->count) && (n->key[pos] < key_byte)) { pos++; } - if (n->child[pos] != nullptr) { + if (n->children[pos] != 0) { for (idx_t i = n->count; i > pos; i--) { n->key[i] = n->key[i - 1]; - n->child[i] = move(n->child[i - 1]); + n->children[i] = n->children[i - 1]; } } n->key[pos] = key_byte; - n->child[pos] = move(child); + n->children[pos] = new_child; n->count++; } else { // Grow to Node16 - auto new_node = make_unique(art, n->prefix_length); + auto new_node = new Node16(); new_node->count = 4; - CopyPrefix(art, node.get(), new_node.get()); + new_node->prefix = move(node->prefix); for (idx_t i = 0; i < 4; i++) { new_node->key[i] = n->key[i]; - new_node->child[i] = move(n->child[i]); + new_node->children[i] = n->children[i]; + n->children[i] = nullptr; } - node = move(new_node); - Node16::Insert(art, node, key_byte, child); + // Delete old node and replace it with new node + delete node; + node = new_node; + Node16::Insert(node, key_byte, new_child); } } -void Node4::Erase(ART &art, unique_ptr &node, int pos) { - Node4 *n = static_cast(node.get()); +void Node4::Erase(Node *&node, int pos, ART &art) { + Node4 *n = (Node4 *)node; D_ASSERT(pos < n->count); - // erase the child and decrease the count - n->child[pos].reset(); + n->children[pos].Reset(); n->count--; // potentially move any children backwards for (; pos < n->count; pos++) { n->key[pos] = n->key[pos + 1]; - n->child[pos] = move(n->child[pos + 1]); + n->children[pos] = n->children[pos + 1]; + } + // set any remaining nodes as nullptr + for (; pos < 4; pos++) { + n->children[pos] = nullptr; } // This is a one way node if (n->count == 1) { - auto childref = n->child[0].get(); - //! concatenate prefixes - auto new_length = node->prefix_length + childref->prefix_length + 1; - //! have to allocate space in our prefix array - unique_ptr new_prefix = unique_ptr(new uint8_t[new_length]); - - //! first move the existing prefix (if any) - for (uint32_t i = 0; i < childref->prefix_length; i++) { - new_prefix[new_length - (i + 1)] = childref->prefix[childref->prefix_length - (i + 1)]; - } - //! now move the current key as part of the prefix - new_prefix[node->prefix_length] = n->key[0]; - //! finally add the old prefix - for (uint32_t i = 0; i < node->prefix_length; i++) { - new_prefix[i] = node->prefix[i]; - } - //! set new prefix and move the child - childref->prefix = move(new_prefix); - childref->prefix_length = new_length; - node = move(n->child[0]); + auto child_ref = n->GetChild(art, 0); + // concatenate prefixes + child_ref->prefix.Concatenate(n->key[0], node->prefix); + n->children[0] = nullptr; + delete node; + node = child_ref; } } @@ -60247,7 +65384,7 @@ void Node4::Erase(ART &art, unique_ptr &node, int pos) { namespace duckdb { -Node48::Node48(ART &art, size_t compression_length) : Node(art, NodeType::N48, compression_length) { +Node48::Node48() : Node(NodeType::N48) { for (idx_t i = 0; i < 256; i++) { child_index[i] = Node::EMPTY_MARKER; } @@ -60284,9 +65421,9 @@ idx_t Node48::GetNextPos(idx_t pos) { return Node::GetNextPos(pos); } -unique_ptr *Node48::GetChild(idx_t pos) { +Node *Node48::GetChild(ART &art, idx_t pos) { D_ASSERT(child_index[pos] != Node::EMPTY_MARKER); - return &child[child_index[pos]]; + return children[child_index[pos]].Unswizzle(art); } idx_t Node48::GetMin() { @@ -60298,57 +65435,248 @@ idx_t Node48::GetMin() { return DConstants::INVALID_INDEX; } -void Node48::Insert(ART &art, unique_ptr &node, uint8_t key_byte, unique_ptr &child) { - Node48 *n = static_cast(node.get()); +void Node48::Insert(Node *&node, uint8_t key_byte, Node *child) { + auto n = (Node48 *)node; // Insert leaf into inner node if (node->count < 48) { // Insert element idx_t pos = n->count; - if (n->child[pos]) { + if (n->children[pos].pointer) { // find an empty position in the node list if the current position is occupied pos = 0; - while (n->child[pos]) { + while (n->children[pos].pointer) { pos++; } } - n->child[pos] = move(child); + n->children[pos] = child; n->child_index[key_byte] = pos; n->count++; } else { // Grow to Node256 - auto new_node = make_unique(art, n->prefix_length); + auto new_node = new Node256(); for (idx_t i = 0; i < 256; i++) { if (n->child_index[i] != Node::EMPTY_MARKER) { - new_node->child[i] = move(n->child[n->child_index[i]]); + new_node->children[i] = n->children[n->child_index[i]]; + n->children[n->child_index[i]] = nullptr; } } new_node->count = n->count; - CopyPrefix(art, n, new_node.get()); - node = move(new_node); - Node256::Insert(art, node, key_byte, child); + new_node->prefix = move(n->prefix); + delete node; + node = new_node; + Node256::Insert(node, key_byte, child); } } -void Node48::Erase(ART &art, unique_ptr &node, int pos) { - Node48 *n = static_cast(node.get()); +void Node48::ReplaceChildPointer(idx_t pos, Node *node) { + children[child_index[pos]] = node; +} - n->child[n->child_index[pos]].reset(); +void Node48::Erase(Node *&node, int pos, ART &art) { + auto n = (Node48 *)(node); + n->children[n->child_index[pos]].Reset(); n->child_index[pos] = Node::EMPTY_MARKER; n->count--; if (node->count <= 12) { - auto new_node = make_unique(art, n->prefix_length); - CopyPrefix(art, n, new_node.get()); + auto new_node = new Node16(); + new_node->prefix = move(n->prefix); for (idx_t i = 0; i < 256; i++) { if (n->child_index[i] != Node::EMPTY_MARKER) { new_node->key[new_node->count] = i; - new_node->child[new_node->count++] = move(n->child[n->child_index[i]]); + new_node->children[new_node->count++] = n->children[n->child_index[i]]; + n->children[n->child_index[i]] = nullptr; } } - node = move(new_node); + delete node; + node = new_node; + } +} + +} // namespace duckdb + + +namespace duckdb { + +uint32_t Prefix::Size() const { + return size; +} + +Prefix::Prefix() : size(0) { +} + +Prefix::Prefix(Key &key, uint32_t depth, uint32_t size) : size(size) { + // Allocate new prefix + prefix = unique_ptr(new uint8_t[size]); + + // Copy Key to Prefix + idx_t prefix_idx = 0; + for (idx_t i = depth; i < size + depth; i++) { + prefix[prefix_idx++] = key.data[i]; + } +} + +uint8_t &Prefix::operator[](idx_t idx) { + D_ASSERT(idx < Size()); + return prefix[idx]; +} + +Prefix &Prefix::operator=(const Prefix &src) { + // Allocate new prefix + prefix = unique_ptr(new uint8_t[src.size]); + + // Copy + for (idx_t i = 0; i < src.size; i++) { + prefix[i] = src.prefix[i]; + } + size = src.size; + return *this; +} + +Prefix &Prefix::operator=(Prefix &&other) noexcept { + prefix = move(other.prefix); + size = other.size; + return *this; +} + +uint8_t Prefix::Reduce(uint32_t n) { + auto new_size = size - n - 1; + auto new_prefix = unique_ptr(new uint8_t[new_size]); + auto key = prefix[n]; + for (idx_t i = 0; i < new_size; i++) { + new_prefix[i] = prefix[i + n + 1]; + } + prefix = move(new_prefix); + size = new_size; + return key; +} + +void Prefix::Concatenate(uint8_t key, Prefix &other) { + auto new_length = size + 1 + other.size; + // have to allocate space in our prefix array + unique_ptr new_prefix = unique_ptr(new uint8_t[new_length]); + idx_t new_prefix_idx = 0; + // 1) Add the to-be deleted Node's prefix + for (uint32_t i = 0; i < other.size; i++) { + new_prefix[new_prefix_idx++] = other[i]; + } + // 2) now move the current key as part of the prefix + new_prefix[new_prefix_idx++] = key; + // 3) move the existing prefix (if any) + for (uint32_t i = 0; i < size; i++) { + new_prefix[new_prefix_idx++] = prefix[i]; + } + prefix = move(new_prefix); + size = new_length; +} + +void Prefix::Serialize(duckdb::MetaBlockWriter &writer) { + writer.Write(size); + for (idx_t i = 0; i < size; i++) { + writer.Write(prefix[i]); + } +} + +void Prefix::Deserialize(duckdb::MetaBlockReader &reader) { + size = reader.Read(); + prefix = unique_ptr(new uint8_t[size]); + for (idx_t i = 0; i < size; i++) { + prefix[i] = reader.Read(); + } +} + +uint32_t Prefix::KeyMismatchPosition(Key &key, uint64_t depth) { + uint64_t pos; + for (pos = 0; pos < size; pos++) { + if (key[depth + pos] != prefix[pos]) { + return pos; + } + } + return pos; +} + +} // namespace duckdb + + +namespace duckdb { +SwizzleablePointer::~SwizzleablePointer() { + if (pointer) { + if (!IsSwizzled()) { + delete (Node *)pointer; + } } } +SwizzleablePointer::SwizzleablePointer(duckdb::MetaBlockReader &reader) { + idx_t block_id = reader.Read(); + idx_t offset = reader.Read(); + if (block_id == DConstants::INVALID_INDEX || offset == DConstants::INVALID_INDEX) { + pointer = 0; + return; + } + idx_t pointer_size = sizeof(pointer) * 8; + pointer = block_id; + pointer = pointer << (pointer_size / 2); + pointer += offset; + // Set the left most bit to indicate this is a swizzled pointer and send it back to the mother-ship + uint64_t mask = 1; + mask = mask << (pointer_size - 1); + pointer |= mask; +} + +SwizzleablePointer &SwizzleablePointer::operator=(const Node *ptr) { + if (sizeof(ptr) == 4) { + pointer = (uint32_t)(size_t)ptr; + } else { + pointer = (uint64_t)ptr; + } + return *this; +} + +bool operator!=(const SwizzleablePointer &s_ptr, const uint64_t &ptr) { + return (s_ptr.pointer != ptr); +} + +BlockPointer SwizzleablePointer::GetSwizzledBlockInfo() { + D_ASSERT(IsSwizzled()); + idx_t pointer_size = sizeof(pointer) * 8; + pointer = pointer & ~(1ULL << (pointer_size - 1)); + uint32_t block_id = pointer >> (pointer_size / 2); + uint32_t offset = pointer & 0xffffffff; + return {block_id, offset}; +} +bool SwizzleablePointer::IsSwizzled() { + idx_t pointer_size = sizeof(pointer) * 8; + return (pointer >> (pointer_size - 1)) & 1; +} + +void SwizzleablePointer::Reset() { + if (pointer) { + if (!IsSwizzled()) { + delete (Node *)pointer; + } + } + *this = nullptr; +} + +Node *SwizzleablePointer::Unswizzle(ART &art) { + if (IsSwizzled()) { + // This means our pointer is not yet in memory, gotta deserialize this + // first we unset the bae + auto block_info = GetSwizzledBlockInfo(); + *this = Node::Deserialize(art, block_info.block_id, block_info.offset); + } + return (Node *)pointer; +} + +BlockPointer SwizzleablePointer::Serialize(ART &art, duckdb::MetaBlockWriter &writer) { + if (pointer) { + Unswizzle(art); + return ((Node *)pointer)->Serialize(art, writer); + } else { + return {(block_id_t)DConstants::INVALID_INDEX, (uint32_t)DConstants::INVALID_INDEX}; + } +} } // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -60370,17 +65698,40 @@ void Node48::Erase(ART &art, unique_ptr &node, int pos) { + namespace duckdb { + class BufferManager; class BufferHandle; +class ColumnDataCollection; +struct ColumnDataAppendState; +struct ClientConfig; struct JoinHTScanState { - JoinHTScanState() : position(0), block_position(0) { +public: + JoinHTScanState() : position(0), block_position(0), total(0), scan_index(0), scanned(0) { } idx_t position; idx_t block_position; - mutex lock; + + //! Used for synchronization of parallel external join + idx_t total; + idx_t scan_index; + idx_t scanned; + +public: + void Reset() { + position = 0; + block_position = 0; + total = 0; + scan_index = 0; + scanned = 0; + } + +private: + //! Implicit copying is not allowed + JoinHTScanState(const JoinHTScanState &) = delete; }; //! JoinHashTable is a linear probing HT that is used for computing joins @@ -60405,7 +65756,7 @@ class JoinHashTable { //! returned by the JoinHashTable::Scan function and can be used to resume a //! probe. struct ScanStructure { - unique_ptr key_data; + unique_ptr key_data; Vector pointers; idx_t count; SelectionVector sel_vector; @@ -60446,6 +65797,7 @@ class JoinHashTable { idx_t ResolvePredicates(DataChunk &keys, SelectionVector &match_sel, SelectionVector &no_match_sel); public: + void InitializeSelectionVector(const SelectionVector *¤t_sel); void AdvancePointers(); void AdvancePointers(const SelectionVector &sel, idx_t sel_count); void GatherResult(Vector &result, const SelectionVector &result_vector, const SelectionVector &sel_vector, @@ -60454,7 +65806,6 @@ class JoinHashTable { idx_t ResolvePredicates(DataChunk &keys, SelectionVector &match_sel, SelectionVector *no_match_sel); }; -private: public: JoinHashTable(BufferManager &buffer_manager, const vector &conditions, vector build_types, JoinType type); @@ -60462,23 +65813,36 @@ class JoinHashTable { //! Add the given data to the HT void Build(DataChunk &keys, DataChunk &input); + //! Merge another HT into this one + void Merge(JoinHashTable &other); + //! Initialize the pointer table for the probe + void InitializePointerTable(); //! Finalize the build of the HT, constructing the actual hash table and making the HT ready for probing. //! Finalize must be called before any call to Probe, and after Finalize is called Build should no longer be //! ever called. - void Finalize(); + void Finalize(idx_t block_idx_start, idx_t block_idx_end, bool parallel); //! Probe the HT with the given input chunk, resulting in the given result - unique_ptr Probe(DataChunk &keys); - //! Scan the HT to construct the final full outer join result after - void ScanFullOuter(DataChunk &result, JoinHTScanState &state); + unique_ptr Probe(DataChunk &keys, Vector *precomputed_hashes = nullptr); + //! Scan the HT to find the rows for the full outer join and return the number of found entries + idx_t ScanFullOuter(JoinHTScanState &state, Vector &addresses); + //! Construct the full outer join result given the addresses and number of found entries + void GatherFullOuter(DataChunk &result, Vector &addresses, idx_t found_entries); + //! Fill the pointer with all the addresses from the hashtable for full scan idx_t FillWithHTOffsets(data_ptr_t *key_locations, JoinHTScanState &state); - idx_t Count() { + idx_t Count() const { return block_collection->count; } + const RowDataCollection &GetBlockCollection() const { + return *block_collection; + } + //! BufferManager BufferManager &buffer_manager; + //! The join conditions + const vector &conditions; //! The types of the keys used in equality comparison vector equality_types; //! The types of the keys @@ -60524,6 +65888,7 @@ class JoinHashTable { } correlated_mark_join_info; private: + unique_ptr InitializeScanStructure(DataChunk &keys, const SelectionVector *¤t_sel); void Hash(DataChunk &keys, const SelectionVector &sel, idx_t count, Vector &hashes); //! Apply a bitmask to the hashes @@ -60531,11 +65896,10 @@ class JoinHashTable { void ApplyBitmask(Vector &hashes, const SelectionVector &sel, idx_t count, Vector &pointers); private: - //! Insert the given set of locations into the HT with the given set of - //! hashes. Caller should hold lock in parallel HT. - void InsertHashes(Vector &hashes, idx_t count, data_ptr_t key_locations[]); + //! Insert the given set of locations into the HT with the given set of hashes + void InsertHashes(Vector &hashes, idx_t count, data_ptr_t key_locations[], bool parallel); - idx_t PrepareKeys(DataChunk &keys, unique_ptr &key_data, const SelectionVector *¤t_sel, + idx_t PrepareKeys(DataChunk &keys, unique_ptr &key_data, const SelectionVector *¤t_sel, SelectionVector &sel, bool build_side); //! The RowDataCollection holding the main data of the hash table @@ -60543,14 +65907,78 @@ class JoinHashTable { //! The stringheap of the JoinHashTable unique_ptr string_heap; //! Pinned handles, these are pinned during finalization only - vector> pinned_handles; + mutex pinned_handles_lock; + vector pinned_handles; //! The hash map of the HT, created after finalization - unique_ptr hash_map; + BufferHandle hash_map; //! Whether or not NULL values are considered equal in each of the comparisons vector null_values_are_equal; //! Copying not allowed JoinHashTable(const JoinHashTable &) = delete; + +public: + //===--------------------------------------------------------------------===// + // External Join + //===--------------------------------------------------------------------===// + //! Whether we are doing an external hash join + bool external; + //! The current number of radix bits used to partition + idx_t radix_bits; + //! Total count + idx_t total_count; + //! Number of tuples for the build-side HT per partitioned round + idx_t tuples_per_round; + + //! The number of tuples that are swizzled + idx_t SwizzledCount() { + return swizzled_block_collection->count; + } + //! Size of the in-memory data + idx_t SizeInBytes() { + return block_collection->SizeInBytes() + string_heap->SizeInBytes(); + } + //! Size of the swizzled data + idx_t SwizzledSize() { + return swizzled_block_collection->SizeInBytes() + swizzled_string_heap->SizeInBytes(); + } + idx_t PointerTableCapacity(idx_t count) { + return NextPowerOfTwo(MaxValue(count * 2, (Storage::BLOCK_SIZE / sizeof(data_ptr_t)) + 1)); + } + + //! Swizzle the blocks in this HT (moves from block_collection and string_heap to swizzled_...) + void SwizzleBlocks(); + //! Unswizzle the blocks in this HT (moves from swizzled_... to block_collection and string_heap) + void UnswizzleBlocks(); + + //! Computes partition sizes and number of radix bits (called before scheduling partition tasks) + void ComputePartitionSizes(ClientConfig &config, vector> &local_hts, idx_t max_ht_size); + //! Partition this HT + void Partition(JoinHashTable &global_ht); + + //! Delete blocks that belong to the current partitioned HT + void Reset(); + //! Build HT for the next partitioned probe round + bool PrepareExternalFinalize(); + //! Probe whatever we can, sink the rest into a thread-local HT + unique_ptr ProbeAndSpill(DataChunk &keys, DataChunk &payload, ColumnDataCollection &spill_collection, + ColumnDataAppendState &spill_append_state, DataChunk &spill_chunk); + +private: + //! First and last partition of the current partitioned round + idx_t partition_start; + idx_t partition_end; + + //! The RowDataCollection holding the swizzled main data of the hash table + unique_ptr swizzled_block_collection; + //! The stringheap accompanying the swizzled main data + unique_ptr swizzled_string_heap; + + //! Partitioned data lock + mutex partition_lock; + //! Partitioned data + vector> partition_block_collections; + vector> partition_string_heaps; }; } // namespace duckdb @@ -60562,6 +65990,8 @@ class JoinHashTable { + + namespace duckdb { using ValidityBytes = JoinHashTable::ValidityBytes; @@ -60569,8 +65999,9 @@ using ScanStructure = JoinHashTable::ScanStructure; JoinHashTable::JoinHashTable(BufferManager &buffer_manager, const vector &conditions, vector btypes, JoinType type) - : buffer_manager(buffer_manager), build_types(move(btypes)), entry_size(0), tuple_size(0), - vfound(Value::BOOLEAN(false)), join_type(type), finalized(false), has_null(false) { + : buffer_manager(buffer_manager), conditions(conditions), build_types(move(btypes)), entry_size(0), tuple_size(0), + vfound(Value::BOOLEAN(false)), join_type(type), finalized(false), has_null(false), external(false), radix_bits(4), + tuples_per_round(0), partition_start(0), partition_end(0) { for (auto &condition : conditions) { D_ASSERT(condition.left->return_type == condition.right->return_type); auto type = condition.left->return_type; @@ -60613,18 +66044,62 @@ JoinHashTable::JoinHashTable(BufferManager &buffer_manager, const vector(STANDARD_VECTOR_SIZE, (Storage::BLOCK_SIZE / entry_size) + 1); block_collection = make_unique(buffer_manager, block_capacity, entry_size); string_heap = make_unique(buffer_manager, (idx_t)Storage::BLOCK_SIZE, 1, true); + swizzled_block_collection = block_collection->CloneEmpty(); + swizzled_string_heap = string_heap->CloneEmpty(); } JoinHashTable::~JoinHashTable() { } +void JoinHashTable::Merge(JoinHashTable &other) { + block_collection->Merge(*other.block_collection); + swizzled_block_collection->Merge(*other.swizzled_block_collection); + if (!layout.AllConstant()) { + string_heap->Merge(*other.string_heap); + swizzled_string_heap->Merge(*other.swizzled_string_heap); + } + + if (join_type == JoinType::MARK) { + auto &info = correlated_mark_join_info; + lock_guard mj_lock(info.mj_lock); + has_null = has_null || other.has_null; + if (!info.correlated_types.empty()) { + auto &other_info = other.correlated_mark_join_info; + info.correlated_counts->Combine(*other_info.correlated_counts); + } + } + + lock_guard lock(partition_lock); + if (partition_block_collections.empty()) { + D_ASSERT(partition_string_heaps.empty()); + // Move partitions to this HT + for (idx_t p = 0; p < other.partition_block_collections.size(); p++) { + partition_block_collections.push_back(move(other.partition_block_collections[p])); + if (!layout.AllConstant()) { + partition_string_heaps.push_back(move(other.partition_string_heaps[p])); + } + } + return; + } + + // Should have same number of partitions + D_ASSERT(partition_block_collections.size() == other.partition_block_collections.size()); + D_ASSERT(partition_string_heaps.size() == other.partition_string_heaps.size()); + for (idx_t idx = 0; idx < other.partition_block_collections.size(); idx++) { + partition_block_collections[idx]->Merge(*other.partition_block_collections[idx]); + if (!layout.AllConstant()) { + partition_string_heaps[idx]->Merge(*other.partition_string_heaps[idx]); + } + } +} + void JoinHashTable::ApplyBitmask(Vector &hashes, idx_t count) { if (hashes.GetVectorType() == VectorType::CONSTANT_VECTOR) { D_ASSERT(!ConstantVector::IsNull(hashes)); auto indices = ConstantVector::GetData(hashes); *indices = *indices & bitmask; } else { - hashes.Normalify(count); + hashes.Flatten(count); auto indices = FlatVector::GetData(hashes); for (idx_t i = 0; i < count; i++) { indices[i] &= bitmask; @@ -60633,12 +66108,12 @@ void JoinHashTable::ApplyBitmask(Vector &hashes, idx_t count) { } void JoinHashTable::ApplyBitmask(Vector &hashes, const SelectionVector &sel, idx_t count, Vector &pointers) { - VectorData hdata; - hashes.Orrify(count, hdata); + UnifiedVectorFormat hdata; + hashes.ToUnifiedFormat(count, hdata); auto hash_data = (hash_t *)hdata.data; auto result_data = FlatVector::GetData(pointers); - auto main_ht = (data_ptr_t *)hash_map->node->buffer; + auto main_ht = (data_ptr_t *)hash_map.Ptr(); for (idx_t i = 0; i < count; i++) { auto rindex = sel.get_index(i); auto hindex = hdata.sel->get_index(rindex); @@ -60663,7 +66138,8 @@ void JoinHashTable::Hash(DataChunk &keys, const SelectionVector &sel, idx_t coun } } -static idx_t FilterNullValues(VectorData &vdata, const SelectionVector &sel, idx_t count, SelectionVector &result) { +static idx_t FilterNullValues(UnifiedVectorFormat &vdata, const SelectionVector &sel, idx_t count, + SelectionVector &result) { idx_t result_count = 0; for (idx_t i = 0; i < count; i++) { auto idx = sel.get_index(i); @@ -60675,9 +66151,9 @@ static idx_t FilterNullValues(VectorData &vdata, const SelectionVector &sel, idx return result_count; } -idx_t JoinHashTable::PrepareKeys(DataChunk &keys, unique_ptr &key_data, +idx_t JoinHashTable::PrepareKeys(DataChunk &keys, unique_ptr &key_data, const SelectionVector *¤t_sel, SelectionVector &sel, bool build_side) { - key_data = keys.Orrify(); + key_data = keys.ToUnifiedFormat(); // figure out which keys are NULL, and create a selection vector out of them current_sel = FlatVector::IncrementalSelectionVector(); @@ -60728,7 +66204,7 @@ void JoinHashTable::Build(DataChunk &keys, DataChunk &payload) { } // prepare the keys for processing - unique_ptr key_data; + unique_ptr key_data; const SelectionVector *current_sel; SelectionVector sel(STANDARD_VECTOR_SIZE); idx_t added_count = PrepareKeys(keys, key_data, current_sel, sel, true); @@ -60753,7 +66229,7 @@ void JoinHashTable::Build(DataChunk &keys, DataChunk &payload) { DataChunk source_chunk; source_chunk.InitializeEmpty(layout.GetTypes()); - vector source_data; + vector source_data; source_data.reserve(layout.ColumnCount()); // serialize the keys to the key locations @@ -60765,22 +66241,22 @@ void JoinHashTable::Build(DataChunk &keys, DataChunk &payload) { D_ASSERT(build_types.size() == payload.ColumnCount()); for (idx_t i = 0; i < payload.ColumnCount(); i++) { source_chunk.data[source_data.size()].Reference(payload.data[i]); - VectorData pdata; - payload.data[i].Orrify(payload.size(), pdata); + UnifiedVectorFormat pdata; + payload.data[i].ToUnifiedFormat(payload.size(), pdata); source_data.emplace_back(move(pdata)); } if (IsRightOuterJoin(join_type)) { // for FULL/RIGHT OUTER joins initialize the "found" boolean to false source_chunk.data[source_data.size()].Reference(vfound); - VectorData fdata; - vfound.Orrify(keys.size(), fdata); + UnifiedVectorFormat fdata; + vfound.ToUnifiedFormat(keys.size(), fdata); source_data.emplace_back(move(fdata)); } // serialise the hashes at the end source_chunk.data[source_data.size()].Reference(hash_values); - VectorData hdata; - hash_values.Orrify(keys.size(), hdata); + UnifiedVectorFormat hdata; + hash_values.ToUnifiedFormat(keys.size(), hdata); source_data.emplace_back(move(hdata)); source_chunk.SetCardinality(keys); @@ -60789,39 +66265,67 @@ void JoinHashTable::Build(DataChunk &keys, DataChunk &payload) { added_count); } -void JoinHashTable::InsertHashes(Vector &hashes, idx_t count, data_ptr_t key_locations[]) { - D_ASSERT(hashes.GetType().id() == LogicalTypeId::HASH); +template +static inline void InsertHashesLoop(atomic pointers[], const hash_t indices[], const idx_t count, + const data_ptr_t key_locations[], const idx_t pointer_offset) { + for (idx_t i = 0; i < count; i++) { + auto index = indices[i]; + if (PARALLEL) { + data_ptr_t head; + do { + head = pointers[index]; + Store(head, key_locations[i] + pointer_offset); + } while (!std::atomic_compare_exchange_weak(&pointers[index], &head, key_locations[i])); + } else { + // set prev in current key to the value (NOTE: this will be nullptr if there is none) + Store(pointers[index], key_locations[i] + pointer_offset); + + // set pointer to current tuple + pointers[index] = key_locations[i]; + } + } +} + +void JoinHashTable::InsertHashes(Vector &hashes, idx_t count, data_ptr_t key_locations[], bool parallel) { + D_ASSERT(hashes.GetType().id() == LogicalType::HASH); // use bitmask to get position in array ApplyBitmask(hashes, count); - hashes.Normalify(count); - + hashes.Flatten(count); D_ASSERT(hashes.GetVectorType() == VectorType::FLAT_VECTOR); - auto pointers = (data_ptr_t *)hash_map->node->buffer; + + auto pointers = (atomic *)hash_map.Ptr(); auto indices = FlatVector::GetData(hashes); - for (idx_t i = 0; i < count; i++) { - auto index = indices[i]; - // set prev in current key to the value (NOTE: this will be nullptr if - // there is none) - Store(pointers[index], key_locations[i] + pointer_offset); - // set pointer to current tuple - pointers[index] = key_locations[i]; + if (parallel) { + InsertHashesLoop(pointers, indices, count, key_locations, pointer_offset); + } else { + InsertHashesLoop(pointers, indices, count, key_locations, pointer_offset); } } -void JoinHashTable::Finalize() { - // the build has finished, now iterate over all the nodes and construct the final hash table - // select a HT that has at least 50% empty space - idx_t capacity = NextPowerOfTwo(MaxValue(Count() * 2, (Storage::BLOCK_SIZE / sizeof(data_ptr_t)) + 1)); +void JoinHashTable::InitializePointerTable() { + idx_t count = external ? MaxValue(tuples_per_round, Count()) : Count(); + idx_t capacity = PointerTableCapacity(count); // size needs to be a power of 2 D_ASSERT((capacity & (capacity - 1)) == 0); bitmask = capacity - 1; - // allocate the HT and initialize it with all-zero entries - hash_map = buffer_manager.Allocate(capacity * sizeof(data_ptr_t)); - memset(hash_map->node->buffer, 0, capacity * sizeof(data_ptr_t)); + if (!hash_map.IsValid()) { + // allocate the HT if not yet done + hash_map = buffer_manager.Allocate(capacity * sizeof(data_ptr_t)); + } + + // initialize HT with all-zero entries + memset(hash_map.Ptr(), 0, capacity * sizeof(data_ptr_t)); +} + +void JoinHashTable::Finalize(idx_t block_idx_start, idx_t block_idx_end, bool parallel) { + // Pointer table should be allocated + D_ASSERT(hash_map.IsValid()); + + vector local_pinned_handles; Vector hashes(LogicalType::HASH); auto hash_data = FlatVector::GetData(hashes); @@ -60829,31 +66333,34 @@ void JoinHashTable::Finalize() { // now construct the actual hash table; scan the nodes // as we can the nodes we pin all the blocks of the HT and keep them pinned until the HT is destroyed // this is so that we can keep pointers around to the blocks - // FIXME: if we cannot keep everything pinned in memory, we could switch to an out-of-memory merge join or so - for (auto &block : block_collection->blocks) { - auto handle = buffer_manager.Pin(block.block); - data_ptr_t dataptr = handle->node->buffer; + for (idx_t block_idx = block_idx_start; block_idx < block_idx_end; block_idx++) { + auto &block = block_collection->blocks[block_idx]; + auto handle = buffer_manager.Pin(block->block); + data_ptr_t dataptr = handle.Ptr(); idx_t entry = 0; - while (entry < block.count) { + while (entry < block->count) { // fetch the next vector of entries from the blocks - idx_t next = MinValue(STANDARD_VECTOR_SIZE, block.count - entry); + idx_t next = MinValue(STANDARD_VECTOR_SIZE, block->count - entry); for (idx_t i = 0; i < next; i++) { hash_data[i] = Load((data_ptr_t)(dataptr + pointer_offset)); key_locations[i] = dataptr; dataptr += entry_size; } // now insert into the hash table - InsertHashes(hashes, next, key_locations); + InsertHashes(hashes, next, key_locations, parallel); entry += next; } - pinned_handles.push_back(move(handle)); + local_pinned_handles.push_back(move(handle)); } - finalized = true; + lock_guard lock(pinned_handles_lock); + for (auto &local_pinned_handle : local_pinned_handles) { + pinned_handles.push_back(move(local_pinned_handle)); + } } -unique_ptr JoinHashTable::Probe(DataChunk &keys) { +unique_ptr JoinHashTable::InitializeScanStructure(DataChunk &keys, const SelectionVector *¤t_sel) { D_ASSERT(Count() > 0); // should be handled before D_ASSERT(finalized); @@ -60866,30 +66373,31 @@ unique_ptr JoinHashTable::Probe(DataChunk &keys) { } // first prepare the keys for probing - const SelectionVector *current_sel; ss->count = PrepareKeys(keys, ss->key_data, current_sel, ss->sel_vector, false); + return ss; +} + +unique_ptr JoinHashTable::Probe(DataChunk &keys, Vector *precomputed_hashes) { + const SelectionVector *current_sel; + auto ss = InitializeScanStructure(keys, current_sel); if (ss->count == 0) { return ss; } - // hash all the keys - Vector hashes(LogicalType::HASH); - Hash(keys, *current_sel, ss->count, hashes); + if (precomputed_hashes) { + ApplyBitmask(*precomputed_hashes, *current_sel, ss->count, ss->pointers); + } else { + // hash all the keys + Vector hashes(LogicalType::HASH); + Hash(keys, *current_sel, ss->count, hashes); - // now initialize the pointers of the scan structure based on the hashes - ApplyBitmask(hashes, *current_sel, ss->count, ss->pointers); + // now initialize the pointers of the scan structure based on the hashes + ApplyBitmask(hashes, *current_sel, ss->count, ss->pointers); + } // create the selection vector linking to only non-empty entries - idx_t count = 0; - auto pointers = FlatVector::GetData(ss->pointers); - for (idx_t i = 0; i < ss->count; i++) { - auto idx = current_sel->get_index(i); - pointers[idx] = Load(pointers[idx]); - if (pointers[idx]) { - ss->sel_vector.set_index(count++, idx); - } - } - ss->count = count; + ss->InitializeSelectionVector(current_sel); + return ss; } @@ -60976,14 +66484,27 @@ void ScanStructure::AdvancePointers(const SelectionVector &sel, idx_t sel_count) this->count = new_count; } +void ScanStructure::InitializeSelectionVector(const SelectionVector *¤t_sel) { + idx_t non_empty_count = 0; + auto ptrs = FlatVector::GetData(pointers); + auto cnt = count; + for (idx_t i = 0; i < cnt; i++) { + const auto idx = current_sel->get_index(i); + ptrs[idx] = Load(ptrs[idx]); + if (ptrs[idx]) { + sel_vector.set_index(non_empty_count++, idx); + } + } + count = non_empty_count; +} + void ScanStructure::AdvancePointers() { AdvancePointers(this->sel_vector, this->count); } void ScanStructure::GatherResult(Vector &result, const SelectionVector &result_vector, const SelectionVector &sel_vector, const idx_t count, const idx_t col_no) { - const auto col_offset = ht.layout.GetOffsets()[col_no]; - RowOperations::Gather(pointers, sel_vector, result, result_vector, count, col_offset, col_no); + RowOperations::Gather(pointers, sel_vector, result, result_vector, count, ht.layout, col_no); } void ScanStructure::GatherResult(Vector &result, const SelectionVector &sel_vector, const idx_t count, @@ -61105,8 +66626,8 @@ void ScanStructure::ConstructMarkJoinResult(DataChunk &join_keys, DataChunk &chi if (ht.null_values_are_equal[col_idx]) { continue; } - VectorData jdata; - join_keys.data[col_idx].Orrify(join_keys.size(), jdata); + UnifiedVectorFormat jdata; + join_keys.data[col_idx].ToUnifiedFormat(join_keys.size(), jdata); if (!jdata.validity.AllValid()) { for (idx_t i = 0; i < join_keys.size(); i++) { auto jidx = jdata.sel->get_index(i); @@ -61174,8 +66695,8 @@ void ScanStructure::NextMarkJoin(DataChunk &keys, DataChunk &input, DataChunk &r mask.Copy(FlatVector::Validity(last_key), input.size()); break; default: { - VectorData kdata; - last_key.Orrify(keys.size(), kdata); + UnifiedVectorFormat kdata; + last_key.ToUnifiedFormat(keys.size(), kdata); for (idx_t i = 0; i < input.size(); i++) { auto kidx = kdata.sel->get_index(i); mask.Set(i, kdata.validity.RowIsValid(kidx)); @@ -61281,64 +66802,64 @@ void ScanStructure::NextSingleJoin(DataChunk &keys, DataChunk &input, DataChunk finished = true; } -void JoinHashTable::ScanFullOuter(DataChunk &result, JoinHTScanState &state) { +idx_t JoinHashTable::ScanFullOuter(JoinHTScanState &state, Vector &addresses) { // scan the HT starting from the current position and check which rows from the build side did not find a match - Vector addresses(LogicalType::POINTER); auto key_locations = FlatVector::GetData(addresses); idx_t found_entries = 0; - { - lock_guard state_lock(state.lock); - for (; state.block_position < block_collection->blocks.size(); state.block_position++, state.position = 0) { - auto &block = block_collection->blocks[state.block_position]; - auto &handle = pinned_handles[state.block_position]; - auto baseptr = handle->node->buffer; - for (; state.position < block.count; state.position++) { - auto tuple_base = baseptr + state.position * entry_size; - auto found_match = Load(tuple_base + tuple_size); - if (!found_match) { - key_locations[found_entries++] = tuple_base; - if (found_entries == STANDARD_VECTOR_SIZE) { - state.position++; - break; - } + for (; state.block_position < block_collection->blocks.size(); state.block_position++, state.position = 0) { + auto &block = block_collection->blocks[state.block_position]; + auto handle = buffer_manager.Pin(block->block); + auto baseptr = handle.Ptr(); + for (; state.position < block->count; state.position++, state.scan_index++) { + auto tuple_base = baseptr + state.position * entry_size; + auto found_match = Load(tuple_base + tuple_size); + if (!found_match) { + key_locations[found_entries++] = tuple_base; + if (found_entries == STANDARD_VECTOR_SIZE) { + state.position++; + state.scan_index++; + break; } } - if (found_entries == STANDARD_VECTOR_SIZE) { - break; - } + } + if (found_entries == STANDARD_VECTOR_SIZE) { + break; } } + return found_entries; +} + +void JoinHashTable::GatherFullOuter(DataChunk &result, Vector &addresses, idx_t found_entries) { + if (found_entries == 0) { + return; + } result.SetCardinality(found_entries); - if (found_entries > 0) { - idx_t left_column_count = result.ColumnCount() - build_types.size(); - const auto &sel_vector = *FlatVector::IncrementalSelectionVector(); - // set the left side as a constant NULL - for (idx_t i = 0; i < left_column_count; i++) { - Vector &vec = result.data[i]; - vec.SetVectorType(VectorType::CONSTANT_VECTOR); - ConstantVector::SetNull(vec, true); - } - // gather the values from the RHS - for (idx_t i = 0; i < build_types.size(); i++) { - auto &vector = result.data[left_column_count + i]; - D_ASSERT(vector.GetType() == build_types[i]); - const auto col_no = condition_types.size() + i; - const auto col_offset = layout.GetOffsets()[col_no]; - RowOperations::Gather(addresses, sel_vector, vector, sel_vector, found_entries, col_offset, col_no); - } + idx_t left_column_count = result.ColumnCount() - build_types.size(); + const auto &sel_vector = *FlatVector::IncrementalSelectionVector(); + // set the left side as a constant NULL + for (idx_t i = 0; i < left_column_count; i++) { + Vector &vec = result.data[i]; + vec.SetVectorType(VectorType::CONSTANT_VECTOR); + ConstantVector::SetNull(vec, true); + } + // gather the values from the RHS + for (idx_t i = 0; i < build_types.size(); i++) { + auto &vector = result.data[left_column_count + i]; + D_ASSERT(vector.GetType() == build_types[i]); + const auto col_no = condition_types.size() + i; + RowOperations::Gather(addresses, sel_vector, vector, sel_vector, found_entries, layout, col_no); } } idx_t JoinHashTable::FillWithHTOffsets(data_ptr_t *key_locations, JoinHTScanState &state) { - // iterate over blocks idx_t key_count = 0; while (state.block_position < block_collection->blocks.size()) { auto &block = block_collection->blocks[state.block_position]; - auto handle = buffer_manager.Pin(block.block); - auto base_ptr = handle->node->buffer; + auto handle = buffer_manager.Pin(block->block); + auto base_ptr = handle.Ptr(); // go through all the tuples within this block - while (state.position < block.count) { + while (state.position < block->count) { auto tuple_base = base_ptr + state.position * entry_size; // store its locations key_locations[key_count++] = tuple_base; @@ -61349,6 +66870,307 @@ idx_t JoinHashTable::FillWithHTOffsets(data_ptr_t *key_locations, JoinHTScanStat } return key_count; } + +void JoinHashTable::SwizzleBlocks() { + if (block_collection->count == 0) { + return; + } + + if (layout.AllConstant()) { + // No heap blocks! Just merge fixed-size data + swizzled_block_collection->Merge(*block_collection); + return; + } + + // We create one heap block per data block and swizzle the pointers + auto &heap_blocks = string_heap->blocks; + idx_t heap_block_idx = 0; + idx_t heap_block_remaining = heap_blocks[heap_block_idx]->count; + for (auto &data_block : block_collection->blocks) { + if (heap_block_remaining == 0) { + heap_block_remaining = heap_blocks[++heap_block_idx]->count; + } + + // Pin the data block and swizzle the pointers within the rows + auto data_handle = buffer_manager.Pin(data_block->block); + auto data_ptr = data_handle.Ptr(); + RowOperations::SwizzleColumns(layout, data_ptr, data_block->count); + + // We want to copy as little of the heap data as possible, check how the data and heap blocks line up + if (heap_block_remaining >= data_block->count) { + // Easy: current heap block contains all strings for this data block, just copy (reference) the block + swizzled_string_heap->blocks.emplace_back(heap_blocks[heap_block_idx]->Copy()); + swizzled_string_heap->blocks.back()->count = data_block->count; + + // Swizzle the heap pointer + auto heap_handle = buffer_manager.Pin(swizzled_string_heap->blocks.back()->block); + auto heap_ptr = Load(data_ptr + layout.GetHeapOffset()); + auto heap_offset = heap_ptr - heap_handle.Ptr(); + RowOperations::SwizzleHeapPointer(layout, data_ptr, heap_ptr, data_block->count, heap_offset); + + // Update counter + heap_block_remaining -= data_block->count; + } else { + // Strings for this data block are spread over the current heap block and the next (and possibly more) + idx_t data_block_remaining = data_block->count; + vector> ptrs_and_sizes; + idx_t total_size = 0; + while (data_block_remaining > 0) { + if (heap_block_remaining == 0) { + heap_block_remaining = heap_blocks[++heap_block_idx]->count; + } + auto next = MinValue(data_block_remaining, heap_block_remaining); + + // Figure out where to start copying strings, and how many bytes we need to copy + auto heap_start_ptr = Load(data_ptr + layout.GetHeapOffset()); + auto heap_end_ptr = + Load(data_ptr + layout.GetHeapOffset() + (next - 1) * layout.GetRowWidth()); + idx_t size = heap_end_ptr - heap_start_ptr + Load(heap_end_ptr); + ptrs_and_sizes.emplace_back(heap_start_ptr, size); + D_ASSERT(size <= heap_blocks[heap_block_idx]->byte_offset); + + // Swizzle the heap pointer + RowOperations::SwizzleHeapPointer(layout, data_ptr, heap_start_ptr, next, total_size); + total_size += size; + + // Update where we are in the data and heap blocks + data_ptr += next * layout.GetRowWidth(); + data_block_remaining -= next; + heap_block_remaining -= next; + } + + // Finally, we allocate a new heap block and copy data to it + swizzled_string_heap->blocks.emplace_back( + make_unique(buffer_manager, MaxValue(total_size, (idx_t)Storage::BLOCK_SIZE), 1)); + auto new_heap_handle = buffer_manager.Pin(swizzled_string_heap->blocks.back()->block); + auto new_heap_ptr = new_heap_handle.Ptr(); + for (auto &ptr_and_size : ptrs_and_sizes) { + memcpy(new_heap_ptr, ptr_and_size.first, ptr_and_size.second); + new_heap_ptr += ptr_and_size.second; + } + } + } + + // We're done with variable-sized data, now just merge the fixed-size data + swizzled_block_collection->Merge(*block_collection); + D_ASSERT(swizzled_block_collection->blocks.size() == swizzled_string_heap->blocks.size()); + + // Update counts and cleanup + swizzled_string_heap->count = string_heap->count; + string_heap->Clear(); +} + +void JoinHashTable::UnswizzleBlocks() { + auto &blocks = swizzled_block_collection->blocks; + auto &heap_blocks = swizzled_string_heap->blocks; +#ifdef DEBUG + if (!layout.AllConstant()) { + D_ASSERT(blocks.size() == heap_blocks.size()); + D_ASSERT(swizzled_block_collection->count == swizzled_string_heap->count); + } +#endif + + for (idx_t block_idx = 0; block_idx < blocks.size(); block_idx++) { + auto &data_block = blocks[block_idx]; + + if (!layout.AllConstant()) { + auto block_handle = buffer_manager.Pin(data_block->block); + + auto &heap_block = heap_blocks[block_idx]; + D_ASSERT(data_block->count == heap_block->count); + auto heap_handle = buffer_manager.Pin(heap_block->block); + + // Unswizzle and move + RowOperations::UnswizzlePointers(layout, block_handle.Ptr(), heap_handle.Ptr(), data_block->count); + string_heap->blocks.push_back(move(heap_block)); + string_heap->pinned_blocks.push_back(move(heap_handle)); + } + + // Fixed size stuff can just be moved + block_collection->blocks.push_back(move(data_block)); + } + + // Update counts and clean up + block_collection->count = swizzled_block_collection->count; + string_heap->count = swizzled_string_heap->count; + swizzled_block_collection->Clear(); + swizzled_string_heap->Clear(); + + D_ASSERT(SwizzledCount() == 0); +} + +void JoinHashTable::ComputePartitionSizes(ClientConfig &config, vector> &local_hts, + idx_t max_ht_size) { + external = true; + + // First set the number of tuples in the HT per partitioned round + total_count = 0; + idx_t total_size = 0; + for (auto &ht : local_hts) { + // TODO: SizeInBytes / SwizzledSize overestimates size by a lot because we make extra references of heap blocks + // Need to compute this more accurately + total_count += ht->Count() + ht->SwizzledCount(); + total_size += ht->SizeInBytes() + ht->SwizzledSize(); + } + + if (total_count == 0) { + return; + } + + total_size += PointerTableCapacity(total_count) * sizeof(data_ptr_t); + idx_t avg_tuple_size = total_size / total_count; + tuples_per_round = max_ht_size / avg_tuple_size; + + if (config.force_external) { + // For force_external we do three rounds to test all code paths + tuples_per_round = (total_count + 2) / 3; + } + + // Set the number of radix bits (minimum 4, maximum 8) + for (; radix_bits < 8; radix_bits++) { + auto num_partitions = RadixPartitioning::NumberOfPartitions(radix_bits); + auto avg_partition_size = total_size / num_partitions; + + // We aim for at least 8 partitions per probe round (tweaked experimentally) + if (avg_partition_size * 8 < max_ht_size) { + break; + } + } +} + +void JoinHashTable::Partition(JoinHashTable &global_ht) { +#ifdef DEBUG + D_ASSERT(layout.ColumnCount() == global_ht.layout.ColumnCount()); + for (idx_t col_idx = 0; col_idx < layout.ColumnCount(); col_idx++) { + D_ASSERT(layout.GetTypes()[col_idx] == global_ht.layout.GetTypes()[col_idx]); + } +#endif + + // Swizzle and Partition + SwizzleBlocks(); + RadixPartitioning::Partition(global_ht.buffer_manager, global_ht.layout, global_ht.pointer_offset, + *swizzled_block_collection, *swizzled_string_heap, partition_block_collections, + partition_string_heaps, global_ht.radix_bits); + + // Add to global HT + global_ht.Merge(*this); +} + +void JoinHashTable::Reset() { + pinned_handles.clear(); + block_collection->Clear(); + string_heap->Clear(); + finalized = false; +} + +bool JoinHashTable::PrepareExternalFinalize() { + idx_t num_partitions = RadixPartitioning::NumberOfPartitions(radix_bits); + if (partition_block_collections.empty() || partition_end == num_partitions) { + return false; + } + + if (finalized) { + Reset(); + } + + // Determine how many partitions we can do next (at least one) + idx_t next = 0; + idx_t count = 0; + partition_start = partition_end; + for (idx_t p = partition_start; p < num_partitions; p++) { + auto partition_count = partition_block_collections[p]->count; + if (partition_count != 0 && count != 0 && count + partition_count > tuples_per_round) { + // We skip over empty partitions (partition_count != 0), + // and need to have at least one partition (count != 0) + break; + } + next++; + count += partition_count; + } + partition_end += next; + + // Move specific partitions to the swizzled_... collections so they can be unswizzled + D_ASSERT(SwizzledCount() == 0); + for (idx_t p = partition_start; p < partition_end; p++) { + auto &p_block_collection = *partition_block_collections[p]; + if (!layout.AllConstant()) { + auto &p_string_heap = *partition_string_heaps[p]; + D_ASSERT(p_block_collection.count == p_string_heap.count); + swizzled_string_heap->Merge(p_string_heap); + // Remove after merging + partition_string_heaps[p] = nullptr; + } + swizzled_block_collection->Merge(p_block_collection); + // Remove after merging + partition_block_collections[p] = nullptr; + } + D_ASSERT(count == SwizzledCount()); + + // Unswizzle them + D_ASSERT(Count() == 0); + UnswizzleBlocks(); + D_ASSERT(count == Count()); + + return true; +} + +static void CreateSpillChunk(DataChunk &spill_chunk, DataChunk &keys, DataChunk &payload, Vector &hashes) { + spill_chunk.Reset(); + idx_t spill_col_idx = 0; + for (idx_t col_idx = 0; col_idx < keys.ColumnCount(); col_idx++) { + spill_chunk.data[col_idx].Reference(keys.data[col_idx]); + } + spill_col_idx += keys.ColumnCount(); + for (idx_t col_idx = 0; col_idx < payload.data.size(); col_idx++) { + spill_chunk.data[spill_col_idx + col_idx].Reference(payload.data[col_idx]); + } + spill_col_idx += payload.ColumnCount(); + spill_chunk.data[spill_col_idx].Reference(hashes); +} + +unique_ptr JoinHashTable::ProbeAndSpill(DataChunk &keys, DataChunk &payload, + ColumnDataCollection &spill_collection, + ColumnDataAppendState &spill_append_state, + DataChunk &spill_chunk) { + // hash all the keys + Vector hashes(LogicalType::HASH); + Hash(keys, *FlatVector::IncrementalSelectionVector(), keys.size(), hashes); + + // find out which keys we can match with the current pinned partitions + SelectionVector true_sel; + SelectionVector false_sel; + true_sel.Initialize(); + false_sel.Initialize(); + auto true_count = RadixPartitioning::Select(hashes, FlatVector::IncrementalSelectionVector(), keys.size(), + radix_bits, partition_end, &true_sel, &false_sel); + auto false_count = keys.size() - true_count; + + // slice the stuff we CAN'T probe right now and append to spill collection + CreateSpillChunk(spill_chunk, keys, payload, hashes); + spill_chunk.Slice(false_sel, false_count); + spill_chunk.Verify(); + spill_collection.Append(spill_append_state, spill_chunk); + + // slice the stuff we CAN probe right now + hashes.Slice(true_sel, true_count); + keys.Slice(true_sel, true_count); + payload.Slice(true_sel, true_count); + + const SelectionVector *current_sel; + auto ss = InitializeScanStructure(keys, current_sel); + if (ss->count == 0) { + return ss; + } + + // now initialize the pointers of the scan structure based on the hashes + ApplyBitmask(hashes, *current_sel, ss->count, ss->pointers); + + // create the selection vector linking to only non-empty entries + ss->InitializeSelectionVector(current_sel); + + return ss; +} + } // namespace duckdb //===----------------------------------------------------------------------===// @@ -61367,6 +67189,7 @@ idx_t JoinHashTable::FillWithHTOffsets(data_ptr_t *key_locations, JoinHTScanStat namespace duckdb { +class ColumnDataCollection; struct NestedLoopJoinInner { static idx_t Perform(idx_t <uple, idx_t &rtuple, DataChunk &left_conditions, DataChunk &right_conditions, @@ -61374,7 +67197,7 @@ struct NestedLoopJoinInner { }; struct NestedLoopJoinMark { - static void Perform(DataChunk &left, ChunkCollection &right, bool found_match[], + static void Perform(DataChunk &left, ColumnDataCollection &right, bool found_match[], const vector &conditions); }; @@ -61400,9 +67223,9 @@ struct InitialNestedLoopJoin { SelectionVector &lvector, SelectionVector &rvector, idx_t current_match_count) { // initialize phase of nested loop join // fill lvector and rvector with matches from the base vectors - VectorData left_data, right_data; - left.Orrify(left_size, left_data); - right.Orrify(right_size, right_data); + UnifiedVectorFormat left_data, right_data; + left.ToUnifiedFormat(left_size, left_data); + right.ToUnifiedFormat(right_size, right_data); auto ldata = (T *)left_data.data; auto rdata = (T *)right_data.data; @@ -61434,9 +67257,9 @@ struct RefineNestedLoopJoin { template static idx_t Operation(Vector &left, Vector &right, idx_t left_size, idx_t right_size, idx_t &lpos, idx_t &rpos, SelectionVector &lvector, SelectionVector &rvector, idx_t current_match_count) { - VectorData left_data, right_data; - left.Orrify(left_size, left_data); - right.Orrify(right_size, right_data); + UnifiedVectorFormat left_data, right_data; + left.ToUnifiedFormat(left_size, left_data); + right.ToUnifiedFormat(right_size, right_data); // refine phase of the nested loop join // refine lvector and rvector based on matches of subsequent conditions (in case there are multiple conditions @@ -61582,9 +67405,9 @@ namespace duckdb { template static void TemplatedMarkJoin(Vector &left, Vector &right, idx_t lcount, idx_t rcount, bool found_match[]) { - VectorData left_data, right_data; - left.Orrify(lcount, left_data); - right.Orrify(rcount, right_data); + UnifiedVectorFormat left_data, right_data; + left.ToUnifiedFormat(lcount, left_data); + right.ToUnifiedFormat(rcount, right_data); auto ldata = (T *)left_data.data; auto rdata = (T *)right_data.data; @@ -61663,14 +67486,19 @@ static void MarkJoinComparisonSwitch(Vector &left, Vector &right, idx_t lcount, } } -void NestedLoopJoinMark::Perform(DataChunk &left, ChunkCollection &right, bool found_match[], +void NestedLoopJoinMark::Perform(DataChunk &left, ColumnDataCollection &right, bool found_match[], const vector &conditions) { // initialize a new temporary selection vector for the left chunk // loop over all chunks in the RHS - for (idx_t chunk_idx = 0; chunk_idx < right.ChunkCount(); chunk_idx++) { - DataChunk &right_chunk = right.GetChunk(chunk_idx); + ColumnDataScanState scan_state; + right.InitializeScan(scan_state); + + DataChunk scan_chunk; + right.InitializeScanChunk(scan_chunk); + + while (right.Scan(scan_state, scan_chunk)) { for (idx_t i = 0; i < conditions.size(); i++) { - MarkJoinComparisonSwitch(left.data[i], right_chunk.data[i], left.size(), right_chunk.size(), found_match, + MarkJoinComparisonSwitch(left.data[i], scan_chunk.data[i], left.size(), scan_chunk.size(), found_match, conditions[i].comparison); } } @@ -61680,6 +67508,277 @@ void NestedLoopJoinMark::Perform(DataChunk &left, ChunkCollection &right, bool f +namespace duckdb { + +AggregateObject::AggregateObject(AggregateFunction function, FunctionData *bind_data, idx_t child_count, + idx_t payload_size, bool distinct, PhysicalType return_type, Expression *filter) + : function(move(function)), bind_data(bind_data), child_count(child_count), payload_size(payload_size), + distinct(distinct), return_type(return_type), filter(filter) { +} + +AggregateObject::AggregateObject(BoundAggregateExpression *aggr) + : AggregateObject(aggr->function, aggr->bind_info.get(), aggr->children.size(), + AlignValue(aggr->function.state_size()), aggr->distinct, aggr->return_type.InternalType(), + aggr->filter.get()) { +} + +vector AggregateObject::CreateAggregateObjects(const vector &bindings) { + vector aggregates; + aggregates.reserve(aggregates.size()); + for (auto &binding : bindings) { + aggregates.emplace_back(binding); + } + return aggregates; +} + +AggregateFilterData::AggregateFilterData(Allocator &allocator, Expression &filter_expr, + const vector &payload_types) + : filter_executor(allocator, &filter_expr), true_sel(STANDARD_VECTOR_SIZE) { + if (payload_types.empty()) { + return; + } + filtered_payload.Initialize(allocator, payload_types); +} + +idx_t AggregateFilterData::ApplyFilter(DataChunk &payload) { + filtered_payload.Reset(); + + auto count = filter_executor.SelectExpression(payload, true_sel); + filtered_payload.Slice(payload, true_sel, count); + return count; +} + +AggregateFilterDataSet::AggregateFilterDataSet() { +} + +void AggregateFilterDataSet::Initialize(Allocator &allocator, const vector &aggregates, + const vector &payload_types) { + bool has_filters = false; + for (auto &aggregate : aggregates) { + if (aggregate.filter) { + has_filters = true; + break; + } + } + if (!has_filters) { + // no filters: nothing to do + return; + } + filter_data.resize(aggregates.size()); + for (idx_t aggr_idx = 0; aggr_idx < aggregates.size(); aggr_idx++) { + auto &aggr = aggregates[aggr_idx]; + if (aggr.filter) { + filter_data[aggr_idx] = make_unique(allocator, *aggr.filter, payload_types); + } + } +} + +AggregateFilterData &AggregateFilterDataSet::GetFilterData(idx_t aggr_idx) { + D_ASSERT(aggr_idx < filter_data.size()); + D_ASSERT(filter_data[aggr_idx]); + return *filter_data[aggr_idx]; +} +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/operator/aggregate/grouped_aggregate_data.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +struct DistinctAggregateData { +public: + DistinctAggregateData(Allocator &allocator, const vector> &aggregates, vector indices, + ClientContext &client); + //! The executor + ExpressionExecutor child_executor; + //! The payload chunk + DataChunk payload_chunk; + //! Indices of the distinct aggregates + vector indices; + //! The data used by the hashtables + vector> grouped_aggregate_data; + //! The hashtables + vector> radix_tables; + //! The groups (arguments) + vector grouping_sets; + //! The global sink states of the hash tables + vector> radix_states; + //! Output chunks to receive distinct data from hashtables + vector> distinct_output_chunks; + //! Mapping from aggregate index to table + //! This indirection is used to allow two aggregates to share the same input data + unordered_map table_map; + //! Occupied tables, not equal to indices if aggregates share input data + vector table_indices; + +public: + bool IsDistinct(idx_t index) const; + const vector &Indices() const; + bool AnyDistinct() const; + +private: + //! Returns the amount of tables that are occupied + idx_t CreateTableIndexMap(const vector> &aggregates); +}; + +} // namespace duckdb + + + + + +namespace duckdb { + +DistinctAggregateData::DistinctAggregateData(Allocator &allocator, const vector> &aggregates, + vector indices, ClientContext &client) + : child_executor(allocator), payload_chunk(), indices(move(indices)) { + const idx_t aggregate_count = aggregates.size(); + + idx_t table_count = CreateTableIndexMap(aggregates); + + grouped_aggregate_data.resize(table_count); + radix_tables.resize(table_count); + radix_states.resize(table_count); + grouping_sets.resize(table_count); + distinct_output_chunks.resize(table_count); + + vector payload_types; + for (idx_t i = 0; i < aggregate_count; i++) { + auto &aggregate = (BoundAggregateExpression &)*aggregates[i]; + + // Initialize the child executor and get the payload types for every aggregate + for (auto &child : aggregate.children) { + payload_types.push_back(child->return_type); + child_executor.AddExpression(*child); + } + if (!aggregate.distinct) { + continue; + } + D_ASSERT(table_map.count(i)); + idx_t table_idx = table_map[i]; + if (radix_tables[table_idx] != nullptr) { + //! Table is already initialized + continue; + } + //! Populate the group with the children of the aggregate + for (size_t set_idx = 0; set_idx < aggregate.children.size(); set_idx++) { + grouping_sets[table_idx].insert(set_idx); + } + // Create the hashtable for the aggregate + grouped_aggregate_data[table_idx] = make_unique(); + grouped_aggregate_data[table_idx]->InitializeDistinct(aggregates[i]); + radix_tables[table_idx] = + make_unique(grouping_sets[table_idx], *grouped_aggregate_data[table_idx]); + + auto &radix_table = *radix_tables[table_idx]; + radix_states[table_idx] = radix_table.GetGlobalSinkState(client); + + vector chunk_types; + for (auto &child_p : aggregate.children) { + chunk_types.push_back(child_p->return_type); + } + + // This is used in Finalize to get the data from the radix table + distinct_output_chunks[table_idx] = make_unique(); + distinct_output_chunks[table_idx]->Initialize(client, chunk_types); + } + if (!payload_types.empty()) { + payload_chunk.Initialize(allocator, payload_types); + } +} + +using aggr_ref_t = std::reference_wrapper; + +struct FindMatchingAggregate { + explicit FindMatchingAggregate(const aggr_ref_t &aggr) : aggr_r(aggr) { + } + bool operator()(const aggr_ref_t other_r) { + auto &other = other_r.get(); + auto &aggr = aggr_r.get(); + if (other.children.size() != aggr.children.size()) { + return false; + } + if (!Expression::Equals(aggr.filter.get(), other.filter.get())) { + return false; + } + for (idx_t i = 0; i < aggr.children.size(); i++) { + auto &other_child = (BoundReferenceExpression &)*other.children[i]; + auto &aggr_child = (BoundReferenceExpression &)*aggr.children[i]; + if (other_child.index != aggr_child.index) { + return false; + } + } + return true; + } + const aggr_ref_t aggr_r; +}; + +idx_t DistinctAggregateData::CreateTableIndexMap(const vector> &aggregates) { + vector table_inputs; + + D_ASSERT(table_map.empty()); + for (auto &agg_idx : indices) { + D_ASSERT(agg_idx < aggregates.size()); + auto &aggregate = (BoundAggregateExpression &)*aggregates[agg_idx]; + + auto matching_inputs = + std::find_if(table_inputs.begin(), table_inputs.end(), FindMatchingAggregate(std::ref(aggregate))); + if (matching_inputs != table_inputs.end()) { + //! Assign the existing table to the aggregate + idx_t found_idx = std::distance(table_inputs.begin(), matching_inputs); + table_map[agg_idx] = found_idx; + continue; + } + //! Create a new table and assign its index to the aggregate + table_map[agg_idx] = table_inputs.size(); + table_inputs.push_back(std::ref(aggregate)); + } + //! Every distinct aggregate needs to be assigned an index + D_ASSERT(table_map.size() == indices.size()); + //! There can not be more tables then there are distinct aggregates + D_ASSERT(table_inputs.size() <= indices.size()); + + return table_inputs.size(); +} + +bool DistinctAggregateData::AnyDistinct() const { + return !radix_tables.empty(); +} + +const vector &DistinctAggregateData::Indices() const { + return this->indices; +} + +bool DistinctAggregateData::IsDistinct(idx_t index) const { + bool is_distinct = !radix_tables.empty() && table_map.count(index); +#ifdef DEBUG + //! Make sure that if it is distinct, it's also in the indices + //! And if it's not distinct, that it's also not in the indices + bool found = false; + for (auto &idx : indices) { + if (idx == index) { + found = true; + break; + } + } + D_ASSERT(found == is_distinct); +#endif + return is_distinct; +} + +} // namespace duckdb + + + @@ -61783,47 +67882,19 @@ PhysicalHashAggregate::PhysicalHashAggregate(ClientContext &context, vector grouping_sets_p, vector> grouping_functions_p, idx_t estimated_cardinality, PhysicalOperatorType type) - : PhysicalOperator(type, move(types), estimated_cardinality), groups(move(groups_p)), - grouping_sets(move(grouping_sets_p)), grouping_functions(move(grouping_functions_p)), any_distinct(false) { + : PhysicalOperator(type, move(types), estimated_cardinality), grouping_sets(move(grouping_sets_p)) { // get a list of all aggregates to be computed - for (auto &expr : groups) { - group_types.push_back(expr->return_type); - } + const idx_t group_count = groups_p.size(); if (grouping_sets.empty()) { GroupingSet set; - for (idx_t i = 0; i < group_types.size(); i++) { + for (idx_t i = 0; i < group_count; i++) { set.insert(i); } grouping_sets.push_back(move(set)); } - vector payload_types_filters; - for (auto &expr : expressions) { - D_ASSERT(expr->expression_class == ExpressionClass::BOUND_AGGREGATE); - D_ASSERT(expr->IsAggregate()); - auto &aggr = (BoundAggregateExpression &)*expr; - bindings.push_back(&aggr); - - if (aggr.distinct) { - any_distinct = true; - } - - aggregate_return_types.push_back(aggr.return_type); - for (auto &child : aggr.children) { - payload_types.push_back(child->return_type); - } - if (aggr.filter) { - payload_types_filters.push_back(aggr.filter->return_type); - } - if (!aggr.function.combine) { - throw InternalException("Aggregate function %s is missing a combine method", aggr.function.name); - } - aggregates.push_back(move(expr)); - } - - for (const auto &pay_filters : payload_types_filters) { - payload_types.push_back(pay_filters); - } + grouped_aggregate_data.InitializeGroupby(move(groups_p), move(expressions), move(grouping_functions_p)); + auto &aggregates = grouped_aggregate_data.aggregates; // filter_indexes must be pre-built, not lazily instantiated in parallel... idx_t aggregate_input_idx = 0; for (auto &aggregate : aggregates) { @@ -61845,7 +67916,7 @@ PhysicalHashAggregate::PhysicalHashAggregate(ClientContext &context, vector state_index; vector> radix_states; + +public: +#if 0 + idx_t MaxThreads() override { + // If there are no tables, we only need one thread. + if (op.radix_tables.empty()) { + return 1; + } + + auto &ht_state = (HashAggregateGlobalState &)*op.sink_state; + idx_t count = 0; + for (size_t sidx = 0; sidx < op.radix_tables.size(); ++sidx) { + count += op.radix_tables[sidx].Size(*ht_state.radix_states[sidx]); + } + + return (count + STANDARD_VECTOR_SIZE - 1 ) / STANDARD_VECTOR_SIZE; + } +#endif }; unique_ptr PhysicalHashAggregate::GetGlobalSourceState(ClientContext &context) const { - return make_unique(*this); + return make_unique(context, *this); +} + +class PhysicalHashAggregateLocalSourceState : public LocalSourceState { +public: + explicit PhysicalHashAggregateLocalSourceState(ExecutionContext &context, const PhysicalHashAggregate &op) { + for (auto &rt : op.radix_tables) { + radix_states.push_back(rt.GetLocalSourceState(context)); + } + } + + vector> radix_states; +}; + +unique_ptr PhysicalHashAggregate::GetLocalSourceState(ExecutionContext &context, + GlobalSourceState &gstate) const { + return make_unique(context, *this); } void PhysicalHashAggregate::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate_p, - LocalSourceState &lstate) const { - auto &gstate = (HashAggregateGlobalState &)*sink_state; - auto &state = (PhysicalHashAggregateState &)gstate_p; - while (state.scan_index < state.radix_states.size()) { - radix_tables[state.scan_index].GetData(context, chunk, *gstate.radix_states[state.scan_index], - *state.radix_states[state.scan_index]); + LocalSourceState &lstate_p) const { + auto &ht_state = (HashAggregateGlobalState &)*sink_state; + auto &gstate = (PhysicalHashAggregateGlobalSourceState &)gstate_p; + auto &lstate = (PhysicalHashAggregateLocalSourceState &)lstate_p; + for (size_t sidx = gstate.state_index; sidx < radix_tables.size(); sidx = ++gstate.state_index) { + radix_tables[sidx].GetData(context, chunk, *ht_state.radix_states[sidx], *gstate.radix_states[sidx], + *lstate.radix_states[sidx]); if (chunk.size() != 0) { return; } - - state.scan_index++; } } string PhysicalHashAggregate::ParamsToString() const { string result; + auto &groups = grouped_aggregate_data.groups; + auto &aggregates = grouped_aggregate_data.aggregates; for (idx_t i = 0; i < groups.size(); i++) { if (i > 0) { result += "\n"; @@ -62087,7 +68197,7 @@ class PhysicalPerfectHashAggregate : public PhysicalOperator { string ParamsToString() const override; //! Create a perfect aggregate hash table for this node - unique_ptr CreateHT(ClientContext &context) const; + unique_ptr CreateHT(Allocator &allocator, ClientContext &context) const; bool IsSink() const override { return true; @@ -62131,9 +68241,10 @@ namespace duckdb { class PerfectAggregateHashTable : public BaseAggregateHashTable { public: - PerfectAggregateHashTable(BufferManager &buffer_manager, const vector &group_types, - vector payload_types_p, vector aggregate_objects, - vector group_minima, vector required_bits); + PerfectAggregateHashTable(Allocator &allocator, BufferManager &buffer_manager, + const vector &group_types, vector payload_types_p, + vector aggregate_objects, vector group_minima, + vector required_bits); ~PerfectAggregateHashTable() override; public: @@ -62207,8 +68318,8 @@ namespace duckdb { class NumericStatistics : public BaseStatistics { public: - explicit NumericStatistics(LogicalType type, StatisticsType stats_type); - NumericStatistics(LogicalType type, Value min, Value max, StatisticsType stats_type); + DUCKDB_API explicit NumericStatistics(LogicalType type, StatisticsType stats_type); + DUCKDB_API NumericStatistics(LogicalType type, Value min, Value max, StatisticsType stats_type); //! The minimum value of the segment Value min; @@ -62216,11 +68327,11 @@ class NumericStatistics : public BaseStatistics { Value max; public: - void Merge(const BaseStatistics &other) override; + DUCKDB_API void Merge(const BaseStatistics &other) override; - bool IsConstant() const override; + DUCKDB_API bool IsConstant() const override; - FilterPropagateResult CheckZonemap(ExpressionType comparison_type, const Value &constant) const; + DUCKDB_API FilterPropagateResult CheckZonemap(ExpressionType comparison_type, const Value &constant) const; unique_ptr Copy() const override; void Serialize(FieldWriter &writer) const override; @@ -62323,9 +68434,10 @@ PhysicalPerfectHashAggregate::PhysicalPerfectHashAggregate(ClientContext &contex } } -unique_ptr PhysicalPerfectHashAggregate::CreateHT(ClientContext &context) const { - return make_unique(BufferManager::GetBufferManager(context), group_types, payload_types, - aggregate_objects, group_minima, required_bits); +unique_ptr PhysicalPerfectHashAggregate::CreateHT(Allocator &allocator, + ClientContext &context) const { + return make_unique(allocator, BufferManager::GetBufferManager(context), group_types, + payload_types, aggregate_objects, group_minima, required_bits); } //===--------------------------------------------------------------------===// @@ -62334,7 +68446,7 @@ unique_ptr PhysicalPerfectHashAggregate::CreateHT(Cli class PerfectHashAggregateGlobalState : public GlobalSinkState { public: PerfectHashAggregateGlobalState(const PhysicalPerfectHashAggregate &op, ClientContext &context) - : ht(op.CreateHT(context)) { + : ht(op.CreateHT(Allocator::Get(context), context)) { } //! The lock for updating the global aggregate state @@ -62345,8 +68457,8 @@ class PerfectHashAggregateGlobalState : public GlobalSinkState { class PerfectHashAggregateLocalState : public LocalSinkState { public: - PerfectHashAggregateLocalState(const PhysicalPerfectHashAggregate &op, ClientContext &context) - : ht(op.CreateHT(context)) { + PerfectHashAggregateLocalState(const PhysicalPerfectHashAggregate &op, ExecutionContext &context) + : ht(op.CreateHT(Allocator::Get(context.client), context.client)) { group_chunk.InitializeEmpty(op.group_types); if (!op.payload_types.empty()) { aggregate_input_chunk.InitializeEmpty(op.payload_types); @@ -62364,7 +68476,7 @@ unique_ptr PhysicalPerfectHashAggregate::GetGlobalSinkState(Cli } unique_ptr PhysicalPerfectHashAggregate::GetLocalSinkState(ExecutionContext &context) const { - return make_unique(*this, context.client); + return make_unique(*this, context); } SinkResultType PhysicalPerfectHashAggregate::Sink(ExecutionContext &context, GlobalSinkState &state, @@ -62470,7 +68582,7 @@ string PhysicalPerfectHashAggregate::ParamsToString() const { //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/execution/operator/aggregate/physical_simple_aggregate.hpp +// duckdb/execution/operator/aggregate/physical_window.hpp // // //===----------------------------------------------------------------------===// @@ -62482,46 +68594,31 @@ string PhysicalPerfectHashAggregate::ParamsToString() const { namespace duckdb { -//! PhysicalSimpleAggregate is an aggregate operator that can only perform aggregates (1) without any groups, (2) -//! without any DISTINCT aggregates, and (3) when all aggregates are combineable -class PhysicalSimpleAggregate : public PhysicalOperator { +//! PhysicalStreamingWindow implements streaming window functions (i.e. with an empty OVER clause) +class PhysicalStreamingWindow : public PhysicalOperator { public: - PhysicalSimpleAggregate(vector types, vector> expressions, - idx_t estimated_cardinality); - - //! The aggregates that have to be computed - vector> aggregates; + PhysicalStreamingWindow(vector types, vector> select_list, + idx_t estimated_cardinality, + PhysicalOperatorType type = PhysicalOperatorType::STREAMING_WINDOW); -public: - // Source interface - unique_ptr GetGlobalSourceState(ClientContext &context) const override; - void GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, - LocalSourceState &lstate) const override; + //! The projection list of the WINDOW statement + vector> select_list; public: - // Sink interface - SinkResultType Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, - DataChunk &input) const override; - void Combine(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate) const override; - SinkFinalizeType Finalize(Pipeline &pipeline, Event &event, ClientContext &context, - GlobalSinkState &gstate) const override; + unique_ptr GetGlobalOperatorState(ClientContext &context) const override; + unique_ptr GetOperatorState(ExecutionContext &context) const override; - unique_ptr GetLocalSinkState(ExecutionContext &context) const override; - unique_ptr GetGlobalSinkState(ClientContext &context) const override; + OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, + GlobalOperatorState &gstate, OperatorState &state) const override; string ParamsToString() const override; - - bool IsSink() const override { - return true; - } - - bool ParallelSink() const override { - return true; - } }; } // namespace duckdb + + + //===----------------------------------------------------------------------===// // DuckDB // @@ -62551,279 +68648,6 @@ class ThreadContext { - - - -namespace duckdb { - -PhysicalSimpleAggregate::PhysicalSimpleAggregate(vector types, vector> expressions, - idx_t estimated_cardinality) - : PhysicalOperator(PhysicalOperatorType::SIMPLE_AGGREGATE, move(types), estimated_cardinality), - aggregates(move(expressions)) { -} - -//===--------------------------------------------------------------------===// -// Sink -//===--------------------------------------------------------------------===// -struct AggregateState { - explicit AggregateState(const vector> &aggregate_expressions) { - for (auto &aggregate : aggregate_expressions) { - D_ASSERT(aggregate->GetExpressionClass() == ExpressionClass::BOUND_AGGREGATE); - auto &aggr = (BoundAggregateExpression &)*aggregate; - auto state = unique_ptr(new data_t[aggr.function.state_size()]); - aggr.function.initialize(state.get()); - aggregates.push_back(move(state)); - destructors.push_back(aggr.function.destructor); - } - } - ~AggregateState() { - D_ASSERT(destructors.size() == aggregates.size()); - for (idx_t i = 0; i < destructors.size(); i++) { - if (!destructors[i]) { - continue; - } - Vector state_vector(Value::POINTER((uintptr_t)aggregates[i].get())); - state_vector.SetVectorType(VectorType::FLAT_VECTOR); - - destructors[i](state_vector, 1); - } - } - - void Move(AggregateState &other) { - other.aggregates = move(aggregates); - other.destructors = move(destructors); - } - - //! The aggregate values - vector> aggregates; - // The destructors - vector destructors; -}; - -class SimpleAggregateGlobalState : public GlobalSinkState { -public: - explicit SimpleAggregateGlobalState(const vector> &aggregates) - : state(aggregates), finished(false) { - } - - //! The lock for updating the global aggregate state - mutex lock; - //! The global aggregate state - AggregateState state; - //! Whether or not the aggregate is finished - bool finished; -}; - -class SimpleAggregateLocalState : public LocalSinkState { -public: - explicit SimpleAggregateLocalState(const vector> &aggregates) : state(aggregates) { - vector payload_types; - for (auto &aggregate : aggregates) { - D_ASSERT(aggregate->GetExpressionClass() == ExpressionClass::BOUND_AGGREGATE); - auto &aggr = (BoundAggregateExpression &)*aggregate; - // initialize the payload chunk - if (!aggr.children.empty()) { - for (auto &child : aggr.children) { - payload_types.push_back(child->return_type); - child_executor.AddExpression(*child); - } - } - } - if (!payload_types.empty()) { // for select count(*) from t; there is no payload at all - payload_chunk.Initialize(payload_types); - } - } - void Reset() { - payload_chunk.Reset(); - } - - //! The local aggregate state - AggregateState state; - //! The executor - ExpressionExecutor child_executor; - //! The payload chunk - DataChunk payload_chunk; -}; - -unique_ptr PhysicalSimpleAggregate::GetGlobalSinkState(ClientContext &context) const { - return make_unique(aggregates); -} - -unique_ptr PhysicalSimpleAggregate::GetLocalSinkState(ExecutionContext &context) const { - return make_unique(aggregates); -} - -SinkResultType PhysicalSimpleAggregate::Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, - DataChunk &input) const { - auto &sink = (SimpleAggregateLocalState &)lstate; - // perform the aggregation inside the local state - idx_t payload_idx = 0, payload_expr_idx = 0; - sink.Reset(); - - DataChunk &payload_chunk = sink.payload_chunk; - for (idx_t aggr_idx = 0; aggr_idx < aggregates.size(); aggr_idx++) { - DataChunk filtered_input; - auto &aggregate = (BoundAggregateExpression &)*aggregates[aggr_idx]; - idx_t payload_cnt = 0; - // resolve the filter (if any) - if (aggregate.filter) { - ExpressionExecutor filter_execution(aggregate.filter.get()); - SelectionVector true_sel(STANDARD_VECTOR_SIZE); - auto count = filter_execution.SelectExpression(input, true_sel); - auto input_types = input.GetTypes(); - filtered_input.Initialize(input_types); - filtered_input.Slice(input, true_sel, count); - sink.child_executor.SetChunk(filtered_input); - payload_chunk.SetCardinality(count); - } else { - sink.child_executor.SetChunk(input); - payload_chunk.SetCardinality(input); - } - // resolve the child expressions of the aggregate (if any) - if (!aggregate.children.empty()) { - for (idx_t i = 0; i < aggregate.children.size(); ++i) { - sink.child_executor.ExecuteExpression(payload_expr_idx, payload_chunk.data[payload_idx + payload_cnt]); - payload_expr_idx++; - payload_cnt++; - } - } - - aggregate.function.simple_update(payload_cnt == 0 ? nullptr : &payload_chunk.data[payload_idx], - aggregate.bind_info.get(), payload_cnt, sink.state.aggregates[aggr_idx].get(), - payload_chunk.size()); - payload_idx += payload_cnt; - } - return SinkResultType::NEED_MORE_INPUT; -} - -//===--------------------------------------------------------------------===// -// Finalize -//===--------------------------------------------------------------------===// -void PhysicalSimpleAggregate::Combine(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate) const { - auto &gstate = (SimpleAggregateGlobalState &)state; - auto &source = (SimpleAggregateLocalState &)lstate; - D_ASSERT(!gstate.finished); - - // finalize: combine the local state into the global state - // all aggregates are combinable: we might be doing a parallel aggregate - // use the combine method to combine the partial aggregates - lock_guard glock(gstate.lock); - for (idx_t aggr_idx = 0; aggr_idx < aggregates.size(); aggr_idx++) { - auto &aggregate = (BoundAggregateExpression &)*aggregates[aggr_idx]; - Vector source_state(Value::POINTER((uintptr_t)source.state.aggregates[aggr_idx].get())); - Vector dest_state(Value::POINTER((uintptr_t)gstate.state.aggregates[aggr_idx].get())); - - aggregate.function.combine(source_state, dest_state, aggregate.bind_info.get(), 1); - } - - auto &client_profiler = QueryProfiler::Get(context.client); - context.thread.profiler.Flush(this, &source.child_executor, "child_executor", 0); - client_profiler.Flush(context.thread.profiler); -} - -SinkFinalizeType PhysicalSimpleAggregate::Finalize(Pipeline &pipeline, Event &event, ClientContext &context, - GlobalSinkState &gstate_p) const { - auto &gstate = (SimpleAggregateGlobalState &)gstate_p; - - D_ASSERT(!gstate.finished); - gstate.finished = true; - return SinkFinalizeType::READY; -} - -//===--------------------------------------------------------------------===// -// Source -//===--------------------------------------------------------------------===// -class SimpleAggregateState : public GlobalSourceState { -public: - SimpleAggregateState() : finished(false) { - } - - bool finished; -}; - -unique_ptr PhysicalSimpleAggregate::GetGlobalSourceState(ClientContext &context) const { - return make_unique(); -} - -void PhysicalSimpleAggregate::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate_p, - LocalSourceState &lstate) const { - auto &gstate = (SimpleAggregateGlobalState &)*sink_state; - auto &state = (SimpleAggregateState &)gstate_p; - D_ASSERT(gstate.finished); - if (state.finished) { - return; - } - - // initialize the result chunk with the aggregate values - chunk.SetCardinality(1); - for (idx_t aggr_idx = 0; aggr_idx < aggregates.size(); aggr_idx++) { - auto &aggregate = (BoundAggregateExpression &)*aggregates[aggr_idx]; - - Vector state_vector(Value::POINTER((uintptr_t)gstate.state.aggregates[aggr_idx].get())); - aggregate.function.finalize(state_vector, aggregate.bind_info.get(), chunk.data[aggr_idx], 1, 0); - } - state.finished = true; -} - -string PhysicalSimpleAggregate::ParamsToString() const { - string result; - for (idx_t i = 0; i < aggregates.size(); i++) { - auto &aggregate = (BoundAggregateExpression &)*aggregates[i]; - if (i > 0) { - result += "\n"; - } - result += aggregates[i]->GetName(); - if (aggregate.filter) { - result += " Filter: " + aggregate.filter->GetName(); - } - } - return result; -} - -} // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/operator/aggregate/physical_window.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { - -//! PhysicalStreamingWindow implements streaming window functions (i.e. with an empty OVER clause) -class PhysicalStreamingWindow : public PhysicalOperator { -public: - PhysicalStreamingWindow(vector types, vector> select_list, - idx_t estimated_cardinality, - PhysicalOperatorType type = PhysicalOperatorType::STREAMING_WINDOW); - - //! The projection list of the WINDOW statement - vector> select_list; - -public: - unique_ptr GetGlobalOperatorState(ClientContext &context) const override; - unique_ptr GetOperatorState(ClientContext &context) const override; - - OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, - GlobalOperatorState &gstate, OperatorState &state) const override; - - string ParamsToString() const override; -}; - -} // namespace duckdb - - - - - - - namespace duckdb { PhysicalStreamingWindow::PhysicalStreamingWindow(vector types, vector> select_list, @@ -62842,30 +68666,60 @@ class StreamingWindowGlobalState : public GlobalOperatorState { class StreamingWindowState : public OperatorState { public: - StreamingWindowState() : initialized(false) { + using StateBuffer = vector; + + StreamingWindowState() : initialized(false), statev(LogicalType::POINTER, (data_ptr_t)&state_ptr) { + } + + ~StreamingWindowState() override { + for (size_t i = 0; i < aggregate_dtors.size(); ++i) { + auto dtor = aggregate_dtors[i]; + if (dtor) { + state_ptr = aggregate_states[i].data(); + dtor(statev, 1); + } + } } - void Initialize(DataChunk &input, const vector> &expressions) { + void Initialize(Allocator &allocator, DataChunk &input, const vector> &expressions) { + const_vectors.resize(expressions.size()); + aggregate_states.resize(expressions.size()); + aggregate_dtors.resize(expressions.size(), nullptr); + for (idx_t expr_idx = 0; expr_idx < expressions.size(); expr_idx++) { auto &expr = *expressions[expr_idx]; + auto &wexpr = (BoundWindowExpression &)expr; switch (expr.GetExpressionType()) { + case ExpressionType::WINDOW_AGGREGATE: { + auto &aggregate = *wexpr.aggregate; + auto &state = aggregate_states[expr_idx]; + aggregate_dtors[expr_idx] = aggregate.destructor; + state.resize(aggregate.state_size()); + aggregate.initialize(state.data()); + break; + } case ExpressionType::WINDOW_FIRST_VALUE: { - auto &wexpr = (BoundWindowExpression &)expr; - auto &ref = (BoundReferenceExpression &)*wexpr.children[0]; - const_vectors.push_back(make_unique(input.data[ref.index].GetValue(0))); + // Just execute the expression once + ExpressionExecutor executor(allocator); + executor.AddExpression(*wexpr.children[0]); + DataChunk result; + result.Initialize(allocator, {wexpr.children[0]->return_type}); + executor.Execute(input, result); + + const_vectors[expr_idx] = make_unique(result.GetValue(0, 0)); break; } case ExpressionType::WINDOW_PERCENT_RANK: { - const_vectors.push_back(make_unique(Value((double)0))); + const_vectors[expr_idx] = make_unique(Value((double)0)); break; } case ExpressionType::WINDOW_RANK: case ExpressionType::WINDOW_RANK_DENSE: { - const_vectors.push_back(make_unique(Value((int64_t)1))); + const_vectors[expr_idx] = make_unique(Value((int64_t)1)); break; } default: - const_vectors.push_back(nullptr); + break; } } initialized = true; @@ -62874,13 +68728,19 @@ class StreamingWindowState : public OperatorState { public: bool initialized; vector> const_vectors; + + // Aggregation + vector aggregate_states; + vector aggregate_dtors; + data_ptr_t state_ptr; + Vector statev; }; unique_ptr PhysicalStreamingWindow::GetGlobalOperatorState(ClientContext &context) const { return make_unique(); } -unique_ptr PhysicalStreamingWindow::GetOperatorState(ClientContext &context) const { +unique_ptr PhysicalStreamingWindow::GetOperatorState(ExecutionContext &context) const { return make_unique(); } @@ -62889,7 +68749,8 @@ OperatorResultType PhysicalStreamingWindow::Execute(ExecutionContext &context, D auto &gstate = (StreamingWindowGlobalState &)gstate_p; auto &state = (StreamingWindowState &)state_p; if (!state.initialized) { - state.Initialize(input, select_list); + auto &allocator = Allocator::Get(context.client); + state.Initialize(allocator, input, select_list); } // Put payload columns in place for (idx_t col_idx = 0; col_idx < input.data.size(); col_idx++) { @@ -62900,7 +68761,58 @@ OperatorResultType PhysicalStreamingWindow::Execute(ExecutionContext &context, D for (idx_t expr_idx = 0; expr_idx < select_list.size(); expr_idx++) { idx_t col_idx = input.data.size() + expr_idx; auto &expr = *select_list[expr_idx]; + auto &result = chunk.data[col_idx]; switch (expr.GetExpressionType()) { + case ExpressionType::WINDOW_AGGREGATE: { + // Establish the aggregation environment + auto &wexpr = (BoundWindowExpression &)expr; + auto &aggregate = *wexpr.aggregate; + auto &statev = state.statev; + state.state_ptr = state.aggregate_states[expr_idx].data(); + AggregateInputData aggr_input_data(wexpr.bind_info.get(), Allocator::DefaultAllocator()); + + // Check for COUNT(*) + if (wexpr.children.empty()) { + D_ASSERT(GetTypeIdSize(result.GetType().InternalType()) == sizeof(int64_t)); + auto data = FlatVector::GetData(result); + for (idx_t i = 0; i < input.size(); ++i) { + data[i] = gstate.row_number + i; + } + break; + } + + // Compute the arguments + auto &allocator = Allocator::Get(context.client); + ExpressionExecutor executor(allocator); + vector payload_types; + for (auto &child : wexpr.children) { + payload_types.push_back(child->return_type); + executor.AddExpression(*child); + } + + DataChunk payload; + payload.Initialize(executor.allocator, payload_types); + executor.Execute(input, payload); + + // Iterate through them using a single SV + payload.Flatten(); + DataChunk row; + row.Initialize(allocator, payload_types); + sel_t s = 0; + SelectionVector sel(&s); + row.Slice(sel, 1); + for (size_t col_idx = 0; col_idx < payload.ColumnCount(); ++col_idx) { + DictionaryVector::Child(row.data[col_idx]).Reference(payload.data[col_idx]); + } + + // Update the state and finalize it one row at a time. + for (idx_t i = 0; i < input.size(); ++i) { + sel.set_index(0, i); + aggregate.update(row.data.data(), aggr_input_data, row.ColumnCount(), statev, 1); + aggregate.finalize(statev, aggr_input_data, result, 1, i); + } + break; + } case ExpressionType::WINDOW_FIRST_VALUE: case ExpressionType::WINDOW_PERCENT_RANK: case ExpressionType::WINDOW_RANK: @@ -62937,6 +68849,684 @@ string PhysicalStreamingWindow::ParamsToString() const { return result; } +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/operator/aggregate/physical_ungrouped_aggregate.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + + + +namespace duckdb { + +//! PhysicalUngroupedAggregate is an aggregate operator that can only perform aggregates (1) without any groups, (2) +//! without any DISTINCT aggregates, and (3) when all aggregates are combineable +class PhysicalUngroupedAggregate : public PhysicalOperator { +public: + PhysicalUngroupedAggregate(vector types, vector> expressions, + idx_t estimated_cardinality); + + //! The aggregates that have to be computed + vector> aggregates; + +public: + // Source interface + unique_ptr GetGlobalSourceState(ClientContext &context) const override; + void GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, + LocalSourceState &lstate) const override; + +public: + // Sink interface + SinkResultType Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, + DataChunk &input) const override; + void Combine(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate) const override; + SinkFinalizeType Finalize(Pipeline &pipeline, Event &event, ClientContext &context, + GlobalSinkState &gstate) const override; + + unique_ptr GetLocalSinkState(ExecutionContext &context) const override; + unique_ptr GetGlobalSinkState(ClientContext &context) const override; + + string ParamsToString() const override; + + bool IsSink() const override { + return true; + } + + bool ParallelSink() const override { + return true; + } + +private: + //! Finalize the distinct aggregates + SinkFinalizeType FinalizeDistinct(Pipeline &pipeline, Event &event, ClientContext &context, + GlobalSinkState &gstate) const; + //! Combine the distinct aggregates + void CombineDistinct(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate) const; + //! Sink the distinct aggregates + void SinkDistinct(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, + DataChunk &input) const; +}; + +} // namespace duckdb + + + + + + + + + + + + + +#include + + +namespace duckdb { + +PhysicalUngroupedAggregate::PhysicalUngroupedAggregate(vector types, + vector> expressions, + idx_t estimated_cardinality) + : PhysicalOperator(PhysicalOperatorType::UNGROUPED_AGGREGATE, move(types), estimated_cardinality), + aggregates(move(expressions)) { +} + +//===--------------------------------------------------------------------===// +// Sink +//===--------------------------------------------------------------------===// +struct AggregateState { + explicit AggregateState(const vector> &aggregate_expressions) { + for (auto &aggregate : aggregate_expressions) { + D_ASSERT(aggregate->GetExpressionClass() == ExpressionClass::BOUND_AGGREGATE); + auto &aggr = (BoundAggregateExpression &)*aggregate; + auto state = unique_ptr(new data_t[aggr.function.state_size()]); + aggr.function.initialize(state.get()); + aggregates.push_back(move(state)); + destructors.push_back(aggr.function.destructor); +#ifdef DEBUG + counts.push_back(0); +#endif + } + } + ~AggregateState() { + D_ASSERT(destructors.size() == aggregates.size()); + for (idx_t i = 0; i < destructors.size(); i++) { + if (!destructors[i]) { + continue; + } + Vector state_vector(Value::POINTER((uintptr_t)aggregates[i].get())); + state_vector.SetVectorType(VectorType::FLAT_VECTOR); + + destructors[i](state_vector, 1); + } + } + + void Move(AggregateState &other) { + other.aggregates = move(aggregates); + other.destructors = move(destructors); + } + + //! The aggregate values + vector> aggregates; + //! The destructors + vector destructors; + //! Counts (used for verification) + vector counts; +}; + +class UngroupedAggregateGlobalState : public GlobalSinkState { +public: + UngroupedAggregateGlobalState(Allocator &allocator, const vector> &aggregates, + ClientContext &client) + : state(aggregates), finished(false) { + + vector indices; + // Determine if there are distinct aggregates + for (idx_t i = 0; i < aggregates.size(); i++) { + auto &aggr = (BoundAggregateExpression &)*(aggregates[i]); + if (!aggr.distinct) { + continue; + } + indices.push_back(i); + } + //! None of the aggregates are distinct + if (indices.empty()) { + return; + } + + distinct_data = make_unique(allocator, aggregates, move(indices), client); + } + + //! The lock for updating the global aggregate state + mutex lock; + //! The global aggregate state + AggregateState state; + //! Whether or not the aggregate is finished + bool finished; + //! The data related to the distinct aggregates (if there are any) + unique_ptr distinct_data; +}; + +class UngroupedAggregateLocalState : public LocalSinkState { +public: + UngroupedAggregateLocalState(Allocator &allocator, const vector> &aggregates, + const vector &child_types, GlobalSinkState &gstate_p, + ExecutionContext &context) + : state(aggregates), child_executor(allocator), payload_chunk(), filter_set() { + auto &gstate = (UngroupedAggregateGlobalState &)gstate_p; + + InitializeDistinctAggregates(gstate, context); + + vector payload_types; + vector aggregate_objects; + for (auto &aggregate : aggregates) { + D_ASSERT(aggregate->GetExpressionClass() == ExpressionClass::BOUND_AGGREGATE); + auto &aggr = (BoundAggregateExpression &)*aggregate; + // initialize the payload chunk + for (auto &child : aggr.children) { + payload_types.push_back(child->return_type); + child_executor.AddExpression(*child); + } + aggregate_objects.emplace_back(&aggr); + } + if (!payload_types.empty()) { // for select count(*) from t; there is no payload at all + payload_chunk.Initialize(allocator, payload_types); + } + filter_set.Initialize(allocator, aggregate_objects, child_types); + } + + //! The local aggregate state + AggregateState state; + //! The executor + ExpressionExecutor child_executor; + //! The payload chunk, containing all the Vectors for the aggregates + DataChunk payload_chunk; + //! Aggregate filter data set + AggregateFilterDataSet filter_set; + //! The local sink states of the distinct aggregates hash tables + vector> radix_states; + +public: + void Reset() { + payload_chunk.Reset(); + } + void InitializeDistinctAggregates(const UngroupedAggregateGlobalState &gstate, ExecutionContext &context) { + + if (!gstate.distinct_data) { + return; + } + auto &data = *gstate.distinct_data; + auto &distinct_indices = data.Indices(); + if (distinct_indices.empty()) { + // No distinct aggregates + return; + } + D_ASSERT(!data.radix_tables.empty()); + + const idx_t aggregate_cnt = data.radix_tables.size(); + radix_states.resize(aggregate_cnt); + + for (auto &idx : distinct_indices) { + idx_t table_idx = data.table_map[idx]; + if (data.radix_tables[table_idx] == nullptr) { + // This aggregate has identical input as another aggregate, so no table is created for it + continue; + } + auto &radix_table = *data.radix_tables[table_idx]; + radix_states[table_idx] = radix_table.GetLocalSinkState(context); + } + } +}; + +unique_ptr PhysicalUngroupedAggregate::GetGlobalSinkState(ClientContext &context) const { + return make_unique(Allocator::Get(context), aggregates, context); +} + +unique_ptr PhysicalUngroupedAggregate::GetLocalSinkState(ExecutionContext &context) const { + D_ASSERT(sink_state); + auto &gstate = *sink_state; + return make_unique(Allocator::Get(context.client), aggregates, + children[0]->GetTypes(), gstate, context); +} + +void PhysicalUngroupedAggregate::SinkDistinct(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, + DataChunk &input) const { + auto &sink = (UngroupedAggregateLocalState &)lstate; + auto &global_sink = (UngroupedAggregateGlobalState &)state; + D_ASSERT(global_sink.distinct_data); + auto &distinct_aggregate_data = *global_sink.distinct_data; + auto &distinct_indices = distinct_aggregate_data.Indices(); + for (auto &idx : distinct_indices) { + auto &aggregate = (BoundAggregateExpression &)*aggregates[idx]; + + idx_t table_idx = distinct_aggregate_data.table_map[idx]; + if (!distinct_aggregate_data.radix_tables[table_idx]) { + continue; + } + D_ASSERT(distinct_aggregate_data.radix_tables[table_idx]); + auto &radix_table = *distinct_aggregate_data.radix_tables[table_idx]; + auto &radix_global_sink = *distinct_aggregate_data.radix_states[table_idx]; + auto &radix_local_sink = *sink.radix_states[table_idx]; + + if (aggregate.filter) { + // Apply the filter before inserting into the hashtable + auto &filtered_data = sink.filter_set.GetFilterData(idx); + idx_t count = filtered_data.ApplyFilter(input); + filtered_data.filtered_payload.SetCardinality(count); + + radix_table.Sink(context, radix_global_sink, radix_local_sink, filtered_data.filtered_payload, + filtered_data.filtered_payload); + } else { + radix_table.Sink(context, radix_global_sink, radix_local_sink, input, input); + } + } +} + +SinkResultType PhysicalUngroupedAggregate::Sink(ExecutionContext &context, GlobalSinkState &state, + LocalSinkState &lstate, DataChunk &input) const { + auto &sink = (UngroupedAggregateLocalState &)lstate; + auto &gstate = (UngroupedAggregateGlobalState &)state; + + // perform the aggregation inside the local state + sink.Reset(); + + if (gstate.distinct_data) { + SinkDistinct(context, state, lstate, input); + } + + DataChunk &payload_chunk = sink.payload_chunk; + + idx_t payload_idx = 0; + idx_t next_payload_idx = 0; + + for (idx_t aggr_idx = 0; aggr_idx < aggregates.size(); aggr_idx++) { + auto &aggregate = (BoundAggregateExpression &)*aggregates[aggr_idx]; + + payload_idx = next_payload_idx; + next_payload_idx = payload_idx + aggregate.children.size(); + + if (aggregate.distinct) { + continue; + } + + idx_t payload_cnt = 0; + // resolve the filter (if any) + if (aggregate.filter) { + auto &filtered_data = sink.filter_set.GetFilterData(aggr_idx); + auto count = filtered_data.ApplyFilter(input); + + sink.child_executor.SetChunk(filtered_data.filtered_payload); + payload_chunk.SetCardinality(count); + } else { + sink.child_executor.SetChunk(input); + payload_chunk.SetCardinality(input); + } + +#ifdef DEBUG + sink.state.counts[aggr_idx] += payload_chunk.size(); +#endif + + // resolve the child expressions of the aggregate (if any) + for (idx_t i = 0; i < aggregate.children.size(); ++i) { + sink.child_executor.ExecuteExpression(payload_idx + payload_cnt, + payload_chunk.data[payload_idx + payload_cnt]); + payload_cnt++; + } + + auto start_of_input = payload_cnt == 0 ? nullptr : &payload_chunk.data[payload_idx]; + AggregateInputData aggr_input_data(aggregate.bind_info.get(), Allocator::DefaultAllocator()); + aggregate.function.simple_update(start_of_input, aggr_input_data, payload_cnt, + sink.state.aggregates[aggr_idx].get(), payload_chunk.size()); + } + return SinkResultType::NEED_MORE_INPUT; +} + +//===--------------------------------------------------------------------===// +// Finalize +//===--------------------------------------------------------------------===// + +void PhysicalUngroupedAggregate::CombineDistinct(ExecutionContext &context, GlobalSinkState &state, + LocalSinkState &lstate) const { + auto &global_sink = (UngroupedAggregateGlobalState &)state; + auto &source = (UngroupedAggregateLocalState &)lstate; + auto &distinct_aggregate_data = global_sink.distinct_data; + + if (!distinct_aggregate_data) { + return; + } + auto table_count = distinct_aggregate_data->radix_tables.size(); + for (idx_t table_idx = 0; table_idx < table_count; table_idx++) { + D_ASSERT(distinct_aggregate_data->radix_tables[table_idx]); + auto &radix_table = *distinct_aggregate_data->radix_tables[table_idx]; + auto &radix_global_sink = *distinct_aggregate_data->radix_states[table_idx]; + auto &radix_local_sink = *source.radix_states[table_idx]; + + radix_table.Combine(context, radix_global_sink, radix_local_sink); + } +} + +void PhysicalUngroupedAggregate::Combine(ExecutionContext &context, GlobalSinkState &state, + LocalSinkState &lstate) const { + auto &gstate = (UngroupedAggregateGlobalState &)state; + auto &source = (UngroupedAggregateLocalState &)lstate; + D_ASSERT(!gstate.finished); + + // finalize: combine the local state into the global state + // all aggregates are combinable: we might be doing a parallel aggregate + // use the combine method to combine the partial aggregates + lock_guard glock(gstate.lock); + + CombineDistinct(context, state, lstate); + + for (idx_t aggr_idx = 0; aggr_idx < aggregates.size(); aggr_idx++) { + auto &aggregate = (BoundAggregateExpression &)*aggregates[aggr_idx]; + + if (aggregate.distinct) { + continue; + } + + Vector source_state(Value::POINTER((uintptr_t)source.state.aggregates[aggr_idx].get())); + Vector dest_state(Value::POINTER((uintptr_t)gstate.state.aggregates[aggr_idx].get())); + + AggregateInputData aggr_input_data(aggregate.bind_info.get(), Allocator::DefaultAllocator()); + aggregate.function.combine(source_state, dest_state, aggr_input_data, 1); +#ifdef DEBUG + gstate.state.counts[aggr_idx] += source.state.counts[aggr_idx]; +#endif + } + + auto &client_profiler = QueryProfiler::Get(context.client); + context.thread.profiler.Flush(this, &source.child_executor, "child_executor", 0); + client_profiler.Flush(context.thread.profiler); +} + +class DistinctAggregateFinalizeTask : public ExecutorTask { +public: + DistinctAggregateFinalizeTask(Executor &executor, shared_ptr event_p, UngroupedAggregateGlobalState &state_p, + ClientContext &context, const PhysicalUngroupedAggregate &op) + : ExecutorTask(executor), event(move(event_p)), gstate(state_p), context(context), op(op) { + } + + void AggregateDistinct() { + D_ASSERT(gstate.distinct_data); + auto &aggregates = op.aggregates; + auto &distinct_aggregate_data = *gstate.distinct_data; + auto &payload_chunk = distinct_aggregate_data.payload_chunk; + + ThreadContext temp_thread_context(context); + ExecutionContext temp_exec_context(context, temp_thread_context); + + idx_t payload_idx = 0; + idx_t next_payload_idx = 0; + + //! Copy of the payload chunk, used to store the data of the radix table for use with the expression executor + //! We can not directly use the payload chunk because the input and the output to the expression executor can + //! not be the same Vector + DataChunk expression_executor_input; + expression_executor_input.InitializeEmpty(payload_chunk.GetTypes()); + expression_executor_input.SetCardinality(0); + + for (idx_t i = 0; i < aggregates.size(); i++) { + auto &aggregate = (BoundAggregateExpression &)*aggregates[i]; + + // Forward the payload idx + payload_idx = next_payload_idx; + next_payload_idx = payload_idx + aggregate.children.size(); + + // If aggregate is not distinct, skip it + if (!distinct_aggregate_data.IsDistinct(i)) { + continue; + } + D_ASSERT(distinct_aggregate_data.table_map.count(i)); + auto table_idx = distinct_aggregate_data.table_map[i]; + auto &radix_table_p = distinct_aggregate_data.radix_tables[table_idx]; + auto &output_chunk = *distinct_aggregate_data.distinct_output_chunks[table_idx]; + + //! Create global and local state for the hashtable + auto global_source_state = radix_table_p->GetGlobalSourceState(context); + auto local_source_state = radix_table_p->GetLocalSourceState(temp_exec_context); + + //! Retrieve the stored data from the hashtable + while (true) { + payload_chunk.Reset(); + output_chunk.Reset(); + radix_table_p->GetData(temp_exec_context, output_chunk, + *distinct_aggregate_data.radix_states[table_idx], *global_source_state, + *local_source_state); + if (output_chunk.size() == 0) { + break; + } + + for (idx_t child_idx = 0; child_idx < aggregate.children.size(); child_idx++) { + expression_executor_input.data[payload_idx + child_idx].Reference(output_chunk.data[child_idx]); + } + expression_executor_input.SetCardinality(output_chunk); + // We dont need to resolve the filter, we already did this in Sink + distinct_aggregate_data.child_executor.SetChunk(expression_executor_input); + + payload_chunk.SetCardinality(output_chunk); + +#ifdef DEBUG + gstate.state.counts[i] += payload_chunk.size(); +#endif + + // resolve the child expressions of the aggregate (if any) + idx_t payload_cnt = 0; + for (auto &child : aggregate.children) { + //! Before executing, remap the indices to point to the payload_chunk + //! Originally these indices correspond to the 'input' chunk + //! So we need to filter out the data that was used for filters (if any) + auto &child_ref = (BoundReferenceExpression &)*child; + child_ref.index = payload_idx + payload_cnt; + + //! The child_executor contains a pointer to the expression we altered above + distinct_aggregate_data.child_executor.ExecuteExpression( + payload_idx + payload_cnt, payload_chunk.data[payload_idx + payload_cnt]); + payload_cnt++; + } + + auto start_of_input = payload_cnt ? &payload_chunk.data[payload_idx] : nullptr; + //! Update the aggregate state + AggregateInputData aggr_input_data(aggregate.bind_info.get(), Allocator::DefaultAllocator()); + aggregate.function.simple_update(start_of_input, aggr_input_data, payload_cnt, + gstate.state.aggregates[i].get(), payload_chunk.size()); + } + } + D_ASSERT(!gstate.finished); + gstate.finished = true; + } + + TaskExecutionResult ExecuteTask(TaskExecutionMode mode) override { + AggregateDistinct(); + event->FinishTask(); + return TaskExecutionResult::TASK_FINISHED; + } + +private: + shared_ptr event; + UngroupedAggregateGlobalState &gstate; + ClientContext &context; + const PhysicalUngroupedAggregate &op; +}; + +// TODO: Create tasks and run these in parallel instead of doing this all in Schedule, single threaded +class DistinctAggregateFinalizeEvent : public Event { +public: + DistinctAggregateFinalizeEvent(const PhysicalUngroupedAggregate &op_p, UngroupedAggregateGlobalState &gstate_p, + Pipeline *pipeline_p, ClientContext &context) + : Event(pipeline_p->executor), op(op_p), gstate(gstate_p), pipeline(pipeline_p), context(context) { + } + const PhysicalUngroupedAggregate &op; + UngroupedAggregateGlobalState &gstate; + Pipeline *pipeline; + ClientContext &context; + +public: + void Schedule() override { + vector> tasks; + tasks.push_back( + make_unique(pipeline->executor, shared_from_this(), gstate, context, op)); + D_ASSERT(!tasks.empty()); + SetTasks(move(tasks)); + } +}; + +class DistinctCombineFinalizeEvent : public Event { +public: + DistinctCombineFinalizeEvent(const PhysicalUngroupedAggregate &op_p, UngroupedAggregateGlobalState &gstate_p, + Pipeline *pipeline_p, ClientContext &client) + : Event(pipeline_p->executor), op(op_p), gstate(gstate_p), pipeline(pipeline_p), client(client) { + } + + const PhysicalUngroupedAggregate &op; + UngroupedAggregateGlobalState &gstate; + Pipeline *pipeline; + ClientContext &client; + +public: + void Schedule() override { + auto &distinct_data = *gstate.distinct_data; + + vector> tasks; + for (idx_t table_idx = 0; table_idx < distinct_data.radix_tables.size(); table_idx++) { + distinct_data.radix_tables[table_idx]->ScheduleTasks(pipeline->executor, shared_from_this(), + *distinct_data.radix_states[table_idx], tasks); + } + D_ASSERT(!tasks.empty()); + SetTasks(move(tasks)); + + //! Now that all tables are combined, it's time to do the distinct aggregations + auto new_event = make_shared(op, gstate, pipeline, client); + this->InsertEvent(move(new_event)); + } +}; + +SinkFinalizeType PhysicalUngroupedAggregate::FinalizeDistinct(Pipeline &pipeline, Event &event, ClientContext &context, + GlobalSinkState &gstate_p) const { + auto &gstate = (UngroupedAggregateGlobalState &)gstate_p; + D_ASSERT(gstate.distinct_data); + auto &distinct_aggregate_data = *gstate.distinct_data; + auto &payload_chunk = distinct_aggregate_data.payload_chunk; + + //! Copy of the payload chunk, used to store the data of the radix table for use with the expression executor + //! We can not directly use the payload chunk because the input and the output to the expression executor can not be + //! the same Vector + DataChunk expression_executor_input; + expression_executor_input.InitializeEmpty(payload_chunk.GetTypes()); + expression_executor_input.SetCardinality(0); + + bool any_partitioned = false; + for (idx_t table_idx = 0; table_idx < distinct_aggregate_data.radix_tables.size(); table_idx++) { + auto &radix_table_p = distinct_aggregate_data.radix_tables[table_idx]; + auto &radix_state = *distinct_aggregate_data.radix_states[table_idx]; + bool partitioned = radix_table_p->Finalize(context, radix_state); + if (partitioned) { + any_partitioned = true; + } + } + if (any_partitioned) { + auto new_event = make_shared(*this, gstate, &pipeline, context); + event.InsertEvent(move(new_event)); + } else { + //! Hashtables aren't partitioned, they dont need to be joined first + //! So we can compute the aggregate already + auto new_event = make_shared(*this, gstate, &pipeline, context); + event.InsertEvent(move(new_event)); + } + return SinkFinalizeType::READY; +} + +SinkFinalizeType PhysicalUngroupedAggregate::Finalize(Pipeline &pipeline, Event &event, ClientContext &context, + GlobalSinkState &gstate_p) const { + auto &gstate = (UngroupedAggregateGlobalState &)gstate_p; + + if (gstate.distinct_data) { + return FinalizeDistinct(pipeline, event, context, gstate_p); + } + + D_ASSERT(!gstate.finished); + gstate.finished = true; + return SinkFinalizeType::READY; +} + +//===--------------------------------------------------------------------===// +// Source +//===--------------------------------------------------------------------===// +class UngroupedAggregateState : public GlobalSourceState { +public: + UngroupedAggregateState() : finished(false) { + } + + bool finished; +}; + +unique_ptr PhysicalUngroupedAggregate::GetGlobalSourceState(ClientContext &context) const { + return make_unique(); +} + +void VerifyNullHandling(DataChunk &chunk, AggregateState &state, const vector> &aggregates) { +#ifdef DEBUG + for (idx_t aggr_idx = 0; aggr_idx < aggregates.size(); aggr_idx++) { + auto &aggr = (BoundAggregateExpression &)*aggregates[aggr_idx]; + if (state.counts[aggr_idx] == 0 && aggr.function.null_handling == FunctionNullHandling::DEFAULT_NULL_HANDLING) { + // Default is when 0 values go in, NULL comes out + UnifiedVectorFormat vdata; + chunk.data[aggr_idx].ToUnifiedFormat(1, vdata); + D_ASSERT(!vdata.validity.RowIsValid(vdata.sel->get_index(0))); + } + } +#endif +} + +void PhysicalUngroupedAggregate::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate_p, + LocalSourceState &lstate) const { + auto &gstate = (UngroupedAggregateGlobalState &)*sink_state; + auto &state = (UngroupedAggregateState &)gstate_p; + D_ASSERT(gstate.finished); + if (state.finished) { + return; + } + + // initialize the result chunk with the aggregate values + chunk.SetCardinality(1); + for (idx_t aggr_idx = 0; aggr_idx < aggregates.size(); aggr_idx++) { + auto &aggregate = (BoundAggregateExpression &)*aggregates[aggr_idx]; + + Vector state_vector(Value::POINTER((uintptr_t)gstate.state.aggregates[aggr_idx].get())); + AggregateInputData aggr_input_data(aggregate.bind_info.get(), Allocator::DefaultAllocator()); + aggregate.function.finalize(state_vector, aggr_input_data, chunk.data[aggr_idx], 1, 0); + } + VerifyNullHandling(chunk, gstate.state, aggregates); + state.finished = true; +} + +string PhysicalUngroupedAggregate::ParamsToString() const { + string result; + for (idx_t i = 0; i < aggregates.size(); i++) { + auto &aggregate = (BoundAggregateExpression &)*aggregates[i]; + if (i > 0) { + result += "\n"; + } + result += aggregates[i]->GetName(); + if (aggregate.filter) { + result += " Filter: " + aggregate.filter->GetName(); + } + } + return result; +} + } // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -62976,11 +69566,17 @@ class PhysicalWindow : public PhysicalOperator { return true; } + bool IsOrderPreserving() const override { + return true; + } + public: // Sink interface SinkResultType Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, DataChunk &input) const override; void Combine(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate) const override; + SinkFinalizeType Finalize(Pipeline &pipeline, Event &event, ClientContext &context, + GlobalSinkState &gstate) const override; unique_ptr GetLocalSinkState(ExecutionContext &context) const override; unique_ptr GetGlobalSinkState(ClientContext &context) const override; @@ -63009,6 +69605,8 @@ class PhysicalWindow : public PhysicalOperator { + + //===----------------------------------------------------------------------===// // DuckDB // @@ -63103,6 +69701,8 @@ class WindowSegmentTree { + + #include #include #include @@ -63111,198 +69711,578 @@ namespace duckdb { using counts_t = std::vector; +class WindowGlobalHashGroup { +public: + using GlobalSortStatePtr = unique_ptr; + using LocalSortStatePtr = unique_ptr; + using Orders = vector; + using Types = vector; + + WindowGlobalHashGroup(BufferManager &buffer_manager, const Orders &partitions, const Orders &orders, + const Types &payload_types, idx_t max_mem, bool external) + : memory_per_thread(max_mem), count(0), partition_layout(partitions) { + + RowLayout payload_layout; + payload_layout.Initialize(payload_types); + global_sort = make_unique(buffer_manager, orders, payload_layout); + global_sort->external = external; + } + + void Combine(LocalSortState &local_sort) { + global_sort->AddLocalState(local_sort); + } + + void PrepareMergePhase() { + global_sort->PrepareMergePhase(); + } + + void ComputeMasks(ValidityMask &partition_mask, ValidityMask &order_mask); + + const idx_t memory_per_thread; + GlobalSortStatePtr global_sort; + atomic count; + + // Mask computation + SortLayout partition_layout; +}; + +void WindowGlobalHashGroup::ComputeMasks(ValidityMask &partition_mask, ValidityMask &order_mask) { + D_ASSERT(count > 0); + + // Set up a comparator for the partition subset + const auto partition_size = partition_layout.comparison_size; + + SBIterator prev(*global_sort, ExpressionType::COMPARE_LESSTHAN); + SBIterator curr(*global_sort, ExpressionType::COMPARE_LESSTHAN); + + partition_mask.SetValidUnsafe(0); + order_mask.SetValidUnsafe(0); + for (++curr; curr.GetIndex() < count; ++curr) { + // Compare the partition subset first because if that differs, then so does the full ordering + int part_cmp = 0; + if (partition_layout.all_constant) { + part_cmp = FastMemcmp(prev.entry_ptr, curr.entry_ptr, partition_size); + } else { + part_cmp = Comparators::CompareTuple(prev.scan, curr.scan, prev.entry_ptr, curr.entry_ptr, partition_layout, + prev.external); + } + + if (part_cmp) { + partition_mask.SetValidUnsafe(curr.GetIndex()); + order_mask.SetValidUnsafe(curr.GetIndex()); + } else if (prev.Compare(curr)) { + order_mask.SetValidUnsafe(curr.GetIndex()); + } + ++prev; + } +} + // Global sink state -class WindowGlobalState : public GlobalSinkState { +class WindowGlobalSinkState : public GlobalSinkState { public: - WindowGlobalState(const PhysicalWindow &op_p, ClientContext &context) - : op(op_p), buffer_manager(BufferManager::GetBufferManager(context)), - mode(DBConfig::GetConfig(context).window_mode) { + using HashGroupPtr = unique_ptr; + using Orders = vector; + using Types = vector; + + WindowGlobalSinkState(const PhysicalWindow &op_p, ClientContext &context) + : op(op_p), buffer_manager(BufferManager::GetBufferManager(context)), allocator(Allocator::Get(context)), + partition_info((idx_t)TaskScheduler::GetScheduler(context).NumberOfThreads()), next_sort(0), + memory_per_thread(0), count(0), mode(DBConfig::GetConfig(context).options.window_mode) { + + D_ASSERT(op.select_list[0]->GetExpressionClass() == ExpressionClass::BOUND_WINDOW); + auto wexpr = reinterpret_cast(op.select_list[0].get()); + + // we sort by both 1) partition by expression list and 2) order by expressions + payload_types = op.children[0]->types; + + partition_cols = wexpr->partitions.size(); + for (idx_t prt_idx = 0; prt_idx < partition_cols; prt_idx++) { + auto &pexpr = wexpr->partitions[prt_idx]; + + if (wexpr->partitions_stats.empty() || !wexpr->partitions_stats[prt_idx]) { + orders.emplace_back(OrderType::ASCENDING, OrderByNullType::NULLS_FIRST, pexpr->Copy(), nullptr); + } else { + orders.emplace_back(OrderType::ASCENDING, OrderByNullType::NULLS_FIRST, pexpr->Copy(), + wexpr->partitions_stats[prt_idx]->Copy()); + } + partitions.emplace_back(orders.back().Copy()); + } + + for (const auto &order : wexpr->orders) { + orders.emplace_back(order.Copy()); + } + + memory_per_thread = op.GetMaxThreadMemory(context); + external = ClientConfig::GetConfig(context).force_external; + } + + WindowGlobalHashGroup *GetUngrouped() { + lock_guard guard(lock); + + if (!ungrouped) { + ungrouped = make_unique(buffer_manager, partitions, orders, payload_types, + memory_per_thread, external); + } + + return ungrouped.get(); + } + + //! Switch to hash grouping + size_t Group() { + lock_guard guard(lock); + if (hash_groups.size() < partition_info.n_partitions) { + hash_groups.resize(partition_info.n_partitions); + } + + return hash_groups.size(); } + + idx_t GroupCount() const { + return std::accumulate( + hash_groups.begin(), hash_groups.end(), 0, + [&](const idx_t &n, const HashGroupPtr &group) { return n + (group ? idx_t(group->count) : 0); }); + } + + WindowGlobalHashGroup *GetHashGroup(idx_t group) { + lock_guard guard(lock); + D_ASSERT(group < hash_groups.size()); + auto &hash_group = hash_groups[group]; + if (!hash_group) { + const auto maxmem = memory_per_thread / partition_info.n_partitions; + hash_group = + make_unique(buffer_manager, partitions, orders, payload_types, maxmem, external); + } + + return hash_group.get(); + } + + void Finalize(); + + size_t GetNextSortGroup() { + for (auto group = next_sort++; group < hash_groups.size(); group = next_sort++) { + // Only non-empty groups exist. + if (hash_groups[group]) { + return group; + } + } + + return hash_groups.size(); + } + const PhysicalWindow &op; BufferManager &buffer_manager; + Allocator &allocator; + size_t partition_cols; + const RadixPartitionInfo partition_info; mutex lock; - ChunkCollection chunks; - ChunkCollection over_collection; - ChunkCollection hash_collection; - counts_t counts; + + // Sorting + Orders partitions; + Orders orders; + Types payload_types; + HashGroupPtr ungrouped; + vector hash_groups; + bool external; + atomic next_sort; + + // OVER() (no sorting) + unique_ptr rows; + unique_ptr strings; + + // Threading + idx_t memory_per_thread; + atomic count; WindowAggregationMode mode; }; +// Per-thread hash group +class WindowLocalHashGroup { +public: + using LocalSortStatePtr = unique_ptr; + using DataChunkPtr = unique_ptr; + + explicit WindowLocalHashGroup(WindowGlobalHashGroup &global_group_p) : global_group(global_group_p), count(0) { + } + + bool SinkChunk(DataChunk &sort_chunk, DataChunk &payload_chunk); + void Combine(); + + WindowGlobalHashGroup &global_group; + LocalSortStatePtr local_sort; + idx_t count; +}; + +bool WindowLocalHashGroup::SinkChunk(DataChunk &sort_buffer, DataChunk &input_chunk) { + D_ASSERT(sort_buffer.size() == input_chunk.size()); + count += input_chunk.size(); + auto &global_sort = *global_group.global_sort; + if (!local_sort) { + local_sort = make_unique(); + local_sort->Initialize(global_sort, global_sort.buffer_manager); + } + + local_sort->SinkChunk(sort_buffer, input_chunk); + + if (local_sort->SizeInBytes() >= global_group.memory_per_thread) { + local_sort->Sort(global_sort, true); + } + + return (local_sort->SizeInBytes() >= global_group.memory_per_thread); +} + +void WindowLocalHashGroup::Combine() { + if (local_sort) { + global_group.Combine(*local_sort); + global_group.count += count; + local_sort.reset(); + } +} + // Per-thread sink state -class WindowLocalState : public LocalSinkState { +class WindowLocalSinkState : public LocalSinkState { public: - explicit WindowLocalState(const PhysicalWindow &op_p, const unsigned partition_bits = 10) - : op(op_p), partition_count(size_t(1) << partition_bits) { + using LocalHashGroupPtr = unique_ptr; + + WindowLocalSinkState(Allocator &allocator, const PhysicalWindow &op_p) + : op(op_p), executor(allocator), count(0), hash_vector(LogicalTypeId::UBIGINT), sel(STANDARD_VECTOR_SIZE) { + + D_ASSERT(op.select_list[0]->GetExpressionClass() == ExpressionClass::BOUND_WINDOW); + auto wexpr = reinterpret_cast(op.select_list[0].get()); + partition_cols = wexpr->partitions.size(); + + // we sort by both 1) partition by expression list and 2) order by expressions + auto &payload_types = op.children[0]->types; + vector over_types; + for (idx_t prt_idx = 0; prt_idx < wexpr->partitions.size(); prt_idx++) { + auto &pexpr = wexpr->partitions[prt_idx]; + over_types.push_back(pexpr->return_type); + executor.AddExpression(*pexpr); + } + + for (const auto &order : wexpr->orders) { + auto &oexpr = order.expression; + over_types.push_back(oexpr->return_type); + executor.AddExpression(*oexpr); + } + + if (!over_types.empty()) { + over_chunk.Initialize(allocator, over_types); + over_subset.Initialize(allocator, over_types); + } + + payload_chunk.Initialize(allocator, payload_types); + payload_subset.Initialize(allocator, payload_types); + payload_layout.Initialize(payload_types); } + // Global state const PhysicalWindow &op; - ChunkCollection chunks; - ChunkCollection over_collection; - ChunkCollection hash_collection; - const size_t partition_count; + + // Input + ExpressionExecutor executor; + DataChunk over_chunk; + DataChunk payload_chunk; + idx_t count; + + // Grouping + idx_t partition_cols; counts_t counts; -}; + counts_t offsets; + Vector hash_vector; + SelectionVector sel; + DataChunk over_subset; + DataChunk payload_subset; + LocalHashGroupPtr ungrouped; + vector hash_groups; -// Per-thread read state -class WindowOperatorState : public LocalSourceState { -public: - WindowOperatorState(const PhysicalWindow &op, ExecutionContext &context) - : buffer_manager(BufferManager::GetBufferManager(context.client)) { - auto &gstate = (WindowGlobalState &)*op.sink_state; - // initialize thread-local operator state - partitions = gstate.counts.size(); - next_part = 0; - position = 0; + // OVER() (no sorting) + RowLayout payload_layout; + unique_ptr rows; + unique_ptr strings; + + //! Switch to grouping the data + void Group(WindowGlobalSinkState &gstate); + //! Compute the OVER values + void Over(DataChunk &input_chunk); + //! Hash the data and group it + void Hash(WindowGlobalSinkState &gstate, DataChunk &input_chunk); + //! Sink an input chunk + void Sink(DataChunk &input_chunk, WindowGlobalSinkState &gstate); + //! Merge the state into the global state. + void Combine(WindowGlobalSinkState &gstate); +}; + +void WindowLocalSinkState::Over(DataChunk &input_chunk) { + if (over_chunk.ColumnCount() > 0) { + over_chunk.Reset(); + executor.Execute(input_chunk, over_chunk); + over_chunk.Verify(); + } +} + +void WindowLocalSinkState::Hash(WindowGlobalSinkState &gstate, DataChunk &input_chunk) { + // There are three types of hash grouping: + // 1. No partitions (no sorting) + // 2. One group (sorting, but no hash grouping) + // 3. Multiple groups (sorting and hash grouping) + if (over_chunk.ColumnCount() == 0) { + return; } - //! The number of partitions to process (0 if there is no partitioning) - size_t partitions; - //! The output read position. - size_t next_part; - //! The generated input chunks - ChunkCollection chunks; - //! The generated output chunks - ChunkCollection window_results; - //! The read cursor - idx_t position; + const auto count = over_chunk.size(); + auto hashes = FlatVector::GetData(hash_vector); + if (hash_groups.empty()) { + // Ungrouped, so take them all + counts.resize(1, count); + } else { + // First pass: count bins sizes + counts.resize(0); + counts.resize(hash_groups.size(), 0); - BufferManager &buffer_manager; - unique_ptr global_sort_state; -}; + VectorOperations::Hash(over_chunk.data[0], hash_vector, count); + for (idx_t prt_idx = 1; prt_idx < partition_cols; ++prt_idx) { + VectorOperations::CombineHash(hash_vector, over_chunk.data[prt_idx], count); + } -// this implements a sorted window functions variant -PhysicalWindow::PhysicalWindow(vector types, vector> select_list, - idx_t estimated_cardinality, PhysicalOperatorType type) - : PhysicalOperator(type, move(types), estimated_cardinality), select_list(move(select_list)) { -} + const auto &partition_info = gstate.partition_info; + if (hash_vector.GetVectorType() == VectorType::CONSTANT_VECTOR) { + const auto group = partition_info.GetHashPartition(hashes[0]); + counts[group] = count; + for (idx_t i = 0; i < count; ++i) { + sel.set_index(i, i); + } + } else { + for (idx_t i = 0; i < count; ++i) { + const auto group = partition_info.GetHashPartition(hashes[i]); + ++counts[group]; + } -template -struct ChunkIterator { + // Second pass: Initialise offsets + offsets.resize(counts.size()); + size_t offset = 0; + for (size_t c = 0; c < counts.size(); ++c) { + offsets[c] = offset; + offset += counts[c]; + } - ChunkIterator(ChunkCollection &collection, const idx_t col_idx) - : collection(collection), col_idx(col_idx), chunk_begin(0), chunk_end(0), ch_idx(0), data(nullptr), - validity(nullptr) { - Update(0); + // Third pass: Build sequential selections + for (idx_t i = 0; i < count; ++i) { + const auto group = partition_info.GetHashPartition(hashes[i]); + auto &group_idx = offsets[group]; + sel.set_index(group_idx++, i); + } + } } - inline void Update(idx_t r) { - if (r >= chunk_end) { - ch_idx = collection.LocateChunk(r); - auto &ch = collection.GetChunk(ch_idx); - chunk_begin = ch_idx * STANDARD_VECTOR_SIZE; - chunk_end = chunk_begin + ch.size(); - auto &vector = ch.data[col_idx]; - data = FlatVector::GetData(vector); - validity = &FlatVector::Validity(vector); + idx_t group_offset = 0; + for (size_t group = 0; group < counts.size(); ++group) { + const auto group_size = counts[group]; + if (group_size) { + auto &local_group = hash_groups[group]; + if (!local_group) { + auto global_group = gstate.GetHashGroup(group); + local_group = make_unique(*global_group); + } + + if (counts.size() == 1) { + local_group->SinkChunk(over_chunk, input_chunk); + } else { + SelectionVector psel(sel.data() + group_offset); + over_subset.Slice(over_chunk, psel, group_size); + payload_subset.Slice(input_chunk, psel, group_size); + local_group->SinkChunk(over_subset, payload_subset); + group_offset += group_size; + } } } +} - inline bool IsValid(idx_t r) { - return validity->RowIsValid(r - chunk_begin); +void WindowLocalSinkState::Group(WindowGlobalSinkState &gstate) { + if (!gstate.partition_cols) { + return; } - inline INPUT_TYPE GetValue(idx_t r) { - return data[r - chunk_begin]; + if (!hash_groups.empty()) { + return; } -private: - ChunkCollection &collection; - idx_t col_idx; - idx_t chunk_begin; - idx_t chunk_end; - idx_t ch_idx; - const INPUT_TYPE *data; - ValidityMask *validity; -}; - -template -static void MaskTypedColumn(ValidityMask &mask, ChunkCollection &over_collection, const idx_t c) { - ChunkIterator ci(over_collection, c); - - // Record the first value - idx_t r = 0; - auto prev_valid = ci.IsValid(r); - auto prev = ci.GetValue(r); - - // Process complete blocks - const auto count = over_collection.Count(); - const auto entry_count = mask.EntryCount(count); - for (idx_t entry_idx = 0; entry_idx < entry_count; ++entry_idx) { - auto validity_entry = mask.GetValidityEntry(entry_idx); - - // Skip the block if it is all boundaries. - idx_t next = MinValue(r + ValidityMask::BITS_PER_VALUE, count); - if (ValidityMask::AllValid(validity_entry)) { - r = next; - continue; + hash_groups.resize(gstate.Group()); + + if (!ungrouped) { + return; + } + + auto &payload_data = *ungrouped->local_sort->payload_data; + auto rows = payload_data.CloneEmpty(payload_data.keep_pinned); + + auto &payload_heap = *ungrouped->local_sort->payload_heap; + auto heap = payload_heap.CloneEmpty(payload_heap.keep_pinned); + + RowDataCollectionScanner::AlignHeapBlocks(*rows, *heap, payload_data, payload_heap, payload_layout); + RowDataCollectionScanner scanner(*rows, *heap, payload_layout, true); + while (scanner.Remaining()) { + payload_chunk.Reset(); + scanner.Scan(payload_chunk); + + Over(payload_chunk); + Hash(gstate, payload_chunk); + } + + ungrouped.reset(); +} + +void WindowLocalSinkState::Sink(DataChunk &input_chunk, WindowGlobalSinkState &gstate) { + gstate.count += input_chunk.size(); + count += input_chunk.size(); + + Over(input_chunk); + + // OVER() + if (over_chunk.ColumnCount() == 0) { + // No sorts, so build paged row chunks + if (!rows) { + const auto entry_size = payload_layout.GetRowWidth(); + const auto capacity = MaxValue(STANDARD_VECTOR_SIZE, (Storage::BLOCK_SIZE / entry_size) + 1); + rows = make_unique(gstate.buffer_manager, capacity, entry_size); + strings = make_unique(gstate.buffer_manager, (idx_t)Storage::BLOCK_SIZE, 1, true); + } + const auto row_count = input_chunk.size(); + const auto row_sel = FlatVector::IncrementalSelectionVector(); + Vector addresses(LogicalType::POINTER); + auto key_locations = FlatVector::GetData(addresses); + const auto prev_rows_blocks = rows->blocks.size(); + auto handles = rows->Build(row_count, key_locations, nullptr, row_sel); + auto input_data = input_chunk.ToUnifiedFormat(); + RowOperations::Scatter(input_chunk, input_data.get(), payload_layout, addresses, *strings, *row_sel, row_count); + // Mark that row blocks contain pointers (heap blocks are pinned) + if (!payload_layout.AllConstant()) { + D_ASSERT(strings->keep_pinned); + for (size_t i = prev_rows_blocks; i < rows->blocks.size(); ++i) { + rows->blocks[i]->block->SetSwizzling("WindowLocalSinkState::Sink"); + } } + return; + } - // Scan the rows in the complete block - idx_t start = r; - for (; r < next; ++r) { - // Update the chunk for this row - ci.Update(r); + // Ungrouped + if (hash_groups.empty()) { + auto global_ungrouped = gstate.GetUngrouped(); + if (!ungrouped) { + ungrouped = make_unique(*global_ungrouped); + } - auto curr_valid = ci.IsValid(r); - auto curr = ci.GetValue(r); - if (!ValidityMask::RowIsValid(validity_entry, r - start)) { - if (curr_valid != prev_valid || (curr_valid && !Equals::Operation(curr, prev))) { - mask.SetValidUnsafe(r); - } + // If we pass our thread memory budget, then switch to hash grouping. + if (ungrouped->SinkChunk(over_chunk, input_chunk) || gstate.count > 100000) { + Group(gstate); + } + return; + } + + // Grouped, so hash + Hash(gstate, input_chunk); +} + +void WindowLocalSinkState::Combine(WindowGlobalSinkState &gstate) { + // OVER() + if (over_chunk.ColumnCount() == 0) { + // Only one partition again, so need a global lock. + lock_guard glock(gstate.lock); + if (gstate.rows) { + if (rows) { + gstate.rows->Merge(*rows); + gstate.strings->Merge(*strings); + rows.reset(); + strings.reset(); } - prev_valid = curr_valid; - prev = curr; + } else { + gstate.rows = move(rows); + gstate.strings = move(strings); + } + return; + } + + // Ungrouped data + idx_t check = 0; + if (ungrouped) { + check += ungrouped->count; + ungrouped->Combine(); + ungrouped.reset(); + } + + // Grouped data + for (auto &local_group : hash_groups) { + if (local_group) { + check += local_group->count; + local_group->Combine(); + local_group.reset(); } } + + D_ASSERT(check == count); } -static void MaskColumn(ValidityMask &mask, ChunkCollection &over_collection, const idx_t c) { - auto &vector = over_collection.GetChunk(0).data[c]; - switch (vector.GetType().InternalType()) { - case PhysicalType::BOOL: - case PhysicalType::INT8: - MaskTypedColumn(mask, over_collection, c); - break; - case PhysicalType::INT16: - MaskTypedColumn(mask, over_collection, c); - break; - case PhysicalType::INT32: - MaskTypedColumn(mask, over_collection, c); - break; - case PhysicalType::INT64: - MaskTypedColumn(mask, over_collection, c); - break; - case PhysicalType::UINT8: - MaskTypedColumn(mask, over_collection, c); - break; - case PhysicalType::UINT16: - MaskTypedColumn(mask, over_collection, c); - break; - case PhysicalType::UINT32: - MaskTypedColumn(mask, over_collection, c); - break; - case PhysicalType::UINT64: - MaskTypedColumn(mask, over_collection, c); - break; - case PhysicalType::INT128: - MaskTypedColumn(mask, over_collection, c); - break; - case PhysicalType::FLOAT: - MaskTypedColumn(mask, over_collection, c); - break; - case PhysicalType::DOUBLE: - MaskTypedColumn(mask, over_collection, c); - break; - case PhysicalType::VARCHAR: - MaskTypedColumn(mask, over_collection, c); - break; - case PhysicalType::INTERVAL: - MaskTypedColumn(mask, over_collection, c); - break; - default: - throw NotImplementedException("Type for comparison"); - break; +void WindowGlobalSinkState::Finalize() { + if (!ungrouped) { + return; + } + + if (hash_groups.empty()) { + hash_groups.emplace_back(move(ungrouped)); + return; } + + // If we have grouped data, merge the remaining ungrouped data into it. + // This can happen if only SOME of the threads ended up regrouping. + // The simplest thing to do is to fake a local thread state, + // push the ungrouped data into it and then use that state to partition the data. + // This is probably OK because this situation will only happen + // with relatively small amounts of data. + + // Sort the data so we can scan it + auto &global_sort = *ungrouped->global_sort; + if (global_sort.sorted_blocks.empty()) { + return; + } + + global_sort.PrepareMergePhase(); + while (global_sort.sorted_blocks.size() > 1) { + global_sort.InitializeMergeRound(); + MergeSorter merge_sorter(global_sort, global_sort.buffer_manager); + merge_sorter.PerformInMergeRound(); + global_sort.CompleteMergeRound(true); + } + + // Sink it into a temporary local sink state + auto lstate = make_unique(allocator, op); + + // Match the grouping. + lstate->Group(*this); + + // Write into the state chunks directly to hash them + auto &payload_chunk = lstate->payload_chunk; + + // Now scan the sorted data + PayloadScanner scanner(global_sort); + while (scanner.Remaining()) { + lstate->payload_chunk.Reset(); + scanner.Scan(lstate->payload_chunk); + if (payload_chunk.size() == 0) { + break; + } + lstate->count += payload_chunk.size(); + + lstate->Over(payload_chunk); + lstate->Hash(*this, payload_chunk); + } + + // Merge the grouped data in. + lstate->Combine(*this); +} + +// this implements a sorted window functions variant +PhysicalWindow::PhysicalWindow(vector types, vector> select_list, + idx_t estimated_cardinality, PhysicalOperatorType type) + : PhysicalOperator(type, move(types), estimated_cardinality), select_list(move(select_list)) { } static idx_t FindNextStart(const ValidityMask &mask, idx_t l, const idx_t r, idx_t &n) { @@ -63370,228 +70350,111 @@ static idx_t FindPrevStart(const ValidityMask &mask, const idx_t l, idx_t r, idx return l; } -static void MaterializeExpressions(Expression **exprs, idx_t expr_count, ChunkCollection &input, - ChunkCollection &output, bool scalar = false) { +static void PrepareInputExpressions(Expression **exprs, idx_t expr_count, ExpressionExecutor &executor, + DataChunk &chunk) { if (expr_count == 0) { return; } vector types; - ExpressionExecutor executor; for (idx_t expr_idx = 0; expr_idx < expr_count; ++expr_idx) { types.push_back(exprs[expr_idx]->return_type); executor.AddExpression(*exprs[expr_idx]); } - for (idx_t i = 0; i < input.ChunkCount(); i++) { - DataChunk chunk; - chunk.Initialize(types); - - executor.Execute(input.GetChunk(i), chunk); - - chunk.Verify(); - output.Append(chunk); - - if (scalar) { - break; - } + if (!types.empty()) { + chunk.Initialize(executor.allocator, types); } } -static void MaterializeExpression(Expression *expr, ChunkCollection &input, ChunkCollection &output, - bool scalar = false) { - MaterializeExpressions(&expr, 1, input, output, scalar); +static void PrepareInputExpression(Expression *expr, ExpressionExecutor &executor, DataChunk &chunk) { + PrepareInputExpressions(&expr, 1, executor, chunk); } -static void SortCollectionForPartition(WindowOperatorState &state, BoundWindowExpression *wexpr, ChunkCollection &input, - ChunkCollection &over, ChunkCollection *hashes, const hash_t hash_bin, - const hash_t hash_mask) { - if (input.Count() == 0) { - return; - } - - vector orders; - // we sort by both 1) partition by expression list and 2) order by expressions - for (idx_t prt_idx = 0; prt_idx < wexpr->partitions.size(); prt_idx++) { - if (wexpr->partitions_stats.empty() || !wexpr->partitions_stats[prt_idx]) { - orders.emplace_back(OrderType::ASCENDING, OrderByNullType::NULLS_FIRST, wexpr->partitions[prt_idx]->Copy(), - nullptr); - } else { - orders.emplace_back(OrderType::ASCENDING, OrderByNullType::NULLS_FIRST, wexpr->partitions[prt_idx]->Copy(), - wexpr->partitions_stats[prt_idx]->Copy()); +struct WindowInputExpression { + WindowInputExpression(Expression *expr_p, Allocator &allocator) + : expr(expr_p), ptype(PhysicalType::INVALID), scalar(true), executor(allocator) { + if (expr) { + PrepareInputExpression(expr, executor, chunk); + ptype = expr->return_type.InternalType(); + scalar = expr->IsScalar(); } } - for (const auto &order : wexpr->orders) { - orders.push_back(order.Copy()); - } - - // fuse input and sort collection into one - // (sorting columns are not decoded, and we need them later) - auto payload_types = input.Types(); - payload_types.insert(payload_types.end(), over.Types().begin(), over.Types().end()); - DataChunk payload_chunk; - payload_chunk.InitializeEmpty(payload_types); - - // initialise partitioning memory - // to minimise copying, we fill up a chunk and then sink it. - SelectionVector sel; - DataChunk over_partition; - DataChunk payload_partition; - if (hashes) { - sel.Initialize(STANDARD_VECTOR_SIZE); - over_partition.Initialize(over.Types()); - payload_partition.Initialize(payload_types); - } - - // initialize row layout for sorting - RowLayout payload_layout; - payload_layout.Initialize(payload_types); - - // initialize sorting states - state.global_sort_state = make_unique(state.buffer_manager, orders, payload_layout); - auto &global_sort_state = *state.global_sort_state; - LocalSortState local_sort_state; - local_sort_state.Initialize(global_sort_state, state.buffer_manager); - // sink collection chunks into row format - const idx_t chunk_count = over.ChunkCount(); - for (idx_t i = 0; i < chunk_count; i++) { - auto &input_chunk = *input.Chunks()[i]; - for (idx_t col_idx = 0; col_idx < input_chunk.ColumnCount(); ++col_idx) { - payload_chunk.data[col_idx].Reference(input_chunk.data[col_idx]); - } - auto &over_chunk = *over.Chunks()[i]; - for (idx_t col_idx = 0; col_idx < over_chunk.ColumnCount(); ++col_idx) { - payload_chunk.data[input_chunk.ColumnCount() + col_idx].Reference(over_chunk.data[col_idx]); - } - payload_chunk.SetCardinality(input_chunk); - - // Extract the hash partition, if any - if (hashes) { - auto &hash_chunk = *hashes->Chunks()[i]; - auto hash_size = hash_chunk.size(); - auto hash_data = FlatVector::GetData(hash_chunk.data[0]); - idx_t bin_size = 0; - for (idx_t i = 0; i < hash_size; ++i) { - if ((hash_data[i] & hash_mask) == hash_bin) { - sel.set_index(bin_size++, i); - } - } - - // Flush the partition chunks if we would overflow - if (over_partition.size() + bin_size > STANDARD_VECTOR_SIZE) { - local_sort_state.SinkChunk(over_partition, payload_partition); - over_partition.Reset(); - payload_partition.Reset(); - } - - // Copy the data for each collection. - if (bin_size) { - over_partition.Append(over_chunk, false, &sel, bin_size); - payload_partition.Append(payload_chunk, false, &sel, bin_size); - } - } else { - local_sort_state.SinkChunk(over_chunk, payload_chunk); + void Execute(DataChunk &input_chunk) { + if (expr) { + chunk.Reset(); + executor.Execute(input_chunk, chunk); + chunk.Verify(); } } - // Flush any ragged partition chunks - if (over_partition.size() > 0) { - local_sort_state.SinkChunk(over_partition, payload_partition); - over_partition.Reset(); - payload_partition.Reset(); + template + inline T GetCell(idx_t i) const { + D_ASSERT(!chunk.data.empty()); + const auto data = FlatVector::GetData(chunk.data[0]); + return data[scalar ? 0 : i]; } - // If there are no hashes, release the input to save memory. - if (!hashes) { - over.Reset(); - input.Reset(); + inline bool CellIsNull(idx_t i) const { + D_ASSERT(!chunk.data.empty()); + return FlatVector::IsNull(chunk.data[0], scalar ? 0 : i); } - // add local state to global state, which sorts the data - global_sort_state.AddLocalState(local_sort_state); - // Prepare for merge phase (in this case we never have a merge phase, but this call is still needed) - global_sort_state.PrepareMergePhase(); -} - -static void ScanSortedPartition(WindowOperatorState &state, ChunkCollection &input, - const vector &input_types, ChunkCollection &over, - const vector &over_types) { - auto &global_sort_state = *state.global_sort_state; - - auto payload_types = input_types; - payload_types.insert(payload_types.end(), over_types.begin(), over_types.end()); - - // scan the sorted row data - PayloadScanner scanner(*global_sort_state.sorted_blocks[0]->payload_data, global_sort_state); - for (;;) { - DataChunk payload_chunk; - payload_chunk.Initialize(payload_types); - payload_chunk.SetCardinality(0); - scanner.Scan(payload_chunk); - if (payload_chunk.size() == 0) { - break; - } - - // split into two - DataChunk over_chunk; - payload_chunk.Split(over_chunk, input_types.size()); - - // append back to collection - input.Append(payload_chunk); - over.Append(over_chunk); + inline void CopyCell(Vector &target, idx_t target_offset) const { + D_ASSERT(!chunk.data.empty()); + auto &source = chunk.data[0]; + auto source_offset = scalar ? 0 : target_offset; + VectorOperations::Copy(source, target, source_offset + 1, source_offset, target_offset); } -} -static void HashChunk(counts_t &counts, DataChunk &hash_chunk, DataChunk &sort_chunk, const idx_t partition_cols) { - const vector hash_types(1, LogicalTypeId::HASH); - hash_chunk.Initialize(hash_types); - hash_chunk.SetCardinality(sort_chunk); - auto &hash_vector = hash_chunk.data[0]; + Expression *expr; + PhysicalType ptype; + bool scalar; + ExpressionExecutor executor; + DataChunk chunk; +}; - const auto count = sort_chunk.size(); - VectorOperations::Hash(sort_chunk.data[0], hash_vector, count); - for (idx_t prt_idx = 1; prt_idx < partition_cols; ++prt_idx) { - VectorOperations::CombineHash(hash_vector, sort_chunk.data[prt_idx], count); +struct WindowInputColumn { + WindowInputColumn(Expression *expr_p, Allocator &allocator, idx_t capacity_p) + : input_expr(expr_p, allocator), count(0), capacity(capacity_p) { + if (input_expr.expr) { + target = make_unique(input_expr.chunk.data[0].GetType(), capacity); + } } - const auto partition_mask = hash_t(counts.size() - 1); - auto hashes = FlatVector::GetData(hash_vector); - if (hash_vector.GetVectorType() == VectorType::CONSTANT_VECTOR) { - const auto bin = (hashes[0] & partition_mask); - counts[bin] += count; - } else { - for (idx_t i = 0; i < count; ++i) { - const auto bin = (hashes[i] & partition_mask); - ++counts[bin]; + void Append(DataChunk &input_chunk) { + if (input_expr.expr && (!input_expr.scalar || !count)) { + input_expr.Execute(input_chunk); + auto &source = input_expr.chunk.data[0]; + const auto source_count = input_expr.chunk.size(); + D_ASSERT(count + source_count <= capacity); + VectorOperations::Copy(source, *target, source_count, 0, count); + count += source_count; } } -} - -static void MaterializeOverForWindow(BoundWindowExpression *wexpr, DataChunk &input_chunk, DataChunk &over_chunk) { - vector over_types; - ExpressionExecutor executor; - // we sort by both 1) partition by expression list and 2) order by expressions - for (idx_t prt_idx = 0; prt_idx < wexpr->partitions.size(); prt_idx++) { - auto &pexpr = wexpr->partitions[prt_idx]; - over_types.push_back(pexpr->return_type); - executor.AddExpression(*pexpr); + inline bool CellIsNull(idx_t i) { + D_ASSERT(target); + D_ASSERT(i < count); + return FlatVector::IsNull(*target, input_expr.scalar ? 0 : i); } - for (idx_t ord_idx = 0; ord_idx < wexpr->orders.size(); ord_idx++) { - auto &oexpr = wexpr->orders[ord_idx].expression; - over_types.push_back(oexpr->return_type); - executor.AddExpression(*oexpr); + template + inline T GetCell(idx_t i) { + D_ASSERT(target); + D_ASSERT(i < count); + const auto data = FlatVector::GetData(*target); + return data[input_expr.scalar ? 0 : i]; } - D_ASSERT(!over_types.empty()); + WindowInputExpression input_expr; - over_chunk.Initialize(over_types); - executor.Execute(input_chunk, over_chunk); - - over_chunk.Verify(); -} +private: + unique_ptr target; + idx_t count; + idx_t capacity; +}; static inline bool BoundaryNeedsPeer(const WindowBoundary &boundary) { switch (boundary) { @@ -63609,11 +70472,10 @@ struct WindowBoundariesState { return expr ? expr->IsScalar() : true; } - explicit WindowBoundariesState(BoundWindowExpression *wexpr) - : type(wexpr->type), start_boundary(wexpr->start), end_boundary(wexpr->end), + WindowBoundariesState(BoundWindowExpression *wexpr, const idx_t input_size) + : type(wexpr->type), input_size(input_size), start_boundary(wexpr->start), end_boundary(wexpr->end), partition_count(wexpr->partitions.size()), order_count(wexpr->orders.size()), range_sense(wexpr->orders.empty() ? OrderType::INVALID : wexpr->orders[0].type), - scalar_start(IsScalar(wexpr->start_expr)), scalar_end(IsScalar(wexpr->end_expr)), has_preceding_range(wexpr->start == WindowBoundary::EXPR_PRECEDING_RANGE || wexpr->end == WindowBoundary::EXPR_PRECEDING_RANGE), has_following_range(wexpr->start == WindowBoundary::EXPR_FOLLOWING_RANGE || @@ -63621,15 +70483,18 @@ struct WindowBoundariesState { needs_peer(BoundaryNeedsPeer(wexpr->end) || wexpr->type == ExpressionType::WINDOW_CUME_DIST) { } + void Update(const idx_t row_idx, WindowInputColumn &range_collection, const idx_t source_offset, + WindowInputExpression &boundary_start, WindowInputExpression &boundary_end, + const ValidityMask &partition_mask, const ValidityMask &order_mask); + // Cached lookups const ExpressionType type; + const idx_t input_size; const WindowBoundary start_boundary; const WindowBoundary end_boundary; - const idx_t partition_count; - const idx_t order_count; + const size_t partition_count; + const size_t order_count; const OrderType range_sense; - const bool scalar_start; - const bool scalar_end; const bool has_preceding_range; const bool has_following_range; const bool needs_peer; @@ -63670,20 +70535,19 @@ static bool CellIsNull(ChunkCollection &collection, idx_t column, idx_t index) { } template -struct ChunkCollectionIterator { - using iterator = ChunkCollectionIterator; +struct WindowColumnIterator { + using iterator = WindowColumnIterator; using iterator_category = std::forward_iterator_tag; using difference_type = std::ptrdiff_t; using value_type = T; using reference = T; using pointer = idx_t; - ChunkCollectionIterator(ChunkCollection &coll_p, idx_t col_no_p, pointer pos_p = 0) - : coll(&coll_p), col_no(col_no_p), pos(pos_p) { + explicit WindowColumnIterator(WindowInputColumn &coll_p, pointer pos_p = 0) : coll(&coll_p), pos(pos_p) { } inline reference operator*() const { - return GetCell(*coll, col_no, pos); + return coll->GetCell(pos); } inline explicit operator pointer() const { return pos; @@ -63707,8 +70571,7 @@ struct ChunkCollectionIterator { } private: - ChunkCollection *coll; - idx_t col_no; + WindowInputColumn *coll; pointer pos; }; @@ -63720,14 +70583,14 @@ struct OperationCompare : public std::function { }; template -static idx_t FindTypedRangeBound(ChunkCollection &over, const idx_t order_col, const idx_t order_begin, - const idx_t order_end, ChunkCollection &boundary, const idx_t boundary_row) { - D_ASSERT(!CellIsNull(boundary, 0, boundary_row)); - const auto val = GetCell(boundary, 0, boundary_row); +static idx_t FindTypedRangeBound(WindowInputColumn &over, const idx_t order_begin, const idx_t order_end, + WindowInputExpression &boundary, const idx_t boundary_row) { + D_ASSERT(!boundary.CellIsNull(boundary_row)); + const auto val = boundary.GetCell(boundary_row); OperationCompare comp; - ChunkCollectionIterator begin(over, order_col, order_begin); - ChunkCollectionIterator end(over, order_col, order_end); + WindowColumnIterator begin(over, order_begin); + WindowColumnIterator end(over, order_end); if (FROM) { return idx_t(std::lower_bound(begin, end, val, comp)); } else { @@ -63736,65 +70599,59 @@ static idx_t FindTypedRangeBound(ChunkCollection &over, const idx_t order_col, c } template -static idx_t FindRangeBound(ChunkCollection &over, const idx_t order_col, const idx_t order_begin, - const idx_t order_end, ChunkCollection &boundary, const idx_t expr_idx) { - const auto &over_types = over.Types(); - D_ASSERT(over_types.size() > order_col); - D_ASSERT(boundary.Types().size() == 1); - D_ASSERT(boundary.Types()[0] == over_types[order_col]); - - switch (over_types[order_col].InternalType()) { +static idx_t FindRangeBound(WindowInputColumn &over, const idx_t order_begin, const idx_t order_end, + WindowInputExpression &boundary, const idx_t expr_idx) { + D_ASSERT(boundary.chunk.ColumnCount() == 1); + D_ASSERT(boundary.chunk.data[0].GetType().InternalType() == over.input_expr.ptype); + + switch (over.input_expr.ptype) { case PhysicalType::INT8: - return FindTypedRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindTypedRangeBound(over, order_begin, order_end, boundary, expr_idx); case PhysicalType::INT16: - return FindTypedRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindTypedRangeBound(over, order_begin, order_end, boundary, expr_idx); case PhysicalType::INT32: - return FindTypedRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindTypedRangeBound(over, order_begin, order_end, boundary, expr_idx); case PhysicalType::INT64: - return FindTypedRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindTypedRangeBound(over, order_begin, order_end, boundary, expr_idx); case PhysicalType::UINT8: - return FindTypedRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindTypedRangeBound(over, order_begin, order_end, boundary, expr_idx); case PhysicalType::UINT16: - return FindTypedRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindTypedRangeBound(over, order_begin, order_end, boundary, expr_idx); case PhysicalType::UINT32: - return FindTypedRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindTypedRangeBound(over, order_begin, order_end, boundary, expr_idx); case PhysicalType::UINT64: - return FindTypedRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindTypedRangeBound(over, order_begin, order_end, boundary, expr_idx); case PhysicalType::INT128: - return FindTypedRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindTypedRangeBound(over, order_begin, order_end, boundary, expr_idx); case PhysicalType::FLOAT: - return FindTypedRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindTypedRangeBound(over, order_begin, order_end, boundary, expr_idx); case PhysicalType::DOUBLE: - return FindTypedRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindTypedRangeBound(over, order_begin, order_end, boundary, expr_idx); case PhysicalType::INTERVAL: - return FindTypedRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindTypedRangeBound(over, order_begin, order_end, boundary, expr_idx); default: throw InternalException("Unsupported column type for RANGE"); } } template -static idx_t FindOrderedRangeBound(ChunkCollection &over, const idx_t order_col, const OrderType range_sense, - const idx_t order_begin, const idx_t order_end, ChunkCollection &boundary, - const idx_t expr_idx) { +static idx_t FindOrderedRangeBound(WindowInputColumn &over, const OrderType range_sense, const idx_t order_begin, + const idx_t order_end, WindowInputExpression &boundary, const idx_t expr_idx) { switch (range_sense) { case OrderType::ASCENDING: - return FindRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindRangeBound(over, order_begin, order_end, boundary, expr_idx); case OrderType::DESCENDING: - return FindRangeBound(over, order_col, order_begin, order_end, boundary, expr_idx); + return FindRangeBound(over, order_begin, order_end, boundary, expr_idx); default: throw InternalException("Unsupported ORDER BY sense for RANGE"); } } -static void UpdateWindowBoundaries(WindowBoundariesState &bounds, const idx_t input_size, const idx_t row_idx, - ChunkCollection &over_collection, ChunkCollection &boundary_start_collection, - ChunkCollection &boundary_end_collection, const ValidityMask &partition_mask, - const ValidityMask &order_mask) { - - // RANGE sorting parameters - const auto order_col = bounds.partition_count; +void WindowBoundariesState::Update(const idx_t row_idx, WindowInputColumn &range_collection, const idx_t expr_idx, + WindowInputExpression &boundary_start, WindowInputExpression &boundary_end, + const ValidityMask &partition_mask, const ValidityMask &order_mask) { + auto &bounds = *this; if (bounds.partition_count + bounds.order_count > 0) { // determine partition and peer group boundaries to ultimately figure out window size @@ -63807,10 +70664,10 @@ static void UpdateWindowBoundaries(WindowBoundariesState &bounds, const idx_t in bounds.peer_start = row_idx; // find end of partition - bounds.partition_end = input_size; + bounds.partition_end = bounds.input_size; if (bounds.partition_count) { idx_t n = 1; - bounds.partition_end = FindNextStart(partition_mask, bounds.partition_start + 1, input_size, n); + bounds.partition_end = FindNextStart(partition_mask, bounds.partition_start + 1, bounds.input_size, n); } // Find valid ordering values for the new partition @@ -63820,7 +70677,7 @@ static void UpdateWindowBoundaries(WindowBoundariesState &bounds, const idx_t in if ((bounds.valid_start < bounds.valid_end) && bounds.has_preceding_range) { // Exclude any leading NULLs - if (CellIsNull(over_collection, order_col, bounds.valid_start)) { + if (range_collection.CellIsNull(bounds.valid_start)) { idx_t n = 1; bounds.valid_start = FindNextStart(order_mask, bounds.valid_start + 1, bounds.valid_end, n); } @@ -63828,7 +70685,7 @@ static void UpdateWindowBoundaries(WindowBoundariesState &bounds, const idx_t in if ((bounds.valid_start < bounds.valid_end) && bounds.has_following_range) { // Exclude any trailing NULLs - if (CellIsNull(over_collection, order_col, bounds.valid_end - 1)) { + if (range_collection.CellIsNull(bounds.valid_end - 1)) { idx_t n = 1; bounds.valid_end = FindPrevStart(order_mask, bounds.valid_start, bounds.valid_end, n); } @@ -63849,7 +70706,7 @@ static void UpdateWindowBoundaries(WindowBoundariesState &bounds, const idx_t in } else { bounds.is_same_partition = false; bounds.is_peer = true; - bounds.partition_end = input_size; + bounds.partition_end = bounds.input_size; bounds.peer_end = bounds.partition_end; } @@ -63868,33 +70725,28 @@ static void UpdateWindowBoundaries(WindowBoundariesState &bounds, const idx_t in bounds.window_start = bounds.peer_start; break; case WindowBoundary::EXPR_PRECEDING_ROWS: { - bounds.window_start = - (int64_t)row_idx - GetCell(boundary_start_collection, 0, bounds.scalar_start ? 0 : row_idx); + bounds.window_start = (int64_t)row_idx - boundary_start.GetCell(expr_idx); break; } case WindowBoundary::EXPR_FOLLOWING_ROWS: { - bounds.window_start = - row_idx + GetCell(boundary_start_collection, 0, bounds.scalar_start ? 0 : row_idx); + bounds.window_start = row_idx + boundary_start.GetCell(expr_idx); break; } case WindowBoundary::EXPR_PRECEDING_RANGE: { - const auto expr_idx = bounds.scalar_start ? 0 : row_idx; - if (CellIsNull(boundary_start_collection, 0, expr_idx)) { + if (boundary_start.CellIsNull(expr_idx)) { bounds.window_start = bounds.peer_start; } else { - bounds.window_start = - FindOrderedRangeBound(over_collection, order_col, bounds.range_sense, bounds.valid_start, row_idx, - boundary_start_collection, expr_idx); + bounds.window_start = FindOrderedRangeBound(range_collection, bounds.range_sense, bounds.valid_start, + row_idx, boundary_start, expr_idx); } break; } case WindowBoundary::EXPR_FOLLOWING_RANGE: { - const auto expr_idx = bounds.scalar_start ? 0 : row_idx; - if (CellIsNull(boundary_start_collection, 0, expr_idx)) { + if (boundary_start.CellIsNull(expr_idx)) { bounds.window_start = bounds.peer_start; } else { - bounds.window_start = FindOrderedRangeBound(over_collection, order_col, bounds.range_sense, row_idx, - bounds.valid_end, boundary_start_collection, expr_idx); + bounds.window_start = FindOrderedRangeBound(range_collection, bounds.range_sense, row_idx, + bounds.valid_end, boundary_start, expr_idx); } break; } @@ -63913,30 +70765,26 @@ static void UpdateWindowBoundaries(WindowBoundariesState &bounds, const idx_t in bounds.window_end = bounds.partition_end; break; case WindowBoundary::EXPR_PRECEDING_ROWS: - bounds.window_end = - (int64_t)row_idx - GetCell(boundary_end_collection, 0, bounds.scalar_end ? 0 : row_idx) + 1; + bounds.window_end = (int64_t)row_idx - boundary_end.GetCell(expr_idx) + 1; break; case WindowBoundary::EXPR_FOLLOWING_ROWS: - bounds.window_end = row_idx + GetCell(boundary_end_collection, 0, bounds.scalar_end ? 0 : row_idx) + 1; + bounds.window_end = row_idx + boundary_end.GetCell(expr_idx) + 1; break; case WindowBoundary::EXPR_PRECEDING_RANGE: { - const auto expr_idx = bounds.scalar_end ? 0 : row_idx; - if (CellIsNull(boundary_end_collection, 0, expr_idx)) { + if (boundary_end.CellIsNull(expr_idx)) { bounds.window_end = bounds.peer_end; } else { - bounds.window_end = - FindOrderedRangeBound(over_collection, order_col, bounds.range_sense, bounds.valid_start, - row_idx, boundary_end_collection, expr_idx); + bounds.window_end = FindOrderedRangeBound(range_collection, bounds.range_sense, bounds.valid_start, + row_idx, boundary_end, expr_idx); } break; } case WindowBoundary::EXPR_FOLLOWING_RANGE: { - const auto expr_idx = bounds.scalar_end ? 0 : row_idx; - if (CellIsNull(boundary_end_collection, 0, expr_idx)) { + if (boundary_end.CellIsNull(expr_idx)) { bounds.window_end = bounds.peer_end; } else { - bounds.window_end = FindOrderedRangeBound(over_collection, order_col, bounds.range_sense, row_idx, - bounds.valid_end, boundary_end_collection, expr_idx); + bounds.window_end = FindOrderedRangeBound(range_collection, bounds.range_sense, row_idx, + bounds.valid_end, boundary_end, expr_idx); } break; } @@ -63963,129 +70811,164 @@ static void UpdateWindowBoundaries(WindowBoundariesState &bounds, const idx_t in } } -static void ComputeWindowExpression(BoundWindowExpression *wexpr, ChunkCollection &input, ChunkCollection &output, - ChunkCollection &over, const ValidityMask &partition_mask, - const ValidityMask &order_mask, WindowAggregationMode mode) { +struct WindowExecutor { + WindowExecutor(BoundWindowExpression *wexpr, Allocator &allocator, const idx_t count); - // TODO we could evaluate those expressions in parallel + void Sink(DataChunk &input_chunk, const idx_t input_idx); + void Finalize(WindowAggregationMode mode); - // evaluate inner expressions of window functions, could be more complex - ChunkCollection payload_collection; - vector exprs; - for (auto &child : wexpr->children) { - exprs.push_back(child.get()); - } - // TODO: child may be a scalar, don't need to materialize the whole collection then - MaterializeExpressions(exprs.data(), exprs.size(), input, payload_collection); + void Evaluate(idx_t row_idx, DataChunk &input_chunk, Vector &result, const ValidityMask &partition_mask, + const ValidityMask &order_mask); - ChunkCollection leadlag_offset_collection; - ChunkCollection leadlag_default_collection; - if (wexpr->type == ExpressionType::WINDOW_LEAD || wexpr->type == ExpressionType::WINDOW_LAG) { - if (wexpr->offset_expr) { - MaterializeExpression(wexpr->offset_expr.get(), input, leadlag_offset_collection, - wexpr->offset_expr->IsScalar()); - } - if (wexpr->default_expr) { - MaterializeExpression(wexpr->default_expr.get(), input, leadlag_default_collection, - wexpr->default_expr->IsScalar()); - } - } + // The function + BoundWindowExpression *wexpr; - // evaluate the FILTER clause and stuff it into a large mask for compactness and reuse + // Frame management + WindowBoundariesState bounds; + uint64_t dense_rank = 1; + uint64_t rank_equal = 0; + uint64_t rank = 1; + + // Expression collections + ChunkCollection payload_collection; + ExpressionExecutor payload_executor; + DataChunk payload_chunk; + + ExpressionExecutor filter_executor; ValidityMask filter_mask; vector filter_bits; + SelectionVector filter_sel; + + // LEAD/LAG Evaluation + WindowInputExpression leadlag_offset; + WindowInputExpression leadlag_default; + + // evaluate boundaries if present. Parser has checked boundary types. + WindowInputExpression boundary_start; + WindowInputExpression boundary_end; + + // evaluate RANGE expressions, if needed + WindowInputColumn range; + + // IGNORE NULLS + ValidityMask ignore_nulls; + + // build a segment tree for frame-adhering aggregates + // see http://www.vldb.org/pvldb/vol8/p1058-leis.pdf + unique_ptr segment_tree = nullptr; +}; + +WindowExecutor::WindowExecutor(BoundWindowExpression *wexpr, Allocator &allocator, const idx_t count) + : wexpr(wexpr), bounds(wexpr, count), payload_collection(allocator), payload_executor(allocator), + filter_executor(allocator), leadlag_offset(wexpr->offset_expr.get(), allocator), + leadlag_default(wexpr->default_expr.get(), allocator), boundary_start(wexpr->start_expr.get(), allocator), + boundary_end(wexpr->end_expr.get(), allocator), + range((bounds.has_preceding_range || bounds.has_following_range) ? wexpr->orders[0].expression.get() : nullptr, + allocator, count) + +{ + // TODO we could evaluate those expressions in parallel + + // evaluate the FILTER clause and stuff it into a large mask for compactness and reuse if (wexpr->filter_expr) { // Start with all invalid and set the ones that pass - filter_bits.resize(ValidityMask::ValidityMaskSize(input.Count()), 0); + filter_bits.resize(ValidityMask::ValidityMaskSize(count), 0); filter_mask.Initialize(filter_bits.data()); - ExpressionExecutor filter_execution(*wexpr->filter_expr); - SelectionVector true_sel(STANDARD_VECTOR_SIZE); - idx_t base_idx = 0; - for (auto &chunk : input.Chunks()) { - const auto filtered = filter_execution.SelectExpression(*chunk, true_sel); - for (idx_t f = 0; f < filtered; ++f) { - filter_mask.SetValid(base_idx + true_sel[f]); - } - base_idx += chunk->size(); - } + filter_executor.AddExpression(*wexpr->filter_expr); + filter_sel.Initialize(STANDARD_VECTOR_SIZE); } - // evaluate boundaries if present. Parser has checked boundary types. - ChunkCollection boundary_start_collection; - if (wexpr->start_expr) { - MaterializeExpression(wexpr->start_expr.get(), input, boundary_start_collection, wexpr->start_expr->IsScalar()); - } + // TODO: child may be a scalar, don't need to materialize the whole collection then - ChunkCollection boundary_end_collection; - if (wexpr->end_expr) { - MaterializeExpression(wexpr->end_expr.get(), input, boundary_end_collection, wexpr->end_expr->IsScalar()); + // evaluate inner expressions of window functions, could be more complex + vector exprs; + for (auto &child : wexpr->children) { + exprs.push_back(child.get()); } + PrepareInputExpressions(exprs.data(), exprs.size(), payload_executor, payload_chunk); +} + +void WindowExecutor::Sink(DataChunk &input_chunk, const idx_t input_idx) { + // Single pass over the input to produce the global data. + // Vectorisation for the win... // Set up a validity mask for IGNORE NULLS - ValidityMask ignore_nulls; + bool check_nulls = false; if (wexpr->ignore_nulls) { switch (wexpr->type) { case ExpressionType::WINDOW_LEAD: case ExpressionType::WINDOW_LAG: case ExpressionType::WINDOW_FIRST_VALUE: case ExpressionType::WINDOW_LAST_VALUE: - case ExpressionType::WINDOW_NTH_VALUE: { - idx_t pos = 0; - for (auto &chunk : payload_collection.Chunks()) { - const auto count = chunk->size(); - VectorData vdata; - chunk->data[0].Orrify(count, vdata); - if (!vdata.validity.AllValid()) { - // Lazily materialise the contents when we find the first NULL - if (ignore_nulls.AllValid()) { - ignore_nulls.Initialize(payload_collection.Count()); - } - // Write to the current position - // Chunks in a collection are full, so we don't have to worry about raggedness - auto dst = ignore_nulls.GetData() + ignore_nulls.EntryCount(pos); - auto src = vdata.validity.GetData(); - for (auto entry_count = vdata.validity.EntryCount(count); entry_count-- > 0;) { - *dst++ = *src++; - } - } - pos += count; - } + case ExpressionType::WINDOW_NTH_VALUE: + check_nulls = true; break; - } default: break; } } + const auto count = input_chunk.size(); + + if (!wexpr->children.empty()) { + payload_chunk.Reset(); + payload_executor.Execute(input_chunk, payload_chunk); + payload_chunk.Verify(); + payload_collection.Append(payload_chunk); + + // process payload chunks while they are still piping hot + if (check_nulls) { + UnifiedVectorFormat vdata; + payload_chunk.data[0].ToUnifiedFormat(count, vdata); + if (!vdata.validity.AllValid()) { + // Lazily materialise the contents when we find the first NULL + if (ignore_nulls.AllValid()) { + ignore_nulls.Initialize(payload_collection.Count()); + } + // Write to the current position + // Chunks in a collection are full, so we don't have to worry about raggedness + auto dst = ignore_nulls.GetData() + ignore_nulls.EntryCount(input_idx); + auto src = vdata.validity.GetData(); + for (auto entry_count = vdata.validity.EntryCount(count); entry_count-- > 0;) { + *dst++ = *src++; + } + } + } + } + + if (wexpr->filter_expr) { + const auto filtered = filter_executor.SelectExpression(input_chunk, filter_sel); + for (idx_t f = 0; f < filtered; ++f) { + filter_mask.SetValid(input_idx + filter_sel[f]); + } + } + + range.Append(input_chunk); +} + +void WindowExecutor::Finalize(WindowAggregationMode mode) { // build a segment tree for frame-adhering aggregates // see http://www.vldb.org/pvldb/vol8/p1058-leis.pdf - unique_ptr segment_tree = nullptr; if (wexpr->aggregate) { segment_tree = make_unique(*(wexpr->aggregate), wexpr->bind_info.get(), wexpr->return_type, &payload_collection, filter_mask, mode); } +} - WindowBoundariesState bounds(wexpr); - uint64_t dense_rank = 1, rank_equal = 0, rank = 1; +void WindowExecutor::Evaluate(idx_t row_idx, DataChunk &input_chunk, Vector &result, const ValidityMask &partition_mask, + const ValidityMask &order_mask) { + // Evaluate the row-level arguments + boundary_start.Execute(input_chunk); + boundary_end.Execute(input_chunk); - // this is the main loop, go through all sorted rows and compute window function result - const vector output_types(1, wexpr->return_type); - DataChunk output_chunk; - output_chunk.Initialize(output_types); - for (idx_t row_idx = 0; row_idx < input.Count(); row_idx++) { - // Grow the chunk if necessary. - const auto output_offset = row_idx % STANDARD_VECTOR_SIZE; - if (output_offset == 0) { - output.Append(output_chunk); - output_chunk.Reset(); - output_chunk.SetCardinality(MinValue(idx_t(STANDARD_VECTOR_SIZE), input.Count() - row_idx)); - } - auto &result = output_chunk.data[0]; + leadlag_offset.Execute(input_chunk); + leadlag_default.Execute(input_chunk); + // this is the main loop, go through all sorted rows and compute window function result + for (idx_t output_offset = 0; output_offset < input_chunk.size(); ++output_offset, ++row_idx) { // special case, OVER (), aggregate over everything - UpdateWindowBoundaries(bounds, input.Count(), row_idx, over, boundary_start_collection, boundary_end_collection, - partition_mask, order_mask); + bounds.Update(row_idx, range, output_offset, boundary_start, boundary_end, partition_mask, order_mask); if (WindowNeedsRank(wexpr)) { if (!bounds.is_same_partition || row_idx == 0) { // special case for first row, need to init dense_rank = 1; @@ -64141,41 +71024,48 @@ static void ComputeWindowExpression(BoundWindowExpression *wexpr, ChunkCollectio } case ExpressionType::WINDOW_NTILE: { D_ASSERT(payload_collection.ColumnCount() == 1); - auto n_param = GetCell(payload_collection, 0, row_idx); - // With thanks from SQLite's ntileValueFunc() - int64_t n_total = bounds.partition_end - bounds.partition_start; - if (n_param > n_total) { - // more groups allowed than we have values - // map every entry to a unique group - n_param = n_total; - } - int64_t n_size = (n_total / n_param); - // find the row idx within the group - D_ASSERT(row_idx >= bounds.partition_start); - int64_t adjusted_row_idx = row_idx - bounds.partition_start; - // now compute the ntile - int64_t n_large = n_total - n_param * n_size; - int64_t i_small = n_large * (n_size + 1); - int64_t result_ntile; - - D_ASSERT((n_large * (n_size + 1) + (n_param - n_large) * n_size) == n_total); - - if (adjusted_row_idx < i_small) { - result_ntile = 1 + adjusted_row_idx / (n_size + 1); + if (CellIsNull(payload_collection, 0, row_idx)) { + FlatVector::SetNull(result, output_offset, true); } else { - result_ntile = 1 + n_large + (adjusted_row_idx - i_small) / n_size; + auto n_param = GetCell(payload_collection, 0, row_idx); + if (n_param < 1) { + throw InvalidInputException("Argument for ntile must be greater than zero"); + } + // With thanks from SQLite's ntileValueFunc() + int64_t n_total = bounds.partition_end - bounds.partition_start; + if (n_param > n_total) { + // more groups allowed than we have values + // map every entry to a unique group + n_param = n_total; + } + int64_t n_size = (n_total / n_param); + // find the row idx within the group + D_ASSERT(row_idx >= bounds.partition_start); + int64_t adjusted_row_idx = row_idx - bounds.partition_start; + // now compute the ntile + int64_t n_large = n_total - n_param * n_size; + int64_t i_small = n_large * (n_size + 1); + int64_t result_ntile; + + D_ASSERT((n_large * (n_size + 1) + (n_param - n_large) * n_size) == n_total); + + if (adjusted_row_idx < i_small) { + result_ntile = 1 + adjusted_row_idx / (n_size + 1); + } else { + result_ntile = 1 + n_large + (adjusted_row_idx - i_small) / n_size; + } + // result has to be between [1, NTILE] + D_ASSERT(result_ntile >= 1 && result_ntile <= n_param); + auto rdata = FlatVector::GetData(result); + rdata[output_offset] = result_ntile; } - // result has to be between [1, NTILE] - D_ASSERT(result_ntile >= 1 && result_ntile <= n_param); - auto rdata = FlatVector::GetData(result); - rdata[output_offset] = result_ntile; break; } case ExpressionType::WINDOW_LEAD: case ExpressionType::WINDOW_LAG: { int64_t offset = 1; if (wexpr->offset_expr) { - offset = GetCell(leadlag_offset_collection, 0, wexpr->offset_expr->IsScalar() ? 0 : row_idx); + offset = leadlag_offset.GetCell(output_offset); } int64_t val_idx = (int64_t)row_idx; if (wexpr->type == ExpressionType::WINDOW_LEAD) { @@ -64198,8 +71088,7 @@ static void ComputeWindowExpression(BoundWindowExpression *wexpr, ChunkCollectio if (!delta) { payload_collection.CopyCell(0, val_idx, result, output_offset); } else if (wexpr->default_expr) { - const auto source_row = wexpr->default_expr->IsScalar() ? 0 : row_idx; - leadlag_default_collection.CopyCell(0, source_row, result, output_offset); + leadlag_default.CopyCell(result, output_offset); } else { FlatVector::SetNull(result, output_offset, true); } @@ -64244,194 +71133,127 @@ static void ComputeWindowExpression(BoundWindowExpression *wexpr, ChunkCollectio } } - // Push the last chunk - output.Append(output_chunk); -} - -using WindowExpressions = vector; - -static void ComputeWindowExpressions(WindowExpressions &window_exprs, ChunkCollection &input, - ChunkCollection &window_results, ChunkCollection &over, - WindowAggregationMode mode) { - // Idempotency - if (input.Count() == 0) { - return; - } - // Pick out a function for the OVER clause - auto over_expr = window_exprs[0]; - - // Set bits for the start of each partition - vector partition_bits(ValidityMask::EntryCount(input.Count()), 0); - ValidityMask partition_mask(partition_bits.data()); - partition_mask.SetValid(0); - - for (idx_t c = 0; c < over_expr->partitions.size(); ++c) { - MaskColumn(partition_mask, over, c); - } - - // Set bits for the start of each peer group. - // Partitions also break peer groups, so start with the partition bits. - const auto sort_col_count = over_expr->partitions.size() + over_expr->orders.size(); - ValidityMask order_mask(partition_mask, input.Count()); - for (idx_t c = over_expr->partitions.size(); c < sort_col_count; ++c) { - MaskColumn(order_mask, over, c); - } - - // Compute the functions columnwise - for (idx_t expr_idx = 0; expr_idx < window_exprs.size(); ++expr_idx) { - ChunkCollection output; - ComputeWindowExpression(window_exprs[expr_idx], input, output, over, partition_mask, order_mask, mode); - window_results.Fuse(output); - } + result.Verify(input_chunk.size()); } //===--------------------------------------------------------------------===// // Sink //===--------------------------------------------------------------------===// -static void GeneratePartition(WindowOperatorState &state, WindowGlobalState &gstate, const idx_t hash_bin) { - auto &op = (PhysicalWindow &)gstate.op; - WindowExpressions window_exprs; - for (idx_t expr_idx = 0; expr_idx < op.select_list.size(); ++expr_idx) { - D_ASSERT(op.select_list[expr_idx]->GetExpressionClass() == ExpressionClass::BOUND_WINDOW); - auto wexpr = reinterpret_cast(op.select_list[expr_idx].get()); - window_exprs.emplace_back(wexpr); - } - - // Get rid of any stale data - state.chunks.Reset(); - state.window_results.Reset(); - state.position = 0; - state.global_sort_state = nullptr; - - // Pick out a function for the OVER clause - auto over_expr = window_exprs[0]; - - // There are three types of partitions: - // 1. No partition (no sorting) - // 2. One partition (sorting, but no hashing) - // 3. Multiple partitions (sorting and hashing) - const auto input_types = gstate.chunks.Types(); - const auto over_types = gstate.over_collection.Types(); - - if (gstate.counts.empty() && hash_bin == 0) { - ChunkCollection &input = gstate.chunks; - ChunkCollection output; - ChunkCollection &over = gstate.over_collection; - - const auto has_sorting = over_expr->partitions.size() + over_expr->orders.size(); - if (has_sorting && input.Count() > 0) { - // 2. One partition - SortCollectionForPartition(state, over_expr, input, over, nullptr, 0, 0); +SinkResultType PhysicalWindow::Sink(ExecutionContext &context, GlobalSinkState &gstate_p, LocalSinkState &lstate_p, + DataChunk &input) const { + auto &gstate = (WindowGlobalSinkState &)gstate_p; + auto &lstate = (WindowLocalSinkState &)lstate_p; - // Overwrite the collections with the sorted data - ScanSortedPartition(state, input, input_types, over, over_types); - } + lstate.Sink(input, gstate); - ComputeWindowExpressions(window_exprs, input, output, over, gstate.mode); - state.chunks.Merge(input); - state.window_results.Merge(output); + return SinkResultType::NEED_MORE_INPUT; +} - } else if (hash_bin < gstate.counts.size() && gstate.counts[hash_bin] > 0) { - // 3. Multiple partitions - const auto hash_mask = hash_t(gstate.counts.size() - 1); - SortCollectionForPartition(state, over_expr, gstate.chunks, gstate.over_collection, &gstate.hash_collection, - hash_bin, hash_mask); +void PhysicalWindow::Combine(ExecutionContext &context, GlobalSinkState &gstate_p, LocalSinkState &lstate_p) const { + auto &gstate = (WindowGlobalSinkState &)gstate_p; + auto &lstate = (WindowLocalSinkState &)lstate_p; + lstate.Combine(gstate); +} - // Scan the sorted data into new Collections - ChunkCollection input; - ChunkCollection output; - ChunkCollection over; - ScanSortedPartition(state, input, input_types, over, over_types); +unique_ptr PhysicalWindow::GetLocalSinkState(ExecutionContext &context) const { + return make_unique(Allocator::Get(context.client), *this); +} - ComputeWindowExpressions(window_exprs, input, output, over, gstate.mode); - state.chunks.Merge(input); - state.window_results.Merge(output); - } +unique_ptr PhysicalWindow::GetGlobalSinkState(ClientContext &context) const { + return make_unique(*this, context); } -static void Scan(WindowOperatorState &state, DataChunk &chunk) { - ChunkCollection &big_data = state.chunks; - ChunkCollection &window_results = state.window_results; +class WindowMergeTask : public ExecutorTask { +public: + WindowMergeTask(shared_ptr event_p, ClientContext &context_p, WindowGlobalHashGroup &hash_group_p) + : ExecutorTask(context_p), event(move(event_p)), hash_group(hash_group_p) { + } - if (state.position >= big_data.Count()) { - return; + TaskExecutionResult ExecuteTask(TaskExecutionMode mode) override { + // Initialize merge sorted and iterate until done + auto &global_sort = *hash_group.global_sort; + MergeSorter merge_sorter(global_sort, global_sort.buffer_manager); + merge_sorter.PerformInMergeRound(); + event->FinishTask(); + return TaskExecutionResult::TASK_FINISHED; } - // just return what was computed before, appending the result cols of the window expressions at the end - auto &proj_ch = big_data.GetChunkForRow(state.position); - auto &wind_ch = window_results.GetChunkForRow(state.position); +private: + shared_ptr event; + WindowGlobalHashGroup &hash_group; +}; - idx_t out_idx = 0; - D_ASSERT(proj_ch.size() == wind_ch.size()); - chunk.SetCardinality(proj_ch); - for (idx_t col_idx = 0; col_idx < proj_ch.ColumnCount(); col_idx++) { - chunk.data[out_idx++].Reference(proj_ch.data[col_idx]); - } - for (idx_t col_idx = 0; col_idx < wind_ch.ColumnCount(); col_idx++) { - chunk.data[out_idx++].Reference(wind_ch.data[col_idx]); +class WindowMergeEvent : public Event { +public: + WindowMergeEvent(WindowGlobalSinkState &gstate_p, Pipeline &pipeline_p, WindowGlobalHashGroup &hash_group_p) + : Event(pipeline_p.executor), gstate(gstate_p), pipeline(pipeline_p), hash_group(hash_group_p) { } - chunk.Verify(); - state.position += STANDARD_VECTOR_SIZE; -} + WindowGlobalSinkState &gstate; + Pipeline &pipeline; + WindowGlobalHashGroup &hash_group; -SinkResultType PhysicalWindow::Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate_p, - DataChunk &input) const { - auto &lstate = (WindowLocalState &)lstate_p; - lstate.chunks.Append(input); +public: + void Schedule() override { + auto &context = pipeline.GetClientContext(); - // Compute the over columns and the hash values for this block (if any) - const auto over_idx = 0; - auto over_expr = reinterpret_cast(select_list[over_idx].get()); + // Schedule tasks equal to the number of threads, which will each merge multiple partitions + auto &ts = TaskScheduler::GetScheduler(context); + idx_t num_threads = ts.NumberOfThreads(); - const auto sort_col_count = over_expr->partitions.size() + over_expr->orders.size(); - if (sort_col_count > 0) { - DataChunk over_chunk; - MaterializeOverForWindow(over_expr, input, over_chunk); + vector> merge_tasks; + for (idx_t tnum = 0; tnum < num_threads; tnum++) { + merge_tasks.push_back(make_unique(shared_from_this(), context, hash_group)); + } + SetTasks(move(merge_tasks)); + } - if (!over_expr->partitions.empty()) { - if (lstate.counts.empty()) { - lstate.counts.resize(lstate.partition_count, 0); - } + void FinishEvent() override { + hash_group.global_sort->CompleteMergeRound(true); + CreateMergeTasks(pipeline, *this, gstate, hash_group); + } - DataChunk hash_chunk; - HashChunk(lstate.counts, hash_chunk, over_chunk, over_expr->partitions.size()); - lstate.hash_collection.Append(hash_chunk); - D_ASSERT(lstate.chunks.Count() == lstate.hash_collection.Count()); - } + static void CreateMergeTasks(Pipeline &pipeline, Event &event, WindowGlobalSinkState &state, + WindowGlobalHashGroup &hash_group) { - lstate.over_collection.Append(over_chunk); - D_ASSERT(lstate.chunks.Count() == lstate.over_collection.Count()); + // Multiple blocks remaining in the group: Schedule the next round + if (hash_group.global_sort->sorted_blocks.size() > 1) { + hash_group.global_sort->InitializeMergeRound(); + auto new_event = make_shared(state, pipeline, hash_group); + event.InsertEvent(move(new_event)); + } } - return SinkResultType::NEED_MORE_INPUT; -} +}; -void PhysicalWindow::Combine(ExecutionContext &context, GlobalSinkState &gstate_p, LocalSinkState &lstate_p) const { - auto &lstate = (WindowLocalState &)lstate_p; - if (lstate.chunks.Count() == 0) { - return; +SinkFinalizeType PhysicalWindow::Finalize(Pipeline &pipeline, Event &event, ClientContext &context, + GlobalSinkState &gstate_p) const { + auto &state = (WindowGlobalSinkState &)gstate_p; + + // Do we have any sorting to schedule? + if (state.rows) { + D_ASSERT(state.hash_groups.empty()); + return state.rows->count ? SinkFinalizeType::READY : SinkFinalizeType::NO_OUTPUT_POSSIBLE; } - auto &gstate = (WindowGlobalState &)gstate_p; - lock_guard glock(gstate.lock); - gstate.chunks.Merge(lstate.chunks); - gstate.over_collection.Merge(lstate.over_collection); - gstate.hash_collection.Merge(lstate.hash_collection); - if (gstate.counts.empty()) { - gstate.counts = lstate.counts; - } else { - D_ASSERT(gstate.counts.size() == lstate.counts.size()); - for (idx_t i = 0; i < gstate.counts.size(); ++i) { - gstate.counts[i] += lstate.counts[i]; - } + + // Find the first group to sort + state.Finalize(); + D_ASSERT(state.count == state.GroupCount()); + auto group = state.GetNextSortGroup(); + if (group >= state.hash_groups.size()) { + // Empty input! + return SinkFinalizeType::NO_OUTPUT_POSSIBLE; } -} -unique_ptr PhysicalWindow::GetLocalSinkState(ExecutionContext &context) const { - return make_unique(*this); -} + // Schedule all the sorts for maximum thread utilisation + for (; group < state.hash_groups.size(); group = state.GetNextSortGroup()) { + auto &hash_group = *state.hash_groups[group]; -unique_ptr PhysicalWindow::GetGlobalSinkState(ClientContext &context) const { - return make_unique(*this, context); + // Prepare for merge sort phase + hash_group.PrepareMergePhase(); + WindowMergeEvent::CreateMergeTasks(pipeline, event, state, hash_group); + } + + return SinkFinalizeType::READY; } //===--------------------------------------------------------------------===// @@ -64439,25 +71261,25 @@ unique_ptr PhysicalWindow::GetGlobalSinkState(ClientContext &co //===--------------------------------------------------------------------===// class WindowGlobalSourceState : public GlobalSourceState { public: - explicit WindowGlobalSourceState(const PhysicalWindow &op) : op(op), next_part(0) { + explicit WindowGlobalSourceState(const PhysicalWindow &op) : op(op), next_bin(0) { } const PhysicalWindow &op; //! The output read position. - atomic next_part; + atomic next_bin; public: idx_t MaxThreads() override { - auto &state = (WindowGlobalState &)*op.sink_state; + auto &state = (WindowGlobalSinkState &)*op.sink_state; // If there is only one partition, we have to process it on one thread. - if (state.counts.empty()) { + if (state.hash_groups.empty()) { return 1; } idx_t max_threads = 0; - for (const auto count : state.counts) { - if (count > 0) { + for (const auto &hash_group : state.hash_groups) { + if (hash_group) { max_threads++; } } @@ -64466,9 +71288,221 @@ class WindowGlobalSourceState : public GlobalSourceState { } }; +// Per-thread read state +class WindowLocalSourceState : public LocalSourceState { +public: + using HashGroupPtr = unique_ptr; + using WindowExecutorPtr = unique_ptr; + using WindowExecutors = vector; + + WindowLocalSourceState(Allocator &allocator_p, const PhysicalWindow &op, ExecutionContext &context) + : allocator(allocator_p) { + vector output_types; + for (idx_t expr_idx = 0; expr_idx < op.select_list.size(); ++expr_idx) { + D_ASSERT(op.select_list[expr_idx]->GetExpressionClass() == ExpressionClass::BOUND_WINDOW); + auto wexpr = reinterpret_cast(op.select_list[expr_idx].get()); + output_types.emplace_back(wexpr->return_type); + } + output_chunk.Initialize(allocator, output_types); + + const auto &input_types = op.children[0]->types; + layout.Initialize(input_types); + input_chunk.Initialize(allocator, input_types); + } + + void MaterializeSortedData(); + void GeneratePartition(WindowGlobalSinkState &gstate, const idx_t hash_bin); + void Scan(DataChunk &chunk); + + HashGroupPtr hash_group; + Allocator &allocator; + + //! The generated input chunks + unique_ptr rows; + unique_ptr heap; + RowLayout layout; + //! The partition boundary mask + vector partition_bits; + ValidityMask partition_mask; + //! The order boundary mask + vector order_bits; + ValidityMask order_mask; + //! The current execution functions + WindowExecutors window_execs; + + //! The read partition + idx_t hash_bin; + //! The read cursor + unique_ptr scanner; + //! Buffer for the inputs + DataChunk input_chunk; + //! Buffer for window results + DataChunk output_chunk; +}; + +void WindowLocalSourceState::MaterializeSortedData() { + auto &global_sort_state = *hash_group->global_sort; + if (global_sort_state.sorted_blocks.empty()) { + return; + } + + // scan the sorted row data + D_ASSERT(global_sort_state.sorted_blocks.size() == 1); + auto &sb = *global_sort_state.sorted_blocks[0]; + + // Free up some memory before allocating more + sb.radix_sorting_data.clear(); + sb.blob_sorting_data = nullptr; + + // Move the sorting row blocks into our RDCs + auto &buffer_manager = global_sort_state.buffer_manager; + auto &sd = *sb.payload_data; + + // Data blocks are required + D_ASSERT(!sd.data_blocks.empty()); + auto &block = sd.data_blocks[0]; + rows = make_unique(buffer_manager, block->capacity, block->entry_size); + rows->blocks = move(sd.data_blocks); + rows->count = std::accumulate(rows->blocks.begin(), rows->blocks.end(), idx_t(0), + [&](idx_t c, const unique_ptr &b) { return c + b->count; }); + + // Heap blocks are optional, but we want both for iteration. + if (!sd.heap_blocks.empty()) { + auto &block = sd.heap_blocks[0]; + heap = make_unique(buffer_manager, block->capacity, block->entry_size); + heap->blocks = move(sd.heap_blocks); + hash_group.reset(); + } else { + heap = make_unique(buffer_manager, (idx_t)Storage::BLOCK_SIZE, 1, true); + } + heap->count = std::accumulate(heap->blocks.begin(), heap->blocks.end(), idx_t(0), + [&](idx_t c, const unique_ptr &b) { return c + b->count; }); +} + +void WindowLocalSourceState::GeneratePartition(WindowGlobalSinkState &gstate, const idx_t hash_bin_p) { + auto &op = (PhysicalWindow &)gstate.op; + + // Get rid of any stale data + hash_bin = hash_bin_p; + hash_group.reset(); + + // There are three types of partitions: + // 1. No partition (no sorting) + // 2. One partition (sorting, but no hashing) + // 3. Multiple partitions (sorting and hashing) + + // How big is the partition? + idx_t count = 0; + if (hash_bin < gstate.hash_groups.size() && gstate.hash_groups[hash_bin]) { + count = gstate.hash_groups[hash_bin]->count; + } else if (gstate.rows && !hash_bin) { + count = gstate.count; + } else { + return; + } + + // Create the executors for each function + window_execs.clear(); + for (idx_t expr_idx = 0; expr_idx < op.select_list.size(); ++expr_idx) { + D_ASSERT(op.select_list[expr_idx]->GetExpressionClass() == ExpressionClass::BOUND_WINDOW); + auto wexpr = reinterpret_cast(op.select_list[expr_idx].get()); + auto wexec = make_unique(wexpr, allocator, count); + window_execs.emplace_back(move(wexec)); + } + + // Initialise masks to false + const auto bit_count = ValidityMask::ValidityMaskSize(count); + partition_bits.clear(); + partition_bits.resize(bit_count, 0); + partition_mask.Initialize(partition_bits.data()); + + order_bits.clear(); + order_bits.resize(bit_count, 0); + order_mask.Initialize(order_bits.data()); + + // Scan the sorted data into new Collections + auto external = gstate.external; + if (gstate.rows && !hash_bin) { + // Simple mask + partition_mask.SetValidUnsafe(0); + order_mask.SetValidUnsafe(0); + // No partition - align the heap blocks with the row blocks + rows = gstate.rows->CloneEmpty(gstate.rows->keep_pinned); + heap = gstate.strings->CloneEmpty(gstate.strings->keep_pinned); + RowDataCollectionScanner::AlignHeapBlocks(*rows, *heap, *gstate.rows, *gstate.strings, layout); + external = true; + } else if (hash_bin < gstate.hash_groups.size() && gstate.hash_groups[hash_bin]) { + // Overwrite the collections with the sorted data + hash_group = move(gstate.hash_groups[hash_bin]); + hash_group->ComputeMasks(partition_mask, order_mask); + MaterializeSortedData(); + } else { + return; + } + + // First pass over the input without flushing + // TODO: Factor out the constructor data as global state + scanner = make_unique(*rows, *heap, layout, external, false); + idx_t input_idx = 0; + while (true) { + input_chunk.Reset(); + scanner->Scan(input_chunk); + if (input_chunk.size() == 0) { + break; + } + + // TODO: Parallelization opportunity + for (auto &wexec : window_execs) { + wexec->Sink(input_chunk, input_idx); + } + input_idx += input_chunk.size(); + } + + // TODO: Parallelization opportunity + for (auto &wexec : window_execs) { + wexec->Finalize(gstate.mode); + } + + // External scanning assumes all blocks are swizzled. + scanner->ReSwizzle(); + + // Second pass can flush + scanner = make_unique(*rows, *heap, layout, external, true); +} + +void WindowLocalSourceState::Scan(DataChunk &result) { + D_ASSERT(scanner); + if (!scanner->Remaining()) { + scanner.reset(); + return; + } + + const auto position = scanner->Scanned(); + input_chunk.Reset(); + scanner->Scan(input_chunk); + + output_chunk.Reset(); + for (idx_t expr_idx = 0; expr_idx < window_execs.size(); ++expr_idx) { + auto &executor = *window_execs[expr_idx]; + executor.Evaluate(position, input_chunk, output_chunk.data[expr_idx], partition_mask, order_mask); + } + output_chunk.SetCardinality(input_chunk); + output_chunk.Verify(); + + idx_t out_idx = 0; + result.SetCardinality(input_chunk); + for (idx_t col_idx = 0; col_idx < input_chunk.ColumnCount(); col_idx++) { + result.data[out_idx++].Reference(input_chunk.data[col_idx]); + } + for (idx_t col_idx = 0; col_idx < output_chunk.ColumnCount(); col_idx++) { + result.data[out_idx++].Reference(output_chunk.data[col_idx]); + } + result.Verify(); +} + unique_ptr PhysicalWindow::GetLocalSourceState(ExecutionContext &context, GlobalSourceState &gstate) const { - return make_unique(*this, context); + return make_unique(Allocator::Get(context.client), *this, context); } unique_ptr PhysicalWindow::GetGlobalSourceState(ClientContext &context) const { @@ -64477,28 +71511,31 @@ unique_ptr PhysicalWindow::GetGlobalSourceState(ClientContext void PhysicalWindow::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate_p, LocalSourceState &lstate_p) const { - auto &state = (WindowOperatorState &)lstate_p; + auto &state = (WindowLocalSourceState &)lstate_p; auto &global_source = (WindowGlobalSourceState &)gstate_p; - auto &gstate = (WindowGlobalState &)*sink_state; + auto &gstate = (WindowGlobalSinkState &)*sink_state; - do { - if (state.position >= state.chunks.Count()) { - auto hash_bin = global_source.next_part++; - for (; hash_bin < state.partitions; hash_bin = global_source.next_part++) { - if (gstate.counts[hash_bin] > 0) { - break; - } - } - GeneratePartition(state, gstate, hash_bin); - } - Scan(state, chunk); - if (chunk.size() != 0) { + const auto bin_count = gstate.hash_groups.empty() ? 1 : gstate.hash_groups.size(); + + // Move to the next bin if we are done. + while (!state.scanner || !state.scanner->Remaining()) { + state.scanner.reset(); + state.rows.reset(); + state.heap.reset(); + auto hash_bin = global_source.next_bin++; + if (hash_bin >= bin_count) { return; - } else { - break; } - } while (true); - D_ASSERT(chunk.size() == 0); + + for (; hash_bin < gstate.hash_groups.size(); hash_bin = global_source.next_bin++) { + if (gstate.hash_groups[hash_bin]) { + break; + } + } + state.GeneratePartition(gstate, hash_bin); + } + + state.Scan(chunk); } string PhysicalWindow::ParamsToString() const { @@ -64539,7 +71576,7 @@ class PhysicalFilter : public PhysicalOperator { unique_ptr expression; public: - unique_ptr GetOperatorState(ClientContext &context) const override; + unique_ptr GetOperatorState(ExecutionContext &context) const override; OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const override; @@ -64578,7 +71615,8 @@ PhysicalFilter::PhysicalFilter(vector types, vector PhysicalFilter::GetOperatorState(ClientContext &context) const { - return make_unique(*expression); +unique_ptr PhysicalFilter::GetOperatorState(ExecutionContext &context) const { + return make_unique(context, *expression); } OperatorResultType PhysicalFilter::Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, @@ -64713,14 +71751,20 @@ PhysicalBatchCollector::PhysicalBatchCollector(PreparedStatementData &data) : Ph //===--------------------------------------------------------------------===// class BatchCollectorGlobalState : public GlobalSinkState { public: + BatchCollectorGlobalState(ClientContext &context, const PhysicalBatchCollector &op) : data(op.types) { + } + mutex glock; - BatchedChunkCollection data; + BatchedDataCollection data; unique_ptr result; }; class BatchCollectorLocalState : public LocalSinkState { public: - BatchedChunkCollection data; + BatchCollectorLocalState(ClientContext &context, const PhysicalBatchCollector &op) : data(op.types) { + } + + BatchedDataCollection data; }; SinkResultType PhysicalBatchCollector::Sink(ExecutionContext &context, GlobalSinkState &gstate, @@ -64742,32 +71786,20 @@ void PhysicalBatchCollector::Combine(ExecutionContext &context, GlobalSinkState SinkFinalizeType PhysicalBatchCollector::Finalize(Pipeline &pipeline, Event &event, ClientContext &context, GlobalSinkState &gstate_p) const { auto &gstate = (BatchCollectorGlobalState &)gstate_p; - auto result = - make_unique(statement_type, properties, types, names, context.shared_from_this()); - DataChunk output; - output.Initialize(types); - - BatchedChunkScanState state; - gstate.data.InitializeScan(state); - while (true) { - output.Reset(); - gstate.data.Scan(state, output); - if (output.size() == 0) { - break; - } - result->collection.Append(output); - } - + auto collection = gstate.data.FetchCollection(); + D_ASSERT(collection); + auto result = make_unique(statement_type, properties, names, move(collection), + context.GetClientProperties()); gstate.result = move(result); return SinkFinalizeType::READY; } unique_ptr PhysicalBatchCollector::GetLocalSinkState(ExecutionContext &context) const { - return make_unique(); + return make_unique(context.client, *this); } unique_ptr PhysicalBatchCollector::GetGlobalSinkState(ClientContext &context) const { - return make_unique(); + return make_unique(context, *this); } unique_ptr PhysicalBatchCollector::GetResult(GlobalSinkState &state) { @@ -64804,8 +71836,10 @@ unique_ptr PhysicalBatchCollector::GetResult(GlobalSinkState &state + namespace duckdb { class CatalogEntry; +class ClientContext; class PhysicalOperator; class SQLStatement; @@ -64820,7 +71854,7 @@ class PreparedStatementData { //! The fully prepared physical plan of the prepared statement unique_ptr plan; //! The map of parameter index to the actual value entry - unordered_map>> value_map; + bound_parameter_map_t value_map; //! The result names of the transaction vector names; @@ -64835,6 +71869,9 @@ class PreparedStatementData { idx_t catalog_version; public: + void CheckParameterCount(idx_t parameter_count); + //! Whether or not the prepared statement data requires the query to rebound for the given parameters + bool RequireRebind(ClientContext &context, const vector &values); //! Bind a set of values to the prepared statement data DUCKDB_API void Bind(vector values); //! Get the expected SQL Type of the bound parameter @@ -64843,6 +71880,7 @@ class PreparedStatementData { } // namespace duckdb + namespace duckdb { class PhysicalExecute : public PhysicalOperator { @@ -65044,10 +72082,11 @@ class PhysicalLimit : public PhysicalOperator { } public: - static bool ComputeOffset(DataChunk &input, idx_t &limit, idx_t &offset, idx_t current_offset, idx_t &max_element, - Expression *limit_expression, Expression *offset_expression); + static bool ComputeOffset(ExecutionContext &context, DataChunk &input, idx_t &limit, idx_t &offset, + idx_t current_offset, idx_t &max_element, Expression *limit_expression, + Expression *offset_expression); static bool HandleOffset(DataChunk &input, idx_t ¤t_offset, idx_t offset, idx_t limit); - static Value GetDelimiter(DataChunk &input, Expression *expr); + static Value GetDelimiter(ExecutionContext &context, DataChunk &input, Expression *expr); }; } // namespace duckdb @@ -65087,7 +72126,7 @@ class PhysicalStreamingLimit : public PhysicalOperator { public: // Operator interface - unique_ptr GetOperatorState(ClientContext &context) const override; + unique_ptr GetOperatorState(ExecutionContext &context) const override; unique_ptr GetGlobalOperatorState(ClientContext &context) const override; OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const override; @@ -65113,7 +72152,7 @@ PhysicalLimit::PhysicalLimit(vector types, idx_t limit, idx_t offse //===--------------------------------------------------------------------===// class LimitGlobalState : public GlobalSinkState { public: - explicit LimitGlobalState(const PhysicalLimit &op) { + explicit LimitGlobalState(ClientContext &context, const PhysicalLimit &op) : data(op.types) { limit = 0; offset = 0; } @@ -65121,12 +72160,12 @@ class LimitGlobalState : public GlobalSinkState { mutex glock; idx_t limit; idx_t offset; - BatchedChunkCollection data; + BatchedDataCollection data; }; class LimitLocalState : public LocalSinkState { public: - explicit LimitLocalState(const PhysicalLimit &op) : current_offset(0) { + explicit LimitLocalState(ClientContext &context, const PhysicalLimit &op) : current_offset(0), data(op.types) { this->limit = op.limit_expression ? DConstants::INVALID_INDEX : op.limit_value; this->offset = op.offset_expression ? DConstants::INVALID_INDEX : op.offset_value; } @@ -65134,19 +72173,20 @@ class LimitLocalState : public LocalSinkState { idx_t current_offset; idx_t limit; idx_t offset; - BatchedChunkCollection data; + BatchedDataCollection data; }; unique_ptr PhysicalLimit::GetGlobalSinkState(ClientContext &context) const { - return make_unique(*this); + return make_unique(context, *this); } unique_ptr PhysicalLimit::GetLocalSinkState(ExecutionContext &context) const { - return make_unique(*this); + return make_unique(context.client, *this); } -bool PhysicalLimit::ComputeOffset(DataChunk &input, idx_t &limit, idx_t &offset, idx_t current_offset, - idx_t &max_element, Expression *limit_expression, Expression *offset_expression) { +bool PhysicalLimit::ComputeOffset(ExecutionContext &context, DataChunk &input, idx_t &limit, idx_t &offset, + idx_t current_offset, idx_t &max_element, Expression *limit_expression, + Expression *offset_expression) { if (limit != DConstants::INVALID_INDEX && offset != DConstants::INVALID_INDEX) { max_element = limit + offset; if ((limit == 0 || current_offset >= max_element) && !(limit_expression || offset_expression)) { @@ -65157,7 +72197,7 @@ bool PhysicalLimit::ComputeOffset(DataChunk &input, idx_t &limit, idx_t &offset, // get the next chunk from the child if (limit == DConstants::INVALID_INDEX) { limit = 1ULL << 62ULL; - Value val = GetDelimiter(input, limit_expression); + Value val = GetDelimiter(context, input, limit_expression); if (!val.IsNull()) { limit = val.GetValue(); } @@ -65167,7 +72207,7 @@ bool PhysicalLimit::ComputeOffset(DataChunk &input, idx_t &limit, idx_t &offset, } if (offset == DConstants::INVALID_INDEX) { offset = 0; - Value val = GetDelimiter(input, offset_expression); + Value val = GetDelimiter(context, input, offset_expression); if (!val.IsNull()) { offset = val.GetValue(); } @@ -65191,10 +72231,14 @@ SinkResultType PhysicalLimit::Sink(ExecutionContext &context, GlobalSinkState &g auto &offset = state.offset; idx_t max_element; - if (!ComputeOffset(input, limit, offset, state.current_offset, max_element, limit_expression.get(), + if (!ComputeOffset(context, input, limit, offset, state.current_offset, max_element, limit_expression.get(), offset_expression.get())) { return SinkResultType::FINISHED; } + auto max_cardinality = max_element - state.current_offset; + if (max_cardinality < input.size()) { + input.SetCardinality(max_cardinality); + } state.data.Append(input, lstate.batch_index); state.current_offset += input.size(); return SinkResultType::NEED_MORE_INPUT; @@ -65290,11 +72334,12 @@ bool PhysicalLimit::HandleOffset(DataChunk &input, idx_t ¤t_offset, idx_t return true; } -Value PhysicalLimit::GetDelimiter(DataChunk &input, Expression *expr) { +Value PhysicalLimit::GetDelimiter(ExecutionContext &context, DataChunk &input, Expression *expr) { DataChunk limit_chunk; vector types {expr->return_type}; - limit_chunk.Initialize(types); - ExpressionExecutor limit_executor(expr); + auto &allocator = Allocator::Get(context.client); + limit_chunk.Initialize(allocator, types); + ExpressionExecutor limit_executor(allocator, expr); auto input_size = input.size(); input.SetCardinality(1); limit_executor.Execute(input, limit_chunk); @@ -65373,7 +72418,8 @@ namespace duckdb { //===--------------------------------------------------------------------===// class LimitPercentGlobalState : public GlobalSinkState { public: - explicit LimitPercentGlobalState(const PhysicalLimitPercent &op) : current_offset(0) { + explicit LimitPercentGlobalState(ClientContext &context, const PhysicalLimitPercent &op) + : current_offset(0), data(context, op.GetTypes()) { if (!op.limit_expression) { this->limit_percent = op.limit_percent; is_limit_percent_delimited = true; @@ -65392,14 +72438,14 @@ class LimitPercentGlobalState : public GlobalSinkState { idx_t current_offset; double limit_percent; idx_t offset; - ChunkCollection data; + ColumnDataCollection data; bool is_limit_percent_delimited = false; bool is_offset_delimited = false; }; unique_ptr PhysicalLimitPercent::GetGlobalSinkState(ClientContext &context) const { - return make_unique(*this); + return make_unique(context, *this); } SinkResultType PhysicalLimitPercent::Sink(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate, @@ -65411,7 +72457,7 @@ SinkResultType PhysicalLimitPercent::Sink(ExecutionContext &context, GlobalSinkS // get the next chunk from the child if (!state.is_limit_percent_delimited) { - Value val = PhysicalLimit::GetDelimiter(input, limit_expression.get()); + Value val = PhysicalLimit::GetDelimiter(context, input, limit_expression.get()); if (!val.IsNull()) { limit_percent = val.GetValue(); } @@ -65421,7 +72467,7 @@ SinkResultType PhysicalLimitPercent::Sink(ExecutionContext &context, GlobalSinkS state.is_limit_percent_delimited = true; } if (!state.is_offset_delimited) { - Value val = PhysicalLimit::GetDelimiter(input, offset_expression.get()); + Value val = PhysicalLimit::GetDelimiter(context, input, offset_expression.get()); if (!val.IsNull()) { offset = val.GetValue(); } @@ -65444,23 +72490,26 @@ SinkResultType PhysicalLimitPercent::Sink(ExecutionContext &context, GlobalSinkS //===--------------------------------------------------------------------===// class LimitPercentOperatorState : public GlobalSourceState { public: - LimitPercentOperatorState() : chunk_idx(0), limit(DConstants::INVALID_INDEX), current_offset(0) { + explicit LimitPercentOperatorState(const PhysicalLimitPercent &op) + : limit(DConstants::INVALID_INDEX), current_offset(0) { + auto &gstate = (LimitPercentGlobalState &)*op.sink_state; + gstate.data.InitializeScan(scan_state); } - idx_t chunk_idx; + ColumnDataScanState scan_state; idx_t limit; idx_t current_offset; }; unique_ptr PhysicalLimitPercent::GetGlobalSourceState(ClientContext &context) const { - return make_unique(); + return make_unique(*this); } void PhysicalLimitPercent::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate_p, LocalSourceState &lstate) const { auto &gstate = (LimitPercentGlobalState &)*sink_state; auto &state = (LimitPercentOperatorState &)gstate_p; - auto &limit_percent = gstate.limit_percent; + auto &percent_limit = gstate.limit_percent; auto &offset = gstate.offset; auto &limit = state.limit; auto ¤t_offset = state.current_offset; @@ -65470,21 +72519,28 @@ void PhysicalLimitPercent::GetData(ExecutionContext &context, DataChunk &chunk, if (count > 0) { count += offset; } - limit = MinValue((idx_t)(limit_percent / 100 * count), count); + if (Value::IsNan(percent_limit) || percent_limit < 0 || percent_limit > 100) { + throw OutOfRangeException("Limit percent out of range, should be between 0% and 100%"); + } + double limit_dbl = percent_limit / 100 * count; + if (limit_dbl > count) { + limit = count; + } else { + limit = idx_t(limit_dbl); + } if (limit == 0) { return; } } - if (current_offset >= limit || state.chunk_idx >= gstate.data.ChunkCount()) { + if (current_offset >= limit) { return; } - - DataChunk &input = gstate.data.GetChunk(state.chunk_idx); - state.chunk_idx++; - if (PhysicalLimit::HandleOffset(input, current_offset, 0, limit)) { - chunk.Reference(input); + if (!gstate.data.Scan(state.scan_state, chunk)) { + return; } + + PhysicalLimit::HandleOffset(chunk, current_offset, 0, limit); } } // namespace duckdb @@ -65533,7 +72589,7 @@ struct LoadInfo : public ParseInfo { namespace duckdb { -//! PhysicalVacuum represents an etension LOAD operation +//! PhysicalLoad represents an extension LOAD operation class PhysicalLoad : public PhysicalOperator { public: explicit PhysicalLoad(unique_ptr info, idx_t estimated_cardinality) @@ -65569,14 +72625,27 @@ class DuckDB; enum class ExtensionLoadResult : uint8_t { LOADED_EXTENSION = 0, EXTENSION_UNKNOWN = 1, NOT_LOADED = 2 }; +struct DefaultExtension { + const char *name; + const char *description; + bool statically_loaded; +}; + class ExtensionHelper { public: static void LoadAllExtensions(DuckDB &db); static ExtensionLoadResult LoadExtension(DuckDB &db, const std::string &extension); - static void InstallExtension(DatabaseInstance &db, const string &extension, bool force_install); - static void LoadExternalExtension(DatabaseInstance &db, const string &extension); + static void InstallExtension(ClientContext &context, const string &extension, bool force_install); + static void LoadExternalExtension(ClientContext &context, const string &extension); + + static string ExtensionDirectory(ClientContext &context); + + static idx_t DefaultExtensionCount(); + static DefaultExtension GetDefaultExtension(idx_t index); + + static const vector GetPublicKeys(); private: static const vector PathComponents(); @@ -65592,11 +72661,10 @@ namespace duckdb { void PhysicalLoad::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate_p, LocalSourceState &lstate) const { - auto &db = DatabaseInstance::GetDatabase(context.client); if (info->load_type == LoadType::INSTALL || info->load_type == LoadType::FORCE_INSTALL) { - ExtensionHelper::InstallExtension(db, info->filename, info->load_type == LoadType::FORCE_INSTALL); + ExtensionHelper::InstallExtension(context.client, info->filename, info->load_type == LoadType::FORCE_INSTALL); } else { - ExtensionHelper::LoadExternalExtension(db, info->filename); + ExtensionHelper::LoadExternalExtension(context.client, info->filename); } } @@ -65652,28 +72720,32 @@ PhysicalMaterializedCollector::PhysicalMaterializedCollector(PreparedStatementDa class MaterializedCollectorGlobalState : public GlobalSinkState { public: mutex glock; - unique_ptr result; + unique_ptr collection; + ColumnDataAppendState append_state; + shared_ptr context; }; SinkResultType PhysicalMaterializedCollector::Sink(ExecutionContext &context, GlobalSinkState &gstate_p, LocalSinkState &lstate, DataChunk &input) const { auto &gstate = (MaterializedCollectorGlobalState &)gstate_p; lock_guard lock(gstate.glock); - gstate.result->collection.Append(input); + gstate.collection->Append(gstate.append_state, input); return SinkResultType::NEED_MORE_INPUT; } unique_ptr PhysicalMaterializedCollector::GetGlobalSinkState(ClientContext &context) const { auto state = make_unique(); - state->result = - make_unique(statement_type, properties, types, names, context.shared_from_this()); + state->collection = make_unique(Allocator::DefaultAllocator(), types); + state->collection->InitializeAppend(state->append_state); + state->context = context.shared_from_this(); return move(state); } unique_ptr PhysicalMaterializedCollector::GetResult(GlobalSinkState &state) { auto &gstate = (MaterializedCollectorGlobalState &)state; - D_ASSERT(gstate.result); - return move(gstate.result); + auto result = make_unique(statement_type, properties, names, move(gstate.collection), + gstate.context->GetClientProperties()); + return move(result); } bool PhysicalMaterializedCollector::ParallelSink() const { @@ -65890,8 +72962,7 @@ class BlockingSample { //! The reservoir sample class maintains a streaming sample of fixed size "sample_count" class ReservoirSample : public BlockingSample { public: - ReservoirSample(idx_t sample_count, int64_t seed) : BlockingSample(seed), sample_count(sample_count) { - } + ReservoirSample(Allocator &allocator, idx_t sample_count, int64_t seed); //! Add a chunk of data to the sample void AddToReservoir(DataChunk &input) override; @@ -65919,7 +72990,7 @@ class ReservoirSamplePercentage : public BlockingSample { constexpr static idx_t RESERVOIR_THRESHOLD = 100000; public: - ReservoirSamplePercentage(double percentage, int64_t seed); + ReservoirSamplePercentage(Allocator &allocator, double percentage, int64_t seed); //! Add a chunk of data to the sample void AddToReservoir(DataChunk &input) override; @@ -65932,6 +73003,7 @@ class ReservoirSamplePercentage : public BlockingSample { void Finalize(); private: + Allocator &allocator; //! The sample_size to sample double sample_percentage; //! The fixed sample size of the sub-reservoirs @@ -65956,19 +73028,19 @@ namespace duckdb { //===--------------------------------------------------------------------===// class SampleGlobalSinkState : public GlobalSinkState { public: - explicit SampleGlobalSinkState(SampleOptions &options) { + explicit SampleGlobalSinkState(Allocator &allocator, SampleOptions &options) { if (options.is_percentage) { auto percentage = options.sample_size.GetValue(); if (percentage == 0) { return; } - sample = make_unique(percentage, options.seed); + sample = make_unique(allocator, percentage, options.seed); } else { auto size = options.sample_size.GetValue(); if (size == 0) { return; } - sample = make_unique(size, options.seed); + sample = make_unique(allocator, size, options.seed); } } @@ -65979,7 +73051,7 @@ class SampleGlobalSinkState : public GlobalSinkState { }; unique_ptr PhysicalReservoirSample::GetGlobalSinkState(ClientContext &context) const { - return make_unique(*options); + return make_unique(Allocator::Get(context), *options); } SinkResultType PhysicalReservoirSample::Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, @@ -66024,6 +73096,7 @@ string PhysicalReservoirSample::ParamsToString() const { + namespace duckdb { PhysicalResultCollector::PhysicalResultCollector(PreparedStatementData &data) @@ -66035,11 +73108,15 @@ PhysicalResultCollector::PhysicalResultCollector(PreparedStatementData &data) unique_ptr PhysicalResultCollector::GetResultCollector(ClientContext &context, PreparedStatementData &data) { auto &config = DBConfig::GetConfig(context); - bool use_materialized_collector = !config.preserve_insertion_order || !data.plan->AllSourcesSupportBatchIndex(); - if (use_materialized_collector) { + bool use_materialized_collector = + !config.options.preserve_insertion_order || !data.plan->AllSourcesSupportBatchIndex(); + if (!data.plan->AllOperatorsPreserveOrder()) { + // the plan is not order preserving, so we just use the parallel materialized collector + return make_unique_base(data, true); + } else if (use_materialized_collector) { // parallel materialized collector only if we don't care about maintaining insertion order return make_unique_base( - data, !config.preserve_insertion_order); + data, !config.options.preserve_insertion_order); } else { // we care about maintaining insertion order and the sources all support batch indexes // use a batch collector @@ -66090,10 +73167,93 @@ void PhysicalResultCollector::BuildPipelines(Executor &executor, Pipeline &curre +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/tableref/bound_basetableref.hpp +// +// +//===----------------------------------------------------------------------===// + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/bound_tableref.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + +namespace duckdb { + +class BoundTableRef { +public: + explicit BoundTableRef(TableReferenceType type) : type(type) { + } + virtual ~BoundTableRef() { + } + + //! The type of table reference + TableReferenceType type; + //! The sample options (if any) + unique_ptr sample; +}; +} // namespace duckdb + + + +namespace duckdb { +class TableCatalogEntry; + +//! Represents a TableReference to a base table in the schema +class BoundBaseTableRef : public BoundTableRef { +public: + BoundBaseTableRef(TableCatalogEntry *table, unique_ptr get) + : BoundTableRef(TableReferenceType::BASE_TABLE), table(table), get(move(get)) { + } + + TableCatalogEntry *table; + unique_ptr get; +}; +} // namespace duckdb + + + namespace duckdb { +struct VacuumOptions { + bool vacuum; + bool analyze; +}; + struct VacuumInfo : public ParseInfo { - // nothing for now +public: + explicit VacuumInfo(VacuumOptions options) : options(options), has_table(false), table(nullptr) {}; + + unique_ptr Copy() { + auto result = make_unique(options); + result->has_table = has_table; + if (has_table) { + result->ref = ref->Copy(); + } + return result; + } + + const VacuumOptions options; + +public: + bool has_table; + unique_ptr ref; + TableCatalogEntry *table; + unordered_map column_id_map; + vector columns; }; } // namespace duckdb @@ -66158,7 +73318,7 @@ void PhysicalSet::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSou extension_option.set_function(context.client, scope, target_value); } if (scope == SetScope::GLOBAL) { - config.set_variables[name] = move(target_value); + config.options.set_variables[name] = move(target_value); } else { auto &client_config = ClientConfig::GetConfig(context.client); client_config.set_variables[name] = move(target_value); @@ -66234,7 +73394,7 @@ class StreamingLimitGlobalState : public GlobalOperatorState { std::atomic current_offset; }; -unique_ptr PhysicalStreamingLimit::GetOperatorState(ClientContext &context) const { +unique_ptr PhysicalStreamingLimit::GetOperatorState(ExecutionContext &context) const { return make_unique(*this); } @@ -66250,8 +73410,8 @@ OperatorResultType PhysicalStreamingLimit::Execute(ExecutionContext &context, Da auto &offset = state.offset; idx_t current_offset = gstate.current_offset.fetch_add(input.size()); idx_t max_element; - if (!PhysicalLimit::ComputeOffset(input, limit, offset, current_offset, max_element, limit_expression.get(), - offset_expression.get())) { + if (!PhysicalLimit::ComputeOffset(context, input, limit, offset, current_offset, max_element, + limit_expression.get(), offset_expression.get())) { return OperatorResultType::FINISHED; } if (PhysicalLimit::HandleOffset(input, current_offset, offset, limit)) { @@ -66296,7 +73456,7 @@ class PhysicalStreamingSample : public PhysicalOperator { public: // Operator interface - unique_ptr GetOperatorState(ClientContext &context) const override; + unique_ptr GetOperatorState(ExecutionContext &context) const override; OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const override; @@ -66362,7 +73522,7 @@ void PhysicalStreamingSample::BernoulliSample(DataChunk &input, DataChunk &resul } } -unique_ptr PhysicalStreamingSample::GetOperatorState(ClientContext &context) const { +unique_ptr PhysicalStreamingSample::GetOperatorState(ExecutionContext &context) const { return make_unique(seed); } @@ -66502,33 +73662,444 @@ void PhysicalTransaction::GetData(ExecutionContext &context, DataChunk &chunk, G + namespace duckdb { -//! PhysicalVacuum represents a VACUUM operation (e.g. VACUUM or ANALYZE) +//! PhysicalVacuum represents a VACUUM operation (i.e. VACUUM or ANALYZE) class PhysicalVacuum : public PhysicalOperator { public: - explicit PhysicalVacuum(unique_ptr info, idx_t estimated_cardinality) - : PhysicalOperator(PhysicalOperatorType::VACUUM, {LogicalType::BOOLEAN}, estimated_cardinality), - info(move(info)) { - } + PhysicalVacuum(unique_ptr info, idx_t estimated_cardinality); unique_ptr info; public: + // Source interface void GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, LocalSourceState &lstate) const override; + +public: + // Sink interface + unique_ptr GetLocalSinkState(ExecutionContext &context) const override; + unique_ptr GetGlobalSinkState(ClientContext &context) const override; + + SinkResultType Sink(ExecutionContext &context, GlobalSinkState &gstate_p, LocalSinkState &lstate_p, + DataChunk &input) const override; + void Combine(ExecutionContext &context, GlobalSinkState &gstate_p, LocalSinkState &lstate_p) const override; + SinkFinalizeType Finalize(Pipeline &pipeline, Event &event, ClientContext &context, + GlobalSinkState &gstate) const override; + + bool IsSink() const override { + return info->has_table; + } + + bool ParallelSink() const override { + return IsSink(); + } }; } // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/operator/logical_get.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + namespace duckdb { +//! LogicalGet represents a scan operation from a data source +class LogicalGet : public LogicalOperator { +public: + LogicalGet(idx_t table_index, TableFunction function, unique_ptr bind_data, + vector returned_types, vector returned_names); + + //! The table index in the current bind context + idx_t table_index; + //! The function that is called + TableFunction function; + //! The bind data of the function + unique_ptr bind_data; + //! The types of ALL columns that can be returned by the table function + vector returned_types; + //! The names of ALL columns that can be returned by the table function + vector names; + //! Bound column IDs + vector column_ids; + //! Filters pushed down for table scan + TableFilterSet table_filters; + //! The set of input parameters for the table function + vector parameters; + //! The set of named input parameters for the table function + named_parameter_map_t named_parameters; + //! The set of named input table types for the table-in table-out function + vector input_table_types; + //! The set of named input table names for the table-in table-out function + vector input_table_names; + + string GetName() const override; + string ParamsToString() const override; + //! Returns the underlying table that is being scanned, or nullptr if there is none + TableCatalogEntry *GetTable() const; + +public: + vector GetColumnBindings() override; + idx_t EstimateCardinality(ClientContext &context) override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + +protected: + void ResolveTypes() override; +}; +} // namespace duckdb + + + + +namespace duckdb { + +PhysicalVacuum::PhysicalVacuum(unique_ptr info_p, idx_t estimated_cardinality) + : PhysicalOperator(PhysicalOperatorType::VACUUM, {LogicalType::BOOLEAN}, estimated_cardinality), + info(move(info_p)) { +} + +class VacuumLocalSinkState : public LocalSinkState { +public: + explicit VacuumLocalSinkState(VacuumInfo &info) { + for (idx_t col_idx = 0; col_idx < info.columns.size(); col_idx++) { + column_distinct_stats.push_back(make_unique()); + } + }; + + vector> column_distinct_stats; +}; + +unique_ptr PhysicalVacuum::GetLocalSinkState(ExecutionContext &context) const { + return make_unique(*info); +} + +class VacuumGlobalSinkState : public GlobalSinkState { +public: + explicit VacuumGlobalSinkState(VacuumInfo &info) { + for (idx_t col_idx = 0; col_idx < info.columns.size(); col_idx++) { + column_distinct_stats.push_back(make_unique()); + } + }; + + mutex stats_lock; + vector> column_distinct_stats; +}; + +unique_ptr PhysicalVacuum::GetGlobalSinkState(ClientContext &context) const { + return make_unique(*info); +} + +SinkResultType PhysicalVacuum::Sink(ExecutionContext &context, GlobalSinkState &gstate_p, LocalSinkState &lstate_p, + DataChunk &input) const { + auto &lstate = (VacuumLocalSinkState &)lstate_p; + D_ASSERT(lstate.column_distinct_stats.size() == info->column_id_map.size()); + + for (idx_t col_idx = 0; col_idx < input.data.size(); col_idx++) { + lstate.column_distinct_stats[col_idx]->Update(input.data[col_idx], input.size(), false); + } + + return SinkResultType::NEED_MORE_INPUT; +} + +void PhysicalVacuum::Combine(ExecutionContext &context, GlobalSinkState &gstate_p, LocalSinkState &lstate_p) const { + auto &gstate = (VacuumGlobalSinkState &)gstate_p; + auto &lstate = (VacuumLocalSinkState &)lstate_p; + + lock_guard lock(gstate.stats_lock); + D_ASSERT(gstate.column_distinct_stats.size() == lstate.column_distinct_stats.size()); + for (idx_t col_idx = 0; col_idx < gstate.column_distinct_stats.size(); col_idx++) { + gstate.column_distinct_stats[col_idx]->Merge(*lstate.column_distinct_stats[col_idx]); + } +} + +SinkFinalizeType PhysicalVacuum::Finalize(Pipeline &pipeline, Event &event, ClientContext &context, + GlobalSinkState &gstate) const { + auto &sink = (VacuumGlobalSinkState &)gstate; + + auto table = info->table; + for (idx_t col_idx = 0; col_idx < sink.column_distinct_stats.size(); col_idx++) { + table->storage->SetStatistics(info->column_id_map.at(col_idx), [&](BaseStatistics &stats) { + stats.distinct_stats = move(sink.column_distinct_stats[col_idx]); + }); + } + + return SinkFinalizeType::READY; +} + void PhysicalVacuum::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, LocalSourceState &lstate) const { // NOP } +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/operator/join/outer_join_marker.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/operator/join/physical_comparison_join.hpp +// +// +//===----------------------------------------------------------------------===// + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/operator/join/physical_join.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +//! PhysicalJoin represents the base class of the join operators +class PhysicalJoin : public PhysicalOperator { +public: + PhysicalJoin(LogicalOperator &op, PhysicalOperatorType type, JoinType join_type, idx_t estimated_cardinality); + + JoinType join_type; + +public: + bool EmptyResultIfRHSIsEmpty() const; + + static void ConstructSemiJoinResult(DataChunk &left, DataChunk &result, bool found_match[]); + static void ConstructAntiJoinResult(DataChunk &left, DataChunk &result, bool found_match[]); + static void ConstructMarkJoinResult(DataChunk &join_keys, DataChunk &left, DataChunk &result, bool found_match[], + bool has_null); + +public: + static void BuildJoinPipelines(Executor &executor, Pipeline ¤t, PipelineBuildState &state, + PhysicalOperator &op); + void BuildPipelines(Executor &executor, Pipeline ¤t, PipelineBuildState &state) override; + vector GetSources() const override; +}; + +} // namespace duckdb + + +namespace duckdb { +class ColumnDataCollection; +struct ColumnDataScanState; + +//! PhysicalJoin represents the base class of the join operators +class PhysicalComparisonJoin : public PhysicalJoin { +public: + PhysicalComparisonJoin(LogicalOperator &op, PhysicalOperatorType type, vector cond, + JoinType join_type, idx_t estimated_cardinality); + + vector conditions; + +public: + string ParamsToString() const override; + + //! Construct the join result of a join with an empty RHS + static void ConstructEmptyJoinResult(JoinType type, bool has_null, DataChunk &input, DataChunk &result); + //! Construct the remainder of a Full Outer Join based on which tuples in the RHS found no match + static void ConstructFullOuterJoinResult(bool *found_match, ColumnDataCollection &input, DataChunk &result, + ColumnDataScanState &scan_state); + + bool IsOrderPreserving() const override { + return false; + } +}; + +} // namespace duckdb + + + +namespace duckdb { + +struct OuterJoinGlobalScanState { + mutex lock; + ColumnDataCollection *data = nullptr; + ColumnDataParallelScanState global_scan; +}; + +struct OuterJoinLocalScanState { + DataChunk scan_chunk; + SelectionVector match_sel; + ColumnDataLocalScanState local_scan; +}; + +class OuterJoinMarker { +public: + OuterJoinMarker(bool enabled); + + bool Enabled() { + return enabled; + } + //! Initializes the outer join counter + void Initialize(idx_t count); + //! Resets the outer join counter + void Reset(); + + //! Sets an indiivdual match + void SetMatch(idx_t position); + + //! Sets multiple matches + void SetMatches(const SelectionVector &sel, idx_t count, idx_t base_idx = 0); + + //! Constructs a left-join result based on which tuples have not found matches + void ConstructLeftJoinResult(DataChunk &left, DataChunk &result); + + //! Returns the maximum number of threads that can be associated with an right-outer join scan + idx_t MaxThreads() const; + + //! Initialize a scan + void InitializeScan(ColumnDataCollection &data, OuterJoinGlobalScanState &gstate); + + //! Initialize a local scan + void InitializeScan(OuterJoinGlobalScanState &gstate, OuterJoinLocalScanState &lstate); + + //! Perform the scan + void Scan(OuterJoinGlobalScanState &gstate, OuterJoinLocalScanState &lstate, DataChunk &result); + +private: + bool enabled; + unique_ptr found_match; + idx_t count; +}; + +} // namespace duckdb + + +namespace duckdb { + +OuterJoinMarker::OuterJoinMarker(bool enabled_p) : enabled(enabled_p), count(0) { +} + +void OuterJoinMarker::Initialize(idx_t count_p) { + if (!enabled) { + return; + } + this->count = count_p; + found_match = unique_ptr(new bool[count]); + Reset(); +} + +void OuterJoinMarker::Reset() { + if (!enabled) { + return; + } + memset(found_match.get(), 0, sizeof(bool) * count); +} + +void OuterJoinMarker::SetMatch(idx_t position) { + if (!enabled) { + return; + } + D_ASSERT(position < count); + found_match[position] = true; +} + +void OuterJoinMarker::SetMatches(const SelectionVector &sel, idx_t count, idx_t base_idx) { + if (!enabled) { + return; + } + for (idx_t i = 0; i < count; i++) { + auto idx = sel.get_index(i); + auto pos = base_idx + idx; + D_ASSERT(pos < this->count); + found_match[pos] = true; + } +} + +void OuterJoinMarker::ConstructLeftJoinResult(DataChunk &left, DataChunk &result) { + if (!enabled) { + return; + } + D_ASSERT(count == STANDARD_VECTOR_SIZE); + SelectionVector remaining_sel(STANDARD_VECTOR_SIZE); + idx_t remaining_count = 0; + for (idx_t i = 0; i < left.size(); i++) { + if (!found_match[i]) { + remaining_sel.set_index(remaining_count++, i); + } + } + if (remaining_count > 0) { + result.Slice(left, remaining_sel, remaining_count); + for (idx_t idx = left.ColumnCount(); idx < result.ColumnCount(); idx++) { + result.data[idx].SetVectorType(VectorType::CONSTANT_VECTOR); + ConstantVector::SetNull(result.data[idx], true); + } + } +} + +idx_t OuterJoinMarker::MaxThreads() const { + return count / (STANDARD_VECTOR_SIZE * 10); +} + +void OuterJoinMarker::InitializeScan(ColumnDataCollection &data, OuterJoinGlobalScanState &gstate) { + gstate.data = &data; + data.InitializeScan(gstate.global_scan); +} + +void OuterJoinMarker::InitializeScan(OuterJoinGlobalScanState &gstate, OuterJoinLocalScanState &lstate) { + D_ASSERT(gstate.data); + lstate.match_sel.Initialize(STANDARD_VECTOR_SIZE); + gstate.data->InitializeScanChunk(lstate.scan_chunk); +} + +void OuterJoinMarker::Scan(OuterJoinGlobalScanState &gstate, OuterJoinLocalScanState &lstate, DataChunk &result) { + D_ASSERT(gstate.data); + // fill in NULL values for the LHS + while (gstate.data->Scan(gstate.global_scan, lstate.local_scan, lstate.scan_chunk)) { + idx_t result_count = 0; + // figure out which tuples didn't find a match in the RHS + for (idx_t i = 0; i < lstate.scan_chunk.size(); i++) { + if (!found_match[lstate.local_scan.current_row_index + i]) { + lstate.match_sel.set_index(result_count++, i); + } + } + if (result_count > 0) { + // if there were any tuples that didn't find a match, output them + idx_t left_column_count = result.ColumnCount() - lstate.scan_chunk.ColumnCount(); + for (idx_t i = 0; i < left_column_count; i++) { + result.data[i].SetVectorType(VectorType::CONSTANT_VECTOR); + ConstantVector::SetNull(result.data[i], true); + } + for (idx_t col_idx = left_column_count; col_idx < result.ColumnCount(); col_idx++) { + result.data[col_idx].Slice(lstate.scan_chunk.data[col_idx - left_column_count], lstate.match_sel, + result_count); + } + result.SetCardinality(result_count); + return; + } + } +} + } // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -66547,8 +74118,8 @@ void PhysicalVacuum::GetData(ExecutionContext &context, DataChunk &chunk, Global namespace duckdb { -class PhysicalHashJoinState; -class HashJoinGlobalState; +class HashJoinOperatorState; +class HashJoinGlobalSinkState; class PhysicalHashJoin; struct PerfectHashJoinStats { @@ -66573,7 +74144,7 @@ class PerfectHashJoinExecutor { public: bool CanDoPerfectHashJoin(); - unique_ptr GetOperatorState(ClientContext &context); + unique_ptr GetOperatorState(ExecutionContext &context); OperatorResultType ProbePerfectHashTable(ExecutionContext &context, DataChunk &input, DataChunk &chunk, OperatorState &state); bool BuildPerfectHashTable(LogicalType &type); @@ -66623,85 +74194,16 @@ class PerfectHashJoinExecutor { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/operator/join/physical_comparison_join.hpp -// -// -//===----------------------------------------------------------------------===// - - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/operator/join/physical_join.hpp -// -// -//===----------------------------------------------------------------------===// - - namespace duckdb { -//! PhysicalJoin represents the base class of the join operators -class PhysicalJoin : public PhysicalOperator { -public: - PhysicalJoin(LogicalOperator &op, PhysicalOperatorType type, JoinType join_type, idx_t estimated_cardinality); - - JoinType join_type; - -public: - bool EmptyResultIfRHSIsEmpty() const; - - static void ConstructSemiJoinResult(DataChunk &left, DataChunk &result, bool found_match[]); - static void ConstructAntiJoinResult(DataChunk &left, DataChunk &result, bool found_match[]); - static void ConstructMarkJoinResult(DataChunk &join_keys, DataChunk &left, DataChunk &result, bool found_match[], - bool has_null); - static void ConstructLeftJoinResult(DataChunk &left, DataChunk &result, bool found_match[]); - -public: - static void BuildJoinPipelines(Executor &executor, Pipeline ¤t, PipelineBuildState &state, - PhysicalOperator &op); - void BuildPipelines(Executor &executor, Pipeline ¤t, PipelineBuildState &state) override; - vector GetSources() const override; -}; - -} // namespace duckdb - - - -namespace duckdb { -class ChunkCollection; - -//! PhysicalJoin represents the base class of the join operators -class PhysicalComparisonJoin : public PhysicalJoin { -public: - PhysicalComparisonJoin(LogicalOperator &op, PhysicalOperatorType type, vector cond, - JoinType join_type, idx_t estimated_cardinality); - - vector conditions; - -public: - string ParamsToString() const override; - - //! Construct the join result of a join with an empty RHS - static void ConstructEmptyJoinResult(JoinType type, bool has_null, DataChunk &input, DataChunk &result); - //! Construct the remainder of a Full Outer Join based on which tuples in the RHS found no match - static void ConstructFullOuterJoinResult(bool *found_match, ChunkCollection &input, DataChunk &result, - idx_t &scan_position); -}; - -} // namespace duckdb - - - +class HashJoinGlobalSinkState; -namespace duckdb { +class HashJoinLocalSourceState; +class HashJoinGlobalSourceState; //! PhysicalHashJoin represents a hash loop join between two tables class PhysicalHashJoin : public PhysicalComparisonJoin { @@ -66714,6 +74216,9 @@ class PhysicalHashJoin : public PhysicalComparisonJoin { vector cond, JoinType join_type, idx_t estimated_cardinality, PerfectHashJoinStats join_state); + //! Initialize HT for this operator + unique_ptr InitializeHashTable(ClientContext &context) const; + vector right_projection_map; //! The types of the keys vector condition_types; @@ -66721,12 +74226,14 @@ class PhysicalHashJoin : public PhysicalComparisonJoin { vector build_types; //! Duplicate eliminated types; only used for delim_joins (i.e. correlated subqueries) vector delim_types; - // used in perfect hash join + //! Used in perfect hash join PerfectHashJoinStats perfect_join_statistics; + //! Whether we can go external (can't yet if recursive CTE or full outer TODO) + bool can_go_external; public: // Operator Interface - unique_ptr GetOperatorState(ClientContext &context) const override; + unique_ptr GetOperatorState(ExecutionContext &context) const override; OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const override; @@ -66741,12 +74248,16 @@ class PhysicalHashJoin : public PhysicalComparisonJoin { public: // Source interface unique_ptr GetGlobalSourceState(ClientContext &context) const override; + unique_ptr GetLocalSourceState(ExecutionContext &context, + GlobalSourceState &gstate) const override; void GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, LocalSourceState &lstate) const override; + //! Becomes a source when it is an external join bool IsSource() const override { - return IsRightOuterJoin(join_type); + return true; } + bool ParallelSource() const override { return true; } @@ -66830,8 +74341,7 @@ bool PerfectHashJoinExecutor::FullScanHashTable(JoinHTScanState &state, LogicalT auto &vector = perfect_hash_table[i]; D_ASSERT(vector.GetType() == ht.build_types[i]); const auto col_no = ht.condition_types.size() + i; - const auto col_offset = ht.layout.GetOffsets()[col_no]; - RowOperations::Gather(tuples_addresses, sel_tuples, vector, sel_build, keys_count, col_offset, col_no, + RowOperations::Gather(tuples_addresses, sel_tuples, vector, sel_build, keys_count, ht.layout, col_no, build_size); } return true; @@ -66869,8 +74379,8 @@ bool PerfectHashJoinExecutor::TemplatedFillSelectionVectorBuild(Vector &source, } auto min_value = perfect_join_statistics.build_min.GetValueUnsafe(); auto max_value = perfect_join_statistics.build_max.GetValueUnsafe(); - VectorData vector_data; - source.Orrify(count, vector_data); + UnifiedVectorFormat vector_data; + source.ToUnifiedFormat(count, vector_data); auto data = reinterpret_cast(vector_data.data); // generate the selection vector for (idx_t i = 0, sel_idx = 0; i < count; ++i) { @@ -66897,6 +74407,16 @@ bool PerfectHashJoinExecutor::TemplatedFillSelectionVectorBuild(Vector &source, //===--------------------------------------------------------------------===// class PerfectHashJoinState : public OperatorState { public: + PerfectHashJoinState(Allocator &allocator, const PhysicalHashJoin &join) : probe_executor(allocator) { + join_keys.Initialize(allocator, join.condition_types); + for (auto &cond : join.conditions) { + probe_executor.AddExpression(*cond.left); + } + build_sel_vec.Initialize(STANDARD_VECTOR_SIZE); + probe_sel_vec.Initialize(STANDARD_VECTOR_SIZE); + seq_sel_vec.Initialize(STANDARD_VECTOR_SIZE); + } + DataChunk join_keys; ExpressionExecutor probe_executor; SelectionVector build_sel_vec; @@ -66904,15 +74424,8 @@ class PerfectHashJoinState : public OperatorState { SelectionVector seq_sel_vec; }; -unique_ptr PerfectHashJoinExecutor::GetOperatorState(ClientContext &context) { - auto state = make_unique(); - state->join_keys.Initialize(join.condition_types); - for (auto &cond : join.conditions) { - state->probe_executor.AddExpression(*cond.left); - } - state->build_sel_vec.Initialize(STANDARD_VECTOR_SIZE); - state->probe_sel_vec.Initialize(STANDARD_VECTOR_SIZE); - state->seq_sel_vec.Initialize(STANDARD_VECTOR_SIZE); +unique_ptr PerfectHashJoinExecutor::GetOperatorState(ExecutionContext &context) { + auto state = make_unique(Allocator::Get(context.client), join); return move(state); } @@ -66989,8 +74502,8 @@ void PerfectHashJoinExecutor::TemplatedFillSelectionVectorProbe(Vector &source, auto min_value = perfect_join_statistics.build_min.GetValueUnsafe(); auto max_value = perfect_join_statistics.build_max.GetValueUnsafe(); - VectorData vector_data; - source.Orrify(count, vector_data); + UnifiedVectorFormat vector_data; + source.ToUnifiedFormat(count, vector_data); auto data = reinterpret_cast(vector_data.data); auto validity_mask = &vector_data.validity; // build selection vector for non-dense build @@ -67060,7 +74573,7 @@ class PhysicalBlockwiseNLJoin : public PhysicalJoin { public: // Operator Interface - unique_ptr GetOperatorState(ClientContext &context) const override; + unique_ptr GetOperatorState(ExecutionContext &context) const override; OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const override; @@ -67075,6 +74588,8 @@ class PhysicalBlockwiseNLJoin : public PhysicalJoin { public: // Source interface unique_ptr GetGlobalSourceState(ClientContext &context) const override; + unique_ptr GetLocalSourceState(ExecutionContext &context, + GlobalSourceState &gstate) const override; void GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, LocalSourceState &lstate) const override; @@ -67088,7 +74603,6 @@ class PhysicalBlockwiseNLJoin : public PhysicalJoin { public: // Sink interface unique_ptr GetGlobalSinkState(ClientContext &context) const override; - unique_ptr GetLocalSinkState(ExecutionContext &context) const override; SinkResultType Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, DataChunk &input) const override; @@ -67113,6 +74627,95 @@ class PhysicalBlockwiseNLJoin : public PhysicalJoin { + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/operator/join/physical_cross_product.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +//! PhysicalCrossProduct represents a cross product between two tables +class PhysicalCrossProduct : public PhysicalOperator { +public: + PhysicalCrossProduct(vector types, unique_ptr left, + unique_ptr right, idx_t estimated_cardinality); + +public: + // Operator Interface + unique_ptr GetOperatorState(ExecutionContext &context) const override; + OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, + GlobalOperatorState &gstate, OperatorState &state) const override; + + bool ParallelOperator() const override { + return true; + } + + bool RequiresCache() const override { + return true; + } + +public: + // Sink Interface + unique_ptr GetGlobalSinkState(ClientContext &context) const override; + SinkResultType Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, + DataChunk &input) const override; + + bool IsSink() const override { + return true; + } + bool ParallelSink() const override { + return true; + } + +public: + void BuildPipelines(Executor &executor, Pipeline ¤t, PipelineBuildState &state) override; + vector GetSources() const override; +}; + +class CrossProductExecutor { +public: + CrossProductExecutor(ColumnDataCollection &rhs); + + OperatorResultType Execute(DataChunk &input, DataChunk &output); + + bool ScanLHS() { + return scan_input_chunk; + } + + idx_t PositionInChunk() { + return position_in_chunk; + } + + idx_t ScanPosition() { + return scan_state.current_row_index; + } + +private: + void Reset(DataChunk &input, DataChunk &output); + bool NextValue(DataChunk &input, DataChunk &output); + +private: + ColumnDataCollection &rhs; + ColumnDataScanState scan_state; + DataChunk scan_chunk; + idx_t position_in_chunk; + bool initialized; + bool finished; + bool scan_input_chunk; +}; + +} // namespace duckdb + + namespace duckdb { PhysicalBlockwiseNLJoin::PhysicalBlockwiseNLJoin(LogicalOperator &op, unique_ptr left, @@ -67138,14 +74741,17 @@ class BlockwiseNLJoinLocalState : public LocalSinkState { class BlockwiseNLJoinGlobalState : public GlobalSinkState { public: + explicit BlockwiseNLJoinGlobalState(ClientContext &context, const PhysicalBlockwiseNLJoin &op) + : right_chunks(context, op.children[1]->GetTypes()), right_outer(IsRightOuterJoin(op.join_type)) { + } + mutex lock; - ChunkCollection right_chunks; - //! Whether or not a tuple on the RHS has found a match, only used for FULL OUTER joins - unique_ptr rhs_found_match; + ColumnDataCollection right_chunks; + OuterJoinMarker right_outer; }; unique_ptr PhysicalBlockwiseNLJoin::GetGlobalSinkState(ClientContext &context) const { - return make_unique(); + return make_unique(context, *this); } unique_ptr PhysicalBlockwiseNLJoin::GetLocalSinkState(ExecutionContext &context) const { @@ -67166,10 +74772,8 @@ SinkResultType PhysicalBlockwiseNLJoin::Sink(ExecutionContext &context, GlobalSi SinkFinalizeType PhysicalBlockwiseNLJoin::Finalize(Pipeline &pipeline, Event &event, ClientContext &context, GlobalSinkState &gstate_p) const { auto &gstate = (BlockwiseNLJoinGlobalState &)gstate_p; - if (IsRightOuterJoin(join_type)) { - gstate.rhs_found_match = unique_ptr(new bool[gstate.right_chunks.Count()]); - memset(gstate.rhs_found_match.get(), 0, sizeof(bool) * gstate.right_chunks.Count()); - } + gstate.right_outer.Initialize(gstate.right_chunks.Count()); + if (gstate.right_chunks.Count() == 0 && EmptyResultIfRHSIsEmpty()) { return SinkFinalizeType::NO_OUTPUT_POSSIBLE; } @@ -67181,23 +74785,22 @@ SinkFinalizeType PhysicalBlockwiseNLJoin::Finalize(Pipeline &pipeline, Event &ev //===--------------------------------------------------------------------===// class BlockwiseNLJoinState : public OperatorState { public: - explicit BlockwiseNLJoinState(const PhysicalBlockwiseNLJoin &op) - : left_position(0), right_position(0), executor(*op.condition) { - if (IsLeftOuterJoin(op.join_type)) { - left_found_match = unique_ptr(new bool[STANDARD_VECTOR_SIZE]); - memset(left_found_match.get(), 0, sizeof(bool) * STANDARD_VECTOR_SIZE); - } + explicit BlockwiseNLJoinState(ExecutionContext &context, ColumnDataCollection &rhs, + const PhysicalBlockwiseNLJoin &op) + : cross_product(rhs), left_outer(IsLeftOuterJoin(op.join_type)), match_sel(STANDARD_VECTOR_SIZE), + executor(Allocator::Get(context.client), *op.condition) { + left_outer.Initialize(STANDARD_VECTOR_SIZE); } - //! Whether or not a tuple on the LHS has found a match, only used for LEFT OUTER and FULL OUTER joins - unique_ptr left_found_match; - idx_t left_position; - idx_t right_position; + CrossProductExecutor cross_product; + OuterJoinMarker left_outer; + SelectionVector match_sel; ExpressionExecutor executor; }; -unique_ptr PhysicalBlockwiseNLJoin::GetOperatorState(ClientContext &context) const { - return make_unique(*this); +unique_ptr PhysicalBlockwiseNLJoin::GetOperatorState(ExecutionContext &context) const { + auto &gstate = (BlockwiseNLJoinGlobalState &)*sink_state; + return make_unique(context, gstate.right_chunks, *this); } OperatorResultType PhysicalBlockwiseNLJoin::Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, @@ -67217,69 +74820,42 @@ OperatorResultType PhysicalBlockwiseNLJoin::Execute(ExecutionContext &context, D } // now perform the actual join - // we construct a combined DataChunk by referencing the LHS and the RHS - // every step that we do not have output results we shift the vectors of the RHS one up or down - // this creates a new "alignment" between the tuples, exhausting all possible O(n^2) combinations - // while allowing us to use vectorized execution for every step + // we perform a cross product, then execute the expression directly on the cross product' result idx_t result_count = 0; do { - if (state.left_position >= input.size()) { - // exhausted LHS, have to pull new LHS chunk - if (state.left_found_match) { + auto result = state.cross_product.Execute(input, chunk); + if (result == OperatorResultType::NEED_MORE_INPUT) { + // exhausted input, have to pull new LHS chunk + if (state.left_outer.Enabled()) { // left join: before we move to the next chunk, see if we need to output any vectors that didn't // have a match found - PhysicalJoin::ConstructLeftJoinResult(input, chunk, state.left_found_match.get()); - memset(state.left_found_match.get(), 0, sizeof(bool) * STANDARD_VECTOR_SIZE); + state.left_outer.ConstructLeftJoinResult(input, chunk); + state.left_outer.Reset(); } - state.left_position = 0; - state.right_position = 0; return OperatorResultType::NEED_MORE_INPUT; } - auto &lchunk = input; - auto &rchunk = gstate.right_chunks.GetChunk(state.right_position); - - // fill in the current element of the LHS into the chunk - D_ASSERT(chunk.ColumnCount() == lchunk.ColumnCount() + rchunk.ColumnCount()); - for (idx_t i = 0; i < lchunk.ColumnCount(); i++) { - ConstantVector::Reference(chunk.data[i], lchunk.data[i], state.left_position, lchunk.size()); - } - // for the RHS we just reference the entire vector - for (idx_t i = 0; i < rchunk.ColumnCount(); i++) { - chunk.data[lchunk.ColumnCount() + i].Reference(rchunk.data[i]); - } - chunk.SetCardinality(rchunk.size()); // now perform the computation - SelectionVector match_sel(STANDARD_VECTOR_SIZE); - result_count = state.executor.SelectExpression(chunk, match_sel); + result_count = state.executor.SelectExpression(chunk, state.match_sel); if (result_count > 0) { // found a match! - // set the match flags in the LHS - if (state.left_found_match) { - state.left_found_match[state.left_position] = true; - } - // set the match flags in the RHS - if (gstate.rhs_found_match) { - for (idx_t i = 0; i < result_count; i++) { - auto idx = match_sel.get_index(i); - gstate.rhs_found_match[state.right_position * STANDARD_VECTOR_SIZE + idx] = true; - } + // check if the cross product is scanning the LHS or the RHS in its entirety + if (!state.cross_product.ScanLHS()) { + // set the match flags in the LHS + state.left_outer.SetMatches(state.match_sel, result_count); + // set the match flag in the RHS + gstate.right_outer.SetMatch(state.cross_product.ScanPosition() + state.cross_product.PositionInChunk()); + } else { + // set the match flag in the LHS + state.left_outer.SetMatch(state.cross_product.PositionInChunk()); + // set the match flags in the RHS + gstate.right_outer.SetMatches(state.match_sel, result_count, state.cross_product.ScanPosition()); } - chunk.Slice(match_sel, result_count); + chunk.Slice(state.match_sel, result_count); } else { // no result: reset the chunk chunk.Reset(); } - // move to the next tuple on the LHS - state.left_position++; - if (state.left_position >= input.size()) { - // exhausted the current chunk, move to the next RHS chunk - state.right_position++; - if (state.right_position < gstate.right_chunks.ChunkCount()) { - // we still have chunks left! start over on the LHS - state.left_position = 0; - } - } } while (result_count == 0); return OperatorResultType::HAVE_MORE_OUTPUT; } @@ -67293,39 +74869,54 @@ string PhysicalBlockwiseNLJoin::ParamsToString() const { //===--------------------------------------------------------------------===// // Source //===--------------------------------------------------------------------===// -class BlockwiseNLJoinScanState : public GlobalSourceState { +class BlockwiseNLJoinGlobalScanState : public GlobalSourceState { public: - explicit BlockwiseNLJoinScanState(const PhysicalBlockwiseNLJoin &op) : op(op), right_outer_position(0) { + explicit BlockwiseNLJoinGlobalScanState(const PhysicalBlockwiseNLJoin &op) : op(op) { + D_ASSERT(op.sink_state); + auto &sink = (BlockwiseNLJoinGlobalState &)*op.sink_state; + sink.right_outer.InitializeScan(sink.right_chunks, scan_state); } - mutex lock; const PhysicalBlockwiseNLJoin &op; - //! The position in the RHS in the final scan of the FULL OUTER JOIN - idx_t right_outer_position; + OuterJoinGlobalScanState scan_state; public: idx_t MaxThreads() override { auto &sink = (BlockwiseNLJoinGlobalState &)*op.sink_state; - return sink.right_chunks.Count() / (STANDARD_VECTOR_SIZE * 10); + return sink.right_outer.MaxThreads(); } }; +class BlockwiseNLJoinLocalScanState : public LocalSourceState { +public: + explicit BlockwiseNLJoinLocalScanState(const PhysicalBlockwiseNLJoin &op, BlockwiseNLJoinGlobalScanState &gstate) { + D_ASSERT(op.sink_state); + auto &sink = (BlockwiseNLJoinGlobalState &)*op.sink_state; + sink.right_outer.InitializeScan(gstate.scan_state, scan_state); + } + + OuterJoinLocalScanState scan_state; +}; + unique_ptr PhysicalBlockwiseNLJoin::GetGlobalSourceState(ClientContext &context) const { - return make_unique(*this); + return make_unique(*this); } -void PhysicalBlockwiseNLJoin::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, - LocalSourceState &lstate) const { +unique_ptr PhysicalBlockwiseNLJoin::GetLocalSourceState(ExecutionContext &context, + GlobalSourceState &gstate) const { + return make_unique(*this, (BlockwiseNLJoinGlobalScanState &)gstate); +} + +void PhysicalBlockwiseNLJoin::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate_p, + LocalSourceState &lstate_p) const { D_ASSERT(IsRightOuterJoin(join_type)); // check if we need to scan any unmatched tuples from the RHS for the full/right outer join auto &sink = (BlockwiseNLJoinGlobalState &)*sink_state; - auto &state = (BlockwiseNLJoinScanState &)gstate; + auto &gstate = (BlockwiseNLJoinGlobalScanState &)gstate_p; + auto &lstate = (BlockwiseNLJoinLocalScanState &)lstate_p; - // if the LHS is exhausted in a FULL/RIGHT OUTER JOIN, we scan the found_match for any chunks we - // still need to output - lock_guard l(state.lock); - PhysicalComparisonJoin::ConstructFullOuterJoinResult(sink.rhs_found_match.get(), sink.right_chunks, chunk, - state.right_outer_position); + // if the LHS is exhausted in a FULL/RIGHT OUTER JOIN, we scan chunks we still need to output + sink.right_outer.Scan(gstate.scan_state, lstate.scan_state, chunk); } } // namespace duckdb @@ -67360,6 +74951,8 @@ string PhysicalComparisonJoin::ParamsToString() const { string op = ExpressionTypeToOperator(it.comparison); extra_info += it.left->GetName() + " " + op + " " + it.right->GetName() + "\n"; } + extra_info += "\nEC = " + std::to_string(estimated_props->GetCardinality()) + "\n"; + extra_info += "COST = " + std::to_string(estimated_props->GetCost()) + "\n"; return extra_info; } @@ -67408,90 +75001,6 @@ void PhysicalComparisonJoin::ConstructEmptyJoinResult(JoinType join_type, bool h } } } - -void PhysicalComparisonJoin::ConstructFullOuterJoinResult(bool *found_match, ChunkCollection &input, DataChunk &result, - idx_t &scan_position) { - // fill in NULL values for the LHS - SelectionVector rsel(STANDARD_VECTOR_SIZE); - while (scan_position < input.Count()) { - auto &rhs_chunk = input.GetChunk(scan_position / STANDARD_VECTOR_SIZE); - idx_t result_count = 0; - // figure out which tuples didn't find a match in the RHS - for (idx_t i = 0; i < rhs_chunk.size(); i++) { - if (!found_match[scan_position + i]) { - rsel.set_index(result_count++, i); - } - } - scan_position += STANDARD_VECTOR_SIZE; - if (result_count > 0) { - // if there were any tuples that didn't find a match, output them - idx_t left_column_count = result.ColumnCount() - input.ColumnCount(); - for (idx_t i = 0; i < left_column_count; i++) { - result.data[i].SetVectorType(VectorType::CONSTANT_VECTOR); - ConstantVector::SetNull(result.data[i], true); - } - for (idx_t col_idx = 0; col_idx < rhs_chunk.ColumnCount(); col_idx++) { - result.data[left_column_count + col_idx].Slice(rhs_chunk.data[col_idx], rsel, result_count); - } - result.SetCardinality(result_count); - return; - } - } -} - -} // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/operator/join/physical_cross_product.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { -//! PhysicalCrossProduct represents a cross product between two tables -class PhysicalCrossProduct : public PhysicalOperator { -public: - PhysicalCrossProduct(vector types, unique_ptr left, - unique_ptr right, idx_t estimated_cardinality); - -public: - // Operator Interface - unique_ptr GetOperatorState(ClientContext &context) const override; - OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, - GlobalOperatorState &gstate, OperatorState &state) const override; - - bool ParallelOperator() const override { - return true; - } - - bool RequiresCache() const override { - return true; - } - -public: - // Sink Interface - unique_ptr GetGlobalSinkState(ClientContext &context) const override; - SinkResultType Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, - DataChunk &input) const override; - - bool IsSink() const override { - return true; - } - bool ParallelSink() const override { - return true; - } - -public: - void BuildPipelines(Executor &executor, Pipeline ¤t, PipelineBuildState &state) override; - vector GetSources() const override; -}; - } // namespace duckdb @@ -67512,78 +75021,121 @@ PhysicalCrossProduct::PhysicalCrossProduct(vector types, unique_ptr //===--------------------------------------------------------------------===// class CrossProductGlobalState : public GlobalSinkState { public: - CrossProductGlobalState() { + explicit CrossProductGlobalState(ClientContext &context, const PhysicalCrossProduct &op) + : rhs_materialized(context, op.children[1]->GetTypes()) { + rhs_materialized.InitializeAppend(append_state); } - ChunkCollection rhs_materialized; + ColumnDataCollection rhs_materialized; + ColumnDataAppendState append_state; mutex rhs_lock; }; unique_ptr PhysicalCrossProduct::GetGlobalSinkState(ClientContext &context) const { - return make_unique(); + return make_unique(context, *this); } SinkResultType PhysicalCrossProduct::Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate_p, DataChunk &input) const { auto &sink = (CrossProductGlobalState &)state; lock_guard client_guard(sink.rhs_lock); - sink.rhs_materialized.Append(input); + sink.rhs_materialized.Append(sink.append_state, input); return SinkResultType::NEED_MORE_INPUT; } //===--------------------------------------------------------------------===// // Operator //===--------------------------------------------------------------------===// -class CrossProductOperatorState : public OperatorState { -public: - CrossProductOperatorState() : right_position(0) { - } - - idx_t right_position; -}; +CrossProductExecutor::CrossProductExecutor(ColumnDataCollection &rhs) + : rhs(rhs), position_in_chunk(0), initialized(false), finished(false) { + rhs.InitializeScanChunk(scan_chunk); +} -unique_ptr PhysicalCrossProduct::GetOperatorState(ClientContext &context) const { - return make_unique(); +void CrossProductExecutor::Reset(DataChunk &input, DataChunk &output) { + initialized = true; + finished = false; + scan_input_chunk = false; + rhs.InitializeScan(scan_state); + position_in_chunk = 0; + scan_chunk.Reset(); } -OperatorResultType PhysicalCrossProduct::Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, - GlobalOperatorState &gstate, OperatorState &state_p) const { - auto &state = (CrossProductOperatorState &)state_p; - auto &sink = (CrossProductGlobalState &)*sink_state; - auto &right_collection = sink.rhs_materialized; +bool CrossProductExecutor::NextValue(DataChunk &input, DataChunk &output) { + if (!initialized) { + // not initialized yet: initialize the scan + Reset(input, output); + } + position_in_chunk++; + idx_t chunk_size = scan_input_chunk ? input.size() : scan_chunk.size(); + if (position_in_chunk < chunk_size) { + return true; + } + // fetch the next chunk + rhs.Scan(scan_state, scan_chunk); + position_in_chunk = 0; + if (scan_chunk.size() == 0) { + return false; + } + // the way the cross product works is that we keep one chunk constantly referenced + // while iterating over the other chunk one value at a time + // the second one is the chunk we are "scanning" - if (sink.rhs_materialized.Count() == 0) { + // for the engine, it is better if we emit larger chunks + // hence the chunk that we keep constantly referenced should be the larger of the two + scan_input_chunk = input.size() < scan_chunk.size(); + return true; +} + +OperatorResultType CrossProductExecutor::Execute(DataChunk &input, DataChunk &output) { + if (rhs.Count() == 0) { // no RHS: empty result return OperatorResultType::FINISHED; } - if (state.right_position >= right_collection.Count()) { + if (!NextValue(input, output)) { // ran out of entries on the RHS // reset the RHS and move to the next chunk on the LHS - state.right_position = 0; + initialized = false; return OperatorResultType::NEED_MORE_INPUT; } - auto &left_chunk = input; - // now match the current vector of the left relation with the current row - // from the right relation - chunk.SetCardinality(left_chunk.size()); - // create a reference to the vectors of the left column - for (idx_t i = 0; i < left_chunk.ColumnCount(); i++) { - chunk.data[i].Reference(left_chunk.data[i]); - } - // duplicate the values on the right side - auto &right_chunk = right_collection.GetChunkForRow(state.right_position); - auto row_in_chunk = state.right_position % STANDARD_VECTOR_SIZE; - for (idx_t i = 0; i < right_collection.ColumnCount(); i++) { - ConstantVector::Reference(chunk.data[left_chunk.ColumnCount() + i], right_chunk.data[i], row_in_chunk, - right_chunk.size()); + // set up the constant chunk + auto &constant_chunk = scan_input_chunk ? scan_chunk : input; + auto col_count = constant_chunk.ColumnCount(); + auto col_offset = scan_input_chunk ? input.ColumnCount() : 0; + output.SetCardinality(constant_chunk.size()); + for (idx_t i = 0; i < col_count; i++) { + output.data[col_offset + i].Reference(constant_chunk.data[i]); } - // for the next iteration, move to the next position on the right side - state.right_position++; + // for the chunk that we are scanning, scan a single value from that chunk + auto &scan = scan_input_chunk ? input : scan_chunk; + col_count = scan.ColumnCount(); + col_offset = scan_input_chunk ? 0 : input.ColumnCount(); + for (idx_t i = 0; i < col_count; i++) { + ConstantVector::Reference(output.data[col_offset + i], scan.data[i], position_in_chunk, scan.size()); + } return OperatorResultType::HAVE_MORE_OUTPUT; } +class CrossProductOperatorState : public OperatorState { +public: + explicit CrossProductOperatorState(ColumnDataCollection &rhs) : executor(rhs) { + } + + CrossProductExecutor executor; +}; + +unique_ptr PhysicalCrossProduct::GetOperatorState(ExecutionContext &context) const { + auto &sink = (CrossProductGlobalState &)*sink_state; + return make_unique(sink.rhs_materialized); +} + +OperatorResultType PhysicalCrossProduct::Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, + GlobalOperatorState &gstate, OperatorState &state_p) const { + auto &state = (CrossProductOperatorState &)state_p; + return state.executor.Execute(input, chunk); +} + //===--------------------------------------------------------------------===// // Pipeline Construction //===--------------------------------------------------------------------===// @@ -67599,44 +75151,6 @@ vector PhysicalCrossProduct::GetSources() const { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/operator/scan/physical_chunk_scan.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { - -//! The PhysicalChunkCollectionScan scans a Chunk Collection -class PhysicalChunkScan : public PhysicalOperator { -public: - PhysicalChunkScan(vector types, PhysicalOperatorType op_type, idx_t estimated_cardinality) - : PhysicalOperator(op_type, move(types), estimated_cardinality), collection(nullptr) { - } - - // the chunk collection to scan - ChunkCollection *collection; - //! Owned chunk collection, if any - unique_ptr owned_collection; - -public: - unique_ptr GetGlobalSourceState(ClientContext &context) const override; - void GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, - LocalSourceState &lstate) const override; - -public: - void BuildPipelines(Executor &executor, Pipeline ¤t, PipelineBuildState &state) override; -}; - -} // namespace duckdb - //===----------------------------------------------------------------------===// // DuckDB @@ -67650,6 +75164,7 @@ class PhysicalChunkScan : public PhysicalOperator { + namespace duckdb { class Pipeline; class RecursiveCTEState; @@ -67661,7 +75176,7 @@ class PhysicalRecursiveCTE : public PhysicalOperator { ~PhysicalRecursiveCTE() override; bool union_all; - std::shared_ptr working_table; + std::shared_ptr working_table; vector> pipelines; public: @@ -67697,6 +75212,45 @@ class PhysicalRecursiveCTE : public PhysicalOperator { +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/operator/scan/physical_column_data_scan.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +//! The PhysicalColumnDataScan scans a ColumnDataCollection +class PhysicalColumnDataScan : public PhysicalOperator { +public: + PhysicalColumnDataScan(vector types, PhysicalOperatorType op_type, idx_t estimated_cardinality) + : PhysicalOperator(op_type, move(types), estimated_cardinality), collection(nullptr) { + } + + // the column data collection to scan + ColumnDataCollection *collection; + //! Owned column data collection, if any + unique_ptr owned_collection; + +public: + unique_ptr GetGlobalSourceState(ClientContext &context) const override; + void GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, + LocalSourceState &lstate) const override; + +public: + void BuildPipelines(Executor &executor, Pipeline ¤t, PipelineBuildState &state) override; +}; + +} // namespace duckdb + + namespace duckdb { PhysicalDelimJoin::PhysicalDelimJoin(vector types, unique_ptr original_join, @@ -67708,10 +75262,10 @@ PhysicalDelimJoin::PhysicalDelimJoin(vector types, unique_ptrchildren[0])); - // we replace it with a PhysicalChunkCollectionScan, that scans the ChunkCollection that we keep cached + // we replace it with a PhysicalColumnDataScan, that scans the ColumnDataCollection that we keep cached // the actual chunk collection to scan will be created in the DelimJoinGlobalState - auto cached_chunk_scan = make_unique(children[0]->GetTypes(), PhysicalOperatorType::CHUNK_SCAN, - estimated_cardinality); + auto cached_chunk_scan = make_unique( + children[0]->GetTypes(), PhysicalOperatorType::COLUMN_DATA_SCAN, estimated_cardinality); join->children[0] = move(cached_chunk_scan); } @@ -67730,26 +75284,33 @@ vector PhysicalDelimJoin::GetChildren() const { //===--------------------------------------------------------------------===// class DelimJoinGlobalState : public GlobalSinkState { public: - explicit DelimJoinGlobalState(const PhysicalDelimJoin *delim_join) { - D_ASSERT(delim_join->delim_scans.size() > 0); + explicit DelimJoinGlobalState(ClientContext &context, const PhysicalDelimJoin &delim_join) + : lhs_data(context, delim_join.children[0]->GetTypes()) { + D_ASSERT(delim_join.delim_scans.size() > 0); // set up the delim join chunk to scan in the original join - auto &cached_chunk_scan = (PhysicalChunkScan &)*delim_join->join->children[0]; + auto &cached_chunk_scan = (PhysicalColumnDataScan &)*delim_join.join->children[0]; cached_chunk_scan.collection = &lhs_data; } - ChunkCollection lhs_data; + ColumnDataCollection lhs_data; mutex lhs_lock; - void Merge(ChunkCollection &input) { + void Merge(ColumnDataCollection &input) { lock_guard guard(lhs_lock); - lhs_data.Append(input); + lhs_data.Combine(input); } }; class DelimJoinLocalState : public LocalSinkState { public: + explicit DelimJoinLocalState(ClientContext &context, const PhysicalDelimJoin &delim_join) + : lhs_data(context, delim_join.children[0]->GetTypes()) { + lhs_data.InitializeAppend(append_state); + } + unique_ptr distinct_state; - ChunkCollection lhs_data; + ColumnDataCollection lhs_data; + ColumnDataAppendState append_state; void Append(DataChunk &input) { lhs_data.Append(input); @@ -67757,7 +75318,7 @@ class DelimJoinLocalState : public LocalSinkState { }; unique_ptr PhysicalDelimJoin::GetGlobalSinkState(ClientContext &context) const { - auto state = make_unique(this); + auto state = make_unique(context, *this); distinct->sink_state = distinct->GetGlobalSinkState(context); if (delim_scans.size() > 1) { PhysicalHashAggregate::SetMultiScan(*distinct->sink_state); @@ -67766,7 +75327,7 @@ unique_ptr PhysicalDelimJoin::GetGlobalSinkState(ClientContext } unique_ptr PhysicalDelimJoin::GetLocalSinkState(ExecutionContext &context) const { - auto state = make_unique(); + auto state = make_unique(context.client, *this); state->distinct_state = distinct->GetLocalSinkState(context); return move(state); } @@ -67774,7 +75335,7 @@ unique_ptr PhysicalDelimJoin::GetLocalSinkState(ExecutionContext SinkResultType PhysicalDelimJoin::Sink(ExecutionContext &context, GlobalSinkState &state_p, LocalSinkState &lstate_p, DataChunk &input) const { auto &lstate = (DelimJoinLocalState &)lstate_p; - lstate.lhs_data.Append(input); + lstate.lhs_data.Append(lstate.append_state, input); distinct->Sink(context, *distinct->sink_state, *lstate.distinct_state, input); return SinkResultType::NEED_MORE_INPUT; } @@ -67836,6 +75397,8 @@ void PhysicalDelimJoin::BuildPipelines(Executor &executor, Pipeline ¤t, Pi + + //===----------------------------------------------------------------------===// // DuckDB // @@ -67930,6 +75493,7 @@ struct MinByFun { struct SumFun { static AggregateFunction GetSumAggregate(PhysicalType type); + static AggregateFunction GetSumAggregateNoOverflow(PhysicalType type); static void RegisterFunction(BuiltinFunctions &set); }; @@ -67957,6 +75521,8 @@ struct StringAggFun { + + namespace duckdb { PhysicalHashJoin::PhysicalHashJoin(LogicalOperator &op, unique_ptr left, @@ -67992,29 +75558,84 @@ PhysicalHashJoin::PhysicalHashJoin(LogicalOperator &op, unique_ptr(op, *hash_table, op.perfect_join_statistics); + // for external hash join + external = op.can_go_external && ClientConfig::GetConfig(context).force_external; + // memory usage per thread scales with max mem / num threads + double max_memory = BufferManager::GetBufferManager(context).GetMaxMemory(); + double num_threads = TaskScheduler::GetScheduler(context).NumberOfThreads(); + // HT may not exceed 60% of memory + max_ht_size = max_memory * 0.6; + sink_memory_per_thread = max_ht_size / num_threads; + // Set probe types + const auto &payload_types = op.children[0]->types; + probe_types.insert(probe_types.end(), op.condition_types.begin(), op.condition_types.end()); + probe_types.insert(probe_types.end(), payload_types.begin(), payload_types.end()); + probe_types.emplace_back(LogicalType::HASH); } - //! The HT used by the join + void ScheduleFinalize(Pipeline &pipeline, Event &event); + +public: + //! Global HT used by the join unique_ptr hash_table; //! The perfect hash join executor (if any) unique_ptr perfect_join_executor; //! Whether or not the hash table has been finalized bool finalized = false; + + //! Whether we are doing an external join + bool external; + //! Memory usage per thread during the Sink and Execute phases + idx_t max_ht_size; + idx_t sink_memory_per_thread; + + //! Hash tables built by each thread + mutex lock; + vector> local_hash_tables; + + //! Excess probe data gathered during Sink + vector probe_types; + vector> spill_collections; + + //! Whether or not we have started scanning data using GetData + atomic scanned_data; }; -unique_ptr PhysicalHashJoin::GetGlobalSinkState(ClientContext &context) const { - auto state = make_unique(); - state->hash_table = +class HashJoinLocalSinkState : public LocalSinkState { +public: + HashJoinLocalSinkState(const PhysicalHashJoin &op, ClientContext &context) + : build_executor(Allocator::Get(context)) { + auto &allocator = Allocator::Get(context); + if (!op.right_projection_map.empty()) { + build_chunk.Initialize(allocator, op.build_types); + } + for (auto &cond : op.conditions) { + build_executor.AddExpression(*cond.right); + } + join_keys.Initialize(allocator, op.condition_types); + + hash_table = op.InitializeHashTable(context); + } + +public: + DataChunk build_chunk; + DataChunk join_keys; + ExpressionExecutor build_executor; + + //! Thread-local HT + unique_ptr hash_table; +}; + +unique_ptr PhysicalHashJoin::InitializeHashTable(ClientContext &context) const { + auto result = make_unique(BufferManager::GetBufferManager(context), conditions, build_types, join_type); if (!delim_types.empty() && join_type == JoinType::MARK) { // correlated MARK join @@ -68027,7 +75648,7 @@ unique_ptr PhysicalHashJoin::GetGlobalSinkState(ClientContext & // we need these to correctly deal with the cases of either: // - (1) the group being empty [in which case the result is always false, even if the comparison is NULL] // - (2) the group containing a NULL value [in which case FALSE becomes NULL] - auto &info = state->hash_table->correlated_mark_join_info; + auto &info = result->correlated_mark_join_info; vector payload_types; vector correlated_aggregates; @@ -68049,40 +75670,35 @@ unique_ptr PhysicalHashJoin::GetGlobalSinkState(ClientContext & payload_types.push_back(aggr->return_type); info.correlated_aggregates.push_back(move(aggr)); + auto &allocator = Allocator::Get(context); info.correlated_counts = make_unique( - BufferManager::GetBufferManager(context), delim_types, payload_types, correlated_aggregates); + allocator, BufferManager::GetBufferManager(context), delim_types, payload_types, correlated_aggregates); info.correlated_types = delim_types; - info.group_chunk.Initialize(delim_types); - info.result_chunk.Initialize(payload_types); + info.group_chunk.Initialize(allocator, delim_types); + info.result_chunk.Initialize(allocator, payload_types); } } - // for perfect hash join - state->perfect_join_executor = - make_unique(*this, *state->hash_table, perfect_join_statistics); - return move(state); + return result; +} + +unique_ptr PhysicalHashJoin::GetGlobalSinkState(ClientContext &context) const { + return make_unique(*this, context); } unique_ptr PhysicalHashJoin::GetLocalSinkState(ExecutionContext &context) const { - auto state = make_unique(); - if (!right_projection_map.empty()) { - state->build_chunk.Initialize(build_types); - } - for (auto &cond : conditions) { - state->build_executor.AddExpression(*cond.right); - } - state->join_keys.Initialize(condition_types); - return move(state); + return make_unique(*this, context.client); } -SinkResultType PhysicalHashJoin::Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate_p, +SinkResultType PhysicalHashJoin::Sink(ExecutionContext &context, GlobalSinkState &gstate_p, LocalSinkState &lstate_p, DataChunk &input) const { - auto &sink = (HashJoinGlobalState &)state; - auto &lstate = (HashJoinLocalState &)lstate_p; + auto &gstate = (HashJoinGlobalSinkState &)gstate_p; + auto &lstate = (HashJoinLocalSinkState &)lstate_p; + // resolve the join keys for the right chunk lstate.join_keys.Reset(); lstate.build_executor.Execute(input, lstate.join_keys); - // TODO: add statement to check for possible per // build the HT + auto &ht = *lstate.hash_table; if (!right_projection_map.empty()) { // there is a projection map: fill the build chunk with the projected columns lstate.build_chunk.Reset(); @@ -68090,31 +75706,191 @@ SinkResultType PhysicalHashJoin::Sink(ExecutionContext &context, GlobalSinkState for (idx_t i = 0; i < right_projection_map.size(); i++) { lstate.build_chunk.data[i].Reference(input.data[right_projection_map[i]]); } - sink.hash_table->Build(lstate.join_keys, lstate.build_chunk); + ht.Build(lstate.join_keys, lstate.build_chunk); } else if (!build_types.empty()) { // there is not a projected map: place the entire right chunk in the HT - sink.hash_table->Build(lstate.join_keys, input); + ht.Build(lstate.join_keys, input); } else { // there are only keys: place an empty chunk in the payload lstate.build_chunk.SetCardinality(input.size()); - sink.hash_table->Build(lstate.join_keys, lstate.build_chunk); + ht.Build(lstate.join_keys, lstate.build_chunk); + } + + // swizzle if we reach memory limit + auto approx_ptr_table_size = ht.Count() * 3 * sizeof(data_ptr_t); + if (can_go_external && ht.SizeInBytes() + approx_ptr_table_size >= gstate.sink_memory_per_thread) { + lstate.hash_table->SwizzleBlocks(); + gstate.external = true; } + return SinkResultType::NEED_MORE_INPUT; } -void PhysicalHashJoin::Combine(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate) const { - auto &state = (HashJoinLocalState &)lstate; +void PhysicalHashJoin::Combine(ExecutionContext &context, GlobalSinkState &gstate_p, LocalSinkState &lstate_p) const { + auto &gstate = (HashJoinGlobalSinkState &)gstate_p; + auto &lstate = (HashJoinLocalSinkState &)lstate_p; + if (lstate.hash_table) { + lock_guard local_ht_lock(gstate.lock); + gstate.local_hash_tables.push_back(move(lstate.hash_table)); + } auto &client_profiler = QueryProfiler::Get(context.client); - context.thread.profiler.Flush(this, &state.build_executor, "build_executor", 1); + context.thread.profiler.Flush(this, &lstate.build_executor, "build_executor", 1); client_profiler.Flush(context.thread.profiler); } //===--------------------------------------------------------------------===// // Finalize //===--------------------------------------------------------------------===// +class HashJoinFinalizeTask : public ExecutorTask { +public: + HashJoinFinalizeTask(shared_ptr event_p, ClientContext &context, HashJoinGlobalSinkState &sink, + idx_t block_idx_start, idx_t block_idx_end, bool parallel) + : ExecutorTask(context), event(move(event_p)), sink(sink), block_idx_start(block_idx_start), + block_idx_end(block_idx_end), parallel(parallel) { + } + + TaskExecutionResult ExecuteTask(TaskExecutionMode mode) override { + sink.hash_table->Finalize(block_idx_start, block_idx_end, parallel); + event->FinishTask(); + return TaskExecutionResult::TASK_FINISHED; + } + +private: + shared_ptr event; + HashJoinGlobalSinkState &sink; + idx_t block_idx_start; + idx_t block_idx_end; + bool parallel; +}; + +class HashJoinFinalizeEvent : public Event { +public: + HashJoinFinalizeEvent(Pipeline &pipeline_p, HashJoinGlobalSinkState &sink) + : Event(pipeline_p.executor), pipeline(pipeline_p), sink(sink) { + } + + Pipeline &pipeline; + HashJoinGlobalSinkState &sink; + +public: + void Schedule() override { + auto &context = pipeline.GetClientContext(); + auto parallel_construct_count = + context.config.verify_parallelism ? STANDARD_VECTOR_SIZE : PARALLEL_CONSTRUCT_COUNT; + + vector> finalize_tasks; + auto &ht = *sink.hash_table; + const auto &block_collection = ht.GetBlockCollection(); + const auto &blocks = block_collection.blocks; + const auto num_blocks = blocks.size(); + if (block_collection.count < parallel_construct_count) { + // Single-threaded finalize + finalize_tasks.push_back( + make_unique(shared_from_this(), context, sink, 0, num_blocks, false)); + } else { + // Parallel finalize + idx_t num_threads = TaskScheduler::GetScheduler(context).NumberOfThreads(); + auto blocks_per_thread = MaxValue((num_blocks + num_threads - 1) / num_threads, 1); + + idx_t block_idx = 0; + for (idx_t thread_idx = 0; thread_idx < num_threads; thread_idx++) { + auto block_idx_start = block_idx; + auto block_idx_end = MinValue(block_idx_start + blocks_per_thread, num_blocks); + finalize_tasks.push_back(make_unique(shared_from_this(), context, sink, + block_idx_start, block_idx_end, true)); + block_idx = block_idx_end; + if (block_idx == num_blocks) { + break; + } + } + } + SetTasks(move(finalize_tasks)); + } + + void FinishEvent() override { + sink.hash_table->finalized = true; + } + + // 1 << 18 TODO: tweak experimentally + static constexpr const idx_t PARALLEL_CONSTRUCT_COUNT = 262144; +}; + +void HashJoinGlobalSinkState::ScheduleFinalize(Pipeline &pipeline, Event &event) { + hash_table->InitializePointerTable(); + auto new_event = make_shared(pipeline, *this); + event.InsertEvent(move(new_event)); +} + +class HashJoinPartitionTask : public ExecutorTask { +public: + HashJoinPartitionTask(shared_ptr event_p, ClientContext &context, JoinHashTable &global_ht, + JoinHashTable &local_ht) + : ExecutorTask(context), event(move(event_p)), global_ht(global_ht), local_ht(local_ht) { + } + + TaskExecutionResult ExecuteTask(TaskExecutionMode mode) override { + local_ht.Partition(global_ht); + event->FinishTask(); + return TaskExecutionResult::TASK_FINISHED; + } + +private: + shared_ptr event; + + JoinHashTable &global_ht; + JoinHashTable &local_ht; +}; + +class HashJoinPartitionEvent : public Event { +public: + HashJoinPartitionEvent(Pipeline &pipeline_p, HashJoinGlobalSinkState &sink, + vector> &local_hts) + : Event(pipeline_p.executor), pipeline(pipeline_p), sink(sink), local_hts(local_hts) { + } + + Pipeline &pipeline; + HashJoinGlobalSinkState &sink; + vector> &local_hts; + +public: + void Schedule() override { + auto &context = pipeline.GetClientContext(); + vector> partition_tasks; + partition_tasks.reserve(local_hts.size()); + for (auto &local_ht : local_hts) { + partition_tasks.push_back( + make_unique(shared_from_this(), context, *sink.hash_table, *local_ht)); + } + SetTasks(move(partition_tasks)); + } + + void FinishEvent() override { + local_hts.clear(); + sink.hash_table->PrepareExternalFinalize(); + sink.ScheduleFinalize(pipeline, *this); + } +}; + SinkFinalizeType PhysicalHashJoin::Finalize(Pipeline &pipeline, Event &event, ClientContext &context, GlobalSinkState &gstate) const { - auto &sink = (HashJoinGlobalState &)gstate; + auto &sink = (HashJoinGlobalSinkState &)gstate; + + if (sink.external) { + D_ASSERT(can_go_external); + // External join - partition HT + sink.perfect_join_executor.reset(); + sink.hash_table->ComputePartitionSizes(context.config, sink.local_hash_tables, sink.max_ht_size); + auto new_event = make_shared(pipeline, sink, sink.local_hash_tables); + event.InsertEvent(move(new_event)); + sink.finalized = true; + return SinkFinalizeType::READY; + } else { + for (auto &local_ht : sink.local_hash_tables) { + sink.hash_table->Merge(*local_ht); + } + sink.local_hash_tables.clear(); + } + // check for possible perfect hash table auto use_perfect_hash = sink.perfect_join_executor->CanDoPerfectHashJoin(); if (use_perfect_hash) { @@ -68125,7 +75901,7 @@ SinkFinalizeType PhysicalHashJoin::Finalize(Pipeline &pipeline, Event &event, Cl // In case of a large build side or duplicates, use regular hash join if (!use_perfect_hash) { sink.perfect_join_executor.reset(); - sink.hash_table->Finalize(); + sink.ScheduleFinalize(pipeline, event); } sink.finalized = true; if (sink.hash_table->Count() == 0 && EmptyResultIfRHSIsEmpty()) { @@ -68137,49 +75913,69 @@ SinkFinalizeType PhysicalHashJoin::Finalize(Pipeline &pipeline, Event &event, Cl //===--------------------------------------------------------------------===// // Operator //===--------------------------------------------------------------------===// -class PhysicalHashJoinState : public OperatorState { +class HashJoinOperatorState : public OperatorState { public: + explicit HashJoinOperatorState(Allocator &allocator) : probe_executor(allocator), spill_collection(nullptr) { + } + DataChunk join_keys; ExpressionExecutor probe_executor; unique_ptr scan_structure; unique_ptr perfect_hash_join_state; + //! Collection and chunk to sink data into for external join + ColumnDataCollection *spill_collection; + ColumnDataAppendState spill_append_state; + DataChunk spill_chunk; + public: void Finalize(PhysicalOperator *op, ExecutionContext &context) override { context.thread.profiler.Flush(op, &probe_executor, "probe_executor", 0); } }; -unique_ptr PhysicalHashJoin::GetOperatorState(ClientContext &context) const { - auto state = make_unique(); - auto &sink = (HashJoinGlobalState &)*sink_state; +unique_ptr PhysicalHashJoin::GetOperatorState(ExecutionContext &context) const { + auto &allocator = Allocator::Get(context.client); + auto &sink = (HashJoinGlobalSinkState &)*sink_state; + auto state = make_unique(allocator); if (sink.perfect_join_executor) { state->perfect_hash_join_state = sink.perfect_join_executor->GetOperatorState(context); } else { - state->join_keys.Initialize(condition_types); + state->join_keys.Initialize(allocator, condition_types); for (auto &cond : conditions) { state->probe_executor.AddExpression(*cond.left); } } + if (sink.external) { + state->spill_chunk.Initialize(allocator, sink.probe_types); + lock_guard local_ht_lock(sink.lock); + sink.spill_collections.push_back( + make_unique(BufferManager::GetBufferManager(context.client), sink.probe_types)); + state->spill_collection = sink.spill_collections.back().get(); + state->spill_collection->InitializeAppend(state->spill_append_state); + } + return move(state); } OperatorResultType PhysicalHashJoin::Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state_p) const { - auto &state = (PhysicalHashJoinState &)state_p; - auto &sink = (HashJoinGlobalState &)*sink_state; + auto &state = (HashJoinOperatorState &)state_p; + auto &sink = (HashJoinGlobalSinkState &)*sink_state; D_ASSERT(sink.finalized); + D_ASSERT(!sink.scanned_data); if (sink.hash_table->Count() == 0 && EmptyResultIfRHSIsEmpty()) { return OperatorResultType::FINISHED; } + if (sink.perfect_join_executor) { + D_ASSERT(!sink.external); return sink.perfect_join_executor->ProbePerfectHashTable(context, input, chunk, *state.perfect_hash_join_state); } if (state.scan_structure) { - // still have elements remaining from the previous probe (i.e. we got - // >1024 elements in the previous probe) + // still have elements remaining from the previous probe (i.e. we got >1024 elements in the previous probe) state.scan_structure->Next(state.join_keys, input, chunk); if (chunk.size() > 0) { return OperatorResultType::HAVE_MORE_OUTPUT; @@ -68193,12 +75989,18 @@ OperatorResultType PhysicalHashJoin::Execute(ExecutionContext &context, DataChun ConstructEmptyJoinResult(sink.hash_table->join_type, sink.hash_table->has_null, input, chunk); return OperatorResultType::NEED_MORE_INPUT; } + // resolve the join keys for the left chunk state.join_keys.Reset(); state.probe_executor.Execute(input, state.join_keys); // perform the actual probe - state.scan_structure = sink.hash_table->Probe(state.join_keys); + if (sink.external) { + state.scan_structure = sink.hash_table->ProbeAndSpill(state.join_keys, input, *state.spill_collection, + state.spill_append_state, state.spill_chunk); + } else { + state.scan_structure = sink.hash_table->Probe(state.join_keys); + } state.scan_structure->Next(state.join_keys, input, chunk); return OperatorResultType::HAVE_MORE_OUTPUT; } @@ -68206,32 +76008,400 @@ OperatorResultType PhysicalHashJoin::Execute(ExecutionContext &context, DataChun //===--------------------------------------------------------------------===// // Source //===--------------------------------------------------------------------===// -class HashJoinScanState : public GlobalSourceState { +enum class HashJoinSourceStage : uint8_t { INIT, BUILD, PROBE, SCAN_HT, DONE }; + +class HashJoinLocalSourceState; + +class HashJoinGlobalSourceState : public GlobalSourceState { public: - explicit HashJoinScanState(const PhysicalHashJoin &op) : op(op) { - } + HashJoinGlobalSourceState(const PhysicalHashJoin &op, ClientContext &context); - const PhysicalHashJoin &op; - //! Only used for FULL OUTER JOIN: scan state of the final scan to find unmatched tuples in the build-side - JoinHTScanState ht_scan_state; + //! Initialize this source state using the info in the sink + void Initialize(HashJoinGlobalSinkState &sink); + //! Partition the probe-side data + void PartitionProbeSide(HashJoinGlobalSinkState &sink); + //! Prepare the next build/probe stage for external hash join (must hold lock) + void PrepareBuild(HashJoinGlobalSinkState &sink); + void PrepareProbe(HashJoinGlobalSinkState &sink); + //! Assigns a task to a local source state + bool AssignTask(HashJoinGlobalSinkState &sink, HashJoinLocalSourceState &lstate); idx_t MaxThreads() override { - auto &sink = (HashJoinGlobalState &)*op.sink_state; - return sink.hash_table->Count() / (STANDARD_VECTOR_SIZE * 10); + return probe_count / ((idx_t)STANDARD_VECTOR_SIZE * parallel_scan_chunk_count); } + +public: + //! The JoinType of the PhysicalHashJoin + JoinType join_type; + + //! Probe-side data that was spilled during Execute + unique_ptr probe_collection = nullptr; + + //! For synchronizing the external hash join + atomic initialized; + atomic global_stage; + mutex &lock; + + //! For HT build synchronization + idx_t build_block_idx; + idx_t build_block_count; + idx_t build_block_done; + idx_t build_blocks_per_thread; + + //! For probe synchronization + ColumnDataParallelScanState probe_global_scan; + idx_t probe_chunk_count; + idx_t probe_chunk_done; + atomic probe_side_partitioned; + + //! For full/outer synchronization + JoinHTScanState full_outer_scan; + + //! To determine the number of threads + idx_t probe_count; + idx_t parallel_scan_chunk_count; +}; + +class HashJoinLocalSourceState : public LocalSourceState { +public: + HashJoinLocalSourceState(const PhysicalHashJoin &op, Allocator &allocator); + + //! Do the work this thread has been assigned + void ExecuteTask(HashJoinGlobalSinkState &sink, HashJoinGlobalSourceState &gstate, DataChunk &chunk); + //! Whether this thread has finished the work it has been assigned + bool TaskFinished(); + //! Build, probe and scan for external hash join + void ExternalBuild(HashJoinGlobalSinkState &sink, HashJoinGlobalSourceState &gstate); + void ExternalProbe(HashJoinGlobalSinkState &sink, HashJoinGlobalSourceState &gstate, DataChunk &chunk); + void ExternalScan(HashJoinGlobalSinkState &sink, HashJoinGlobalSourceState &gstate, DataChunk &chunk); + + //! Scans the HT for full/outer join + void ScanFullOuter(HashJoinGlobalSinkState &sink, HashJoinGlobalSourceState &gstate); + +public: + //! The stage that this thread was assigned work for + HashJoinSourceStage local_stage; + //! Vector with pointers here so we don't have to re-initialize + Vector addresses; + + //! Blocks assigned to this thread for building the pointer table + idx_t build_block_idx_start; + idx_t build_block_idx_end; + + //! Local scan state for probe collection + ColumnDataLocalScanState probe_local_scan; + //! Indices for ColumnDataCollection::NextScanIndex + idx_t chunk_index; + idx_t segment_index; + idx_t row_index; + //! Chunks for holding the scanned probe collection + DataChunk probe_chunk; + DataChunk join_keys; + DataChunk payload; + //! Column indices to easily reference the join keys/payload columns in probe_chunk + vector join_key_indices; + vector payload_indices; + //! Scan structure for the external probe + unique_ptr scan_structure; + + //! Current number of tuples from a full/outer scan that are 'in-flight' + idx_t full_outer_found_entries; + idx_t full_outer_in_progress; }; unique_ptr PhysicalHashJoin::GetGlobalSourceState(ClientContext &context) const { - return make_unique(*this); + return make_unique(*this, context); } -void PhysicalHashJoin::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, - LocalSourceState &lstate) const { - D_ASSERT(IsRightOuterJoin(join_type)); - // check if we need to scan any unmatched tuples from the RHS for the full/right outer join - auto &sink = (HashJoinGlobalState &)*sink_state; - auto &state = (HashJoinScanState &)gstate; - sink.hash_table->ScanFullOuter(chunk, state.ht_scan_state); +unique_ptr PhysicalHashJoin::GetLocalSourceState(ExecutionContext &context, + GlobalSourceState &gstate) const { + return make_unique(*this, Allocator::Get(context.client)); +} + +HashJoinGlobalSourceState::HashJoinGlobalSourceState(const PhysicalHashJoin &op, ClientContext &context) + : join_type(op.join_type), initialized(false), global_stage(HashJoinSourceStage::INIT), + lock(probe_global_scan.lock), probe_side_partitioned(false), probe_count(op.children[0]->estimated_cardinality), + parallel_scan_chunk_count(context.config.verify_parallelism ? 1 : 120) { +} + +void HashJoinGlobalSourceState::Initialize(HashJoinGlobalSinkState &sink) { + if (initialized) { + return; + } + lock_guard init_lock(lock); + if (initialized) { + // Have to check if anything changed since we got the lock + return; + } + full_outer_scan.total = sink.hash_table->Count(); + + auto block_capacity = sink.hash_table->GetBlockCollection().block_capacity; + build_blocks_per_thread = + MaxValue(idx_t(parallel_scan_chunk_count * STANDARD_VECTOR_SIZE) / block_capacity, 1); + + initialized = true; +} + +void HashJoinGlobalSourceState::PartitionProbeSide(HashJoinGlobalSinkState &sink) { + if (probe_side_partitioned) { + return; + } + lock_guard guard(lock); + if (probe_side_partitioned) { + return; + } + + // For now we actually don't partition the probe side TODO + for (auto &spill_collection : sink.spill_collections) { + if (!probe_collection) { + probe_collection = move(spill_collection); + } else { + probe_collection->Combine(*spill_collection); + } + } + sink.spill_collections.clear(); + + probe_chunk_count = probe_collection->ChunkCount(); + + probe_side_partitioned = true; +} + +void HashJoinGlobalSourceState::PrepareBuild(HashJoinGlobalSinkState &sink) { + D_ASSERT(global_stage != HashJoinSourceStage::BUILD); + auto &ht = *sink.hash_table; + + // Put the next partitions in the block collection + if (!ht.PrepareExternalFinalize()) { + global_stage = HashJoinSourceStage::DONE; + return; + } + + auto &block_collection = ht.GetBlockCollection(); + build_block_idx = 0; + build_block_count = block_collection.blocks.size(); + build_block_done = 0; + ht.InitializePointerTable(); + + global_stage = HashJoinSourceStage::BUILD; +} + +void HashJoinGlobalSourceState::PrepareProbe(HashJoinGlobalSinkState &sink) { + probe_collection->InitializeScan(probe_global_scan); + probe_chunk_done = 0; + + if (IsRightOuterJoin(join_type)) { + full_outer_scan.Reset(); + full_outer_scan.total = sink.hash_table->Count(); + } + + global_stage = HashJoinSourceStage::PROBE; +} + +bool HashJoinGlobalSourceState::AssignTask(HashJoinGlobalSinkState &sink, HashJoinLocalSourceState &lstate) { + D_ASSERT(lstate.TaskFinished()); + + lock_guard guard(lock); + switch (global_stage.load()) { + case HashJoinSourceStage::BUILD: + if (build_block_idx != build_block_count) { + lstate.local_stage = global_stage; + lstate.build_block_idx_start = build_block_idx; + build_block_idx = MinValue(build_block_count, build_block_idx + build_blocks_per_thread); + lstate.build_block_idx_end = build_block_idx; + return true; + } + break; + case HashJoinSourceStage::PROBE: + if (probe_collection->NextScanIndex(probe_global_scan.scan_state, lstate.chunk_index, lstate.segment_index, + lstate.row_index)) { + lstate.local_stage = global_stage; + return true; + } + break; + case HashJoinSourceStage::SCAN_HT: + if (full_outer_scan.scan_index != full_outer_scan.total) { + lstate.local_stage = global_stage; + lstate.ScanFullOuter(sink, *this); + return true; + } + break; + case HashJoinSourceStage::DONE: + break; + default: + throw InternalException("Unexpected HashJoinSourceStage in AssignTask!"); + } + return false; +} + +HashJoinLocalSourceState::HashJoinLocalSourceState(const PhysicalHashJoin &op, Allocator &allocator) + : local_stage(HashJoinSourceStage::INIT), addresses(LogicalType::POINTER) { + auto &sink = (HashJoinGlobalSinkState &)*op.sink_state; + probe_chunk.Initialize(allocator, sink.probe_types); + join_keys.Initialize(allocator, op.condition_types); + payload.Initialize(allocator, op.children[0]->types); + + // Store the indices of the columns to reference them easily + idx_t col_idx = 0; + for (; col_idx < op.condition_types.size(); col_idx++) { + join_key_indices.push_back(col_idx); + } + for (; col_idx < sink.probe_types.size() - 1; col_idx++) { + payload_indices.push_back(col_idx); + } +} + +void HashJoinLocalSourceState::ExecuteTask(HashJoinGlobalSinkState &sink, HashJoinGlobalSourceState &gstate, + DataChunk &chunk) { + switch (local_stage) { + case HashJoinSourceStage::BUILD: + ExternalBuild(sink, gstate); + break; + case HashJoinSourceStage::PROBE: + ExternalProbe(sink, gstate, chunk); + break; + case HashJoinSourceStage::SCAN_HT: + ExternalScan(sink, gstate, chunk); + break; + default: + throw InternalException("Unexpected HashJoinSourceStage in ExecuteTask!"); + } +} + +bool HashJoinLocalSourceState::TaskFinished() { + switch (local_stage) { + case HashJoinSourceStage::INIT: + case HashJoinSourceStage::BUILD: + return true; + case HashJoinSourceStage::PROBE: + return scan_structure == nullptr; + case HashJoinSourceStage::SCAN_HT: + return full_outer_in_progress == 0; + default: + throw InternalException("Unexpected HashJoinSourceStage in TaskFinished!"); + } +} + +void HashJoinLocalSourceState::ExternalBuild(HashJoinGlobalSinkState &sink, HashJoinGlobalSourceState &gstate) { + D_ASSERT(local_stage == HashJoinSourceStage::BUILD); + + auto &ht = *sink.hash_table; + ht.Finalize(build_block_idx_start, build_block_idx_end, true); + + lock_guard guard(gstate.lock); + gstate.build_block_done += build_block_idx_end - build_block_idx_start; + if (gstate.build_block_done == gstate.build_block_count) { + ht.finalized = true; + gstate.PrepareProbe(sink); + } +} + +void HashJoinLocalSourceState::ExternalProbe(HashJoinGlobalSinkState &sink, HashJoinGlobalSourceState &gstate, + DataChunk &chunk) { + D_ASSERT(local_stage == HashJoinSourceStage::PROBE && sink.hash_table->finalized); + + if (scan_structure) { + // Still have elements remaining from the previous probe (i.e. we got >1024 elements in the previous probe) + scan_structure->Next(join_keys, payload, chunk); + if (chunk.size() == 0) { + scan_structure = nullptr; + lock_guard lock(gstate.lock); + if (++gstate.probe_chunk_done == gstate.probe_chunk_count) { + if (IsRightOuterJoin(gstate.join_type)) { + gstate.global_stage = HashJoinSourceStage::SCAN_HT; + } else { + gstate.PrepareBuild(sink); + } + } + } + return; + } + + // Scan input chunk for next probe + gstate.probe_collection->ScanAtIndex(gstate.probe_global_scan, probe_local_scan, probe_chunk, chunk_index, + segment_index, row_index); + + // Get the probe chunk columns/hashes + join_keys.ReferenceColumns(probe_chunk, join_key_indices); + payload.ReferenceColumns(probe_chunk, payload_indices); + auto precomputed_hashes = &probe_chunk.data.back(); + + // Perform the probe + scan_structure = sink.hash_table->Probe(join_keys, precomputed_hashes); + scan_structure->Next(join_keys, payload, chunk); +} + +void HashJoinLocalSourceState::ExternalScan(HashJoinGlobalSinkState &sink, HashJoinGlobalSourceState &gstate, + DataChunk &chunk) { + D_ASSERT(local_stage == HashJoinSourceStage::SCAN_HT && full_outer_in_progress != 0); + + if (full_outer_found_entries != 0) { + // Just did a scan, now gather + sink.hash_table->GatherFullOuter(chunk, addresses, full_outer_found_entries); + full_outer_found_entries = 0; + return; + } + + lock_guard guard(gstate.lock); + auto &fo_ss = gstate.full_outer_scan; + fo_ss.scanned += full_outer_in_progress; + full_outer_in_progress = 0; + if (fo_ss.scanned == fo_ss.total) { + gstate.PrepareBuild(sink); + return; + } +} + +void HashJoinLocalSourceState::ScanFullOuter(HashJoinGlobalSinkState &sink, HashJoinGlobalSourceState &gstate) { + auto &fo_ss = gstate.full_outer_scan; + idx_t scan_index_before = fo_ss.scan_index; + full_outer_found_entries = sink.hash_table->ScanFullOuter(fo_ss, addresses); + idx_t scanned = fo_ss.scan_index - scan_index_before; + full_outer_in_progress = scanned; +} + +void PhysicalHashJoin::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate_p, + LocalSourceState &lstate_p) const { + auto &sink = (HashJoinGlobalSinkState &)*sink_state; + auto &gstate = (HashJoinGlobalSourceState &)gstate_p; + auto &lstate = (HashJoinLocalSourceState &)lstate_p; + sink.scanned_data = true; + + if (!sink.external) { + if (IsRightOuterJoin(join_type)) { + { + lock_guard guard(gstate.lock); + lstate.ScanFullOuter(sink, gstate); + } + sink.hash_table->GatherFullOuter(chunk, lstate.addresses, lstate.full_outer_found_entries); + } + return; + } + D_ASSERT(can_go_external); + + if (gstate.global_stage == HashJoinSourceStage::INIT) { + gstate.Initialize(sink); + gstate.PartitionProbeSide(sink); + + lock_guard lock(gstate.lock); + if (gstate.global_stage == HashJoinSourceStage::INIT) { + if (IsRightOuterJoin(join_type)) { + gstate.global_stage = HashJoinSourceStage::SCAN_HT; + } else { + gstate.PrepareBuild(sink); + } + } + } + + // Any call to GetData must produce tuples, otherwise the pipeline executor thinks that we're done + // Therefore, we loop until we've produced tuples, or until the operator is actually done + while (gstate.global_stage != HashJoinSourceStage::DONE && chunk.size() == 0) { + if (lstate.TaskFinished()) { + if (!gstate.AssignTask(sink, lstate)) { + continue; // Cannot assign work, spinlock + } + } + lstate.ExecuteTask(sink, gstate, chunk); + } } } // namespace duckdb @@ -68269,7 +76439,7 @@ class PhysicalRangeJoin : public PhysicalComparisonJoin { public: class LocalSortedTable { public: - LocalSortedTable(const PhysicalRangeJoin &op, const idx_t child); + LocalSortedTable(Allocator &allocator, const PhysicalRangeJoin &op, const idx_t child); void Sink(DataChunk &input, GlobalSortState &global_sort_state); @@ -68312,7 +76482,7 @@ class PhysicalRangeJoin : public PhysicalComparisonJoin { } inline idx_t BlockSize(idx_t i) const { - return global_sort_state.sorted_blocks[0]->radix_sorting_data[i].count; + return global_sort_state.sorted_blocks[0]->radix_sorting_data[i]->count; } void Combine(LocalSortedTable <able); @@ -68342,8 +76512,10 @@ class PhysicalRangeJoin : public PhysicalComparisonJoin { public: // Gather the result values and slice the payload columns to those values. - static void SliceSortedPayload(DataChunk &payload, GlobalSortState &state, const idx_t block_idx, - const SelectionVector &result, const idx_t result_count, const idx_t left_cols = 0); + // Returns a buffer handle to the pinned heap block (if any) + static BufferHandle SliceSortedPayload(DataChunk &payload, GlobalSortState &state, const idx_t block_idx, + const SelectionVector &result, const idx_t result_count, + const idx_t left_cols = 0); // Apply a tail condition to the current selection static idx_t SelectJoinTail(const ExpressionType &condition, Vector &left, Vector &right, const SelectionVector *sel, idx_t count, SelectionVector *true_sel); @@ -68424,7 +76596,6 @@ class PhysicalIEJoin : public PhysicalRangeJoin { - #include namespace duckdb { @@ -68483,7 +76654,8 @@ class IEJoinLocalState : public LocalSinkState { public: using LocalSortedTable = PhysicalRangeJoin::LocalSortedTable; - IEJoinLocalState(const PhysicalRangeJoin &op, const idx_t child) : table(op, child) { + IEJoinLocalState(Allocator &allocator, const PhysicalRangeJoin &op, const idx_t child) + : table(allocator, op, child) { } //! The local sort state @@ -68543,7 +76715,7 @@ unique_ptr PhysicalIEJoin::GetLocalSinkState(ExecutionContext &c const auto &ie_sink = (IEJoinGlobalState &)*sink_state; sink_child = ie_sink.child; } - return make_unique(*this, sink_child); + return make_unique(Allocator::Get(context.client), *this, sink_child); } SinkResultType PhysicalIEJoin::Sink(ExecutionContext &context, GlobalSinkState &gstate_p, LocalSinkState &lstate_p, @@ -68604,104 +76776,6 @@ OperatorResultType PhysicalIEJoin::Execute(ExecutionContext &context, DataChunk //===--------------------------------------------------------------------===// // Source //===--------------------------------------------------------------------===// -struct SBIterator { - static int ComparisonValue(ExpressionType comparison) { - switch (comparison) { - case ExpressionType::COMPARE_LESSTHAN: - case ExpressionType::COMPARE_GREATERTHAN: - return -1; - case ExpressionType::COMPARE_LESSTHANOREQUALTO: - case ExpressionType::COMPARE_GREATERTHANOREQUALTO: - return 0; - default: - throw InternalException("Unimplemented comparison type for IEJoin!"); - } - } - - explicit SBIterator(GlobalSortState &gss, ExpressionType comparison, idx_t entry_idx_p = 0) - : sort_layout(gss.sort_layout), block_count(gss.sorted_blocks[0]->radix_sorting_data.size()), - block_capacity(gss.block_capacity), cmp_size(sort_layout.comparison_size), entry_size(sort_layout.entry_size), - all_constant(sort_layout.all_constant), external(gss.external), cmp(ComparisonValue(comparison)), - scan(gss.buffer_manager, gss), block_ptr(nullptr), entry_ptr(nullptr) { - - scan.sb = gss.sorted_blocks[0].get(); - scan.block_idx = block_count; - SetIndex(entry_idx_p); - } - - inline idx_t GetIndex() const { - return entry_idx; - } - - inline void SetIndex(idx_t entry_idx_p) { - const auto new_block_idx = entry_idx_p / block_capacity; - if (new_block_idx != scan.block_idx) { - scan.SetIndices(new_block_idx, 0); - if (new_block_idx < block_count) { - scan.PinRadix(scan.block_idx); - block_ptr = scan.RadixPtr(); - if (!all_constant) { - scan.PinData(*scan.sb->blob_sorting_data); - } - } - } - - scan.entry_idx = entry_idx_p % block_capacity; - entry_ptr = block_ptr + scan.entry_idx * entry_size; - entry_idx = entry_idx_p; - } - - inline SBIterator &operator++() { - if (++scan.entry_idx < block_capacity) { - entry_ptr += entry_size; - ++entry_idx; - } else { - SetIndex(entry_idx + 1); - } - - return *this; - } - - inline SBIterator &operator--() { - if (scan.entry_idx) { - --scan.entry_idx; - --entry_idx; - entry_ptr -= entry_size; - } else { - SetIndex(entry_idx - 1); - } - - return *this; - } - - inline bool Compare(const SBIterator &other) const { - int comp_res; - if (all_constant) { - comp_res = FastMemcmp(entry_ptr, other.entry_ptr, cmp_size); - } else { - comp_res = Comparators::CompareTuple(scan, other.scan, entry_ptr, other.entry_ptr, sort_layout, external); - } - - return comp_res <= cmp; - } - - // Fixed comparison parameters - const SortLayout &sort_layout; - const idx_t block_count; - const idx_t block_capacity; - const size_t cmp_size; - const size_t entry_size; - const bool all_constant; - const bool external; - const int cmp; - - // Iteration state - SBScanState scan; - idx_t entry_idx; - data_ptr_t block_ptr; - data_ptr_t entry_ptr; -}; - struct IEJoinUnion { using SortedTable = PhysicalRangeJoin::GlobalSortedTable; @@ -68729,7 +76803,7 @@ struct IEJoinUnion { PayloadScanner scanner(blocks, gstate, false); DataChunk payload; - payload.Initialize(gstate.payload_layout.GetTypes()); + payload.Initialize(Allocator::DefaultAllocator(), gstate.payload_layout.GetTypes()); for (;;) { scanner.Scan(payload); const auto count = payload.size(); @@ -68796,7 +76870,7 @@ idx_t IEJoinUnion::AppendKey(SortedTable &table, ExpressionExecutor &executor, S auto table_idx = block_idx * gstate.block_capacity; DataChunk scanned; - scanned.Initialize(scanner.GetPayloadTypes()); + scanned.Initialize(Allocator::DefaultAllocator(), scanner.GetPayloadTypes()); // Writing auto types = local_sort_state.sort_layout->logical_types; @@ -68808,7 +76882,7 @@ idx_t IEJoinUnion::AppendKey(SortedTable &table, ExpressionExecutor &executor, S DataChunk keys; DataChunk payload; - keys.Initialize(types); + keys.Initialize(Allocator::DefaultAllocator(), types); idx_t inserted = 0; for (auto rid = base; table_idx < valid;) { @@ -68856,6 +76930,7 @@ idx_t IEJoinUnion::AppendKey(SortedTable &table, ExpressionExecutor &executor, S IEJoinUnion::IEJoinUnion(ClientContext &context, const PhysicalIEJoin &op, SortedTable &t1, const idx_t b1, SortedTable &t2, const idx_t b2) : n(0), i(0) { + auto &allocator = Allocator::Get(context); // input : query Q with 2 join predicates t1.X op1 t2.X' and t1.Y op2 t2.Y', tables T, T' of sizes m and n resp. // output: a list of tuple pairs (ti , tj) // Note that T/T' are already sorted on X/X' and contain the payload data @@ -68901,13 +76976,13 @@ IEJoinUnion::IEJoinUnion(ClientContext &context, const PhysicalIEJoin &op, Sorte l1 = make_unique(context, orders, payload_layout); // LHS has positive rids - ExpressionExecutor l_executor; + ExpressionExecutor l_executor(allocator); l_executor.AddExpression(*order1.expression); l_executor.AddExpression(*order2.expression); AppendKey(t1, l_executor, *l1, 1, 1, b1); // RHS has negative rids - ExpressionExecutor r_executor; + ExpressionExecutor r_executor(allocator); r_executor.AddExpression(*op.rhs_orders[0][0].expression); r_executor.AddExpression(*op.rhs_orders[1][0].expression); AppendKey(t2, r_executor, *l1, -1, -1, b2); @@ -68934,7 +77009,7 @@ IEJoinUnion::IEJoinUnion(ClientContext &context, const PhysicalIEJoin &op, Sorte ref = make_unique(order2.expression->return_type, 0); orders.emplace_back(BoundOrderByNode(order2.type, order2.null_order, move(ref))); - ExpressionExecutor executor; + ExpressionExecutor executor(allocator); executor.AddExpression(*orders[0].expression); l2 = make_unique(context, orders, payload_layout); @@ -69144,15 +77219,16 @@ idx_t IEJoinUnion::JoinComplexBlocks(SelectionVector &lsel, SelectionVector &rse class IEJoinState : public OperatorState { public: - explicit IEJoinState(const PhysicalIEJoin &op) : local_left(op, 0) {}; + explicit IEJoinState(Allocator &allocator, const PhysicalIEJoin &op) : local_left(allocator, op, 0) {}; IEJoinLocalState local_left; }; class IEJoinLocalSourceState : public LocalSourceState { public: - explicit IEJoinLocalSourceState(const PhysicalIEJoin &op) - : op(op), true_sel(STANDARD_VECTOR_SIZE), left_matches(nullptr), right_matches(nullptr) { + explicit IEJoinLocalSourceState(Allocator &allocator, const PhysicalIEJoin &op) + : op(op), true_sel(STANDARD_VECTOR_SIZE), left_executor(allocator), right_executor(allocator), + left_matches(nullptr), right_matches(nullptr) { if (op.conditions.size() < 3) { return; @@ -69170,8 +77246,8 @@ class IEJoinLocalSourceState : public LocalSourceState { right_executor.AddExpression(*cond.right); } - left_keys.Initialize(left_types); - right_keys.Initialize(right_types); + left_keys.Initialize(allocator, left_types); + right_keys.Initialize(allocator, right_types); } idx_t SelectOuterRows(bool *matches) { @@ -69441,7 +77517,7 @@ unique_ptr PhysicalIEJoin::GetGlobalSourceState(ClientContext unique_ptr PhysicalIEJoin::GetLocalSourceState(ExecutionContext &context, GlobalSourceState &gstate) const { - return make_unique(*this); + return make_unique(Allocator::Get(context.client), *this); } void PhysicalIEJoin::GetData(ExecutionContext &context, DataChunk &result, GlobalSourceState &gstate, @@ -69600,7 +77676,7 @@ class PhysicalIndexJoin : public PhysicalOperator { bool lhs_first = true; public: - unique_ptr GetOperatorState(ClientContext &context) const override; + unique_ptr GetOperatorState(ExecutionContext &context) const override; OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const override; @@ -69731,7 +77807,9 @@ struct TableScanBindData : public TableFunctionData { //! The table scan function represents a sequential scan over one of DuckDB's base tables. struct TableScanFunction { + static void RegisterFunction(BuiltinFunctions &set); static TableFunction GetFunction(); + static TableFunction GetIndexScanFunction(); static TableCatalogEntry *GetTableEntry(const TableFunction &function, const FunctionData *bind_data); }; @@ -69746,16 +77824,16 @@ namespace duckdb { class IndexJoinOperatorState : public OperatorState { public: - explicit IndexJoinOperatorState(const PhysicalIndexJoin &op) { + IndexJoinOperatorState(Allocator &allocator, const PhysicalIndexJoin &op) : probe_executor(allocator) { rhs_rows.resize(STANDARD_VECTOR_SIZE); result_sizes.resize(STANDARD_VECTOR_SIZE); - join_keys.Initialize(op.condition_types); + join_keys.Initialize(allocator, op.condition_types); for (auto &cond : op.conditions) { probe_executor.AddExpression(*cond.left); } if (!op.fetch_types.empty()) { - rhs_chunk.Initialize(op.fetch_types); + rhs_chunk.Initialize(allocator, op.fetch_types); } rhs_sel.Initialize(STANDARD_VECTOR_SIZE); } @@ -69815,8 +77893,8 @@ PhysicalIndexJoin::PhysicalIndexJoin(LogicalOperator &op, unique_ptr PhysicalIndexJoin::GetOperatorState(ClientContext &context) const { - return make_unique(*this); +unique_ptr PhysicalIndexJoin::GetOperatorState(ExecutionContext &context) const { + return make_unique(Allocator::Get(context.client), *this); } void PhysicalIndexJoin::Output(ExecutionContext &context, DataChunk &input, DataChunk &chunk, @@ -69950,6 +78028,8 @@ vector PhysicalIndexJoin::GetSources() const { + + namespace duckdb { PhysicalJoin::PhysicalJoin(LogicalOperator &op, PhysicalOperatorType type, JoinType join_type, @@ -69977,18 +78057,36 @@ void PhysicalJoin::BuildJoinPipelines(Executor &executor, Pipeline ¤t, Pip op.op_state.reset(); op.sink_state.reset(); - // on the LHS (probe child), the operator becomes a regular operator + // 'current' is the probe pipeline: add this operator state.AddPipelineOperator(current, &op); - if (op.IsSource()) { - // FULL or RIGHT outer join - // schedule a scan of the node as a child pipeline - // this scan has to be performed AFTER all the probing has happened - if (state.recursive_cte) { - throw NotImplementedException("FULL and RIGHT outer joins are not supported in recursive CTEs yet"); + + // Join can become a source operator if it's RIGHT/OUTER, or if the hash join goes out-of-core + // this pipeline has to happen AFTER all the probing has happened + bool add_child_pipeline = false; + if (op.type != PhysicalOperatorType::CROSS_PRODUCT) { + auto &join_op = (PhysicalJoin &)op; + if (IsRightOuterJoin(join_op.join_type)) { + if (state.recursive_cte) { + throw NotImplementedException("FULL and RIGHT outer joins are not supported in recursive CTEs yet"); + } + add_child_pipeline = true; + } + + if (join_op.type == PhysicalOperatorType::HASH_JOIN) { + auto &hash_join_op = (PhysicalHashJoin &)join_op; + hash_join_op.can_go_external = !state.recursive_cte && !IsRightOuterJoin(join_op.join_type) && + join_op.join_type != JoinType::ANTI && join_op.join_type != JoinType::MARK; + if (hash_join_op.can_go_external) { + add_child_pipeline = true; + } + } + + if (add_child_pipeline) { + state.AddChildPipeline(executor, current); } - state.AddChildPipeline(executor, current); } - // continue building the pipeline on this child + + // continue building the LHS pipeline (probe child) op.children[0]->BuildPipelines(executor, current, state); // on the RHS (build side), we construct a new child pipeline with this pipeline as its source @@ -70035,7 +78133,7 @@ class PhysicalNestedLoopJoin : public PhysicalComparisonJoin { public: // Operator Interface - unique_ptr GetOperatorState(ClientContext &context) const override; + unique_ptr GetOperatorState(ExecutionContext &context) const override; OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const override; @@ -70050,6 +78148,8 @@ class PhysicalNestedLoopJoin : public PhysicalComparisonJoin { public: // Source interface unique_ptr GetGlobalSourceState(ClientContext &context) const override; + unique_ptr GetLocalSourceState(ExecutionContext &context, + GlobalSourceState &gstate) const override; void GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, LocalSourceState &lstate) const override; @@ -70077,6 +78177,12 @@ class PhysicalNestedLoopJoin : public PhysicalComparisonJoin { return true; } + static bool IsSupported(const vector &conditions); + +public: + //! Returns a list of the types of the join conditions + vector GetJoinTypes() const; + private: // resolve joins that output max N elements (SEMI, ANTI, MARK) void ResolveSimpleJoin(ExecutionContext &context, DataChunk &input, DataChunk &chunk, OperatorState &state) const; @@ -70094,6 +78200,7 @@ class PhysicalNestedLoopJoin : public PhysicalComparisonJoin { + namespace duckdb { PhysicalNestedLoopJoin::PhysicalNestedLoopJoin(LogicalOperator &op, unique_ptr left, @@ -70106,8 +78213,8 @@ PhysicalNestedLoopJoin::PhysicalNestedLoopJoin(LogicalOperator &op, unique_ptr

(mark_vector); auto &mask = FlatVector::Validity(mark_vector); for (idx_t col_idx = 0; col_idx < join_keys.ColumnCount(); col_idx++) { - VectorData jdata; - join_keys.data[col_idx].Orrify(join_keys.size(), jdata); + UnifiedVectorFormat jdata; + join_keys.data[col_idx].ToUnifiedFormat(join_keys.size(), jdata); if (!jdata.validity.AllValid()) { for (idx_t i = 0; i < join_keys.size(); i++) { auto jidx = jdata.sel->get_index(i); @@ -70193,18 +78300,29 @@ void PhysicalJoin::ConstructMarkJoinResult(DataChunk &join_keys, DataChunk &left } } +bool PhysicalNestedLoopJoin::IsSupported(const vector &conditions) { + for (auto &cond : conditions) { + if (cond.left->return_type.InternalType() == PhysicalType::STRUCT || + cond.left->return_type.InternalType() == PhysicalType::LIST) { + return false; + } + } + return true; +} + //===--------------------------------------------------------------------===// // Sink //===--------------------------------------------------------------------===// class NestedLoopJoinLocalState : public LocalSinkState { public: - explicit NestedLoopJoinLocalState(const vector &conditions) { + explicit NestedLoopJoinLocalState(Allocator &allocator, const vector &conditions) + : rhs_executor(allocator) { vector condition_types; for (auto &cond : conditions) { rhs_executor.AddExpression(*cond.right); condition_types.push_back(cond.right->return_type); } - right_condition.Initialize(condition_types); + right_condition.Initialize(allocator, condition_types); } //! The chunk holding the right condition @@ -70215,20 +78333,30 @@ class NestedLoopJoinLocalState : public LocalSinkState { class NestedLoopJoinGlobalState : public GlobalSinkState { public: - NestedLoopJoinGlobalState() : has_null(false) { + explicit NestedLoopJoinGlobalState(ClientContext &context, const PhysicalNestedLoopJoin &op) + : right_payload_data(context, op.children[1]->types), right_condition_data(context, op.GetJoinTypes()), + has_null(false), right_outer(IsRightOuterJoin(op.join_type)) { } mutex nj_lock; //! Materialized data of the RHS - ChunkCollection right_data; + ColumnDataCollection right_payload_data; //! Materialized join condition of the RHS - ChunkCollection right_chunks; + ColumnDataCollection right_condition_data; //! Whether or not the RHS of the nested loop join has NULL values bool has_null; //! A bool indicating for each tuple in the RHS if they found a match (only used in FULL OUTER JOIN) - unique_ptr right_found_match; + OuterJoinMarker right_outer; }; +vector PhysicalNestedLoopJoin::GetJoinTypes() const { + vector result; + for (auto &op : conditions) { + result.push_back(op.right->return_type); + } + return result; +} + SinkResultType PhysicalNestedLoopJoin::Sink(ExecutionContext &context, GlobalSinkState &state, LocalSinkState &lstate, DataChunk &input) const { auto &gstate = (NestedLoopJoinGlobalState &)state; @@ -70246,10 +78374,10 @@ SinkResultType PhysicalNestedLoopJoin::Sink(ExecutionContext &context, GlobalSin } } - // append the data and the + // append the payload data and the conditions lock_guard nj_guard(gstate.nj_lock); - gstate.right_data.Append(input); - gstate.right_chunks.Append(nlj_state.right_condition); + gstate.right_payload_data.Append(input); + gstate.right_condition_data.Append(nlj_state.right_condition); return SinkResultType::NEED_MORE_INPUT; } @@ -70264,23 +78392,19 @@ void PhysicalNestedLoopJoin::Combine(ExecutionContext &context, GlobalSinkState SinkFinalizeType PhysicalNestedLoopJoin::Finalize(Pipeline &pipeline, Event &event, ClientContext &context, GlobalSinkState &gstate_p) const { auto &gstate = (NestedLoopJoinGlobalState &)gstate_p; - if (join_type == JoinType::OUTER || join_type == JoinType::RIGHT) { - // for FULL/RIGHT OUTER JOIN, initialize found_match to false for every tuple - gstate.right_found_match = unique_ptr(new bool[gstate.right_data.Count()]); - memset(gstate.right_found_match.get(), 0, sizeof(bool) * gstate.right_data.Count()); - } - if (gstate.right_chunks.Count() == 0 && EmptyResultIfRHSIsEmpty()) { + gstate.right_outer.Initialize(gstate.right_payload_data.Count()); + if (gstate.right_payload_data.Count() == 0 && EmptyResultIfRHSIsEmpty()) { return SinkFinalizeType::NO_OUTPUT_POSSIBLE; } return SinkFinalizeType::READY; } unique_ptr PhysicalNestedLoopJoin::GetGlobalSinkState(ClientContext &context) const { - return make_unique(); + return make_unique(context, *this); } unique_ptr PhysicalNestedLoopJoin::GetLocalSinkState(ExecutionContext &context) const { - return make_unique(conditions); + return make_unique(Allocator::Get(context.client), conditions); } //===--------------------------------------------------------------------===// @@ -70288,31 +78412,36 @@ unique_ptr PhysicalNestedLoopJoin::GetLocalSinkState(ExecutionCo //===--------------------------------------------------------------------===// class PhysicalNestedLoopJoinState : public OperatorState { public: - PhysicalNestedLoopJoinState(const PhysicalNestedLoopJoin &op, const vector &conditions) - : fetch_next_left(true), fetch_next_right(false), right_chunk(0), left_tuple(0), right_tuple(0) { + PhysicalNestedLoopJoinState(Allocator &allocator, const PhysicalNestedLoopJoin &op, + const vector &conditions) + : fetch_next_left(true), fetch_next_right(false), lhs_executor(allocator), left_tuple(0), right_tuple(0), + left_outer(IsLeftOuterJoin(op.join_type)) { vector condition_types; for (auto &cond : conditions) { lhs_executor.AddExpression(*cond.left); condition_types.push_back(cond.left->return_type); } - left_condition.Initialize(condition_types); - if (IsLeftOuterJoin(op.join_type)) { - left_found_match = unique_ptr(new bool[STANDARD_VECTOR_SIZE]); - memset(left_found_match.get(), 0, sizeof(bool) * STANDARD_VECTOR_SIZE); - } + left_condition.Initialize(allocator, condition_types); + right_condition.Initialize(allocator, condition_types); + right_payload.Initialize(allocator, op.children[1]->GetTypes()); + left_outer.Initialize(STANDARD_VECTOR_SIZE); } bool fetch_next_left; bool fetch_next_right; - idx_t right_chunk; DataChunk left_condition; //! The executor of the LHS condition ExpressionExecutor lhs_executor; + ColumnDataScanState condition_scan_state; + ColumnDataScanState payload_scan_state; + DataChunk right_condition; + DataChunk right_payload; + idx_t left_tuple; idx_t right_tuple; - unique_ptr left_found_match; + OuterJoinMarker left_outer; public: void Finalize(PhysicalOperator *op, ExecutionContext &context) override { @@ -70320,15 +78449,15 @@ class PhysicalNestedLoopJoinState : public OperatorState { } }; -unique_ptr PhysicalNestedLoopJoin::GetOperatorState(ClientContext &context) const { - return make_unique(*this, conditions); +unique_ptr PhysicalNestedLoopJoin::GetOperatorState(ExecutionContext &context) const { + return make_unique(Allocator::Get(context.client), *this, conditions); } OperatorResultType PhysicalNestedLoopJoin::Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate_p, OperatorState &state_p) const { auto &gstate = (NestedLoopJoinGlobalState &)*sink_state; - if (gstate.right_chunks.Count() == 0) { + if (gstate.right_payload_data.Count() == 0) { // empty RHS if (!EmptyResultIfRHSIsEmpty()) { ConstructEmptyJoinResult(join_type, gstate.has_null, input, chunk); @@ -70364,7 +78493,7 @@ void PhysicalNestedLoopJoin::ResolveSimpleJoin(ExecutionContext &context, DataCh state.lhs_executor.Execute(input, state.left_condition); bool found_match[STANDARD_VECTOR_SIZE] = {false}; - NestedLoopJoinMark::Perform(state.left_condition, gstate.right_chunks, found_match, conditions); + NestedLoopJoinMark::Perform(state.left_condition, gstate.right_condition_data, found_match, conditions); switch (join_type) { case JoinType::MARK: // now construct the mark join result from the found matches @@ -70383,23 +78512,6 @@ void PhysicalNestedLoopJoin::ResolveSimpleJoin(ExecutionContext &context, DataCh } } -void PhysicalJoin::ConstructLeftJoinResult(DataChunk &left, DataChunk &result, bool found_match[]) { - SelectionVector remaining_sel(STANDARD_VECTOR_SIZE); - idx_t remaining_count = 0; - for (idx_t i = 0; i < left.size(); i++) { - if (!found_match[i]) { - remaining_sel.set_index(remaining_count++, i); - } - } - if (remaining_count > 0) { - result.Slice(left, remaining_sel, remaining_count); - for (idx_t idx = left.ColumnCount(); idx < result.ColumnCount(); idx++) { - result.data[idx].SetVectorType(VectorType::CONSTANT_VECTOR); - ConstantVector::SetNull(result.data[idx], true); - } - } -} - OperatorResultType PhysicalNestedLoopJoin::ResolveComplexJoin(ExecutionContext &context, DataChunk &input, DataChunk &chunk, OperatorState &state_p) const { auto &state = (PhysicalNestedLoopJoinState &)state_p; @@ -70409,19 +78521,25 @@ OperatorResultType PhysicalNestedLoopJoin::ResolveComplexJoin(ExecutionContext & do { if (state.fetch_next_right) { // we exhausted the chunk on the right: move to the next chunk on the right - state.right_chunk++; state.left_tuple = 0; state.right_tuple = 0; state.fetch_next_right = false; // check if we exhausted all chunks on the RHS - if (state.right_chunk >= gstate.right_chunks.ChunkCount()) { - state.fetch_next_left = true; + if (gstate.right_condition_data.Scan(state.condition_scan_state, state.right_condition)) { + if (!gstate.right_payload_data.Scan(state.payload_scan_state, state.right_payload)) { + throw InternalException("Nested loop join: payload and conditions are unaligned!?"); + } + if (state.right_condition.size() != state.right_payload.size()) { + throw InternalException("Nested loop join: payload and conditions are unaligned!?"); + } + } else { // we exhausted all chunks on the right: move to the next chunk on the left - if (IsLeftOuterJoin(join_type)) { + state.fetch_next_left = true; + if (state.left_outer.Enabled()) { // left join: before we move to the next chunk, see if we need to output any vectors that didn't // have a match found - PhysicalJoin::ConstructLeftJoinResult(input, chunk, state.left_found_match.get()); - memset(state.left_found_match.get(), 0, sizeof(bool) * STANDARD_VECTOR_SIZE); + state.left_outer.ConstructLeftJoinResult(input, chunk); + state.left_outer.Reset(); } return OperatorResultType::NEED_MORE_INPUT; } @@ -70433,44 +78551,41 @@ OperatorResultType PhysicalNestedLoopJoin::ResolveComplexJoin(ExecutionContext & state.left_tuple = 0; state.right_tuple = 0; - state.right_chunk = 0; + gstate.right_condition_data.InitializeScan(state.condition_scan_state); + gstate.right_condition_data.Scan(state.condition_scan_state, state.right_condition); + + gstate.right_payload_data.InitializeScan(state.payload_scan_state); + gstate.right_payload_data.Scan(state.payload_scan_state, state.right_payload); state.fetch_next_left = false; } // now we have a left and a right chunk that we can join together // note that we only get here in the case of a LEFT, INNER or FULL join auto &left_chunk = input; - auto &right_chunk = gstate.right_chunks.GetChunk(state.right_chunk); - auto &right_data = gstate.right_data.GetChunk(state.right_chunk); + auto &right_condition = state.right_condition; + auto &right_payload = state.right_payload; // sanity check left_chunk.Verify(); - right_chunk.Verify(); - right_data.Verify(); + right_condition.Verify(); + right_payload.Verify(); // now perform the join SelectionVector lvector(STANDARD_VECTOR_SIZE), rvector(STANDARD_VECTOR_SIZE); match_count = NestedLoopJoinInner::Perform(state.left_tuple, state.right_tuple, state.left_condition, - right_chunk, lvector, rvector, conditions); + right_condition, lvector, rvector, conditions); // we have finished resolving the join conditions if (match_count > 0) { // we have matching tuples! // construct the result - if (state.left_found_match) { - for (idx_t i = 0; i < match_count; i++) { - state.left_found_match[lvector.get_index(i)] = true; - } - } - if (gstate.right_found_match) { - for (idx_t i = 0; i < match_count; i++) { - gstate.right_found_match[state.right_chunk * STANDARD_VECTOR_SIZE + rvector.get_index(i)] = true; - } - } + state.left_outer.SetMatches(lvector, match_count); + gstate.right_outer.SetMatches(rvector, match_count, state.condition_scan_state.current_row_index); + chunk.Slice(input, lvector, match_count); - chunk.Slice(right_data, rvector, match_count, input.ColumnCount()); + chunk.Slice(right_payload, rvector, match_count, input.ColumnCount()); } // check if we exhausted the RHS, if we did we need to move to the next right chunk in the next iteration - if (state.right_tuple >= right_chunk.size()) { + if (state.right_tuple >= right_condition.size()) { state.fetch_next_right = true; } } while (match_count == 0); @@ -70480,37 +78595,54 @@ OperatorResultType PhysicalNestedLoopJoin::ResolveComplexJoin(ExecutionContext & //===--------------------------------------------------------------------===// // Source //===--------------------------------------------------------------------===// -class NestedLoopJoinScanState : public GlobalSourceState { +class NestedLoopJoinGlobalScanState : public GlobalSourceState { public: - explicit NestedLoopJoinScanState(const PhysicalNestedLoopJoin &op) : op(op), right_outer_position(0) { + explicit NestedLoopJoinGlobalScanState(const PhysicalNestedLoopJoin &op) : op(op) { + D_ASSERT(op.sink_state); + auto &sink = (NestedLoopJoinGlobalState &)*op.sink_state; + sink.right_outer.InitializeScan(sink.right_payload_data, scan_state); } - mutex lock; const PhysicalNestedLoopJoin &op; - idx_t right_outer_position; + OuterJoinGlobalScanState scan_state; public: idx_t MaxThreads() override { auto &sink = (NestedLoopJoinGlobalState &)*op.sink_state; - return sink.right_chunks.Count() / (STANDARD_VECTOR_SIZE * 10); + return sink.right_outer.MaxThreads(); + } +}; + +class NestedLoopJoinLocalScanState : public LocalSourceState { +public: + explicit NestedLoopJoinLocalScanState(const PhysicalNestedLoopJoin &op, NestedLoopJoinGlobalScanState &gstate) { + D_ASSERT(op.sink_state); + auto &sink = (NestedLoopJoinGlobalState &)*op.sink_state; + sink.right_outer.InitializeScan(gstate.scan_state, scan_state); } + + OuterJoinLocalScanState scan_state; }; unique_ptr PhysicalNestedLoopJoin::GetGlobalSourceState(ClientContext &context) const { - return make_unique(*this); + return make_unique(*this); } -void PhysicalNestedLoopJoin::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, - LocalSourceState &lstate) const { +unique_ptr PhysicalNestedLoopJoin::GetLocalSourceState(ExecutionContext &context, + GlobalSourceState &gstate) const { + return make_unique(*this, (NestedLoopJoinGlobalScanState &)gstate); +} + +void PhysicalNestedLoopJoin::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate_p, + LocalSourceState &lstate_p) const { D_ASSERT(IsRightOuterJoin(join_type)); // check if we need to scan any unmatched tuples from the RHS for the full/right outer join auto &sink = (NestedLoopJoinGlobalState &)*sink_state; - auto &state = (NestedLoopJoinScanState &)gstate; + auto &gstate = (NestedLoopJoinGlobalScanState &)gstate_p; + auto &lstate = (NestedLoopJoinLocalScanState &)lstate_p; - // if the LHS is exhausted in a FULL/RIGHT OUTER JOIN, we scan the found_match for any chunks we - // still need to output - lock_guard l(state.lock); - ConstructFullOuterJoinResult(sink.right_found_match.get(), sink.right_data, chunk, state.right_outer_position); + // if the LHS is exhausted in a FULL/RIGHT OUTER JOIN, we scan chunks we still need to output + sink.right_outer.Scan(gstate.scan_state, lstate.scan_state, chunk); } } // namespace duckdb @@ -70545,7 +78677,7 @@ class PhysicalPiecewiseMergeJoin : public PhysicalRangeJoin { public: // Operator Interface - unique_ptr GetOperatorState(ClientContext &context) const override; + unique_ptr GetOperatorState(ExecutionContext &context) const override; OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const override; @@ -70609,6 +78741,7 @@ class PhysicalPiecewiseMergeJoin : public PhysicalRangeJoin { + namespace duckdb { PhysicalPiecewiseMergeJoin::PhysicalPiecewiseMergeJoin(LogicalOperator &op, unique_ptr left, @@ -70655,7 +78788,8 @@ PhysicalPiecewiseMergeJoin::PhysicalPiecewiseMergeJoin(LogicalOperator &op, uniq //===--------------------------------------------------------------------===// class MergeJoinLocalState : public LocalSinkState { public: - explicit MergeJoinLocalState(const PhysicalRangeJoin &op, const idx_t child) : table(op, child) { + explicit MergeJoinLocalState(Allocator &allocator, const PhysicalRangeJoin &op, const idx_t child) + : table(allocator, op, child) { } //! The local sort state @@ -70701,7 +78835,7 @@ unique_ptr PhysicalPiecewiseMergeJoin::GetGlobalSinkState(Clien unique_ptr PhysicalPiecewiseMergeJoin::GetLocalSinkState(ExecutionContext &context) const { // We only sink the RHS - return make_unique(*this, 1); + return make_unique(Allocator::Get(context.client), *this, 1); } SinkResultType PhysicalPiecewiseMergeJoin::Sink(ExecutionContext &context, GlobalSinkState &gstate_p, @@ -70755,20 +78889,18 @@ class PiecewiseMergeJoinState : public OperatorState { public: using LocalSortedTable = PhysicalRangeJoin::LocalSortedTable; - explicit PiecewiseMergeJoinState(const PhysicalPiecewiseMergeJoin &op, BufferManager &buffer_manager, - bool force_external) - : op(op), buffer_manager(buffer_manager), force_external(force_external), left_position(0), first_fetch(true), - finished(true), right_position(0), right_chunk_index(0) { + explicit PiecewiseMergeJoinState(Allocator &allocator, const PhysicalPiecewiseMergeJoin &op, + BufferManager &buffer_manager, bool force_external) + : allocator(allocator), op(op), buffer_manager(buffer_manager), force_external(force_external), + left_outer(IsLeftOuterJoin(op.join_type)), left_position(0), first_fetch(true), finished(true), + right_position(0), right_chunk_index(0), rhs_executor(allocator) { vector condition_types; for (auto &order : op.lhs_orders) { condition_types.push_back(order.expression->return_type); } - if (IsLeftOuterJoin(op.join_type)) { - lhs_found_match = unique_ptr(new bool[STANDARD_VECTOR_SIZE]); - memset(lhs_found_match.get(), 0, sizeof(bool) * STANDARD_VECTOR_SIZE); - } + left_outer.Initialize(STANDARD_VECTOR_SIZE); lhs_layout.Initialize(op.children[0]->types); - lhs_payload.Initialize(op.children[0]->types); + lhs_payload.Initialize(allocator, op.children[0]->types); lhs_order.emplace_back(op.lhs_orders[0].Copy()); @@ -70779,16 +78911,17 @@ class PiecewiseMergeJoinState : public OperatorState { rhs_executor.AddExpression(*order.expression); condition_types.push_back(order.expression->return_type); } - rhs_keys.Initialize(condition_types); + rhs_keys.Initialize(allocator, condition_types); } + Allocator &allocator; const PhysicalPiecewiseMergeJoin &op; BufferManager &buffer_manager; bool force_external; // Block sorting DataChunk lhs_payload; - unique_ptr lhs_found_match; + OuterJoinMarker left_outer; vector lhs_order; RowLayout lhs_layout; unique_ptr lhs_local_table; @@ -70809,12 +78942,13 @@ class PiecewiseMergeJoinState : public OperatorState { DataChunk rhs_keys; DataChunk rhs_input; ExpressionExecutor rhs_executor; + BufferHandle payload_heap_handle; public: void ResolveJoinKeys(DataChunk &input) { // sort by join key lhs_global_state = make_unique(buffer_manager, lhs_order, lhs_layout); - lhs_local_table = make_unique(op, 0); + lhs_local_table = make_unique(allocator, op, 0); lhs_local_table->Sink(input, *lhs_global_state); // Set external (can be forced with the PRAGMA) @@ -70846,10 +78980,11 @@ class PiecewiseMergeJoinState : public OperatorState { } }; -unique_ptr PhysicalPiecewiseMergeJoin::GetOperatorState(ClientContext &context) const { - auto &buffer_manager = BufferManager::GetBufferManager(context); - auto &config = ClientConfig::GetConfig(context); - return make_unique(*this, buffer_manager, config.force_external); +unique_ptr PhysicalPiecewiseMergeJoin::GetOperatorState(ExecutionContext &context) const { + auto &buffer_manager = BufferManager::GetBufferManager(context.client); + auto &config = ClientConfig::GetConfig(context.client); + return make_unique(Allocator::Get(context.client), *this, buffer_manager, + config.force_external); } static inline idx_t SortedBlockNotNull(const idx_t base, const idx_t count, const idx_t not_null) { @@ -70936,7 +79071,7 @@ static idx_t MergeJoinSimpleBlocks(PiecewiseMergeJoinState &lstate, MergeJoinGlo // get the biggest value from the RHS chunk MergeJoinPinSortingBlock(rread, r_block_idx); - auto &rblock = rread.sb->radix_sorting_data[r_block_idx]; + auto &rblock = *rread.sb->radix_sorting_data[r_block_idx]; const auto r_not_null = SortedBlockNotNull(right_base, rblock.count, rstate.table->count - rstate.table->has_null); if (r_not_null == 0) { @@ -71001,7 +79136,7 @@ void PhysicalPiecewiseMergeJoin::ResolveSimpleJoin(ExecutionContext &context, Da // The only part of the join keys that is actually used is the validity mask. // Since the payload is sorted, we can just set the tail end of the validity masks to invalid. for (auto &key : lhs_table.keys.data) { - key.Normalify(lhs_table.keys.size()); + key.Flatten(lhs_table.keys.size()); auto &mask = FlatVector::Validity(key); if (mask.AllValid()) { continue; @@ -71119,11 +79254,11 @@ OperatorResultType PhysicalPiecewiseMergeJoin::ResolveComplexJoin(ExecutionConte state.finished = false; } if (state.finished) { - if (IsLeftOuterJoin(join_type)) { + if (state.left_outer.Enabled()) { // left join: before we move to the next chunk, see if we need to output any vectors that didn't // have a match found - PhysicalJoin::ConstructLeftJoinResult(state.lhs_payload, chunk, state.lhs_found_match.get()); - memset(state.lhs_found_match.get(), 0, sizeof(bool) * STANDARD_VECTOR_SIZE); + state.left_outer.ConstructLeftJoinResult(state.lhs_payload, chunk); + state.left_outer.Reset(); } state.first_fetch = true; state.finished = false; @@ -71134,7 +79269,7 @@ OperatorResultType PhysicalPiecewiseMergeJoin::ResolveComplexJoin(ExecutionConte const auto lhs_not_null = lhs_table.count - lhs_table.has_null; BlockMergeInfo left_info(*state.lhs_global_state, 0, state.left_position, lhs_not_null); - const auto &rblock = rsorted.radix_sorting_data[state.right_chunk_index]; + const auto &rblock = *rsorted.radix_sorting_data[state.right_chunk_index]; const auto rhs_not_null = SortedBlockNotNull(state.right_base, rblock.count, gstate.table->count - gstate.table->has_null); BlockMergeInfo right_info(gstate.table->global_sort_state, state.right_chunk_index, state.right_position, @@ -71146,7 +79281,7 @@ OperatorResultType PhysicalPiecewiseMergeJoin::ResolveComplexJoin(ExecutionConte // move to the next right chunk state.left_position = 0; state.right_position = 0; - state.right_base += rsorted.radix_sorting_data[state.right_chunk_index].count; + state.right_base += rsorted.radix_sorting_data[state.right_chunk_index]->count; state.right_chunk_index++; if (state.right_chunk_index >= rsorted.radix_sorting_data.size()) { state.finished = true; @@ -71157,8 +79292,8 @@ OperatorResultType PhysicalPiecewiseMergeJoin::ResolveComplexJoin(ExecutionConte for (idx_t c = 0; c < state.lhs_payload.ColumnCount(); ++c) { chunk.data[c].Slice(state.lhs_payload.data[c], left_info.result, result_count); } - SliceSortedPayload(chunk, right_info.state, right_info.block_idx, right_info.result, result_count, - left_cols); + state.payload_heap_handle = SliceSortedPayload(chunk, right_info.state, right_info.block_idx, + right_info.result, result_count, left_cols); chunk.SetCardinality(result_count); auto sel = FlatVector::IncrementalSelectionVector(); @@ -71195,9 +79330,9 @@ OperatorResultType PhysicalPiecewiseMergeJoin::ResolveComplexJoin(ExecutionConte } // found matches: mark the found matches if required - if (state.lhs_found_match) { + if (state.left_outer.Enabled()) { for (idx_t i = 0; i < result_count; i++) { - state.lhs_found_match[left_info.result[sel->get_index(i)]] = true; + state.left_outer.SetMatch(left_info.result[sel->get_index(i)]); } } if (gstate.table->found_match) { @@ -71290,10 +79425,8 @@ void PhysicalPiecewiseMergeJoin::GetData(ExecutionContext &context, DataChunk &r // still need to output const auto found_match = sink.table->found_match.get(); - // ConstructFullOuterJoinResult(sink.table->found_match.get(), sink.right_chunks, chunk, - // state.right_outer_position); DataChunk rhs_chunk; - rhs_chunk.Initialize(sink.table->global_sort_state.payload_layout.GetTypes()); + rhs_chunk.Initialize(Allocator::Get(context.client), sink.table->global_sort_state.payload_layout.GetTypes()); SelectionVector rsel(STANDARD_VECTOR_SIZE); for (;;) { // Read the next sorted chunk @@ -71349,8 +79482,9 @@ void PhysicalPiecewiseMergeJoin::GetData(ExecutionContext &context, DataChunk &r namespace duckdb { -PhysicalRangeJoin::LocalSortedTable::LocalSortedTable(const PhysicalRangeJoin &op, const idx_t child) - : op(op), has_null(0), count(0) { +PhysicalRangeJoin::LocalSortedTable::LocalSortedTable(Allocator &allocator, const PhysicalRangeJoin &op, + const idx_t child) + : op(op), executor(allocator), has_null(0), count(0) { // Initialize order clause expression executor and key DataChunk vector types; for (const auto &cond : op.conditions) { @@ -71359,7 +79493,7 @@ PhysicalRangeJoin::LocalSortedTable::LocalSortedTable(const PhysicalRangeJoin &o types.push_back(expr->return_type); } - keys.Initialize(types); + keys.Initialize(allocator, types); } void PhysicalRangeJoin::LocalSortedTable::Sink(DataChunk &input, GlobalSortState &global_sort_state) { @@ -71391,14 +79525,10 @@ PhysicalRangeJoin::GlobalSortedTable::GlobalSortedTable(ClientContext &context, memory_per_thread(0) { D_ASSERT(orders.size() == 1); - // Set external (can be force with the PRAGMA) + // Set external (can be forced with the PRAGMA) auto &config = ClientConfig::GetConfig(context); global_sort_state.external = config.force_external; - // Memory usage per thread should scale with max mem / num threads - // We take 1/4th of this, to be conservative - idx_t max_memory = global_sort_state.buffer_manager.GetMaxMemory(); - idx_t num_threads = TaskScheduler::GetScheduler(context).NumberOfThreads(); - memory_per_thread = (max_memory / num_threads) / 4; + memory_per_thread = PhysicalRangeJoin::GetMaxThreadMemory(context); } void PhysicalRangeJoin::GlobalSortedTable::Combine(LocalSortedTable <able) { @@ -71551,8 +79681,8 @@ idx_t PhysicalRangeJoin::LocalSortedTable::MergeNulls(const vector 1) { - // Normalify the primary, as it will need to merge arbitrary validity masks - primary.Normalify(count); + // Flatten the primary, as it will need to merge arbitrary validity masks + primary.Flatten(count); auto &pvalidity = FlatVector::Validity(primary); D_ASSERT(keys.ColumnCount() == conditions.size()); for (size_t c = 1; c < keys.data.size(); ++c) { @@ -71560,10 +79690,10 @@ idx_t PhysicalRangeJoin::LocalSortedTable::MergeNulls(const vectorPtr(), - addr_count); + heap_ptr = read_state.payload_heap_handle.Ptr(); } // Deserialize the payload data auto sel = FlatVector::IncrementalSelectionVector(); - for (idx_t col_idx = 0; col_idx < sorted_data.layout.ColumnCount(); col_idx++) { - const auto col_offset = sorted_data.layout.GetOffsets()[col_idx]; - auto &col = payload.data[left_cols + col_idx]; - RowOperations::Gather(addresses, *sel, col, *sel, addr_count, col_offset, col_idx); + for (idx_t col_no = 0; col_no < sorted_data.layout.ColumnCount(); col_no++) { + auto &col = payload.data[left_cols + col_no]; + RowOperations::Gather(addresses, *sel, col, *sel, addr_count, sorted_data.layout, col_no, 0, heap_ptr); col.Slice(gsel, result_count); } + + return move(read_state.payload_heap_handle); } idx_t PhysicalRangeJoin::SelectJoinTail(const ExpressionType &condition, Vector &left, Vector &right, @@ -71768,7 +79899,15 @@ class OrderGlobalState : public GlobalSinkState { class OrderLocalState : public LocalSinkState { public: - OrderLocalState() { + OrderLocalState(ExecutionContext &context, const vector &orders) + : executor(Allocator::Get(context.client)) { + // Initialize order clause expression executor and DataChunk + vector types; + for (auto &order : orders) { + types.push_back(order.expression->return_type); + executor.AddExpression(*order.expression); + } + sort.Initialize(Allocator::Get(context.client), types); } public: @@ -71787,23 +79926,12 @@ unique_ptr PhysicalOrder::GetGlobalSinkState(ClientContext &con auto state = make_unique(BufferManager::GetBufferManager(context), *this, payload_layout); // Set external (can be force with the PRAGMA) state->global_sort_state.external = ClientConfig::GetConfig(context).force_external; - // Memory usage per thread should scale with max mem / num threads - // We take 1/4th of this, to be conservative - idx_t max_memory = BufferManager::GetBufferManager(context).GetMaxMemory(); - idx_t num_threads = TaskScheduler::GetScheduler(context).NumberOfThreads(); - state->memory_per_thread = (max_memory / num_threads) / 4; + state->memory_per_thread = GetMaxThreadMemory(context); return move(state); } unique_ptr PhysicalOrder::GetLocalSinkState(ExecutionContext &context) const { - auto result = make_unique(); - // Initialize order clause expression executor and DataChunk - vector types; - for (auto &order : orders) { - types.push_back(order.expression->return_type); - result->executor.AddExpression(*order.expression); - } - result->sort.Initialize(types); + auto result = make_unique(context, orders); return move(result); } @@ -72021,9 +80149,6 @@ class PhysicalTopN : public PhysicalOperator { } string ParamsToString() const override; - -private: - unique_ptr ComputeTopN(ChunkCollection &big_data, idx_t &heap_size); }; } // namespace duckdb @@ -72083,8 +80208,13 @@ class TopNHeap { public: TopNHeap(ClientContext &context, const vector &payload_types, const vector &orders, idx_t limit, idx_t offset); + TopNHeap(ExecutionContext &context, const vector &payload_types, + const vector &orders, idx_t limit, idx_t offset); + TopNHeap(BufferManager &buffer_manager, Allocator &allocator, const vector &payload_types, + const vector &orders, idx_t limit, idx_t offset); - ClientContext &context; + Allocator &allocator; + BufferManager &buffer_manager; const vector &payload_types; const vector &orders; idx_t limit; @@ -72128,7 +80258,7 @@ TopNSortState::TopNSortState(TopNHeap &heap) : heap(heap), count(0), is_sorted(f void TopNSortState::Initialize() { RowLayout layout; layout.Initialize(heap.payload_types); - auto &buffer_manager = BufferManager::GetBufferManager(heap.context); + auto &buffer_manager = heap.buffer_manager; global_state = make_unique(buffer_manager, heap.orders, layout); local_state = make_unique(); local_state->Initialize(*global_state, buffer_manager); @@ -72168,7 +80298,7 @@ void TopNSortState::Finalize() { global_state->PrepareMergePhase(); while (global_state->sorted_blocks.size() > 1) { - MergeSorter merge_sorter(*global_state, BufferManager::GetBufferManager(heap.context)); + MergeSorter merge_sorter(*global_state, heap.buffer_manager); merge_sorter.PerformInMergeRound(); global_state->CompleteMergeRound(); } @@ -72245,11 +80375,12 @@ void TopNSortState::Scan(TopNScanState &state, DataChunk &chunk) { //===--------------------------------------------------------------------===// // TopNHeap //===--------------------------------------------------------------------===// -TopNHeap::TopNHeap(ClientContext &context_p, const vector &payload_types_p, +TopNHeap::TopNHeap(BufferManager &buffer_manager, Allocator &allocator, const vector &payload_types_p, const vector &orders_p, idx_t limit, idx_t offset) - : context(context_p), payload_types(payload_types_p), orders(orders_p), limit(limit), offset(offset), - sort_state(*this), has_boundary_values(false), final_sel(STANDARD_VECTOR_SIZE), true_sel(STANDARD_VECTOR_SIZE), - false_sel(STANDARD_VECTOR_SIZE), new_remaining_sel(STANDARD_VECTOR_SIZE) { + : allocator(allocator), buffer_manager(buffer_manager), payload_types(payload_types_p), orders(orders_p), + limit(limit), offset(offset), sort_state(*this), executor(allocator), has_boundary_values(false), + final_sel(STANDARD_VECTOR_SIZE), true_sel(STANDARD_VECTOR_SIZE), false_sel(STANDARD_VECTOR_SIZE), + new_remaining_sel(STANDARD_VECTOR_SIZE) { // initialize the executor and the sort_chunk vector sort_types; for (auto &order : orders) { @@ -72257,13 +80388,25 @@ TopNHeap::TopNHeap(ClientContext &context_p, const vector &payload_ sort_types.push_back(expr->return_type); executor.AddExpression(*expr); } - payload_chunk.Initialize(payload_types); - sort_chunk.Initialize(sort_types); - compare_chunk.Initialize(sort_types); - boundary_values.Initialize(sort_types); + payload_chunk.Initialize(allocator, payload_types); + sort_chunk.Initialize(allocator, sort_types); + compare_chunk.Initialize(allocator, sort_types); + boundary_values.Initialize(allocator, sort_types); sort_state.Initialize(); } +TopNHeap::TopNHeap(ClientContext &context, const vector &payload_types, + const vector &orders, idx_t limit, idx_t offset) + : TopNHeap(BufferManager::GetBufferManager(context), BufferAllocator::Get(context), payload_types, orders, limit, + offset) { +} + +TopNHeap::TopNHeap(ExecutionContext &context, const vector &payload_types, + const vector &orders, idx_t limit, idx_t offset) + : TopNHeap(BufferManager::GetBufferManager(context.client), Allocator::Get(context.client), payload_types, orders, + limit, offset) { +} + void TopNHeap::Sink(DataChunk &input) { sort_state.Sink(input); } @@ -72302,7 +80445,7 @@ void TopNHeap::Reduce() { sort_state.InitializeScan(state, false); DataChunk new_chunk; - new_chunk.Initialize(payload_types); + new_chunk.Initialize(allocator, payload_types); DataChunk *current_chunk = &new_chunk; DataChunk *prev_chunk = &payload_chunk; @@ -72429,7 +80572,7 @@ class TopNGlobalState : public GlobalSinkState { class TopNLocalState : public LocalSinkState { public: - TopNLocalState(ClientContext &context, const vector &payload_types, + TopNLocalState(ExecutionContext &context, const vector &payload_types, const vector &orders, idx_t limit, idx_t offset) : heap(context, payload_types, orders, limit, offset) { } @@ -72438,7 +80581,7 @@ class TopNLocalState : public LocalSinkState { }; unique_ptr PhysicalTopN::GetLocalSinkState(ExecutionContext &context) const { - return make_unique(context.client, types, orders, limit, offset); + return make_unique(context, types, orders, limit, offset); } unique_ptr PhysicalTopN::GetGlobalSinkState(ClientContext &context) const { @@ -72613,7 +80756,7 @@ struct StrTimeFormat { //! Format is literals[0], specifiers[0], literals[1], ..., specifiers[n - 1], literals[n] vector literals; //! The constant size that appears in the format string - idx_t constant_size; + idx_t constant_size = 0; //! The max numeric width of the specifier (if it is parsed as a number), or -1 if it is not a number vector numeric_width; @@ -72630,6 +80773,9 @@ struct StrfTimeFormat : public StrTimeFormat { DUCKDB_API static string Format(timestamp_t timestamp, const string &format); + DUCKDB_API void ConvertDateVector(Vector &input, Vector &result, idx_t count); + DUCKDB_API void ConvertTimestampVector(Vector &input, Vector &result, idx_t count); + protected: //! The variable-length specifiers. To determine total string size, these need to be checked. vector var_length_specifiers; @@ -72764,6 +80910,8 @@ struct BufferedCSVReaderOptions { //! Whether file is compressed or not, and if so which compression type //! AUTO_DETECT (default; infer from file extension) FileCompressionType compression = FileCompressionType::AUTO_DETECT; + //! The column names of the columns to read/write + vector names; //===--------------------------------------------------------------------===// // ReadCSVOptions @@ -72790,21 +80938,27 @@ struct BufferedCSVReaderOptions { string file_path; //! Whether or not to include a file name column bool include_file_name = false; + //! Whether or not to include a parsed hive partition columns + bool include_parsed_hive_partitions = false; //===--------------------------------------------------------------------===// // WriteCSVOptions //===--------------------------------------------------------------------===// - //! The column names of the columns to write - vector names; //! True, if column with that index must be quoted vector force_quote; //! The date format to use (if any is specified) std::map date_format = {{LogicalTypeId::DATE, {}}, {LogicalTypeId::TIMESTAMP, {}}}; + //! The date format to use for writing (if any is specified) + std::map write_date_format = {{LogicalTypeId::DATE, {}}, + {LogicalTypeId::TIMESTAMP, {}}}; //! Whether or not a type format is specified std::map has_format = {{LogicalTypeId::DATE, false}, {LogicalTypeId::TIMESTAMP, false}}; + void Serialize(FieldWriter &writer) const; + void Deserialize(FieldReader &reader); + void SetDelimiter(const string &delimiter); //! Set an option that is supported by both reading and writing functions, called by //! the SetReadOption and SetWriteOption methods @@ -72816,6 +80970,7 @@ struct BufferedCSVReaderOptions { void SetReadOption(const string &loption, const Value &value, vector &expected_names); void SetWriteOption(const string &loption, const Value &value); + void SetDateFormat(LogicalTypeId type, const string &format, bool read_format); std::string ToString() const; }; @@ -72834,11 +80989,12 @@ class BufferedCSVReader { BufferedCSVReader(ClientContext &context, BufferedCSVReaderOptions options, const vector &requested_types = vector()); - BufferedCSVReader(FileSystem &fs, FileOpener *opener, BufferedCSVReaderOptions options, + BufferedCSVReader(FileSystem &fs, Allocator &allocator, FileOpener *opener, BufferedCSVReaderOptions options, const vector &requested_types = vector()); ~BufferedCSVReader(); FileSystem &fs; + Allocator &allocator; FileOpener *opener; BufferedCSVReaderOptions options; vector sql_types; @@ -73207,6 +81363,22 @@ void BufferedCSVReaderOptions::SetDelimiter(const string &input) { } } +void BufferedCSVReaderOptions::SetDateFormat(LogicalTypeId type, const string &format, bool read_format) { + string error; + if (read_format) { + auto &date_format = this->date_format[type]; + error = StrTimeFormat::ParseFormatSpecifier(format, date_format); + date_format.format_specifier = format; + } else { + auto &date_format = this->write_date_format[type]; + error = StrTimeFormat::ParseFormatSpecifier(format, date_format); + } + if (!error.empty()) { + throw InvalidInputException("Could not parse DATEFORMAT: %s", error.c_str()); + } + has_format[type] = true; +} + void BufferedCSVReaderOptions::SetReadOption(const string &loption, const Value &value, vector &expected_names) { if (SetBaseOption(loption, value)) { @@ -73251,22 +81423,10 @@ void BufferedCSVReaderOptions::SetReadOption(const string &loption, const Value force_not_null = ParseColumnList(value, expected_names, loption); } else if (loption == "date_format" || loption == "dateformat") { string format = ParseString(value, loption); - auto &date_format = this->date_format[LogicalTypeId::DATE]; - string error = StrTimeFormat::ParseFormatSpecifier(format, date_format); - date_format.format_specifier = format; - if (!error.empty()) { - throw InvalidInputException("Could not parse DATEFORMAT: %s", error.c_str()); - } - has_format[LogicalTypeId::DATE] = true; + SetDateFormat(LogicalTypeId::DATE, format, true); } else if (loption == "timestamp_format" || loption == "timestampformat") { string format = ParseString(value, loption); - auto ×tamp_format = date_format[LogicalTypeId::TIMESTAMP]; - string error = StrTimeFormat::ParseFormatSpecifier(format, timestamp_format); - timestamp_format.format_specifier = format; - if (!error.empty()) { - throw InvalidInputException("Could not parse TIMESTAMPFORMAT: %s", error.c_str()); - } - has_format[LogicalTypeId::TIMESTAMP] = true; + SetDateFormat(LogicalTypeId::TIMESTAMP, format, true); } else if (loption == "escape") { escape = ParseString(value, loption); has_escape = true; @@ -73284,6 +81444,15 @@ void BufferedCSVReaderOptions::SetWriteOption(const string &loption, const Value if (loption == "force_quote") { force_quote = ParseColumnList(value, names, loption); + } else if (loption == "date_format" || loption == "dateformat") { + string format = ParseString(value, loption); + SetDateFormat(LogicalTypeId::DATE, format, false); + } else if (loption == "timestamp_format" || loption == "timestampformat") { + string format = ParseString(value, loption); + if (StringUtil::Lower(format) == "iso") { + format = "%Y-%m-%dT%H:%M:%S.%fZ"; + } + SetDateFormat(LogicalTypeId::TIMESTAMP, format, false); } else { throw BinderException("Unrecognized option CSV writer \"%s\"", loption); } @@ -73390,14 +81559,20 @@ static bool StartsWithNumericDate(string &separator, const string &value) { string GenerateDateFormat(const string &separator, const char *format_template) { string format_specifier = format_template; - - // replace all dashes with the separator - for (auto pos = std::find(format_specifier.begin(), format_specifier.end(), '-'); pos != format_specifier.end(); - pos = std::find(pos + separator.size(), format_specifier.end(), '-')) { - format_specifier.replace(pos, pos + 1, separator); + auto amount_of_dashes = std::count(format_specifier.begin(), format_specifier.end(), '-'); + if (!amount_of_dashes) { + return format_specifier; } - - return format_specifier; + string result; + result.reserve(format_specifier.size() - amount_of_dashes + (amount_of_dashes * separator.size())); + for (auto &character : format_specifier) { + if (character == '-') { + result += separator; + } else { + result += character; + } + } + return result; } TextSearchShiftArray::TextSearchShiftArray() { @@ -73431,17 +81606,18 @@ TextSearchShiftArray::TextSearchShiftArray(string search_term) : length(search_t } } -BufferedCSVReader::BufferedCSVReader(FileSystem &fs_p, FileOpener *opener_p, BufferedCSVReaderOptions options_p, - const vector &requested_types) - : fs(fs_p), opener(opener_p), options(move(options_p)), buffer_size(0), position(0), start(0) { +BufferedCSVReader::BufferedCSVReader(FileSystem &fs_p, Allocator &allocator, FileOpener *opener_p, + BufferedCSVReaderOptions options_p, const vector &requested_types) + : fs(fs_p), allocator(allocator), opener(opener_p), options(move(options_p)), buffer_size(0), position(0), + start(0) { file_handle = OpenCSV(options); Initialize(requested_types); } BufferedCSVReader::BufferedCSVReader(ClientContext &context, BufferedCSVReaderOptions options_p, const vector &requested_types) - : BufferedCSVReader(FileSystem::GetFileSystem(context), FileSystem::GetFileOpener(context), move(options_p), - requested_types) { + : BufferedCSVReader(FileSystem::GetFileSystem(context), Allocator::Get(context), FileSystem::GetFileOpener(context), + move(options_p), requested_types) { } BufferedCSVReader::~BufferedCSVReader() { @@ -73608,7 +81784,7 @@ void BufferedCSVReader::InitParseChunk(idx_t num_cols) { // initialize the parse_chunk with a set of VARCHAR types vector varchar_types(num_cols, LogicalType::VARCHAR); - parse_chunk.Initialize(varchar_types); + parse_chunk.Initialize(allocator, varchar_types); } } @@ -73935,7 +82111,7 @@ void BufferedCSVReader::DetectCandidateTypes(const vector &type_can // jump to beginning and skip potential header JumpToBeginning(options.skip_rows, true); DataChunk header_row; - header_row.Initialize(sql_types); + header_row.Initialize(allocator, sql_types); parse_chunk.Copy(header_row); if (header_row.size() == 0) { @@ -74055,7 +82231,7 @@ void BufferedCSVReader::DetectCandidateTypes(const vector &type_can best_format_candidates = format_candidates; best_header_row.Destroy(); auto header_row_types = header_row.GetTypes(); - best_header_row.Initialize(header_row_types); + best_header_row.Initialize(allocator, header_row_types); header_row.Copy(best_header_row); } } @@ -75100,7 +83276,7 @@ SinkResultType PhysicalCopyToFile::Sink(ExecutionContext &context, GlobalSinkSta auto &l = (CopyToFunctionLocalState &)lstate; g.rows_copied += input.size(); - function.copy_to_sink(context.client, *bind_data, *g.global_state, *l.local_state, input); + function.copy_to_sink(context, *bind_data, *g.global_state, *l.local_state, input); return SinkResultType::NEED_MORE_INPUT; } @@ -75109,7 +83285,7 @@ void PhysicalCopyToFile::Combine(ExecutionContext &context, GlobalSinkState &gst auto &l = (CopyToFunctionLocalState &)lstate; if (function.copy_to_combine) { - function.copy_to_combine(context.client, *bind_data, *g.global_state, *l.local_state); + function.copy_to_combine(context, *bind_data, *g.global_state, *l.local_state); } } @@ -75127,7 +83303,7 @@ SinkFinalizeType PhysicalCopyToFile::Finalize(Pipeline &pipeline, Event &event, } unique_ptr PhysicalCopyToFile::GetLocalSinkState(ExecutionContext &context) const { - return make_unique(function.copy_to_initialize_local(context.client, *bind_data)); + return make_unique(function.copy_to_initialize_local(context, *bind_data)); } unique_ptr PhysicalCopyToFile::GetGlobalSinkState(ClientContext &context) const { return make_unique(function.copy_to_initialize_global(context, *bind_data, file_path)); @@ -75221,6 +83397,7 @@ class PhysicalDelete : public PhysicalOperator { + namespace duckdb { //===--------------------------------------------------------------------===// @@ -75228,19 +83405,19 @@ namespace duckdb { //===--------------------------------------------------------------------===// class DeleteGlobalState : public GlobalSinkState { public: - DeleteGlobalState() : deleted_count(0), returned_chunk_count(0) { + explicit DeleteGlobalState(ClientContext &context, const vector &return_types) + : deleted_count(0), return_collection(context, return_types) { } mutex delete_lock; idx_t deleted_count; - ChunkCollection return_chunk_collection; - idx_t returned_chunk_count; + ColumnDataCollection return_collection; }; class DeleteLocalState : public LocalSinkState { public: - explicit DeleteLocalState(const vector &table_types) { - delete_chunk.Initialize(table_types); + DeleteLocalState(Allocator &allocator, const vector &table_types) { + delete_chunk.Initialize(allocator, table_types); } DataChunk delete_chunk; }; @@ -75262,9 +83439,9 @@ SinkResultType PhysicalDelete::Sink(ExecutionContext &context, GlobalSinkState & lock_guard delete_guard(gstate.delete_lock); if (return_chunk) { - row_identifiers.Normalify(input.size()); + row_identifiers.Flatten(input.size()); table.Fetch(transaction, ustate.delete_chunk, column_ids, row_identifiers, input.size(), cfs); - gstate.return_chunk_collection.Append(ustate.delete_chunk); + gstate.return_collection.Append(ustate.delete_chunk); } gstate.deleted_count += table.Delete(tableref, context.client, row_identifiers, input.size()); @@ -75272,11 +83449,11 @@ SinkResultType PhysicalDelete::Sink(ExecutionContext &context, GlobalSinkState & } unique_ptr PhysicalDelete::GetGlobalSinkState(ClientContext &context) const { - return make_unique(); + return make_unique(context, GetTypes()); } unique_ptr PhysicalDelete::GetLocalSinkState(ExecutionContext &context) const { - return make_unique(table.GetTypes()); + return make_unique(Allocator::Get(context.client), table.GetTypes()); } //===--------------------------------------------------------------------===// @@ -75284,14 +83461,20 @@ unique_ptr PhysicalDelete::GetLocalSinkState(ExecutionContext &c //===--------------------------------------------------------------------===// class DeleteSourceState : public GlobalSourceState { public: - DeleteSourceState() : finished(false) { + explicit DeleteSourceState(const PhysicalDelete &op) : finished(false) { + if (op.return_chunk) { + D_ASSERT(op.sink_state); + auto &g = (DeleteGlobalState &)*op.sink_state; + g.return_collection.InitializeScan(scan_state); + } } + ColumnDataScanState scan_state; bool finished; }; unique_ptr PhysicalDelete::GetGlobalSourceState(ClientContext &context) const { - return make_unique(); + return make_unique(*this); } void PhysicalDelete::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, @@ -75306,18 +83489,10 @@ void PhysicalDelete::GetData(ExecutionContext &context, DataChunk &chunk, Global chunk.SetCardinality(1); chunk.SetValue(0, 0, Value::BIGINT(g.deleted_count)); state.finished = true; - } - - idx_t chunk_return = g.returned_chunk_count; - if (chunk_return >= g.return_chunk_collection.Chunks().size()) { return; } - chunk.Reference(g.return_chunk_collection.GetChunk(chunk_return)); - chunk.SetCardinality((g.return_chunk_collection.GetChunk(chunk_return)).size()); - g.returned_chunk_count += 1; - if (g.returned_chunk_count >= g.return_chunk_collection.Chunks().size()) { - state.finished = true; - } + + g.return_collection.Scan(state.scan_state, chunk); } } // namespace duckdb @@ -75350,6 +83525,7 @@ void PhysicalDelete::GetData(ExecutionContext &context, DataChunk &chunk, Global namespace duckdb { +class TableCatalogEntry; struct ExportedTableData { //! Name of the exported table @@ -75424,6 +83600,7 @@ class PhysicalExport : public PhysicalOperator { + #include #include @@ -75528,6 +83705,7 @@ void PhysicalExport::GetData(ExecutionContext &context, DataChunk &chunk, Global vector tables; vector views; vector indexes; + vector macros; auto schema_list = Catalog::GetCatalog(ccontext).schemas->GetEntries(context.client); for (auto &schema : schema_list) { @@ -75547,6 +83725,16 @@ void PhysicalExport::GetData(ExecutionContext &context, DataChunk &chunk, Global schema->Scan(context.client, CatalogType::TYPE_ENTRY, [&](CatalogEntry *entry) { custom_types.push_back(entry); }); schema->Scan(context.client, CatalogType::INDEX_ENTRY, [&](CatalogEntry *entry) { indexes.push_back(entry); }); + schema->Scan(context.client, CatalogType::MACRO_ENTRY, [&](CatalogEntry *entry) { + if (!entry->internal && entry->type == CatalogType::MACRO_ENTRY) { + macros.push_back(entry); + } + }); + schema->Scan(context.client, CatalogType::TABLE_MACRO_ENTRY, [&](CatalogEntry *entry) { + if (!entry->internal && entry->type == CatalogType::TABLE_MACRO_ENTRY) { + macros.push_back(entry); + } + }); } // consider the order of tables because of foreign key constraint @@ -75554,6 +83742,10 @@ void PhysicalExport::GetData(ExecutionContext &context, DataChunk &chunk, Global tables.push_back((CatalogEntry *)exported_tables.data[i].entry); } + // order macro's by timestamp so nested macro's are imported nicely + sort(macros.begin(), macros.end(), + [](const CatalogEntry *lhs, const CatalogEntry *rhs) { return lhs->oid < rhs->oid; }); + // write the schema.sql file // export order is SCHEMA -> SEQUENCE -> TABLE -> VIEW -> INDEX @@ -75564,6 +83756,7 @@ void PhysicalExport::GetData(ExecutionContext &context, DataChunk &chunk, Global WriteCatalogEntries(ss, tables); WriteCatalogEntries(ss, views); WriteCatalogEntries(ss, indexes); + WriteCatalogEntries(ss, macros); WriteStringStreamToFile(fs, opener, ss, fs.JoinPath(info->file_path, "schema.sql")); @@ -75676,20 +83869,21 @@ namespace duckdb { //===--------------------------------------------------------------------===// class InsertGlobalState : public GlobalSinkState { public: - InsertGlobalState() : insert_count(0), returned_chunk_count(0) { + explicit InsertGlobalState(ClientContext &context, const vector &return_types) + : insert_count(0), return_collection(context, return_types) { } mutex lock; idx_t insert_count; - ChunkCollection return_chunk_collection; - idx_t returned_chunk_count; + ColumnDataCollection return_collection; }; class InsertLocalState : public LocalSinkState { public: - InsertLocalState(const vector &types, const vector> &bound_defaults) - : default_executor(bound_defaults) { - insert_chunk.Initialize(types); + InsertLocalState(Allocator &allocator, const vector &types, + const vector> &bound_defaults) + : default_executor(allocator, bound_defaults) { + insert_chunk.Initialize(allocator, types); } DataChunk insert_chunk; @@ -75709,7 +83903,7 @@ SinkResultType PhysicalInsert::Sink(ExecutionContext &context, GlobalSinkState & auto &gstate = (InsertGlobalState &)state; auto &istate = (InsertLocalState &)lstate; - chunk.Normalify(); + chunk.Flatten(); istate.default_executor.SetChunk(chunk); istate.insert_chunk.Reset(); @@ -75745,7 +83939,7 @@ SinkResultType PhysicalInsert::Sink(ExecutionContext &context, GlobalSinkState & table->storage->Append(*table, context.client, istate.insert_chunk); if (return_chunk) { - gstate.return_chunk_collection.Append(istate.insert_chunk); + gstate.return_collection.Append(istate.insert_chunk); } gstate.insert_count += chunk.size(); @@ -75753,11 +83947,11 @@ SinkResultType PhysicalInsert::Sink(ExecutionContext &context, GlobalSinkState & } unique_ptr PhysicalInsert::GetGlobalSinkState(ClientContext &context) const { - return make_unique(); + return make_unique(context, GetTypes()); } unique_ptr PhysicalInsert::GetLocalSinkState(ExecutionContext &context) const { - return make_unique(table->GetTypes(), bound_defaults); + return make_unique(Allocator::Get(context.client), table->GetTypes(), bound_defaults); } void PhysicalInsert::Combine(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate) const { @@ -75772,14 +83966,20 @@ void PhysicalInsert::Combine(ExecutionContext &context, GlobalSinkState &gstate, //===--------------------------------------------------------------------===// class InsertSourceState : public GlobalSourceState { public: - InsertSourceState() : finished(false) { + explicit InsertSourceState(const PhysicalInsert &op) : finished(false) { + if (op.return_chunk) { + D_ASSERT(op.sink_state); + auto &g = (InsertGlobalState &)*op.sink_state; + g.return_collection.InitializeScan(scan_state); + } } + ColumnDataScanState scan_state; bool finished; }; unique_ptr PhysicalInsert::GetGlobalSourceState(ClientContext &context) const { - return make_unique(); + return make_unique(*this); } void PhysicalInsert::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, @@ -75793,19 +83993,10 @@ void PhysicalInsert::GetData(ExecutionContext &context, DataChunk &chunk, Global chunk.SetCardinality(1); chunk.SetValue(0, 0, Value::BIGINT(insert_gstate.insert_count)); state.finished = true; - } - - idx_t chunk_return = insert_gstate.returned_chunk_count; - if (chunk_return >= insert_gstate.return_chunk_collection.Chunks().size()) { return; } - chunk.Reference(insert_gstate.return_chunk_collection.GetChunk(chunk_return)); - chunk.SetCardinality((insert_gstate.return_chunk_collection.GetChunk(chunk_return)).size()); - insert_gstate.returned_chunk_count += 1; - if (insert_gstate.returned_chunk_count >= insert_gstate.return_chunk_collection.Chunks().size()) { - state.finished = true; - } + insert_gstate.return_collection.Scan(state.scan_state, chunk); } } // namespace duckdb @@ -75885,30 +84076,30 @@ namespace duckdb { //===--------------------------------------------------------------------===// class UpdateGlobalState : public GlobalSinkState { public: - UpdateGlobalState() : updated_count(0), returned_chunk_count(0) { + explicit UpdateGlobalState(ClientContext &context, const vector &return_types) + : updated_count(0), return_collection(context, return_types) { } mutex lock; idx_t updated_count; unordered_set updated_columns; - ChunkCollection return_chunk_collection; - idx_t returned_chunk_count; + ColumnDataCollection return_collection; }; class UpdateLocalState : public LocalSinkState { public: - UpdateLocalState(const vector> &expressions, const vector &table_types, - const vector> &bound_defaults) - : default_executor(bound_defaults) { + UpdateLocalState(Allocator &allocator, const vector> &expressions, + const vector &table_types, const vector> &bound_defaults) + : default_executor(allocator, bound_defaults) { // initialize the update chunk vector update_types; update_types.reserve(expressions.size()); for (auto &expr : expressions) { update_types.push_back(expr->return_type); } - update_chunk.Initialize(update_types); + update_chunk.Initialize(allocator, update_types); // initialize the mock chunk - mock_chunk.Initialize(table_types); + mock_chunk.Initialize(allocator, table_types); } DataChunk update_chunk; @@ -75924,7 +84115,7 @@ SinkResultType PhysicalUpdate::Sink(ExecutionContext &context, GlobalSinkState & DataChunk &update_chunk = ustate.update_chunk; DataChunk &mock_chunk = ustate.mock_chunk; - chunk.Normalify(); + chunk.Flatten(); ustate.default_executor.SetChunk(chunk); // update data in the base table @@ -75982,7 +84173,7 @@ SinkResultType PhysicalUpdate::Sink(ExecutionContext &context, GlobalSinkState & } if (return_chunk) { - gstate.return_chunk_collection.Append(mock_chunk); + gstate.return_collection.Append(mock_chunk); } gstate.updated_count += chunk.size(); @@ -75991,11 +84182,11 @@ SinkResultType PhysicalUpdate::Sink(ExecutionContext &context, GlobalSinkState & } unique_ptr PhysicalUpdate::GetGlobalSinkState(ClientContext &context) const { - return make_unique(); + return make_unique(context, GetTypes()); } unique_ptr PhysicalUpdate::GetLocalSinkState(ExecutionContext &context) const { - return make_unique(expressions, table.GetTypes(), bound_defaults); + return make_unique(Allocator::Get(context.client), expressions, table.GetTypes(), bound_defaults); } void PhysicalUpdate::Combine(ExecutionContext &context, GlobalSinkState &gstate, LocalSinkState &lstate) const { @@ -76010,14 +84201,20 @@ void PhysicalUpdate::Combine(ExecutionContext &context, GlobalSinkState &gstate, //===--------------------------------------------------------------------===// class UpdateSourceState : public GlobalSourceState { public: - UpdateSourceState() : finished(false) { + explicit UpdateSourceState(const PhysicalUpdate &op) : finished(false) { + if (op.return_chunk) { + D_ASSERT(op.sink_state); + auto &g = (UpdateGlobalState &)*op.sink_state; + g.return_collection.InitializeScan(scan_state); + } } + ColumnDataScanState scan_state; bool finished; }; unique_ptr PhysicalUpdate::GetGlobalSourceState(ClientContext &context) const { - return make_unique(); + return make_unique(*this); } void PhysicalUpdate::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, @@ -76031,18 +84228,10 @@ void PhysicalUpdate::GetData(ExecutionContext &context, DataChunk &chunk, Global chunk.SetCardinality(1); chunk.SetValue(0, 0, Value::BIGINT(g.updated_count)); state.finished = true; - } - - idx_t chunk_return = g.returned_chunk_count; - if (chunk_return >= g.return_chunk_collection.Chunks().size()) { return; } - chunk.Reference(g.return_chunk_collection.GetChunk(chunk_return)); - chunk.SetCardinality((g.return_chunk_collection.GetChunk(chunk_return)).size()); - g.returned_chunk_count += 1; - if (g.returned_chunk_count >= g.return_chunk_collection.Chunks().size()) { - state.finished = true; - } + + g.return_collection.Scan(state.scan_state, chunk); } } // namespace duckdb @@ -76069,7 +84258,7 @@ class PhysicalProjection : public PhysicalOperator { vector> select_list; public: - unique_ptr GetOperatorState(ClientContext &context) const override; + unique_ptr GetOperatorState(ExecutionContext &context) const override; OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const override; @@ -76089,7 +84278,8 @@ namespace duckdb { class ProjectionState : public OperatorState { public: - explicit ProjectionState(const vector> &expressions) : executor(expressions) { + explicit ProjectionState(ExecutionContext &context, const vector> &expressions) + : executor(Allocator::Get(context.client), expressions) { } ExpressionExecutor executor; @@ -76113,8 +84303,8 @@ OperatorResultType PhysicalProjection::Execute(ExecutionContext &context, DataCh return OperatorResultType::NEED_MORE_INPUT; } -unique_ptr PhysicalProjection::GetOperatorState(ClientContext &context) const { - return make_unique(select_list); +unique_ptr PhysicalProjection::GetOperatorState(ExecutionContext &context) const { + return make_unique(context, select_list); } string PhysicalProjection::ParamsToString() const { @@ -76150,7 +84340,7 @@ class PhysicalTableInOutFunction : public PhysicalOperator { idx_t estimated_cardinality); public: - unique_ptr GetOperatorState(ClientContext &context) const override; + unique_ptr GetOperatorState(ExecutionContext &context) const override; unique_ptr GetGlobalOperatorState(ClientContext &context) const override; OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const override; @@ -76196,11 +84386,12 @@ PhysicalTableInOutFunction::PhysicalTableInOutFunction(vector types function(move(function_p)), bind_data(move(bind_data_p)), column_ids(move(column_ids_p)) { } -unique_ptr PhysicalTableInOutFunction::GetOperatorState(ClientContext &context) const { +unique_ptr PhysicalTableInOutFunction::GetOperatorState(ExecutionContext &context) const { + auto &gstate = (TableInOutGlobalState &)*op_state; auto result = make_unique(); if (function.init_local) { TableFunctionInitInput input(bind_data.get(), column_ids, nullptr); - result->local_state = function.init_local(context, input, nullptr); + result->local_state = function.init_local(context, input, gstate.global_state.get()); } return move(result); } @@ -76219,7 +84410,7 @@ OperatorResultType PhysicalTableInOutFunction::Execute(ExecutionContext &context auto &gstate = (TableInOutGlobalState &)gstate_p; auto &state = (TableInOutLocalState &)state_p; TableFunctionInput data(bind_data.get(), state.local_state.get(), gstate.global_state.get()); - return function.in_out_function(context.client, data, input, chunk); + return function.in_out_function(context, data, input, chunk); } } // namespace duckdb @@ -76249,7 +84440,7 @@ class PhysicalUnnest : public PhysicalOperator { vector> select_list; public: - unique_ptr GetOperatorState(ClientContext &context) const override; + unique_ptr GetOperatorState(ExecutionContext &context) const override; OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const override; @@ -76258,8 +84449,9 @@ class PhysicalUnnest : public PhysicalOperator { } public: - static unique_ptr GetState(ClientContext &context); - static OperatorResultType ExecuteInternal(ClientContext &context, DataChunk &input, DataChunk &chunk, + static unique_ptr GetState(ExecutionContext &context, + const vector> &select_list); + static OperatorResultType ExecuteInternal(ExecutionContext &context, DataChunk &input, DataChunk &chunk, OperatorState &state, const vector> &select_list, bool include_input = true); }; @@ -76277,7 +84469,19 @@ namespace duckdb { class UnnestOperatorState : public OperatorState { public: - UnnestOperatorState() : parent_position(0), list_position(0), list_length(-1), first_fetch(true) { + UnnestOperatorState(Allocator &allocator, const vector> &select_list) + : parent_position(0), list_position(0), list_length(-1), first_fetch(true), executor(allocator) { + vector list_data_types; + for (auto &exp : select_list) { + D_ASSERT(exp->type == ExpressionType::BOUND_UNNEST); + auto bue = (BoundUnnestExpression *)exp.get(); + list_data_types.push_back(bue->child->return_type); + executor.AddExpression(*bue->child.get()); + } + list_data.Initialize(allocator, list_data_types); + + list_vector_data.resize(list_data.ColumnCount()); + list_child_data.resize(list_data.ColumnCount()); } idx_t parent_position; @@ -76285,9 +84489,10 @@ class UnnestOperatorState : public OperatorState { int64_t list_length; bool first_fetch; + ExpressionExecutor executor; DataChunk list_data; - vector list_vector_data; - vector list_child_data; + vector list_vector_data; + vector list_child_data; }; // this implements a sorted window functions variant @@ -76317,7 +84522,7 @@ static void UnnestNull(idx_t start, idx_t end, Vector &result) { } template -static void TemplatedUnnest(VectorData &vdata, idx_t start, idx_t end, Vector &result) { +static void TemplatedUnnest(UnifiedVectorFormat &vdata, idx_t start, idx_t end, Vector &result) { auto source_data = (T *)vdata.data; auto &source_mask = vdata.validity; auto result_data = FlatVector::GetData(result); @@ -76335,7 +84540,7 @@ static void TemplatedUnnest(VectorData &vdata, idx_t start, idx_t end, Vector &r } } -static void UnnestValidity(VectorData &vdata, idx_t start, idx_t end, Vector &result) { +static void UnnestValidity(UnifiedVectorFormat &vdata, idx_t start, idx_t end, Vector &result) { auto &source_mask = vdata.validity; auto &result_mask = FlatVector::Validity(result); @@ -76346,7 +84551,8 @@ static void UnnestValidity(VectorData &vdata, idx_t start, idx_t end, Vector &re } } -static void UnnestVector(VectorData &vdata, Vector &source, idx_t list_size, idx_t start, idx_t end, Vector &result) { +static void UnnestVector(UnifiedVectorFormat &vdata, Vector &source, idx_t list_size, idx_t start, idx_t end, + Vector &result) { switch (result.GetType().InternalType()) { case PhysicalType::BOOL: case PhysicalType::INT8: @@ -76400,8 +84606,8 @@ static void UnnestVector(VectorData &vdata, Vector &source, idx_t list_size, idx auto &target_entries = StructVector::GetEntries(result); UnnestValidity(vdata, start, end, result); for (idx_t i = 0; i < source_entries.size(); i++) { - VectorData sdata; - source_entries[i]->Orrify(list_size, sdata); + UnifiedVectorFormat sdata; + source_entries[i]->ToUnifiedFormat(list_size, sdata); UnnestVector(sdata, *source_entries[i], list_size, start, end, *target_entries[i]); } break; @@ -76411,15 +84617,16 @@ static void UnnestVector(VectorData &vdata, Vector &source, idx_t list_size, idx } } -unique_ptr PhysicalUnnest::GetOperatorState(ClientContext &context) const { - return PhysicalUnnest::GetState(context); +unique_ptr PhysicalUnnest::GetOperatorState(ExecutionContext &context) const { + return PhysicalUnnest::GetState(context, select_list); } -unique_ptr PhysicalUnnest::GetState(ClientContext &context) { - return make_unique(); +unique_ptr PhysicalUnnest::GetState(ExecutionContext &context, + const vector> &select_list) { + return make_unique(Allocator::Get(context.client), select_list); } -OperatorResultType PhysicalUnnest::ExecuteInternal(ClientContext &context, DataChunk &input, DataChunk &chunk, +OperatorResultType PhysicalUnnest::ExecuteInternal(ExecutionContext &context, DataChunk &input, DataChunk &chunk, OperatorState &state_p, const vector> &select_list, bool include_input) { @@ -76427,38 +84634,29 @@ OperatorResultType PhysicalUnnest::ExecuteInternal(ClientContext &context, DataC do { if (state.first_fetch) { // get the list data to unnest - ExpressionExecutor executor; - vector list_data_types; - for (auto &exp : select_list) { - D_ASSERT(exp->type == ExpressionType::BOUND_UNNEST); - auto bue = (BoundUnnestExpression *)exp.get(); - list_data_types.push_back(bue->child->return_type); - executor.AddExpression(*bue->child.get()); - } - state.list_data.Destroy(); - state.list_data.Initialize(list_data_types); - executor.Execute(input, state.list_data); + state.list_data.Reset(); + state.executor.Execute(input, state.list_data); // paranoia aplenty state.list_data.Verify(); D_ASSERT(input.size() == state.list_data.size()); D_ASSERT(state.list_data.ColumnCount() == select_list.size()); + D_ASSERT(state.list_vector_data.size() == state.list_data.ColumnCount()); + D_ASSERT(state.list_child_data.size() == state.list_data.ColumnCount()); - // initialize VectorData object so the nullmask can accessed - state.list_vector_data.resize(state.list_data.ColumnCount()); - state.list_child_data.resize(state.list_data.ColumnCount()); + // initialize UnifiedVectorFormat object so the nullmask can accessed for (idx_t col_idx = 0; col_idx < state.list_data.ColumnCount(); col_idx++) { auto &list_vector = state.list_data.data[col_idx]; - list_vector.Orrify(state.list_data.size(), state.list_vector_data[col_idx]); + list_vector.ToUnifiedFormat(state.list_data.size(), state.list_vector_data[col_idx]); if (list_vector.GetType() == LogicalType::SQLNULL) { // UNNEST(NULL) auto &child_vector = list_vector; - child_vector.Orrify(0, state.list_child_data[col_idx]); + child_vector.ToUnifiedFormat(0, state.list_child_data[col_idx]); } else { auto list_size = ListVector::GetListSize(list_vector); auto &child_vector = ListVector::GetEntry(list_vector); - child_vector.Orrify(list_size, state.list_child_data[col_idx]); + child_vector.ToUnifiedFormat(list_size, state.list_child_data[col_idx]); } } state.first_fetch = false; @@ -76563,7 +84761,7 @@ OperatorResultType PhysicalUnnest::ExecuteInternal(ClientContext &context, DataC OperatorResultType PhysicalUnnest::Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const { - return ExecuteInternal(context.client, input, chunk, state, select_list); + return ExecuteInternal(context, input, chunk, state, select_list); } } // namespace duckdb @@ -76573,39 +84771,38 @@ OperatorResultType PhysicalUnnest::Execute(ExecutionContext &context, DataChunk namespace duckdb { -class PhysicalChunkScanState : public GlobalSourceState { +class PhysicalColumnDataScanState : public GlobalSourceState { public: - explicit PhysicalChunkScanState() : chunk_index(0) { + explicit PhysicalColumnDataScanState() : initialized(false) { } //! The current position in the scan - idx_t chunk_index; + ColumnDataScanState scan_state; + bool initialized; }; -unique_ptr PhysicalChunkScan::GetGlobalSourceState(ClientContext &context) const { - return make_unique(); +unique_ptr PhysicalColumnDataScan::GetGlobalSourceState(ClientContext &context) const { + return make_unique(); } -void PhysicalChunkScan::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, - LocalSourceState &lstate) const { - auto &state = (PhysicalChunkScanState &)gstate; +void PhysicalColumnDataScan::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate, + LocalSourceState &lstate) const { + auto &state = (PhysicalColumnDataScanState &)gstate; D_ASSERT(collection); if (collection->Count() == 0) { return; } - D_ASSERT(chunk.GetTypes() == collection->Types()); - if (state.chunk_index >= collection->ChunkCount()) { - return; + if (!state.initialized) { + collection->InitializeScan(state.scan_state); + state.initialized = true; } - auto &collection_chunk = collection->GetChunk(state.chunk_index); - chunk.Reference(collection_chunk); - state.chunk_index++; + collection->Scan(state.scan_state, chunk); } //===--------------------------------------------------------------------===// // Pipeline Construction //===--------------------------------------------------------------------===// -void PhysicalChunkScan::BuildPipelines(Executor &executor, Pipeline ¤t, PipelineBuildState &state) { +void PhysicalColumnDataScan::BuildPipelines(Executor &executor, Pipeline ¤t, PipelineBuildState &state) { // check if there is any additional action we need to do depending on the type switch (type) { case PhysicalOperatorType::DELIM_SCAN: { @@ -76752,7 +84949,7 @@ class PhysicalExpressionScan : public PhysicalOperator { vector>> expressions; public: - unique_ptr GetOperatorState(ClientContext &context) const override; + unique_ptr GetOperatorState(ExecutionContext &context) const override; OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const override; @@ -76762,7 +84959,8 @@ class PhysicalExpressionScan : public PhysicalOperator { public: bool IsFoldable() const; - void EvaluateExpression(idx_t expression_idx, DataChunk *child_chunk, DataChunk &result) const; + void EvaluateExpression(Allocator &allocator, idx_t expression_idx, DataChunk *child_chunk, + DataChunk &result) const; }; } // namespace duckdb @@ -76774,8 +84972,8 @@ namespace duckdb { class ExpressionScanState : public OperatorState { public: - explicit ExpressionScanState(const PhysicalExpressionScan &op) : expression_index(0) { - temp_chunk.Initialize(op.GetTypes()); + explicit ExpressionScanState(Allocator &allocator, const PhysicalExpressionScan &op) : expression_index(0) { + temp_chunk.Initialize(allocator, op.GetTypes()); } //! The current position in the scan @@ -76784,8 +84982,8 @@ class ExpressionScanState : public OperatorState { DataChunk temp_chunk; }; -unique_ptr PhysicalExpressionScan::GetOperatorState(ClientContext &context) const { - return make_unique(*this); +unique_ptr PhysicalExpressionScan::GetOperatorState(ExecutionContext &context) const { + return make_unique(Allocator::Get(context.client), *this); } OperatorResultType PhysicalExpressionScan::Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, @@ -76795,7 +84993,7 @@ OperatorResultType PhysicalExpressionScan::Execute(ExecutionContext &context, Da for (; chunk.size() + input.size() <= STANDARD_VECTOR_SIZE && state.expression_index < expressions.size(); state.expression_index++) { state.temp_chunk.Reset(); - EvaluateExpression(state.expression_index, &input, state.temp_chunk); + EvaluateExpression(Allocator::Get(context.client), state.expression_index, &input, state.temp_chunk); chunk.Append(state.temp_chunk); } if (state.expression_index < expressions.size()) { @@ -76806,8 +85004,9 @@ OperatorResultType PhysicalExpressionScan::Execute(ExecutionContext &context, Da } } -void PhysicalExpressionScan::EvaluateExpression(idx_t expression_idx, DataChunk *child_chunk, DataChunk &result) const { - ExpressionExecutor executor(expressions[expression_idx]); +void PhysicalExpressionScan::EvaluateExpression(Allocator &allocator, idx_t expression_idx, DataChunk *child_chunk, + DataChunk &result) const { + ExpressionExecutor executor(allocator, expressions[expression_idx]); if (child_chunk) { child_chunk->Verify(); executor.Execute(*child_chunk, result); @@ -76876,7 +85075,7 @@ class TableScanLocalSourceState : public LocalSourceState { const PhysicalTableScan &op) { if (op.function.init_local) { TableFunctionInitInput input(op.bind_data.get(), op.column_ids, op.table_filters.get()); - local_state = op.function.init_local(context.client, input, gstate.global_state.get()); + local_state = op.function.init_local(context, input, gstate.global_state.get()); } } @@ -76953,6 +85152,7 @@ string PhysicalTableScan::ParamsToString() const { } } } + result += "\nEC=" + to_string(estimated_cardinality) + "\n"; return result; } @@ -77162,6 +85362,7 @@ class PhysicalCreateIndex : public PhysicalOperator { + namespace duckdb { //===--------------------------------------------------------------------===// @@ -77199,8 +85400,7 @@ void PhysicalCreateIndex::GetData(ExecutionContext &context, DataChunk &chunk, G unique_ptr index; switch (info->index_type) { case IndexType::ART: { - index = make_unique(column_ids, unbound_expressions, - info->unique ? IndexConstraintType::UNIQUE : IndexConstraintType::NONE); + index = make_unique(column_ids, unbound_expressions, info->constraint_type, *context.client.db); break; } default: @@ -77208,6 +85408,9 @@ void PhysicalCreateIndex::GetData(ExecutionContext &context, DataChunk &chunk, G } index_entry->index = index.get(); index_entry->info = table.storage->info; + for (auto &parsed_expr : info->parsed_expressions) { + index_entry->parsed_expressions.push_back(parsed_expr->Copy()); + } table.storage->AddIndex(move(index), expressions); chunk.SetCardinality(0); @@ -77573,6 +85776,7 @@ class PhysicalCreateType : public PhysicalOperator { + namespace duckdb { PhysicalCreateType::PhysicalCreateType(unique_ptr info, idx_t estimated_cardinality) @@ -77759,7 +85963,6 @@ void PhysicalDrop::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSo - namespace duckdb { PhysicalRecursiveCTE::PhysicalRecursiveCTE(vector types, bool union_all, unique_ptr top, @@ -77778,16 +85981,19 @@ PhysicalRecursiveCTE::~PhysicalRecursiveCTE() { class RecursiveCTEState : public GlobalSinkState { public: explicit RecursiveCTEState(ClientContext &context, const PhysicalRecursiveCTE &op) - : new_groups(STANDARD_VECTOR_SIZE) { - ht = make_unique(BufferManager::GetBufferManager(context), op.types, - vector(), vector()); + : intermediate_table(context, op.GetTypes()), new_groups(STANDARD_VECTOR_SIZE) { + ht = make_unique(Allocator::Get(context), BufferManager::GetBufferManager(context), + op.types, vector(), + vector()); } unique_ptr ht; bool intermediate_empty = true; - ChunkCollection intermediate_table; - idx_t chunk_idx = 0; + ColumnDataCollection intermediate_table; + ColumnDataScanState scan_state; + bool initialized = false; + bool finished_scan = false; SelectionVector new_groups; }; @@ -77827,29 +86033,40 @@ SinkResultType PhysicalRecursiveCTE::Sink(ExecutionContext &context, GlobalSinkS void PhysicalRecursiveCTE::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSourceState &gstate_p, LocalSourceState &lstate) const { auto &gstate = (RecursiveCTEState &)*sink_state; + if (!gstate.initialized) { + gstate.intermediate_table.InitializeScan(gstate.scan_state); + gstate.finished_scan = false; + gstate.initialized = true; + } while (chunk.size() == 0) { - if (gstate.chunk_idx < gstate.intermediate_table.ChunkCount()) { + if (!gstate.finished_scan) { // scan any chunks we have collected so far - chunk.Reference(gstate.intermediate_table.GetChunk(gstate.chunk_idx)); - gstate.chunk_idx++; - break; + gstate.intermediate_table.Scan(gstate.scan_state, chunk); + if (chunk.size() == 0) { + gstate.finished_scan = true; + } else { + break; + } } else { // we have run out of chunks // now we need to recurse // we set up the working table as the data we gathered in this iteration of the recursion working_table->Reset(); - working_table->Merge(gstate.intermediate_table); + working_table->Combine(gstate.intermediate_table); // and we clear the intermediate table + gstate.finished_scan = false; gstate.intermediate_table.Reset(); - gstate.chunk_idx = 0; // now we need to re-execute all of the pipelines that depend on the recursion ExecuteRecursivePipelines(context); // check if we obtained any results // if not, we are done if (gstate.intermediate_table.Count() == 0) { + gstate.finished_scan = true; break; } + // set up the scan again + gstate.intermediate_table.InitializeScan(gstate.scan_state); } } } @@ -77980,17 +86197,7 @@ void PhysicalUnion::BuildPipelines(Executor &executor, Pipeline ¤t, Pipeli auto union_pipeline = make_shared(executor); auto pipeline_ptr = union_pipeline.get(); - auto &child_pipelines = state.GetChildPipelines(executor); - auto &child_dependencies = state.GetChildDependencies(executor); auto &union_pipelines = state.GetUnionPipelines(executor); - // set up dependencies for any child pipelines to this union pipeline - auto child_entry = child_pipelines.find(¤t); - if (child_entry != child_pipelines.end()) { - for (auto ¤t_child : child_entry->second) { - D_ASSERT(child_dependencies.find(current_child.get()) != child_dependencies.end()); - child_dependencies[current_child.get()].push_back(pipeline_ptr); - } - } // for the current pipeline, continue building on the LHS state.SetPipelineOperators(*union_pipeline, state.GetPipelineOperators(current)); children[0]->BuildPipelines(executor, current, state); @@ -78058,18 +86265,19 @@ RadixPartitionInfo::RadixPartitionInfo(const idx_t n_partitions_upper_bound) D_ASSERT(radix_bits <= 8); } -PartitionableHashTable::PartitionableHashTable(BufferManager &buffer_manager_p, RadixPartitionInfo &partition_info_p, - vector group_types_p, vector payload_types_p, +PartitionableHashTable::PartitionableHashTable(Allocator &allocator, BufferManager &buffer_manager_p, + RadixPartitionInfo &partition_info_p, vector group_types_p, + vector payload_types_p, vector bindings_p) - : buffer_manager(buffer_manager_p), group_types(move(group_types_p)), payload_types(move(payload_types_p)), - bindings(move(bindings_p)), is_partitioned(false), partition_info(partition_info_p), hashes(LogicalType::HASH), - hashes_subset(LogicalType::HASH) { + : allocator(allocator), buffer_manager(buffer_manager_p), group_types(move(group_types_p)), + payload_types(move(payload_types_p)), bindings(move(bindings_p)), is_partitioned(false), + partition_info(partition_info_p), hashes(LogicalType::HASH), hashes_subset(LogicalType::HASH) { sel_vectors.resize(partition_info.n_partitions); sel_vector_sizes.resize(partition_info.n_partitions); - group_subset.Initialize(group_types); + group_subset.Initialize(allocator, group_types); if (!payload_types.empty()) { - payload_subset.Initialize(payload_types); + payload_subset.Initialize(allocator, payload_types); } for (hash_t r = 0; r < partition_info.n_partitions; r++) { @@ -78084,8 +86292,8 @@ idx_t PartitionableHashTable::ListAddChunk(HashTableList &list, DataChunk &group // early release first part of ht and prevent adding of more data list.back()->Finalize(); } - list.push_back(make_unique(buffer_manager, group_types, payload_types, bindings, - HtEntryType::HT_WIDTH_32)); + list.push_back(make_unique(allocator, buffer_manager, group_types, payload_types, + bindings, HtEntryType::HT_WIDTH_32)); } return list.back()->AddChunk(groups, group_hashes, payload); } @@ -78109,11 +86317,11 @@ idx_t PartitionableHashTable::AddChunk(DataChunk &groups, DataChunk &payload, bo sel_vector_sizes[r] = 0; } - hashes.Normalify(groups.size()); + hashes.Flatten(groups.size()); auto hashes_ptr = FlatVector::GetData(hashes); for (idx_t i = 0; i < groups.size(); i++) { - auto partition = (hashes_ptr[i] & partition_info.radix_mask) >> partition_info.RADIX_SHIFT; + auto partition = partition_info.GetHashPartition(hashes_ptr[i]); D_ASSERT(partition < partition_info.n_partitions); sel_vectors[partition].set_index(sel_vector_sizes[partition]++, i); } @@ -78129,7 +86337,11 @@ idx_t PartitionableHashTable::AddChunk(DataChunk &groups, DataChunk &payload, bo idx_t group_count = 0; for (hash_t r = 0; r < partition_info.n_partitions; r++) { group_subset.Slice(groups, sel_vectors[r], sel_vector_sizes[r]); - payload_subset.Slice(payload, sel_vectors[r], sel_vector_sizes[r]); + if (!payload_types.empty()) { + payload_subset.Slice(payload, sel_vectors[r], sel_vector_sizes[r]); + } else { + payload_subset.SetCardinality(sel_vector_sizes[r]); + } hashes_subset.Slice(hashes, sel_vectors[r], sel_vector_sizes[r]); group_count += ListAddChunk(radix_partitioned_hts[r], group_subset, hashes_subset, payload_subset); @@ -78139,14 +86351,14 @@ idx_t PartitionableHashTable::AddChunk(DataChunk &groups, DataChunk &payload, bo void PartitionableHashTable::Partition() { D_ASSERT(!IsPartitioned()); - D_ASSERT(radix_partitioned_hts.size() == 0); + D_ASSERT(radix_partitioned_hts.empty()); D_ASSERT(partition_info.n_partitions > 1); vector partition_hts(partition_info.n_partitions); for (auto &unpartitioned_ht : unpartitioned_hts) { for (idx_t r = 0; r < partition_info.n_partitions; r++) { radix_partitioned_hts[r].push_back(make_unique( - buffer_manager, group_types, payload_types, bindings, HtEntryType::HT_WIDTH_32)); + allocator, buffer_manager, group_types, payload_types, bindings, HtEntryType::HT_WIDTH_32)); partition_hts[r] = radix_partitioned_hts[r].back().get(); } unpartitioned_ht->Partition(partition_hts, partition_info.radix_mask, partition_info.RADIX_SHIFT); @@ -78194,14 +86406,14 @@ void PartitionableHashTable::Finalize() { namespace duckdb { -PerfectAggregateHashTable::PerfectAggregateHashTable(BufferManager &buffer_manager, +PerfectAggregateHashTable::PerfectAggregateHashTable(Allocator &allocator, BufferManager &buffer_manager, const vector &group_types_p, vector payload_types_p, vector aggregate_objects_p, vector group_minima_p, vector required_bits_p) - : BaseAggregateHashTable(buffer_manager, move(payload_types_p)), addresses(LogicalType::POINTER), - required_bits(move(required_bits_p)), total_required_bits(0), group_minima(move(group_minima_p)), - sel(STANDARD_VECTOR_SIZE) { + : BaseAggregateHashTable(allocator, aggregate_objects_p, buffer_manager, move(payload_types_p)), + addresses(LogicalType::POINTER), required_bits(move(required_bits_p)), total_required_bits(0), + group_minima(move(group_minima_p)), sel(STANDARD_VECTOR_SIZE) { for (auto &group_bits : required_bits) { total_required_bits += group_bits; } @@ -78226,7 +86438,7 @@ PerfectAggregateHashTable::~PerfectAggregateHashTable() { } template -static void ComputeGroupLocationTemplated(VectorData &group_data, Value &min, uintptr_t *address_data, +static void ComputeGroupLocationTemplated(UnifiedVectorFormat &group_data, Value &min, uintptr_t *address_data, idx_t current_shift, idx_t count) { auto data = (T *)group_data.data; auto min_val = min.GetValueUnsafe(); @@ -78254,8 +86466,8 @@ static void ComputeGroupLocationTemplated(VectorData &group_data, Value &min, ui } static void ComputeGroupLocation(Vector &group, Value &min, uintptr_t *address_data, idx_t current_shift, idx_t count) { - VectorData vdata; - group.Orrify(count, vdata); + UnifiedVectorFormat vdata; + group.ToUnifiedFormat(count, vdata); switch (group.GetType().InternalType()) { case PhysicalType::INT8: @@ -78309,10 +86521,12 @@ void PerfectAggregateHashTable::AddChunk(DataChunk &groups, DataChunk &payload) // after finding the group location we update the aggregates idx_t payload_idx = 0; auto &aggregates = layout.GetAggregates(); - for (auto &aggregate : aggregates) { + for (idx_t aggr_idx = 0; aggr_idx < aggregates.size(); aggr_idx++) { + auto &aggregate = aggregates[aggr_idx]; auto input_count = (idx_t)aggregate.child_count; if (aggregate.filter) { - RowOperations::UpdateFilteredStates(aggregate, addresses, payload, payload_idx); + RowOperations::UpdateFilteredStates(filter_set.GetFilterData(aggr_idx), aggregate, addresses, payload, + payload_idx); } else { RowOperations::UpdateStates(aggregate, addresses, payload, payload_idx, payload.size()); } @@ -78483,6 +86697,7 @@ void PerfectAggregateHashTable::Destroy() { + namespace duckdb { string PhysicalOperator::GetName() const { @@ -78512,7 +86727,7 @@ vector PhysicalOperator::GetChildren() const { // Operator //===--------------------------------------------------------------------===// // LCOV_EXCL_START -unique_ptr PhysicalOperator::GetOperatorState(ClientContext &context) const { +unique_ptr PhysicalOperator::GetOperatorState(ExecutionContext &context) const { return make_unique(); } @@ -78580,6 +86795,14 @@ unique_ptr PhysicalOperator::GetGlobalSinkState(ClientContext & return make_unique(); } +idx_t PhysicalOperator::GetMaxThreadMemory(ClientContext &context) { + // Memory usage per thread should scale with max mem / num threads + // We take 1/4th of this, to be conservative + idx_t max_memory = BufferManager::GetBufferManager(context).GetMaxMemory(); + idx_t num_threads = TaskScheduler::GetScheduler(context).NumberOfThreads(); + return (max_memory / num_threads) / 4; +} + //===--------------------------------------------------------------------===// // Pipeline Construction //===--------------------------------------------------------------------===// @@ -78663,6 +86886,18 @@ bool PhysicalOperator::AllSourcesSupportBatchIndex() const { return true; } +bool PhysicalOperator::AllOperatorsPreserveOrder() const { + if (!IsOrderPreserving()) { + return false; + } + for (auto &child : children) { + if (!child->IsOrderPreserving()) { + return false; + } + } + return true; +} + void PhysicalOperator::Verify() { #ifdef DEBUG auto sources = GetSources(); @@ -78675,125 +86910,6 @@ void PhysicalOperator::Verify() { } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/operator/subtract.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { - -struct SubtractOperator { - template - static inline TR Operation(TA left, TB right) { - return left - right; - } -}; - -template <> -float SubtractOperator::Operation(float left, float right); -template <> -double SubtractOperator::Operation(double left, double right); -template <> -interval_t SubtractOperator::Operation(interval_t left, interval_t right); -template <> -int64_t SubtractOperator::Operation(date_t left, date_t right); -template <> -date_t SubtractOperator::Operation(date_t left, int32_t right); -template <> -date_t SubtractOperator::Operation(date_t left, interval_t right); -template <> -timestamp_t SubtractOperator::Operation(timestamp_t left, interval_t right); -template <> -interval_t SubtractOperator::Operation(timestamp_t left, timestamp_t right); - -struct TrySubtractOperator { - template - static inline bool Operation(TA left, TB right, TR &result) { - throw InternalException("Unimplemented type for TrySubtractOperator"); - } -}; - -template <> -bool TrySubtractOperator::Operation(uint8_t left, uint8_t right, uint8_t &result); -template <> -bool TrySubtractOperator::Operation(uint16_t left, uint16_t right, uint16_t &result); -template <> -bool TrySubtractOperator::Operation(uint32_t left, uint32_t right, uint32_t &result); -template <> -bool TrySubtractOperator::Operation(uint64_t left, uint64_t right, uint64_t &result); - -template <> -bool TrySubtractOperator::Operation(int8_t left, int8_t right, int8_t &result); -template <> -bool TrySubtractOperator::Operation(int16_t left, int16_t right, int16_t &result); -template <> -bool TrySubtractOperator::Operation(int32_t left, int32_t right, int32_t &result); -template <> -bool TrySubtractOperator::Operation(int64_t left, int64_t right, int64_t &result); -template <> -bool TrySubtractOperator::Operation(hugeint_t left, hugeint_t right, hugeint_t &result); - -struct SubtractOperatorOverflowCheck { - template - static inline TR Operation(TA left, TB right) { - TR result; - if (!TrySubtractOperator::Operation(left, right, result)) { - throw OutOfRangeException("Overflow in subtraction of %s (%d - %d)!", TypeIdToString(GetTypeId()), left, - right); - } - return result; - } -}; - -struct TryDecimalSubtract { - template - static inline bool Operation(TA left, TB right, TR &result) { - throw InternalException("Unimplemented type for TryDecimalSubtract"); - } -}; - -template <> -bool TryDecimalSubtract::Operation(int16_t left, int16_t right, int16_t &result); -template <> -bool TryDecimalSubtract::Operation(int32_t left, int32_t right, int32_t &result); -template <> -bool TryDecimalSubtract::Operation(int64_t left, int64_t right, int64_t &result); -template <> -bool TryDecimalSubtract::Operation(hugeint_t left, hugeint_t right, hugeint_t &result); - -struct DecimalSubtractOverflowCheck { - template - static inline TR Operation(TA left, TB right) { - TR result; - if (!TryDecimalSubtract::Operation(left, right, result)) { - throw OutOfRangeException("Overflow in subtract of DECIMAL(18) (%d - %d). You might want to add an " - "explicit cast to a bigger decimal.", - left, right); - } - return result; - } -}; - -template <> -hugeint_t DecimalSubtractOverflowCheck::Operation(hugeint_t left, hugeint_t right); - -struct SubtractTimeOperator { - template - static TR Operation(TA left, TB right); -}; - -template <> -dtime_t SubtractTimeOperator::Operation(dtime_t left, interval_t right); - -} // namespace duckdb @@ -78849,6 +86965,9 @@ class LogicalLimitPercent : public LogicalOperator { return children[0]->GetColumnBindings(); } + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { types = children[0]->types; @@ -78859,21 +86978,21 @@ class LogicalLimitPercent : public LogicalOperator { - namespace duckdb { class ClientContext; +class ColumnDataCollection; //! The physical plan generator generates a physical execution plan from a //! logical query plan class PhysicalPlanGenerator { public: - explicit PhysicalPlanGenerator(ClientContext &context) : context(context) { - } + explicit PhysicalPlanGenerator(ClientContext &context); + ~PhysicalPlanGenerator(); unordered_set dependencies; //! Recursive CTEs require at least one ChunkScan, referencing the working_table. //! This data structure is used to establish it. - unordered_map> rec_ctes; + unordered_map> recursive_cte_tables; public: //! Creates a plan from the logical operator. This involves resolving column bindings and generating physical @@ -78885,7 +87004,7 @@ class PhysicalPlanGenerator { unique_ptr CreatePlan(LogicalAggregate &op); unique_ptr CreatePlan(LogicalAnyJoin &op); - unique_ptr CreatePlan(LogicalChunkGet &op); + unique_ptr CreatePlan(LogicalColumnDataGet &op); unique_ptr CreatePlan(LogicalComparisonJoin &op); unique_ptr CreatePlan(LogicalCreate &op); unique_ptr CreatePlan(LogicalCreateTable &op); @@ -79020,6 +87139,8 @@ class LogicalAggregate : public LogicalOperator { string ParamsToString() const override; vector GetColumnBindings() override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override; @@ -79148,15 +87269,15 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalAggregate bool use_simple_aggregation = true; for (auto &expression : op.expressions) { auto &aggregate = (BoundAggregateExpression &)*expression; - if (!aggregate.function.simple_update || aggregate.distinct) { + if (!aggregate.function.simple_update) { // unsupported aggregate for simple aggregation: use hash aggregation use_simple_aggregation = false; break; } } if (use_simple_aggregation) { - groupby = make_unique_base(op.types, move(op.expressions), - op.estimated_cardinality); + groupby = make_unique_base(op.types, move(op.expressions), + op.estimated_cardinality); } else { groupby = make_unique_base(context, op.types, move(op.expressions), op.estimated_cardinality); @@ -79245,6 +87366,8 @@ class LogicalAnyJoin : public LogicalJoin { public: string ParamsToString() const override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -79271,7 +87394,7 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalAnyJoin &o //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/planner/operator/logical_chunk_get.hpp +// duckdb/planner/operator/logical_column_data_get.hpp // // //===----------------------------------------------------------------------===// @@ -79283,27 +87406,23 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalAnyJoin &o namespace duckdb { -//! LogicalChunkGet represents a scan operation from a ChunkCollection -class LogicalChunkGet : public LogicalOperator { +//! LogicalColumnDataGet represents a scan operation from a ColumnDataCollection +class LogicalColumnDataGet : public LogicalOperator { public: - LogicalChunkGet(idx_t table_index, vector types, unique_ptr collection) - : LogicalOperator(LogicalOperatorType::LOGICAL_CHUNK_GET), table_index(table_index), - collection(move(collection)) { - D_ASSERT(types.size() > 0); - chunk_types = types; - } + LogicalColumnDataGet(idx_t table_index, vector types, unique_ptr collection); //! The table index in the current bind context idx_t table_index; //! The types of the chunk vector chunk_types; //! The chunk collection to scan - unique_ptr collection; + unique_ptr collection; public: - vector GetColumnBindings() override { - return GenerateColumnBindings(table_index, chunk_types.size()); - } + vector GetColumnBindings() override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override { @@ -79316,13 +87435,13 @@ class LogicalChunkGet : public LogicalOperator { namespace duckdb { -unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalChunkGet &op) { +unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalColumnDataGet &op) { D_ASSERT(op.children.size() == 0); D_ASSERT(op.collection); // create a PhysicalChunkScan pointing towards the owned collection auto chunk_scan = - make_unique(op.types, PhysicalOperatorType::CHUNK_SCAN, op.estimated_cardinality); + make_unique(op.types, PhysicalOperatorType::COLUMN_DATA_SCAN, op.estimated_cardinality); chunk_scan->owned_collection = move(op.collection); chunk_scan->collection = chunk_scan->owned_collection.get(); return move(chunk_scan); @@ -79346,6 +87465,7 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalChunkGet & + namespace duckdb { static bool CanPlanIndexJoin(Transaction &transaction, TableScanBindData *bind_data, PhysicalTableScan &scan) { @@ -79402,6 +87522,16 @@ void CheckForPerfectJoinOpt(LogicalComparisonJoin &op, PerfectHashJoinStats &joi if (op.join_stats.empty()) { return; } + for (auto &type : op.children[1]->types) { + switch (type.id()) { + case LogicalTypeId::STRUCT: + case LogicalTypeId::LIST: + case LogicalTypeId::MAP: + return; + default: + break; + } + } // with equality condition and null values not equal for (auto &&condition : op.conditions) { if (condition.comparison != ExpressionType::COMPARE_EQUAL) { @@ -79488,6 +87618,14 @@ void TransformIndexJoin(ClientContext &context, LogicalComparisonJoin &op, Index } } +static void RewriteJoinCondition(Expression &expr, idx_t offset) { + if (expr.type == ExpressionType::BOUND_REF) { + auto &ref = (BoundReferenceExpression &)expr; + ref.index += offset; + } + ExpressionIterator::EnumerateChildren(expr, [&](Expression &child) { RewriteJoinCondition(child, offset); }); +} + unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalComparisonJoin &op) { // now visit the children D_ASSERT(op.children.size() == 2); @@ -79555,7 +87693,7 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalComparison } else { bool can_merge = has_range > 0; - bool can_iejoin = has_range >= 2 && rec_ctes.empty(); + bool can_iejoin = has_range >= 2 && recursive_cte_tables.empty(); switch (op.join_type) { case JoinType::SEMI: case JoinType::ANTI: @@ -79573,10 +87711,17 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalComparison // range join: use piecewise merge join plan = make_unique(op, move(left), move(right), move(op.conditions), op.join_type, op.estimated_cardinality); - } else { + } else if (PhysicalNestedLoopJoin::IsSupported(op.conditions)) { // inequality join: use nested loop plan = make_unique(op, move(left), move(right), move(op.conditions), op.join_type, op.estimated_cardinality); + } else { + for (auto &cond : op.conditions) { + RewriteJoinCondition(*cond.right, left->types.size()); + } + auto condition = JoinCondition::CreateExpression(move(op.conditions)); + plan = make_unique(op, move(left), move(right), move(condition), op.join_type, + op.estimated_cardinality); } } return plan; @@ -79612,6 +87757,10 @@ class LogicalCopyToFile : public LogicalOperator { bool use_tmp_file; bool is_file_and_exists; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { types.emplace_back(LogicalType::BIGINT); @@ -79624,6 +87773,9 @@ namespace duckdb { unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalCopyToFile &op) { auto plan = CreatePlan(*op.children[0]); + auto &fs = FileSystem::GetFileSystem(context); + op.file_path = fs.ExpandPath(op.file_path, FileSystem::GetFileOpener(context)); + bool use_tmp_file = op.is_file_and_exists && op.use_tmp_file; if (use_tmp_file) { op.file_path += ".tmp"; @@ -79671,6 +87823,10 @@ class LogicalCreate : public LogicalOperator { SchemaCatalogEntry *schema; unique_ptr info; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { types.emplace_back(LogicalType::BIGINT); @@ -79725,42 +87881,6 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalCreateInde -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/expression_iterator.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -#include - -namespace duckdb { -class BoundQueryNode; -class BoundTableRef; - -class ExpressionIterator { -public: - static void EnumerateChildren(const Expression &expression, - const std::function &callback); - static void EnumerateChildren(Expression &expression, const std::function &callback); - static void EnumerateChildren(Expression &expression, - const std::function &child)> &callback); - - static void EnumerateExpression(unique_ptr &expr, - const std::function &callback); - - static void EnumerateTableRefChildren(BoundTableRef &ref, const std::function &callback); - static void EnumerateQueryNodeChildren(BoundQueryNode &node, - const std::function &callback); -}; - -} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -79788,6 +87908,10 @@ class LogicalCreateTable : public LogicalOperator { //! Create Table information unique_ptr info; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { types.emplace_back(LogicalType::BIGINT); @@ -79850,12 +87974,19 @@ namespace duckdb { //! LogicalCrossProduct represents a cross product between two relations class LogicalCrossProduct : public LogicalOperator { + LogicalCrossProduct() : LogicalOperator(LogicalOperatorType::LOGICAL_CROSS_PRODUCT) {}; + public: - LogicalCrossProduct(); + LogicalCrossProduct(unique_ptr left, unique_ptr right); public: + static unique_ptr Create(unique_ptr left, unique_ptr right); + vector GetColumnBindings() override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override; }; @@ -79889,6 +88020,8 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalCrossProdu + + namespace duckdb { class LogicalDelete : public LogicalOperator { @@ -79901,6 +88034,10 @@ class LogicalDelete : public LogicalOperator { idx_t table_index; bool return_chunk; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: vector GetColumnBindings() override { if (return_chunk) { @@ -79974,6 +88111,8 @@ class LogicalDelimGet : public LogicalOperator { vector GetColumnBindings() override { return GenerateColumnBindings(table_index, chunk_types.size()); } + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override { @@ -79991,7 +88130,7 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalDelimGet & // create a PhysicalChunkScan without an owned_collection, the collection will be added later auto chunk_scan = - make_unique(op.types, PhysicalOperatorType::DELIM_SCAN, op.estimated_cardinality); + make_unique(op.types, PhysicalOperatorType::DELIM_SCAN, op.estimated_cardinality); return move(chunk_scan); } @@ -80006,7 +88145,6 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalDelimGet & - namespace duckdb { static void GatherDelimScans(PhysicalOperator *op, vector &delim_scans) { @@ -80088,6 +88226,8 @@ class LogicalDistinct : public LogicalOperator { vector GetColumnBindings() override { return children[0]->GetColumnBindings(); } + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override { @@ -80208,6 +88348,8 @@ class LogicalDummyScan : public LogicalOperator { idx_t EstimateCardinality(ClientContext &context) override { return 1; } + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override { @@ -80243,9 +88385,11 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalDummyScan namespace duckdb { -//! LogicalEmptyResult returns an empty result. This is created by the optimizer if it can reason that ceratin parts of +//! LogicalEmptyResult returns an empty result. This is created by the optimizer if it can reason that certain parts of //! the tree will always return an empty result. class LogicalEmptyResult : public LogicalOperator { + LogicalEmptyResult(); + public: explicit LogicalEmptyResult(unique_ptr op); @@ -80258,6 +88402,8 @@ class LogicalEmptyResult : public LogicalOperator { vector GetColumnBindings() override { return bindings; } + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override { @@ -80302,6 +88448,10 @@ class LogicalExecute : public LogicalOperator { shared_ptr prepared; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { // already resolved @@ -80335,7 +88485,6 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalExecute &o } // namespace duckdb - //===----------------------------------------------------------------------===// // DuckDB // @@ -80384,6 +88533,9 @@ class ExplainStatement : public SQLStatement { namespace duckdb { class LogicalExplain : public LogicalOperator { + LogicalExplain(ExplainType explain_type) + : LogicalOperator(LogicalOperatorType::LOGICAL_EXPLAIN), explain_type(explain_type) {}; + public: LogicalExplain(unique_ptr plan, ExplainType explain_type) : LogicalOperator(LogicalOperatorType::LOGICAL_EXPLAIN), explain_type(explain_type) { @@ -80395,6 +88547,10 @@ class LogicalExplain : public LogicalOperator { string logical_plan_unopt; string logical_plan_opt; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { types = {LogicalType::VARCHAR, LogicalType::VARCHAR}; @@ -80410,6 +88566,8 @@ class LogicalExplain : public LogicalOperator { + + namespace duckdb { unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalExplain &op) { @@ -80439,11 +88597,14 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalExplain &o values = {op.logical_plan_unopt, logical_plan_opt, op.physical_plan}; } - // create a ChunkCollection from the output - auto collection = make_unique(); + // create a ColumnDataCollection from the output + auto &allocator = Allocator::Get(context); + vector plan_types {LogicalType::VARCHAR, LogicalType::VARCHAR}; + auto collection = + make_unique(context, plan_types, ColumnDataAllocatorType::IN_MEMORY_ALLOCATOR); DataChunk chunk; - chunk.Initialize(op.types); + chunk.Initialize(allocator, op.types); for (idx_t i = 0; i < keys.size(); i++) { chunk.SetValue(0, chunk.size(), Value(keys[i])); chunk.SetValue(1, chunk.size(), Value(values[i])); @@ -80457,7 +88618,7 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalExplain &o // create a chunk scan to output the result auto chunk_scan = - make_unique(op.types, PhysicalOperatorType::CHUNK_SCAN, op.estimated_cardinality); + make_unique(op.types, PhysicalOperatorType::COLUMN_DATA_SCAN, op.estimated_cardinality); chunk_scan->owned_collection = move(collection); chunk_scan->collection = chunk_scan->owned_collection.get(); return move(chunk_scan); @@ -80493,6 +88654,10 @@ class LogicalExport : public LogicalOperator { unique_ptr copy_info; BoundExportData exported_tables; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { types.emplace_back(LogicalType::BOOLEAN); @@ -80507,7 +88672,7 @@ namespace duckdb { unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalExport &op) { auto &config = DBConfig::GetConfig(context); - if (!config.enable_external_access) { + if (!config.options.enable_external_access) { throw PermissionException("Export is disabled through configuration"); } auto export_node = make_unique(op.types, op.function, move(op.copy_info), op.estimated_cardinality, @@ -80557,6 +88722,8 @@ class LogicalExpressionGet : public LogicalOperator { vector GetColumnBindings() override { return GenerateColumnBindings(table_index, expr_types.size()); } + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override { @@ -80568,6 +88735,7 @@ class LogicalExpressionGet : public LogicalOperator { + namespace duckdb { unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalExpressionGet &op) { @@ -80579,19 +88747,23 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalExpression if (!expr_scan->IsFoldable()) { return move(expr_scan); } + auto &allocator = Allocator::Get(context); // simple expression scan (i.e. no subqueries to evaluate and no prepared statement parameters) // we can evaluate all the expressions right now and turn this into a chunk collection scan - auto chunk_scan = - make_unique(op.types, PhysicalOperatorType::CHUNK_SCAN, expr_scan->expressions.size()); - chunk_scan->owned_collection = make_unique(); + auto chunk_scan = make_unique(op.types, PhysicalOperatorType::COLUMN_DATA_SCAN, + expr_scan->expressions.size()); + chunk_scan->owned_collection = make_unique(context, op.types); chunk_scan->collection = chunk_scan->owned_collection.get(); DataChunk chunk; - chunk.Initialize(op.types); + chunk.Initialize(allocator, op.types); + + ColumnDataAppendState append_state; + chunk_scan->owned_collection->InitializeAppend(append_state); for (idx_t expression_idx = 0; expression_idx < expr_scan->expressions.size(); expression_idx++) { chunk.Reset(); - expr_scan->EvaluateExpression(expression_idx, nullptr, chunk); - chunk_scan->owned_collection->Append(chunk); + expr_scan->EvaluateExpression(allocator, expression_idx, nullptr, chunk); + chunk_scan->owned_collection->Append(append_state, chunk); } return move(chunk_scan); } @@ -81062,6 +89234,8 @@ class LogicalFilter : public LogicalOperator { public: vector GetColumnBindings() override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); bool SplitPredicates() { return SplitPredicates(expressions); @@ -81076,57 +89250,6 @@ class LogicalFilter : public LogicalOperator { } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/operator/logical_get.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - -namespace duckdb { - -//! LogicalGet represents a scan operation from a data source -class LogicalGet : public LogicalOperator { -public: - LogicalGet(idx_t table_index, TableFunction function, unique_ptr bind_data, - vector returned_types, vector returned_names); - - //! The table index in the current bind context - idx_t table_index; - //! The function that is called - TableFunction function; - //! The bind data of the function - unique_ptr bind_data; - //! The types of ALL columns that can be returned by the table function - vector returned_types; - //! The names of ALL columns that can be returned by the table function - vector names; - //! Bound column IDs - vector column_ids; - //! Filters pushed down for table scan - TableFilterSet table_filters; - - string GetName() const override; - string ParamsToString() const override; - //! Returns the underlying table that is being scanned, or nullptr if there is none - TableCatalogEntry *GetTable() const; - -public: - vector GetColumnBindings() override; - - idx_t EstimateCardinality(ClientContext &context) override; - -protected: - void ResolveTypes() override; -}; -} // namespace duckdb namespace duckdb { @@ -81287,6 +89410,10 @@ class LogicalInsert : public LogicalOperator { //! The default statements used by the table vector> bound_defaults; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: vector GetColumnBindings() override { if (return_chunk) { @@ -81328,6 +89455,7 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalInsert &op + //===----------------------------------------------------------------------===// // DuckDB // @@ -81357,16 +89485,17 @@ class LogicalLimit : public LogicalOperator { public: vector GetColumnBindings() override; - idx_t EstimateCardinality(ClientContext &context) override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override; }; } // namespace duckdb - namespace duckdb { unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalLimit &op) { @@ -81374,8 +89503,10 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalLimit &op) auto plan = CreatePlan(*op.children[0]); auto &config = DBConfig::GetConfig(context); + bool plan_preserves_order = plan->AllOperatorsPreserveOrder(); + unique_ptr limit; - if (!config.preserve_insertion_order) { + if (!config.options.preserve_insertion_order || !plan_preserves_order) { // use parallel streaming limit if insertion order is not important limit = make_unique(op.types, (idx_t)op.limit_val, op.offset_val, move(op.limit), move(op.offset), op.estimated_cardinality, true); @@ -81459,6 +89590,8 @@ class LogicalOrder : public LogicalOperator { vector GetColumnBindings() override { return children[0]->GetColumnBindings(); } + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override { @@ -81512,6 +89645,10 @@ class LogicalPragma : public LogicalOperator { //! The context of the call PragmaInfo info; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { types.emplace_back(LogicalType::BOOLEAN); @@ -81553,16 +89690,29 @@ class LogicalPrepare : public LogicalOperator { public: LogicalPrepare(string name, shared_ptr prepared, unique_ptr logical_plan) : LogicalOperator(LogicalOperatorType::LOGICAL_PREPARE), name(name), prepared(move(prepared)) { - children.push_back(move(logical_plan)); + if (logical_plan) { + children.push_back(move(logical_plan)); + } } string name; shared_ptr prepared; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { types.emplace_back(LogicalType::BOOLEAN); } + + bool RequireOptimizer() const override { + if (!prepared->properties.bound_all_parameters) { + return false; + } + return children[0]->RequireOptimizer(); + } }; } // namespace duckdb @@ -81571,12 +89721,14 @@ class LogicalPrepare : public LogicalOperator { namespace duckdb { unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalPrepare &op) { - D_ASSERT(op.children.size() == 1); + D_ASSERT(op.children.size() <= 1); // generate physical plan - auto plan = CreatePlan(*op.children[0]); - op.prepared->types = plan->types; - op.prepared->plan = move(plan); + if (!op.children.empty()) { + auto plan = CreatePlan(*op.children[0]); + op.prepared->types = plan->types; + op.prepared->plan = move(plan); + } return make_unique(op.name, move(op.prepared), op.estimated_cardinality); } @@ -81607,6 +89759,8 @@ class LogicalProjection : public LogicalOperator { public: vector GetColumnBindings() override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override; @@ -81673,6 +89827,10 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalProjection namespace duckdb { class LogicalRecursiveCTE : public LogicalOperator { + LogicalRecursiveCTE(idx_t table_index, idx_t column_count, bool union_all, LogicalOperatorType type) + : LogicalOperator(type), union_all(union_all), table_index(table_index), column_count(column_count) { + } + public: LogicalRecursiveCTE(idx_t table_index, idx_t column_count, bool union_all, unique_ptr top, unique_ptr bottom, LogicalOperatorType type) @@ -81690,6 +89848,8 @@ class LogicalRecursiveCTE : public LogicalOperator { vector GetColumnBindings() override { return GenerateColumnBindings(table_index, column_count); } + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override { @@ -81713,7 +89873,7 @@ class LogicalRecursiveCTE : public LogicalOperator { namespace duckdb { -//! LogicalChunkGet represents a scan operation from a ChunkCollection +//! LogicalCTERef represents a reference to a recursive CTE class LogicalCTERef : public LogicalOperator { public: LogicalCTERef(idx_t table_index, idx_t cte_index, vector types, vector colnames) @@ -81735,6 +89895,8 @@ class LogicalCTERef : public LogicalOperator { vector GetColumnBindings() override { return GenerateColumnBindings(table_index, chunk_types.size()); } + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override { @@ -81745,16 +89907,17 @@ class LogicalCTERef : public LogicalOperator { } // namespace duckdb + namespace duckdb { unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalRecursiveCTE &op) { D_ASSERT(op.children.size() == 2); // Create the working_table that the PhysicalRecursiveCTE will use for evaluation. - auto working_table = std::make_shared(); + auto working_table = std::make_shared(context, op.types); - // Add the ChunkCollection to the context of this PhysicalPlanGenerator - rec_ctes[op.table_index] = working_table; + // Add the ColumnDataCollection to the context of this PhysicalPlanGenerator + recursive_cte_tables[op.table_index] = working_table; auto left = CreatePlan(*op.children[0]); auto right = CreatePlan(*op.children[1]); @@ -81769,12 +89932,12 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalRecursiveC unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalCTERef &op) { D_ASSERT(op.children.empty()); - auto chunk_scan = - make_unique(op.types, PhysicalOperatorType::RECURSIVE_CTE_SCAN, op.estimated_cardinality); + auto chunk_scan = make_unique(op.types, PhysicalOperatorType::RECURSIVE_CTE_SCAN, + op.estimated_cardinality); // CreatePlan of a LogicalRecursiveCTE must have happened before. - auto cte = rec_ctes.find(op.cte_index); - if (cte == rec_ctes.end()) { + auto cte = recursive_cte_tables.find(op.cte_index); + if (cte == recursive_cte_tables.end()) { throw Exception("Referenced recursive CTE does not exist."); } chunk_scan->collection = cte->second.get(); @@ -81810,9 +89973,11 @@ class LogicalSample : public LogicalOperator { public: vector GetColumnBindings() override; - idx_t EstimateCardinality(ClientContext &context) override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override; }; @@ -81879,6 +90044,10 @@ class LogicalSet : public LogicalOperator { Value value; SetScope scope; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { types.emplace_back(LogicalType::BOOLEAN); @@ -81915,6 +90084,10 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalSet &op) { namespace duckdb { class LogicalSetOperation : public LogicalOperator { + LogicalSetOperation(idx_t table_index, idx_t column_count, LogicalOperatorType type) + : LogicalOperator(type), table_index(table_index), column_count(column_count) { + } + public: LogicalSetOperation(idx_t table_index, idx_t column_count, unique_ptr top, unique_ptr bottom, LogicalOperatorType type) @@ -81933,6 +90106,9 @@ class LogicalSetOperation : public LogicalOperator { return GenerateColumnBindings(table_index, column_count); } + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { types = children[0]->types; @@ -82035,6 +90211,8 @@ struct ShowSelectInfo : public ParseInfo { namespace duckdb { class LogicalShow : public LogicalOperator { + LogicalShow() : LogicalOperator(LogicalOperatorType::LOGICAL_SHOW) {}; + public: explicit LogicalShow(unique_ptr plan) : LogicalOperator(LogicalOperatorType::LOGICAL_SHOW) { children.push_back(move(plan)); @@ -82043,6 +90221,10 @@ class LogicalShow : public LogicalOperator { vector types_select; vector aliases; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { types = {LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR, @@ -82060,9 +90242,11 @@ namespace duckdb { unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalShow &op) { DataChunk output; - output.Initialize(op.types); + output.Initialize(Allocator::Get(context), op.types); - auto collection = make_unique(); + auto collection = make_unique(context, op.types); + ColumnDataAppendState append_state; + collection->InitializeAppend(append_state); for (idx_t column_idx = 0; column_idx < op.types_select.size(); column_idx++) { auto type = op.types_select[column_idx]; auto &name = op.aliases[column_idx]; @@ -82082,16 +90266,16 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalShow &op) output.SetCardinality(output.size() + 1); if (output.size() == STANDARD_VECTOR_SIZE) { - collection->Append(output); + collection->Append(append_state, output); output.Reset(); } } - collection->Append(output); + collection->Append(append_state, output); // create a chunk scan to output the result auto chunk_scan = - make_unique(op.types, PhysicalOperatorType::CHUNK_SCAN, op.estimated_cardinality); + make_unique(op.types, PhysicalOperatorType::COLUMN_DATA_SCAN, op.estimated_cardinality); chunk_scan->owned_collection = move(collection); chunk_scan->collection = chunk_scan->owned_collection.get(); return move(chunk_scan); @@ -82100,6 +90284,14 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalShow &op) } // namespace duckdb + + + + + + + + //===----------------------------------------------------------------------===// // DuckDB // @@ -82124,6 +90316,10 @@ class LogicalSimple : public LogicalOperator { unique_ptr info; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: void ResolveTypes() override { types.emplace_back(LogicalType::BOOLEAN); @@ -82132,15 +90328,6 @@ class LogicalSimple : public LogicalOperator { } // namespace duckdb - - - - - - - - - namespace duckdb { unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalSimple &op) { @@ -82153,9 +90340,15 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalSimple &op case LogicalOperatorType::LOGICAL_TRANSACTION: return make_unique(unique_ptr_cast(move(op.info)), op.estimated_cardinality); - case LogicalOperatorType::LOGICAL_VACUUM: - return make_unique(unique_ptr_cast(move(op.info)), - op.estimated_cardinality); + case LogicalOperatorType::LOGICAL_VACUUM: { + auto result = make_unique(unique_ptr_cast(move(op.info)), + op.estimated_cardinality); + if (!op.children.empty()) { + auto child = CreatePlan(*op.children[0]); + result->children.push_back(move(child)); + } + return move(result); + } case LogicalOperatorType::LOGICAL_LOAD: return make_unique(unique_ptr_cast(move(op.info)), op.estimated_cardinality); default: @@ -82198,6 +90391,8 @@ class LogicalTopN : public LogicalOperator { vector GetColumnBindings() override { return children[0]->GetColumnBindings(); } + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override { @@ -82249,6 +90444,8 @@ class LogicalUnnest : public LogicalOperator { public: vector GetColumnBindings() override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override; @@ -82282,6 +90479,7 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalUnnest &op + namespace duckdb { class LogicalUpdate : public LogicalOperator { @@ -82300,6 +90498,10 @@ class LogicalUpdate : public LogicalOperator { vector> bound_defaults; bool update_is_del_and_insert; +public: + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); + protected: vector GetColumnBindings() override { if (return_chunk) { @@ -82368,6 +90570,8 @@ class LogicalWindow : public LogicalOperator { public: vector GetColumnBindings() override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(LogicalDeserializationState &state, FieldReader &reader); protected: void ResolveTypes() override; @@ -82386,6 +90590,10 @@ static bool IsStreamingWindow(unique_ptr &expr) { } switch (wexpr->type) { // TODO: add more expression types here? + case ExpressionType::WINDOW_AGGREGATE: + // We can stream aggregates if they are "running totals" and don't use filters + return wexpr->start == WindowBoundary::UNBOUNDED_PRECEDING && wexpr->end == WindowBoundary::CURRENT_ROW_ROWS && + !wexpr->filter_expr; case ExpressionType::WINDOW_FIRST_VALUE: case ExpressionType::WINDOW_PERCENT_RANK: case ExpressionType::WINDOW_RANK: @@ -82464,7 +90672,7 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalWindow &op plan = move(window); // Remember the projection order if we changed it - if (!remaining.empty() || !evaluation_order.empty()) { + if (!streaming_windows.empty() || !blocking_windows.empty() || !evaluation_order.empty()) { evaluation_order.insert(evaluation_order.end(), matching.begin(), matching.end()); } } @@ -82497,6 +90705,7 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalWindow &op + namespace duckdb { class DependencyExtractor : public LogicalOperatorVisitor { @@ -82517,6 +90726,12 @@ class DependencyExtractor : public LogicalOperatorVisitor { unordered_set &dependencies; }; +PhysicalPlanGenerator::PhysicalPlanGenerator(ClientContext &context) : context(context) { +} + +PhysicalPlanGenerator::~PhysicalPlanGenerator() { +} + unique_ptr PhysicalPlanGenerator::CreatePlan(unique_ptr op) { auto &profiler = QueryProfiler::Get(context); @@ -82546,98 +90761,149 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalOperator &op) { op.estimated_cardinality = op.EstimateCardinality(context); + unique_ptr plan = nullptr; + switch (op.type) { case LogicalOperatorType::LOGICAL_GET: - return CreatePlan((LogicalGet &)op); + plan = CreatePlan((LogicalGet &)op); + break; case LogicalOperatorType::LOGICAL_PROJECTION: - return CreatePlan((LogicalProjection &)op); + plan = CreatePlan((LogicalProjection &)op); + break; case LogicalOperatorType::LOGICAL_EMPTY_RESULT: - return CreatePlan((LogicalEmptyResult &)op); + plan = CreatePlan((LogicalEmptyResult &)op); + break; case LogicalOperatorType::LOGICAL_FILTER: - return CreatePlan((LogicalFilter &)op); + plan = CreatePlan((LogicalFilter &)op); + break; case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY: - return CreatePlan((LogicalAggregate &)op); + plan = CreatePlan((LogicalAggregate &)op); + break; case LogicalOperatorType::LOGICAL_WINDOW: - return CreatePlan((LogicalWindow &)op); + plan = CreatePlan((LogicalWindow &)op); + break; case LogicalOperatorType::LOGICAL_UNNEST: - return CreatePlan((LogicalUnnest &)op); + plan = CreatePlan((LogicalUnnest &)op); + break; case LogicalOperatorType::LOGICAL_LIMIT: - return CreatePlan((LogicalLimit &)op); + plan = CreatePlan((LogicalLimit &)op); + break; case LogicalOperatorType::LOGICAL_LIMIT_PERCENT: - return CreatePlan((LogicalLimitPercent &)op); + plan = CreatePlan((LogicalLimitPercent &)op); + break; case LogicalOperatorType::LOGICAL_SAMPLE: - return CreatePlan((LogicalSample &)op); + plan = CreatePlan((LogicalSample &)op); + break; case LogicalOperatorType::LOGICAL_ORDER_BY: - return CreatePlan((LogicalOrder &)op); + plan = CreatePlan((LogicalOrder &)op); + break; case LogicalOperatorType::LOGICAL_TOP_N: - return CreatePlan((LogicalTopN &)op); + plan = CreatePlan((LogicalTopN &)op); + break; case LogicalOperatorType::LOGICAL_COPY_TO_FILE: - return CreatePlan((LogicalCopyToFile &)op); + plan = CreatePlan((LogicalCopyToFile &)op); + break; case LogicalOperatorType::LOGICAL_DUMMY_SCAN: - return CreatePlan((LogicalDummyScan &)op); + plan = CreatePlan((LogicalDummyScan &)op); + break; case LogicalOperatorType::LOGICAL_ANY_JOIN: - return CreatePlan((LogicalAnyJoin &)op); + plan = CreatePlan((LogicalAnyJoin &)op); + break; case LogicalOperatorType::LOGICAL_DELIM_JOIN: - return CreatePlan((LogicalDelimJoin &)op); + plan = CreatePlan((LogicalDelimJoin &)op); + break; case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: - return CreatePlan((LogicalComparisonJoin &)op); + plan = CreatePlan((LogicalComparisonJoin &)op); + break; case LogicalOperatorType::LOGICAL_CROSS_PRODUCT: - return CreatePlan((LogicalCrossProduct &)op); + plan = CreatePlan((LogicalCrossProduct &)op); + break; case LogicalOperatorType::LOGICAL_UNION: case LogicalOperatorType::LOGICAL_EXCEPT: case LogicalOperatorType::LOGICAL_INTERSECT: - return CreatePlan((LogicalSetOperation &)op); + plan = CreatePlan((LogicalSetOperation &)op); + break; case LogicalOperatorType::LOGICAL_INSERT: - return CreatePlan((LogicalInsert &)op); + plan = CreatePlan((LogicalInsert &)op); + break; case LogicalOperatorType::LOGICAL_DELETE: - return CreatePlan((LogicalDelete &)op); + plan = CreatePlan((LogicalDelete &)op); + break; case LogicalOperatorType::LOGICAL_CHUNK_GET: - return CreatePlan((LogicalChunkGet &)op); + plan = CreatePlan((LogicalColumnDataGet &)op); + break; case LogicalOperatorType::LOGICAL_DELIM_GET: - return CreatePlan((LogicalDelimGet &)op); + plan = CreatePlan((LogicalDelimGet &)op); + break; case LogicalOperatorType::LOGICAL_EXPRESSION_GET: - return CreatePlan((LogicalExpressionGet &)op); + plan = CreatePlan((LogicalExpressionGet &)op); + break; case LogicalOperatorType::LOGICAL_UPDATE: - return CreatePlan((LogicalUpdate &)op); + plan = CreatePlan((LogicalUpdate &)op); + break; case LogicalOperatorType::LOGICAL_CREATE_TABLE: - return CreatePlan((LogicalCreateTable &)op); + plan = CreatePlan((LogicalCreateTable &)op); + break; case LogicalOperatorType::LOGICAL_CREATE_INDEX: - return CreatePlan((LogicalCreateIndex &)op); + plan = CreatePlan((LogicalCreateIndex &)op); + break; case LogicalOperatorType::LOGICAL_EXPLAIN: - return CreatePlan((LogicalExplain &)op); + plan = CreatePlan((LogicalExplain &)op); + break; case LogicalOperatorType::LOGICAL_SHOW: - return CreatePlan((LogicalShow &)op); + plan = CreatePlan((LogicalShow &)op); + break; case LogicalOperatorType::LOGICAL_DISTINCT: - return CreatePlan((LogicalDistinct &)op); + plan = CreatePlan((LogicalDistinct &)op); + break; case LogicalOperatorType::LOGICAL_PREPARE: - return CreatePlan((LogicalPrepare &)op); + plan = CreatePlan((LogicalPrepare &)op); + break; case LogicalOperatorType::LOGICAL_EXECUTE: - return CreatePlan((LogicalExecute &)op); + plan = CreatePlan((LogicalExecute &)op); + break; case LogicalOperatorType::LOGICAL_CREATE_VIEW: case LogicalOperatorType::LOGICAL_CREATE_SEQUENCE: case LogicalOperatorType::LOGICAL_CREATE_SCHEMA: case LogicalOperatorType::LOGICAL_CREATE_MACRO: case LogicalOperatorType::LOGICAL_CREATE_TYPE: - return CreatePlan((LogicalCreate &)op); + plan = CreatePlan((LogicalCreate &)op); + break; case LogicalOperatorType::LOGICAL_PRAGMA: - return CreatePlan((LogicalPragma &)op); + plan = CreatePlan((LogicalPragma &)op); + break; case LogicalOperatorType::LOGICAL_TRANSACTION: case LogicalOperatorType::LOGICAL_ALTER: case LogicalOperatorType::LOGICAL_DROP: case LogicalOperatorType::LOGICAL_VACUUM: case LogicalOperatorType::LOGICAL_LOAD: - return CreatePlan((LogicalSimple &)op); + plan = CreatePlan((LogicalSimple &)op); + break; case LogicalOperatorType::LOGICAL_RECURSIVE_CTE: - return CreatePlan((LogicalRecursiveCTE &)op); + plan = CreatePlan((LogicalRecursiveCTE &)op); + break; case LogicalOperatorType::LOGICAL_CTE_REF: - return CreatePlan((LogicalCTERef &)op); + plan = CreatePlan((LogicalCTERef &)op); + break; case LogicalOperatorType::LOGICAL_EXPORT: - return CreatePlan((LogicalExport &)op); + plan = CreatePlan((LogicalExport &)op); + break; case LogicalOperatorType::LOGICAL_SET: - return CreatePlan((LogicalSet &)op); - default: + plan = CreatePlan((LogicalSet &)op); + break; + default: { throw NotImplementedException("Unimplemented logical operator type!"); } + } + + if (op.estimated_props) { + plan->estimated_cardinality = op.estimated_props->GetCardinality(); + plan->estimated_props = op.estimated_props->Copy(); + } else { + plan->estimated_props = make_unique(); + } + + return plan; } } // namespace duckdb @@ -82648,10 +90914,29 @@ unique_ptr PhysicalPlanGenerator::CreatePlan(LogicalOperator & namespace duckdb { -RadixPartitionedHashTable::RadixPartitionedHashTable(GroupingSet &grouping_set_p, const PhysicalHashAggregate &op_p) +// compute the GROUPING values +// for each parameter to the GROUPING clause, we check if the hash table groups on this particular group +// if it does, we return 0, otherwise we return 1 +// we then use bitshifts to combine these values +void RadixPartitionedHashTable::SetGroupingValues() { + auto &grouping_functions = op.GetGroupingFunctions(); + for (auto &grouping : grouping_functions) { + int64_t grouping_value = 0; + for (idx_t i = 0; i < grouping.size(); i++) { + if (grouping_set.find(grouping[i]) == grouping_set.end()) { + // we don't group on this value! + grouping_value += 1 << (grouping.size() - (i + 1)); + } + } + grouping_values.push_back(Value::BIGINT(grouping_value)); + } +} + +RadixPartitionedHashTable::RadixPartitionedHashTable(GroupingSet &grouping_set_p, const GroupedAggregateData &op_p) : grouping_set(grouping_set_p), op(op_p) { - for (idx_t i = 0; i < op.groups.size(); i++) { + auto groups_count = op.GroupCount(); + for (idx_t i = 0; i < groups_count; i++) { if (grouping_set.find(i) == grouping_set.end()) { null_groups.push_back(i); } @@ -82668,20 +90953,7 @@ RadixPartitionedHashTable::RadixPartitionedHashTable(GroupingSet &grouping_set_p D_ASSERT(entry < op.group_types.size()); group_types.push_back(op.group_types[entry]); } - // compute the GROUPING values - // for each parameter to the GROUPING clause, we check if the hash table groups on this particular group - // if it does, we return 0, otherwise we return 1 - // we then use bitshifts to combine these values - for (auto &grouping : op.grouping_functions) { - int64_t grouping_value = 0; - for (idx_t i = 0; i < grouping.size(); i++) { - if (grouping_set.find(grouping[i]) == grouping_set.end()) { - // we don't group on this value! - grouping_value += 1 << (grouping.size() - (i + 1)); - } - } - grouping_values.push_back(Value::BIGINT(grouping_value)); - } + SetGroupingValues(); } //===--------------------------------------------------------------------===// @@ -82766,9 +91038,9 @@ void RadixPartitionedHashTable::Sink(ExecutionContext &context, GlobalSinkState lock_guard glock(gstate.lock); gstate.is_empty = gstate.is_empty && group_chunk.size() == 0; if (gstate.finalized_hts.empty()) { - gstate.finalized_hts.push_back( - make_unique(BufferManager::GetBufferManager(context.client), group_types, - op.payload_types, op.bindings, HtEntryType::HT_WIDTH_64)); + gstate.finalized_hts.push_back(make_unique( + Allocator::Get(context.client), BufferManager::GetBufferManager(context.client), group_types, + op.payload_types, op.bindings, HtEntryType::HT_WIDTH_64)); } D_ASSERT(gstate.finalized_hts.size() == 1); D_ASSERT(gstate.finalized_hts[0]); @@ -82783,9 +91055,9 @@ void RadixPartitionedHashTable::Sink(ExecutionContext &context, GlobalSinkState } if (!llstate.ht) { - llstate.ht = - make_unique(BufferManager::GetBufferManager(context.client), gstate.partition_info, - group_types, op.payload_types, op.bindings); + llstate.ht = make_unique( + Allocator::Get(context.client), BufferManager::GetBufferManager(context.client), gstate.partition_info, + group_types, op.payload_types, op.bindings); } gstate.total_groups += @@ -82853,6 +91125,8 @@ bool RadixPartitionedHashTable::Finalize(ClientContext &context, GlobalSinkState } } + auto &allocator = Allocator::Get(context); + auto &buffer_manager = BufferManager::GetBufferManager(context); if (any_partitioned) { // if one is partitioned, all have to be // this should mostly have already happened in Combine, but if not we do it here @@ -82864,9 +91138,8 @@ bool RadixPartitionedHashTable::Finalize(ClientContext &context, GlobalSinkState // schedule additional tasks to combine the partial HTs gstate.finalized_hts.resize(gstate.partition_info.n_partitions); for (idx_t r = 0; r < gstate.partition_info.n_partitions; r++) { - gstate.finalized_hts[r] = - make_unique(BufferManager::GetBufferManager(context), group_types, - op.payload_types, op.bindings, HtEntryType::HT_WIDTH_64); + gstate.finalized_hts[r] = make_unique( + allocator, buffer_manager, group_types, op.payload_types, op.bindings, HtEntryType::HT_WIDTH_64); } gstate.is_partitioned = true; return true; @@ -82874,9 +91147,8 @@ bool RadixPartitionedHashTable::Finalize(ClientContext &context, GlobalSinkState // TODO possible optimization, if total count < limit for 32 bit ht, use that one // create this ht here so finalize needs no lock on gstate - gstate.finalized_hts.push_back(make_unique(BufferManager::GetBufferManager(context), - group_types, op.payload_types, - op.bindings, HtEntryType::HT_WIDTH_64)); + gstate.finalized_hts.push_back(make_unique( + allocator, buffer_manager, group_types, op.payload_types, op.bindings, HtEntryType::HT_WIDTH_64)); for (auto &pht : gstate.intermediate_hts) { auto unpartitioned = pht->GetUnpartitioned(); for (auto &unpartitioned_ht : unpartitioned) { @@ -82948,41 +91220,68 @@ bool RadixPartitionedHashTable::ForceSingleHT(GlobalSinkState &state) const { //===--------------------------------------------------------------------===// class RadixHTGlobalSourceState : public GlobalSourceState { public: - explicit RadixHTGlobalSourceState(const RadixPartitionedHashTable &ht) + explicit RadixHTGlobalSourceState(Allocator &allocator, const RadixPartitionedHashTable &ht) : ht_index(0), ht_scan_position(0), finished(false) { + } + + //! Heavy handed for now. + mutex lock; + //! The current position to scan the HT for output tuples + idx_t ht_index; + idx_t ht_scan_position; + atomic finished; +}; + +class RadixHTLocalSourceState : public LocalSourceState { +public: + explicit RadixHTLocalSourceState(ExecutionContext &context, const RadixPartitionedHashTable &ht) { + auto &allocator = Allocator::Get(context.client); auto scan_chunk_types = ht.group_types; for (auto &aggr_type : ht.op.aggregate_return_types) { scan_chunk_types.push_back(aggr_type); } - scan_chunk.Initialize(scan_chunk_types); + scan_chunk.Initialize(allocator, scan_chunk_types); } //! Materialized GROUP BY expressions & aggregates DataChunk scan_chunk; - //! The current position to scan the HT for output tuples - idx_t ht_index; - idx_t ht_scan_position; - bool finished; }; -unique_ptr RadixPartitionedHashTable::GetGlobalSourceState() const { - return make_unique(*this); +unique_ptr RadixPartitionedHashTable::GetGlobalSourceState(ClientContext &context) const { + return make_unique(Allocator::Get(context), *this); +} + +unique_ptr RadixPartitionedHashTable::GetLocalSourceState(ExecutionContext &context) const { + return make_unique(context, *this); +} + +idx_t RadixPartitionedHashTable::Size(GlobalSinkState &sink_state) const { + auto &gstate = (RadixHTGlobalState &)sink_state; + if (gstate.is_empty && grouping_set.empty()) { + return 1; + } + + idx_t count = 0; + for (const auto &ht : gstate.finalized_hts) { + count += ht->Size(); + } + return count; } void RadixPartitionedHashTable::GetData(ExecutionContext &context, DataChunk &chunk, GlobalSinkState &sink_state, - GlobalSourceState &source_state) const { + GlobalSourceState &gsstate, LocalSourceState &lsstate) const { auto &gstate = (RadixHTGlobalState &)sink_state; - auto &state = (RadixHTGlobalSourceState &)source_state; + auto &state = (RadixHTGlobalSourceState &)gsstate; + auto &lstate = (RadixHTLocalSourceState &)lsstate; D_ASSERT(gstate.is_finalized); if (state.finished) { return; } - state.scan_chunk.Reset(); // special case hack to sort out aggregating from empty intermediates // for aggregations without groups if (gstate.is_empty && grouping_set.empty()) { - D_ASSERT(chunk.ColumnCount() == null_groups.size() + op.aggregates.size()); + D_ASSERT(chunk.ColumnCount() == null_groups.size() + op.aggregates.size() + op.grouping_functions.size()); // for each column in the aggregates, set to initial state chunk.SetCardinality(1); for (auto null_group : null_groups) { @@ -82995,28 +91294,34 @@ void RadixPartitionedHashTable::GetData(ExecutionContext &context, DataChunk &ch auto aggr_state = unique_ptr(new data_t[aggr.function.state_size()]); aggr.function.initialize(aggr_state.get()); + AggregateInputData aggr_input_data(aggr.bind_info.get(), Allocator::DefaultAllocator()); Vector state_vector(Value::POINTER((uintptr_t)aggr_state.get())); - aggr.function.finalize(state_vector, aggr.bind_info.get(), chunk.data[null_groups.size() + i], 1, 0); + aggr.function.finalize(state_vector, aggr_input_data, chunk.data[null_groups.size() + i], 1, 0); if (aggr.function.destructor) { aggr.function.destructor(state_vector, 1); } } + for (idx_t i = 0; i < op.grouping_functions.size(); i++) { + chunk.data[null_groups.size() + op.aggregates.size() + i].Reference(grouping_values[i]); + } state.finished = true; return; } - if (gstate.is_empty && !state.finished) { + if (gstate.is_empty) { state.finished = true; return; } idx_t elements_found = 0; + lstate.scan_chunk.Reset(); while (true) { + lock_guard glock(state.lock); if (state.ht_index == gstate.finalized_hts.size()) { state.finished = true; return; } D_ASSERT(gstate.finalized_hts[state.ht_index]); - elements_found = gstate.finalized_hts[state.ht_index]->Scan(state.ht_scan_position, state.scan_chunk); + elements_found = gstate.finalized_hts[state.ht_index]->Scan(state.ht_scan_position, lstate.scan_chunk); if (elements_found > 0) { break; @@ -83033,18 +91338,18 @@ void RadixPartitionedHashTable::GetData(ExecutionContext &context, DataChunk &ch idx_t chunk_index = 0; for (auto &entry : grouping_set) { - chunk.data[entry].Reference(state.scan_chunk.data[chunk_index++]); + chunk.data[entry].Reference(lstate.scan_chunk.data[chunk_index++]); } for (auto null_group : null_groups) { chunk.data[null_group].SetVectorType(VectorType::CONSTANT_VECTOR); ConstantVector::SetNull(chunk.data[null_group], true); } for (idx_t col_idx = 0; col_idx < op.aggregates.size(); col_idx++) { - chunk.data[op.groups.size() + col_idx].Reference(state.scan_chunk.data[group_types.size() + col_idx]); + chunk.data[op.GroupCount() + col_idx].Reference(lstate.scan_chunk.data[group_types.size() + col_idx]); } D_ASSERT(op.grouping_functions.size() == grouping_values.size()); for (idx_t i = 0; i < op.grouping_functions.size(); i++) { - chunk.data[op.groups.size() + op.aggregates.size() + i].Reference(grouping_values[i]); + chunk.data[op.GroupCount() + op.aggregates.size() + i].Reference(grouping_values[i]); } } @@ -83054,6 +91359,10 @@ void RadixPartitionedHashTable::GetData(ExecutionContext &context, DataChunk &ch namespace duckdb { +ReservoirSample::ReservoirSample(Allocator &allocator, idx_t sample_count, int64_t seed) + : BlockingSample(seed), sample_count(sample_count), reservoir(allocator) { +} + void ReservoirSample::AddToReservoir(DataChunk &input) { if (sample_count == 0) { return; @@ -83101,7 +91410,7 @@ void ReservoirSample::ReplaceElement(DataChunk &input, idx_t index_in_chunk) { idx_t ReservoirSample::FillReservoir(DataChunk &input) { idx_t chunk_count = input.size(); - input.Normalify(); + input.Flatten(); // we have not: append to the reservoir idx_t required_count; @@ -83136,10 +91445,11 @@ idx_t ReservoirSample::FillReservoir(DataChunk &input) { return input.size(); } -ReservoirSamplePercentage::ReservoirSamplePercentage(double percentage, int64_t seed) - : BlockingSample(seed), sample_percentage(percentage / 100.0), current_count(0), is_finalized(false) { +ReservoirSamplePercentage::ReservoirSamplePercentage(Allocator &allocator, double percentage, int64_t seed) + : BlockingSample(seed), allocator(allocator), sample_percentage(percentage / 100.0), current_count(0), + is_finalized(false) { reservoir_sample_size = idx_t(sample_percentage * RESERVOIR_THRESHOLD); - current_sample = make_unique(reservoir_sample_size, random.NextRandomInteger()); + current_sample = make_unique(allocator, reservoir_sample_size, random.NextRandomInteger()); } void ReservoirSamplePercentage::AddToReservoir(DataChunk &input) { @@ -83150,7 +91460,7 @@ void ReservoirSamplePercentage::AddToReservoir(DataChunk &input) { idx_t append_to_next_sample = input.size() - append_to_current_sample_count; if (append_to_current_sample_count > 0) { // we have elements remaining, first add them to the current sample - input.Normalify(); + input.Flatten(); input.SetCardinality(append_to_current_sample_count); current_sample->AddToReservoir(input); @@ -83167,7 +91477,7 @@ void ReservoirSamplePercentage::AddToReservoir(DataChunk &input) { finished_samples.push_back(move(current_sample)); // allocate a new sample, and potentially add the remainder of the current input to that sample - current_sample = make_unique(reservoir_sample_size, random.NextRandomInteger()); + current_sample = make_unique(allocator, reservoir_sample_size, random.NextRandomInteger()); if (append_to_next_sample > 0) { current_sample->AddToReservoir(input); } @@ -83200,7 +91510,7 @@ void ReservoirSamplePercentage::Finalize() { if (current_count > 0) { // create a new sample auto new_sample_size = idx_t(round(sample_percentage * current_count)); - auto new_sample = make_unique(new_sample_size, random.NextRandomInteger()); + auto new_sample = make_unique(allocator, new_sample_size, random.NextRandomInteger()); while (true) { auto chunk = current_sample->GetChunk(); if (!chunk || chunk->size() == 0) { @@ -83287,12 +91597,12 @@ WindowSegmentTree::WindowSegmentTree(AggregateFunction &aggregate, FunctionData #if STANDARD_VECTOR_SIZE < 512 throw NotImplementedException("Window functions are not supported for vector sizes < 512"); #endif - statep.Normalify(STANDARD_VECTOR_SIZE); + statep.Flatten(STANDARD_VECTOR_SIZE); statev.SetVectorType(VectorType::FLAT_VECTOR); // Prevent conversion of results to constants if (input_ref && input_ref->ColumnCount() > 0) { filter_sel.Initialize(STANDARD_VECTOR_SIZE); - inputs.Initialize(input_ref->Types()); + inputs.Initialize(Allocator::DefaultAllocator(), input_ref->Types()); // if we have a frame-by-frame method, share the single state if (aggregate.window && UseWindowAPI()) { AggregateInit(); @@ -83333,7 +91643,8 @@ void WindowSegmentTree::AggregateInit() { } void WindowSegmentTree::AggegateFinal(Vector &result, idx_t rid) { - aggregate.finalize(statev, bind_info, result, 1, rid); + AggregateInputData aggr_input_data(bind_info, Allocator::DefaultAllocator()); + aggregate.finalize(statev, aggr_input_data, result, 1, rid); if (aggregate.destructor) { aggregate.destructor(statev, 1); @@ -83400,7 +91711,8 @@ void WindowSegmentTree::WindowSegmentValue(idx_t l_idx, idx_t begin, idx_t end) Vector s(statep, 0); if (l_idx == 0) { ExtractFrame(begin, end); - aggregate.update(&inputs.data[0], bind_info, input_ref->ColumnCount(), s, inputs.size()); + AggregateInputData aggr_input_data(bind_info, Allocator::DefaultAllocator()); + aggregate.update(&inputs.data[0], aggr_input_data, input_ref->ColumnCount(), s, inputs.size()); } else { inputs.Reset(); inputs.SetCardinality(end - begin); @@ -83413,7 +91725,8 @@ void WindowSegmentTree::WindowSegmentValue(idx_t l_idx, idx_t begin, idx_t end) pdata[i] = begin_ptr + i * state.size(); } v.Verify(inputs.size()); - aggregate.combine(v, s, bind_info, inputs.size()); + AggregateInputData aggr_input_data(bind_info, Allocator::DefaultAllocator()); + aggregate.combine(v, s, aggr_input_data, inputs.size()); } } @@ -83515,8 +91828,9 @@ void WindowSegmentTree::Compute(Vector &result, idx_t rid, idx_t begin, idx_t en active = FrameBounds(active_chunks.first * STANDARD_VECTOR_SIZE, MinValue((active_chunks.second + 1) * STANDARD_VECTOR_SIZE, coll.Count())); - aggregate.window(inputs.data.data(), filter_mask, bind_info, inputs.ColumnCount(), state.data(), frame, prev, - result, rid, active.first); + AggregateInputData aggr_input_data(bind_info, Allocator::DefaultAllocator()); + aggregate.window(inputs.data.data(), filter_mask, aggr_input_data, inputs.ColumnCount(), state.data(), frame, + prev, result, rid, active.first); return; } @@ -83750,18 +92064,18 @@ struct BaseSumOperation { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { - STATEOP::template Combine(source, target, bind_data); + static void Combine(const STATE &source, STATE *target, AggregateInputData &aggr_input_data) { + STATEOP::template Combine(source, target, aggr_input_data); } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { STATEOP::template AddValues(state, 1); ADDOP::template AddNumber(*state, input[idx]); } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, + static void ConstantOperation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t count) { STATEOP::template AddValues(state, count); ADDOP::template AddConstant(*state, *input, count); @@ -83779,6 +92093,7 @@ struct BaseSumOperation { + namespace duckdb { template @@ -83836,7 +92151,7 @@ struct AverageSetOperation { state->Initialize(); } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { target->Combine(source); } template @@ -83857,12 +92172,12 @@ static T GetAverageDivident(uint64_t count, FunctionData *bind_data) { struct IntegerAverageOperation : public BaseSumOperation { template - static void Finalize(Vector &result, FunctionData *bind_data, STATE *state, T *target, ValidityMask &mask, - idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &aggr_input_data, STATE *state, T *target, + ValidityMask &mask, idx_t idx) { if (state->count == 0) { mask.SetInvalid(idx); } else { - double divident = GetAverageDivident(state->count, bind_data); + double divident = GetAverageDivident(state->count, aggr_input_data.bind_data); target[idx] = double(state->value) / divident; } } @@ -83870,12 +92185,12 @@ struct IntegerAverageOperation : public BaseSumOperation { template - static void Finalize(Vector &result, FunctionData *bind_data, STATE *state, T *target, ValidityMask &mask, - idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &aggr_input_data, STATE *state, T *target, + ValidityMask &mask, idx_t idx) { if (state->count == 0) { mask.SetInvalid(idx); } else { - long double divident = GetAverageDivident(state->count, bind_data); + long double divident = GetAverageDivident(state->count, aggr_input_data.bind_data); target[idx] = Hugeint::Cast(state->value) / divident; } } @@ -83883,12 +92198,12 @@ struct IntegerAverageOperationHugeint : public BaseSumOperation { template - static void Finalize(Vector &result, FunctionData *bind_data, STATE *state, T *target, ValidityMask &mask, - idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &aggr_input_data, STATE *state, T *target, + ValidityMask &mask, idx_t idx) { if (state->count == 0) { mask.SetInvalid(idx); } else { - long double divident = GetAverageDivident(state->count, bind_data); + long double divident = GetAverageDivident(state->count, aggr_input_data.bind_data); target[idx] = Hugeint::Cast(state->value) / divident; } } @@ -83896,7 +92211,7 @@ struct HugeintAverageOperation : public BaseSumOperation { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->count == 0) { mask.SetInvalid(idx); } else { @@ -83910,7 +92225,7 @@ struct NumericAverageOperation : public BaseSumOperation { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->count == 0) { mask.SetInvalid(idx); } else { @@ -83924,24 +92239,22 @@ struct KahanAverageOperation : public BaseSumOperation, int16_t, double, IntegerAverageOperation>( - LogicalType::SMALLINT, LogicalType::DOUBLE, true); + LogicalType::SMALLINT, LogicalType::DOUBLE); + } case PhysicalType::INT32: { - auto function = - AggregateFunction::UnaryAggregate, int32_t, double, IntegerAverageOperationHugeint>( - LogicalType::INTEGER, LogicalType::DOUBLE, true); - return function; + return AggregateFunction::UnaryAggregate, int32_t, double, IntegerAverageOperationHugeint>( + LogicalType::INTEGER, LogicalType::DOUBLE); } case PhysicalType::INT64: { - auto function = - AggregateFunction::UnaryAggregate, int64_t, double, IntegerAverageOperationHugeint>( - LogicalType::BIGINT, LogicalType::DOUBLE, true); - return function; + return AggregateFunction::UnaryAggregate, int64_t, double, IntegerAverageOperationHugeint>( + LogicalType::BIGINT, LogicalType::DOUBLE); } - case PhysicalType::INT128: + case PhysicalType::INT128: { return AggregateFunction::UnaryAggregate, hugeint_t, double, HugeintAverageOperation>( - LogicalType::HUGEINT, LogicalType::DOUBLE, true); + LogicalType::HUGEINT, LogicalType::DOUBLE); + } default: throw InternalException("Unimplemented average aggregate"); } @@ -83960,14 +92273,16 @@ unique_ptr BindDecimalAvg(ClientContext &context, AggregateFunctio void AvgFun::RegisterFunction(BuiltinFunctions &set) { AggregateFunctionSet avg("avg"); + avg.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL}, LogicalTypeId::DECIMAL, nullptr, nullptr, nullptr, - nullptr, nullptr, true, nullptr, BindDecimalAvg)); + nullptr, nullptr, FunctionNullHandling::DEFAULT_NULL_HANDLING, nullptr, + BindDecimalAvg)); avg.AddFunction(GetAverageAggregate(PhysicalType::INT16)); avg.AddFunction(GetAverageAggregate(PhysicalType::INT32)); avg.AddFunction(GetAverageAggregate(PhysicalType::INT64)); avg.AddFunction(GetAverageAggregate(PhysicalType::INT128)); avg.AddFunction(AggregateFunction::UnaryAggregate, double, double, NumericAverageOperation>( - LogicalType::DOUBLE, LogicalType::DOUBLE, true)); + LogicalType::DOUBLE, LogicalType::DOUBLE)); set.AddFunction(avg); avg.name = "mean"; @@ -83975,7 +92290,7 @@ void AvgFun::RegisterFunction(BuiltinFunctions &set) { AggregateFunctionSet favg("favg"); favg.AddFunction(AggregateFunction::UnaryAggregate( - LogicalType::DOUBLE, LogicalType::DOUBLE, true)); + LogicalType::DOUBLE, LogicalType::DOUBLE)); set.AddFunction(favg); } @@ -84012,7 +92327,7 @@ struct CovarOperation { } template - static void Operation(STATE *state, FunctionData *bind_data, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, + static void Operation(STATE *state, AggregateInputData &, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, ValidityMask &bmask, idx_t xidx, idx_t yidx) { // update running mean and d^2 const uint64_t n = ++(state->count); @@ -84033,7 +92348,7 @@ struct CovarOperation { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (target->count == 0) { *target = source; } else if (source.count > 0) { @@ -84059,7 +92374,7 @@ struct CovarOperation { struct CovarPopOperation : public CovarOperation { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->count == 0) { mask.SetInvalid(idx); } else { @@ -84070,7 +92385,7 @@ struct CovarPopOperation : public CovarOperation { struct CovarSampOperation : public CovarOperation { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if ((state->count) < 2) { mask.SetInvalid(idx); } else { @@ -84112,8 +92427,7 @@ struct STDDevBaseOperation { } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input_data, ValidityMask &mask, - idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input_data, ValidityMask &mask, idx_t idx) { // update running mean and d^2 state->count++; const double input = input_data[idx]; @@ -84127,15 +92441,15 @@ struct STDDevBaseOperation { } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input_data, ValidityMask &mask, - idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input_data, + ValidityMask &mask, idx_t count) { for (idx_t i = 0; i < count; i++) { - Operation(state, bind_data, input_data, mask, 0); + Operation(state, aggr_input_data, input_data, mask, 0); } } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (target->count == 0) { *target = source; } else if (source.count > 0) { @@ -84156,7 +92470,7 @@ struct STDDevBaseOperation { struct VarSampOperation : public STDDevBaseOperation { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->count <= 1) { mask.SetInvalid(idx); } else { @@ -84170,7 +92484,7 @@ struct VarSampOperation : public STDDevBaseOperation { struct VarPopOperation : public STDDevBaseOperation { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->count == 0) { mask.SetInvalid(idx); } else { @@ -84184,7 +92498,7 @@ struct VarPopOperation : public STDDevBaseOperation { struct STDDevSampOperation : public STDDevBaseOperation { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->count <= 1) { mask.SetInvalid(idx); } else { @@ -84198,7 +92512,7 @@ struct STDDevSampOperation : public STDDevBaseOperation { struct STDDevPopOperation : public STDDevBaseOperation { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->count == 0) { mask.SetInvalid(idx); } else { @@ -84212,7 +92526,7 @@ struct STDDevPopOperation : public STDDevBaseOperation { struct StandardErrorOfTheMeanOperation : public STDDevBaseOperation { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->count == 0) { mask.SetInvalid(idx); } else { @@ -84259,23 +92573,25 @@ struct CorrOperation { } template - static void Operation(STATE *state, FunctionData *bind_data, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, - ValidityMask &bmask, idx_t xidx, idx_t yidx) { - CovarOperation::Operation(&state->cov_pop, bind_data, x_data, y_data, amask, - bmask, xidx, yidx); - STDDevBaseOperation::Operation(&state->dev_pop_x, bind_data, x_data, amask, xidx); - STDDevBaseOperation::Operation(&state->dev_pop_y, bind_data, y_data, bmask, yidx); + static void Operation(STATE *state, AggregateInputData &aggr_input_data, A_TYPE *x_data, B_TYPE *y_data, + ValidityMask &amask, ValidityMask &bmask, idx_t xidx, idx_t yidx) { + CovarOperation::Operation(&state->cov_pop, aggr_input_data, x_data, y_data, + amask, bmask, xidx, yidx); + STDDevBaseOperation::Operation(&state->dev_pop_x, aggr_input_data, x_data, amask, + xidx); + STDDevBaseOperation::Operation(&state->dev_pop_y, aggr_input_data, y_data, bmask, + yidx); } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { - CovarOperation::Combine(source.cov_pop, &target->cov_pop, bind_data); - STDDevBaseOperation::Combine(source.dev_pop_x, &target->dev_pop_x, bind_data); - STDDevBaseOperation::Combine(source.dev_pop_y, &target->dev_pop_y, bind_data); + static void Combine(const STATE &source, STATE *target, AggregateInputData &aggr_input_data) { + CovarOperation::Combine(source.cov_pop, &target->cov_pop, aggr_input_data); + STDDevBaseOperation::Combine(source.dev_pop_x, &target->dev_pop_x, aggr_input_data); + STDDevBaseOperation::Combine(source.dev_pop_y, &target->dev_pop_y, aggr_input_data); } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->cov_pop.count == 0 || state->dev_pop_x.count == 0 || state->dev_pop_y.count == 0) { mask.SetInvalid(idx); } else { @@ -84434,7 +92750,7 @@ struct ApproxCountDistinctFunction { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (!source.log) { return; } @@ -84449,7 +92765,7 @@ struct ApproxCountDistinctFunction { } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->log) { target[idx] = state->log->Count(); } else { @@ -84468,7 +92784,7 @@ struct ApproxCountDistinctFunction { } }; -static void ApproxCountDistinctSimpleUpdateFunction(Vector inputs[], FunctionData *bind_data, idx_t input_count, +static void ApproxCountDistinctSimpleUpdateFunction(Vector inputs[], AggregateInputData &, idx_t input_count, data_ptr_t state, idx_t count) { D_ASSERT(input_count == 1); @@ -84477,8 +92793,8 @@ static void ApproxCountDistinctSimpleUpdateFunction(Vector inputs[], FunctionDat agg_state->log = new HyperLogLog(); } - VectorData vdata; - inputs[0].Orrify(count, vdata); + UnifiedVectorFormat vdata; + inputs[0].ToUnifiedFormat(count, vdata); uint64_t indices[STANDARD_VECTOR_SIZE]; uint8_t counts[STANDARD_VECTOR_SIZE]; @@ -84487,12 +92803,12 @@ static void ApproxCountDistinctSimpleUpdateFunction(Vector inputs[], FunctionDat agg_state->log->AddToLog(vdata, count, indices, counts); } -static void ApproxCountDistinctUpdateFunction(Vector inputs[], FunctionData *bind_data, idx_t input_count, +static void ApproxCountDistinctUpdateFunction(Vector inputs[], AggregateInputData &, idx_t input_count, Vector &state_vector, idx_t count) { D_ASSERT(input_count == 1); - VectorData sdata; - state_vector.Orrify(count, sdata); + UnifiedVectorFormat sdata; + state_vector.ToUnifiedFormat(count, sdata); auto states = (ApproxDistinctCountState **)sdata.data; for (idx_t i = 0; i < count; i++) { @@ -84502,8 +92818,8 @@ static void ApproxCountDistinctUpdateFunction(Vector inputs[], FunctionData *bin } } - VectorData vdata; - inputs[0].Orrify(count, vdata); + UnifiedVectorFormat vdata; + inputs[0].ToUnifiedFormat(count, vdata); uint64_t indices[STANDARD_VECTOR_SIZE]; uint8_t counts[STANDARD_VECTOR_SIZE]; @@ -84513,7 +92829,7 @@ static void ApproxCountDistinctUpdateFunction(Vector inputs[], FunctionData *bin } AggregateFunction GetApproxCountDistinctFunction(const LogicalType &input_type) { - return AggregateFunction( + auto fun = AggregateFunction( {input_type}, LogicalTypeId::BIGINT, AggregateFunction::StateSize, AggregateFunction::StateInitialize, ApproxCountDistinctUpdateFunction, @@ -84521,6 +92837,8 @@ AggregateFunction GetApproxCountDistinctFunction(const LogicalType &input_type) AggregateFunction::StateFinalize, ApproxCountDistinctSimpleUpdateFunction, nullptr, AggregateFunction::StateDestroy); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + return fun; } void ApproxCountDistinctFun::RegisterFunction(BuiltinFunctions &set) { @@ -84607,7 +92925,7 @@ struct ArgMinMaxBase { } template - static void Operation(STATE *state, FunctionData *bind_data, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, + static void Operation(STATE *state, AggregateInputData &, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, ValidityMask &bmask, idx_t xidx, idx_t yidx) { if (!state->is_initialized) { ArgMinMaxAssignValue(state->arg, x_data[xidx], false); @@ -84627,7 +92945,7 @@ struct ArgMinMaxBase { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (!source.is_initialized) { return; } @@ -84646,7 +92964,7 @@ struct ArgMinMaxBase { template struct StringArgMinMax : public ArgMinMaxBase { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->is_initialized) { mask.SetInvalid(idx); } else { @@ -84658,7 +92976,7 @@ struct StringArgMinMax : public ArgMinMaxBase { template struct NumericArgMinMax : public ArgMinMaxBase { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->is_initialized) { mask.SetInvalid(idx); } else { @@ -84797,7 +93115,7 @@ struct BitAndOperation { } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { if (!state->is_set) { state->is_set = true; state->value = input[idx]; @@ -84807,14 +93125,14 @@ struct BitAndOperation { } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { - // count is irrelevant - Operation(state, bind_data, input, mask, 0); + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { + // count is not relevant + Operation(state, aggr_input_data, input, mask, 0); } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->is_set) { mask.SetInvalid(idx); } else { @@ -84823,7 +93141,7 @@ struct BitAndOperation { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (!source.is_set) { // source is NULL, nothing to do. return; @@ -84857,7 +93175,7 @@ struct BitOrOperation { } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { if (!state->is_set) { state->is_set = true; state->value = input[idx]; @@ -84867,14 +93185,14 @@ struct BitOrOperation { } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { // count is irrelevant - Operation(state, bind_data, input, mask, 0); + Operation(state, aggr_input_data, input, mask, 0); } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->is_set) { mask.SetInvalid(idx); } else { @@ -84883,7 +93201,7 @@ struct BitOrOperation { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (!source.is_set) { // source is NULL, nothing to do. return; @@ -84917,7 +93235,7 @@ struct BitXorOperation { } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { if (!state->is_set) { state->is_set = true; state->value = input[idx]; @@ -84927,14 +93245,15 @@ struct BitXorOperation { } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { - // count is irrelevant - Operation(state, bind_data, input, mask, 0); + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { + for (idx_t i = 0; i < count; i++) { + Operation(state, aggr_input_data, input, mask, 0); + } } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->is_set) { mask.SetInvalid(idx); } else { @@ -84943,7 +93262,7 @@ struct BitXorOperation { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (!source.is_set) { // source is NULL, nothing to do. return; @@ -84991,13 +93310,13 @@ struct BoolAndFunFunction { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { target->val = target->val && source.val; target->empty = target->empty && source.empty; } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->empty) { mask.SetInvalid(idx); return; @@ -85006,16 +93325,16 @@ struct BoolAndFunFunction { } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { state->empty = false; state->val = input[idx] && state->val; } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { for (idx_t i = 0; i < count; i++) { - Operation(state, bind_data, input, mask, 0); + Operation(state, aggr_input_data, input, mask, 0); } } static bool IgnoreNull() { @@ -85031,13 +93350,13 @@ struct BoolOrFunFunction { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { target->val = target->val || source.val; target->empty = target->empty && source.empty; } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->empty) { mask.SetInvalid(idx); return; @@ -85045,16 +93364,16 @@ struct BoolOrFunFunction { target[idx] = state->val; } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { state->empty = false; state->val = input[idx] || state->val; } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { for (idx_t i = 0; i < count; i++) { - Operation(state, bind_data, input, mask, 0); + Operation(state, aggr_input_data, input, mask, 0); } } @@ -85107,36 +93426,36 @@ struct BaseCountFunction { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { *target += source; } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { target[idx] = *state; } }; struct CountStarFunction : public BaseCountFunction { template - static void Operation(STATE *state, FunctionData *bind_data, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, idx_t idx) { *state += 1; } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &, idx_t count) { *state += count; } }; struct CountFunction : public BaseCountFunction { template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { *state += 1; } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, + static void ConstantOperation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t count) { *state += count; } @@ -85150,12 +93469,25 @@ AggregateFunction CountFun::GetFunction() { auto fun = AggregateFunction::UnaryAggregate( LogicalType(LogicalTypeId::ANY), LogicalType::BIGINT); fun.name = "count"; + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; return fun; } +static void CountStarSerialize(FieldWriter &writer, const FunctionData *bind_data, const AggregateFunction &function) { +} + +static unique_ptr CountStarDeserialize(ClientContext &context, FieldReader &reader, + AggregateFunction &function) { + return nullptr; +} + AggregateFunction CountStarFun::GetFunction() { auto fun = AggregateFunction::NullaryAggregate(LogicalType::BIGINT); fun.name = "count_star"; + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + // TODO is there a better way to set those? + fun.serialize = CountStarSerialize; + fun.deserialize = CountStarDeserialize; return fun; } @@ -85224,7 +93556,7 @@ struct EntropyFunctionBase { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (!source.distinct) { return; } @@ -85240,7 +93572,7 @@ struct EntropyFunctionBase { } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { double count = state->count; if (state->distinct) { double entropy = 0; @@ -85266,7 +93598,7 @@ struct EntropyFunctionBase { struct EntropyFunction : EntropyFunctionBase { template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { if (!state->distinct) { state->distinct = new unordered_map(); } @@ -85274,17 +93606,17 @@ struct EntropyFunction : EntropyFunctionBase { state->count++; } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { for (idx_t i = 0; i < count; i++) { - Operation(state, bind_data, input, mask, 0); + Operation(state, aggr_input_data, input, mask, 0); } } }; struct EntropyFunctionString : EntropyFunctionBase { template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { if (!state->distinct) { state->distinct = new unordered_map(); } @@ -85294,10 +93626,10 @@ struct EntropyFunctionString : EntropyFunctionBase { } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { for (idx_t i = 0; i < count; i++) { - Operation(state, bind_data, input, mask, 0); + Operation(state, aggr_input_data, input, mask, 0); } } }; @@ -85308,11 +93640,11 @@ AggregateFunction GetEntropyFunction(const LogicalType &input_type, const Logica EntropyFunction>(input_type, result_type); } -AggregateFunction GetEntropyFunction(PhysicalType type) { +AggregateFunction GetEntropyFunctionInternal(PhysicalType type) { switch (type) { case PhysicalType::UINT16: return AggregateFunction::UnaryAggregateDestructor, uint16_t, double, EntropyFunction>( - LogicalType::UTINYINT, LogicalType::DOUBLE); + LogicalType::USMALLINT, LogicalType::DOUBLE); case PhysicalType::UINT32: return AggregateFunction::UnaryAggregateDestructor, uint32_t, double, EntropyFunction>( LogicalType::UINTEGER, LogicalType::DOUBLE); @@ -85321,7 +93653,7 @@ AggregateFunction GetEntropyFunction(PhysicalType type) { LogicalType::UBIGINT, LogicalType::DOUBLE); case PhysicalType::INT16: return AggregateFunction::UnaryAggregateDestructor, int16_t, double, EntropyFunction>( - LogicalType::TINYINT, LogicalType::DOUBLE); + LogicalType::SMALLINT, LogicalType::DOUBLE); case PhysicalType::INT32: return AggregateFunction::UnaryAggregateDestructor, int32_t, double, EntropyFunction>( LogicalType::INTEGER, LogicalType::DOUBLE); @@ -85344,6 +93676,12 @@ AggregateFunction GetEntropyFunction(PhysicalType type) { } } +AggregateFunction GetEntropyFunction(PhysicalType type) { + auto fun = GetEntropyFunctionInternal(type); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + return fun; +} + void EntropyFun::RegisterFunction(BuiltinFunctions &set) { AggregateFunctionSet entropy("entropy"); entropy.AddFunction(GetEntropyFunction(PhysicalType::UINT16)); @@ -85387,15 +93725,18 @@ struct FirstFunctionBase { } }; -template +template struct FirstFunction : public FirstFunctionBase { template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { if (LAST || !state->is_set) { - state->is_set = true; if (!mask.RowIsValid(idx)) { + if (!SKIP_NULLS) { + state->is_set = true; + } state->is_null = true; } else { + state->is_set = true; state->is_null = false; state->value = input[idx]; } @@ -85403,20 +93744,20 @@ struct FirstFunction : public FirstFunctionBase { } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { - Operation(state, bind_data, input, mask, 0); + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { + Operation(state, aggr_input_data, input, mask, 0); } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (!target->is_set) { *target = source; } } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->is_set || state->is_null) { mask.SetInvalid(idx); } else { @@ -85425,14 +93766,17 @@ struct FirstFunction : public FirstFunctionBase { } }; -template +template struct FirstFunctionString : public FirstFunctionBase { template static void SetValue(STATE *state, string_t value, bool is_null) { - state->is_set = true; if (is_null) { - state->is_null = true; + if (!SKIP_NULLS) { + state->is_set = true; + state->is_null = true; + } } else { + state->is_set = true; if (value.IsInlined()) { state->value = value; } else { @@ -85447,27 +93791,27 @@ struct FirstFunctionString : public FirstFunctionBase { } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { if (LAST || !state->is_set) { SetValue(state, input[idx], !mask.RowIsValid(idx)); } } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { - Operation(state, bind_data, input, mask, 0); + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { + Operation(state, aggr_input_data, input, mask, 0); } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (source.is_set && (LAST || !target->is_set)) { SetValue(target, source.value, source.is_null); } } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->is_set || state->is_null) { mask.SetInvalid(idx); } else { @@ -85487,7 +93831,7 @@ struct FirstStateVector { Vector *value; }; -template +template struct FirstVectorFunction { template static void Initialize(STATE *state) { @@ -85501,7 +93845,7 @@ struct FirstVectorFunction { } } static bool IgnoreNull() { - return false; + return SKIP_NULLS; } template @@ -85515,13 +93859,20 @@ struct FirstVectorFunction { VectorOperations::Copy(input, *state->value, sel, 1, 0, 0); } - static void Update(Vector inputs[], FunctionData *, idx_t input_count, Vector &state_vector, idx_t count) { + static void Update(Vector inputs[], AggregateInputData &, idx_t input_count, Vector &state_vector, idx_t count) { auto &input = inputs[0]; - VectorData sdata; - state_vector.Orrify(count, sdata); + UnifiedVectorFormat idata; + input.ToUnifiedFormat(count, idata); + + UnifiedVectorFormat sdata; + state_vector.ToUnifiedFormat(count, sdata); auto states = (FirstStateVector **)sdata.data; for (idx_t i = 0; i < count; i++) { + const auto idx = idata.sel->get_index(i); + if (SKIP_NULLS && !idata.validity.RowIsValid(idx)) { + continue; + } auto state = states[sdata.sel->get_index(i)]; if (LAST || !state->value) { SetValue(state, input, i); @@ -85530,14 +93881,14 @@ struct FirstVectorFunction { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (source.value && (LAST || !target->value)) { SetValue(target, *source.value, 0); } } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->value) { // we need to use FlatVector::SetNull here // since for STRUCT columns only setting the validity mask of the struct is incorrect @@ -85560,79 +93911,77 @@ struct FirstVectorFunction { } }; -template +template static AggregateFunction GetFirstAggregateTemplated(LogicalType type) { - auto agg = AggregateFunction::UnaryAggregate, T, T, FirstFunction>(type, type); - return agg; + return AggregateFunction::UnaryAggregate, T, T, FirstFunction>(type, type); } -template +template static AggregateFunction GetFirstFunction(const LogicalType &type); -template +template AggregateFunction GetDecimalFirstFunction(const LogicalType &type) { D_ASSERT(type.id() == LogicalTypeId::DECIMAL); switch (type.InternalType()) { case PhysicalType::INT16: - return GetFirstFunction(LogicalType::SMALLINT); + return GetFirstFunction(LogicalType::SMALLINT); case PhysicalType::INT32: - return GetFirstFunction(LogicalType::INTEGER); + return GetFirstFunction(LogicalType::INTEGER); case PhysicalType::INT64: - return GetFirstFunction(LogicalType::BIGINT); + return GetFirstFunction(LogicalType::BIGINT); default: - return GetFirstFunction(LogicalType::HUGEINT); + return GetFirstFunction(LogicalType::HUGEINT); } } -template +template static AggregateFunction GetFirstFunction(const LogicalType &type) { switch (type.id()) { case LogicalTypeId::BOOLEAN: - return GetFirstAggregateTemplated(type); + return GetFirstAggregateTemplated(type); case LogicalTypeId::TINYINT: - return GetFirstAggregateTemplated(type); + return GetFirstAggregateTemplated(type); case LogicalTypeId::SMALLINT: - return GetFirstAggregateTemplated(type); + return GetFirstAggregateTemplated(type); case LogicalTypeId::INTEGER: case LogicalTypeId::DATE: - return GetFirstAggregateTemplated(type); + return GetFirstAggregateTemplated(type); case LogicalTypeId::BIGINT: case LogicalTypeId::TIME: case LogicalTypeId::TIMESTAMP: case LogicalTypeId::TIME_TZ: case LogicalTypeId::TIMESTAMP_TZ: - return GetFirstAggregateTemplated(type); + return GetFirstAggregateTemplated(type); case LogicalTypeId::UTINYINT: - return GetFirstAggregateTemplated(type); + return GetFirstAggregateTemplated(type); case LogicalTypeId::USMALLINT: - return GetFirstAggregateTemplated(type); + return GetFirstAggregateTemplated(type); case LogicalTypeId::UINTEGER: - return GetFirstAggregateTemplated(type); + return GetFirstAggregateTemplated(type); case LogicalTypeId::UBIGINT: - return GetFirstAggregateTemplated(type); + return GetFirstAggregateTemplated(type); case LogicalTypeId::HUGEINT: - return GetFirstAggregateTemplated(type); + return GetFirstAggregateTemplated(type); case LogicalTypeId::FLOAT: - return GetFirstAggregateTemplated(type); + return GetFirstAggregateTemplated(type); case LogicalTypeId::DOUBLE: - return GetFirstAggregateTemplated(type); + return GetFirstAggregateTemplated(type); case LogicalTypeId::INTERVAL: - return GetFirstAggregateTemplated(type); + return GetFirstAggregateTemplated(type); case LogicalTypeId::VARCHAR: - case LogicalTypeId::BLOB: { - auto agg = AggregateFunction::UnaryAggregateDestructor, string_t, string_t, - FirstFunctionString>(type, type); - return agg; - } + case LogicalTypeId::BLOB: + return AggregateFunction::UnaryAggregateDestructor, string_t, string_t, + FirstFunctionString>(type, type); case LogicalTypeId::DECIMAL: { type.Verify(); - AggregateFunction function = GetDecimalFirstFunction(type); + AggregateFunction function = GetDecimalFirstFunction(type); function.arguments[0] = type; function.return_type = type; + // TODO set_key here? return function; } default: { - using OP = FirstVectorFunction; + using OP = FirstVectorFunction; return AggregateFunction({type}, type, AggregateFunction::StateSize, AggregateFunction::StateInitialize, OP::Update, AggregateFunction::StateCombine, @@ -85643,16 +93992,16 @@ static AggregateFunction GetFirstFunction(const LogicalType &type) { } AggregateFunction FirstFun::GetFunction(const LogicalType &type) { - auto fun = GetFirstFunction(type); + auto fun = GetFirstFunction(type); fun.name = "first"; return fun; } -template +template unique_ptr BindDecimalFirst(ClientContext &context, AggregateFunction &function, vector> &arguments) { auto decimal_type = arguments[0]->return_type; - function = GetFirstFunction(decimal_type); + function = GetFirstFunction(decimal_type); function.name = "first"; function.return_type = decimal_type; return nullptr; @@ -85661,15 +94010,19 @@ unique_ptr BindDecimalFirst(ClientContext &context, AggregateFunct void FirstFun::RegisterFunction(BuiltinFunctions &set) { AggregateFunctionSet first("first"); AggregateFunctionSet last("last"); + AggregateFunctionSet any_value("any_value"); for (auto &type : LogicalType::AllTypes()) { if (type.id() == LogicalTypeId::DECIMAL) { first.AddFunction(AggregateFunction({type}, type, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - BindDecimalFirst, nullptr, nullptr, nullptr)); + BindDecimalFirst, nullptr, nullptr, nullptr)); last.AddFunction(AggregateFunction({type}, type, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - BindDecimalFirst, nullptr, nullptr, nullptr)); + BindDecimalFirst, nullptr, nullptr, nullptr)); + any_value.AddFunction(AggregateFunction({type}, type, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + BindDecimalFirst, nullptr, nullptr, nullptr)); } else { - first.AddFunction(GetFirstFunction(type)); - last.AddFunction(GetFirstFunction(type)); + first.AddFunction(GetFirstFunction(type)); + last.AddFunction(GetFirstFunction(type)); + any_value.AddFunction(GetFirstFunction(type)); } } set.AddFunction(first); @@ -85677,6 +94030,8 @@ void FirstFun::RegisterFunction(BuiltinFunctions &set) { set.AddFunction(first); set.AddFunction(last); + + set.AddFunction(any_value); } } // namespace duckdb @@ -85703,15 +94058,15 @@ struct KurtosisOperation { } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { for (idx_t i = 0; i < count; i++) { - Operation(state, bind_data, input, mask, 0); + Operation(state, aggr_input_data, input, mask, 0); } } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *data, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *data, ValidityMask &mask, idx_t idx) { state->n++; state->sum += data[idx]; state->sum_sqr += pow(data[idx], 2); @@ -85720,7 +94075,7 @@ struct KurtosisOperation { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (source.n == 0) { return; } @@ -85732,7 +94087,7 @@ struct KurtosisOperation { } template - static void Finalize(Vector &result, FunctionData *bind_data, STATE *state, TARGET_TYPE *target, ValidityMask &mask, + static void Finalize(Vector &result, AggregateInputData &, STATE *state, TARGET_TYPE *target, ValidityMask &mask, idx_t idx) { auto n = (double)state->n; if (n <= 3) { @@ -85784,7 +94139,6 @@ void KurtosisFun::RegisterFunction(BuiltinFunctions &set) { - namespace duckdb { template @@ -85810,24 +94164,24 @@ static AggregateFunction GetUnaryAggregate(LogicalType type) { case LogicalTypeId::TIMESTAMP_TZ: case LogicalTypeId::TIME_TZ: case LogicalTypeId::BIGINT: - return AggregateFunction::UnaryAggregate, int64_t, int64_t, OP>(type, type, true); + return AggregateFunction::UnaryAggregate, int64_t, int64_t, OP>(type, type); case LogicalTypeId::UTINYINT: - return AggregateFunction::UnaryAggregate, uint8_t, uint8_t, OP>(type, type, true); + return AggregateFunction::UnaryAggregate, uint8_t, uint8_t, OP>(type, type); case LogicalTypeId::USMALLINT: - return AggregateFunction::UnaryAggregate, uint16_t, uint16_t, OP>(type, type, true); + return AggregateFunction::UnaryAggregate, uint16_t, uint16_t, OP>(type, type); case LogicalTypeId::UINTEGER: - return AggregateFunction::UnaryAggregate, uint32_t, uint32_t, OP>(type, type, true); + return AggregateFunction::UnaryAggregate, uint32_t, uint32_t, OP>(type, type); case LogicalTypeId::UBIGINT: - return AggregateFunction::UnaryAggregate, uint64_t, uint64_t, OP>(type, type, true); + return AggregateFunction::UnaryAggregate, uint64_t, uint64_t, OP>(type, type); case LogicalTypeId::HUGEINT: case LogicalTypeId::UUID: - return AggregateFunction::UnaryAggregate, hugeint_t, hugeint_t, OP>(type, type, true); + return AggregateFunction::UnaryAggregate, hugeint_t, hugeint_t, OP>(type, type); case LogicalTypeId::FLOAT: - return AggregateFunction::UnaryAggregate, float, float, OP>(type, type, true); + return AggregateFunction::UnaryAggregate, float, float, OP>(type, type); case LogicalTypeId::DOUBLE: - return AggregateFunction::UnaryAggregate, double, double, OP>(type, type, true); + return AggregateFunction::UnaryAggregate, double, double, OP>(type, type); case LogicalTypeId::INTERVAL: - return AggregateFunction::UnaryAggregate, interval_t, interval_t, OP>(type, type, true); + return AggregateFunction::UnaryAggregate, interval_t, interval_t, OP>(type, type); default: throw InternalException("Unimplemented type for min/max aggregate"); } @@ -85840,7 +94194,7 @@ struct MinMaxBase { } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, + static void ConstantOperation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t count) { D_ASSERT(mask.RowIsValid(0)); if (!state->isset) { @@ -85852,7 +94206,7 @@ struct MinMaxBase { } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { if (!state->isset) { OP::template Assign(state, input[idx]); state->isset = true; @@ -85873,7 +94227,7 @@ struct NumericMinMaxBase : public MinMaxBase { } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { mask.Set(idx, state->isset); target[idx] = state->value; } @@ -85888,7 +94242,7 @@ struct MinOperation : public NumericMinMaxBase { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (!source.isset) { // source is NULL, nothing to do return; @@ -85911,7 +94265,7 @@ struct MaxOperation : public NumericMinMaxBase { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (!source.isset) { // source is NULL, nothing to do return; @@ -85949,7 +94303,7 @@ struct StringMinMaxBase : public MinMaxBase { } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->isset) { mask.SetInvalid(idx); } else { @@ -85958,7 +94312,7 @@ struct StringMinMaxBase : public MinMaxBase { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (!source.isset) { // source is NULL, nothing to do return; @@ -85993,9 +94347,9 @@ struct MaxOperationString : public StringMinMaxBase { template static bool TemplatedOptimumType(Vector &left, idx_t lidx, idx_t lcount, Vector &right, idx_t ridx, idx_t rcount) { - VectorData lvdata, rvdata; - left.Orrify(lcount, lvdata); - right.Orrify(rcount, rvdata); + UnifiedVectorFormat lvdata, rvdata; + left.ToUnifiedFormat(lcount, lvdata); + right.ToUnifiedFormat(rcount, rvdata); lidx = lvdata.sel->get_index(lidx); ridx = rvdata.sel->get_index(ridx); @@ -86064,9 +94418,9 @@ static bool TemplatedOptimumStruct(Vector &left, idx_t lidx_p, idx_t lcount, Vec idx_t rcount) { // STRUCT dictionaries apply to all the children // so map the indexes first - VectorData lvdata, rvdata; - left.Orrify(lcount, lvdata); - right.Orrify(rcount, rvdata); + UnifiedVectorFormat lvdata, rvdata; + left.ToUnifiedFormat(lcount, lvdata); + right.ToUnifiedFormat(rcount, rvdata); idx_t lidx = lvdata.sel->get_index(lidx_p); idx_t ridx = rvdata.sel->get_index(ridx_p); @@ -86106,9 +94460,9 @@ static bool TemplatedOptimumStruct(Vector &left, idx_t lidx_p, idx_t lcount, Vec template static bool TemplatedOptimumList(Vector &left, idx_t lidx, idx_t lcount, Vector &right, idx_t ridx, idx_t rcount) { - VectorData lvdata, rvdata; - left.Orrify(lcount, lvdata); - right.Orrify(rcount, rvdata); + UnifiedVectorFormat lvdata, rvdata; + left.ToUnifiedFormat(lcount, lvdata); + right.ToUnifiedFormat(rcount, rvdata); // Update the indexes and vector sizes for recursion. lidx = lvdata.sel->get_index(lidx); @@ -86194,13 +94548,13 @@ struct VectorMinMaxBase { } template - static void Update(Vector inputs[], FunctionData *, idx_t input_count, Vector &state_vector, idx_t count) { + static void Update(Vector inputs[], AggregateInputData &, idx_t input_count, Vector &state_vector, idx_t count) { auto &input = inputs[0]; - VectorData idata; - input.Orrify(count, idata); + UnifiedVectorFormat idata; + input.ToUnifiedFormat(count, idata); - VectorData sdata; - state_vector.Orrify(count, sdata); + UnifiedVectorFormat sdata; + state_vector.ToUnifiedFormat(count, sdata); auto states = (STATE **)sdata.data; for (idx_t i = 0; i < count; i++) { @@ -86219,7 +94573,7 @@ struct VectorMinMaxBase { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (!source.value) { return; } else if (!target->value) { @@ -86230,7 +94584,7 @@ struct VectorMinMaxBase { } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->value) { // we need to use SetNull here // since for STRUCT columns only setting the validity mask of the struct is incorrect @@ -86318,14 +94672,14 @@ static void AddMinMaxOperator(AggregateFunctionSet &set) { AggregateFunction::UnaryAggregateDestructor, string_t, string_t, OP_STRING>( type.id(), type.id())); } else if (type.id() == LogicalTypeId::DECIMAL) { - set.AddFunction(AggregateFunction({type}, type, nullptr, nullptr, nullptr, nullptr, nullptr, false, nullptr, + set.AddFunction(AggregateFunction({type}, type, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, BindDecimalMinMax)); } else if (type.id() == LogicalTypeId::LIST || type.id() == LogicalTypeId::MAP || type.id() == LogicalTypeId::STRUCT) { set.AddFunction(GetMinMaxFunction(type)); } else { - set.AddFunction(GetUnaryAggregate(type)); + set.AddFunction(GetUnaryAggregate(type)); // TODO this is pretty evil } } } @@ -86364,13 +94718,13 @@ struct ProductFunction { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { target->val *= source.val; target->empty = target->empty && source.empty; } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->empty) { mask.SetInvalid(idx); return; @@ -86378,7 +94732,7 @@ struct ProductFunction { target[idx] = state->val; } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { if (state->empty) { state->empty = false; } @@ -86386,10 +94740,10 @@ struct ProductFunction { } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { for (idx_t i = 0; i < count; i++) { - Operation(state, bind_data, input, mask, 0); + Operation(state, aggr_input_data, input, mask, 0); } } @@ -86435,15 +94789,15 @@ struct SkewnessOperation { } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { for (idx_t i = 0; i < count; i++) { - Operation(state, bind_data, input, mask, 0); + Operation(state, aggr_input_data, input, mask, 0); } } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *data, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *data, ValidityMask &mask, idx_t idx) { state->n++; state->sum += data[idx]; state->sum_sqr += pow(data[idx], 2); @@ -86451,7 +94805,7 @@ struct SkewnessOperation { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (source.n == 0) { return; } @@ -86463,7 +94817,7 @@ struct SkewnessOperation { } template - static void Finalize(Vector &result, FunctionData *bind_data, STATE *state, TARGET_TYPE *target, ValidityMask &mask, + static void Finalize(Vector &result, AggregateInputData &, STATE *state, TARGET_TYPE *target, ValidityMask &mask, idx_t idx) { if (state->n <= 2) { mask.SetInvalid(idx); @@ -86506,6 +94860,7 @@ void SkewFun::RegisterFunction(BuiltinFunctions &set) { + namespace duckdb { struct StringAggState { @@ -86538,7 +94893,7 @@ struct StringAggFunction { } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->dataptr) { mask.SetInvalid(idx); } else { @@ -86593,26 +94948,26 @@ struct StringAggFunction { } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *str_data, ValidityMask &str_mask, - idx_t str_idx) { - PerformOperation(state, str_data[str_idx], bind_data); + static void Operation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *str_data, + ValidityMask &str_mask, idx_t str_idx) { + PerformOperation(state, str_data[str_idx], aggr_input_data.bind_data); } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { for (idx_t i = 0; i < count; i++) { - Operation(state, bind_data, input, mask, 0); + Operation(state, aggr_input_data, input, mask, 0); } } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &aggr_input_data) { if (!source.dataptr) { // source is not set: skip combining return; } - PerformOperation(target, string_t(source.dataptr, source.size), bind_data); + PerformOperation(target, string_t(source.dataptr, source.size), aggr_input_data.bind_data); } }; @@ -86623,6 +94978,9 @@ unique_ptr StringAggBind(ClientContext &context, AggregateFunction return make_unique(","); } D_ASSERT(arguments.size() == 2); + if (arguments[1]->HasParameter()) { + throw ParameterNotResolvedException(); + } if (!arguments[1]->IsFoldable()) { throw BinderException("Separator argument to StringAgg must be a constant"); } @@ -86630,29 +94988,38 @@ unique_ptr StringAggBind(ClientContext &context, AggregateFunction if (separator_val.IsNull()) { arguments[0] = make_unique(Value(LogicalType::VARCHAR)); } - function.arguments.erase(function.arguments.begin() + 1); + Function::EraseArgument(function, arguments, arguments.size() - 1); return make_unique(separator_val.ToString()); } +static void StringAggSerialize(FieldWriter &writer, const FunctionData *bind_data_p, + const AggregateFunction &function) { + D_ASSERT(bind_data_p); + auto bind_data = (StringAggBindData *)bind_data_p; + writer.WriteString(bind_data->sep); +} + +unique_ptr StringAggDeserialize(ClientContext &context, FieldReader &reader, + AggregateFunction &bound_function) { + auto sep = reader.ReadRequired(); + return make_unique(move(sep)); +} + void StringAggFun::RegisterFunction(BuiltinFunctions &set) { AggregateFunctionSet string_agg("string_agg"); - string_agg.AddFunction( - AggregateFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::VARCHAR, - AggregateFunction::StateSize, - AggregateFunction::StateInitialize, - AggregateFunction::UnaryScatterUpdate, - AggregateFunction::StateCombine, - AggregateFunction::StateFinalize, - AggregateFunction::UnaryUpdate, StringAggBind, - AggregateFunction::StateDestroy)); - string_agg.AddFunction( - AggregateFunction({LogicalType::VARCHAR}, LogicalType::VARCHAR, AggregateFunction::StateSize, - AggregateFunction::StateInitialize, - AggregateFunction::UnaryScatterUpdate, - AggregateFunction::StateCombine, - AggregateFunction::StateFinalize, - AggregateFunction::UnaryUpdate, StringAggBind, - AggregateFunction::StateDestroy)); + AggregateFunction string_agg_param( + {LogicalType::VARCHAR}, LogicalType::VARCHAR, AggregateFunction::StateSize, + AggregateFunction::StateInitialize, + AggregateFunction::UnaryScatterUpdate, + AggregateFunction::StateCombine, + AggregateFunction::StateFinalize, + AggregateFunction::UnaryUpdate, StringAggBind, + AggregateFunction::StateDestroy); + string_agg_param.serialize = StringAggSerialize; + string_agg_param.deserialize = StringAggDeserialize; + string_agg.AddFunction(string_agg_param); + string_agg_param.arguments.emplace_back(LogicalType::VARCHAR); + string_agg.AddFunction(string_agg_param); set.AddFunction(string_agg); string_agg.name = "group_concat"; set.AddFunction(string_agg); @@ -86675,7 +95042,7 @@ struct SumSetOperation { state->Initialize(); } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { target->Combine(source); } template @@ -86686,7 +95053,7 @@ struct SumSetOperation { struct IntegerSumOperation : public BaseSumOperation { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->isset) { mask.SetInvalid(idx); } else { @@ -86697,7 +95064,7 @@ struct IntegerSumOperation : public BaseSumOperation { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->isset) { mask.SetInvalid(idx); } else { @@ -86709,7 +95076,7 @@ struct SumToHugeintOperation : public BaseSumOperation struct DoubleSumOperation : public BaseSumOperation { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->isset) { mask.SetInvalid(idx); } else { @@ -86726,7 +95093,7 @@ using KahanSumOperation = DoubleSumOperation; struct HugeintSumOperation : public BaseSumOperation { template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (!state->isset) { mask.SetInvalid(idx); } else { @@ -86766,53 +95133,63 @@ unique_ptr SumPropagateStats(ClientContext &context, BoundAggreg return nullptr; } // total sum is guaranteed to fit in a single int64: use int64 sum instead of hugeint sum - switch (internal_type) { - case PhysicalType::INT32: - expr.function = - AggregateFunction::UnaryAggregate, int32_t, hugeint_t, IntegerSumOperation>( - LogicalType::INTEGER, LogicalType::HUGEINT, true); - expr.function.name = "sum"; - break; - case PhysicalType::INT64: - expr.function = - AggregateFunction::UnaryAggregate, int64_t, hugeint_t, IntegerSumOperation>( - LogicalType::BIGINT, LogicalType::HUGEINT, true); - expr.function.name = "sum"; - break; - default: - throw InternalException("Unsupported type for propagate sum stats"); - } + expr.function = SumFun::GetSumAggregateNoOverflow(internal_type); } return nullptr; } AggregateFunction SumFun::GetSumAggregate(PhysicalType type) { switch (type) { - case PhysicalType::INT16: - return AggregateFunction::UnaryAggregate, int16_t, hugeint_t, IntegerSumOperation>( - LogicalType::SMALLINT, LogicalType::HUGEINT, true); + case PhysicalType::INT16: { + auto function = AggregateFunction::UnaryAggregate, int16_t, hugeint_t, IntegerSumOperation>( + LogicalType::SMALLINT, LogicalType::HUGEINT); + return function; + } + case PhysicalType::INT32: { auto function = AggregateFunction::UnaryAggregate, int32_t, hugeint_t, SumToHugeintOperation>( - LogicalType::INTEGER, LogicalType::HUGEINT, true); + LogicalType::INTEGER, LogicalType::HUGEINT); function.statistics = SumPropagateStats; return function; } case PhysicalType::INT64: { auto function = AggregateFunction::UnaryAggregate, int64_t, hugeint_t, SumToHugeintOperation>( - LogicalType::BIGINT, LogicalType::HUGEINT, true); + LogicalType::BIGINT, LogicalType::HUGEINT); function.statistics = SumPropagateStats; return function; } - case PhysicalType::INT128: - return AggregateFunction::UnaryAggregate, hugeint_t, hugeint_t, HugeintSumOperation>( - LogicalType::HUGEINT, LogicalType::HUGEINT, true); + case PhysicalType::INT128: { + auto function = + AggregateFunction::UnaryAggregate, hugeint_t, hugeint_t, HugeintSumOperation>( + LogicalType::HUGEINT, LogicalType::HUGEINT); + return function; + } default: throw InternalException("Unimplemented sum aggregate"); } } +AggregateFunction SumFun::GetSumAggregateNoOverflow(PhysicalType type) { + switch (type) { + case PhysicalType::INT32: { + auto function = AggregateFunction::UnaryAggregate, int32_t, hugeint_t, IntegerSumOperation>( + LogicalType::INTEGER, LogicalType::HUGEINT); + function.name = "sum_no_overflow"; + return function; + } + case PhysicalType::INT64: { + auto function = AggregateFunction::UnaryAggregate, int64_t, hugeint_t, IntegerSumOperation>( + LogicalType::BIGINT, LogicalType::HUGEINT); + function.name = "sum_no_overflow"; + return function; + } + default: + throw BinderException("Unsupported internal type for sum_no_overflow"); + } +} + unique_ptr BindDecimalSum(ClientContext &context, AggregateFunction &function, vector> &arguments) { auto decimal_type = arguments[0]->return_type; @@ -86823,24 +95200,43 @@ unique_ptr BindDecimalSum(ClientContext &context, AggregateFunctio return nullptr; } +unique_ptr BindDecimalSumNoOverflow(ClientContext &context, AggregateFunction &function, + vector> &arguments) { + auto decimal_type = arguments[0]->return_type; + function = SumFun::GetSumAggregateNoOverflow(decimal_type.InternalType()); + function.name = "sum_no_overflow"; + function.arguments[0] = decimal_type; + function.return_type = LogicalType::DECIMAL(Decimal::MAX_WIDTH_DECIMAL, DecimalType::GetScale(decimal_type)); + return nullptr; +} + void SumFun::RegisterFunction(BuiltinFunctions &set) { AggregateFunctionSet sum("sum"); // decimal sum.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL}, LogicalTypeId::DECIMAL, nullptr, nullptr, nullptr, - nullptr, nullptr, true, nullptr, BindDecimalSum)); + nullptr, nullptr, FunctionNullHandling::DEFAULT_NULL_HANDLING, nullptr, + BindDecimalSum)); sum.AddFunction(GetSumAggregate(PhysicalType::INT16)); sum.AddFunction(GetSumAggregate(PhysicalType::INT32)); sum.AddFunction(GetSumAggregate(PhysicalType::INT64)); sum.AddFunction(GetSumAggregate(PhysicalType::INT128)); sum.AddFunction(AggregateFunction::UnaryAggregate, double, double, NumericSumOperation>( - LogicalType::DOUBLE, LogicalType::DOUBLE, true)); + LogicalType::DOUBLE, LogicalType::DOUBLE)); set.AddFunction(sum); + AggregateFunctionSet sum_no_overflow("sum_no_overflow"); + sum_no_overflow.AddFunction(GetSumAggregateNoOverflow(PhysicalType::INT32)); + sum_no_overflow.AddFunction(GetSumAggregateNoOverflow(PhysicalType::INT64)); + sum_no_overflow.AddFunction( + AggregateFunction({LogicalTypeId::DECIMAL}, LogicalTypeId::DECIMAL, nullptr, nullptr, nullptr, nullptr, nullptr, + FunctionNullHandling::DEFAULT_NULL_HANDLING, nullptr, BindDecimalSumNoOverflow)); + set.AddFunction(sum_no_overflow); + // fsum AggregateFunctionSet fsum("fsum"); fsum.AddFunction(AggregateFunction::UnaryAggregate( - LogicalType::DOUBLE, LogicalType::DOUBLE, true)); + LogicalType::DOUBLE, LogicalType::DOUBLE)); set.AddFunction(fsum); @@ -87596,6 +95992,7 @@ class TDigest { + #include #include #include @@ -87611,7 +96008,7 @@ struct ApproximateQuantileBindData : public FunctionData { explicit ApproximateQuantileBindData(float quantile_p) : quantiles(1, quantile_p) { } - explicit ApproximateQuantileBindData(const vector &quantiles_p) : quantiles(quantiles_p) { + explicit ApproximateQuantileBindData(vector quantiles_p) : quantiles(move(quantiles_p)) { } unique_ptr Copy() const override { @@ -87620,7 +96017,23 @@ struct ApproximateQuantileBindData : public FunctionData { bool Equals(const FunctionData &other_p) const override { auto &other = (ApproximateQuantileBindData &)other_p; - return quantiles == other.quantiles; + // return quantiles == other.quantiles; + if (quantiles != other.quantiles) { + return false; + } + return true; + } + + static void Serialize(FieldWriter &writer, const FunctionData *bind_data_p, const AggregateFunction &function) { + D_ASSERT(bind_data_p); + auto bind_data = (ApproximateQuantileBindData *)bind_data_p; + writer.WriteList(bind_data->quantiles); + } + + static unique_ptr Deserialize(ClientContext &context, FieldReader &reader, + AggregateFunction &bound_function) { + auto quantiles = reader.ReadRequiredList(); + return make_unique(move(quantiles)); } vector quantiles; @@ -87636,15 +96049,15 @@ struct ApproxQuantileOperation { } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { for (idx_t i = 0; i < count; i++) { - Operation(state, bind_data, input, mask, 0); + Operation(state, aggr_input_data, input, mask, 0); } } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *data, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *data, ValidityMask &mask, idx_t idx) { if (!state->h) { state->h = new duckdb_tdigest::TDigest(100); } @@ -87654,7 +96067,7 @@ struct ApproxQuantileOperation { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (source.pos == 0) { return; } @@ -87681,7 +96094,7 @@ struct ApproxQuantileOperation { struct ApproxQuantileScalarOperation : public ApproxQuantileOperation { template - static void Finalize(Vector &result, FunctionData *bind_data_p, STATE *state, TARGET_TYPE *target, + static void Finalize(Vector &result, AggregateInputData &aggr_input_data, STATE *state, TARGET_TYPE *target, ValidityMask &mask, idx_t idx) { if (state->pos == 0) { @@ -87689,9 +96102,9 @@ struct ApproxQuantileScalarOperation : public ApproxQuantileOperation { return; } D_ASSERT(state->h); - D_ASSERT(bind_data_p); + D_ASSERT(aggr_input_data.bind_data); state->h->compress(); - auto bind_data = (ApproximateQuantileBindData *)bind_data_p; + auto bind_data = (ApproximateQuantileBindData *)aggr_input_data.bind_data; D_ASSERT(bind_data->quantiles.size() == 1); target[idx] = Cast::template Operation(state->h->quantile(bind_data->quantiles[0])); } @@ -87703,12 +96116,10 @@ AggregateFunction GetApproximateQuantileAggregateFunction(PhysicalType type) { return AggregateFunction::UnaryAggregateDestructor(LogicalType::SMALLINT, LogicalType::SMALLINT); - case PhysicalType::INT32: return AggregateFunction::UnaryAggregateDestructor(LogicalType::INTEGER, LogicalType::INTEGER); - case PhysicalType::INT64: return AggregateFunction::UnaryAggregateDestructor(LogicalType::BIGINT, @@ -87717,16 +96128,17 @@ AggregateFunction GetApproximateQuantileAggregateFunction(PhysicalType type) { return AggregateFunction::UnaryAggregateDestructor(LogicalType::DOUBLE, LogicalType::DOUBLE); - default: throw InternalException("Unimplemented quantile aggregate"); } } static float CheckApproxQuantile(const Value &quantile_val) { + if (quantile_val.IsNull()) { + throw BinderException("APPROXIMATE QUANTILE parameter cannot be NULL"); + } auto quantile = quantile_val.GetValue(); - - if (quantile_val.IsNull() || quantile < 0 || quantile > 1) { + if (quantile < 0 || quantile > 1) { throw BinderException("APPROXIMATE QUANTILE can only take parameters in range [0, 1]"); } @@ -87735,7 +96147,10 @@ static float CheckApproxQuantile(const Value &quantile_val) { unique_ptr BindApproxQuantile(ClientContext &context, AggregateFunction &function, vector> &arguments) { - if (!arguments[1]->IsScalar()) { + if (arguments[1]->HasParameter()) { + throw ParameterNotResolvedException(); + } + if (!arguments[1]->IsFoldable()) { throw BinderException("APPROXIMATE QUANTILE can only take constant quantile parameters"); } Value quantile_val = ExpressionExecutor::EvaluateScalar(*arguments[1]); @@ -87750,7 +96165,7 @@ unique_ptr BindApproxQuantile(ClientContext &context, AggregateFun } // remove the quantile argument so we can use the unary aggregate - arguments.pop_back(); + Function::EraseArgument(function, arguments, arguments.size() - 1); return make_unique(quantiles); } @@ -87759,12 +96174,16 @@ unique_ptr BindApproxQuantileDecimal(ClientContext &context, Aggre auto bind_data = BindApproxQuantile(context, function, arguments); function = GetApproximateQuantileAggregateFunction(arguments[0]->return_type.InternalType()); function.name = "approx_quantile"; + function.serialize = ApproximateQuantileBindData::Serialize; + function.deserialize = ApproximateQuantileBindData::Deserialize; return bind_data; } AggregateFunction GetApproximateQuantileAggregate(PhysicalType type) { auto fun = GetApproximateQuantileAggregateFunction(type); fun.bind = BindApproxQuantile; + fun.serialize = ApproximateQuantileBindData::Serialize; + fun.deserialize = ApproximateQuantileBindData::Deserialize; // temporarily push an argument so we can bind the actual quantile fun.arguments.emplace_back(LogicalType::FLOAT); return fun; @@ -87774,15 +96193,15 @@ template struct ApproxQuantileListOperation : public ApproxQuantileOperation { template - static void Finalize(Vector &result_list, FunctionData *bind_data_p, STATE *state, RESULT_TYPE *target, + static void Finalize(Vector &result_list, AggregateInputData &aggr_input_data, STATE *state, RESULT_TYPE *target, ValidityMask &mask, idx_t idx) { if (state->pos == 0) { mask.SetInvalid(idx); return; } - D_ASSERT(bind_data_p); - auto bind_data = (ApproximateQuantileBindData *)bind_data_p; + D_ASSERT(aggr_input_data.bind_data); + auto bind_data = (ApproximateQuantileBindData *)aggr_input_data.bind_data; auto &result = ListVector::GetEntry(result_list); auto ridx = ListVector::GetListSize(result_list); @@ -87804,12 +96223,12 @@ struct ApproxQuantileListOperation : public ApproxQuantileOperation { } template - static void FinalizeList(Vector &states, FunctionData *bind_data_p, Vector &result, idx_t count, // NOLINT + static void FinalizeList(Vector &states, AggregateInputData &aggr_input_data, Vector &result, idx_t count, // NOLINT idx_t offset) { D_ASSERT(result.GetType().id() == LogicalTypeId::LIST); - D_ASSERT(bind_data_p); - auto bind_data = (ApproximateQuantileBindData *)bind_data_p; + D_ASSERT(aggr_input_data.bind_data); + auto bind_data = (ApproximateQuantileBindData *)aggr_input_data.bind_data; if (states.GetVectorType() == VectorType::CONSTANT_VECTOR) { result.SetVectorType(VectorType::CONSTANT_VECTOR); @@ -87818,7 +96237,7 @@ struct ApproxQuantileListOperation : public ApproxQuantileOperation { auto sdata = ConstantVector::GetData(states); auto rdata = ConstantVector::GetData(result); auto &mask = ConstantVector::Validity(result); - Finalize(result, bind_data, sdata[0], rdata, mask, 0); + Finalize(result, aggr_input_data, sdata[0], rdata, mask, 0); } else { D_ASSERT(states.GetVectorType() == VectorType::FLAT_VECTOR); result.SetVectorType(VectorType::FLAT_VECTOR); @@ -87828,7 +96247,7 @@ struct ApproxQuantileListOperation : public ApproxQuantileOperation { auto rdata = FlatVector::GetData(result); auto &mask = FlatVector::Validity(result); for (idx_t i = 0; i < count; i++) { - Finalize(result, bind_data, sdata[i], rdata, mask, i + offset); + Finalize(result, aggr_input_data, sdata[i], rdata, mask, i + offset); } } @@ -87851,6 +96270,8 @@ AggregateFunction GetTypedApproxQuantileListAggregateFunction(const LogicalType using STATE = ApproxQuantileState; using OP = ApproxQuantileListOperation; auto fun = ApproxQuantileListAggregate(type, type); + fun.serialize = ApproximateQuantileBindData::Serialize; + fun.deserialize = ApproximateQuantileBindData::Deserialize; return fun; } @@ -87866,7 +96287,6 @@ AggregateFunction GetApproxQuantileListAggregateFunction(const LogicalType &type return GetTypedApproxQuantileListAggregateFunction(type); case LogicalTypeId::HUGEINT: return GetTypedApproxQuantileListAggregateFunction(type); - case LogicalTypeId::FLOAT: return GetTypedApproxQuantileListAggregateFunction(type); case LogicalTypeId::DOUBLE: @@ -87884,8 +96304,6 @@ AggregateFunction GetApproxQuantileListAggregateFunction(const LogicalType &type default: throw NotImplementedException("Unimplemented approximate quantile list aggregate"); } - break; - default: // TODO: Add quantitative temporal types throw NotImplementedException("Unimplemented approximate quantile list aggregate"); @@ -87897,12 +96315,16 @@ unique_ptr BindApproxQuantileDecimalList(ClientContext &context, A auto bind_data = BindApproxQuantile(context, function, arguments); function = GetApproxQuantileListAggregateFunction(arguments[0]->return_type); function.name = "approx_quantile"; + function.serialize = ApproximateQuantileBindData::Serialize; + function.deserialize = ApproximateQuantileBindData::Deserialize; return bind_data; } AggregateFunction GetApproxQuantileListAggregate(const LogicalType &type) { auto fun = GetApproxQuantileListAggregateFunction(type); fun.bind = BindApproxQuantile; + fun.serialize = ApproximateQuantileBindData::Serialize; + fun.deserialize = ApproximateQuantileBindData::Deserialize; // temporarily push an argument so we can bind the actual quantile auto list_of_float = LogicalType::LIST(LogicalType::FLOAT); fun.arguments.push_back(list_of_float); @@ -88069,7 +96491,7 @@ struct ModeFunction { } template - static void Operation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t idx) { if (!state->frequency_map) { state->frequency_map = new unordered_map(); } @@ -88078,7 +96500,7 @@ struct ModeFunction { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (!source.frequency_map) { return; } @@ -88093,7 +96515,7 @@ struct ModeFunction { } template - static void Finalize(Vector &result, FunctionData *, STATE *state, INPUT_TYPE *target, ValidityMask &mask, + static void Finalize(Vector &result, AggregateInputData &, STATE *state, INPUT_TYPE *target, ValidityMask &mask, idx_t idx) { if (!state->frequency_map) { mask.SetInvalid(idx); @@ -88107,7 +96529,7 @@ struct ModeFunction { } } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, + static void ConstantOperation(STATE *state, AggregateInputData &, INPUT_TYPE *input, ValidityMask &mask, idx_t count) { if (!state->frequency_map) { state->frequency_map = new unordered_map(); @@ -88118,7 +96540,7 @@ struct ModeFunction { template static void Window(const INPUT_TYPE *data, const ValidityMask &fmask, const ValidityMask &dmask, - FunctionData *bind_data_p, STATE *state, const FrameBounds &frame, const FrameBounds &prev, + AggregateInputData &, STATE *state, const FrameBounds &frame, const FrameBounds &prev, Vector &result, idx_t rid, idx_t bias) { auto rdata = FlatVector::GetData(result); auto &rmask = FlatVector::Validity(result); @@ -88356,6 +96778,7 @@ inline interval_t TryAbsOperator::Operation(interval_t input) { + #include #include #include @@ -88727,20 +97150,20 @@ struct QuantileOperation { } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { for (idx_t i = 0; i < count; i++) { - Operation(state, bind_data, input, mask, 0); + Operation(state, aggr_input_data, input, mask, 0); } } template - static void Operation(STATE *state, FunctionData *bind_data_p, INPUT_TYPE *data, ValidityMask &mask, idx_t idx) { + static void Operation(STATE *state, AggregateInputData &, INPUT_TYPE *data, ValidityMask &mask, idx_t idx) { state->v.emplace_back(data[idx]); } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (source.v.empty()) { return; } @@ -88758,12 +97181,13 @@ struct QuantileOperation { }; template -static void ExecuteListFinalize(Vector &states, FunctionData *bind_data_p, Vector &result, idx_t count, // NOLINT +static void ExecuteListFinalize(Vector &states, AggregateInputData &aggr_input_data, Vector &result, + idx_t count, // NOLINT idx_t offset) { D_ASSERT(result.GetType().id() == LogicalTypeId::LIST); - D_ASSERT(bind_data_p); - auto bind_data = (QuantileBindData *)bind_data_p; + D_ASSERT(aggr_input_data.bind_data); + auto bind_data = (QuantileBindData *)aggr_input_data.bind_data; if (states.GetVectorType() == VectorType::CONSTANT_VECTOR) { result.SetVectorType(VectorType::CONSTANT_VECTOR); @@ -88772,7 +97196,7 @@ static void ExecuteListFinalize(Vector &states, FunctionData *bind_data_p, Vecto auto sdata = ConstantVector::GetData(states); auto rdata = ConstantVector::GetData(result); auto &mask = ConstantVector::Validity(result); - OP::template Finalize(result, bind_data, sdata[0], rdata, mask, 0); + OP::template Finalize(result, aggr_input_data, sdata[0], rdata, mask, 0); } else { D_ASSERT(states.GetVectorType() == VectorType::FLAT_VECTOR); result.SetVectorType(VectorType::FLAT_VECTOR); @@ -88782,7 +97206,7 @@ static void ExecuteListFinalize(Vector &states, FunctionData *bind_data_p, Vecto auto rdata = FlatVector::GetData(result); auto &mask = FlatVector::Validity(result); for (idx_t i = 0; i < count; i++) { - OP::template Finalize(result, bind_data, sdata[i], rdata, mask, i + offset); + OP::template Finalize(result, aggr_input_data, sdata[i], rdata, mask, i + offset); } } @@ -88803,14 +97227,14 @@ template struct QuantileScalarOperation : public QuantileOperation { template - static void Finalize(Vector &result, FunctionData *bind_data_p, STATE *state, RESULT_TYPE *target, + static void Finalize(Vector &result, AggregateInputData &aggr_input_data, STATE *state, RESULT_TYPE *target, ValidityMask &mask, idx_t idx) { if (state->v.empty()) { mask.SetInvalid(idx); return; } - D_ASSERT(bind_data_p); - auto bind_data = (QuantileBindData *)bind_data_p; + D_ASSERT(aggr_input_data.bind_data); + auto bind_data = (QuantileBindData *)aggr_input_data.bind_data; D_ASSERT(bind_data->quantiles.size() == 1); Interpolator interp(bind_data->quantiles[0], state->v.size()); target[idx] = interp.template Operation(state->v.data(), result); @@ -88818,8 +97242,8 @@ struct QuantileScalarOperation : public QuantileOperation { template static void Window(const INPUT_TYPE *data, const ValidityMask &fmask, const ValidityMask &dmask, - FunctionData *bind_data_p, STATE *state, const FrameBounds &frame, const FrameBounds &prev, - Vector &result, idx_t ridx, idx_t bias) { + AggregateInputData &aggr_input_data, STATE *state, const FrameBounds &frame, + const FrameBounds &prev, Vector &result, idx_t ridx, idx_t bias) { auto rdata = FlatVector::GetData(result); auto &rmask = FlatVector::Validity(result); @@ -88832,8 +97256,8 @@ struct QuantileScalarOperation : public QuantileOperation { auto index = state->w.data(); D_ASSERT(index); - D_ASSERT(bind_data_p); - auto bind_data = (QuantileBindData *)bind_data_p; + D_ASSERT(aggr_input_data.bind_data); + auto bind_data = (QuantileBindData *)aggr_input_data.bind_data; // Find the two positions needed const auto q = bind_data->quantiles[0]; @@ -88892,7 +97316,6 @@ AggregateFunction GetDiscreteQuantileAggregateFunction(const LogicalType &type) return GetTypedDiscreteQuantileAggregateFunction(type); case LogicalTypeId::HUGEINT: return GetTypedDiscreteQuantileAggregateFunction(type); - case LogicalTypeId::FLOAT: return GetTypedDiscreteQuantileAggregateFunction(type); case LogicalTypeId::DOUBLE: @@ -88910,8 +97333,6 @@ AggregateFunction GetDiscreteQuantileAggregateFunction(const LogicalType &type) default: throw NotImplementedException("Unimplemented discrete quantile aggregate"); } - break; - case LogicalTypeId::DATE: return GetTypedDiscreteQuantileAggregateFunction(type); case LogicalTypeId::TIMESTAMP: @@ -88935,15 +97356,15 @@ template struct QuantileListOperation : public QuantileOperation { template - static void Finalize(Vector &result_list, FunctionData *bind_data_p, STATE *state, RESULT_TYPE *target, + static void Finalize(Vector &result_list, AggregateInputData &aggr_input_data, STATE *state, RESULT_TYPE *target, ValidityMask &mask, idx_t idx) { if (state->v.empty()) { mask.SetInvalid(idx); return; } - D_ASSERT(bind_data_p); - auto bind_data = (QuantileBindData *)bind_data_p; + D_ASSERT(aggr_input_data.bind_data); + auto bind_data = (QuantileBindData *)aggr_input_data.bind_data; auto &result = ListVector::GetEntry(result_list); auto ridx = ListVector::GetListSize(result_list); @@ -88970,10 +97391,10 @@ struct QuantileListOperation : public QuantileOperation { template static void Window(const INPUT_TYPE *data, const ValidityMask &fmask, const ValidityMask &dmask, - FunctionData *bind_data_p, STATE *state, const FrameBounds &frame, const FrameBounds &prev, - Vector &list, idx_t lidx, idx_t bias) { - D_ASSERT(bind_data_p); - auto bind_data = (QuantileBindData *)bind_data_p; + AggregateInputData &aggr_input_data, STATE *state, const FrameBounds &frame, + const FrameBounds &prev, Vector &list, idx_t lidx, idx_t bias) { + D_ASSERT(aggr_input_data.bind_data); + auto bind_data = (QuantileBindData *)aggr_input_data.bind_data; QuantileIncluded included(fmask, dmask, bias); @@ -89084,7 +97505,6 @@ AggregateFunction GetDiscreteQuantileListAggregateFunction(const LogicalType &ty return GetTypedDiscreteQuantileListAggregateFunction(type); case LogicalTypeId::HUGEINT: return GetTypedDiscreteQuantileListAggregateFunction(type); - case LogicalTypeId::FLOAT: return GetTypedDiscreteQuantileListAggregateFunction(type); case LogicalTypeId::DOUBLE: @@ -89102,8 +97522,6 @@ AggregateFunction GetDiscreteQuantileListAggregateFunction(const LogicalType &ty default: throw NotImplementedException("Unimplemented discrete quantile list aggregate"); } - break; - case LogicalTypeId::DATE: return GetTypedDiscreteQuantileListAggregateFunction(type); case LogicalTypeId::TIMESTAMP: @@ -89114,10 +97532,8 @@ AggregateFunction GetDiscreteQuantileListAggregateFunction(const LogicalType &ty return GetTypedDiscreteQuantileListAggregateFunction(type); case LogicalTypeId::INTERVAL: return GetTypedDiscreteQuantileListAggregateFunction(type); - case LogicalTypeId::VARCHAR: return GetTypedDiscreteQuantileListAggregateFunction(type); - default: throw NotImplementedException("Unimplemented discrete quantile list aggregate"); } @@ -89145,7 +97561,6 @@ AggregateFunction GetContinuousQuantileAggregateFunction(const LogicalType &type return GetTypedContinuousQuantileAggregateFunction(type, LogicalType::DOUBLE); case LogicalTypeId::HUGEINT: return GetTypedContinuousQuantileAggregateFunction(type, LogicalType::DOUBLE); - case LogicalTypeId::FLOAT: return GetTypedContinuousQuantileAggregateFunction(type, type); case LogicalTypeId::DOUBLE: @@ -89163,8 +97578,6 @@ AggregateFunction GetContinuousQuantileAggregateFunction(const LogicalType &type default: throw NotImplementedException("Unimplemented continuous quantile DECIMAL aggregate"); } - break; - case LogicalTypeId::DATE: return GetTypedContinuousQuantileAggregateFunction(type, LogicalType::TIMESTAMP); case LogicalTypeId::TIMESTAMP: @@ -89314,8 +97727,8 @@ template struct MedianAbsoluteDeviationOperation : public QuantileOperation { template - static void Finalize(Vector &result, FunctionData *bind_data_p, STATE *state, RESULT_TYPE *target, - ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, RESULT_TYPE *target, ValidityMask &mask, + idx_t idx) { if (state->v.empty()) { mask.SetInvalid(idx); return; @@ -89330,7 +97743,7 @@ struct MedianAbsoluteDeviationOperation : public QuantileOperation { template static void Window(const INPUT_TYPE *data, const ValidityMask &fmask, const ValidityMask &dmask, - FunctionData *bind_data_p, STATE *state, const FrameBounds &frame, const FrameBounds &prev, + AggregateInputData &, STATE *state, const FrameBounds &frame, const FrameBounds &prev, Vector &result, idx_t ridx, idx_t bias) { auto rdata = FlatVector::GetData(result); auto &rmask = FlatVector::Validity(result); @@ -89452,6 +97865,20 @@ AggregateFunction GetMedianAbsoluteDeviationAggregateFunction(const LogicalType } } +static void QuantileSerialize(FieldWriter &writer, const FunctionData *bind_data_p, const AggregateFunction &function) { + D_ASSERT(bind_data_p); + throw NotImplementedException("FIXME: serializing quantiles is not supported right now"); + // + // auto bind_data = (QuantileBindData *)bind_data_p; + // writer.WriteList(bind_data->quantiles); +} + +unique_ptr QuantileDeserialize(ClientContext &context, FieldReader &reader, + AggregateFunction &bound_function) { + auto quantiles = reader.ReadRequiredList(); + return make_unique(move(quantiles)); +} + unique_ptr BindMedian(ClientContext &context, AggregateFunction &function, vector> &arguments) { return make_unique(0.5); @@ -89463,6 +97890,8 @@ unique_ptr BindMedianDecimal(ClientContext &context, AggregateFunc function = GetDiscreteQuantileAggregateFunction(arguments[0]->return_type); function.name = "median"; + function.serialize = QuantileSerialize; + function.deserialize = QuantileDeserialize; return bind_data; } @@ -89474,9 +97903,11 @@ unique_ptr BindMedianAbsoluteDeviationDecimal(ClientContext &conte } static double CheckQuantile(const Value &quantile_val) { + if (quantile_val.IsNull()) { + throw BinderException("QUANTILE parameter cannot be NULL"); + } auto quantile = quantile_val.GetValue(); - - if (quantile_val.IsNull() || quantile < 0 || quantile > 1) { + if (quantile < 0 || quantile > 1) { throw BinderException("QUANTILE can only take parameters in the range [0, 1]"); } @@ -89485,6 +97916,9 @@ static double CheckQuantile(const Value &quantile_val) { unique_ptr BindQuantile(ClientContext &context, AggregateFunction &function, vector> &arguments) { + if (arguments[1]->HasParameter()) { + throw ParameterNotResolvedException(); + } if (!arguments[1]->IsFoldable()) { throw BinderException("QUANTILE can only take constant parameters"); } @@ -89498,15 +97932,22 @@ unique_ptr BindQuantile(ClientContext &context, AggregateFunction } } - arguments.pop_back(); + Function::EraseArgument(function, arguments, arguments.size() - 1); return make_unique(quantiles); } +static void QuantileDecimalSerialize(FieldWriter &writer, const FunctionData *bind_data_p, + const AggregateFunction &function) { + throw NotImplementedException("FIXME: serializing quantiles with decimals is not supported right now"); +} + unique_ptr BindDiscreteQuantileDecimal(ClientContext &context, AggregateFunction &function, vector> &arguments) { auto bind_data = BindQuantile(context, function, arguments); function = GetDiscreteQuantileAggregateFunction(arguments[0]->return_type); function.name = "quantile_disc"; + function.serialize = QuantileDecimalSerialize; + function.deserialize = QuantileDeserialize; return bind_data; } @@ -89515,6 +97956,8 @@ unique_ptr BindDiscreteQuantileDecimalList(ClientContext &context, auto bind_data = BindQuantile(context, function, arguments); function = GetDiscreteQuantileListAggregateFunction(arguments[0]->return_type); function.name = "quantile_disc"; + function.serialize = QuantileDecimalSerialize; + function.deserialize = QuantileDeserialize; return bind_data; } @@ -89523,6 +97966,8 @@ unique_ptr BindContinuousQuantileDecimal(ClientContext &context, A auto bind_data = BindQuantile(context, function, arguments); function = GetContinuousQuantileAggregateFunction(arguments[0]->return_type); function.name = "quantile_cont"; + function.serialize = QuantileDecimalSerialize; + function.deserialize = QuantileDeserialize; return bind_data; } @@ -89531,6 +97976,8 @@ unique_ptr BindContinuousQuantileDecimalList(ClientContext &contex auto bind_data = BindQuantile(context, function, arguments); function = GetContinuousQuantileListAggregateFunction(arguments[0]->return_type); function.name = "quantile_cont"; + function.serialize = QuantileDecimalSerialize; + function.deserialize = QuantileDeserialize; return bind_data; } @@ -89548,12 +97995,16 @@ AggregateFunction GetMedianAggregate(const LogicalType &type) { auto fun = CanInterpolate(type) ? GetContinuousQuantileAggregateFunction(type) : GetDiscreteQuantileAggregateFunction(type); fun.bind = BindMedian; + fun.serialize = QuantileSerialize; + fun.deserialize = QuantileDeserialize; return fun; } AggregateFunction GetDiscreteQuantileAggregate(const LogicalType &type) { auto fun = GetDiscreteQuantileAggregateFunction(type); fun.bind = BindQuantile; + fun.serialize = QuantileSerialize; + fun.deserialize = QuantileDeserialize; // temporarily push an argument so we can bind the actual quantile fun.arguments.emplace_back(LogicalType::DOUBLE); return fun; @@ -89562,6 +98013,8 @@ AggregateFunction GetDiscreteQuantileAggregate(const LogicalType &type) { AggregateFunction GetDiscreteQuantileListAggregate(const LogicalType &type) { auto fun = GetDiscreteQuantileListAggregateFunction(type); fun.bind = BindQuantile; + fun.serialize = QuantileSerialize; + fun.deserialize = QuantileDeserialize; // temporarily push an argument so we can bind the actual quantile auto list_of_double = LogicalType::LIST(LogicalType::DOUBLE); fun.arguments.push_back(list_of_double); @@ -89571,6 +98024,8 @@ AggregateFunction GetDiscreteQuantileListAggregate(const LogicalType &type) { AggregateFunction GetContinuousQuantileAggregate(const LogicalType &type) { auto fun = GetContinuousQuantileAggregateFunction(type); fun.bind = BindQuantile; + fun.serialize = QuantileSerialize; + fun.deserialize = QuantileDeserialize; // temporarily push an argument so we can bind the actual quantile fun.arguments.emplace_back(LogicalType::DOUBLE); return fun; @@ -89579,12 +98034,23 @@ AggregateFunction GetContinuousQuantileAggregate(const LogicalType &type) { AggregateFunction GetContinuousQuantileListAggregate(const LogicalType &type) { auto fun = GetContinuousQuantileListAggregateFunction(type); fun.bind = BindQuantile; + fun.serialize = QuantileSerialize; + fun.deserialize = QuantileDeserialize; // temporarily push an argument so we can bind the actual quantile auto list_of_double = LogicalType::LIST(LogicalType::DOUBLE); fun.arguments.push_back(list_of_double); return fun; } +AggregateFunction GetQuantileDecimalAggregate(const vector &arguments, const LogicalType &return_type, + bind_aggregate_function_t bind) { + AggregateFunction fun(arguments, return_type, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, bind); + fun.bind = bind; + fun.serialize = QuantileSerialize; + fun.deserialize = QuantileDeserialize; + return fun; +} + void QuantileFun::RegisterFunction(BuiltinFunctions &set) { const vector QUANTILES = {LogicalType::TINYINT, LogicalType::SMALLINT, LogicalType::INTEGER, LogicalType::BIGINT, LogicalType::HUGEINT, LogicalType::FLOAT, @@ -89593,24 +98059,22 @@ void QuantileFun::RegisterFunction(BuiltinFunctions &set) { LogicalType::INTERVAL, LogicalType::VARCHAR}; AggregateFunctionSet median("median"); - median.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL}, LogicalTypeId::DECIMAL, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, BindMedianDecimal)); + median.AddFunction( + GetQuantileDecimalAggregate({LogicalTypeId::DECIMAL}, LogicalTypeId::DECIMAL, BindMedianDecimal)); AggregateFunctionSet quantile_disc("quantile_disc"); - quantile_disc.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL, LogicalType::DOUBLE}, LogicalTypeId::DECIMAL, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - BindDiscreteQuantileDecimal)); - quantile_disc.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL, LogicalType::LIST(LogicalType::DOUBLE)}, - LogicalType::LIST(LogicalTypeId::DECIMAL), nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, BindDiscreteQuantileDecimalList)); + quantile_disc.AddFunction(GetQuantileDecimalAggregate({LogicalTypeId::DECIMAL, LogicalType::DOUBLE}, + LogicalTypeId::DECIMAL, BindDiscreteQuantileDecimal)); + quantile_disc.AddFunction( + GetQuantileDecimalAggregate({LogicalTypeId::DECIMAL, LogicalType::LIST(LogicalType::DOUBLE)}, + LogicalType::LIST(LogicalTypeId::DECIMAL), BindDiscreteQuantileDecimalList)); AggregateFunctionSet quantile_cont("quantile_cont"); - quantile_cont.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL, LogicalType::DOUBLE}, LogicalTypeId::DECIMAL, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, - BindContinuousQuantileDecimal)); - quantile_cont.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL, LogicalType::LIST(LogicalType::DOUBLE)}, - LogicalType::LIST(LogicalTypeId::DECIMAL), nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, BindContinuousQuantileDecimalList)); + quantile_cont.AddFunction(GetQuantileDecimalAggregate({LogicalTypeId::DECIMAL, LogicalType::DOUBLE}, + LogicalTypeId::DECIMAL, BindContinuousQuantileDecimal)); + quantile_cont.AddFunction( + GetQuantileDecimalAggregate({LogicalTypeId::DECIMAL, LogicalType::LIST(LogicalType::DOUBLE)}, + LogicalType::LIST(LogicalTypeId::DECIMAL), BindContinuousQuantileDecimalList)); for (const auto &type : QUANTILES) { median.AddFunction(GetMedianAggregate(type)); @@ -89649,6 +98113,7 @@ void QuantileFun::RegisterFunction(BuiltinFunctions &set) { + #include #include @@ -89695,8 +98160,8 @@ struct ReservoirQuantileBindData : public FunctionData { : quantiles(1, quantile_p), sample_size(sample_size_p) { } - ReservoirQuantileBindData(const vector &quantiles_p, int32_t sample_size_p) - : quantiles(quantiles_p), sample_size(sample_size_p) { + ReservoirQuantileBindData(vector quantiles_p, int32_t sample_size_p) + : quantiles(move(quantiles_p)), sample_size(sample_size_p) { } unique_ptr Copy() const override { @@ -89708,6 +98173,20 @@ struct ReservoirQuantileBindData : public FunctionData { return quantiles == other.quantiles && sample_size == other.sample_size; } + static void Serialize(FieldWriter &writer, const FunctionData *bind_data_p, const AggregateFunction &function) { + D_ASSERT(bind_data_p); + auto bind_data = (ReservoirQuantileBindData *)bind_data_p; + writer.WriteList(bind_data->quantiles); + writer.WriteField(bind_data->sample_size); + } + + static unique_ptr Deserialize(ClientContext &context, FieldReader &reader, + AggregateFunction &bound_function) { + auto quantiles = reader.ReadRequiredList(); + auto sample_size = reader.ReadRequired(); + return make_unique(move(quantiles), sample_size); + } + vector quantiles; int32_t sample_size; }; @@ -89722,16 +98201,17 @@ struct ReservoirQuantileOperation { } template - static void ConstantOperation(STATE *state, FunctionData *bind_data, INPUT_TYPE *input, ValidityMask &mask, - idx_t count) { + static void ConstantOperation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *input, + ValidityMask &mask, idx_t count) { for (idx_t i = 0; i < count; i++) { - Operation(state, bind_data, input, mask, 0); + Operation(state, aggr_input_data, input, mask, 0); } } template - static void Operation(STATE *state, FunctionData *bind_data_p, INPUT_TYPE *data, ValidityMask &mask, idx_t idx) { - auto bind_data = (ReservoirQuantileBindData *)bind_data_p; + static void Operation(STATE *state, AggregateInputData &aggr_input_data, INPUT_TYPE *data, ValidityMask &mask, + idx_t idx) { + auto bind_data = (ReservoirQuantileBindData *)aggr_input_data.bind_data; D_ASSERT(bind_data); if (state->pos == 0) { state->Resize(bind_data->sample_size); @@ -89744,7 +98224,7 @@ struct ReservoirQuantileOperation { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (source.pos == 0) { return; } @@ -89778,15 +98258,15 @@ struct ReservoirQuantileOperation { struct ReservoirQuantileScalarOperation : public ReservoirQuantileOperation { template - static void Finalize(Vector &result, FunctionData *bind_data_p, STATE *state, TARGET_TYPE *target, + static void Finalize(Vector &result, AggregateInputData &aggr_input_data, STATE *state, TARGET_TYPE *target, ValidityMask &mask, idx_t idx) { if (state->pos == 0) { mask.SetInvalid(idx); return; } D_ASSERT(state->v); - D_ASSERT(bind_data_p); - auto bind_data = (ReservoirQuantileBindData *)bind_data_p; + D_ASSERT(aggr_input_data.bind_data); + auto bind_data = (ReservoirQuantileBindData *)aggr_input_data.bind_data; auto v_t = state->v; D_ASSERT(bind_data->quantiles.size() == 1); auto offset = (idx_t)((double)(state->pos - 1) * bind_data->quantiles[0]); @@ -89838,15 +98318,15 @@ template struct ReservoirQuantileListOperation : public ReservoirQuantileOperation { template - static void Finalize(Vector &result_list, FunctionData *bind_data_p, STATE *state, RESULT_TYPE *target, + static void Finalize(Vector &result_list, AggregateInputData &aggr_input_data, STATE *state, RESULT_TYPE *target, ValidityMask &mask, idx_t idx) { if (state->pos == 0) { mask.SetInvalid(idx); return; } - D_ASSERT(bind_data_p); - auto bind_data = (ReservoirQuantileBindData *)bind_data_p; + D_ASSERT(aggr_input_data.bind_data); + auto bind_data = (ReservoirQuantileBindData *)aggr_input_data.bind_data; auto &result = ListVector::GetEntry(result_list); auto ridx = ListVector::GetListSize(result_list); @@ -89870,12 +98350,12 @@ struct ReservoirQuantileListOperation : public ReservoirQuantileOperation { } template - static void FinalizeList(Vector &states, FunctionData *bind_data_p, Vector &result, idx_t count, // NOLINT + static void FinalizeList(Vector &states, AggregateInputData &aggr_input_data, Vector &result, idx_t count, // NOLINT idx_t offset) { D_ASSERT(result.GetType().id() == LogicalTypeId::LIST); - D_ASSERT(bind_data_p); - auto bind_data = (ReservoirQuantileBindData *)bind_data_p; + D_ASSERT(aggr_input_data.bind_data); + auto bind_data = (ReservoirQuantileBindData *)aggr_input_data.bind_data; if (states.GetVectorType() == VectorType::CONSTANT_VECTOR) { result.SetVectorType(VectorType::CONSTANT_VECTOR); @@ -89884,7 +98364,7 @@ struct ReservoirQuantileListOperation : public ReservoirQuantileOperation { auto sdata = ConstantVector::GetData(states); auto rdata = ConstantVector::GetData(result); auto &mask = ConstantVector::Validity(result); - Finalize(result, bind_data, sdata[0], rdata, mask, 0); + Finalize(result, aggr_input_data, sdata[0], rdata, mask, 0); } else { D_ASSERT(states.GetVectorType() == VectorType::FLAT_VECTOR); result.SetVectorType(VectorType::FLAT_VECTOR); @@ -89894,7 +98374,7 @@ struct ReservoirQuantileListOperation : public ReservoirQuantileOperation { auto rdata = FlatVector::GetData(result); auto &mask = FlatVector::Validity(result); for (idx_t i = 0; i < count; i++) { - Finalize(result, bind_data, sdata[i], rdata, mask, i + offset); + Finalize(result, aggr_input_data, sdata[i], rdata, mask, i + offset); } } @@ -89932,7 +98412,6 @@ AggregateFunction GetReservoirQuantileListAggregateFunction(const LogicalType &t return GetTypedReservoirQuantileListAggregateFunction(type); case LogicalTypeId::HUGEINT: return GetTypedReservoirQuantileListAggregateFunction(type); - case LogicalTypeId::FLOAT: return GetTypedReservoirQuantileListAggregateFunction(type); case LogicalTypeId::DOUBLE: @@ -89950,8 +98429,6 @@ AggregateFunction GetReservoirQuantileListAggregateFunction(const LogicalType &t default: throw NotImplementedException("Unimplemented reservoir quantile list aggregate"); } - break; - default: // TODO: Add quantitative temporal types throw NotImplementedException("Unimplemented reservoir quantile list aggregate"); @@ -89959,17 +98436,21 @@ AggregateFunction GetReservoirQuantileListAggregateFunction(const LogicalType &t } static double CheckReservoirQuantile(const Value &quantile_val) { + if (quantile_val.IsNull()) { + throw BinderException("RESERVOIR_QUANTILE QUANTILE parameter cannot be NULL"); + } auto quantile = quantile_val.GetValue(); - - if (quantile_val.IsNull() || quantile < 0 || quantile > 1) { + if (quantile < 0 || quantile > 1) { throw BinderException("RESERVOIR_QUANTILE can only take parameters in the range [0, 1]"); } - return quantile; } unique_ptr BindReservoirQuantile(ClientContext &context, AggregateFunction &function, vector> &arguments) { + if (arguments[1]->HasParameter()) { + throw ParameterNotResolvedException(); + } if (!arguments[1]->IsFoldable()) { throw BinderException("RESERVOIR_QUANTILE can only take constant quantile parameters"); } @@ -89991,6 +98472,9 @@ unique_ptr BindReservoirQuantile(ClientContext &context, Aggregate throw BinderException("RESERVOIR_QUANTILE can only take constant sample size parameters"); } Value sample_size_val = ExpressionExecutor::EvaluateScalar(*arguments[2]); + if (sample_size_val.IsNull()) { + throw BinderException("Size of the RESERVOIR_QUANTILE sample cannot be NULL"); + } auto sample_size = sample_size_val.GetValue(); if (sample_size_val.IsNull() || sample_size <= 0) { @@ -89998,22 +98482,26 @@ unique_ptr BindReservoirQuantile(ClientContext &context, Aggregate } // remove the quantile argument so we can use the unary aggregate - arguments.pop_back(); - arguments.pop_back(); + Function::EraseArgument(function, arguments, arguments.size() - 1); + Function::EraseArgument(function, arguments, arguments.size() - 1); return make_unique(quantiles, sample_size); } unique_ptr BindReservoirQuantileDecimal(ClientContext &context, AggregateFunction &function, vector> &arguments) { - auto bind_data = BindReservoirQuantile(context, function, arguments); function = GetReservoirQuantileAggregateFunction(arguments[0]->return_type.InternalType()); + auto bind_data = BindReservoirQuantile(context, function, arguments); function.name = "reservoir_quantile"; + function.serialize = ReservoirQuantileBindData::Serialize; + function.deserialize = ReservoirQuantileBindData::Deserialize; return bind_data; } AggregateFunction GetReservoirQuantileAggregate(PhysicalType type) { auto fun = GetReservoirQuantileAggregateFunction(type); fun.bind = BindReservoirQuantile; + fun.serialize = ReservoirQuantileBindData::Serialize; + fun.deserialize = ReservoirQuantileBindData::Deserialize; // temporarily push an argument so we can bind the actual quantile fun.arguments.emplace_back(LogicalType::DOUBLE); return fun; @@ -90021,8 +98509,10 @@ AggregateFunction GetReservoirQuantileAggregate(PhysicalType type) { unique_ptr BindReservoirQuantileDecimalList(ClientContext &context, AggregateFunction &function, vector> &arguments) { - auto bind_data = BindReservoirQuantile(context, function, arguments); function = GetReservoirQuantileListAggregateFunction(arguments[0]->return_type); + auto bind_data = BindReservoirQuantile(context, function, arguments); + function.serialize = ReservoirQuantileBindData::Serialize; + function.deserialize = ReservoirQuantileBindData::Deserialize; function.name = "reservoir_quantile"; return bind_data; } @@ -90030,6 +98520,8 @@ unique_ptr BindReservoirQuantileDecimalList(ClientContext &context AggregateFunction GetReservoirQuantileListAggregate(const LogicalType &type) { auto fun = GetReservoirQuantileListAggregateFunction(type); fun.bind = BindReservoirQuantile; + fun.serialize = ReservoirQuantileBindData::Serialize; + fun.deserialize = ReservoirQuantileBindData::Deserialize; // temporarily push an argument so we can bind the actual quantile auto list_of_double = LogicalType::LIST(LogicalType::DOUBLE); fun.arguments.push_back(list_of_double); @@ -90039,7 +98531,6 @@ AggregateFunction GetReservoirQuantileListAggregate(const LogicalType &type) { static void DefineReservoirQuantile(AggregateFunctionSet &set, const LogicalType &type) { // Four versions: type, scalar/list[, count] auto fun = GetReservoirQuantileAggregate(type.InternalType()); - fun.bind = BindReservoirQuantile; set.AddFunction(fun); fun.arguments.emplace_back(LogicalType::INTEGER); @@ -90053,24 +98544,27 @@ static void DefineReservoirQuantile(AggregateFunctionSet &set, const LogicalType set.AddFunction(fun); } +static void GetReservoirQuantileDecimalFunction(AggregateFunctionSet &set, const vector &arguments, + const LogicalType &return_value) { + AggregateFunction fun(arguments, return_value, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + BindReservoirQuantileDecimal); + fun.serialize = ReservoirQuantileBindData::Serialize; + fun.deserialize = ReservoirQuantileBindData::Deserialize; + set.AddFunction(fun); + + fun.arguments.emplace_back(LogicalType::INTEGER); + set.AddFunction(fun); +} + void ReservoirQuantileFun::RegisterFunction(BuiltinFunctions &set) { AggregateFunctionSet reservoir_quantile("reservoir_quantile"); // DECIMAL - reservoir_quantile.AddFunction( - AggregateFunction({LogicalTypeId::DECIMAL, LogicalType::DOUBLE, LogicalType::INTEGER}, LogicalTypeId::DECIMAL, - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, BindReservoirQuantileDecimal)); - reservoir_quantile.AddFunction(AggregateFunction({LogicalTypeId::DECIMAL, LogicalType::DOUBLE}, - LogicalTypeId::DECIMAL, nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, BindReservoirQuantileDecimal)); - reservoir_quantile.AddFunction( - AggregateFunction({LogicalTypeId::DECIMAL, LogicalType::LIST(LogicalType::DOUBLE), LogicalType::INTEGER}, - LogicalType::LIST(LogicalTypeId::DECIMAL), nullptr, nullptr, nullptr, nullptr, nullptr, - nullptr, BindReservoirQuantileDecimalList)); - - reservoir_quantile.AddFunction(AggregateFunction( - {LogicalTypeId::DECIMAL, LogicalType::LIST(LogicalType::DOUBLE)}, LogicalType::LIST(LogicalTypeId::DECIMAL), - nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, BindReservoirQuantileDecimalList)); + GetReservoirQuantileDecimalFunction(reservoir_quantile, {LogicalTypeId::DECIMAL, LogicalType::DOUBLE}, + LogicalTypeId::DECIMAL); + GetReservoirQuantileDecimalFunction(reservoir_quantile, + {LogicalTypeId::DECIMAL, LogicalType::LIST(LogicalType::DOUBLE)}, + LogicalType::LIST(LogicalTypeId::DECIMAL)); DefineReservoirQuantile(reservoir_quantile, LogicalTypeId::TINYINT); DefineReservoirQuantile(reservoir_quantile, LogicalTypeId::SMALLINT); @@ -90112,13 +98606,15 @@ void BuiltinFunctions::RegisterHolisticAggregates() { namespace duckdb { -struct ListFun { - static void RegisterFunction(BuiltinFunctions &set); -}; struct HistogramFun { static void RegisterFunction(BuiltinFunctions &set); static AggregateFunction GetHistogramUnorderedMap(LogicalType &type); }; + +struct ListFun { + static void RegisterFunction(BuiltinFunctions &set); +}; + } // namespace duckdb @@ -90130,7 +98626,7 @@ namespace duckdb { struct HistogramFunctor { template > - static void HistogramUpdate(VectorData &sdata, VectorData &input_data, idx_t count) { + static void HistogramUpdate(UnifiedVectorFormat &sdata, UnifiedVectorFormat &input_data, idx_t count) { auto states = (HistogramAggState **)sdata.data; for (idx_t i = 0; i < count; i++) { @@ -90153,7 +98649,7 @@ struct HistogramFunctor { struct HistogramStringFunctor { template > - static void HistogramUpdate(VectorData &sdata, VectorData &input_data, idx_t count) { + static void HistogramUpdate(UnifiedVectorFormat &sdata, UnifiedVectorFormat &input_data, idx_t count) { auto states = (HistogramAggState **)sdata.data; for (idx_t i = 0; i < count; i++) { @@ -90194,25 +98690,25 @@ struct HistogramFunction { }; template -static void HistogramUpdateFunction(Vector inputs[], FunctionData *, idx_t input_count, Vector &state_vector, +static void HistogramUpdateFunction(Vector inputs[], AggregateInputData &, idx_t input_count, Vector &state_vector, idx_t count) { D_ASSERT(input_count == 1); auto &input = inputs[0]; - VectorData sdata; - state_vector.Orrify(count, sdata); - VectorData input_data; - input.Orrify(count, input_data); + UnifiedVectorFormat sdata; + state_vector.ToUnifiedFormat(count, sdata); + UnifiedVectorFormat input_data; + input.ToUnifiedFormat(count, input_data); OP::template HistogramUpdate(sdata, input_data, count); } template -static void HistogramCombineFunction(Vector &state, Vector &combined, FunctionData *bind_data, idx_t count) { +static void HistogramCombineFunction(Vector &state, Vector &combined, AggregateInputData &, idx_t count) { - VectorData sdata; - state.Orrify(count, sdata); + UnifiedVectorFormat sdata; + state.ToUnifiedFormat(count, sdata); auto states_ptr = (HistogramAggState **)sdata.data; auto combined_ptr = FlatVector::GetData *>(combined); @@ -90234,10 +98730,11 @@ static void HistogramCombineFunction(Vector &state, Vector &combined, FunctionDa } template -static void HistogramFinalizeFunction(Vector &state_vector, FunctionData *, Vector &result, idx_t count, idx_t offset) { +static void HistogramFinalizeFunction(Vector &state_vector, AggregateInputData &, Vector &result, idx_t count, + idx_t offset) { - VectorData sdata; - state_vector.Orrify(count, sdata); + UnifiedVectorFormat sdata; + state_vector.ToUnifiedFormat(count, sdata); auto states = (HistogramAggState **)sdata.data; auto &mask = FlatVector::Validity(result); @@ -90285,8 +98782,8 @@ unique_ptr HistogramBindFunction(ClientContext &context, Aggregate D_ASSERT(arguments.size() == 1); child_list_t struct_children; - struct_children.push_back({"bucket", LogicalType::LIST(arguments[0]->return_type)}); - struct_children.push_back({"count", LogicalType::LIST(LogicalType::UBIGINT)}); + struct_children.push_back({"key", LogicalType::LIST(arguments[0]->return_type)}); + struct_children.push_back({"value", LogicalType::LIST(LogicalType::UBIGINT)}); auto struct_type = LogicalType::MAP(move(struct_children)); function.return_type = struct_type; @@ -90401,20 +98898,692 @@ AggregateFunction HistogramFun::GetHistogramUnorderedMap(LogicalType &type) { namespace duckdb { +struct ListSegment { + uint16_t count; + uint16_t capacity; + ListSegment *next; +}; +struct LinkedList { + LinkedList() {}; + LinkedList(idx_t total_capacity_p, ListSegment *first_segment_p, ListSegment *last_segment_p) + : total_capacity(total_capacity_p), first_segment(first_segment_p), last_segment(last_segment_p) { + } + + idx_t total_capacity = 0; + ListSegment *first_segment = nullptr; + ListSegment *last_segment = nullptr; +}; + +// forward declarations +struct WriteDataToSegment; +struct ReadDataFromSegment; +typedef ListSegment *(*create_segment_t)(WriteDataToSegment &write_data_to_segment, Allocator &allocator, + vector &owning_vector, uint16_t &capacity); +typedef void (*write_data_to_segment_t)(WriteDataToSegment &write_data_to_segment, Allocator &allocator, + vector &owning_vector, ListSegment *segment, Vector &input, + idx_t &entry_idx, idx_t &count); +typedef void (*read_data_from_segment_t)(ReadDataFromSegment &read_data_from_segment, ListSegment *segment, + Vector &result, idx_t &total_count); + +struct WriteDataToSegment { + create_segment_t create_segment; + write_data_to_segment_t segment_function; + vector child_functions; +}; +struct ReadDataFromSegment { + read_data_from_segment_t segment_function; + vector child_functions; +}; + +// forward declarations +static void AppendRow(WriteDataToSegment &write_data_to_segment, Allocator &allocator, + vector &owning_vector, LinkedList *linked_list, Vector &input, idx_t &entry_idx, + idx_t &count); +static void BuildListVector(ReadDataFromSegment &read_data_from_segment, LinkedList *linked_list, Vector &result, + idx_t &initial_total_count); + +template +static data_ptr_t AllocatePrimitiveData(Allocator &allocator, vector &owning_vector, + uint16_t &capacity) { + + owning_vector.emplace_back(allocator.Allocate(sizeof(ListSegment) + capacity * (sizeof(bool) + sizeof(T)))); + return owning_vector.back().get(); +} + +static data_ptr_t AllocateListData(Allocator &allocator, vector &owning_vector, uint16_t &capacity) { + + owning_vector.emplace_back( + allocator.Allocate(sizeof(ListSegment) + capacity * (sizeof(bool) + sizeof(uint64_t)) + sizeof(LinkedList))); + return owning_vector.back().get(); +} + +static data_ptr_t AllocateStructData(Allocator &allocator, vector &owning_vector, uint16_t &capacity, + idx_t child_count) { + + owning_vector.emplace_back( + allocator.Allocate(sizeof(ListSegment) + capacity * sizeof(bool) + child_count * sizeof(ListSegment *))); + return owning_vector.back().get(); +} + +template +static T *GetPrimitiveData(ListSegment *segment) { + return (T *)(((char *)segment) + sizeof(ListSegment) + segment->capacity * sizeof(bool)); +} + +static uint64_t *GetListLengthData(ListSegment *segment) { + return (uint64_t *)(((char *)segment) + sizeof(ListSegment) + segment->capacity * sizeof(bool)); +} + +static LinkedList *GetListChildData(ListSegment *segment) { + return (LinkedList *)(((char *)segment) + sizeof(ListSegment) + + segment->capacity * (sizeof(bool) + sizeof(uint64_t))); +} + +static ListSegment **GetStructData(ListSegment *segment) { + return (ListSegment **)(((char *)segment) + sizeof(ListSegment) + segment->capacity * sizeof(bool)); +} + +static bool *GetNullMask(ListSegment *segment) { + return (bool *)(((char *)segment) + sizeof(ListSegment)); +} + +static uint16_t GetCapacityForNewSegment(LinkedList *linked_list) { + + // consecutive segments grow by the power of two + uint16_t capacity = 4; + if (linked_list->last_segment) { + auto next_power_of_two = linked_list->last_segment->capacity * 2; + capacity = next_power_of_two < 65536 ? next_power_of_two : linked_list->last_segment->capacity; + } + return capacity; +} + +template +static ListSegment *CreatePrimitiveSegment(WriteDataToSegment &, Allocator &allocator, + vector &owning_vector, uint16_t &capacity) { + + // allocate data and set the header + auto segment = (ListSegment *)AllocatePrimitiveData(allocator, owning_vector, capacity); + segment->capacity = capacity; + segment->count = 0; + segment->next = nullptr; + return segment; +} + +static ListSegment *CreateListSegment(WriteDataToSegment &, Allocator &allocator, vector &owning_vector, + uint16_t &capacity) { + + // allocate data and set the header + auto segment = (ListSegment *)AllocateListData(allocator, owning_vector, capacity); + segment->capacity = capacity; + segment->count = 0; + segment->next = nullptr; + + // create an empty linked list for the child vector + auto linked_child_list = GetListChildData(segment); + LinkedList linked_list(0, nullptr, nullptr); + Store(linked_list, (data_ptr_t)linked_child_list); + + return segment; +} + +static ListSegment *CreateStructSegment(WriteDataToSegment &write_data_to_segment, Allocator &allocator, + vector &owning_vector, uint16_t &capacity) { + + // allocate data and set header + auto segment = (ListSegment *)AllocateStructData(allocator, owning_vector, capacity, + write_data_to_segment.child_functions.size()); + segment->capacity = capacity; + segment->count = 0; + segment->next = nullptr; + + // create a child ListSegment with exactly the same capacity for each child vector + auto child_segments = GetStructData(segment); + for (idx_t i = 0; i < write_data_to_segment.child_functions.size(); i++) { + auto child_function = write_data_to_segment.child_functions[i]; + auto child_segment = child_function.create_segment(child_function, allocator, owning_vector, capacity); + Store(child_segment, (data_ptr_t)(child_segments + i)); + } + + return segment; +} + +static ListSegment *GetSegment(WriteDataToSegment &write_data_to_segment, Allocator &allocator, + vector &owning_vector, LinkedList *linked_list) { + + ListSegment *segment = nullptr; + + // determine segment + if (!linked_list->last_segment) { + // empty linked list, create the first (and last) segment + auto capacity = GetCapacityForNewSegment(linked_list); + segment = write_data_to_segment.create_segment(write_data_to_segment, allocator, owning_vector, capacity); + linked_list->first_segment = segment; + linked_list->last_segment = segment; + + } else if (linked_list->last_segment->capacity == linked_list->last_segment->count) { + // the last segment of the linked list is full, create a new one and append it + auto capacity = GetCapacityForNewSegment(linked_list); + segment = write_data_to_segment.create_segment(write_data_to_segment, allocator, owning_vector, capacity); + linked_list->last_segment->next = segment; + linked_list->last_segment = segment; + + } else { + // the last segment of the linked list is not full, append the data to it + segment = linked_list->last_segment; + } + + D_ASSERT(segment); + return segment; +} + +template +static void WriteDataToPrimitiveSegment(WriteDataToSegment &, Allocator &allocator, + vector &owning_vector, ListSegment *segment, Vector &input, + idx_t &entry_idx, idx_t &count) { + + // get the vector data and the source index of the entry that we want to write + auto input_data = FlatVector::GetData(input); + + // write null validity + auto null_mask = GetNullMask(segment); + auto is_null = FlatVector::IsNull(input, entry_idx); + null_mask[segment->count] = is_null; + + // write value + if (!is_null) { + auto data = GetPrimitiveData(segment); + Store(((T *)input_data)[entry_idx], (data_ptr_t)(data + segment->count)); + } +} + +static void WriteDataToVarcharSegment(WriteDataToSegment &write_data_to_segment, Allocator &allocator, + vector &owning_vector, ListSegment *segment, Vector &input, + idx_t &entry_idx, idx_t &count) { + + // get the vector data and the source index of the entry that we want to write + auto input_data = FlatVector::GetData(input); + + // write null validity + auto null_mask = GetNullMask(segment); + auto is_null = FlatVector::IsNull(input, entry_idx); + null_mask[segment->count] = is_null; + + // set the length of this string + auto str_length_data = GetListLengthData(segment); + uint64_t str_length = 0; + + // get the string + string_t str_t; + if (!is_null) { + str_t = ((string_t *)input_data)[entry_idx]; + str_length = str_t.GetSize(); + } + + // we can reconstruct the offset from the length + Store(str_length, (data_ptr_t)(str_length_data + segment->count)); + + if (is_null) { + return; + } + + // write the characters to the linked list of child segments + auto child_segments = Load((data_ptr_t)GetListChildData(segment)); + for (char &c : str_t.GetString()) { + auto child_segment = + GetSegment(write_data_to_segment.child_functions.back(), allocator, owning_vector, &child_segments); + auto data = GetPrimitiveData(child_segment); + data[child_segment->count] = c; + child_segment->count++; + child_segments.total_capacity++; + } + + // store the updated linked list + Store(child_segments, (data_ptr_t)GetListChildData(segment)); +} + +static void WriteDataToListSegment(WriteDataToSegment &write_data_to_segment, Allocator &allocator, + vector &owning_vector, ListSegment *segment, Vector &input, + idx_t &entry_idx, idx_t &count) { + + // get the vector data and the source index of the entry that we want to write + auto input_data = FlatVector::GetData(input); + + // write null validity + auto null_mask = GetNullMask(segment); + auto is_null = FlatVector::IsNull(input, entry_idx); + null_mask[segment->count] = is_null; + + // set the length of this list + auto list_length_data = GetListLengthData(segment); + uint64_t list_length = 0; + + if (!is_null) { + // get list entry information + auto list_entries = (list_entry_t *)input_data; + const auto &list_entry = list_entries[entry_idx]; + list_length = list_entry.length; + + // get the child vector and its data + auto lists_size = ListVector::GetListSize(input); + auto &child_vector = ListVector::GetEntry(input); + + // loop over the child vector entries and recurse on them + auto child_segments = Load((data_ptr_t)GetListChildData(segment)); + D_ASSERT(write_data_to_segment.child_functions.size() == 1); + for (idx_t child_idx = 0; child_idx < list_entry.length; child_idx++) { + auto source_idx_child = list_entry.offset + child_idx; + AppendRow(write_data_to_segment.child_functions[0], allocator, owning_vector, &child_segments, child_vector, + source_idx_child, lists_size); + } + // store the updated linked list + Store(child_segments, (data_ptr_t)GetListChildData(segment)); + } + + Store(list_length, (data_ptr_t)(list_length_data + segment->count)); +} + +static void WriteDataToStructSegment(WriteDataToSegment &write_data_to_segment, Allocator &allocator, + vector &owning_vector, ListSegment *segment, Vector &input, + idx_t &entry_idx, idx_t &count) { + + // write null validity + auto null_mask = GetNullMask(segment); + auto is_null = FlatVector::IsNull(input, entry_idx); + null_mask[segment->count] = is_null; + + // write value + auto &children = StructVector::GetEntries(input); + D_ASSERT(children.size() == write_data_to_segment.child_functions.size()); + auto child_list = GetStructData(segment); + + // write the data of each of the children of the struct + for (idx_t child_count = 0; child_count < children.size(); child_count++) { + auto child_list_segment = Load((data_ptr_t)(child_list + child_count)); + auto &child_function = write_data_to_segment.child_functions[child_count]; + child_function.segment_function(child_function, allocator, owning_vector, child_list_segment, + *children[child_count], entry_idx, count); + child_list_segment->count++; + } +} + +static void AppendRow(WriteDataToSegment &write_data_to_segment, Allocator &allocator, + vector &owning_vector, LinkedList *linked_list, Vector &input, idx_t &entry_idx, + idx_t &count) { + + D_ASSERT(input.GetVectorType() == VectorType::FLAT_VECTOR); + + auto segment = GetSegment(write_data_to_segment, allocator, owning_vector, linked_list); + write_data_to_segment.segment_function(write_data_to_segment, allocator, owning_vector, segment, input, entry_idx, + count); + + linked_list->total_capacity++; + segment->count++; +} + +template +static void ReadDataFromPrimitiveSegment(ReadDataFromSegment &, ListSegment *segment, Vector &result, + idx_t &total_count) { + + auto &aggr_vector_validity = FlatVector::Validity(result); + + // set NULLs + auto null_mask = GetNullMask(segment); + for (idx_t i = 0; i < segment->count; i++) { + if (null_mask[i]) { + aggr_vector_validity.SetInvalid(total_count + i); + } + } + + auto aggr_vector_data = FlatVector::GetData(result); + + // load values + for (idx_t i = 0; i < segment->count; i++) { + if (aggr_vector_validity.RowIsValid(total_count + i)) { + auto data = GetPrimitiveData(segment); + ((T *)aggr_vector_data)[total_count + i] = Load((data_ptr_t)(data + i)); + } + } +} + +static void ReadDataFromVarcharSegment(ReadDataFromSegment &, ListSegment *segment, Vector &result, + idx_t &total_count) { + + auto &aggr_vector_validity = FlatVector::Validity(result); + + // set NULLs + auto null_mask = GetNullMask(segment); + for (idx_t i = 0; i < segment->count; i++) { + if (null_mask[i]) { + aggr_vector_validity.SetInvalid(total_count + i); + } + } + + // append all the child chars to one string + string str = ""; + auto linked_child_list = Load((data_ptr_t)GetListChildData(segment)); + while (linked_child_list.first_segment) { + auto child_segment = linked_child_list.first_segment; + auto data = GetPrimitiveData(child_segment); + str.append(data, child_segment->count); + linked_child_list.first_segment = child_segment->next; + } + linked_child_list.last_segment = nullptr; + + // use length and (reconstructed) offset to get the correct substrings + auto aggr_vector_data = FlatVector::GetData(result); + auto str_length_data = GetListLengthData(segment); + + // get the substrings and write them to the result vector + idx_t offset = 0; + for (idx_t i = 0; i < segment->count; i++) { + if (!null_mask[i]) { + auto str_length = Load((data_ptr_t)(str_length_data + i)); + auto substr = str.substr(offset, str_length); + auto str_t = StringVector::AddStringOrBlob(result, substr); + ((string_t *)aggr_vector_data)[total_count + i] = str_t; + offset += str_length; + } + } +} + +static void ReadDataFromListSegment(ReadDataFromSegment &read_data_from_segment, ListSegment *segment, Vector &result, + idx_t &total_count) { + + auto &aggr_vector_validity = FlatVector::Validity(result); + + // set NULLs + auto null_mask = GetNullMask(segment); + for (idx_t i = 0; i < segment->count; i++) { + if (null_mask[i]) { + aggr_vector_validity.SetInvalid(total_count + i); + } + } + + auto list_vector_data = FlatVector::GetData(result); + + // get the starting offset + idx_t offset = 0; + if (total_count != 0) { + offset = list_vector_data[total_count - 1].offset + list_vector_data[total_count - 1].length; + } + idx_t starting_offset = offset; + + // set length and offsets + auto list_length_data = GetListLengthData(segment); + for (idx_t i = 0; i < segment->count; i++) { + auto list_length = Load((data_ptr_t)(list_length_data + i)); + list_vector_data[total_count + i].length = list_length; + list_vector_data[total_count + i].offset = offset; + offset += list_length; + } + + auto &child_vector = ListVector::GetEntry(result); + auto linked_child_list = Load((data_ptr_t)GetListChildData(segment)); + ListVector::Reserve(result, offset); + + // recurse into the linked list of child values + D_ASSERT(read_data_from_segment.child_functions.size() == 1); + BuildListVector(read_data_from_segment.child_functions[0], &linked_child_list, child_vector, starting_offset); +} + +static void ReadDataFromStructSegment(ReadDataFromSegment &read_data_from_segment, ListSegment *segment, Vector &result, + idx_t &total_count) { + + auto &aggr_vector_validity = FlatVector::Validity(result); + + // set NULLs + auto null_mask = GetNullMask(segment); + for (idx_t i = 0; i < segment->count; i++) { + if (null_mask[i]) { + aggr_vector_validity.SetInvalid(total_count + i); + } + } + + auto &children = StructVector::GetEntries(result); + + // recurse into the child segments of each child of the struct + D_ASSERT(children.size() == read_data_from_segment.child_functions.size()); + auto struct_children = GetStructData(segment); + for (idx_t child_count = 0; child_count < children.size(); child_count++) { + auto struct_children_segment = Load((data_ptr_t)(struct_children + child_count)); + auto &child_function = read_data_from_segment.child_functions[child_count]; + child_function.segment_function(child_function, struct_children_segment, *children[child_count], total_count); + } +} + +static void BuildListVector(ReadDataFromSegment &read_data_from_segment, LinkedList *linked_list, Vector &result, + idx_t &initial_total_count) { + + idx_t total_count = initial_total_count; + while (linked_list->first_segment) { + auto segment = linked_list->first_segment; + read_data_from_segment.segment_function(read_data_from_segment, segment, result, total_count); + + total_count += segment->count; + linked_list->first_segment = segment->next; + } + + linked_list->last_segment = nullptr; +} + +static void InitializeValidities(Vector &vector, idx_t &capacity) { + + auto &validity_mask = FlatVector::Validity(vector); + validity_mask.Initialize(capacity); + + if (vector.GetType().id() == LogicalTypeId::LIST) { + auto &child_vector = ListVector::GetEntry(vector); + InitializeValidities(child_vector, capacity); + } else if (vector.GetType().id() == LogicalTypeId::STRUCT || vector.GetType().id() == LogicalTypeId::MAP) { + auto &children = StructVector::GetEntries(vector); + for (auto &child : children) { + InitializeValidities(*child, capacity); + } + } +} + +static void RecursiveFlatten(Vector &vector, idx_t &count) { + + if (vector.GetVectorType() != VectorType::FLAT_VECTOR) { + vector.Flatten(count); + } + + if (vector.GetType().id() == LogicalTypeId::LIST) { + auto &child_vector = ListVector::GetEntry(vector); + auto child_vector_count = ListVector::GetListSize(vector); + RecursiveFlatten(child_vector, child_vector_count); + + } else if (vector.GetType().id() == LogicalTypeId::STRUCT || vector.GetType().id() == LogicalTypeId::MAP) { + auto &children = StructVector::GetEntries(vector); + for (auto &child : children) { + RecursiveFlatten(*child, count); + } + } +} + +struct ListBindData : public FunctionData { + explicit ListBindData(const LogicalType &stype_p); + ~ListBindData() override; + + LogicalType stype; + WriteDataToSegment write_data_to_segment; + ReadDataFromSegment read_data_from_segment; + + unique_ptr Copy() const override { + return make_unique(stype); + } + + bool Equals(const FunctionData &other_p) const override { + auto &other = (const ListBindData &)other_p; + return stype == other.stype; + } +}; + +static void GetSegmentDataFunctions(WriteDataToSegment &write_data_to_segment, + ReadDataFromSegment &read_data_from_segment, const LogicalType &type) { + + auto physical_type = type.InternalType(); + switch (physical_type) { + case PhysicalType::BIT: + case PhysicalType::BOOL: { + write_data_to_segment.create_segment = CreatePrimitiveSegment; + write_data_to_segment.segment_function = WriteDataToPrimitiveSegment; + read_data_from_segment.segment_function = ReadDataFromPrimitiveSegment; + break; + } + case PhysicalType::INT8: { + write_data_to_segment.create_segment = CreatePrimitiveSegment; + write_data_to_segment.segment_function = WriteDataToPrimitiveSegment; + read_data_from_segment.segment_function = ReadDataFromPrimitiveSegment; + break; + } + case PhysicalType::INT16: { + write_data_to_segment.create_segment = CreatePrimitiveSegment; + write_data_to_segment.segment_function = WriteDataToPrimitiveSegment; + read_data_from_segment.segment_function = ReadDataFromPrimitiveSegment; + break; + } + case PhysicalType::INT32: { + write_data_to_segment.create_segment = CreatePrimitiveSegment; + write_data_to_segment.segment_function = WriteDataToPrimitiveSegment; + read_data_from_segment.segment_function = ReadDataFromPrimitiveSegment; + break; + } + case PhysicalType::INT64: { + write_data_to_segment.create_segment = CreatePrimitiveSegment; + write_data_to_segment.segment_function = WriteDataToPrimitiveSegment; + read_data_from_segment.segment_function = ReadDataFromPrimitiveSegment; + break; + } + case PhysicalType::UINT8: { + write_data_to_segment.create_segment = CreatePrimitiveSegment; + write_data_to_segment.segment_function = WriteDataToPrimitiveSegment; + read_data_from_segment.segment_function = ReadDataFromPrimitiveSegment; + break; + } + case PhysicalType::UINT16: { + write_data_to_segment.create_segment = CreatePrimitiveSegment; + write_data_to_segment.segment_function = WriteDataToPrimitiveSegment; + read_data_from_segment.segment_function = ReadDataFromPrimitiveSegment; + break; + } + case PhysicalType::UINT32: { + write_data_to_segment.create_segment = CreatePrimitiveSegment; + write_data_to_segment.segment_function = WriteDataToPrimitiveSegment; + read_data_from_segment.segment_function = ReadDataFromPrimitiveSegment; + break; + } + case PhysicalType::UINT64: { + write_data_to_segment.create_segment = CreatePrimitiveSegment; + write_data_to_segment.segment_function = WriteDataToPrimitiveSegment; + read_data_from_segment.segment_function = ReadDataFromPrimitiveSegment; + break; + } + case PhysicalType::FLOAT: { + write_data_to_segment.create_segment = CreatePrimitiveSegment; + write_data_to_segment.segment_function = WriteDataToPrimitiveSegment; + read_data_from_segment.segment_function = ReadDataFromPrimitiveSegment; + break; + } + case PhysicalType::DOUBLE: { + write_data_to_segment.create_segment = CreatePrimitiveSegment; + write_data_to_segment.segment_function = WriteDataToPrimitiveSegment; + read_data_from_segment.segment_function = ReadDataFromPrimitiveSegment; + break; + } + case PhysicalType::INT128: { + write_data_to_segment.create_segment = CreatePrimitiveSegment; + write_data_to_segment.segment_function = WriteDataToPrimitiveSegment; + read_data_from_segment.segment_function = ReadDataFromPrimitiveSegment; + break; + } + case PhysicalType::INTERVAL: { + write_data_to_segment.create_segment = CreatePrimitiveSegment; + write_data_to_segment.segment_function = WriteDataToPrimitiveSegment; + read_data_from_segment.segment_function = ReadDataFromPrimitiveSegment; + break; + } + case PhysicalType::VARCHAR: { + write_data_to_segment.create_segment = CreateListSegment; + write_data_to_segment.segment_function = WriteDataToVarcharSegment; + read_data_from_segment.segment_function = ReadDataFromVarcharSegment; + + write_data_to_segment.child_functions.emplace_back(WriteDataToSegment()); + write_data_to_segment.child_functions.back().create_segment = CreatePrimitiveSegment; + break; + } + case PhysicalType::LIST: { + write_data_to_segment.create_segment = CreateListSegment; + write_data_to_segment.segment_function = WriteDataToListSegment; + read_data_from_segment.segment_function = ReadDataFromListSegment; + + // recurse + write_data_to_segment.child_functions.emplace_back(WriteDataToSegment()); + read_data_from_segment.child_functions.emplace_back(ReadDataFromSegment()); + GetSegmentDataFunctions(write_data_to_segment.child_functions.back(), + read_data_from_segment.child_functions.back(), ListType::GetChildType(type)); + break; + } + case PhysicalType::STRUCT: { + write_data_to_segment.create_segment = CreateStructSegment; + write_data_to_segment.segment_function = WriteDataToStructSegment; + read_data_from_segment.segment_function = ReadDataFromStructSegment; + + // recurse + auto child_types = StructType::GetChildTypes(type); + for (idx_t i = 0; i < child_types.size(); i++) { + write_data_to_segment.child_functions.emplace_back(WriteDataToSegment()); + read_data_from_segment.child_functions.emplace_back(ReadDataFromSegment()); + GetSegmentDataFunctions(write_data_to_segment.child_functions.back(), + read_data_from_segment.child_functions.back(), child_types[i].second); + } + break; + } + default: + throw InternalException("LIST aggregate not yet implemented for " + type.ToString()); + } +} + +ListBindData::ListBindData(const LogicalType &stype_p) : stype(stype_p) { + + // always unnest once because the result vector is of type LIST + auto type = ListType::GetChildType(stype_p); + GetSegmentDataFunctions(write_data_to_segment, read_data_from_segment, type); +} + +ListBindData::~ListBindData() { +} + struct ListAggState { - Vector *list_vector; + LinkedList *linked_list; + LogicalType *type; + vector *owning_vector; }; struct ListFunction { template static void Initialize(STATE *state) { - state->list_vector = nullptr; + state->linked_list = nullptr; + state->type = nullptr; + state->owning_vector = nullptr; } template static void Destroy(STATE *state) { - if (state->list_vector) { - delete state->list_vector; + D_ASSERT(state); + if (state->linked_list) { + delete state->linked_list; + state->linked_list = nullptr; + } + if (state->type) { + delete state->type; + state->type = nullptr; + } + if (state->owning_vector) { + state->owning_vector->clear(); + delete state->owning_vector; + state->owning_vector = nullptr; } } static bool IgnoreNull() { @@ -90422,88 +99591,136 @@ struct ListFunction { } }; -static void ListUpdateFunction(Vector inputs[], FunctionData *, idx_t input_count, Vector &state_vector, idx_t count) { +static void ListUpdateFunction(Vector inputs[], AggregateInputData &aggr_input_data, idx_t input_count, + Vector &state_vector, idx_t count) { D_ASSERT(input_count == 1); auto &input = inputs[0]; - VectorData sdata; - state_vector.Orrify(count, sdata); - - auto list_vector_type = LogicalType::LIST(input.GetType()); + UnifiedVectorFormat sdata; + state_vector.ToUnifiedFormat(count, sdata); auto states = (ListAggState **)sdata.data; - if (input.GetVectorType() == VectorType::SEQUENCE_VECTOR) { - input.Normalify(count); - } + RecursiveFlatten(input, count); + + auto &list_bind_data = (ListBindData &)*aggr_input_data.bind_data; + for (idx_t i = 0; i < count; i++) { auto state = states[sdata.sel->get_index(i)]; - if (!state->list_vector) { - // NOTE: any number bigger than 1 can cause DuckDB to run out of memory for specific queries - // consisting of millions of groups in the group by and complex (nested) vectors - state->list_vector = new Vector(list_vector_type, 1); + if (!state->linked_list) { + state->linked_list = new LinkedList(0, nullptr, nullptr); + state->type = new LogicalType(input.GetType()); + state->owning_vector = new vector; } - ListVector::Append(*state->list_vector, input, i + 1, i); + D_ASSERT(state->type); + AppendRow(list_bind_data.write_data_to_segment, aggr_input_data.allocator, *state->owning_vector, + state->linked_list, input, i, count); } } -static void ListCombineFunction(Vector &state, Vector &combined, FunctionData *bind_data, idx_t count) { - VectorData sdata; - state.Orrify(count, sdata); +static void ListCombineFunction(Vector &state, Vector &combined, AggregateInputData &, idx_t count) { + UnifiedVectorFormat sdata; + state.ToUnifiedFormat(count, sdata); auto states_ptr = (ListAggState **)sdata.data; auto combined_ptr = FlatVector::GetData(combined); for (idx_t i = 0; i < count; i++) { auto state = states_ptr[sdata.sel->get_index(i)]; - if (!state->list_vector) { + if (!state->linked_list) { // NULL, no need to append. continue; } - if (!combined_ptr[i]->list_vector) { - // NOTE: initializing this with a capacity of ListVector::GetListSize(*state->list_vector) causes - // DuckDB to run out of memory for multiple threads with millions of groups in the group by and complex - // (nested) vectors - combined_ptr[i]->list_vector = new Vector(state->list_vector->GetType(), 1); + D_ASSERT(state->type); + D_ASSERT(state->owning_vector); + if (!combined_ptr[i]->linked_list) { + + // copy the linked list + combined_ptr[i]->linked_list = new LinkedList(0, nullptr, nullptr); + combined_ptr[i]->linked_list->first_segment = state->linked_list->first_segment; + combined_ptr[i]->linked_list->last_segment = state->linked_list->last_segment; + combined_ptr[i]->linked_list->total_capacity = state->linked_list->total_capacity; + + // copy the type + combined_ptr[i]->type = new LogicalType(*state->type); + + // new owning_vector to hold the unique pointers + combined_ptr[i]->owning_vector = new vector; + + } else { + combined_ptr[i]->linked_list->last_segment->next = state->linked_list->first_segment; + combined_ptr[i]->linked_list->last_segment = state->linked_list->last_segment; + combined_ptr[i]->linked_list->total_capacity += state->linked_list->total_capacity; + } + + // copy the owning vector (and its unique pointers to the allocated data) + // FIXME: more efficient way of copying the unique pointers? + auto &owning_vector = *state->owning_vector; + for (idx_t j = 0; j < state->owning_vector->size(); j++) { + combined_ptr[i]->owning_vector->push_back(move(owning_vector[j])); } - ListVector::Append(*combined_ptr[i]->list_vector, ListVector::GetEntry(*state->list_vector), - ListVector::GetListSize(*state->list_vector)); } } -static void ListFinalize(Vector &state_vector, FunctionData *, Vector &result, idx_t count, idx_t offset) { - VectorData sdata; - state_vector.Orrify(count, sdata); +static void ListFinalize(Vector &state_vector, AggregateInputData &aggr_input_data, Vector &result, idx_t count, + idx_t offset) { + UnifiedVectorFormat sdata; + state_vector.ToUnifiedFormat(count, sdata); auto states = (ListAggState **)sdata.data; D_ASSERT(result.GetType().id() == LogicalTypeId::LIST); auto &mask = FlatVector::Validity(result); - auto list_struct_data = FlatVector::GetData(result); + auto result_data = FlatVector::GetData(result); size_t total_len = ListVector::GetListSize(result); + auto &list_bind_data = (ListBindData &)*aggr_input_data.bind_data; + for (idx_t i = 0; i < count; i++) { + auto state = states[sdata.sel->get_index(i)]; const auto rid = i + offset; - if (!state->list_vector) { + if (!state->linked_list) { mask.SetInvalid(rid); continue; } - auto &state_lv = *state->list_vector; - auto state_lv_count = ListVector::GetListSize(state_lv); - list_struct_data[rid].length = state_lv_count; - list_struct_data[rid].offset = total_len; - total_len += state_lv_count; + // set the length and offset of this list in the result vector + auto total_capacity = state->linked_list->total_capacity; + result_data[rid].length = total_capacity; + result_data[rid].offset = total_len; + total_len += total_capacity; + + D_ASSERT(state->type); - auto &list_vec_to_append = ListVector::GetEntry(state_lv); - ListVector::Append(result, list_vec_to_append, state_lv_count); + Vector aggr_vector(*state->type, total_capacity); + // FIXME: this is a workaround because the constructor of a vector does not set the size + // of the validity mask, and by default it is set to STANDARD_VECTOR_SIZE + // ListVector::Reserve only increases the validity mask, if (to_reserve > capacity), + // which will not be the case if the value passed to the constructor of aggr_vector + // is greater than to_reserve + InitializeValidities(aggr_vector, total_capacity); + + idx_t total_count = 0; + BuildListVector(list_bind_data.read_data_from_segment, state->linked_list, aggr_vector, total_count); + ListVector::Append(result, aggr_vector, total_capacity); + + // now destroy the state (for parallel destruction) + ListFunction::Destroy(state); } } unique_ptr ListBindFunction(ClientContext &context, AggregateFunction &function, vector> &arguments) { D_ASSERT(arguments.size() == 1); + D_ASSERT(function.arguments.size() == 1); + + if (arguments[0]->return_type.id() == LogicalTypeId::UNKNOWN) { + function.arguments[0] = LogicalTypeId::UNKNOWN; + function.return_type = LogicalType::SQLNULL; + return nullptr; + } + function.return_type = LogicalType::LIST(arguments[0]->return_type); - return nullptr; + return make_unique(function.return_type); } void ListFun::RegisterFunction(BuiltinFunctions &set) { @@ -90600,13 +99817,13 @@ struct RegrAvgFunction { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { target->sum += source.sum; target->count += source.count; } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->count == 0) { mask.SetInvalid(idx); } else { @@ -90619,7 +99836,7 @@ struct RegrAvgFunction { }; struct RegrAvgXFunction : RegrAvgFunction { template - static void Operation(STATE *state, FunctionData *bind_data, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, + static void Operation(STATE *state, AggregateInputData &, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, ValidityMask &bmask, idx_t xidx, idx_t yidx) { state->sum += y_data[yidx]; state->count++; @@ -90628,7 +99845,7 @@ struct RegrAvgXFunction : RegrAvgFunction { struct RegrAvgYFunction : RegrAvgFunction { template - static void Operation(STATE *state, FunctionData *bind_data, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, + static void Operation(STATE *state, AggregateInputData &, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, ValidityMask &bmask, idx_t xidx, idx_t yidx) { state->sum += x_data[xidx]; state->count++; @@ -90678,19 +99895,19 @@ struct RegrCountFunction { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { *target += source; } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { target[idx] = *state; } static bool IgnoreNull() { return true; } template - static void Operation(STATE *state, FunctionData *bind_data, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, + static void Operation(STATE *state, AggregateInputData &, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, ValidityMask &bmask, idx_t xidx, idx_t yidx) { *state += 1; } @@ -90740,21 +99957,21 @@ struct RegrSlopeOperation { } template - static void Operation(STATE *state, FunctionData *bind_data, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, - ValidityMask &bmask, idx_t xidx, idx_t yidx) { - CovarOperation::Operation(&state->cov_pop, bind_data, y_data, x_data, bmask, - amask, yidx, xidx); - STDDevBaseOperation::Operation(&state->var_pop, bind_data, y_data, bmask, yidx); + static void Operation(STATE *state, AggregateInputData &aggr_input_data, A_TYPE *x_data, B_TYPE *y_data, + ValidityMask &amask, ValidityMask &bmask, idx_t xidx, idx_t yidx) { + CovarOperation::Operation(&state->cov_pop, aggr_input_data, y_data, x_data, + bmask, amask, yidx, xidx); + STDDevBaseOperation::Operation(&state->var_pop, aggr_input_data, y_data, bmask, yidx); } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { - CovarOperation::Combine(source.cov_pop, &target->cov_pop, bind_data); - STDDevBaseOperation::Combine(source.var_pop, &target->var_pop, bind_data); + static void Combine(const STATE &source, STATE *target, AggregateInputData &aggr_input_data) { + CovarOperation::Combine(source.cov_pop, &target->cov_pop, aggr_input_data); + STDDevBaseOperation::Combine(source.var_pop, &target->var_pop, aggr_input_data); } template - static void Finalize(Vector &result, FunctionData *, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &, STATE *state, T *target, ValidityMask &mask, idx_t idx) { if (state->cov_pop.count == 0 || state->var_pop.count == 0) { mask.SetInvalid(idx); } else { @@ -90798,30 +100015,31 @@ struct RegrInterceptOperation { } template - static void Operation(STATE *state, FunctionData *bind_data, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, - ValidityMask &bmask, idx_t xidx, idx_t yidx) { + static void Operation(STATE *state, AggregateInputData &aggr_input_data, A_TYPE *x_data, B_TYPE *y_data, + ValidityMask &amask, ValidityMask &bmask, idx_t xidx, idx_t yidx) { state->count++; state->sum_x += y_data[yidx]; state->sum_y += x_data[xidx]; - RegrSlopeOperation::Operation(&state->slope, bind_data, x_data, y_data, - amask, bmask, xidx, yidx); + RegrSlopeOperation::Operation(&state->slope, aggr_input_data, x_data, + y_data, amask, bmask, xidx, yidx); } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &aggr_input_data) { target->count += source.count; target->sum_x += source.sum_x; target->sum_y += source.sum_y; - RegrSlopeOperation::Combine(source.slope, &target->slope, bind_data); + RegrSlopeOperation::Combine(source.slope, &target->slope, aggr_input_data); } template - static void Finalize(Vector &result, FunctionData *fd, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &aggr_input_data, STATE *state, T *target, + ValidityMask &mask, idx_t idx) { if (state->count == 0) { mask.SetInvalid(idx); return; } - RegrSlopeOperation::Finalize(result, fd, &state->slope, target, mask, idx); + RegrSlopeOperation::Finalize(result, aggr_input_data, &state->slope, target, mask, idx); auto x_avg = state->sum_x / state->count; auto y_avg = state->sum_y / state->count; target[idx] = y_avg - target[idx] * x_avg; @@ -90867,23 +100085,26 @@ struct RegrR2Operation { } template - static void Operation(STATE *state, FunctionData *bind_data, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, - ValidityMask &bmask, idx_t xidx, idx_t yidx) { - CorrOperation::Operation(&state->corr, bind_data, y_data, x_data, bmask, amask, - yidx, xidx); - STDDevBaseOperation::Operation(&state->var_pop_x, bind_data, y_data, bmask, yidx); - STDDevBaseOperation::Operation(&state->var_pop_y, bind_data, x_data, amask, xidx); + static void Operation(STATE *state, AggregateInputData &aggr_input_data, A_TYPE *x_data, B_TYPE *y_data, + ValidityMask &amask, ValidityMask &bmask, idx_t xidx, idx_t yidx) { + CorrOperation::Operation(&state->corr, aggr_input_data, y_data, x_data, bmask, + amask, yidx, xidx); + STDDevBaseOperation::Operation(&state->var_pop_x, aggr_input_data, y_data, bmask, + yidx); + STDDevBaseOperation::Operation(&state->var_pop_y, aggr_input_data, x_data, amask, + xidx); } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { - CorrOperation::Combine(source.corr, &target->corr, bind_data); - STDDevBaseOperation::Combine(source.var_pop_x, &target->var_pop_x, bind_data); - STDDevBaseOperation::Combine(source.var_pop_y, &target->var_pop_y, bind_data); + static void Combine(const STATE &source, STATE *target, AggregateInputData &aggr_input_data) { + CorrOperation::Combine(source.corr, &target->corr, aggr_input_data); + STDDevBaseOperation::Combine(source.var_pop_x, &target->var_pop_x, aggr_input_data); + STDDevBaseOperation::Combine(source.var_pop_y, &target->var_pop_y, aggr_input_data); } template - static void Finalize(Vector &result, FunctionData *fd, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &aggr_input_data, STATE *state, T *target, + ValidityMask &mask, idx_t idx) { auto var_pop_x = state->var_pop_x.count > 1 ? (state->var_pop_x.dsquared / state->var_pop_x.count) : 0; if (!Value::DoubleIsFinite(var_pop_x)) { throw OutOfRangeException("VARPOP(X) is out of range!"); @@ -90900,7 +100121,7 @@ struct RegrR2Operation { target[idx] = 1; return; } - CorrOperation::Finalize(result, fd, &state->corr, target, mask, idx); + CorrOperation::Finalize(result, aggr_input_data, &state->corr, target, mask, idx); target[idx] = pow(target[idx], 2); } @@ -90962,13 +100183,14 @@ struct RegrBaseOperation { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { - RegrCountFunction::Combine(source.count, &target->count, bind_data); - STDDevBaseOperation::Combine(source.var_pop, &target->var_pop, bind_data); + static void Combine(const STATE &source, STATE *target, AggregateInputData &aggr_input_data) { + RegrCountFunction::Combine(source.count, &target->count, aggr_input_data); + STDDevBaseOperation::Combine(source.var_pop, &target->var_pop, aggr_input_data); } template - static void Finalize(Vector &result, FunctionData *fd, STATE *state, T *target, ValidityMask &mask, idx_t idx) { + static void Finalize(Vector &result, AggregateInputData &aggr_input_data, STATE *state, T *target, + ValidityMask &mask, idx_t idx) { if (state->var_pop.count == 0) { mask.SetInvalid(idx); return; @@ -90977,7 +100199,7 @@ struct RegrBaseOperation { if (!Value::DoubleIsFinite(var_pop)) { throw OutOfRangeException("VARPOP is out of range!"); } - RegrCountFunction::Finalize(result, fd, &state->count, target, mask, idx); + RegrCountFunction::Finalize(result, aggr_input_data, &state->count, target, mask, idx); target[idx] *= var_pop; } @@ -90988,21 +100210,21 @@ struct RegrBaseOperation { struct RegrSXXOperation : RegrBaseOperation { template - static void Operation(STATE *state, FunctionData *bind_data, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, - ValidityMask &bmask, idx_t xidx, idx_t yidx) { - RegrCountFunction::Operation(&state->count, bind_data, y_data, x_data, bmask, amask, - yidx, xidx); - STDDevBaseOperation::Operation(&state->var_pop, bind_data, y_data, bmask, yidx); + static void Operation(STATE *state, AggregateInputData &aggr_input_data, A_TYPE *x_data, B_TYPE *y_data, + ValidityMask &amask, ValidityMask &bmask, idx_t xidx, idx_t yidx) { + RegrCountFunction::Operation(&state->count, aggr_input_data, y_data, x_data, bmask, + amask, yidx, xidx); + STDDevBaseOperation::Operation(&state->var_pop, aggr_input_data, y_data, bmask, yidx); } }; struct RegrSYYOperation : RegrBaseOperation { template - static void Operation(STATE *state, FunctionData *bind_data, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, - ValidityMask &bmask, idx_t xidx, idx_t yidx) { - RegrCountFunction::Operation(&state->count, bind_data, y_data, x_data, bmask, amask, - yidx, xidx); - STDDevBaseOperation::Operation(&state->var_pop, bind_data, x_data, bmask, xidx); + static void Operation(STATE *state, AggregateInputData &aggr_input_data, A_TYPE *x_data, B_TYPE *y_data, + ValidityMask &amask, ValidityMask &bmask, idx_t xidx, idx_t yidx) { + RegrCountFunction::Operation(&state->count, aggr_input_data, y_data, x_data, bmask, + amask, yidx, xidx); + STDDevBaseOperation::Operation(&state->var_pop, aggr_input_data, x_data, bmask, xidx); } }; @@ -91043,25 +100265,26 @@ struct RegrSXYOperation { } template - static void Operation(STATE *state, FunctionData *bind_data, A_TYPE *x_data, B_TYPE *y_data, ValidityMask &amask, - ValidityMask &bmask, idx_t xidx, idx_t yidx) { - RegrCountFunction::Operation(&state->count, bind_data, y_data, x_data, bmask, amask, - yidx, xidx); - CovarOperation::Operation(&state->cov_pop, bind_data, x_data, y_data, amask, - bmask, xidx, yidx); + static void Operation(STATE *state, AggregateInputData &aggr_input_data, A_TYPE *x_data, B_TYPE *y_data, + ValidityMask &amask, ValidityMask &bmask, idx_t xidx, idx_t yidx) { + RegrCountFunction::Operation(&state->count, aggr_input_data, y_data, x_data, bmask, + amask, yidx, xidx); + CovarOperation::Operation(&state->cov_pop, aggr_input_data, x_data, y_data, + amask, bmask, xidx, yidx); } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { - CovarOperation::Combine(source.cov_pop, &target->cov_pop, bind_data); - RegrCountFunction::Combine(source.count, &target->count, bind_data); + static void Combine(const STATE &source, STATE *target, AggregateInputData &aggr_input_data) { + CovarOperation::Combine(source.cov_pop, &target->cov_pop, aggr_input_data); + RegrCountFunction::Combine(source.count, &target->count, aggr_input_data); } template - static void Finalize(Vector &result, FunctionData *fd, STATE *state, T *target, ValidityMask &mask, idx_t idx) { - CovarPopOperation::Finalize(result, fd, &state->cov_pop, target, mask, idx); + static void Finalize(Vector &result, AggregateInputData &aggr_input_data, STATE *state, T *target, + ValidityMask &mask, idx_t idx) { + CovarPopOperation::Finalize(result, aggr_input_data, &state->cov_pop, target, mask, idx); auto cov_pop = target[idx]; - RegrCountFunction::Finalize(result, fd, &state->count, target, mask, idx); + RegrCountFunction::Finalize(result, aggr_input_data, &state->count, target, mask, idx); target[idx] *= cov_pop; } @@ -91172,7 +100395,8 @@ struct SortedAggregateBindData : public FunctionData { }; struct SortedAggregateState { - SortedAggregateState() : nsel(0) { + SortedAggregateState() + : arguments(Allocator::DefaultAllocator()), ordering(Allocator::DefaultAllocator()), nsel(0) { } ChunkCollection arguments; @@ -91211,9 +100435,9 @@ struct SortedAggregateFunction { sort_chunk.SetCardinality(count); } - static void SimpleUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, data_ptr_t state, + static void SimpleUpdate(Vector inputs[], AggregateInputData &aggr_input_data, idx_t input_count, data_ptr_t state, idx_t count) { - const auto order_bind = (SortedAggregateBindData *)bind_data; + const auto order_bind = (SortedAggregateBindData *)aggr_input_data.bind_data; DataChunk arg_chunk; DataChunk sort_chunk; ProjectInputs(inputs, order_bind, input_count, count, arg_chunk, sort_chunk); @@ -91223,22 +100447,22 @@ struct SortedAggregateFunction { order_state->ordering.Append(sort_chunk); } - static void ScatterUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, Vector &states, + static void ScatterUpdate(Vector inputs[], AggregateInputData &aggr_input_data, idx_t input_count, Vector &states, idx_t count) { if (!count) { return; } // Append the arguments to the two sub-collections - const auto order_bind = (SortedAggregateBindData *)bind_data; + const auto order_bind = (SortedAggregateBindData *)aggr_input_data.bind_data; DataChunk arg_inputs; DataChunk sort_inputs; ProjectInputs(inputs, order_bind, input_count, count, arg_inputs, sort_inputs); // We have to scatter the chunks one at a time // so build a selection vector for each one. - VectorData svdata; - states.Orrify(count, svdata); + UnifiedVectorFormat svdata; + states.ToUnifiedFormat(count, svdata); // Build the selection vector for each state. auto sdata = (SortedAggregateState **)svdata.data; @@ -91275,7 +100499,7 @@ struct SortedAggregateFunction { } template - static void Combine(const STATE &source, STATE *target, FunctionData *bind_data) { + static void Combine(const STATE &source, STATE *target, AggregateInputData &) { if (source.arguments.Count() == 0) { return; } @@ -91283,8 +100507,9 @@ struct SortedAggregateFunction { target->ordering.Append(const_cast(source.ordering)); } - static void Finalize(Vector &states, FunctionData *bind_data, Vector &result, idx_t count, idx_t offset) { - const auto order_bind = (SortedAggregateBindData *)bind_data; + static void Finalize(Vector &states, AggregateInputData &aggr_input_data, Vector &result, idx_t count, + idx_t offset) { + const auto order_bind = (SortedAggregateBindData *)aggr_input_data.bind_data; // Reusable inner state vector agg_state(order_bind->function.state_size()); @@ -91296,6 +100521,7 @@ struct SortedAggregateFunction { // State variables const auto input_count = order_bind->function.arguments.size(); auto bind_info = order_bind->bind_info.get(); + AggregateInputData aggr_bind_info(bind_info, Allocator::DefaultAllocator()); // Inner aggregate APIs auto initialize = order_bind->function.initialize; @@ -91320,23 +100546,31 @@ struct SortedAggregateFunction { for (auto &chunk : state->arguments.Chunks()) { // These are all simple updates, so use it if available if (simple_update) { - simple_update(chunk->data.data(), bind_info, input_count, agg_state.data(), chunk->size()); + simple_update(chunk->data.data(), aggr_bind_info, input_count, agg_state.data(), chunk->size()); } else { // We are only updating a constant state agg_state_vec.SetVectorType(VectorType::CONSTANT_VECTOR); - update(chunk->data.data(), bind_info, input_count, agg_state_vec, chunk->size()); + update(chunk->data.data(), aggr_bind_info, input_count, agg_state_vec, chunk->size()); } } // Finalize a single value at the next offset agg_state_vec.SetVectorType(states.GetVectorType()); - finalize(agg_state_vec, bind_info, result, 1, i + offset); + finalize(agg_state_vec, aggr_bind_info, result, 1, i + offset); if (destructor) { destructor(agg_state_vec, 1); } } } + + static void Serialize(FieldWriter &writer, const FunctionData *bind_data, const AggregateFunction &function) { + throw NotImplementedException("FIXME: serialize sorted aggregate not supported"); + } + static unique_ptr Deserialize(ClientContext &context, FieldReader &reader, + AggregateFunction &function) { + throw NotImplementedException("FIXME: deserialize sorted aggregate not supported"); + } }; unique_ptr AggregateFunction::BindSortedAggregate(AggregateFunction &bound_function, @@ -91365,31 +100599,12 @@ unique_ptr AggregateFunction::BindSortedAggregate(AggregateFunctio AggregateFunction::StateCombine, SortedAggregateFunction::Finalize, SortedAggregateFunction::SimpleUpdate, nullptr, AggregateFunction::StateDestroy); + bound_function.serialize = SortedAggregateFunction::Serialize; + bound_function.deserialize = SortedAggregateFunction::Deserialize; return move(sorted_bind); } -} // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/function/cast_rules.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - -namespace duckdb { -//! Contains a list of rules for casting -class CastRules { -public: - //! Returns the cost of performing an implicit cost from "from" to "to", or -1 if an implicit cast is not possible - static int64_t ImplicitCast(const LogicalType &from, const LogicalType &to); -}; - } // namespace duckdb @@ -91871,9 +101086,10 @@ bool SimpleNamedParameterFunction::HasNamedParameters() { } BaseScalarFunction::BaseScalarFunction(string name_p, vector arguments_p, LogicalType return_type_p, - bool has_side_effects, LogicalType varargs_p, bool propagates_null_values_p) + FunctionSideEffects side_effects, LogicalType varargs_p, + FunctionNullHandling null_handling) : SimpleFunction(move(name_p), move(arguments_p), move(varargs_p)), return_type(move(return_type_p)), - has_side_effects(has_side_effects), propagates_null_values(propagates_null_values_p) { + side_effects(side_effects), null_handling(null_handling) { } BaseScalarFunction::~BaseScalarFunction() { @@ -91885,6 +101101,7 @@ string BaseScalarFunction::ToString() { // add your initializer for new functions here void BuiltinFunctions::Initialize() { + RegisterTableScanFunctions(); RegisterSQLiteFunctions(); RegisterReadFunctions(); RegisterTableFunctions(); @@ -91938,7 +101155,7 @@ void BuiltinFunctions::AddFunction(PragmaFunction function) { catalog.CreatePragmaFunction(context, &info); } -void BuiltinFunctions::AddFunction(const string &name, vector functions) { +void BuiltinFunctions::AddFunction(const string &name, PragmaFunctionSet functions) { CreatePragmaFunctionInfo info(name, move(functions)); catalog.CreatePragmaFunction(context, &info); } @@ -92010,7 +101227,7 @@ string Function::CallToString(const string &name, const vector &arg return StringUtil::Format("%s(%s)", name, StringUtil::Join(input_arguments, ", ")); } -static int64_t BindVarArgsFunctionCost(SimpleFunction &func, vector &arguments) { +static int64_t BindVarArgsFunctionCost(const SimpleFunction &func, const vector &arguments) { if (arguments.size() < func.arguments.size()) { // not enough arguments to fulfill the non-vararg part of the function return -1; @@ -92034,7 +101251,7 @@ static int64_t BindVarArgsFunctionCost(SimpleFunction &func, vector return cost; } -static int64_t BindFunctionCost(SimpleFunction &func, vector &arguments) { +static int64_t BindFunctionCost(const SimpleFunction &func, const vector &arguments) { if (func.HasVarArgs()) { // special case varargs function return BindVarArgsFunctionCost(func, arguments); @@ -92045,6 +101262,10 @@ static int64_t BindFunctionCost(SimpleFunction &func, vector &argum } int64_t cost = 0; for (idx_t i = 0; i < arguments.size(); i++) { + // Check alias first + if (arguments[i].GetAlias() != func.arguments[i].GetAlias()) { + return -1; + } if (arguments[i].id() == func.arguments[i].id()) { // arguments match: do nothing continue; @@ -92062,13 +101283,13 @@ static int64_t BindFunctionCost(SimpleFunction &func, vector &argum } template -static vector BindFunctionsFromArguments(const string &name, vector &functions, - vector &arguments, string &error) { +static vector BindFunctionsFromArguments(const string &name, FunctionSet &functions, + const vector &arguments, string &error) { idx_t best_function = DConstants::INVALID_INDEX; int64_t lowest_cost = NumericLimits::Maximum(); vector candidate_functions; - for (idx_t f_idx = 0; f_idx < functions.size(); f_idx++) { - auto &func = functions[f_idx]; + for (idx_t f_idx = 0; f_idx < functions.functions.size(); f_idx++) { + auto &func = functions.functions[f_idx]; // check the arguments of the function int64_t cost = BindFunctionCost(func, arguments); if (cost < 0) { @@ -92090,7 +101311,7 @@ static vector BindFunctionsFromArguments(const string &name, vector &f // no matching function was found, throw an error string call_str = Function::CallToString(name, arguments); string candidate_str = ""; - for (auto &f : functions) { + for (auto &f : functions.functions) { candidate_str += "\t" + f.ToString() + "\n"; } error = StringUtil::Format("No function matches the given name and argument types '%s'. You might need to add " @@ -92103,15 +101324,16 @@ static vector BindFunctionsFromArguments(const string &name, vector &f } template -static idx_t MultipleCandidateException(const string &name, vector &functions, vector &candidate_functions, - vector &arguments, string &error) { - D_ASSERT(functions.size() > 1); +static idx_t MultipleCandidateException(const string &name, FunctionSet &functions, + vector &candidate_functions, const vector &arguments, + string &error) { + D_ASSERT(functions.functions.size() > 1); // there are multiple possible function definitions // throw an exception explaining which overloads are there string call_str = Function::CallToString(name, arguments); string candidate_str = ""; for (auto &conf : candidate_functions) { - auto &f = functions[conf]; + T f = functions.GetFunctionByOffset(conf); candidate_str += "\t" + f.ToString() + "\n"; } error = StringUtil::Format("Could not choose a best candidate function for the function call \"%s\". In order to " @@ -92121,23 +101343,20 @@ static idx_t MultipleCandidateException(const string &name, vector &functions } template -static idx_t BindFunctionFromArguments(const string &name, vector &functions, vector &arguments, - string &error, bool &cast_parameters) { +static idx_t BindFunctionFromArguments(const string &name, FunctionSet &functions, + const vector &arguments, string &error) { auto candidate_functions = BindFunctionsFromArguments(name, functions, arguments, error); if (candidate_functions.empty()) { // no candidates return DConstants::INVALID_INDEX; } - cast_parameters = true; if (candidate_functions.size() > 1) { // multiple candidates, check if there are any unknown arguments bool has_parameters = false; for (auto &arg_type : arguments) { if (arg_type.id() == LogicalTypeId::UNKNOWN) { - //! there are! disable casting of parameters, but do not throw an error - cast_parameters = false; - has_parameters = true; - break; + //! there are! we could not resolve parameters in this case + throw ParameterNotResolvedException(); } } if (!has_parameters) { @@ -92147,39 +101366,31 @@ static idx_t BindFunctionFromArguments(const string &name, vector &functions, return candidate_functions[0]; } -idx_t Function::BindFunction(const string &name, vector &functions, vector &arguments, - string &error, bool &cast_parameters) { - return BindFunctionFromArguments(name, functions, arguments, error, cast_parameters); -} - -idx_t Function::BindFunction(const string &name, vector &functions, vector &arguments, - string &error, bool &cast_parameters) { - return BindFunctionFromArguments(name, functions, arguments, error, cast_parameters); +idx_t Function::BindFunction(const string &name, ScalarFunctionSet &functions, const vector &arguments, + string &error) { + return BindFunctionFromArguments(name, functions, arguments, error); } -idx_t Function::BindFunction(const string &name, vector &functions, vector &arguments, +idx_t Function::BindFunction(const string &name, AggregateFunctionSet &functions, const vector &arguments, string &error) { - bool cast_parameters; - return BindFunction(name, functions, arguments, error, cast_parameters); + return BindFunctionFromArguments(name, functions, arguments, error); } -idx_t Function::BindFunction(const string &name, vector &functions, vector &arguments, +idx_t Function::BindFunction(const string &name, TableFunctionSet &functions, const vector &arguments, string &error) { - bool cast_parameters; - return BindFunctionFromArguments(name, functions, arguments, error, cast_parameters); + return BindFunctionFromArguments(name, functions, arguments, error); } -idx_t Function::BindFunction(const string &name, vector &functions, PragmaInfo &info, string &error) { +idx_t Function::BindFunction(const string &name, PragmaFunctionSet &functions, PragmaInfo &info, string &error) { vector types; for (auto &value : info.parameters) { types.push_back(value.type()); } - bool cast_parameters; - idx_t entry = BindFunctionFromArguments(name, functions, types, error, cast_parameters); + idx_t entry = BindFunctionFromArguments(name, functions, types, error); if (entry == DConstants::INVALID_INDEX) { throw BinderException(error); } - auto &candidate_function = functions[entry]; + auto candidate_function = functions.GetFunctionByOffset(entry); // cast the input parameters for (idx_t i = 0; i < info.parameters.size(); i++) { auto target_type = @@ -92198,24 +101409,35 @@ vector GetLogicalTypesFromExpressions(vector return types; } -idx_t Function::BindFunction(const string &name, vector &functions, - vector> &arguments, string &error, bool &cast_parameters) { +idx_t Function::BindFunction(const string &name, ScalarFunctionSet &functions, + vector> &arguments, string &error) { auto types = GetLogicalTypesFromExpressions(arguments); - return Function::BindFunction(name, functions, types, error, cast_parameters); + return Function::BindFunction(name, functions, types, error); } -idx_t Function::BindFunction(const string &name, vector &functions, +idx_t Function::BindFunction(const string &name, AggregateFunctionSet &functions, vector> &arguments, string &error) { auto types = GetLogicalTypesFromExpressions(arguments); return Function::BindFunction(name, functions, types, error); } -idx_t Function::BindFunction(const string &name, vector &functions, - vector> &arguments, string &error) { +idx_t Function::BindFunction(const string &name, TableFunctionSet &functions, vector> &arguments, + string &error) { auto types = GetLogicalTypesFromExpressions(arguments); return Function::BindFunction(name, functions, types, error); } +void Function::EraseArgument(SimpleFunction &bound_function, vector> &arguments, + idx_t argument_index) { + if (bound_function.original_arguments.empty()) { + bound_function.original_arguments = bound_function.arguments; + } + D_ASSERT(arguments.size() == bound_function.arguments.size()); + D_ASSERT(argument_index < arguments.size()); + arguments.erase(arguments.begin() + argument_index); + bound_function.arguments.erase(bound_function.arguments.begin() + argument_index); +} + enum class LogicalTypeComparisonResult { IDENTICAL_TYPE, TARGET_IS_ANY, DIFFERENT_TYPES }; LogicalTypeComparisonResult RequiresCast(const LogicalType &source_type, const LogicalType &target_type) { @@ -92231,13 +101453,12 @@ LogicalTypeComparisonResult RequiresCast(const LogicalType &source_type, const L return LogicalTypeComparisonResult::DIFFERENT_TYPES; } -void BaseScalarFunction::CastToFunctionArguments(vector> &children, - bool cast_parameter_expressions) { +void BaseScalarFunction::CastToFunctionArguments(vector> &children) { for (idx_t i = 0; i < children.size(); i++) { auto target_type = i < this->arguments.size() ? this->arguments[i] : this->varargs; target_type.Verify(); - // check if the source type is a paramter, and we have disabled casting of parameters - if (children[i]->return_type.id() == LogicalTypeId::UNKNOWN && !cast_parameter_expressions) { + // don't cast lambda children, they get removed anyways + if (children[i]->return_type.id() == LogicalTypeId::LAMBDA) { continue; } // check if the type of child matches the type of function argument @@ -92251,43 +101472,48 @@ void BaseScalarFunction::CastToFunctionArguments(vector> } } -unique_ptr ScalarFunction::BindScalarFunction(ClientContext &context, const string &schema, - const string &name, - vector> children, - string &error, bool is_operator) { +unique_ptr ScalarFunction::BindScalarFunction(ClientContext &context, const string &schema, + const string &name, vector> children, + string &error, bool is_operator, Binder *binder) { // bind the function auto function = Catalog::GetCatalog(context).GetEntry(context, CatalogType::SCALAR_FUNCTION_ENTRY, schema, name); D_ASSERT(function && function->type == CatalogType::SCALAR_FUNCTION_ENTRY); return ScalarFunction::BindScalarFunction(context, (ScalarFunctionCatalogEntry &)*function, move(children), error, - is_operator); + is_operator, binder); } -unique_ptr ScalarFunction::BindScalarFunction(ClientContext &context, - ScalarFunctionCatalogEntry &func, - vector> children, - string &error, bool is_operator) { +unique_ptr ScalarFunction::BindScalarFunction(ClientContext &context, ScalarFunctionCatalogEntry &func, + vector> children, string &error, + bool is_operator, Binder *binder) { // bind the function - bool cast_parameters; - idx_t best_function = Function::BindFunction(func.name, func.functions, children, error, cast_parameters); + idx_t best_function = Function::BindFunction(func.name, func.functions, children, error); if (best_function == DConstants::INVALID_INDEX) { return nullptr; } // found a matching function! - auto &bound_function = func.functions[best_function]; - return ScalarFunction::BindScalarFunction(context, bound_function, move(children), is_operator, cast_parameters); + auto bound_function = func.functions.GetFunctionByOffset(best_function); + + if (bound_function.null_handling == FunctionNullHandling::DEFAULT_NULL_HANDLING) { + for (auto &child : children) { + if (child->return_type == LogicalTypeId::SQLNULL) { + return make_unique(Value(LogicalType::SQLNULL)); + } + } + } + return ScalarFunction::BindScalarFunction(context, bound_function, move(children), is_operator); } unique_ptr ScalarFunction::BindScalarFunction(ClientContext &context, ScalarFunction bound_function, vector> children, - bool is_operator, bool cast_parameters) { + bool is_operator) { unique_ptr bind_info; if (bound_function.bind) { bind_info = bound_function.bind(context, bound_function, children); } // check if we need to add casts to the children - bound_function.CastToFunctionArguments(children, cast_parameters); + bound_function.CastToFunctionArguments(children); // now create the function auto return_type = bound_function.return_type; @@ -92295,9 +101521,10 @@ unique_ptr ScalarFunction::BindScalarFunction(ClientCon move(bind_info), is_operator); } -unique_ptr AggregateFunction::BindAggregateFunction( - ClientContext &context, AggregateFunction bound_function, vector> children, - unique_ptr filter, bool is_distinct, unique_ptr order_bys, bool cast_parameters) { +unique_ptr +AggregateFunction::BindAggregateFunction(ClientContext &context, AggregateFunction bound_function, + vector> children, unique_ptr filter, + bool is_distinct, unique_ptr order_bys) { unique_ptr bind_info; if (bound_function.bind) { bind_info = bound_function.bind(context, bound_function, children); @@ -92306,7 +101533,7 @@ unique_ptr AggregateFunction::BindAggregateFunction( } // check if we need to add casts to the children - bound_function.CastToFunctionArguments(children, cast_parameters); + bound_function.CastToFunctionArguments(children); // Special case: for ORDER BY aggregates, we wrap the aggregate function in a SortedAggregateFunction // The children are the sort clauses and the binding contains the ordering data. @@ -92321,6 +101548,68 @@ unique_ptr AggregateFunction::BindAggregateFunction( } // namespace duckdb +namespace duckdb { + +ScalarFunctionSet::ScalarFunctionSet(string name) : FunctionSet(move(name)) { +} + +ScalarFunction ScalarFunctionSet::GetFunctionByArguments(const vector &arguments) { + string error; + idx_t index = Function::BindFunction(name, *this, arguments, error); + if (index == DConstants::INVALID_INDEX) { + throw InternalException("Failed to find function %s(%s)\n%s", name, StringUtil::ToString(arguments, ","), + error); + } + return GetFunctionByOffset(index); +} + +AggregateFunctionSet::AggregateFunctionSet(string name) : FunctionSet(move(name)) { +} + +AggregateFunction AggregateFunctionSet::GetFunctionByArguments(const vector &arguments) { + string error; + idx_t index = Function::BindFunction(name, *this, arguments, error); + if (index == DConstants::INVALID_INDEX) { + // check if the arguments are a prefix of any of the arguments + // this is used for functions such as quantile or string_agg that delete part of their arguments during bind + // FIXME: we should come up with a better solution here + for (auto &func : functions) { + if (arguments.size() >= func.arguments.size()) { + continue; + } + bool is_prefix = true; + for (idx_t k = 0; k < arguments.size(); k++) { + if (arguments[k] != func.arguments[k]) { + is_prefix = false; + break; + } + } + if (is_prefix) { + return func; + } + } + throw InternalException("Failed to find function %s(%s)\n%s", name, StringUtil::ToString(arguments, ","), + error); + } + return GetFunctionByOffset(index); +} + +TableFunctionSet::TableFunctionSet(string name) : FunctionSet(move(name)) { +} + +TableFunction TableFunctionSet::GetFunctionByArguments(const vector &arguments) { + string error; + idx_t index = Function::BindFunction(name, *this, arguments, error); + if (index == DConstants::INVALID_INDEX) { + throw InternalException("Failed to find function %s(%s)\n%s", name, StringUtil::ToString(arguments, ","), + error); + } + return GetFunctionByOffset(index); +} + +} // namespace duckdb + + @@ -92343,7 +101632,8 @@ string MacroFunction::ValidateArguments(MacroFunction ¯o_def, const string & // separate positional and default arguments for (auto &arg : function_expr.children) { - if (arg->type == ExpressionType::VALUE_CONSTANT && !arg->alias.empty()) { + if ((arg->type == ExpressionType::VALUE_CONSTANT || arg->type == ExpressionType::VALUE_PARAMETER) && + !arg->alias.empty()) { // default argument if (macro_def.default_parameters.find(arg->alias) == macro_def.default_parameters.end()) { return StringUtil::Format("Macro %s does not have default parameter %s!", name, arg->alias); @@ -92397,6 +101687,18 @@ void MacroFunction::CopyProperties(MacroFunction &other) { } } +string MacroFunction::ToSQL(const string &schema, const string &name) { + vector param_strings; + for (auto ¶m : parameters) { + param_strings.push_back(param->ToString()); + } + for (auto &named_param : default_parameters) { + param_strings.push_back(StringUtil::Format("%s := %s", named_param.first, named_param.second->ToString())); + } + + return StringUtil::Format("CREATE MACRO %s.%s(%s) AS ", schema, name, StringUtil::Join(param_strings, ", ")); +} + } // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -92439,13 +101741,13 @@ namespace duckdb { static void PragmaEnableProfilingStatement(ClientContext &context, const FunctionParameters ¶meters) { auto &config = ClientConfig::GetConfig(context); - config.profiler_print_format = ProfilerPrintFormat::QUERY_TREE; config.enable_profiler = true; + config.emit_profiler_output = true; } void RegisterEnableProfiling(BuiltinFunctions &set) { - vector functions; - functions.push_back(PragmaFunction::PragmaStatement(string(), PragmaEnableProfilingStatement)); + PragmaFunctionSet functions(""); + functions.AddFunction(PragmaFunction::PragmaStatement(string(), PragmaEnableProfilingStatement)); set.AddFunction("enable_profile", functions); set.AddFunction("enable_profiling", functions); @@ -92454,7 +101756,6 @@ void RegisterEnableProfiling(BuiltinFunctions &set) { static void PragmaDisableProfiling(ClientContext &context, const FunctionParameters ¶meters) { auto &config = ClientConfig::GetConfig(context); config.enable_profiler = false; - config.profiler_print_format = ProfilerPrintFormat::NONE; } static void PragmaEnableProgressBar(ClientContext &context, const FunctionParameters ¶meters) { @@ -92475,10 +101776,28 @@ static void PragmaDisablePrintProgressBar(ClientContext &context, const Function static void PragmaEnableVerification(ClientContext &context, const FunctionParameters ¶meters) { ClientConfig::GetConfig(context).query_verification_enabled = true; + ClientConfig::GetConfig(context).verify_serializer = true; } static void PragmaDisableVerification(ClientContext &context, const FunctionParameters ¶meters) { ClientConfig::GetConfig(context).query_verification_enabled = false; + ClientConfig::GetConfig(context).verify_serializer = false; +} + +static void PragmaVerifySerializer(ClientContext &context, const FunctionParameters ¶meters) { + ClientConfig::GetConfig(context).verify_serializer = true; +} + +static void PragmaDisableVerifySerializer(ClientContext &context, const FunctionParameters ¶meters) { + ClientConfig::GetConfig(context).verify_serializer = false; +} + +static void PragmaEnableExternalVerification(ClientContext &context, const FunctionParameters ¶meters) { + ClientConfig::GetConfig(context).verify_external = true; +} + +static void PragmaDisableExternalVerification(ClientContext &context, const FunctionParameters ¶meters) { + ClientConfig::GetConfig(context).verify_external = false; } static void PragmaEnableForceParallelism(ClientContext &context, const FunctionParameters ¶meters) { @@ -92490,7 +101809,7 @@ static void PragmaEnableForceIndexJoin(ClientContext &context, const FunctionPar } static void PragmaForceCheckpoint(ClientContext &context, const FunctionParameters ¶meters) { - DBConfig::GetConfig(context).force_checkpoint = true; + DBConfig::GetConfig(context).options.force_checkpoint = true; } static void PragmaDisableForceParallelism(ClientContext &context, const FunctionParameters ¶meters) { @@ -92498,19 +101817,19 @@ static void PragmaDisableForceParallelism(ClientContext &context, const Function } static void PragmaEnableObjectCache(ClientContext &context, const FunctionParameters ¶meters) { - DBConfig::GetConfig(context).object_cache_enable = true; + DBConfig::GetConfig(context).options.object_cache_enable = true; } static void PragmaDisableObjectCache(ClientContext &context, const FunctionParameters ¶meters) { - DBConfig::GetConfig(context).object_cache_enable = false; + DBConfig::GetConfig(context).options.object_cache_enable = false; } static void PragmaEnableCheckpointOnShutdown(ClientContext &context, const FunctionParameters ¶meters) { - DBConfig::GetConfig(context).checkpoint_on_shutdown = true; + DBConfig::GetConfig(context).options.checkpoint_on_shutdown = true; } static void PragmaDisableCheckpointOnShutdown(ClientContext &context, const FunctionParameters ¶meters) { - DBConfig::GetConfig(context).checkpoint_on_shutdown = false; + DBConfig::GetConfig(context).options.checkpoint_on_shutdown = false; } static void PragmaEnableOptimizer(ClientContext &context, const FunctionParameters ¶meters) { @@ -92530,6 +101849,12 @@ void PragmaFunctions::RegisterFunction(BuiltinFunctions &set) { set.AddFunction(PragmaFunction::PragmaStatement("enable_verification", PragmaEnableVerification)); set.AddFunction(PragmaFunction::PragmaStatement("disable_verification", PragmaDisableVerification)); + set.AddFunction(PragmaFunction::PragmaStatement("verify_external", PragmaEnableExternalVerification)); + set.AddFunction(PragmaFunction::PragmaStatement("disable_verify_external", PragmaDisableExternalVerification)); + + set.AddFunction(PragmaFunction::PragmaStatement("verify_serializer", PragmaVerifySerializer)); + set.AddFunction(PragmaFunction::PragmaStatement("disable_verify_serializer", PragmaDisableVerifySerializer)); + set.AddFunction(PragmaFunction::PragmaStatement("verify_parallelism", PragmaEnableForceParallelism)); set.AddFunction(PragmaFunction::PragmaStatement("disable_verify_parallelism", PragmaDisableForceParallelism)); @@ -92615,7 +101940,7 @@ string PragmaVersion(ClientContext &context, const FunctionParameters ¶meter string PragmaImportDatabase(ClientContext &context, const FunctionParameters ¶meters) { auto &config = DBConfig::GetConfig(context); - if (!config.enable_external_access) { + if (!config.options.enable_external_access) { throw PermissionException("Import is disabled through configuration"); } auto &fs = FileSystem::GetFileSystem(context); @@ -92987,16 +102312,16 @@ unique_ptr BindCurrentTime(ClientContext &context, ScalarFunction } void CurrentTimeFun::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction(ScalarFunction("current_time", {}, LogicalType::TIME, CurrentTimeFunction, false, BindCurrentTime)); + set.AddFunction(ScalarFunction("get_current_time", {}, LogicalType::TIME, CurrentTimeFunction, BindCurrentTime)); } void CurrentDateFun::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction(ScalarFunction("current_date", {}, LogicalType::DATE, CurrentDateFunction, false, BindCurrentTime)); + set.AddFunction(ScalarFunction("current_date", {}, LogicalType::DATE, CurrentDateFunction, BindCurrentTime)); } void CurrentTimestampFun::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction({"now", "current_timestamp"}, ScalarFunction({}, LogicalType::TIMESTAMP, CurrentTimestampFunction, - false, false, BindCurrentTime)); + set.AddFunction({"now", "get_current_timestamp"}, + ScalarFunction({}, LogicalType::TIMESTAMP, CurrentTimestampFunction, BindCurrentTime)); } } // namespace duckdb @@ -93452,6 +102777,7 @@ void DateDiffFun::RegisterFunction(BuiltinFunctions &set) { + namespace duckdb { bool TryGetDatePartSpecifier(const string &specifier_p, DatePartSpecifier &result) { @@ -94651,10 +103977,10 @@ void AddGenericDatePartOperator(BuiltinFunctions &set, const string &name, scala scalar_function_t ts_func, scalar_function_t interval_func, function_statistics_t date_stats, function_statistics_t ts_stats) { ScalarFunctionSet operator_set(name); - operator_set.AddFunction(ScalarFunction({LogicalType::DATE}, LogicalType::BIGINT, move(date_func), false, false, - nullptr, nullptr, date_stats)); - operator_set.AddFunction(ScalarFunction({LogicalType::TIMESTAMP}, LogicalType::BIGINT, move(ts_func), false, false, - nullptr, nullptr, ts_stats)); + operator_set.AddFunction( + ScalarFunction({LogicalType::DATE}, LogicalType::BIGINT, move(date_func), nullptr, nullptr, date_stats)); + operator_set.AddFunction( + ScalarFunction({LogicalType::TIMESTAMP}, LogicalType::BIGINT, move(ts_func), nullptr, nullptr, ts_stats)); operator_set.AddFunction(ScalarFunction({LogicalType::INTERVAL}, LogicalType::BIGINT, move(interval_func))); set.AddFunction(operator_set); } @@ -94672,13 +103998,13 @@ void AddGenericTimePartOperator(BuiltinFunctions &set, const string &name, scala function_statistics_t date_stats, function_statistics_t ts_stats, function_statistics_t time_stats) { ScalarFunctionSet operator_set(name); - operator_set.AddFunction(ScalarFunction({LogicalType::DATE}, LogicalType::BIGINT, move(date_func), false, false, - nullptr, nullptr, date_stats)); - operator_set.AddFunction(ScalarFunction({LogicalType::TIMESTAMP}, LogicalType::BIGINT, move(ts_func), false, false, - nullptr, nullptr, ts_stats)); + operator_set.AddFunction( + ScalarFunction({LogicalType::DATE}, LogicalType::BIGINT, move(date_func), nullptr, nullptr, date_stats)); + operator_set.AddFunction( + ScalarFunction({LogicalType::TIMESTAMP}, LogicalType::BIGINT, move(ts_func), nullptr, nullptr, ts_stats)); operator_set.AddFunction(ScalarFunction({LogicalType::INTERVAL}, LogicalType::BIGINT, move(interval_func))); - operator_set.AddFunction(ScalarFunction({LogicalType::TIME}, LogicalType::BIGINT, move(time_func), false, false, - nullptr, nullptr, time_stats)); + operator_set.AddFunction( + ScalarFunction({LogicalType::TIME}, LogicalType::BIGINT, move(time_func), nullptr, nullptr, time_stats)); set.AddFunction(operator_set); } @@ -94740,6 +104066,9 @@ struct StructDatePart { static unique_ptr Bind(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { // collect names and deconflict, construct return type + if (arguments[0]->HasParameter()) { + throw ParameterNotResolvedException(); + } if (!arguments[0]->IsFoldable()) { throw BinderException("%s can only take constant lists of part names", bound_function.name); } @@ -94771,8 +104100,7 @@ struct StructDatePart { throw BinderException("%s can only take constant lists of part names", bound_function.name); } - arguments.erase(arguments.begin()); - bound_function.arguments.erase(bound_function.arguments.begin()); + Function::EraseArgument(bound_function, arguments, 0); bound_function.return_type = LogicalType::STRUCT(move(struct_children)); return make_unique(bound_function.return_type, part_codes); } @@ -94825,8 +104153,8 @@ struct StructDatePart { } } } else { - VectorData rdata; - input.Orrify(count, rdata); + UnifiedVectorFormat rdata; + input.ToUnifiedFormat(count, rdata); const auto &arg_valid = rdata.validity; auto tdata = (const INPUT_TYPE *)rdata.data; @@ -94885,11 +104213,29 @@ struct StructDatePart { result.Verify(count); } + static void SerializeFunction(FieldWriter &writer, const FunctionData *bind_data_p, + const ScalarFunction &function) { + D_ASSERT(bind_data_p); + auto &info = (BindData &)*bind_data_p; + writer.WriteSerializable(info.stype); + writer.WriteList(info.part_codes); + } + + static unique_ptr DeserializeFunction(ClientContext &context, FieldReader &reader, + ScalarFunction &bound_function) { + auto stype = reader.ReadRequiredSerializable(); + auto part_codes = reader.ReadRequiredList(); + return make_unique(move(stype), move(part_codes)); + } + template static ScalarFunction GetFunction(const LogicalType &temporal_type) { auto part_type = LogicalType::LIST(LogicalType::VARCHAR); auto result_type = LogicalType::STRUCT({}); - return ScalarFunction({part_type, temporal_type}, result_type, Function, false, false, Bind); + ScalarFunction result({part_type, temporal_type}, result_type, Function, Bind); + result.serialize = SerializeFunction; + result.deserialize = DeserializeFunction; + return result; } }; @@ -95442,18 +104788,22 @@ void DateSubFun::RegisterFunction(BuiltinFunctions &set) { + namespace duckdb { struct DateTrunc { + template + static inline TR UnaryFunction(TA input) { + if (Value::IsFinite(input)) { + return OP::template Operation(input); + } else { + return Cast::template Operation(input); + } + } + template static inline void UnaryExecute(Vector &left, Vector &result, idx_t count) { - UnaryExecutor::Execute(left, result, count, [&](TA input) { - if (Value::IsFinite(input)) { - return OP::template Operation(input); - } else { - return Cast::template Operation(input); - } - }); + UnaryExecutor::Execute(left, result, count, UnaryFunction); } struct MillenniumOperator { @@ -96016,6 +105366,82 @@ static void DateTruncFunction(DataChunk &args, ExpressionState &state, Vector &r } } +template +static unique_ptr DateTruncStatistics(vector> &child_stats) { + // we can only propagate date stats if the child has stats + if (!child_stats[1]) { + return nullptr; + } + auto &nstats = (NumericStatistics &)*child_stats[1]; + if (nstats.min.IsNull() || nstats.max.IsNull()) { + return nullptr; + } + // run the operator on both the min and the max, this gives us the [min, max] bound + auto min = nstats.min.GetValueUnsafe(); + auto max = nstats.max.GetValueUnsafe(); + if (min > max) { + return nullptr; + } + + // Infinite values are unmodified + auto min_part = DateTrunc::UnaryFunction(min); + auto max_part = DateTrunc::UnaryFunction(max); + + auto min_value = Value::CreateValue(min_part); + auto max_value = Value::CreateValue(max_part); + auto result = make_unique(min_value.type(), min_value, max_value, StatisticsType::LOCAL_STATS); + if (child_stats[0]->validity_stats) { + result->validity_stats = child_stats[1]->validity_stats->Copy(); + } + return move(result); +} + +template +static unique_ptr PropagateDateTruncStatistics(ClientContext &context, FunctionStatisticsInput &input) { + return DateTruncStatistics(input.child_stats); +} + +template +static function_statistics_t DateTruncStats(DatePartSpecifier type) { + switch (type) { + case DatePartSpecifier::MILLENNIUM: + return PropagateDateTruncStatistics; + case DatePartSpecifier::CENTURY: + return PropagateDateTruncStatistics; + case DatePartSpecifier::DECADE: + return PropagateDateTruncStatistics; + case DatePartSpecifier::YEAR: + return PropagateDateTruncStatistics; + case DatePartSpecifier::QUARTER: + return PropagateDateTruncStatistics; + case DatePartSpecifier::MONTH: + return PropagateDateTruncStatistics; + case DatePartSpecifier::WEEK: + case DatePartSpecifier::YEARWEEK: + return PropagateDateTruncStatistics; + case DatePartSpecifier::ISOYEAR: + return PropagateDateTruncStatistics; + case DatePartSpecifier::DAY: + case DatePartSpecifier::DOW: + case DatePartSpecifier::ISODOW: + case DatePartSpecifier::DOY: + return PropagateDateTruncStatistics; + case DatePartSpecifier::HOUR: + return PropagateDateTruncStatistics; + case DatePartSpecifier::MINUTE: + return PropagateDateTruncStatistics; + case DatePartSpecifier::SECOND: + case DatePartSpecifier::EPOCH: + return PropagateDateTruncStatistics; + case DatePartSpecifier::MILLISECONDS: + return PropagateDateTruncStatistics; + case DatePartSpecifier::MICROSECONDS: + return PropagateDateTruncStatistics; + default: + throw NotImplementedException("Specifier type not implemented for DATETRUNC statistics"); + } +} + static unique_ptr DateTruncBind(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { if (!arguments[0]->IsFoldable()) { @@ -96043,19 +105469,31 @@ static unique_ptr DateTruncBind(ClientContext &context, ScalarFunc case DatePartSpecifier::DOW: case DatePartSpecifier::ISODOW: case DatePartSpecifier::DOY: - switch (arguments[1]->return_type.id()) { + switch (bound_function.arguments[1].id()) { case LogicalType::TIMESTAMP: bound_function.function = DateTruncFunction; + bound_function.statistics = DateTruncStats(part_code); break; case LogicalType::DATE: bound_function.function = DateTruncFunction; + bound_function.statistics = DateTruncStats(part_code); break; default: - break; + throw NotImplementedException("Temporal argument type for DATETRUNC"); } bound_function.return_type = LogicalType::DATE; break; default: + switch (bound_function.arguments[1].id()) { + case LogicalType::TIMESTAMP: + bound_function.statistics = DateTruncStats(part_code); + break; + case LogicalType::DATE: + bound_function.statistics = DateTruncStats(part_code); + break; + default: + throw NotImplementedException("Temporal argument type for DATETRUNC"); + } break; } @@ -96065,9 +105503,9 @@ static unique_ptr DateTruncBind(ClientContext &context, ScalarFunc void DateTruncFun::RegisterFunction(BuiltinFunctions &set) { ScalarFunctionSet date_trunc("date_trunc"); date_trunc.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::TIMESTAMP}, LogicalType::TIMESTAMP, - DateTruncFunction, false, false, DateTruncBind)); + DateTruncFunction, DateTruncBind)); date_trunc.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::DATE}, LogicalType::TIMESTAMP, - DateTruncFunction, false, false, DateTruncBind)); + DateTruncFunction, DateTruncBind)); date_trunc.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::INTERVAL}, LogicalType::INTERVAL, DateTruncFunction)); set.AddFunction(date_trunc); @@ -96185,9 +105623,9 @@ struct SenaryExecutor { auto &result_validity = FlatVector::Validity(result); bool all_valid = true; - vector vdata(NCOLS); + vector vdata(NCOLS); for (size_t c = 0; c < NCOLS; ++c) { - input.data[c].Orrify(count, vdata[c]); + input.data[c].ToUnifiedFormat(count, vdata[c]); all_valid = all_valid && vdata[c].validity.AllValid(); } @@ -96343,10 +105781,6 @@ void MakeDateFun::RegisterFunction(BuiltinFunctions &set) { - - - - #include namespace duckdb { @@ -96751,6 +106185,9 @@ string StrfTimeFormat::Format(timestamp_t timestamp, const string &format_str) { } string StrTimeFormat::ParseFormatSpecifier(const string &format_string, StrTimeFormat &format) { + if (format_string.empty()) { + return "Empty format string"; + } format.specifiers.clear(); format.literals.clear(); format.numeric_width.clear(); @@ -96940,10 +106377,15 @@ struct StrfTimeBindData : public FunctionData { template static unique_ptr StrfTimeBindFunction(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { - if (!arguments[REVERSED ? 0 : 1]->IsFoldable()) { + auto format_idx = REVERSED ? 0 : 1; + auto &format_arg = arguments[format_idx]; + if (format_arg->HasParameter()) { + throw ParameterNotResolvedException(); + } + if (!format_arg->IsFoldable()) { throw InvalidInputException("strftime format must be a constant"); } - Value options_str = ExpressionExecutor::EvaluateScalar(*arguments[REVERSED ? 0 : 1]); + Value options_str = ExpressionExecutor::EvaluateScalar(*format_arg); auto format_string = options_str.GetValue(); StrfTimeFormat format; if (!options_str.IsNull()) { @@ -96955,6 +106397,25 @@ static unique_ptr StrfTimeBindFunction(ClientContext &context, Sca return make_unique(format, format_string); } +void StrfTimeFormat::ConvertDateVector(Vector &input, Vector &result, idx_t count) { + D_ASSERT(input.GetType().id() == LogicalTypeId::DATE); + D_ASSERT(result.GetType().id() == LogicalTypeId::VARCHAR); + UnaryExecutor::ExecuteWithNulls(input, result, count, + [&](date_t input, ValidityMask &mask, idx_t idx) { + if (Date::IsFinite(input)) { + dtime_t time(0); + idx_t len = GetLength(input, time, 0, nullptr); + string_t target = StringVector::EmptyString(result, len); + FormatString(input, time, target.GetDataWriteable()); + target.Finalize(); + return target; + } else { + mask.SetInvalid(idx); + return string_t(); + } + }); +} + template static void StrfTimeFunctionDate(DataChunk &args, ExpressionState &state, Vector &result) { auto &func_expr = (BoundFunctionExpression &)state.expr; @@ -96965,13 +106426,21 @@ static void StrfTimeFunctionDate(DataChunk &args, ExpressionState &state, Vector ConstantVector::SetNull(result, true); return; } - UnaryExecutor::ExecuteWithNulls( - args.data[REVERSED ? 1 : 0], result, args.size(), [&](date_t input, ValidityMask &mask, idx_t idx) { - if (Date::IsFinite(input)) { - dtime_t time(0); - idx_t len = info.format.GetLength(input, time, 0, nullptr); + info.format.ConvertDateVector(args.data[REVERSED ? 1 : 0], result, args.size()); +} + +void StrfTimeFormat::ConvertTimestampVector(Vector &input, Vector &result, idx_t count) { + D_ASSERT(input.GetType().id() == LogicalTypeId::TIMESTAMP); + D_ASSERT(result.GetType().id() == LogicalTypeId::VARCHAR); + UnaryExecutor::ExecuteWithNulls( + input, result, count, [&](timestamp_t input, ValidityMask &mask, idx_t idx) { + if (Timestamp::IsFinite(input)) { + date_t date; + dtime_t time; + Timestamp::Convert(input, date, time); + idx_t len = GetLength(date, time, 0, nullptr); string_t target = StringVector::EmptyString(result, len); - info.format.FormatString(input, time, target.GetDataWriteable()); + FormatString(date, time, target.GetDataWriteable()); target.Finalize(); return target; } else { @@ -96991,39 +106460,23 @@ static void StrfTimeFunctionTimestamp(DataChunk &args, ExpressionState &state, V ConstantVector::SetNull(result, true); return; } - - UnaryExecutor::ExecuteWithNulls( - args.data[REVERSED ? 1 : 0], result, args.size(), [&](timestamp_t input, ValidityMask &mask, idx_t idx) { - if (Timestamp::IsFinite(input)) { - date_t date; - dtime_t time; - Timestamp::Convert(input, date, time); - idx_t len = info.format.GetLength(date, time, 0, nullptr); - string_t target = StringVector::EmptyString(result, len); - info.format.FormatString(date, time, target.GetDataWriteable()); - target.Finalize(); - return target; - } else { - mask.SetInvalid(idx); - return string_t(); - } - }); + info.format.ConvertTimestampVector(args.data[REVERSED ? 1 : 0], result, args.size()); } void StrfTimeFun::RegisterFunction(BuiltinFunctions &set) { ScalarFunctionSet strftime("strftime"); strftime.AddFunction(ScalarFunction({LogicalType::DATE, LogicalType::VARCHAR}, LogicalType::VARCHAR, - StrfTimeFunctionDate, false, false, StrfTimeBindFunction)); + StrfTimeFunctionDate, StrfTimeBindFunction)); strftime.AddFunction(ScalarFunction({LogicalType::TIMESTAMP, LogicalType::VARCHAR}, LogicalType::VARCHAR, - StrfTimeFunctionTimestamp, false, false, StrfTimeBindFunction)); + StrfTimeFunctionTimestamp, StrfTimeBindFunction)); strftime.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::DATE}, LogicalType::VARCHAR, - StrfTimeFunctionDate, false, false, StrfTimeBindFunction)); + StrfTimeFunctionDate, StrfTimeBindFunction)); strftime.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::TIMESTAMP}, LogicalType::VARCHAR, - StrfTimeFunctionTimestamp, false, false, StrfTimeBindFunction)); + StrfTimeFunctionTimestamp, StrfTimeBindFunction)); set.AddFunction(strftime); } @@ -97129,6 +106582,7 @@ bool StrpTimeFormat::Parse(string_t str, ParseResult &result) { uint64_t yearday = 0; for (idx_t i = 0;; i++) { + D_ASSERT(i < literals.size()); // first compare the literal const auto &literal = literals[i]; for (size_t l = 0; l < literal.size();) { @@ -97513,13 +106967,19 @@ struct StrpTimeBindData : public FunctionData { static unique_ptr StrpTimeBindFunction(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { + if (arguments[1]->HasParameter()) { + throw ParameterNotResolvedException(); + } if (!arguments[1]->IsFoldable()) { throw InvalidInputException("strptime format must be a constant"); } Value options_str = ExpressionExecutor::EvaluateScalar(*arguments[1]); string format_string = options_str.ToString(); StrpTimeFormat format; - if (!options_str.IsNull() && options_str.type().id() == LogicalTypeId::VARCHAR) { + if (!options_str.IsNull()) { + if (options_str.type().id() != LogicalTypeId::VARCHAR) { + throw InvalidInputException("strptime format must be a string"); + } format.format_specifier = format_string; string error = StrTimeFormat::ParseFormatSpecifier(format_string, format); if (!error.empty()) { @@ -97623,8 +107083,10 @@ static void StrpTimeFunction(DataChunk &args, ExpressionState &state, Vector &re void StrpTimeFun::RegisterFunction(BuiltinFunctions &set) { ScalarFunctionSet strptime("strptime"); - strptime.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::TIMESTAMP, - StrpTimeFunction, false, false, StrpTimeBindFunction)); + auto fun = ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::TIMESTAMP, StrpTimeFunction, + StrpTimeBindFunction); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + strptime.AddFunction(fun); set.AddFunction(strptime); } @@ -97876,8 +107338,15 @@ static void EnumRangeBoundaryFunction(DataChunk &input, ExpressionState &state, result.Reference(val); } +static void CheckEnumParameter(const Expression &expr) { + if (expr.HasParameter()) { + throw ParameterNotResolvedException(); + } +} + unique_ptr BindEnumFunction(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { + CheckEnumParameter(*arguments[0]); if (arguments[0]->return_type.id() != LogicalTypeId::ENUM) { throw BinderException("This function needs an ENUM as an argument"); } @@ -97886,6 +107355,8 @@ unique_ptr BindEnumFunction(ClientContext &context, ScalarFunction unique_ptr BindEnumRangeBoundaryFunction(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { + CheckEnumParameter(*arguments[0]); + CheckEnumParameter(*arguments[1]); if (arguments[0]->return_type.id() != LogicalTypeId::ENUM && arguments[0]->return_type != LogicalType::SQLNULL) { throw BinderException("This function needs an ENUM as an argument"); } @@ -97898,31 +107369,38 @@ unique_ptr BindEnumRangeBoundaryFunction(ClientContext &context, S if (arguments[0]->return_type.id() == LogicalTypeId::ENUM && arguments[1]->return_type.id() == LogicalTypeId::ENUM && arguments[0]->return_type != arguments[1]->return_type) { - throw BinderException("The parameters need to link to ONLY one enum OR be NULL "); } return nullptr; } void EnumFirst::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction(ScalarFunction("enum_first", {LogicalType::ANY}, LogicalType::VARCHAR, EnumFirstFunction, false, - BindEnumFunction)); + auto fun = + ScalarFunction("enum_first", {LogicalType::ANY}, LogicalType::VARCHAR, EnumFirstFunction, BindEnumFunction); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + set.AddFunction(fun); } void EnumLast::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction(ScalarFunction("enum_last", {LogicalType::ANY}, LogicalType::VARCHAR, EnumLastFunction, false, - BindEnumFunction)); + auto fun = + ScalarFunction("enum_last", {LogicalType::ANY}, LogicalType::VARCHAR, EnumLastFunction, BindEnumFunction); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + set.AddFunction(fun); } void EnumRange::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction(ScalarFunction("enum_range", {LogicalType::ANY}, LogicalType::LIST(LogicalType::VARCHAR), - EnumRangeFunction, false, BindEnumFunction)); + auto fun = ScalarFunction("enum_range", {LogicalType::ANY}, LogicalType::LIST(LogicalType::VARCHAR), + EnumRangeFunction, BindEnumFunction); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + set.AddFunction(fun); } void EnumRangeBoundary::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction(ScalarFunction("enum_range_boundary", {LogicalType::ANY, LogicalType::ANY}, - LogicalType::LIST(LogicalType::VARCHAR), EnumRangeBoundaryFunction, false, - BindEnumRangeBoundaryFunction)); + auto fun = ScalarFunction("enum_range_boundary", {LogicalType::ANY, LogicalType::ANY}, + LogicalType::LIST(LogicalType::VARCHAR), EnumRangeBoundaryFunction, + BindEnumRangeBoundaryFunction); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + set.AddFunction(fun); } } // namespace duckdb @@ -97979,9 +107457,10 @@ struct TypeOfFun { }; struct ConstantOrNull { - static ScalarFunction GetFunction(LogicalType return_type); + static ScalarFunction GetFunction(const LogicalType &return_type); static unique_ptr Bind(Value value); static bool IsConstantOrNull(BoundFunctionExpression &expr, const Value &val); + static void RegisterFunction(BuiltinFunctions &set); }; struct CurrentSettingFun { @@ -98018,7 +107497,9 @@ static void AliasFunction(DataChunk &args, ExpressionState &state, Vector &resul } void AliasFun::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction(ScalarFunction("alias", {LogicalType::ANY}, LogicalType::VARCHAR, AliasFunction)); + auto fun = ScalarFunction("alias", {LogicalType::ANY}, LogicalType::VARCHAR, AliasFunction); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + set.AddFunction(fun); } } // namespace duckdb @@ -98050,13 +107531,13 @@ static void ConstantOrNullFunction(DataChunk &args, ExpressionState &state, Vect auto &func_expr = (BoundFunctionExpression &)state.expr; auto &info = (ConstantOrNullBindData &)*func_expr.bind_info; result.Reference(info.value); - for (idx_t idx = 0; idx < args.ColumnCount(); idx++) { + for (idx_t idx = 1; idx < args.ColumnCount(); idx++) { switch (args.data[idx].GetVectorType()) { case VectorType::FLAT_VECTOR: { auto &input_mask = FlatVector::Validity(args.data[idx]); if (!input_mask.AllValid()) { // there are null values: need to merge them into the result - result.Normalify(args.size()); + result.Flatten(args.size()); auto &result_mask = FlatVector::Validity(result); result_mask.Combine(input_mask, args.size()); } @@ -98072,10 +107553,10 @@ static void ConstantOrNullFunction(DataChunk &args, ExpressionState &state, Vect break; } default: { - VectorData vdata; - args.data[idx].Orrify(args.size(), vdata); + UnifiedVectorFormat vdata; + args.data[idx].ToUnifiedFormat(args.size(), vdata); if (!vdata.validity.AllValid()) { - result.Normalify(args.size()); + result.Flatten(args.size()); auto &result_mask = FlatVector::Validity(result); for (idx_t i = 0; i < args.size(); i++) { if (!vdata.validity.RowIsValid(vdata.sel->get_index(i))) { @@ -98089,8 +107570,8 @@ static void ConstantOrNullFunction(DataChunk &args, ExpressionState &state, Vect } } -ScalarFunction ConstantOrNull::GetFunction(LogicalType return_type) { - return ScalarFunction("constant_or_null", {}, move(return_type), ConstantOrNullFunction); +ScalarFunction ConstantOrNull::GetFunction(const LogicalType &return_type) { + return ScalarFunction("constant_or_null", {return_type, LogicalType::ANY}, return_type, ConstantOrNullFunction); } unique_ptr ConstantOrNull::Bind(Value value) { @@ -98107,6 +107588,27 @@ bool ConstantOrNull::IsConstantOrNull(BoundFunctionExpression &expr, const Value return bind_data.value == val; } +unique_ptr ConstantOrNullBind(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + if (arguments[0]->HasParameter()) { + throw ParameterNotResolvedException(); + } + if (!arguments[0]->IsFoldable()) { + throw BinderException("ConstantOrNull requires a constant input"); + } + D_ASSERT(arguments.size() >= 2); + auto value = ExpressionExecutor::EvaluateScalar(*arguments[0]); + bound_function.return_type = arguments[0]->return_type; + return make_unique(move(value)); +} + +void ConstantOrNull::RegisterFunction(BuiltinFunctions &set) { + auto fun = ConstantOrNull::GetFunction(LogicalType::ANY); + fun.bind = ConstantOrNullBind; + fun.varargs = LogicalType::ANY; + set.AddFunction(fun); +} + } // namespace duckdb @@ -98144,7 +107646,9 @@ unique_ptr CurrentSettingBind(ClientContext &context, ScalarFuncti vector> &arguments) { auto &key_child = arguments[0]; - + if (key_child->return_type.id() == LogicalTypeId::UNKNOWN) { + throw ParameterNotResolvedException(); + } if (key_child->return_type.id() != LogicalTypeId::VARCHAR || key_child->return_type.id() != LogicalTypeId::VARCHAR || !key_child->IsFoldable()) { throw ParserException("Key name for current_setting needs to be a constant string"); @@ -98167,8 +107671,10 @@ unique_ptr CurrentSettingBind(ClientContext &context, ScalarFuncti } void CurrentSettingFun::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction(ScalarFunction("current_setting", {LogicalType::VARCHAR}, LogicalType::ANY, CurrentSettingFunction, - false, CurrentSettingBind)); + auto fun = ScalarFunction("current_setting", {LogicalType::VARCHAR}, LogicalType::ANY, CurrentSettingFunction, + CurrentSettingBind); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + set.AddFunction(fun); } } // namespace duckdb @@ -98183,6 +107689,7 @@ static void HashFunction(DataChunk &args, ExpressionState &state, Vector &result void HashFun::RegisterFunction(BuiltinFunctions &set) { auto hash_fun = ScalarFunction("hash", {LogicalType::ANY}, LogicalType::HASH, HashFunction); hash_fun.varargs = LogicalType::ANY; + hash_fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; set.AddFunction(hash_fun); } @@ -98224,8 +107731,8 @@ static void LeastGreatestFunction(DataChunk &args, ExpressionState &state, Vecto // copy over the first column bool result_has_value[STANDARD_VECTOR_SIZE]; { - VectorData vdata; - args.data[0].Orrify(args.size(), vdata); + UnifiedVectorFormat vdata; + args.data[0].ToUnifiedFormat(args.size(), vdata); auto input_data = (T *)vdata.data; for (idx_t i = 0; i < args.size(); i++) { auto vindex = vdata.sel->get_index(i); @@ -98245,8 +107752,8 @@ static void LeastGreatestFunction(DataChunk &args, ExpressionState &state, Vecto continue; } - VectorData vdata; - args.data[col_idx].Orrify(args.size(), vdata); + UnifiedVectorFormat vdata; + args.data[col_idx].ToUnifiedFormat(args.size(), vdata); auto input_data = (T *)vdata.data; if (!vdata.validity.AllValid()) { @@ -98285,23 +107792,26 @@ static void LeastGreatestFunction(DataChunk &args, ExpressionState &state, Vecto template ScalarFunction GetLeastGreatestFunction(const LogicalType &type) { - return ScalarFunction({type}, type, LeastGreatestFunction, true, false, nullptr, nullptr, nullptr, nullptr, - type); + return ScalarFunction({type}, type, LeastGreatestFunction, nullptr, nullptr, nullptr, nullptr, type, + FunctionSideEffects::NO_SIDE_EFFECTS, FunctionNullHandling::SPECIAL_HANDLING); } template static void RegisterLeastGreatest(BuiltinFunctions &set, const string &fun_name) { ScalarFunctionSet fun_set(fun_name); fun_set.AddFunction(ScalarFunction({LogicalType::BIGINT}, LogicalType::BIGINT, LeastGreatestFunction, - true, false, nullptr, nullptr, nullptr, nullptr, LogicalType::BIGINT)); - fun_set.AddFunction(ScalarFunction({LogicalType::HUGEINT}, LogicalType::HUGEINT, - LeastGreatestFunction, true, false, nullptr, nullptr, nullptr, - nullptr, LogicalType::HUGEINT)); + nullptr, nullptr, nullptr, nullptr, LogicalType::BIGINT, + FunctionSideEffects::NO_SIDE_EFFECTS, FunctionNullHandling::SPECIAL_HANDLING)); + fun_set.AddFunction(ScalarFunction( + {LogicalType::HUGEINT}, LogicalType::HUGEINT, LeastGreatestFunction, nullptr, nullptr, nullptr, + nullptr, LogicalType::HUGEINT, FunctionSideEffects::NO_SIDE_EFFECTS, FunctionNullHandling::SPECIAL_HANDLING)); fun_set.AddFunction(ScalarFunction({LogicalType::DOUBLE}, LogicalType::DOUBLE, LeastGreatestFunction, - true, false, nullptr, nullptr, nullptr, nullptr, LogicalType::DOUBLE)); + nullptr, nullptr, nullptr, nullptr, LogicalType::DOUBLE, + FunctionSideEffects::NO_SIDE_EFFECTS, FunctionNullHandling::SPECIAL_HANDLING)); fun_set.AddFunction(ScalarFunction({LogicalType::VARCHAR}, LogicalType::VARCHAR, - LeastGreatestFunction, true, false, nullptr, nullptr, - nullptr, nullptr, LogicalType::VARCHAR)); + LeastGreatestFunction, nullptr, nullptr, nullptr, nullptr, + LogicalType::VARCHAR, FunctionSideEffects::NO_SIDE_EFFECTS, + FunctionNullHandling::SPECIAL_HANDLING)); fun_set.AddFunction(GetLeastGreatestFunction(LogicalType::TIMESTAMP)); fun_set.AddFunction(GetLeastGreatestFunction(LogicalType::TIME)); @@ -98370,8 +107880,11 @@ static unique_ptr StatsPropagateStats(ClientContext &context, Fu } void StatsFun::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction(ScalarFunction("stats", {LogicalType::ANY}, LogicalType::VARCHAR, StatsFunction, true, StatsBind, - nullptr, StatsPropagateStats)); + ScalarFunction stats("stats", {LogicalType::ANY}, LogicalType::VARCHAR, StatsFunction, StatsBind, nullptr, + StatsPropagateStats); + stats.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + stats.side_effects = FunctionSideEffects::HAS_SIDE_EFFECTS; + set.AddFunction(stats); } } // namespace duckdb @@ -98385,7 +107898,9 @@ static void TypeOfFunction(DataChunk &args, ExpressionState &state, Vector &resu } void TypeOfFun::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction(ScalarFunction("typeof", {LogicalType::ANY}, LogicalType::VARCHAR, TypeOfFunction)); + auto fun = ScalarFunction("typeof", {LogicalType::ANY}, LogicalType::VARCHAR, TypeOfFunction); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + set.AddFunction(fun); } } // namespace duckdb @@ -98400,6 +107915,7 @@ void BuiltinFunctions::RegisterGenericFunctions() { Register(); Register(); Register(); + Register(); Register(); Register(); } @@ -98509,11 +108025,11 @@ static void ExecuteSlice(Vector &result, Vector &s, Vector &b, Vector &e, const rdata[0] = SliceValue(result, sliced, begin, end); } } else { - VectorData sdata, bdata, edata; + UnifiedVectorFormat sdata, bdata, edata; - s.Orrify(count, sdata); - b.Orrify(count, bdata); - e.Orrify(count, edata); + s.ToUnifiedFormat(count, sdata); + b.ToUnifiedFormat(count, bdata); + e.ToUnifiedFormat(count, edata); auto rdata = FlatVector::GetData(result); auto &rmask = FlatVector::Validity(result); @@ -98554,10 +108070,13 @@ static void ArraySliceFunction(DataChunk &args, ExpressionState &state, Vector & Vector &b = args.data[1]; Vector &e = args.data[2]; - s.Normalify(count); + result.SetVectorType(args.AllConstant() ? VectorType::CONSTANT_VECTOR : VectorType::FLAT_VECTOR); switch (result.GetType().id()) { case LogicalTypeId::LIST: // Share the value dictionary as we are just going to slice it + if (s.GetVectorType() != VectorType::FLAT_VECTOR && s.GetVectorType() != VectorType::CONSTANT_VECTOR) { + s.Flatten(count); + } ListVector::ReferenceEntry(result, s); ExecuteSlice(result, s, b, e, count); break; @@ -98567,14 +108086,6 @@ static void ArraySliceFunction(DataChunk &args, ExpressionState &state, Vector & default: throw NotImplementedException("Specifier type not implemented"); } - - result.SetVectorType(VectorType::CONSTANT_VECTOR); - for (idx_t i = 0; i < args.ColumnCount(); i++) { - if (args.data[i].GetVectorType() != VectorType::CONSTANT_VECTOR) { - result.SetVectorType(VectorType::FLAT_VECTOR); - break; - } - } } static unique_ptr ArraySliceBind(ClientContext &context, ScalarFunction &bound_function, @@ -98591,6 +108102,7 @@ static unique_ptr ArraySliceBind(ClientContext &context, ScalarFun bound_function.arguments[1] = LogicalType::INTEGER; bound_function.arguments[2] = LogicalType::INTEGER; break; + case LogicalTypeId::SQLNULL: case LogicalTypeId::UNKNOWN: bound_function.arguments[0] = LogicalTypeId::UNKNOWN; bound_function.return_type = LogicalType::SQLNULL; @@ -98605,8 +108117,9 @@ static unique_ptr ArraySliceBind(ClientContext &context, ScalarFun void ArraySliceFun::RegisterFunction(BuiltinFunctions &set) { // the arguments and return types are actually set in the binder function ScalarFunction fun({LogicalType::ANY, LogicalType::BIGINT, LogicalType::BIGINT}, LogicalType::ANY, - ArraySliceFunction, false, false, ArraySliceBind); + ArraySliceFunction, ArraySliceBind); fun.varargs = LogicalType::ANY; + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; set.AddFunction({"array_slice", "list_slice"}, fun); } @@ -98615,17 +108128,8 @@ void ArraySliceFun::RegisterFunction(BuiltinFunctions &set) { -namespace duckdb { - -template -static inline bool ValueEqualsOrNot(const T &left, const T &right) { - return left == right; -} -template <> -inline bool ValueEqualsOrNot(const string_t &left, const string_t &right) { - return StringComparisonOperators::EqualsOrNot(left, right); -} +namespace duckdb { struct ContainsFunctor { static inline bool Initialize() { @@ -98666,15 +108170,15 @@ static void TemplatedContainsOrPosition(DataChunk &args, ExpressionState &state, auto list_size = ListVector::GetListSize(list); auto &child_vector = ListVector::GetEntry(list); - VectorData child_data; - child_vector.Orrify(list_size, child_data); + UnifiedVectorFormat child_data; + child_vector.ToUnifiedFormat(list_size, child_data); - VectorData list_data; - list.Orrify(count, list_data); + UnifiedVectorFormat list_data; + list.ToUnifiedFormat(count, list_data); auto list_entries = (list_entry_t *)list_data.data; - VectorData value_data; - value_vector.Orrify(count, value_data); + UnifiedVectorFormat value_data; + value_vector.ToUnifiedFormat(count, value_data); // not required for a comparison of nested types auto child_value = FlatVector::GetData(child_vector); @@ -98700,21 +108204,26 @@ static void TemplatedContainsOrPosition(DataChunk &args, ExpressionState &state, } if (!is_nested) { - if (ValueEqualsOrNot(child_value[child_value_idx], values[value_index])) { + if (Equals::Operation(child_value[child_value_idx], values[value_index])) { result_entries[i] = OP::UpdateResultEntries(child_idx); break; // Found value in list, no need to look further } } else { // FIXME: using Value is less efficient than modifying the vector comparison code // to more efficiently compare nested types - if (ValueEqualsOrNot(child_vector.GetValue(child_value_idx), - value_vector.GetValue(value_index))) { + auto lvalue = child_vector.GetValue(child_value_idx); + auto rvalue = value_vector.GetValue(value_index); + if (Value::NotDistinctFrom(lvalue, rvalue)) { result_entries[i] = OP::UpdateResultEntries(child_idx); break; // Found value in list, no need to look further } } } } + + if (args.AllConstant()) { + result.SetVectorType(VectorType::CONSTANT_VECTOR); + } } template @@ -98782,17 +108291,7 @@ static unique_ptr ListContainsOrPositionBind(ClientContext &contex const auto &list = arguments[0]->return_type; // change to list const auto &value = arguments[1]->return_type; - if (list.id() == LogicalTypeId::SQLNULL && value.id() == LogicalTypeId::SQLNULL) { - bound_function.arguments[0] = LogicalType::SQLNULL; - bound_function.arguments[1] = LogicalType::SQLNULL; - bound_function.return_type = LogicalType::SQLNULL; - } else if (list.id() == LogicalTypeId::SQLNULL || value.id() == LogicalTypeId::SQLNULL) { - // In case either the list or the value is NULL, return NULL - // Similar to behaviour of prestoDB - bound_function.arguments[0] = list; - bound_function.arguments[1] = value; - bound_function.return_type = LogicalTypeId::SQLNULL; - } else if (list.id() == LogicalTypeId::UNKNOWN) { + if (list.id() == LogicalTypeId::UNKNOWN) { bound_function.return_type = RETURN_TYPE; if (value.id() != LogicalTypeId::UNKNOWN) { // only list is a parameter, cast it to a list of value type @@ -98832,13 +108331,13 @@ static unique_ptr ListPositionBind(ClientContext &context, ScalarF ScalarFunction ListContainsFun::GetFunction() { return ScalarFunction({LogicalType::LIST(LogicalType::ANY), LogicalType::ANY}, // argument list LogicalType::BOOLEAN, // return type - ListContainsFunction, false, false, ListContainsBind, nullptr); + ListContainsFunction, ListContainsBind, nullptr); } ScalarFunction ListPositionFun::GetFunction() { return ScalarFunction({LogicalType::LIST(LogicalType::ANY), LogicalType::ANY}, // argument list LogicalType::INTEGER, // return type - ListPositionFunction, false, false, ListPositionBind, nullptr); + ListPositionFunction, ListPositionBind, nullptr); } void ListContainsFun::RegisterFunction(BuiltinFunctions &set) { @@ -98851,6 +108350,7 @@ void ListPositionFun::RegisterFunction(BuiltinFunctions &set) { } // namespace duckdb + //===----------------------------------------------------------------------===// // DuckDB // @@ -98902,8 +108402,8 @@ void ListFlattenFunction(DataChunk &args, ExpressionState &state, Vector &result idx_t count = args.size(); - VectorData list_data; - input.Orrify(count, list_data); + UnifiedVectorFormat list_data; + input.ToUnifiedFormat(count, list_data); auto list_entries = (list_entry_t *)list_data.data; auto &child_vector = ListVector::GetEntry(input); @@ -98923,12 +108423,15 @@ void ListFlattenFunction(DataChunk &args, ExpressionState &state, Vector &result result_entries[i].offset = 0; result_entries[i].length = 0; } + if (args.AllConstant()) { + result.SetVectorType(VectorType::CONSTANT_VECTOR); + } return; } auto child_size = ListVector::GetListSize(input); - VectorData child_data; - child_vector.Orrify(child_size, child_data); + UnifiedVectorFormat child_data; + child_vector.ToUnifiedFormat(child_size, child_data); auto child_entries = (list_entry_t *)child_data.data; auto &data_vector = ListVector::GetEntry(child_vector); @@ -98968,7 +108471,7 @@ void ListFlattenFunction(DataChunk &args, ExpressionState &state, Vector &result offset += length; } - if (input.GetVectorType() == VectorType::CONSTANT_VECTOR) { + if (args.AllConstant()) { result.SetVectorType(VectorType::CONSTANT_VECTOR); } } @@ -98979,10 +108482,6 @@ static unique_ptr ListFlattenBind(ClientContext &context, ScalarFu auto &input_type = arguments[0]->return_type; bound_function.arguments[0] = input_type; - if (input_type.id() == LogicalTypeId::SQLNULL) { - bound_function.return_type = LogicalType(LogicalTypeId::SQLNULL); - return make_unique(bound_function.return_type); - } if (input_type.id() == LogicalTypeId::UNKNOWN) { bound_function.arguments[0] = LogicalType(LogicalTypeId::UNKNOWN); bound_function.return_type = LogicalType(LogicalTypeId::SQLNULL); @@ -98995,6 +108494,11 @@ static unique_ptr ListFlattenBind(ClientContext &context, ScalarFu bound_function.return_type = input_type; return make_unique(bound_function.return_type); } + if (child_type.id() == LogicalTypeId::UNKNOWN) { + bound_function.arguments[0] = LogicalType(LogicalTypeId::UNKNOWN); + bound_function.return_type = LogicalType(LogicalTypeId::SQLNULL); + return nullptr; + } D_ASSERT(child_type.id() == LogicalTypeId::LIST); bound_function.return_type = child_type; @@ -99018,7 +108522,7 @@ static unique_ptr ListFlattenStats(ClientContext &context, Funct void ListFlattenFun::RegisterFunction(BuiltinFunctions &set) { ScalarFunction fun({LogicalType::LIST(LogicalType::LIST(LogicalType::ANY))}, LogicalType::LIST(LogicalType::ANY), - ListFlattenFunction, false, false, ListFlattenBind, nullptr, ListFlattenStats); + ListFlattenFunction, ListFlattenBind, nullptr, ListFlattenStats); set.AddFunction({"flatten"}, fun); } @@ -99052,6 +108556,13 @@ struct ListAggregatesBindData : public FunctionData { auto &other = (const ListAggregatesBindData &)other_p; return stype == other.stype && aggr_expr->Equals(other.aggr_expr.get()); } + static void Serialize(FieldWriter &writer, const FunctionData *bind_data_p, const ScalarFunction &function) { + throw NotImplementedException("FIXME: list aggr serialize"); + } + static unique_ptr Deserialize(ClientContext &context, FieldReader &reader, + ScalarFunction &bound_function) { + throw NotImplementedException("FIXME: list aggr deserialize"); + } }; ListAggregatesBindData::ListAggregatesBindData(const LogicalType &stype_p, unique_ptr aggr_expr_p) @@ -99104,8 +108615,8 @@ struct DistinctFunctor { template > static void ListExecuteFunction(Vector &result, Vector &state_vector, idx_t count) { - VectorData sdata; - state_vector.Orrify(count, sdata); + UnifiedVectorFormat sdata; + state_vector.ToUnifiedFormat(count, sdata); auto states = (HistogramAggState **)sdata.data; auto result_data = FlatVector::GetData(result); @@ -99137,8 +108648,8 @@ struct UniqueFunctor { template > static void ListExecuteFunction(Vector &result, Vector &state_vector, idx_t count) { - VectorData sdata; - state_vector.Orrify(count, sdata); + UnifiedVectorFormat sdata; + state_vector.ToUnifiedFormat(count, sdata); auto states = (HistogramAggState **)sdata.data; auto result_data = FlatVector::GetData(result); @@ -99177,17 +108688,18 @@ static void ListAggregatesFunction(DataChunk &args, ExpressionState &state, Vect auto &func_expr = (BoundFunctionExpression &)state.expr; auto &info = (ListAggregatesBindData &)*func_expr.bind_info; auto &aggr = (BoundAggregateExpression &)*info.aggr_expr; + AggregateInputData aggr_input_data(aggr.bind_info.get(), Allocator::DefaultAllocator()); D_ASSERT(aggr.function.update); auto lists_size = ListVector::GetListSize(lists); auto &child_vector = ListVector::GetEntry(lists); - VectorData child_data; - child_vector.Orrify(lists_size, child_data); + UnifiedVectorFormat child_data; + child_vector.ToUnifiedFormat(lists_size, child_data); - VectorData lists_data; - lists.Orrify(count, lists_data); + UnifiedVectorFormat lists_data; + lists.ToUnifiedFormat(count, lists_data); auto list_entries = (list_entry_t *)lists_data.data; // state_buffer holds the state for each list of this chunk @@ -99228,13 +108740,11 @@ static void ListAggregatesFunction(DataChunk &args, ExpressionState &state, Vect } for (idx_t child_idx = 0; child_idx < list_entry.length; child_idx++) { - // states vector is full, update if (states_idx == STANDARD_VECTOR_SIZE) { - // update the aggregate state(s) Vector slice = Vector(child_vector, sel_vector, states_idx); - aggr.function.update(&slice, aggr.bind_info.get(), 1, state_vector_update, states_idx); + aggr.function.update(&slice, aggr_input_data, 1, state_vector_update, states_idx); // reset values states_idx = 0; @@ -99250,12 +108760,12 @@ static void ListAggregatesFunction(DataChunk &args, ExpressionState &state, Vect // update the remaining elements of the last list(s) if (states_idx != 0) { Vector slice = Vector(child_vector, sel_vector, states_idx); - aggr.function.update(&slice, aggr.bind_info.get(), 1, state_vector_update, states_idx); + aggr.function.update(&slice, aggr_input_data, 1, state_vector_update, states_idx); } if (IS_AGGR) { // finalize all the aggregate states - aggr.function.finalize(state_vector.state_vector, aggr.bind_info.get(), result, count, 0); + aggr.function.finalize(state_vector.state_vector, aggr_input_data, result, count, 0); } else { // finalize manually to use the map @@ -99307,34 +108817,6 @@ static void ListAggregatesFunction(DataChunk &args, ExpressionState &state, Vect FUNCTION_FUNCTOR::template ListExecuteFunction( result, state_vector.state_vector, count); break; - case PhysicalType::DATE32: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - case PhysicalType::DATE64: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - case PhysicalType::TIMESTAMP: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - case PhysicalType::TIME32: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - case PhysicalType::TIME64: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - case PhysicalType::STRING: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; - case PhysicalType::LARGE_STRING: - FUNCTION_FUNCTOR::template ListExecuteFunction( - result, state_vector.state_vector, count); - break; case PhysicalType::VARCHAR: FUNCTION_FUNCTOR::template ListExecuteFunction( result, state_vector.state_vector, count); @@ -99343,6 +108825,10 @@ static void ListAggregatesFunction(DataChunk &args, ExpressionState &state, Vect throw InternalException("Unimplemented histogram aggregate"); } } + + if (args.AllConstant()) { + result.SetVectorType(VectorType::CONSTANT_VECTOR); + } } static void ListAggregateFunction(DataChunk &args, ExpressionState &state, Vector &result) { @@ -99364,14 +108850,21 @@ static void ListUniqueFunction(DataChunk &args, ExpressionState &state, Vector & } template -static unique_ptr ListAggregatesBindFunction(ClientContext &context, ScalarFunction &bound_function, - const LogicalType &list_child_type, - AggregateFunction &aggr_function) { +static unique_ptr +ListAggregatesBindFunction(ClientContext &context, ScalarFunction &bound_function, const LogicalType &list_child_type, + AggregateFunction &aggr_function, vector> &arguments) { // create the child expression and its type vector> children; auto expr = make_unique(Value(list_child_type)); children.push_back(move(expr)); + // push any extra arguments into the list aggregate bind + if (arguments.size() > 2) { + for (idx_t i = 2; i < arguments.size(); i++) { + children.push_back(move(arguments[i])); + } + arguments.resize(2); + } auto bound_aggr_function = AggregateFunction::BindAggregateFunction(context, aggr_function, move(children)); bound_function.arguments[0] = LogicalType::LIST(bound_aggr_function->function.arguments[0]); @@ -99379,6 +108872,12 @@ static unique_ptr ListAggregatesBindFunction(ClientContext &contex if (IS_AGGR) { bound_function.return_type = bound_aggr_function->function.return_type; } + // check if the aggregate function consumed all the extra input arguments + if (bound_aggr_function->children.size() > 1) { + throw InvalidInputException( + "Aggregate function %s is not supported for list_aggr: extra arguments were not removed during bind", + bound_aggr_function->ToString()); + } return make_unique(bound_function.return_type, move(bound_aggr_function)); } @@ -99386,7 +108885,6 @@ static unique_ptr ListAggregatesBindFunction(ClientContext &contex template static unique_ptr ListAggregatesBind(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { - if (arguments[0]->return_type.id() == LogicalTypeId::SQLNULL) { bound_function.arguments[0] = LogicalType::SQLNULL; bound_function.return_type = LogicalType::SQLNULL; @@ -99398,7 +108896,6 @@ static unique_ptr ListAggregatesBind(ClientContext &context, Scala string function_name = "histogram"; if (IS_AGGR) { // get the name of the aggregate function - if (!arguments[1]->IsFoldable()) { throw InvalidInputException("Aggregate function name must be a constant"); } @@ -99423,31 +108920,34 @@ static unique_ptr ListAggregatesBind(ClientContext &context, Scala string error; vector types; types.push_back(list_child_type); + // push any extra arguments into the type list + for (idx_t i = 2; i < arguments.size(); i++) { + types.push_back(arguments[i]->return_type); + } auto best_function_idx = Function::BindFunction(func->name, func->functions, types, error); if (best_function_idx == DConstants::INVALID_INDEX) { - throw BinderException("No matching aggregate function"); + throw BinderException("No matching aggregate function\n%s", error); } // found a matching function, bind it as an aggregate - auto &best_function = func->functions[best_function_idx]; - + auto best_function = func->functions.GetFunctionByOffset(best_function_idx); if (IS_AGGR) { - return ListAggregatesBindFunction(context, bound_function, list_child_type, best_function); + return ListAggregatesBindFunction(context, bound_function, list_child_type, best_function, arguments); } // create the unordered map histogram function D_ASSERT(best_function.arguments.size() == 1); auto key_type = best_function.arguments[0]; auto aggr_function = HistogramFun::GetHistogramUnorderedMap(key_type); - return ListAggregatesBindFunction(context, bound_function, list_child_type, aggr_function); + return ListAggregatesBindFunction(context, bound_function, list_child_type, aggr_function, arguments); } static unique_ptr ListAggregateBind(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { // the list column and the name of the aggregate function - D_ASSERT(bound_function.arguments.size() == 2); - D_ASSERT(arguments.size() == 2); + D_ASSERT(bound_function.arguments.size() >= 2); + D_ASSERT(arguments.size() >= 2); return ListAggregatesBind(context, bound_function, arguments); } @@ -99473,17 +108973,22 @@ static unique_ptr ListUniqueBind(ClientContext &context, ScalarFun } ScalarFunction ListAggregateFun::GetFunction() { - return ScalarFunction({LogicalType::LIST(LogicalType::ANY), LogicalType::VARCHAR}, LogicalType::ANY, - ListAggregateFunction, false, false, ListAggregateBind); + auto result = ScalarFunction({LogicalType::LIST(LogicalType::ANY), LogicalType::VARCHAR}, LogicalType::ANY, + ListAggregateFunction, ListAggregateBind); + result.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + result.varargs = LogicalType::ANY; + result.serialize = ListAggregatesBindData::Serialize; + result.deserialize = ListAggregatesBindData::Deserialize; + return result; } ScalarFunction ListDistinctFun::GetFunction() { return ScalarFunction({LogicalType::LIST(LogicalType::ANY)}, LogicalType::LIST(LogicalType::ANY), - ListDistinctFunction, false, false, ListDistinctBind); + ListDistinctFunction, ListDistinctBind); } ScalarFunction ListUniqueFun::GetFunction() { - return ScalarFunction({LogicalType::LIST(LogicalType::ANY)}, LogicalType::UBIGINT, ListUniqueFunction, false, false, + return ScalarFunction({LogicalType::LIST(LogicalType::ANY)}, LogicalType::UBIGINT, ListUniqueFunction, ListUniqueBind); } @@ -99507,6 +109012,7 @@ void ListUniqueFun::RegisterFunction(BuiltinFunctions &set) { + namespace duckdb { static void ListConcatFunction(DataChunk &args, ExpressionState &state, Vector &result) { @@ -99524,10 +109030,10 @@ static void ListConcatFunction(DataChunk &args, ExpressionState &state, Vector & return; } - VectorData lhs_data; - VectorData rhs_data; - lhs.Orrify(count, lhs_data); - rhs.Orrify(count, rhs_data); + UnifiedVectorFormat lhs_data; + UnifiedVectorFormat rhs_data; + lhs.ToUnifiedFormat(count, lhs_data); + rhs.ToUnifiedFormat(count, rhs_data); auto lhs_entries = (list_entry_t *)lhs_data.data; auto rhs_entries = (list_entry_t *)rhs_data.data; @@ -99535,10 +109041,10 @@ static void ListConcatFunction(DataChunk &args, ExpressionState &state, Vector & auto rhs_list_size = ListVector::GetListSize(rhs); auto &lhs_child = ListVector::GetEntry(lhs); auto &rhs_child = ListVector::GetEntry(rhs); - VectorData lhs_child_data; - VectorData rhs_child_data; - lhs_child.Orrify(lhs_list_size, lhs_child_data); - rhs_child.Orrify(rhs_list_size, rhs_child_data); + UnifiedVectorFormat lhs_child_data; + UnifiedVectorFormat rhs_child_data; + lhs_child.ToUnifiedFormat(lhs_list_size, lhs_child_data); + rhs_child.ToUnifiedFormat(rhs_list_size, rhs_child_data); result.SetVectorType(VectorType::FLAT_VECTOR); auto result_entries = FlatVector::GetData(result); @@ -99581,8 +109087,8 @@ static unique_ptr ListConcatBind(ClientContext &context, ScalarFun auto &lhs = arguments[0]->return_type; auto &rhs = arguments[1]->return_type; - if (lhs.id() == LogicalTypeId::SQLNULL && rhs.id() == LogicalTypeId::SQLNULL) { - bound_function.return_type = LogicalType::SQLNULL; + if (lhs.id() == LogicalTypeId::UNKNOWN || rhs.id() == LogicalTypeId::UNKNOWN) { + throw ParameterNotResolvedException(); } else if (lhs.id() == LogicalTypeId::SQLNULL || rhs.id() == LogicalTypeId::SQLNULL) { // we mimic postgres behaviour: list_concat(NULL, my_list) = my_list bound_function.arguments[0] = lhs; @@ -99624,9 +109130,11 @@ static unique_ptr ListConcatStats(ClientContext &context, Functi ScalarFunction ListConcatFun::GetFunction() { // the arguments and return types are actually set in the binder function - return ScalarFunction({LogicalType::LIST(LogicalType::ANY), LogicalType::LIST(LogicalType::ANY)}, - LogicalType::LIST(LogicalType::ANY), ListConcatFunction, false, false, ListConcatBind, - nullptr, ListConcatStats); + auto fun = ScalarFunction({LogicalType::LIST(LogicalType::ANY), LogicalType::LIST(LogicalType::ANY)}, + LogicalType::LIST(LogicalType::ANY), ListConcatFunction, ListConcatBind, nullptr, + ListConcatStats); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + return fun; } void ListConcatFun::RegisterFunction(BuiltinFunctions &set) { @@ -99649,10 +109157,10 @@ void ListConcatFun::RegisterFunction(BuiltinFunctions &set) { namespace duckdb { template -void ListExtractTemplate(idx_t count, VectorData &list_data, VectorData &offsets_data, Vector &child_vector, - idx_t list_size, Vector &result) { - VectorData child_data; - child_vector.Orrify(list_size, child_data); +void ListExtractTemplate(idx_t count, UnifiedVectorFormat &list_data, UnifiedVectorFormat &offsets_data, + Vector &child_vector, idx_t list_size, Vector &result) { + UnifiedVectorFormat child_data; + child_vector.ToUnifiedFormat(list_size, child_data); T *result_data; @@ -99712,8 +109220,8 @@ void ListExtractTemplate(idx_t count, VectorData &list_data, VectorData &offsets result.SetVectorType(VectorType::CONSTANT_VECTOR); } } -static void ExecuteListExtractInternal(const idx_t count, VectorData &list, VectorData &offsets, Vector &child_vector, - idx_t list_size, Vector &result) { +static void ExecuteListExtractInternal(const idx_t count, UnifiedVectorFormat &list, UnifiedVectorFormat &offsets, + Vector &child_vector, idx_t list_size, Vector &result) { D_ASSERT(child_vector.GetType() == result.GetType()); switch (result.GetType().InternalType()) { case PhysicalType::BOOL: @@ -99784,11 +109292,11 @@ static void ExecuteListExtractInternal(const idx_t count, VectorData &list, Vect static void ExecuteListExtract(Vector &result, Vector &list, Vector &offsets, const idx_t count) { D_ASSERT(list.GetType().id() == LogicalTypeId::LIST); - VectorData list_data; - VectorData offsets_data; + UnifiedVectorFormat list_data; + UnifiedVectorFormat offsets_data; - list.Orrify(count, list_data); - offsets.Orrify(count, offsets_data); + list.ToUnifiedFormat(count, list_data); + offsets.ToUnifiedFormat(count, offsets_data); ExecuteListExtractInternal(count, list_data, offsets_data, ListVector::GetEntry(list), ListVector::GetListSize(list), result); result.Verify(count); @@ -99834,14 +109342,9 @@ static void ListExtractFunction(DataChunk &args, ExpressionState &state, Vector static unique_ptr ListExtractBind(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { D_ASSERT(bound_function.arguments.size() == 2); - if (arguments[0]->return_type.id() == LogicalTypeId::SQLNULL) { - bound_function.arguments[0] = LogicalType::SQLNULL; - bound_function.return_type = LogicalType::SQLNULL; - } else { - D_ASSERT(LogicalTypeId::LIST == arguments[0]->return_type.id()); - // list extract returns the child type of the list as return type - bound_function.return_type = ListType::GetChildType(arguments[0]->return_type); - } + D_ASSERT(LogicalTypeId::LIST == arguments[0]->return_type.id()); + // list extract returns the child type of the list as return type + bound_function.return_type = ListType::GetChildType(arguments[0]->return_type); return make_unique(bound_function.return_type); } @@ -99863,10 +109366,9 @@ static unique_ptr ListExtractStats(ClientContext &context, Funct void ListExtractFun::RegisterFunction(BuiltinFunctions &set) { // the arguments and return types are actually set in the binder function ScalarFunction lfun({LogicalType::LIST(LogicalType::ANY), LogicalType::BIGINT}, LogicalType::ANY, - ListExtractFunction, false, false, ListExtractBind, nullptr, ListExtractStats); + ListExtractFunction, ListExtractBind, nullptr, ListExtractStats); - ScalarFunction sfun({LogicalType::VARCHAR, LogicalType::BIGINT}, LogicalType::VARCHAR, ListExtractFunction, false, - false, nullptr); + ScalarFunction sfun({LogicalType::VARCHAR, LogicalType::BIGINT}, LogicalType::VARCHAR, ListExtractFunction); ScalarFunctionSet list_extract("list_extract"); list_extract.AddFunction(lfun); @@ -99894,6 +109396,392 @@ void ListExtractFun::RegisterFunction(BuiltinFunctions &set) { +namespace duckdb { + +struct ListLambdaBindData : public FunctionData { + ListLambdaBindData(const LogicalType &stype_p, unique_ptr lambda_expr); + ~ListLambdaBindData() override; + + LogicalType stype; + unique_ptr lambda_expr; + +public: + bool Equals(const FunctionData &other_p) const override; + unique_ptr Copy() const override; + static void Serialize(FieldWriter &writer, const FunctionData *bind_data_p, const ScalarFunction &function) { + throw NotImplementedException("FIXME: list lambda serialize"); + } + static unique_ptr Deserialize(ClientContext &context, FieldReader &reader, + ScalarFunction &bound_function) { + throw NotImplementedException("FIXME: list lambda deserialize"); + } +}; + +ListLambdaBindData::ListLambdaBindData(const LogicalType &stype_p, unique_ptr lambda_expr_p) + : stype(stype_p), lambda_expr(move(lambda_expr_p)) { +} + +unique_ptr ListLambdaBindData::Copy() const { + return make_unique(stype, lambda_expr->Copy()); +} + +bool ListLambdaBindData::Equals(const FunctionData &other_p) const { + auto &other = (ListLambdaBindData &)other_p; + return lambda_expr->Equals(other.lambda_expr.get()) && stype == other.stype; +} + +ListLambdaBindData::~ListLambdaBindData() { +} + +static void AppendTransformedToResult(Vector &lambda_vector, idx_t &elem_cnt, Vector &result) { + + // append the lambda_vector to the result list + UnifiedVectorFormat lambda_child_data; + lambda_vector.ToUnifiedFormat(elem_cnt, lambda_child_data); + ListVector::Append(result, lambda_vector, *lambda_child_data.sel, elem_cnt, 0); +} + +static void AppendFilteredToResult(Vector &lambda_vector, list_entry_t *result_entries, idx_t &elem_cnt, Vector &result, + idx_t &curr_list_len, idx_t &curr_list_offset, idx_t &appended_lists_cnt, + vector &lists_len, idx_t &curr_original_list_len, DataChunk &input_chunk) { + + idx_t true_count = 0; + SelectionVector true_sel(elem_cnt); + auto lambda_values = FlatVector::GetData(lambda_vector); + auto &lambda_validity = FlatVector::Validity(lambda_vector); + + // compute the new lengths and offsets, and create a selection vector + for (idx_t i = 0; i < elem_cnt; i++) { + + while (appended_lists_cnt < lists_len.size() && lists_len[appended_lists_cnt] == 0) { + result_entries[appended_lists_cnt].offset = curr_list_offset; + result_entries[appended_lists_cnt].length = 0; + appended_lists_cnt++; + } + + // found a true value + if (lambda_validity.RowIsValid(i)) { + if (lambda_values[i] > 0) { + true_sel.set_index(true_count++, i); + curr_list_len++; + } + } + curr_original_list_len++; + + if (lists_len[appended_lists_cnt] == curr_original_list_len) { + result_entries[appended_lists_cnt].offset = curr_list_offset; + result_entries[appended_lists_cnt].length = curr_list_len; + curr_list_offset += curr_list_len; + appended_lists_cnt++; + curr_list_len = 0; + curr_original_list_len = 0; + } + } + + while (appended_lists_cnt < lists_len.size() && lists_len[appended_lists_cnt] == 0) { + result_entries[appended_lists_cnt].offset = curr_list_offset; + result_entries[appended_lists_cnt].length = 0; + appended_lists_cnt++; + } + + // slice to get the new lists and append them to the result + Vector new_lists(input_chunk.data[0], true_sel, true_count); + new_lists.Flatten(true_count); + UnifiedVectorFormat new_lists_child_data; + new_lists.ToUnifiedFormat(true_count, new_lists_child_data); + ListVector::Append(result, new_lists, *new_lists_child_data.sel, true_count, 0); +} + +static void ExecuteExpression(vector &types, vector &result_types, idx_t &elem_cnt, + SelectionVector &sel, vector &sel_vectors, DataChunk &input_chunk, + DataChunk &lambda_chunk, Vector &child_vector, DataChunk &args, + ExpressionExecutor &expr_executor) { + + input_chunk.SetCardinality(elem_cnt); + lambda_chunk.SetCardinality(elem_cnt); + + // set the list child vector + Vector slice(child_vector, sel, elem_cnt); + slice.Flatten(elem_cnt); + input_chunk.data[0].Reference(slice); + + // set the other vectors + vector slices; + for (idx_t col_idx = 0; col_idx < args.ColumnCount() - 1; col_idx++) { + slices.emplace_back(Vector(args.data[col_idx + 1], sel_vectors[col_idx], elem_cnt)); + slices[col_idx].Flatten(elem_cnt); + input_chunk.data[col_idx + 1].Reference(slices[col_idx]); + } + + // execute the lambda expression + expr_executor.Execute(input_chunk, lambda_chunk); +} + +template +static void ListLambdaFunction(DataChunk &args, ExpressionState &state, Vector &result) { + + // always at least the list argument + D_ASSERT(args.ColumnCount() >= 1); + + auto count = args.size(); + Vector &lists = args.data[0]; + + result.SetVectorType(VectorType::FLAT_VECTOR); + auto result_entries = FlatVector::GetData(result); + auto &result_validity = FlatVector::Validity(result); + + if (lists.GetType().id() == LogicalTypeId::SQLNULL) { + result_validity.SetInvalid(0); + return; + } + + // get the lists data + UnifiedVectorFormat lists_data; + lists.ToUnifiedFormat(count, lists_data); + auto list_entries = (list_entry_t *)lists_data.data; + + // get the lambda expression + auto &func_expr = (BoundFunctionExpression &)state.expr; + auto &info = (ListLambdaBindData &)*func_expr.bind_info; + auto &lambda_expr = info.lambda_expr; + + // get the child vector and child data + auto lists_size = ListVector::GetListSize(lists); + auto &child_vector = ListVector::GetEntry(lists); + UnifiedVectorFormat child_data; + child_vector.ToUnifiedFormat(lists_size, child_data); + + // to slice the child vector + SelectionVector sel(STANDARD_VECTOR_SIZE); + + // this vector never contains more than one element + vector result_types; + result_types.push_back(lambda_expr->return_type); + + // non-lambda parameter columns + vector columns; + vector indexes; + vector sel_vectors; + + vector types; + types.push_back(child_vector.GetType()); + + // skip the list column + for (idx_t i = 1; i < args.ColumnCount(); i++) { + columns.emplace_back(UnifiedVectorFormat()); + args.data[i].ToUnifiedFormat(count, columns[i - 1]); + indexes.push_back(0); + sel_vectors.emplace_back(SelectionVector(STANDARD_VECTOR_SIZE)); + types.push_back(args.data[i].GetType()); + } + + // get the expression executor + ExpressionExecutor expr_executor(Allocator::DefaultAllocator(), *lambda_expr); + + // these are only for the list_filter + vector lists_len; + idx_t curr_list_len = 0; + idx_t curr_list_offset = 0; + idx_t appended_lists_cnt = 0; + idx_t curr_original_list_len = 0; + + if (!IS_TRANSFORM) { + lists_len.reserve(count); + } + + DataChunk input_chunk; + DataChunk lambda_chunk; + input_chunk.InitializeEmpty(types); + lambda_chunk.Initialize(Allocator::DefaultAllocator(), result_types); + + // loop over the child entries and create chunks to be executed by the expression executor + idx_t elem_cnt = 0; + idx_t offset = 0; + for (idx_t row_idx = 0; row_idx < count; row_idx++) { + + auto lists_index = lists_data.sel->get_index(row_idx); + const auto &list_entry = list_entries[lists_index]; + + // set the result to NULL for this row + if (!lists_data.validity.RowIsValid(lists_index)) { + result_validity.SetInvalid(row_idx); + if (!IS_TRANSFORM) { + lists_len.push_back(0); + } + continue; + } + + // set the length and offset of the resulting lists of list_transform + if (IS_TRANSFORM) { + result_entries[row_idx].offset = offset; + result_entries[row_idx].length = list_entry.length; + offset += list_entry.length; + } else { + lists_len.push_back(list_entry.length); + } + + // empty list, nothing to execute + if (list_entry.length == 0) { + continue; + } + + // get the data indexes + for (idx_t col_idx = 0; col_idx < args.ColumnCount() - 1; col_idx++) { + indexes[col_idx] = columns[col_idx].sel->get_index(row_idx); + } + + // iterate list elements and create transformed expression columns + for (idx_t child_idx = 0; child_idx < list_entry.length; child_idx++) { + + // reached STANDARD_VECTOR_SIZE elements + if (elem_cnt == STANDARD_VECTOR_SIZE) { + + lambda_chunk.Reset(); + ExecuteExpression(types, result_types, elem_cnt, sel, sel_vectors, input_chunk, lambda_chunk, + child_vector, args, expr_executor); + + auto &lambda_vector = lambda_chunk.data[0]; + + if (IS_TRANSFORM) { + AppendTransformedToResult(lambda_vector, elem_cnt, result); + } else { + AppendFilteredToResult(lambda_vector, result_entries, elem_cnt, result, curr_list_len, + curr_list_offset, appended_lists_cnt, lists_len, curr_original_list_len, + input_chunk); + } + elem_cnt = 0; + } + + // to slice the child vector + auto source_idx = child_data.sel->get_index(list_entry.offset + child_idx); + sel.set_index(elem_cnt, source_idx); + + // for each column, set the index of the selection vector to slice properly + for (idx_t col_idx = 0; col_idx < args.ColumnCount() - 1; col_idx++) { + sel_vectors[col_idx].set_index(elem_cnt, indexes[col_idx]); + } + elem_cnt++; + } + } + + lambda_chunk.Reset(); + ExecuteExpression(types, result_types, elem_cnt, sel, sel_vectors, input_chunk, lambda_chunk, child_vector, args, + expr_executor); + auto &lambda_vector = lambda_chunk.data[0]; + + if (IS_TRANSFORM) { + AppendTransformedToResult(lambda_vector, elem_cnt, result); + } else { + AppendFilteredToResult(lambda_vector, result_entries, elem_cnt, result, curr_list_len, curr_list_offset, + appended_lists_cnt, lists_len, curr_original_list_len, input_chunk); + } + + if (args.AllConstant()) { + result.SetVectorType(VectorType::CONSTANT_VECTOR); + } +} + +static void ListTransformFunction(DataChunk &args, ExpressionState &state, Vector &result) { + ListLambdaFunction<>(args, state, result); +} + +static void ListFilterFunction(DataChunk &args, ExpressionState &state, Vector &result) { + ListLambdaFunction(args, state, result); +} + +template +static unique_ptr ListLambdaBind(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + + auto &bound_lambda_expr = (BoundLambdaExpression &)*arguments[1]; + if (bound_lambda_expr.parameter_count != LAMBDA_PARAM_CNT) { + throw BinderException("Incorrect number of parameters in lambda function! " + bound_function.name + + " expects " + to_string(LAMBDA_PARAM_CNT) + " parameter(s)."); + } + + if (arguments[0]->return_type.id() == LogicalTypeId::SQLNULL) { + bound_function.arguments.pop_back(); + bound_function.arguments[0] = LogicalType::SQLNULL; + bound_function.return_type = LogicalType::SQLNULL; + return make_unique(bound_function.return_type); + } + + if (arguments[0]->return_type.id() == LogicalTypeId::UNKNOWN) { + throw ParameterNotResolvedException(); + } + + D_ASSERT(arguments[0]->return_type.id() == LogicalTypeId::LIST); + + // get the lambda expression and put it in the bind info + auto lambda_expr = move(bound_lambda_expr.lambda_expr); + return make_unique(bound_function.return_type, move(lambda_expr)); +} + +static unique_ptr ListTransformBind(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + + // at least the list column and the lambda function + D_ASSERT(arguments.size() == 2); + if (arguments[1]->expression_class != ExpressionClass::BOUND_LAMBDA) { + throw BinderException("Invalid lambda expression!"); + } + + auto &bound_lambda_expr = (BoundLambdaExpression &)*arguments[1]; + bound_function.return_type = LogicalType::LIST(bound_lambda_expr.lambda_expr->return_type); + return ListLambdaBind<1>(context, bound_function, arguments); +} + +static unique_ptr ListFilterBind(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + + // at least the list column and the lambda function + D_ASSERT(arguments.size() == 2); + if (arguments[1]->expression_class != ExpressionClass::BOUND_LAMBDA) { + throw BinderException("Invalid lambda expression!"); + } + bound_function.return_type = arguments[0]->return_type; + return ListLambdaBind<1>(context, bound_function, arguments); +} + +void ListTransformFun::RegisterFunction(BuiltinFunctions &set) { + + ScalarFunction fun("list_transform", {LogicalType::LIST(LogicalType::ANY), LogicalType::LAMBDA}, + LogicalType::LIST(LogicalType::ANY), ListTransformFunction, ListTransformBind, nullptr, nullptr); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + fun.serialize = ListLambdaBindData::Serialize; + fun.deserialize = ListLambdaBindData::Deserialize; + set.AddFunction(fun); + + fun.name = "array_transform"; + set.AddFunction(fun); + fun.name = "list_apply"; + set.AddFunction(fun); + fun.name = "array_apply"; + set.AddFunction(fun); +} + +void ListFilterFun::RegisterFunction(BuiltinFunctions &set) { + + ScalarFunction fun("list_filter", {LogicalType::LIST(LogicalType::ANY), LogicalType::LAMBDA}, + LogicalType::LIST(LogicalType::ANY), ListFilterFunction, ListFilterBind, nullptr, nullptr); + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + fun.serialize = ListLambdaBindData::Serialize; + fun.deserialize = ListLambdaBindData::Deserialize; + set.AddFunction(fun); + + fun.name = "array_filter"; + set.AddFunction(fun); +} + +} // namespace duckdb + + + + + + + + namespace duckdb { @@ -99978,13 +109866,15 @@ void SinkDataChunk(Vector *child_vector, SelectionVector &sel, idx_t offset_list payload_chunk.data[0].Reference(payload_vector); payload_chunk.SetCardinality(offset_lists_indices); + key_chunk.Verify(); + payload_chunk.Verify(); + // sink local_sort_state.SinkChunk(key_chunk, payload_chunk); data_to_sort = true; } static void ListSortFunction(DataChunk &args, ExpressionState &state, Vector &result) { - D_ASSERT(args.ColumnCount() >= 1 && args.ColumnCount() <= 3); auto count = args.size(); Vector &lists = args.data[0]; @@ -99992,6 +109882,12 @@ static void ListSortFunction(DataChunk &args, ExpressionState &state, Vector &re result.SetVectorType(VectorType::FLAT_VECTOR); auto &result_validity = FlatVector::Validity(result); + for (auto &v : args.data) { + if (v.GetVectorType() != VectorType::FLAT_VECTOR && v.GetVectorType() != VectorType::CONSTANT_VECTOR) { + v.Flatten(count); + } + } + if (lists.GetType().id() == LogicalTypeId::SQLNULL) { result_validity.SetInvalid(0); return; @@ -100010,12 +109906,12 @@ static void ListSortFunction(DataChunk &args, ExpressionState &state, Vector &re // get the child vector auto lists_size = ListVector::GetListSize(lists); auto &child_vector = ListVector::GetEntry(lists); - VectorData child_data; - child_vector.Orrify(lists_size, child_data); + UnifiedVectorFormat child_data; + child_vector.ToUnifiedFormat(lists_size, child_data); // get the lists data - VectorData lists_data; - lists.Orrify(count, lists_data); + UnifiedVectorFormat lists_data; + lists.ToUnifiedFormat(count, lists_data); auto list_entries = (list_entry_t *)lists_data.data; // create the lists_indices vector, this contains an element for each list's entry, @@ -100039,7 +109935,6 @@ static void ListSortFunction(DataChunk &args, ExpressionState &state, Vector &re bool data_to_sort = false; for (idx_t i = 0; i < count; i++) { - auto lists_index = lists_data.sel->get_index(i); const auto &list_entry = list_entries[lists_index]; @@ -100055,7 +109950,6 @@ static void ListSortFunction(DataChunk &args, ExpressionState &state, Vector &re } for (idx_t child_idx = 0; child_idx < list_entry.length; child_idx++) { - // lists_indices vector is full, sink if (offset_lists_indices == STANDARD_VECTOR_SIZE) { SinkDataChunk(&child_vector, sel, offset_lists_indices, info.types, info.payload_types, payload_vector, @@ -100063,10 +109957,10 @@ static void ListSortFunction(DataChunk &args, ExpressionState &state, Vector &re offset_lists_indices = 0; } - auto source_idx = child_data.sel->get_index(list_entry.offset + child_idx); + auto source_idx = list_entry.offset + child_idx; sel.set_index(offset_lists_indices, source_idx); lists_indices_data[offset_lists_indices] = (uint32_t)i; - payload_vector_data[offset_lists_indices] = incr_payload_count; + payload_vector_data[offset_lists_indices] = source_idx; offset_lists_indices++; incr_payload_count++; } @@ -100078,7 +109972,6 @@ static void ListSortFunction(DataChunk &args, ExpressionState &state, Vector &re } if (data_to_sort) { - // add local state to global state, which sorts the data global_sort_state.AddLocalState(local_sort_state); global_sort_state.PrepareMergePhase(); @@ -100091,7 +109984,7 @@ static void ListSortFunction(DataChunk &args, ExpressionState &state, Vector &re PayloadScanner scanner(*global_sort_state.sorted_blocks[0]->payload_data, global_sort_state); for (;;) { DataChunk result_chunk; - result_chunk.Initialize(info.payload_types); + result_chunk.Initialize(Allocator::DefaultAllocator(), info.payload_types); result_chunk.SetCardinality(0); scanner.Scan(result_chunk); if (result_chunk.size() == 0) { @@ -100105,28 +109998,26 @@ static void ListSortFunction(DataChunk &args, ExpressionState &state, Vector &re for (idx_t i = 0; i < row_count; i++) { sel_sorted.set_index(sel_sorted_idx, result_data[i]); + D_ASSERT(result_data[i] < lists_size); sel_sorted_idx++; } } D_ASSERT(sel_sorted_idx == incr_payload_count); child_vector.Slice(sel_sorted, sel_sorted_idx); - child_vector.Normalify(sel_sorted_idx); + child_vector.Flatten(sel_sorted_idx); } result.Reference(lists); + + if (args.AllConstant()) { + result.SetVectorType(VectorType::CONSTANT_VECTOR); + } } static unique_ptr ListSortBind(ClientContext &context, ScalarFunction &bound_function, vector> &arguments, OrderType &order, OrderByNullType &null_order) { - - if (arguments[0]->return_type.id() == LogicalTypeId::SQLNULL) { - bound_function.arguments[0] = LogicalType::SQLNULL; - bound_function.return_type = LogicalType::SQLNULL; - return make_unique(bound_function.return_type); - } - bound_function.arguments[0] = arguments[0]->return_type; bound_function.return_type = arguments[0]->return_type; auto child_type = ListType::GetChildType(arguments[0]->return_type); @@ -100160,8 +110051,8 @@ static unique_ptr ListNormalSortBind(ClientContext &context, Scala // set default values auto &config = DBConfig::GetConfig(context); - auto order = config.default_order_type; - auto null_order = config.default_null_order; + auto order = config.options.default_order_type; + auto null_order = config.options.default_null_order; // get the sorting order if (arguments.size() >= 2) { @@ -100198,8 +110089,9 @@ static unique_ptr ListReverseSortBind(ClientContext &context, Scal // set (reverse) default values auto &config = DBConfig::GetConfig(context); - auto order = (config.default_order_type == OrderType::ASCENDING) ? OrderType::DESCENDING : OrderType::ASCENDING; - auto null_order = config.default_null_order; + auto order = + (config.options.default_order_type == OrderType::ASCENDING) ? OrderType::DESCENDING : OrderType::ASCENDING; + auto null_order = config.options.default_null_order; // get the null sorting order if (arguments.size() == 2) { @@ -100215,15 +110107,15 @@ void ListSortFun::RegisterFunction(BuiltinFunctions &set) { // one parameter: list ScalarFunction sort({LogicalType::LIST(LogicalType::ANY)}, LogicalType::LIST(LogicalType::ANY), ListSortFunction, - false, false, ListNormalSortBind); + ListNormalSortBind); // two parameters: list, order ScalarFunction sort_order({LogicalType::LIST(LogicalType::ANY), LogicalType::VARCHAR}, - LogicalType::LIST(LogicalType::ANY), ListSortFunction, false, false, ListNormalSortBind); + LogicalType::LIST(LogicalType::ANY), ListSortFunction, ListNormalSortBind); // three parameters: list, order, null order ScalarFunction sort_orders({LogicalType::LIST(LogicalType::ANY), LogicalType::VARCHAR, LogicalType::VARCHAR}, - LogicalType::LIST(LogicalType::ANY), ListSortFunction, false, false, ListNormalSortBind); + LogicalType::LIST(LogicalType::ANY), ListSortFunction, ListNormalSortBind); ScalarFunctionSet list_sort("list_sort"); list_sort.AddFunction(sort); @@ -100241,12 +110133,11 @@ void ListSortFun::RegisterFunction(BuiltinFunctions &set) { // one parameter: list ScalarFunction sort_reverse({LogicalType::LIST(LogicalType::ANY)}, LogicalType::LIST(LogicalType::ANY), - ListSortFunction, false, false, ListReverseSortBind); + ListSortFunction, ListReverseSortBind); // two parameters: list, null order ScalarFunction sort_reverse_null_order({LogicalType::LIST(LogicalType::ANY), LogicalType::VARCHAR}, - LogicalType::LIST(LogicalType::ANY), ListSortFunction, false, false, - ListReverseSortBind); + LogicalType::LIST(LogicalType::ANY), ListSortFunction, ListReverseSortBind); ScalarFunctionSet list_reverse_sort("list_reverse_sort"); list_reverse_sort.AddFunction(sort_reverse); @@ -100268,6 +110159,7 @@ void ListSortFun::RegisterFunction(BuiltinFunctions &set) { + namespace duckdb { static void ListValueFunction(DataChunk &args, ExpressionState &state, Vector &result) { @@ -100296,8 +110188,8 @@ static void ListValueFunction(DataChunk &args, ExpressionState &state, Vector &r static unique_ptr ListValueBind(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { // collect names and deconflict, construct return type - LogicalType child_type = LogicalType::SQLNULL; - for (idx_t i = 0; i < arguments.size(); i++) { + LogicalType child_type = arguments.empty() ? LogicalType::SQLNULL : arguments[0]->return_type; + for (idx_t i = 1; i < arguments.size(); i++) { child_type = LogicalType::MaxLogicalType(child_type, arguments[i]->return_type); } @@ -100324,9 +110216,10 @@ unique_ptr ListValueStats(ClientContext &context, FunctionStatis void ListValueFun::RegisterFunction(BuiltinFunctions &set) { // the arguments and return types are actually set in the binder function - ScalarFunction fun("list_value", {}, LogicalTypeId::LIST, ListValueFunction, false, ListValueBind, nullptr, + ScalarFunction fun("list_value", {}, LogicalTypeId::LIST, ListValueFunction, ListValueBind, nullptr, ListValueStats); fun.varargs = LogicalType::ANY; + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; set.AddFunction(fun); fun.name = "list_pack"; set.AddFunction(fun); @@ -100449,16 +110342,16 @@ class RangeInfoStruct { explicit RangeInfoStruct(DataChunk &args_p) : args(args_p) { switch (args.ColumnCount()) { case 1: - args.data[0].Orrify(args.size(), vdata[0]); + args.data[0].ToUnifiedFormat(args.size(), vdata[0]); break; case 2: - args.data[0].Orrify(args.size(), vdata[0]); - args.data[1].Orrify(args.size(), vdata[1]); + args.data[0].ToUnifiedFormat(args.size(), vdata[0]); + args.data[1].ToUnifiedFormat(args.size(), vdata[1]); break; case 3: - args.data[0].Orrify(args.size(), vdata[0]); - args.data[1].Orrify(args.size(), vdata[1]); - args.data[2].Orrify(args.size(), vdata[2]); + args.data[0].ToUnifiedFormat(args.size(), vdata[0]); + args.data[1].ToUnifiedFormat(args.size(), vdata[1]); + args.data[2].ToUnifiedFormat(args.size(), vdata[2]); break; default: throw InternalException("Unsupported number of parameters for range"); @@ -100519,7 +110412,7 @@ class RangeInfoStruct { private: DataChunk &args; - VectorData vdata[3]; + UnifiedVectorFormat vdata[3]; }; template @@ -100616,12 +110509,12 @@ namespace duckdb { static void CardinalityFunction(DataChunk &args, ExpressionState &state, Vector &result) { auto &map = args.data[0]; - VectorData list_data; + UnifiedVectorFormat list_data; result.SetVectorType(VectorType::FLAT_VECTOR); auto result_data = FlatVector::GetData(result); auto &children = StructVector::GetEntries(map); - children[0]->Orrify(args.size(), list_data); + children[0]->ToUnifiedFormat(args.size(), list_data); for (idx_t row = 0; row < args.size(); row++) { auto list_entry = ((list_entry_t *)list_data.data)[list_data.sel->get_index(row)]; result_data[row] = list_entry.length; @@ -100644,9 +110537,9 @@ static unique_ptr CardinalityBind(ClientContext &context, ScalarFu } void CardinalityFun::RegisterFunction(BuiltinFunctions &set) { - ScalarFunction fun("cardinality", {LogicalType::ANY}, LogicalType::UBIGINT, CardinalityFunction, false, - CardinalityBind); + ScalarFunction fun("cardinality", {LogicalType::ANY}, LogicalType::UBIGINT, CardinalityFunction, CardinalityBind); fun.varargs = LogicalType::ANY; + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; set.AddFunction(fun); } @@ -100699,19 +110592,19 @@ namespace duckdb { // TODO: this doesn't recursively verify maps if maps are nested MapInvalidReason CheckMapValidity(Vector &map, idx_t count, const SelectionVector &sel) { D_ASSERT(map.GetType().id() == LogicalTypeId::MAP); - VectorData map_vdata; - map.Orrify(count, map_vdata); + UnifiedVectorFormat map_vdata; + map.ToUnifiedFormat(count, map_vdata); auto &map_validity = map_vdata.validity; auto &key_vector = *(StructVector::GetEntries(map)[0]); - VectorData key_vdata; - key_vector.Orrify(count, key_vdata); + UnifiedVectorFormat key_vdata; + key_vector.ToUnifiedFormat(count, key_vdata); auto key_data = (list_entry_t *)key_vdata.data; auto &key_validity = key_vdata.validity; auto &key_entries = ListVector::GetEntry(key_vector); - VectorData key_entry_vdata; - key_entries.Orrify(count, key_entry_vdata); + UnifiedVectorFormat key_entry_vdata; + key_entries.ToUnifiedFormat(count, key_entry_vdata); auto &entry_validity = key_entry_vdata.validity; for (idx_t row = 0; row < count; row++) { @@ -100742,7 +110635,7 @@ MapInvalidReason CheckMapValidity(Vector &map, idx_t count, const SelectionVecto return MapInvalidReason::VALID; } -static void MapConversionVerify(Vector &vector, idx_t count) { +void MapConversionVerify(Vector &vector, idx_t count) { auto valid_check = CheckMapValidity(vector, count); switch (valid_check) { case MapInvalidReason::VALID: @@ -100795,8 +110688,12 @@ static void MapFunction(DataChunk &args, ExpressionState &state, Vector &result) return; } - if (ListVector::GetListSize(args.data[0]) != ListVector::GetListSize(args.data[1])) { - throw Exception("Key list has a different size from Value list"); + auto key_count = ListVector::GetListSize(args.data[0]); + auto value_count = ListVector::GetListSize(args.data[1]); + if (key_count != value_count) { + throw InvalidInputException( + "Error in MAP creation: key list has a different size from value list (%lld keys, %lld values)", key_count, + value_count); } key_vector.Reference(args.data[0]); @@ -100837,8 +110734,9 @@ static unique_ptr MapBind(ClientContext &context, ScalarFunction & void MapFun::RegisterFunction(BuiltinFunctions &set) { //! the arguments and return types are actually set in the binder function - ScalarFunction fun("map", {}, LogicalTypeId::MAP, MapFunction, false, MapBind); + ScalarFunction fun("map", {}, LogicalTypeId::MAP, MapFunction, MapBind); fun.varargs = LogicalType::ANY; + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; set.AddFunction(fun); } @@ -100860,7 +110758,7 @@ void FillResult(Value &values, Vector &result, idx_t row) { } //! now set the pointer - auto &entry = ((list_entry_t *)result.GetData())[row]; + auto &entry = ListVector::GetData(result)[row]; entry.length = list_values.size(); entry.offset = current_offset; } @@ -100870,19 +110768,29 @@ static void MapExtractFunction(DataChunk &args, ExpressionState &state, Vector & D_ASSERT(args.data[0].GetType().id() == LogicalTypeId::MAP); result.SetVectorType(VectorType::FLAT_VECTOR); + if (args.data[1].GetType().id() == LogicalTypeId::SQLNULL) { + //! We don't need to look through the map if the 'key' to look for is NULL + //! Because maps can't have NULL as key + ListVector::SetListSize(result, 0); + result.SetVectorType(VectorType::CONSTANT_VECTOR); + auto list_data = ConstantVector::GetData(result); + list_data->offset = 0; + list_data->length = 0; + result.Verify(args.size()); + return; + } + auto &map = args.data[0]; auto &key = args.data[1]; - auto key_value = key.GetValue(0); - VectorData offset_data; + UnifiedVectorFormat offset_data; auto &children = StructVector::GetEntries(map); - children[0]->Orrify(args.size(), offset_data); - auto &key_type = ListType::GetChildType(children[0]->GetType()); - if (key_type != LogicalTypeId::SQLNULL) { - key_value = key_value.CastAs(key_type); - } + + children[0]->ToUnifiedFormat(args.size(), offset_data); for (idx_t row = 0; row < args.size(); row++) { + idx_t row_index = offset_data.sel->get_index(row); + auto key_value = key.GetValue(row_index); auto offsets = ListVector::Search(*children[0], key_value, offset_data.sel->get_index(row)); auto values = ListVector::GetValuesFromOffsets(*children[1], offsets); FillResult(values, result, row); @@ -100903,24 +110811,202 @@ static unique_ptr MapExtractBind(ClientContext &context, ScalarFun if (arguments[0]->return_type.id() != LogicalTypeId::MAP) { throw BinderException("MAP_EXTRACT can only operate on MAPs"); } - auto &child_types = StructType::GetChildTypes(arguments[0]->return_type); - auto &value_type = ListType::GetChildType(child_types[1].second); + auto &value_type = MapType::ValueType(arguments[0]->return_type); //! Here we have to construct the List Type that will be returned bound_function.return_type = LogicalType::LIST(value_type); + auto key_type = MapType::KeyType(arguments[0]->return_type); + if (key_type.id() != LogicalTypeId::SQLNULL && arguments[1]->return_type.id() != LogicalTypeId::SQLNULL) { + bound_function.arguments[1] = MapType::KeyType(arguments[0]->return_type); + } return make_unique(value_type); } void MapExtractFun::RegisterFunction(BuiltinFunctions &set) { - ScalarFunction fun("map_extract", {LogicalType::ANY, LogicalType::ANY}, LogicalType::ANY, MapExtractFunction, false, + ScalarFunction fun("map_extract", {LogicalType::ANY, LogicalType::ANY}, LogicalType::ANY, MapExtractFunction, MapExtractBind); fun.varargs = LogicalType::ANY; + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; set.AddFunction(fun); fun.name = "element_at"; set.AddFunction(fun); } } // namespace duckdb + + + + + + + +namespace duckdb { + +struct VectorInfo { + Vector &container; + list_entry_t &data; +}; + +static void MapStruct(Value &element, VectorInfo &keys, VectorInfo &values) { + D_ASSERT(element.type().id() == LogicalTypeId::STRUCT); + D_ASSERT(!element.IsNull()); + auto &key_value = StructValue::GetChildren(element); + auto &key = key_value[0]; + auto &value = key_value[1]; + + if (key.IsNull()) { + throw InvalidInputException("None of the keys of the map can be NULL"); + } + // Add to the inner key/value lists of the resulting map + ListVector::PushBack(keys.container, key); + ListVector::PushBack(values.container, value); +} + +// FIXME: this operation has a time complexity of O(n^2) +void CheckKeyUniqueness(VectorInfo &keys) { + auto end = keys.data.offset + keys.data.length; + auto &entries = ListVector::GetEntry(keys.container); + for (auto lhs = keys.data.offset; lhs < end; lhs++) { + auto element = entries.GetValue(lhs); + D_ASSERT(!element.IsNull()); + for (auto rhs = lhs + 1; rhs < end; rhs++) { + auto other = entries.GetValue(rhs); + D_ASSERT(!other.IsNull()); + + if (element.type() != other.type()) { + throw InvalidInputException("Not all keys are of the same type!"); + } + if (element == other) { + throw InvalidInputException("The given keys aren't unique"); + } + } + } +} + +static bool MapSingleList(VectorInfo &input, VectorInfo &keys, VectorInfo &values) { + // Get the length and offset of this list from the argument data + auto pair_amount = input.data.length; + auto input_offset = input.data.offset; + + // Loop over the list of structs + idx_t inserted_values = 0; + for (idx_t i = 0; i < pair_amount; i++) { + auto index = i + input_offset; + // Get the struct using the offset and the index; + auto element = input.container.GetValue(index); + if (element.IsNull()) { + continue; + } + MapStruct(element, keys, values); + inserted_values++; + } + // Set the length of the key value lists + keys.data.length = inserted_values; + values.data.length = inserted_values; + return inserted_values != 0; +} + +static void MapFromEntriesFunction(DataChunk &args, ExpressionState &state, Vector &result) { + D_ASSERT(result.GetType().id() == LogicalTypeId::MAP); + + result.SetVectorType(duckdb::VectorType::FLAT_VECTOR); + + // Get the arguments vector + auto &input_list = args.data[0]; + auto arg_data = FlatVector::GetData(input_list); + auto &entries = ListVector::GetEntry(input_list); + + // Prepare the result vectors + auto &child_entries = StructVector::GetEntries(result); + D_ASSERT(child_entries.size() == 2); + auto &key_vector = *child_entries[0]; + auto &value_vector = *child_entries[1]; + auto &result_validity = FlatVector::Validity(result); + + // Get the offset+length data for the list(s) + auto key_data = FlatVector::GetData(key_vector); + auto value_data = FlatVector::GetData(value_vector); + + auto &key_validity = FlatVector::Validity(key_vector); + auto &value_validity = FlatVector::Validity(value_vector); + + auto count = args.size(); + + UnifiedVectorFormat input_list_data; + input_list.ToUnifiedFormat(count, input_list_data); + + // Current offset into the keys/values list + idx_t offset = 0; + + // Transform to mapped values + for (idx_t i = 0; i < count; i++) { + VectorInfo input {entries, arg_data[i]}; + VectorInfo keys {key_vector, key_data[i]}; + VectorInfo values {value_vector, value_data[i]}; + + keys.data.offset = offset; + values.data.offset = offset; + auto row_valid = MapSingleList(input, keys, values); + offset += keys.data.length; + + // Check validity + if (!row_valid || !input_list_data.validity.RowIsValid(i)) { + key_validity.SetInvalid(i); + value_validity.SetInvalid(i); + result_validity.SetInvalid(i); + } + } + MapConversionVerify(result, count); + result.Verify(count); + + if (args.AllConstant()) { + result.SetVectorType(VectorType::CONSTANT_VECTOR); + } +} + +static unique_ptr MapFromEntriesBind(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + child_list_t child_types; + + if (arguments.size() != 1) { + throw InvalidInputException("The input argument must be a list of structs."); + } + auto &list = arguments[0]->return_type; + + if (list.id() == LogicalTypeId::UNKNOWN) { + bound_function.arguments.emplace_back(LogicalTypeId::UNKNOWN); + bound_function.return_type = LogicalType(LogicalTypeId::SQLNULL); + return nullptr; + } + + if (list.id() != LogicalTypeId::LIST) { + throw InvalidInputException("The provided argument is not a list of structs"); + } + auto &elem_type = ListType::GetChildType(list); + if (elem_type.id() != LogicalTypeId::STRUCT) { + throw InvalidInputException("The elements of the list must be structs"); + } + auto &children = StructType::GetChildTypes(elem_type); + if (children.size() != 2) { + throw InvalidInputException("The provided struct type should only contain 2 fields, a key and a value"); + } + child_types.push_back(make_pair("key", LogicalType::LIST(children[0].second))); + child_types.push_back(make_pair("value", LogicalType::LIST(children[1].second))); + + //! this is more for completeness reasons + bound_function.return_type = LogicalType::MAP(move(child_types)); + return make_unique(bound_function.return_type); +} + +void MapFromEntriesFun::RegisterFunction(BuiltinFunctions &set) { + //! the arguments and return types are actually set in the binder function + ScalarFunction fun("map_from_entries", {}, LogicalTypeId::MAP, MapFromEntriesFunction, MapFromEntriesBind); + fun.null_handling = FunctionNullHandling::DEFAULT_NULL_HANDLING; + fun.varargs = LogicalType::ANY; + set.AddFunction(fun); +} + +} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB // @@ -101153,10 +111239,9 @@ void NextAfterFun::RegisterFunction(BuiltinFunctions &set) { ScalarFunctionSet next_after_fun("nextafter"); next_after_fun.AddFunction( ScalarFunction("nextafter", {LogicalType::DOUBLE, LogicalType::DOUBLE}, LogicalType::DOUBLE, - ScalarFunction::BinaryFunction, false)); + ScalarFunction::BinaryFunction)); next_after_fun.AddFunction(ScalarFunction("nextafter", {LogicalType::FLOAT, LogicalType::FLOAT}, LogicalType::FLOAT, - ScalarFunction::BinaryFunction, - false)); + ScalarFunction::BinaryFunction)); set.AddFunction(next_after_fun); } @@ -101256,7 +111341,7 @@ void AbsFun::RegisterFunction(BuiltinFunctions &set) { for (auto &type : LogicalType::Numeric()) { switch (type.id()) { case LogicalTypeId::DECIMAL: - abs.AddFunction(ScalarFunction({type}, type, nullptr, false, false, DecimalUnaryOpBind)); + abs.AddFunction(ScalarFunction({type}, type, nullptr, DecimalUnaryOpBind)); break; case LogicalTypeId::TINYINT: case LogicalTypeId::SMALLINT: @@ -101291,8 +111376,24 @@ struct BitCntOperator { static inline TR Operation(TA input) { using TU = typename std::make_unsigned::type; TR count = 0; - for (auto value = TU(input); value > 0; value >>= 1) { - count += TR(value & 1); + for (auto value = TU(input); value; ++count) { + value &= (value - 1); + } + return count; + } +}; + +struct HugeIntBitCntOperator { + template + static inline TR Operation(TA input) { + using TU = typename std::make_unsigned::type; + TR count = 0; + + for (auto value = TU(input.upper); value; ++count) { + value &= (value - 1); + } + for (auto value = TU(input.lower); value; ++count) { + value &= (value - 1); } return count; } @@ -101308,6 +111409,8 @@ void BitCountFun::RegisterFunction(BuiltinFunctions &set) { ScalarFunction::UnaryFunction)); functions.AddFunction(ScalarFunction({LogicalType::BIGINT}, LogicalType::TINYINT, ScalarFunction::UnaryFunction)); + functions.AddFunction(ScalarFunction({LogicalType::HUGEINT}, LogicalType::TINYINT, + ScalarFunction::UnaryFunction)); set.AddFunction(functions); } @@ -101447,7 +111550,7 @@ void CeilFun::RegisterFunction(BuiltinFunctions &set) { default: throw InternalException("Unimplemented numeric type for function \"ceil\""); } - ceil.AddFunction(ScalarFunction({type}, type, func, false, false, bind_func)); + ceil.AddFunction(ScalarFunction({type}, type, func, bind_func)); } set.AddFunction(ceil); @@ -101503,7 +111606,7 @@ void FloorFun::RegisterFunction(BuiltinFunctions &set) { default: throw InternalException("Unimplemented numeric type for function \"floor\""); } - floor.AddFunction(ScalarFunction({type}, type, func, false, false, bind_func)); + floor.AddFunction(ScalarFunction({type}, type, func, bind_func)); } set.AddFunction(floor); } @@ -101628,6 +111731,9 @@ static void DecimalRoundPositivePrecisionFunction(DataChunk &input, ExpressionSt unique_ptr BindDecimalRoundPrecision(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { auto &decimal_type = arguments[0]->return_type; + if (arguments[1]->HasParameter()) { + throw ParameterNotResolvedException(); + } if (!arguments[1]->IsFoldable()) { throw NotImplementedException("ROUND(DECIMAL, INTEGER) with non-constant precision is not supported"); } @@ -101715,9 +111821,8 @@ void RoundFun::RegisterFunction(BuiltinFunctions &set) { default: throw InternalException("Unimplemented numeric type for function \"floor\""); } - round.AddFunction(ScalarFunction({type}, type, round_func, false, false, bind_func)); - round.AddFunction( - ScalarFunction({type, LogicalType::INTEGER}, type, round_prec_func, false, false, bind_prec_func)); + round.AddFunction(ScalarFunction({type}, type, round_func, bind_func)); + round.AddFunction(ScalarFunction({type, LogicalType::INTEGER}, type, round_prec_func, bind_prec_func)); } set.AddFunction(round); } @@ -102283,8 +112388,10 @@ static unique_ptr RandomInitLocalState(const BoundFunctionEx } void RandomFun::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction(ScalarFunction("random", {}, LogicalType::DOUBLE, RandomFunction, true, RandomBind, nullptr, - nullptr, RandomInitLocalState)); + ScalarFunction random("random", {}, LogicalType::DOUBLE, RandomFunction, RandomBind, nullptr, nullptr, + RandomInitLocalState); + random.side_effects = FunctionSideEffects::HAS_SIDE_EFFECTS; + set.AddFunction(random); } static void GenerateUUIDFunction(DataChunk &args, ExpressionState &state, Vector &result) { @@ -102295,42 +112402,15 @@ static void GenerateUUIDFunction(DataChunk &args, ExpressionState &state, Vector auto result_data = FlatVector::GetData(result); for (idx_t i = 0; i < args.size(); i++) { - uint8_t bytes[16]; - for (int i = 0; i < 16; i += 4) { - *reinterpret_cast(bytes + i) = lstate.random_engine.NextRandomInteger(); - } - // variant must be 10xxxxxx - bytes[8] &= 0xBF; - bytes[8] |= 0x80; - // version must be 0100xxxx - bytes[6] &= 0x4F; - bytes[6] |= 0x40; - - result_data[i].upper = 0; - result_data[i].upper |= ((int64_t)bytes[0] << 56); - result_data[i].upper |= ((int64_t)bytes[1] << 48); - result_data[i].upper |= ((int64_t)bytes[3] << 40); - result_data[i].upper |= ((int64_t)bytes[4] << 32); - result_data[i].upper |= ((int64_t)bytes[5] << 24); - result_data[i].upper |= ((int64_t)bytes[6] << 16); - result_data[i].upper |= ((int64_t)bytes[7] << 8); - result_data[i].upper |= bytes[8]; - result_data[i].lower = 0; - result_data[i].lower |= ((uint64_t)bytes[8] << 56); - result_data[i].lower |= ((uint64_t)bytes[9] << 48); - result_data[i].lower |= ((uint64_t)bytes[10] << 40); - result_data[i].lower |= ((uint64_t)bytes[11] << 32); - result_data[i].lower |= ((uint64_t)bytes[12] << 24); - result_data[i].lower |= ((uint64_t)bytes[13] << 16); - result_data[i].lower |= ((uint64_t)bytes[14] << 8); - result_data[i].lower |= bytes[15]; + result_data[i] = UUID::GenerateRandomUUID(lstate.random_engine); } } void UUIDFun::RegisterFunction(BuiltinFunctions &set) { - ScalarFunction uuid_function({}, LogicalType::UUID, GenerateUUIDFunction, false, true, RandomBind, nullptr, nullptr, + ScalarFunction uuid_function({}, LogicalType::UUID, GenerateUUIDFunction, RandomBind, nullptr, nullptr, RandomInitLocalState); // generate a random uuid + uuid_function.side_effects = FunctionSideEffects::HAS_SIDE_EFFECTS; set.AddFunction({"uuid", "gen_random_uuid"}, uuid_function); } @@ -102366,7 +112446,7 @@ static void SetSeedFunction(DataChunk &args, ExpressionState &state, Vector &res auto &func_expr = (BoundFunctionExpression &)state.expr; auto &info = (SetseedBindData &)*func_expr.bind_info; auto &input = args.data[0]; - input.Normalify(args.size()); + input.Flatten(args.size()); auto input_seeds = FlatVector::GetData(input); uint32_t half_max = NumericLimits::Maximum() / 2; @@ -102390,8 +112470,9 @@ unique_ptr SetSeedBind(ClientContext &context, ScalarFunction &bou } void SetseedFun::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction( - ScalarFunction("setseed", {LogicalType::DOUBLE}, LogicalType::SQLNULL, SetSeedFunction, true, SetSeedBind)); + ScalarFunction setseed("setseed", {LogicalType::DOUBLE}, LogicalType::SQLNULL, SetSeedFunction, SetSeedBind); + setseed.side_effects = FunctionSideEffects::HAS_SIDE_EFFECTS; + set.AddFunction(setseed); } } // namespace duckdb @@ -102448,6 +112529,9 @@ void BuiltinFunctions::RegisterNestedFunctions() { Register(); Register(); Register(); + Register(); + Register(); + Register(); Register(); Register(); Register(); @@ -102460,6 +112544,7 @@ void BuiltinFunctions::RegisterNestedFunctions() { Register(); Register(); Register(); + Register(); Register(); Register(); } @@ -102713,6 +112798,7 @@ dtime_t AddTimeOperator::Operation(interval_t left, dtime_t right) { + //===----------------------------------------------------------------------===// // DuckDB // @@ -102879,6 +112965,24 @@ struct SubtractPropagateStatistics { } }; +struct DecimalArithmeticBindData : public FunctionData { + DecimalArithmeticBindData() : check_overflow(true) { + } + + unique_ptr Copy() const override { + auto res = make_unique(); + res->check_overflow = check_overflow; + return move(res); + } + + bool Equals(const FunctionData &other_p) const override { + auto other = (DecimalArithmeticBindData &)other_p; + return other.check_overflow == check_overflow; + } + + bool check_overflow; +}; + template static unique_ptr PropagateNumericStats(ClientContext &context, FunctionStatisticsInput &input) { auto &child_stats = input.child_stats; @@ -102919,6 +113023,10 @@ static unique_ptr PropagateNumericStats(ClientContext &context, new_max = Value(expr.return_type); } else { // no potential overflow: replace with non-overflowing operator + if (input.bind_data) { + auto bind_data = (DecimalArithmeticBindData *)input.bind_data; + bind_data->check_overflow = false; + } expr.function.function = GetScalarIntegerFunction(expr.return_type.InternalType()); } auto stats = @@ -102930,6 +113038,9 @@ static unique_ptr PropagateNumericStats(ClientContext &context, template unique_ptr BindDecimalAddSubtract(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { + + auto bind_data = make_unique(); + // get the max width and scale of the input arguments uint8_t max_width = 0, max_scale = 0, max_width_over_scale = 0; for (idx_t i = 0; i < arguments.size(); i++) { @@ -102947,16 +113058,15 @@ unique_ptr BindDecimalAddSubtract(ClientContext &context, ScalarFu } D_ASSERT(max_width > 0); // for addition/subtraction, we add 1 to the width to ensure we don't overflow - bool check_overflow = false; auto required_width = MaxValue(max_scale + max_width_over_scale, max_width) + 1; if (required_width > Decimal::MAX_WIDTH_INT64 && max_width <= Decimal::MAX_WIDTH_INT64) { // we don't automatically promote past the hugeint boundary to avoid the large hugeint performance penalty - check_overflow = true; + bind_data->check_overflow = true; required_width = Decimal::MAX_WIDTH_INT64; } if (required_width > Decimal::MAX_WIDTH_DECIMAL) { // target width does not fit in decimal at all: truncate the scale and perform overflow detection - check_overflow = true; + bind_data->check_overflow = true; required_width = Decimal::MAX_WIDTH_DECIMAL; } // arithmetic between two decimal arguments: check the types of the input arguments @@ -102976,7 +113086,7 @@ unique_ptr BindDecimalAddSubtract(ClientContext &context, ScalarFu } bound_function.return_type = result_type; // now select the physical function to execute - if (check_overflow) { + if (bind_data->check_overflow) { bound_function.function = GetScalarBinaryFunction(result_type.InternalType()); } else { bound_function.function = GetScalarBinaryFunction(result_type.InternalType()); @@ -102989,7 +113099,39 @@ unique_ptr BindDecimalAddSubtract(ClientContext &context, ScalarFu bound_function.statistics = PropagateNumericStats; } } - return nullptr; + return move(bind_data); +} + +static void SerializeDecimalArithmetic(FieldWriter &writer, const FunctionData *bind_data_p, + const ScalarFunction &function) { + D_ASSERT(bind_data_p); + auto bind_data = (DecimalArithmeticBindData *)bind_data_p; + writer.WriteField(bind_data->check_overflow); + writer.WriteSerializable(function.return_type); + writer.WriteRegularSerializableList(function.arguments); +} + +// TODO this is partially duplicated from the bind +template +unique_ptr DeserializeDecimalArithmetic(ClientContext &context, FieldReader &reader, + ScalarFunction &bound_function) { + // re-change the function pointers + auto check_overflow = reader.ReadRequired(); + auto return_type = reader.ReadRequiredSerializable(); + auto arguments = reader.template ReadRequiredSerializableList(); + + if (check_overflow) { + bound_function.function = GetScalarBinaryFunction(return_type.InternalType()); + } else { + bound_function.function = GetScalarBinaryFunction(return_type.InternalType()); + } + bound_function.statistics = nullptr; // TODO we likely dont want to do stats prop again + bound_function.return_type = return_type; + bound_function.arguments = arguments; + + auto bind_data = make_unique(); + bind_data->check_overflow = check_overflow; + return move(bind_data); } unique_ptr NopDecimalBind(ClientContext &context, ScalarFunction &bound_function, @@ -103002,7 +113144,7 @@ unique_ptr NopDecimalBind(ClientContext &context, ScalarFunction & ScalarFunction AddFun::GetFunction(const LogicalType &type) { D_ASSERT(type.IsNumeric()); if (type.id() == LogicalTypeId::DECIMAL) { - return ScalarFunction("+", {type}, type, ScalarFunction::NopFunction, false, NopDecimalBind); + return ScalarFunction("+", {type}, type, ScalarFunction::NopFunction, NopDecimalBind); } else { return ScalarFunction("+", {type}, type, ScalarFunction::NopFunction); } @@ -103011,13 +113153,15 @@ ScalarFunction AddFun::GetFunction(const LogicalType &type) { ScalarFunction AddFun::GetFunction(const LogicalType &left_type, const LogicalType &right_type) { if (left_type.IsNumeric() && left_type.id() == right_type.id()) { if (left_type.id() == LogicalTypeId::DECIMAL) { - return ScalarFunction("+", {left_type, right_type}, left_type, nullptr, false, - BindDecimalAddSubtract); + auto function = ScalarFunction("+", {left_type, right_type}, left_type, nullptr, + BindDecimalAddSubtract); + function.serialize = SerializeDecimalArithmetic; + function.deserialize = DeserializeDecimalArithmetic; + return function; } else if (left_type.IsIntegral() && left_type.id() != LogicalTypeId::HUGEINT) { return ScalarFunction("+", {left_type, right_type}, left_type, - GetScalarIntegerFunction(left_type.InternalType()), false, - nullptr, nullptr, - PropagateNumericStats); + GetScalarIntegerFunction(left_type.InternalType()), nullptr, + nullptr, PropagateNumericStats); } else { return ScalarFunction("+", {left_type, right_type}, left_type, GetScalarBinaryFunction(left_type.InternalType())); @@ -103157,8 +113301,29 @@ interval_t NegateOperator::Operation(interval_t input) { return result; } +struct DecimalNegateBindData : public FunctionData { + DecimalNegateBindData() : bound_type(LogicalTypeId::INVALID) { + } + + unique_ptr Copy() const override { + auto res = make_unique(); + res->bound_type = bound_type; + return move(res); + } + + bool Equals(const FunctionData &other_p) const override { + auto other = (DecimalNegateBindData &)other_p; + return other.bound_type == bound_type; + } + + LogicalTypeId bound_type; +}; + unique_ptr DecimalNegateBind(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { + + auto bind_data = make_unique(); + auto &decimal_type = arguments[0]->return_type; auto width = DecimalType::GetWidth(decimal_type); if (width <= Decimal::MAX_WIDTH_INT16) { @@ -103242,24 +113407,29 @@ ScalarFunction SubtractFun::GetFunction(const LogicalType &type) { if (type.id() == LogicalTypeId::INTERVAL) { return ScalarFunction("-", {type}, type, ScalarFunction::UnaryFunction); } else if (type.id() == LogicalTypeId::DECIMAL) { - return ScalarFunction("-", {type}, type, nullptr, false, DecimalNegateBind, nullptr, NegateBindStatistics); + return ScalarFunction("-", {type}, type, nullptr, DecimalNegateBind, nullptr, NegateBindStatistics); } else { D_ASSERT(type.IsNumeric()); - return ScalarFunction("-", {type}, type, ScalarFunction::GetScalarUnaryFunction(type), false, - nullptr, nullptr, NegateBindStatistics); + return ScalarFunction("-", {type}, type, ScalarFunction::GetScalarUnaryFunction(type), nullptr, + nullptr, NegateBindStatistics); } } ScalarFunction SubtractFun::GetFunction(const LogicalType &left_type, const LogicalType &right_type) { if (left_type.IsNumeric() && left_type.id() == right_type.id()) { if (left_type.id() == LogicalTypeId::DECIMAL) { - return ScalarFunction("-", {left_type, right_type}, left_type, nullptr, false, - BindDecimalAddSubtract); + auto function = + ScalarFunction("-", {left_type, right_type}, left_type, nullptr, + BindDecimalAddSubtract); + function.serialize = SerializeDecimalArithmetic; + function.deserialize = DeserializeDecimalArithmetic; + return function; } else if (left_type.IsIntegral() && left_type.id() != LogicalTypeId::HUGEINT) { return ScalarFunction( "-", {left_type, right_type}, left_type, - GetScalarIntegerFunction(left_type.InternalType()), false, nullptr, - nullptr, PropagateNumericStats); + GetScalarIntegerFunction(left_type.InternalType()), nullptr, nullptr, + PropagateNumericStats); + } else { return ScalarFunction("-", {left_type, right_type}, left_type, GetScalarBinaryFunction(left_type.InternalType())); @@ -103271,6 +113441,7 @@ ScalarFunction SubtractFun::GetFunction(const LogicalType &left_type, const Logi if (right_type.id() == LogicalTypeId::DATE) { return ScalarFunction("-", {left_type, right_type}, LogicalType::BIGINT, ScalarFunction::BinaryFunction); + } else if (right_type.id() == LogicalTypeId::INTEGER) { return ScalarFunction("-", {left_type, right_type}, LogicalType::DATE, ScalarFunction::BinaryFunction); @@ -103381,6 +113552,9 @@ struct MultiplyPropagateStatistics { unique_ptr BindDecimalMultiply(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { + + auto bind_data = make_unique(); + uint8_t result_width = 0, result_scale = 0; uint8_t max_width = 0; for (idx_t i = 0; i < arguments.size(); i++) { @@ -103406,14 +113580,13 @@ unique_ptr BindDecimalMultiply(ClientContext &context, ScalarFunct "or add an explicit cast to a decimal with a lower scale.", result_scale, Decimal::MAX_WIDTH_DECIMAL); } - bool check_overflow = false; if (result_width > Decimal::MAX_WIDTH_INT64 && max_width <= Decimal::MAX_WIDTH_INT64 && result_scale < Decimal::MAX_WIDTH_INT64) { - check_overflow = true; + bind_data->check_overflow = true; result_width = Decimal::MAX_WIDTH_INT64; } if (result_width > Decimal::MAX_WIDTH_DECIMAL) { - check_overflow = true; + bind_data->check_overflow = true; result_width = Decimal::MAX_WIDTH_DECIMAL; } LogicalType result_type = LogicalType::DECIMAL(result_width, result_scale); @@ -103435,7 +113608,7 @@ unique_ptr BindDecimalMultiply(ClientContext &context, ScalarFunct result_type.Verify(); bound_function.return_type = result_type; // now select the physical function to execute - if (check_overflow) { + if (bind_data->check_overflow) { bound_function.function = GetScalarBinaryFunction(result_type.InternalType()); } else { bound_function.function = GetScalarBinaryFunction(result_type.InternalType()); @@ -103444,30 +113617,33 @@ unique_ptr BindDecimalMultiply(ClientContext &context, ScalarFunct bound_function.statistics = PropagateNumericStats; } - return nullptr; + return move(bind_data); } void MultiplyFun::RegisterFunction(BuiltinFunctions &set) { ScalarFunctionSet functions("*"); for (auto &type : LogicalType::Numeric()) { if (type.id() == LogicalTypeId::DECIMAL) { - functions.AddFunction(ScalarFunction({type, type}, type, nullptr, true, false, BindDecimalMultiply)); + ScalarFunction function({type, type}, type, nullptr, BindDecimalMultiply); + function.serialize = SerializeDecimalArithmetic; + function.deserialize = DeserializeDecimalArithmetic; + functions.AddFunction(function); } else if (TypeIsIntegral(type.InternalType()) && type.id() != LogicalTypeId::HUGEINT) { functions.AddFunction(ScalarFunction( - {type, type}, type, GetScalarIntegerFunction(type.InternalType()), true, - false, nullptr, nullptr, + {type, type}, type, GetScalarIntegerFunction(type.InternalType()), + nullptr, nullptr, PropagateNumericStats)); } else { - functions.AddFunction(ScalarFunction({type, type}, type, - GetScalarBinaryFunction(type.InternalType()), true)); + functions.AddFunction( + ScalarFunction({type, type}, type, GetScalarBinaryFunction(type.InternalType()))); } } functions.AddFunction( ScalarFunction({LogicalType::INTERVAL, LogicalType::BIGINT}, LogicalType::INTERVAL, - ScalarFunction::BinaryFunction, true)); + ScalarFunction::BinaryFunction)); functions.AddFunction( ScalarFunction({LogicalType::BIGINT, LogicalType::INTERVAL}, LogicalType::INTERVAL, - ScalarFunction::BinaryFunction, true)); + ScalarFunction::BinaryFunction)); set.AddFunction(functions); functions.name = "multiply"; @@ -104108,8 +114284,6 @@ hugeint_t DecimalMultiplyOverflowCheck::Operation(hugeint_t left, hugeint_t righ -#include - namespace duckdb { //===--------------------------------------------------------------------===// @@ -104166,18 +114340,12 @@ interval_t SubtractOperator::Operation(interval_t left, interval_t right) { template <> date_t SubtractOperator::Operation(date_t left, interval_t right) { - right.months = -right.months; - right.days = -right.days; - right.micros = -right.micros; - return AddOperator::Operation(left, right); + return AddOperator::Operation(left, Interval::Invert(right)); } template <> timestamp_t SubtractOperator::Operation(timestamp_t left, interval_t right) { - right.months = -right.months; - right.days = -right.days; - right.micros = -right.micros; - return AddOperator::Operation(left, right); + return AddOperator::Operation(left, Interval::Invert(right)); } template <> @@ -104400,7 +114568,6 @@ struct CurrvalFun { - namespace duckdb { struct NextvalBindData : public FunctionData { @@ -104512,8 +114679,7 @@ static unique_ptr NextValBind(ClientContext &context, ScalarFuncti // evaluate the constant and perform the catalog lookup already auto seqname = ExpressionExecutor::EvaluateScalar(*arguments[0]); if (!seqname.IsNull()) { - D_ASSERT(seqname.type().id() == LogicalTypeId::VARCHAR); - auto qname = QualifiedName::Parse(StringValue::Get(seqname)); + auto qname = QualifiedName::Parse(seqname.ToString()); sequence = Catalog::GetCatalog(context).GetEntry(context, qname.schema, qname.name); } } @@ -104528,14 +114694,17 @@ static void NextValDependency(BoundFunctionExpression &expr, unordered_set, true, NextValBind, NextValDependency)); + ScalarFunction next_val("nextval", {LogicalType::VARCHAR}, LogicalType::BIGINT, + NextValFunction, NextValBind, NextValDependency); + next_val.side_effects = FunctionSideEffects::HAS_SIDE_EFFECTS; + set.AddFunction(next_val); } void CurrvalFun::RegisterFunction(BuiltinFunctions &set) { - set.AddFunction(ScalarFunction("currval", {LogicalType::VARCHAR}, LogicalType::BIGINT, - NextValFunction, true, NextValBind, - NextValDependency)); + ScalarFunction curr_val("currval", {LogicalType::VARCHAR}, LogicalType::BIGINT, + NextValFunction, NextValBind, NextValDependency); + curr_val.side_effects = FunctionSideEffects::HAS_SIDE_EFFECTS; + set.AddFunction(curr_val); } } // namespace duckdb @@ -104740,8 +114909,8 @@ static unique_ptr CaseConvertPropagateStats(ClientContext &conte } ScalarFunction LowerFun::GetFunction() { - return ScalarFunction("lower", {LogicalType::VARCHAR}, LogicalType::VARCHAR, CaseConvertFunction, false, - nullptr, nullptr, CaseConvertPropagateStats); + return ScalarFunction("lower", {LogicalType::VARCHAR}, LogicalType::VARCHAR, CaseConvertFunction, nullptr, + nullptr, CaseConvertPropagateStats); } void LowerFun::RegisterFunction(BuiltinFunctions &set) { @@ -104750,8 +114919,8 @@ void LowerFun::RegisterFunction(BuiltinFunctions &set) { void UpperFun::RegisterFunction(BuiltinFunctions &set) { set.AddFunction({"upper", "ucase"}, - ScalarFunction({LogicalType::VARCHAR}, LogicalType::VARCHAR, CaseConvertFunction, false, - false, nullptr, nullptr, CaseConvertPropagateStats)); + ScalarFunction({LogicalType::VARCHAR}, LogicalType::VARCHAR, CaseConvertFunction, nullptr, + nullptr, CaseConvertPropagateStats)); } } // namespace duckdb @@ -104787,7 +114956,6 @@ void CHR::RegisterFunction(BuiltinFunctions &set) { - #include namespace duckdb { @@ -104811,8 +114979,8 @@ static void ConcatFunction(DataChunk &args, ExpressionState &state, Vector &resu // non-constant vector: set the result type to a flat vector result.SetVectorType(VectorType::FLAT_VECTOR); // now get the lengths of each of the input elements - VectorData vdata; - input.Orrify(args.size(), vdata); + UnifiedVectorFormat vdata; + input.ToUnifiedFormat(args.size(), vdata); auto input_data = (string_t *)vdata.data; // now add the length of each vector to the result length @@ -104857,8 +115025,8 @@ static void ConcatFunction(DataChunk &args, ExpressionState &state, Vector &resu } } else { // standard vector - VectorData idata; - input.Orrify(args.size(), idata); + UnifiedVectorFormat idata; + input.ToUnifiedFormat(args.size(), idata); auto input_data = (string_t *)idata.data; for (idx_t i = 0; i < args.size(); i++) { @@ -104901,9 +115069,9 @@ static void TemplatedConcatWS(DataChunk &args, string_t *sep_data, const Selecti const SelectionVector &rsel, idx_t count, Vector &result) { vector result_lengths(args.size(), 0); vector has_results(args.size(), false); - auto orrified_data = unique_ptr(new VectorData[args.ColumnCount() - 1]); + auto orrified_data = unique_ptr(new UnifiedVectorFormat[args.ColumnCount() - 1]); for (idx_t col_idx = 1; col_idx < args.ColumnCount(); col_idx++) { - args.data[col_idx].Orrify(args.size(), orrified_data[col_idx - 1]); + args.data[col_idx].ToUnifiedFormat(args.size(), orrified_data[col_idx - 1]); } // first figure out the lengths @@ -104969,8 +115137,8 @@ static void TemplatedConcatWS(DataChunk &args, string_t *sep_data, const Selecti static void ConcatWSFunction(DataChunk &args, ExpressionState &state, Vector &result) { auto &separator = args.data[0]; - VectorData vdata; - separator.Orrify(args.size(), vdata); + UnifiedVectorFormat vdata; + separator.ToUnifiedFormat(args.size(), vdata); result.SetVectorType(VectorType::CONSTANT_VECTOR); for (idx_t col_idx = 0; col_idx < args.ColumnCount(); col_idx++) { @@ -105028,6 +115196,7 @@ void ConcatFun::RegisterFunction(BuiltinFunctions &set) { // concat_ws(',', '', '') = "," ScalarFunction concat = ScalarFunction("concat", {LogicalType::VARCHAR}, LogicalType::VARCHAR, ConcatFunction); concat.varargs = LogicalType::VARCHAR; + concat.null_handling = FunctionNullHandling::SPECIAL_HANDLING; set.AddFunction(concat); ScalarFunctionSet concat_op("||"); @@ -105035,11 +115204,15 @@ void ConcatFun::RegisterFunction(BuiltinFunctions &set) { ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::VARCHAR, ConcatOperator)); concat_op.AddFunction(ScalarFunction({LogicalType::BLOB, LogicalType::BLOB}, LogicalType::BLOB, ConcatOperator)); concat_op.AddFunction(ListConcatFun::GetFunction()); + for (auto &fun : concat_op.functions) { + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + } set.AddFunction(concat_op); ScalarFunction concat_ws = ScalarFunction("concat_ws", {LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::VARCHAR, ConcatWSFunction); concat_ws.varargs = LogicalType::VARCHAR; + concat_ws.null_handling = FunctionNullHandling::SPECIAL_HANDLING; set.AddFunction(concat_ws); } @@ -105268,8 +115441,8 @@ void InstrFun::RegisterFunction(BuiltinFunctions &set) { ScalarFunction instr("instr", // name of the function {LogicalType::VARCHAR, LogicalType::VARCHAR}, // argument list LogicalType::BIGINT, // return type - ScalarFunction::BinaryFunction, false, nullptr, - nullptr, InStrPropagateStats); + ScalarFunction::BinaryFunction, nullptr, nullptr, + InStrPropagateStats); set.AddFunction(instr); instr.name = "strpos"; set.AddFunction(instr); @@ -105348,6 +115521,1187 @@ void JaccardFun::RegisterFunction(BuiltinFunctions &set) { } // namespace duckdb +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #9 +// See the end of this file for a list + +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2022 Max Bachmann */ + + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #9 +// See the end of this file for a list + +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2022 Max Bachmann */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace duckdb_jaro_winkler { + +namespace common { + +/** + * @defgroup Common Common + * Common utilities shared among multiple functions + * @{ + */ + +/* taken from https://stackoverflow.com/a/30766365/11335032 */ +template +struct is_iterator { + static char test(...); + + template ::difference_type, + typename = typename std::iterator_traits::pointer, + typename = typename std::iterator_traits::reference, + typename = typename std::iterator_traits::value_type, + typename = typename std::iterator_traits::iterator_category> + static long test(U&&); + + constexpr static bool value = std::is_same())), long>::value; +}; + +constexpr double result_cutoff(double result, double score_cutoff) +{ + return (result >= score_cutoff) ? result : 0; +} + +template +T ceildiv(T a, U divisor) +{ + return static_cast(a / divisor) + static_cast((a % divisor) != 0); +} + +/** + * Removes common prefix of two string views // todo + */ +template +int64_t remove_common_prefix(InputIt1& first1, InputIt1 last1, InputIt2& first2, InputIt2 last2) +{ + // DuckDB passes a raw pointer, but this gives compile errors for std:: + int64_t len1 = std::distance(first1, last1); + int64_t len2 = std::distance(first2, last2); + const int64_t max_comparisons = std::min(len1, len2); + int64_t prefix; + for (prefix = 0; prefix < max_comparisons; prefix++) { + if (first1[prefix] != first2[prefix]) { + break; + } + } + +// int64_t prefix = static_cast( +// std::distance(first1, std::mismatch(first1, last1, first2, last2).first)); + first1 += prefix; + first2 += prefix; + return prefix; +} + +struct BitvectorHashmap { + struct MapElem { + uint64_t key = 0; + uint64_t value = 0; + }; + + BitvectorHashmap() : m_map() + {} + + template + void insert(CharT key, int64_t pos) + { + insert_mask(key, 1ull << pos); + } + + template + void insert_mask(CharT key, uint64_t mask) + { + uint64_t i = lookup(static_cast(key)); + m_map[i].key = key; + m_map[i].value |= mask; + } + + template + uint64_t get(CharT key) const + { + return m_map[lookup(static_cast(key))].value; + } + +private: + /** + * lookup key inside the hashmap using a similar collision resolution + * strategy to CPython and Ruby + */ + uint64_t lookup(uint64_t key) const + { + uint64_t i = key % 128; + + if (!m_map[i].value || m_map[i].key == key) { + return i; + } + + uint64_t perturb = key; + while (true) { + i = ((i * 5) + perturb + 1) % 128; + if (!m_map[i].value || m_map[i].key == key) { + return i; + } + + perturb >>= 5; + } + } + + std::array m_map; +}; + +struct PatternMatchVector { + struct MapElem { + uint64_t key = 0; + uint64_t value = 0; + }; + + PatternMatchVector() : m_map(), m_extendedAscii() + {} + + template + PatternMatchVector(InputIt1 first, InputIt1 last) : m_map(), m_extendedAscii() + { + insert(first, last); + } + + template + void insert(InputIt1 first, InputIt1 last) + { + uint64_t mask = 1; + for (int64_t i = 0; i < std::distance(first, last); ++i) { + auto key = first[i]; + if (key >= 0 && key <= 255) { + m_extendedAscii[key] |= mask; + } + else { + m_map.insert_mask(key, mask); + } + mask <<= 1; + } + } + + template + void insert(CharT key, int64_t pos) + { + uint64_t mask = 1ull << pos; + if (key >= 0 && key <= 255) { + m_extendedAscii[key] |= mask; + } + else { + m_map.insert_mask(key, mask); + } + } + + template + uint64_t get(CharT key) const + { + if (key >= 0 && key <= 255) { + return m_extendedAscii[key]; + } + else { + return m_map.get(key); + } + } + + /** + * combat func for BlockPatternMatchVector + */ + template + uint64_t get(int64_t block, CharT key) const + { + (void)block; + assert(block == 0); + return get(key); + } + +private: + BitvectorHashmap m_map; + std::array m_extendedAscii; +}; + +struct BlockPatternMatchVector { + BlockPatternMatchVector() : m_block_count(0) + {} + + template + BlockPatternMatchVector(InputIt1 first, InputIt1 last) : m_block_count(0) + { + insert(first, last); + } + + template + void insert(int64_t block, CharT key, int pos) + { + uint64_t mask = 1ull << pos; + + assert(block < m_block_count); + if (key >= 0 && key <= 255) { + m_extendedAscii[key * m_block_count + block] |= mask; + } + else { + m_map[block].insert_mask(key, mask); + } + } + + template + void insert(InputIt1 first, InputIt1 last) + { + int64_t len = std::distance(first, last); + m_block_count = ceildiv(len, 64); + m_map.resize(m_block_count); + m_extendedAscii.resize(m_block_count * 256); + + for (int64_t i = 0; i < len; ++i) { + int64_t block = i / 64; + int64_t pos = i % 64; + insert(block, first[i], pos); + } + } + + /** + * combat func for PatternMatchVector + */ + template + uint64_t get(CharT key) const + { + return get(0, key); + } + + template + uint64_t get(int64_t block, CharT key) const + { + assert(block < m_block_count); + if (key >= 0 && key <= 255) { + return m_extendedAscii[key * m_block_count + block]; + } + else { + return m_map[block].get(key); + } + } + +private: + std::vector m_map; + std::vector m_extendedAscii; + int64_t m_block_count; +}; + +/**@}*/ + +} // namespace common +} // namespace duckdb_jaro_winkler + + +// LICENSE_CHANGE_END + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #9 +// See the end of this file for a list + +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2022 Max Bachmann */ + + + + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #9 +// See the end of this file for a list + +/* SPDX-License-Identifier: MIT */ +/* Copyright © 2022 Max Bachmann */ + + + +#include + +#if defined(_MSC_VER) && !defined(__clang__) +# include +#endif + +namespace duckdb_jaro_winkler { +namespace intrinsics { + +template +T bit_mask_lsb(int n) +{ + T mask = -1; + if (n < static_cast(sizeof(T) * 8)) { + mask += static_cast(1) << n; + } + return mask; +} + +template +bool bittest(T a, int bit) +{ + return (a >> bit) & 1; +} + +static inline int64_t popcount(uint64_t x) +{ + const uint64_t m1 = 0x5555555555555555; + const uint64_t m2 = 0x3333333333333333; + const uint64_t m4 = 0x0f0f0f0f0f0f0f0f; + const uint64_t h01 = 0x0101010101010101; + + x -= (x >> 1) & m1; + x = (x & m2) + ((x >> 2) & m2); + x = (x + (x >> 4)) & m4; + return static_cast((x * h01) >> 56); +} + +/** + * Extract the lowest set bit from a. If no bits are set in a returns 0. + */ +template +T blsi(T a) +{ +#if _MSC_VER && !defined(__clang__) +# pragma warning(push) +/* unary minus operator applied to unsigned type, result still unsigned */ +# pragma warning(disable: 4146) +#endif + return a & -a; +#if _MSC_VER && !defined(__clang__) +# pragma warning(pop) +#endif +} + +/** + * Clear the lowest set bit in a. + */ +template +T blsr(T x) +{ + return x & (x - 1); +} + +#if defined(_MSC_VER) && !defined(__clang__) +static inline int tzcnt(uint32_t x) +{ + unsigned long trailing_zero = 0; + _BitScanForward(&trailing_zero, x); + return trailing_zero; +} + +# if defined(_M_ARM) || defined(_M_X64) +static inline int tzcnt(uint64_t x) +{ + unsigned long trailing_zero = 0; + _BitScanForward64(&trailing_zero, x); + return trailing_zero; +} +# else +static inline int tzcnt(uint64_t x) +{ + uint32_t msh = (uint32_t)(x >> 32); + uint32_t lsh = (uint32_t)(x & 0xFFFFFFFF); + if (lsh != 0) { + return tzcnt(lsh); + } + return 32 + tzcnt(msh); +} +# endif + +#else /* gcc / clang */ +//static inline int tzcnt(uint32_t x) +//{ +// return __builtin_ctz(x); +//} + +static inline int tzcnt(uint64_t x) +{ + return __builtin_ctzll(x); +} +#endif + +} // namespace intrinsics +} // namespace duckdb_jaro_winkler + + +// LICENSE_CHANGE_END + + +namespace duckdb_jaro_winkler { +namespace detail { + +struct FlaggedCharsWord { + uint64_t P_flag; + uint64_t T_flag; +}; + +struct FlaggedCharsMultiword { + std::vector P_flag; + std::vector T_flag; +}; + +struct SearchBoundMask { + int64_t words = 0; + int64_t empty_words = 0; + uint64_t last_mask = 0; + uint64_t first_mask = 0; +}; + +struct TextPosition { + TextPosition(int64_t Word_, int64_t WordPos_) : Word(Word_), WordPos(WordPos_) + {} + int64_t Word; + int64_t WordPos; +}; + +static inline double jaro_calculate_similarity(int64_t P_len, int64_t T_len, int64_t CommonChars, + int64_t Transpositions) +{ + Transpositions /= 2; + double Sim = 0; + Sim += static_cast(CommonChars) / static_cast(P_len); + Sim += static_cast(CommonChars) / static_cast(T_len); + Sim += (static_cast(CommonChars) - static_cast(Transpositions)) / static_cast(CommonChars); + return Sim / 3.0; +} + +/** + * @brief filter matches below score_cutoff based on string lengths + */ +static inline bool jaro_length_filter(int64_t P_len, int64_t T_len, double score_cutoff) +{ + if (!T_len || !P_len) return false; + + double min_len = static_cast(std::min(P_len, T_len)); + double Sim = min_len / static_cast(P_len) + min_len / static_cast(T_len) + 1.0; + Sim /= 3.0; + return Sim >= score_cutoff; +} + +/** + * @brief filter matches below score_cutoff based on string lengths and common characters + */ +static inline bool jaro_common_char_filter(int64_t P_len, int64_t T_len, int64_t CommonChars, + double score_cutoff) +{ + if (!CommonChars) return false; + + double Sim = 0; + Sim += static_cast(CommonChars) / static_cast(P_len); + Sim += static_cast(CommonChars) / static_cast(T_len); + Sim += 1.0; + Sim /= 3.0; + return Sim >= score_cutoff; +} + +static inline int64_t count_common_chars(const FlaggedCharsWord& flagged) +{ + return intrinsics::popcount(flagged.P_flag); +} + +static inline int64_t count_common_chars(const FlaggedCharsMultiword& flagged) +{ + int64_t CommonChars = 0; + if (flagged.P_flag.size() < flagged.T_flag.size()) { + for (uint64_t flag : flagged.P_flag) { + CommonChars += intrinsics::popcount(flag); + } + } + else { + for (uint64_t flag : flagged.T_flag) { + CommonChars += intrinsics::popcount(flag); + } + } + return CommonChars; +} + +template +static inline FlaggedCharsWord +flag_similar_characters_word(const PM_Vec& PM, InputIt1 P_first, + InputIt1 P_last, InputIt2 T_first, InputIt2 T_last, int Bound) +{ + using namespace intrinsics; + int64_t P_len = std::distance(P_first, P_last); + (void)P_len; + int64_t T_len = std::distance(T_first, T_last); + assert(P_len <= 64); + assert(T_len <= 64); + assert(Bound > P_len || P_len - Bound <= T_len); + + FlaggedCharsWord flagged = {0, 0}; + + uint64_t BoundMask = bit_mask_lsb(Bound + 1); + + int64_t j = 0; + for (; j < std::min(static_cast(Bound), T_len); ++j) { + uint64_t PM_j = PM.get(T_first[j]) & BoundMask & (~flagged.P_flag); + + flagged.P_flag |= blsi(PM_j); + flagged.T_flag |= static_cast(PM_j != 0) << j; + + BoundMask = (BoundMask << 1) | 1; + } + + for (; j < T_len; ++j) { + uint64_t PM_j = PM.get(T_first[j]) & BoundMask & (~flagged.P_flag); + + flagged.P_flag |= blsi(PM_j); + flagged.T_flag |= static_cast(PM_j != 0) << j; + + BoundMask <<= 1; + } + + return flagged; +} + +template +static inline void flag_similar_characters_step(const common::BlockPatternMatchVector& PM, + CharT T_j, FlaggedCharsMultiword& flagged, + int64_t j, SearchBoundMask BoundMask) +{ + using namespace intrinsics; + + int64_t j_word = j / 64; + int64_t j_pos = j % 64; + int64_t word = BoundMask.empty_words; + int64_t last_word = word + BoundMask.words; + + if (BoundMask.words == 1) { + uint64_t PM_j = PM.get(word, T_j) & BoundMask.last_mask & BoundMask.first_mask & + (~flagged.P_flag[word]); + + flagged.P_flag[word] |= blsi(PM_j); + flagged.T_flag[j_word] |= static_cast(PM_j != 0) << j_pos; + return; + } + + if (BoundMask.first_mask) { + uint64_t PM_j = PM.get(word, T_j) & BoundMask.first_mask & (~flagged.P_flag[word]); + + if (PM_j) { + flagged.P_flag[word] |= blsi(PM_j); + flagged.T_flag[j_word] |= 1ull << j_pos; + return; + } + word++; + } + + for (; word < last_word - 1; ++word) { + uint64_t PM_j = PM.get(word, T_j) & (~flagged.P_flag[word]); + + if (PM_j) { + flagged.P_flag[word] |= blsi(PM_j); + flagged.T_flag[j_word] |= 1ull << j_pos; + return; + } + } + + if (BoundMask.last_mask) { + uint64_t PM_j = PM.get(word, T_j) & BoundMask.last_mask & (~flagged.P_flag[word]); + + flagged.P_flag[word] |= blsi(PM_j); + flagged.T_flag[j_word] |= static_cast(PM_j != 0) << j_pos; + } +} + +template +static inline FlaggedCharsMultiword +flag_similar_characters_block(const common::BlockPatternMatchVector& PM, InputIt1 P_first, + InputIt1 P_last, InputIt2 T_first, InputIt2 T_last, int64_t Bound) +{ + using namespace intrinsics; + int64_t P_len = std::distance(P_first, P_last); + int64_t T_len = std::distance(T_first, T_last); + assert(P_len > 64 || T_len > 64); + assert(Bound > P_len || P_len - Bound <= T_len); + assert(Bound >= 31); + + int64_t TextWords = common::ceildiv(T_len, 64); + int64_t PatternWords = common::ceildiv(P_len, 64); + + FlaggedCharsMultiword flagged; + flagged.T_flag.resize(TextWords); + flagged.P_flag.resize(PatternWords); + + SearchBoundMask BoundMask; + int64_t start_range = std::min(Bound + 1, P_len); + BoundMask.words = 1 + start_range / 64; + BoundMask.empty_words = 0; + BoundMask.last_mask = (1ull << (start_range % 64)) - 1; + BoundMask.first_mask = ~UINT64_C(0); + + for (int64_t j = 0; j < T_len; ++j) { + flag_similar_characters_step(PM, T_first[j], flagged, j, BoundMask); + + if (j + Bound + 1 < P_len) { + BoundMask.last_mask = (BoundMask.last_mask << 1) | 1; + if (j + Bound + 2 < P_len && BoundMask.last_mask == ~UINT64_C(0)) { + BoundMask.last_mask = 0; + BoundMask.words++; + } + } + + if (j >= Bound) { + BoundMask.first_mask <<= 1; + if (BoundMask.first_mask == 0) { + BoundMask.first_mask = ~UINT64_C(0); + BoundMask.words--; + BoundMask.empty_words++; + } + } + } + + return flagged; +} + +template +static inline int64_t count_transpositions_word(const PM_Vec& PM, + InputIt1 T_first, InputIt1, + const FlaggedCharsWord& flagged) +{ + using namespace intrinsics; + uint64_t P_flag = flagged.P_flag; + uint64_t T_flag = flagged.T_flag; + int64_t Transpositions = 0; + while (T_flag) { + uint64_t PatternFlagMask = blsi(P_flag); + + Transpositions += !(PM.get(T_first[tzcnt(T_flag)]) & PatternFlagMask); + + T_flag = blsr(T_flag); + P_flag ^= PatternFlagMask; + } + + return Transpositions; +} + +template +static inline int64_t +count_transpositions_block(const common::BlockPatternMatchVector& PM, InputIt1 T_first, InputIt1, + const FlaggedCharsMultiword& flagged, int64_t FlaggedChars) +{ + using namespace intrinsics; + int64_t TextWord = 0; + int64_t PatternWord = 0; + uint64_t T_flag = flagged.T_flag[TextWord]; + uint64_t P_flag = flagged.P_flag[PatternWord]; + + int64_t Transpositions = 0; + while (FlaggedChars) { + while (!T_flag) { + TextWord++; + T_first += 64; + T_flag = flagged.T_flag[TextWord]; + } + + while (T_flag) { + while (!P_flag) { + PatternWord++; + P_flag = flagged.P_flag[PatternWord]; + } + + uint64_t PatternFlagMask = blsi(P_flag); + + Transpositions += !(PM.get(PatternWord, T_first[tzcnt(T_flag)]) & PatternFlagMask); + + T_flag = blsr(T_flag); + P_flag ^= PatternFlagMask; + + FlaggedChars--; + } + } + + return Transpositions; +} + +/** + * @brief find bounds and skip out of bound parts of the sequences + * + */ +template +int64_t jaro_bounds(InputIt1 P_first, InputIt1& P_last, InputIt2 T_first, InputIt2& T_last) +{ + int64_t P_len = std::distance(P_first, P_last); + int64_t T_len = std::distance(T_first, T_last); + + /* since jaro uses a sliding window some parts of T/P might never be in + * range an can be removed ahead of time + */ + int64_t Bound = 0; + if (T_len > P_len) { + Bound = T_len / 2 - 1; + if (T_len > P_len + Bound) { + T_last = T_first + P_len + Bound; + } + } + else { + Bound = P_len / 2 - 1; + if (P_len > T_len + Bound) { + P_last = P_first + T_len + Bound; + } + } + return Bound; +} + +template +double jaro_similarity(InputIt1 P_first, InputIt1 P_last, InputIt2 T_first, InputIt2 T_last, + double score_cutoff) +{ + int64_t P_len = std::distance(P_first, P_last); + int64_t T_len = std::distance(T_first, T_last); + + /* filter out based on the length difference between the two strings */ + if (!jaro_length_filter(P_len, T_len, score_cutoff)) { + return 0.0; + } + + if (P_len == 1 && T_len == 1) { + return static_cast(P_first[0] == T_first[0]); + } + + int64_t Bound = jaro_bounds(P_first, P_last, T_first, T_last); + + /* common prefix never includes Transpositions */ + int64_t CommonChars = common::remove_common_prefix(P_first, P_last, T_first, T_last); + int64_t Transpositions = 0; + int64_t P_view_len = std::distance(P_first, P_last); + int64_t T_view_len = std::distance(T_first, T_last); + + if (!P_view_len || !T_view_len) { + /* already has correct number of common chars and transpositions */ + } + else if (P_view_len <= 64 && T_view_len <= 64) { + common::PatternMatchVector PM(P_first, P_last); + auto flagged = flag_similar_characters_word(PM, P_first, P_last, T_first, T_last, static_cast(Bound)); + CommonChars += count_common_chars(flagged); + + if (!jaro_common_char_filter(P_len, T_len, CommonChars, score_cutoff)) { + return 0.0; + } + + Transpositions = count_transpositions_word(PM, T_first, T_last, flagged); + } + else { + common::BlockPatternMatchVector PM(P_first, P_last); + auto flagged = flag_similar_characters_block(PM, P_first, P_last, T_first, T_last, Bound); + int64_t FlaggedChars = count_common_chars(flagged); + CommonChars += FlaggedChars; + + if (!jaro_common_char_filter(P_len, T_len, CommonChars, score_cutoff)) { + return 0.0; + } + + Transpositions = count_transpositions_block(PM, T_first, T_last, flagged, FlaggedChars); + } + + double Sim = jaro_calculate_similarity(P_len, T_len, CommonChars, Transpositions); + return common::result_cutoff(Sim, score_cutoff); +} + +template +double jaro_similarity(const common::BlockPatternMatchVector& PM, InputIt1 P_first, InputIt1 P_last, + InputIt2 T_first, InputIt2 T_last, double score_cutoff) +{ + int64_t P_len = std::distance(P_first, P_last); + int64_t T_len = std::distance(T_first, T_last); + + /* filter out based on the length difference between the two strings */ + if (!jaro_length_filter(P_len, T_len, score_cutoff)) { + return 0.0; + } + + if (P_len == 1 && T_len == 1) { + return static_cast(P_first[0] == T_first[0]); + } + + int64_t Bound = jaro_bounds(P_first, P_last, T_first, T_last); + + /* common prefix never includes Transpositions */ + int64_t CommonChars = 0; + int64_t Transpositions = 0; + int64_t P_view_len = std::distance(P_first, P_last); + int64_t T_view_len = std::distance(T_first, T_last); + + if (!P_view_len || !T_view_len) { + /* already has correct number of common chars and transpositions */ + } + else if (P_view_len <= 64 && T_view_len <= 64) { + auto flagged = flag_similar_characters_word(PM, P_first, P_last, T_first, T_last, static_cast(Bound)); + CommonChars += count_common_chars(flagged); + + if (!jaro_common_char_filter(P_len, T_len, CommonChars, score_cutoff)) { + return 0.0; + } + + Transpositions = count_transpositions_word(PM, T_first, T_last, flagged); + } + else { + auto flagged = flag_similar_characters_block(PM, P_first, P_last, T_first, T_last, Bound); + int64_t FlaggedChars = count_common_chars(flagged); + CommonChars += FlaggedChars; + + if (!jaro_common_char_filter(P_len, T_len, CommonChars, score_cutoff)) { + return 0.0; + } + + Transpositions = count_transpositions_block(PM, T_first, T_last, flagged, FlaggedChars); + } + + double Sim = jaro_calculate_similarity(P_len, T_len, CommonChars, Transpositions); + return common::result_cutoff(Sim, score_cutoff); +} + +template +double jaro_winkler_similarity(InputIt1 P_first, InputIt1 P_last, InputIt2 T_first, InputIt2 T_last, + double prefix_weight, double score_cutoff) +{ + int64_t P_len = std::distance(P_first, P_last); + int64_t T_len = std::distance(T_first, T_last); + int64_t min_len = std::min(P_len, T_len); + int64_t prefix = 0; + int64_t max_prefix = std::min(min_len, 4); + + for (; prefix < max_prefix; ++prefix) { + if (T_first[prefix] != P_first[prefix]) { + break; + } + } + + double jaro_score_cutoff = score_cutoff; + if (jaro_score_cutoff > 0.7) { + double prefix_sim = prefix * prefix_weight; + + if (prefix_sim >= 1.0) { + jaro_score_cutoff = 0.7; + } + else { + jaro_score_cutoff = + std::max(0.7, (prefix_sim - jaro_score_cutoff) / (prefix_sim - 1.0)); + } + } + + double Sim = jaro_similarity(P_first, P_last, T_first, T_last, jaro_score_cutoff); + if (Sim > 0.7) { + Sim += prefix * prefix_weight * (1.0 - Sim); + } + + return common::result_cutoff(Sim, score_cutoff); +} + +template +double jaro_winkler_similarity(const common::BlockPatternMatchVector& PM, InputIt1 P_first, + InputIt1 P_last, InputIt2 T_first, InputIt2 T_last, + double prefix_weight, double score_cutoff) +{ + int64_t P_len = std::distance(P_first, P_last); + int64_t T_len = std::distance(T_first, T_last); + int64_t min_len = std::min(P_len, T_len); + int64_t prefix = 0; + int64_t max_prefix = std::min(min_len, 4); + + for (; prefix < max_prefix; ++prefix) { + if (T_first[prefix] != P_first[prefix]) { + break; + } + } + + double jaro_score_cutoff = score_cutoff; + if (jaro_score_cutoff > 0.7) { + double prefix_sim = prefix * prefix_weight; + + if (prefix_sim >= 1.0) { + jaro_score_cutoff = 0.7; + } + else { + jaro_score_cutoff = + std::max(0.7, (prefix_sim - jaro_score_cutoff) / (prefix_sim - 1.0)); + } + } + + double Sim = jaro_similarity(PM, P_first, P_last, T_first, T_last, jaro_score_cutoff); + if (Sim > 0.7) { + Sim += prefix * prefix_weight * (1.0 - Sim); + } + + return common::result_cutoff(Sim, score_cutoff); +} + +} // namespace detail +} // namespace duckdb_jaro_winkler + + +// LICENSE_CHANGE_END + + +#include + +namespace duckdb_jaro_winkler { + +/** + * @defgroup jaro_winkler jaro_winkler + * @{ + */ + +/** + * @brief Calculates the jaro winkler similarity + * + * @tparam Sentence1 This is a string that can be converted to + * basic_string_view + * @tparam Sentence2 This is a string that can be converted to + * basic_string_view + * + * @param s1 + * string to compare with s2 (for type info check Template parameters above) + * @param s2 + * string to compare with s1 (for type info check Template parameters above) + * @param prefix_weight + * Weight used for the common prefix of the two strings. + * Has to be between 0 and 0.25. Default is 0.1. + * @param score_cutoff + * Optional argument for a score threshold as a float between 0 and 100. + * For similarity < score_cutoff 0 is returned instead. Default is 0, + * which deactivates this behaviour. + * + * @return jaro winkler similarity between s1 and s2 + * as a float between 0 and 100 + */ +template +typename std::enable_if< + common::is_iterator::value && common::is_iterator::value, double>::type +jaro_winkler_similarity(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, + double prefix_weight = 0.1, double score_cutoff = 0.0) +{ + if (prefix_weight < 0.0 || prefix_weight > 0.25) { + throw std::invalid_argument("prefix_weight has to be between 0.0 and 0.25"); + } + + return detail::jaro_winkler_similarity(first1, last1, first2, last2, prefix_weight, + score_cutoff); +} + +template +double jaro_winkler_similarity(const S1& s1, const S2& s2, double prefix_weight = 0.1, + double score_cutoff = 0.0) +{ + return jaro_winkler_similarity(std::begin(s1), std::end(s1), std::begin(s2), std::end(s2), + prefix_weight, score_cutoff); +} + +template +struct CachedJaroWinklerSimilarity { + template + CachedJaroWinklerSimilarity(InputIt1 first1, InputIt1 last1, double prefix_weight_ = 0.1) + : s1(first1, last1), PM(first1, last1), prefix_weight(prefix_weight_) + { + if (prefix_weight < 0.0 || prefix_weight > 0.25) { + throw std::invalid_argument("prefix_weight has to be between 0.0 and 0.25"); + } + } + + template + CachedJaroWinklerSimilarity(const S1& s1_, double prefix_weight_ = 0.1) + : CachedJaroWinklerSimilarity(std::begin(s1_), std::end(s1_), prefix_weight_) + {} + + template + double similarity(InputIt2 first2, InputIt2 last2, double score_cutoff = 0) const + { + return detail::jaro_winkler_similarity(PM, std::begin(s1), std::end(s1), first2, last2, + prefix_weight, score_cutoff); + } + + template + double similarity(const S2& s2, double score_cutoff = 0) const + { + return similarity(std::begin(s2), std::end(s2), score_cutoff); + } + + template + double normalized_similarity(InputIt2 first2, InputIt2 last2, double score_cutoff = 0) const + { + return similarity(first2, last2, score_cutoff); + } + + template + double normalized_similarity(const S2& s2, double score_cutoff = 0) const + { + return similarity(s2, score_cutoff); + } + +private: + std::basic_string s1; + common::BlockPatternMatchVector PM; + + double prefix_weight; +}; + +/** + * @brief Calculates the jaro similarity + * + * @tparam Sentence1 This is a string that can be converted to + * basic_string_view + * @tparam Sentence2 This is a string that can be converted to + * basic_string_view + * + * @param s1 + * string to compare with s2 (for type info check Template parameters above) + * @param s2 + * string to compare with s1 (for type info check Template parameters above) + * @param score_cutoff + * Optional argument for a score threshold as a float between 0 and 100. + * For similarity < score_cutoff 0 is returned instead. Default is 0, + * which deactivates this behaviour. + * + * @return jaro similarity between s1 and s2 + * as a float between 0 and 100 + */ +template +double jaro_similarity(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, + double score_cutoff = 0.0) +{ + return detail::jaro_similarity(first1, last1, first2, last2, score_cutoff); +} + +template +double jaro_similarity(const S1& s1, const S2& s2, double score_cutoff = 0.0) +{ + return jaro_similarity(std::begin(s1), std::end(s1), std::begin(s2), std::end(s2), + score_cutoff); +} + +template +struct CachedJaroSimilarity { + template + CachedJaroSimilarity(InputIt1 first1, InputIt1 last1) : s1(first1, last1), PM(first1, last1) + {} + + template + CachedJaroSimilarity(const S1& s1_) : CachedJaroSimilarity(std::begin(s1_), std::end(s1_)) + {} + + template + double similarity(InputIt2 first2, InputIt2 last2, double score_cutoff = 0) const + { + return detail::jaro_similarity(PM, std::begin(s1), std::end(s1), first2, last2, + score_cutoff); + } + + template + double similarity(const S2& s2, double score_cutoff = 0) const + { + return similarity(std::begin(s2), std::end(s2), score_cutoff); + } + + template + double normalized_similarity(InputIt2 first2, InputIt2 last2, double score_cutoff = 0) const + { + return similarity(first2, last2, score_cutoff); + } + + template + double normalized_similarity(const S2& s2, double score_cutoff = 0) const + { + return similarity(s2, score_cutoff); + } + +private: + std::basic_string s1; + common::BlockPatternMatchVector PM; +}; + +/**@}*/ + +} // namespace duckdb_jaro_winkler + + +// LICENSE_CHANGE_END + + + + +namespace duckdb { + +static inline double JaroScalarFunction(const string_t &s1, const string_t &s2) { + auto s1_begin = s1.GetDataUnsafe(); + auto s2_begin = s2.GetDataUnsafe(); + return duckdb_jaro_winkler::jaro_similarity(s1_begin, s1_begin + s1.GetSize(), s2_begin, s2_begin + s2.GetSize()); +} + +static inline double JaroWinklerScalarFunction(const string_t &s1, const string_t &s2) { + auto s1_begin = s1.GetDataUnsafe(); + auto s2_begin = s2.GetDataUnsafe(); + return duckdb_jaro_winkler::jaro_winkler_similarity(s1_begin, s1_begin + s1.GetSize(), s2_begin, + s2_begin + s2.GetSize()); +} + +template +static void CachedFunction(Vector &constant, Vector &other, Vector &result, idx_t count) { + auto val = constant.GetValue(0); + if (val.IsNull()) { + auto &result_validity = FlatVector::Validity(result); + result_validity.SetAllInvalid(count); + return; + } + + auto str_val = StringValue::Get(val); + auto cached = CACHED_SIMILARITY(str_val); + UnaryExecutor::Execute(other, result, count, [&](const string_t &other_str) { + auto other_str_begin = other_str.GetDataUnsafe(); + return cached.similarity(other_str_begin, other_str_begin + other_str.GetSize()); + }); +} + +template > +static void TemplatedJaroWinklerFunction(DataChunk &args, Vector &result, SIMILARITY_FUNCTION fun) { + bool arg0_constant = args.data[0].GetVectorType() == VectorType::CONSTANT_VECTOR; + bool arg1_constant = args.data[1].GetVectorType() == VectorType::CONSTANT_VECTOR; + if (!(arg0_constant ^ arg1_constant)) { + // We can't optimize by caching one of the two strings + BinaryExecutor::Execute(args.data[0], args.data[1], result, args.size(), fun); + return; + } + + if (arg0_constant) { + CachedFunction(args.data[0], args.data[1], result, args.size()); + } else { + CachedFunction(args.data[1], args.data[0], result, args.size()); + } +} + +static void JaroFunction(DataChunk &args, ExpressionState &state, Vector &result) { + TemplatedJaroWinklerFunction>(args, result, JaroScalarFunction); +} + +static void JaroWinklerFunction(DataChunk &args, ExpressionState &state, Vector &result) { + TemplatedJaroWinklerFunction>(args, result, + JaroWinklerScalarFunction); +} + +void JaroWinklerFun::RegisterFunction(BuiltinFunctions &set) { + set.AddFunction(ScalarFunction("jaro_similarity", {LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::DOUBLE, + JaroFunction)); + set.AddFunction(ScalarFunction("jaro_winkler_similarity", {LogicalType::VARCHAR, LogicalType::VARCHAR}, + LogicalType::DOUBLE, JaroWinklerFunction)); +} + +} // namespace duckdb + + #include #include @@ -105413,6 +116767,7 @@ void RightFun::RegisterFunction(BuiltinFunctions &set) { + namespace duckdb { // length returns the size in characters @@ -105473,18 +116828,21 @@ static unique_ptr LengthPropagateStats(ClientContext &context, F static unique_ptr ListLengthBind(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { + if (arguments[0]->HasParameter()) { + throw ParameterNotResolvedException(); + } bound_function.arguments[0] = arguments[0]->return_type; return nullptr; } void LengthFun::RegisterFunction(BuiltinFunctions &set) { - ScalarFunction array_length_unary = ScalarFunction( - {LogicalType::LIST(LogicalType::ANY)}, LogicalType::BIGINT, - ScalarFunction::UnaryFunction, false, false, ListLengthBind); + ScalarFunction array_length_unary = + ScalarFunction({LogicalType::LIST(LogicalType::ANY)}, LogicalType::BIGINT, + ScalarFunction::UnaryFunction, ListLengthBind); ScalarFunctionSet length("length"); length.AddFunction(ScalarFunction({LogicalType::VARCHAR}, LogicalType::BIGINT, - ScalarFunction::UnaryFunction, false, - false, nullptr, nullptr, LengthPropagateStats)); + ScalarFunction::UnaryFunction, nullptr, + nullptr, LengthPropagateStats)); length.AddFunction(array_length_unary); set.AddFunction(length); length.name = "len"; @@ -105492,10 +116850,9 @@ void LengthFun::RegisterFunction(BuiltinFunctions &set) { ScalarFunctionSet array_length("array_length"); array_length.AddFunction(array_length_unary); - array_length.AddFunction( - ScalarFunction({LogicalType::LIST(LogicalType::ANY), LogicalType::BIGINT}, LogicalType::BIGINT, - ScalarFunction::BinaryFunction, false, - false, ListLengthBind)); + array_length.AddFunction(ScalarFunction( + {LogicalType::LIST(LogicalType::ANY), LogicalType::BIGINT}, LogicalType::BIGINT, + ScalarFunction::BinaryFunction, ListLengthBind)); set.AddFunction(array_length); set.AddFunction(ScalarFunction("strlen", {LogicalType::VARCHAR}, LogicalType::BIGINT, @@ -105818,6 +117175,9 @@ static unique_ptr LikeBindFunction(ClientContext &context, ScalarF D_ASSERT(arguments.size() == 2 || arguments.size() == 3); if (arguments[1]->IsFoldable()) { Value pattern_str = ExpressionExecutor::EvaluateScalar(*arguments[1]); + if (pattern_str.IsNull()) { + return nullptr; + } return LikeMatcher::CreateLikeMatcher(pattern_str.ToString()); } return nullptr; @@ -106118,21 +117478,21 @@ static void RegularLikeFunction(DataChunk &input, ExpressionState &state, Vector void LikeFun::RegisterFunction(BuiltinFunctions &set) { // like set.AddFunction(ScalarFunction("~~", {LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::BOOLEAN, - RegularLikeFunction, false, LikeBindFunction)); + RegularLikeFunction, LikeBindFunction)); // not like set.AddFunction(ScalarFunction("!~~", {LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::BOOLEAN, - RegularLikeFunction, false, LikeBindFunction)); + RegularLikeFunction, LikeBindFunction)); // glob set.AddFunction(ScalarFunction("~~~", {LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::BOOLEAN, ScalarFunction::BinaryFunction)); // ilike set.AddFunction(ScalarFunction("~~*", {LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::BOOLEAN, - ScalarFunction::BinaryFunction, false, - nullptr, nullptr, ILikePropagateStats)); + ScalarFunction::BinaryFunction, nullptr, + nullptr, ILikePropagateStats)); // not ilike set.AddFunction(ScalarFunction("!~~*", {LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::BOOLEAN, - ScalarFunction::BinaryFunction, false, - nullptr, nullptr, ILikePropagateStats)); + ScalarFunction::BinaryFunction, nullptr, + nullptr, ILikePropagateStats)); } void LikeEscapeFun::RegisterFunction(BuiltinFunctions &set) { @@ -106628,7 +117988,7 @@ static void PrintfFunction(DataChunk &args, ExpressionState &state, Vector &resu break; default: // FLAT VECTOR, we can directly OR the nullmask - args.data[i].Normalify(args.size()); + args.data[i].Flatten(args.size()); result.SetVectorType(VectorType::FLAT_VECTOR); result_validity.Combine(FlatVector::Validity(args.data[i]), args.size()); break; @@ -106667,7 +118027,7 @@ static void PrintfFunction(DataChunk &args, ExpressionState &state, Vector &resu break; } case LogicalTypeId::SMALLINT: { - auto arg_data = FlatVector::GetData(col); + auto arg_data = FlatVector::GetData(col); format_args.emplace_back(duckdb_fmt::internal::make_arg(arg_data[arg_idx])); break; } @@ -106712,14 +118072,14 @@ void PrintfFun::RegisterFunction(BuiltinFunctions &set) { // duckdb_fmt::printf_context, duckdb_fmt::vsprintf ScalarFunction printf_fun = ScalarFunction("printf", {LogicalType::VARCHAR}, LogicalType::VARCHAR, - PrintfFunction, false, BindPrintfFunction); + PrintfFunction, BindPrintfFunction); printf_fun.varargs = LogicalType::ANY; set.AddFunction(printf_fun); // duckdb_fmt::format_context, duckdb_fmt::vformat ScalarFunction format_fun = ScalarFunction("format", {LogicalType::VARCHAR}, LogicalType::VARCHAR, - PrintfFunction, false, BindPrintfFunction); + PrintfFunction, BindPrintfFunction); format_fun.varargs = LogicalType::ANY; set.AddFunction(format_fun); } @@ -106938,6 +118298,9 @@ static unique_ptr RegexpMatchesBind(ClientContext &context, Scalar RE2::Options options; options.set_log_errors(false); if (arguments.size() == 3) { + if (arguments[2]->HasParameter()) { + throw ParameterNotResolvedException(); + } if (!arguments[2]->IsFoldable()) { throw InvalidInputException("Regex options field must be a constant"); } @@ -106994,6 +118357,9 @@ static unique_ptr RegexReplaceBind(ClientContext &context, ScalarF auto data = make_unique(); data->options.set_log_errors(false); if (arguments.size() == 4) { + if (arguments[3]->HasParameter()) { + throw ParameterNotResolvedException(); + } if (!arguments[3]->IsFoldable()) { throw InvalidInputException("Regex options field must be a constant"); } @@ -107072,6 +118438,9 @@ static unique_ptr RegexExtractBind(ClientContext &context, ScalarF string group_string = ""; if (arguments.size() == 3) { + if (arguments[2]->HasParameter()) { + throw ParameterNotResolvedException(); + } if (!arguments[2]->IsFoldable()) { throw InvalidInputException("Group index field field must be a constant!"); } @@ -107092,37 +118461,41 @@ static unique_ptr RegexExtractBind(ClientContext &context, ScalarF void RegexpFun::RegisterFunction(BuiltinFunctions &set) { ScalarFunctionSet regexp_full_match("regexp_full_match"); - regexp_full_match.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::BOOLEAN, - RegexpMatchesFunction, false, false, RegexpMatchesBind, - nullptr, nullptr, RegexInitLocalState)); - regexp_full_match.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR}, - LogicalType::BOOLEAN, RegexpMatchesFunction, false, - false, RegexpMatchesBind, nullptr, nullptr, RegexInitLocalState)); + regexp_full_match.AddFunction(ScalarFunction( + {LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::BOOLEAN, RegexpMatchesFunction, + RegexpMatchesBind, nullptr, nullptr, RegexInitLocalState, LogicalType::INVALID, + FunctionSideEffects::NO_SIDE_EFFECTS, FunctionNullHandling::SPECIAL_HANDLING)); + regexp_full_match.AddFunction(ScalarFunction( + {LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::BOOLEAN, + RegexpMatchesFunction, RegexpMatchesBind, nullptr, nullptr, RegexInitLocalState, + LogicalType::INVALID, FunctionSideEffects::NO_SIDE_EFFECTS, FunctionNullHandling::SPECIAL_HANDLING)); ScalarFunctionSet regexp_partial_match("regexp_matches"); - regexp_partial_match.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::BOOLEAN, - RegexpMatchesFunction, false, false, - RegexpMatchesBind, nullptr, nullptr, RegexInitLocalState)); - regexp_partial_match.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR}, - LogicalType::BOOLEAN, RegexpMatchesFunction, - false, false, RegexpMatchesBind, nullptr, nullptr, - RegexInitLocalState)); + regexp_partial_match.AddFunction(ScalarFunction( + {LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::BOOLEAN, RegexpMatchesFunction, + RegexpMatchesBind, nullptr, nullptr, RegexInitLocalState, LogicalType::INVALID, + FunctionSideEffects::NO_SIDE_EFFECTS, FunctionNullHandling::SPECIAL_HANDLING)); + regexp_partial_match.AddFunction(ScalarFunction( + {LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::BOOLEAN, + RegexpMatchesFunction, RegexpMatchesBind, nullptr, nullptr, RegexInitLocalState, + LogicalType::INVALID, FunctionSideEffects::NO_SIDE_EFFECTS, FunctionNullHandling::SPECIAL_HANDLING)); ScalarFunctionSet regexp_replace("regexp_replace"); regexp_replace.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR}, - LogicalType::VARCHAR, RegexReplaceFunction, false, false, - RegexReplaceBind)); + LogicalType::VARCHAR, RegexReplaceFunction, RegexReplaceBind)); regexp_replace.AddFunction( ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::VARCHAR}, - LogicalType::VARCHAR, RegexReplaceFunction, false, false, RegexReplaceBind)); + LogicalType::VARCHAR, RegexReplaceFunction, RegexReplaceBind)); ScalarFunctionSet regexp_extract("regexp_extract"); - regexp_extract.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::VARCHAR, - RegexExtractFunction, false, false, RegexExtractBind, nullptr, nullptr, - RegexExtractInitLocalState)); - regexp_extract.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::INTEGER}, - LogicalType::VARCHAR, RegexExtractFunction, false, false, - RegexExtractBind, nullptr, nullptr, RegexExtractInitLocalState)); + regexp_extract.AddFunction( + ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, LogicalType::VARCHAR, RegexExtractFunction, + RegexExtractBind, nullptr, nullptr, RegexExtractInitLocalState, LogicalType::INVALID, + FunctionSideEffects::NO_SIDE_EFFECTS, FunctionNullHandling::SPECIAL_HANDLING)); + regexp_extract.AddFunction(ScalarFunction( + {LogicalType::VARCHAR, LogicalType::VARCHAR, LogicalType::INTEGER}, LogicalType::VARCHAR, RegexExtractFunction, + RegexExtractBind, nullptr, nullptr, RegexExtractInitLocalState, LogicalType::INVALID, + FunctionSideEffects::NO_SIDE_EFFECTS, FunctionNullHandling::SPECIAL_HANDLING)); set.AddFunction(regexp_full_match); set.AddFunction(regexp_partial_match); @@ -107328,8 +118701,6 @@ void ReverseFun::RegisterFunction(BuiltinFunctions &set) { - - namespace duckdb { struct StringSplitIterator { @@ -107509,12 +118880,12 @@ unique_ptr BaseStringSplitFunction(string_t input, string_t delim, const } static void StringSplitExecutor(DataChunk &args, ExpressionState &state, Vector &result, const bool regex) { - VectorData input_data; - args.data[0].Orrify(args.size(), input_data); + UnifiedVectorFormat input_data; + args.data[0].ToUnifiedFormat(args.size(), input_data); auto inputs = (string_t *)input_data.data; - VectorData delim_data; - args.data[1].Orrify(args.size(), delim_data); + UnifiedVectorFormat delim_data; + args.data[1].ToUnifiedFormat(args.size(), delim_data); auto delims = (string_t *)delim_data.data; D_ASSERT(result.GetType().id() == LogicalTypeId::LIST); @@ -107553,8 +118924,7 @@ static void StringSplitExecutor(DataChunk &args, ExpressionState &state, Vector } D_ASSERT(ListVector::GetListSize(result) == total_len); - if (args.data[0].GetVectorType() == VectorType::CONSTANT_VECTOR && - args.data[1].GetVectorType() == VectorType::CONSTANT_VECTOR) { + if (args.AllConstant()) { result.SetVectorType(VectorType::CONSTANT_VECTOR); } } @@ -107570,12 +118940,15 @@ static void StringSplitRegexFunction(DataChunk &args, ExpressionState &state, Ve void StringSplitFun::RegisterFunction(BuiltinFunctions &set) { auto varchar_list_type = LogicalType::LIST(LogicalType::VARCHAR); - set.AddFunction( - {"string_split", "str_split", "string_to_array", "split"}, - ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, varchar_list_type, StringSplitFunction)); - set.AddFunction( - {"string_split_regex", "str_split_regex", "regexp_split_to_array"}, - ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, varchar_list_type, StringSplitRegexFunction)); + auto regular_fun = + ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, varchar_list_type, StringSplitFunction); + regular_fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + set.AddFunction({"string_split", "str_split", "string_to_array", "split"}, regular_fun); + + auto regex_fun = + ScalarFunction({LogicalType::VARCHAR, LogicalType::VARCHAR}, varchar_list_type, StringSplitRegexFunction); + regex_fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + set.AddFunction({"string_split_regex", "str_split_regex", "regexp_split_to_array"}, regex_fun); } } // namespace duckdb @@ -107815,10 +119188,10 @@ static unique_ptr SubstringPropagateStats(ClientContext &context void SubstringFun::RegisterFunction(BuiltinFunctions &set) { ScalarFunctionSet substr("substring"); substr.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::BIGINT, LogicalType::BIGINT}, - LogicalType::VARCHAR, SubstringFunction, false, false, nullptr, nullptr, + LogicalType::VARCHAR, SubstringFunction, nullptr, nullptr, SubstringPropagateStats)); substr.AddFunction(ScalarFunction({LogicalType::VARCHAR, LogicalType::BIGINT}, LogicalType::VARCHAR, - SubstringFunction, false, false, nullptr, nullptr, SubstringPropagateStats)); + SubstringFunction, nullptr, nullptr, SubstringPropagateStats)); set.AddFunction(substr); substr.name = "substr"; set.AddFunction(substr); @@ -108059,6 +119432,7 @@ void BuiltinFunctions::RegisterStringFunctions() { Register(); Register(); Register(); + Register(); // blob functions Register(); @@ -108073,6 +119447,7 @@ void BuiltinFunctions::RegisterStringFunctions() { + //===----------------------------------------------------------------------===// // DuckDB // @@ -108111,7 +119486,6 @@ class StructStatistics : public BaseStatistics { } // namespace duckdb - namespace duckdb { struct StructExtractBindData : public FunctionData { @@ -108150,22 +119524,22 @@ static void StructExtractFunction(DataChunk &args, ExpressionState &state, Vecto static unique_ptr StructExtractBind(ClientContext &context, ScalarFunction &bound_function, vector> &arguments) { D_ASSERT(bound_function.arguments.size() == 2); - if (arguments[0]->return_type.id() == LogicalTypeId::SQLNULL || - arguments[1]->return_type.id() == LogicalTypeId::SQLNULL) { - bound_function.return_type = LogicalType::SQLNULL; - bound_function.arguments[0] = LogicalType::SQLNULL; - return make_unique("", 0, LogicalType::SQLNULL); + if (arguments[0]->return_type.id() == LogicalTypeId::UNKNOWN) { + throw ParameterNotResolvedException(); } D_ASSERT(LogicalTypeId::STRUCT == arguments[0]->return_type.id()); auto &struct_children = StructType::GetChildTypes(arguments[0]->return_type); if (struct_children.empty()) { throw InternalException("Can't extract something from an empty struct"); } + bound_function.arguments[0] = arguments[0]->return_type; auto &key_child = arguments[1]; + if (key_child->HasParameter()) { + throw ParameterNotResolvedException(); + } - if (key_child->return_type.id() != LogicalTypeId::VARCHAR || - key_child->return_type.id() != LogicalTypeId::VARCHAR || !key_child->IsFoldable()) { + if (key_child->return_type.id() != LogicalTypeId::VARCHAR || !key_child->IsFoldable()) { throw BinderException("Key name for struct_extract needs to be a constant string"); } Value key_val = ExpressionExecutor::EvaluateScalar(*key_child.get()); @@ -108202,7 +119576,6 @@ static unique_ptr StructExtractBind(ClientContext &context, Scalar } bound_function.return_type = return_type; - bound_function.arguments[0] = arguments[0]->return_type; return make_unique(key, key_index, return_type); } @@ -108222,7 +119595,7 @@ static unique_ptr PropagateStructExtractStats(ClientContext &con ScalarFunction StructExtractFun::GetFunction() { return ScalarFunction("struct_extract", {LogicalTypeId::STRUCT, LogicalType::VARCHAR}, LogicalType::ANY, - StructExtractFunction, false, StructExtractBind, nullptr, PropagateStructExtractStats); + StructExtractFunction, StructExtractBind, nullptr, PropagateStructExtractStats); } void StructExtractFun::RegisterFunction(BuiltinFunctions &set) { @@ -108240,6 +119613,116 @@ void StructExtractFun::RegisterFunction(BuiltinFunctions &set) { +namespace duckdb { + +static void StructInsertFunction(DataChunk &args, ExpressionState &state, Vector &result) { + auto &starting_vec = args.data[0]; + + starting_vec.Verify(args.size()); + + auto &starting_child_entries = StructVector::GetEntries(starting_vec); + auto &result_child_entries = StructVector::GetEntries(result); + + // Assign the starting vector entries to the result vector + for (size_t i = 0; i < starting_child_entries.size(); i++) { + auto &starting_child = starting_child_entries[i]; + result_child_entries[i]->Reference(*starting_child); + } + + // Assign the new entries to the result vector + for (size_t i = 1; i < args.ColumnCount(); i++) { + result_child_entries[starting_child_entries.size() + i - 1]->Reference(args.data[i]); + } + + result.Verify(args.size()); + + if (args.AllConstant()) { + result.SetVectorType(VectorType::CONSTANT_VECTOR); + } +} + +static unique_ptr StructInsertBind(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + case_insensitive_set_t name_collision_set; + + if (arguments.empty()) { + throw Exception("Missing required arguments for struct_insert function."); + } + + if (LogicalTypeId::STRUCT != arguments[0]->return_type.id()) { + throw Exception("The first argument to struct_insert must be a STRUCT"); + } + + if (arguments.size() < 2) { + throw Exception("Can't insert nothing into a struct"); + } + + child_list_t new_struct_children; + + auto &existing_struct_children = StructType::GetChildTypes(arguments[0]->return_type); + + for (size_t i = 0; i < existing_struct_children.size(); i++) { + auto &child = existing_struct_children[i]; + name_collision_set.insert(child.first); + new_struct_children.push_back(make_pair(child.first, child.second)); + } + + // Loop through the additional arguments (name/value pairs) + for (idx_t i = 1; i < arguments.size(); i++) { + auto &child = arguments[i]; + if (child->alias.empty() && bound_function.name == "struct_insert") { + throw BinderException("Need named argument for struct insert, e.g. STRUCT_PACK(a := b)"); + } + if (name_collision_set.find(child->alias) != name_collision_set.end()) { + throw BinderException("Duplicate struct entry name \"%s\"", child->alias); + } + name_collision_set.insert(child->alias); + new_struct_children.push_back(make_pair(child->alias, arguments[i]->return_type)); + } + + // this is more for completeness reasons + bound_function.return_type = LogicalType::STRUCT(move(new_struct_children)); + return make_unique(bound_function.return_type); +} + +unique_ptr StructInsertStats(ClientContext &context, FunctionStatisticsInput &input) { + auto &child_stats = input.child_stats; + auto &expr = input.expr; + + auto &existing_struct_stats = (StructStatistics &)*child_stats[0]; + auto new_struct_stats = make_unique(expr.return_type); + + for (idx_t i = 0; i < existing_struct_stats.child_stats.size(); i++) { + new_struct_stats->child_stats[i] = + existing_struct_stats.child_stats[i] ? existing_struct_stats.child_stats[i]->Copy() : nullptr; + } + + auto offset = new_struct_stats->child_stats.size() - child_stats.size(); + for (idx_t i = 1; i < child_stats.size(); i++) { + new_struct_stats->child_stats[offset + i] = child_stats[i] ? child_stats[i]->Copy() : nullptr; + } + return move(new_struct_stats); +} + +void StructInsertFun::RegisterFunction(BuiltinFunctions &set) { + // the arguments and return types are actually set in the binder function + ScalarFunction fun("struct_insert", {}, LogicalTypeId::STRUCT, StructInsertFunction, StructInsertBind, nullptr, + StructInsertStats); + fun.varargs = LogicalType::ANY; + fun.serialize = VariableReturnBindData::Serialize; + fun.deserialize = VariableReturnBindData::Deserialize; + set.AddFunction(fun); +} + +} // namespace duckdb + + + + + + + + namespace duckdb { static void StructPackFunction(DataChunk &args, ExpressionState &state, Vector &result) { @@ -108305,9 +119788,12 @@ unique_ptr StructPackStats(ClientContext &context, FunctionStati void StructPackFun::RegisterFunction(BuiltinFunctions &set) { // the arguments and return types are actually set in the binder function - ScalarFunction fun("struct_pack", {}, LogicalTypeId::STRUCT, StructPackFunction, false, StructPackBind, nullptr, + ScalarFunction fun("struct_pack", {}, LogicalTypeId::STRUCT, StructPackFunction, StructPackBind, nullptr, StructPackStats); fun.varargs = LogicalType::ANY; + fun.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + fun.serialize = VariableReturnBindData::Serialize; + fun.deserialize = VariableReturnBindData::Deserialize; set.AddFunction(fun); fun.name = "row"; set.AddFunction(fun); @@ -108324,11 +119810,11 @@ namespace duckdb { // aggregate state export struct ExportAggregateBindData : public FunctionData { - AggregateFunction &aggr; + AggregateFunction aggr; idx_t state_size; - explicit ExportAggregateBindData(AggregateFunction &aggr_p, idx_t state_size_p) - : aggr(aggr_p), state_size(state_size_p) { + explicit ExportAggregateBindData(AggregateFunction aggr_p, idx_t state_size_p) + : aggr(move(aggr_p)), state_size(state_size_p) { } unique_ptr Copy() const override { @@ -108394,8 +119880,8 @@ static void AggregateStateFinalize(DataChunk &input, ExpressionState &state_p, V auto state_vec_ptr = FlatVector::GetData(local_state.addresses); - VectorData state_data; - input.data[0].Orrify(input.size(), state_data); + UnifiedVectorFormat state_data; + input.data[0].ToUnifiedFormat(input.size(), state_data); for (idx_t i = 0; i < input.size(); i++) { auto state_idx = state_data.sel->get_index(i); auto state_entry = &((string_t *)state_data.data)[state_idx]; @@ -108412,7 +119898,8 @@ static void AggregateStateFinalize(DataChunk &input, ExpressionState &state_p, V state_vec_ptr[i] = (data_ptr_t)target_ptr; } - bind_data.aggr.finalize(local_state.addresses, nullptr, result, input.size(), 0); + AggregateInputData aggr_input_data(nullptr, Allocator::DefaultAllocator()); + bind_data.aggr.finalize(local_state.addresses, aggr_input_data, result, input.size(), 0); for (idx_t i = 0; i < input.size(); i++) { auto state_idx = state_data.sel->get_index(i); @@ -108437,9 +119924,9 @@ static void AggregateStateCombine(DataChunk &input, ExpressionState &state_p, Ve input.data[0].GetType().ToString(), input.data[1].GetType().ToString()); } - VectorData state0_data, state1_data; - input.data[0].Orrify(input.size(), state0_data); - input.data[1].Orrify(input.size(), state1_data); + UnifiedVectorFormat state0_data, state1_data; + input.data[0].ToUnifiedFormat(input.size(), state0_data); + input.data[1].ToUnifiedFormat(input.size(), state1_data); auto result_ptr = FlatVector::GetData(result); @@ -108475,7 +119962,8 @@ static void AggregateStateCombine(DataChunk &input, ExpressionState &state_p, Ve memcpy(local_state.state_buffer0.get(), state0.GetDataUnsafe(), bind_data.state_size); memcpy(local_state.state_buffer1.get(), state1.GetDataUnsafe(), bind_data.state_size); - bind_data.aggr.combine(local_state.state_vector0, local_state.state_vector1, nullptr, 1); + AggregateInputData aggr_input_data(nullptr, Allocator::DefaultAllocator()); + bind_data.aggr.combine(local_state.state_vector0, local_state.state_vector1, aggr_input_data, 1); result_ptr[i] = StringVector::AddStringOrBlob(result, (const char *)local_state.state_buffer1.get(), bind_data.state_size); @@ -108521,7 +120009,7 @@ static unique_ptr BindAggregateState(ClientContext &context, Scala if (best_function == DConstants::INVALID_INDEX) { throw InternalException("Could not re-bind exported aggregate %s: %s", state_type.function_name, error); } - auto &bound_aggr = aggr->functions[best_function]; + auto bound_aggr = aggr->functions.GetFunctionByOffset(best_function); if (bound_aggr.return_type != state_type.return_type || bound_aggr.arguments != state_type.bound_argument_types) { throw InternalException("Type mismatch for exported aggregate %s", state_type.function_name); } @@ -108536,10 +120024,10 @@ static unique_ptr BindAggregateState(ClientContext &context, Scala return make_unique(bound_aggr, bound_aggr.state_size()); } -static void ExportAggregateFinalize(Vector &state, FunctionData *bind_data_p, Vector &result, idx_t count, +static void ExportAggregateFinalize(Vector &state, AggregateInputData &aggr_input_data, Vector &result, idx_t count, idx_t offset) { D_ASSERT(offset == 0); - auto bind_data = (ExportAggregateFunctionBindData *)bind_data_p; + auto bind_data = (ExportAggregateFunctionBindData *)aggr_input_data.bind_data; auto state_size = bind_data->aggregate->function.state_size(); auto blob_ptr = FlatVector::GetData(result); auto addresses_ptr = FlatVector::GetData(state); @@ -108563,6 +120051,24 @@ bool ExportAggregateFunctionBindData::Equals(const FunctionData &other_p) const return aggregate->Equals(other.aggregate.get()); } +static void ExportStateAggregateSerialize(FieldWriter &writer, const FunctionData *bind_data_p, + const AggregateFunction &function) { + throw NotImplementedException("FIXME: export state serialize"); +} +static unique_ptr ExportStateAggregateDeserialize(ClientContext &context, FieldReader &reader, + AggregateFunction &bound_function) { + throw NotImplementedException("FIXME: export state deserialize"); +} + +static void ExportStateScalarSerialize(FieldWriter &writer, const FunctionData *bind_data_p, + const ScalarFunction &function) { + throw NotImplementedException("FIXME: export state serialize"); +} +static unique_ptr ExportStateScalarDeserialize(ClientContext &context, FieldReader &reader, + ScalarFunction &bound_function) { + throw NotImplementedException("FIXME: export state deserialize"); +} + unique_ptr ExportAggregateFunction::Bind(unique_ptr child_aggregate) { auto &bound_function = child_aggregate->function; @@ -108597,6 +120103,9 @@ ExportAggregateFunction::Bind(unique_ptr child_aggrega bound_function.combine, ExportAggregateFinalize, bound_function.simple_update, /* can't bind this again */ nullptr, /* no dynamic state yet */ nullptr, /* can't propagate statistics */ nullptr, nullptr); + export_function.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + export_function.serialize = ExportStateAggregateSerialize; + export_function.deserialize = ExportStateAggregateDeserialize; return make_unique(export_function, move(child_aggregate->children), move(child_aggregate->filter), move(export_bind_data), @@ -108604,14 +120113,22 @@ ExportAggregateFunction::Bind(unique_ptr child_aggrega } ScalarFunction ExportAggregateFunction::GetFinalize() { - return ScalarFunction("finalize", {LogicalTypeId::AGGREGATE_STATE}, LogicalTypeId::INVALID, AggregateStateFinalize, - false, BindAggregateState, nullptr, nullptr, InitFinalizeState); + auto result = ScalarFunction("finalize", {LogicalTypeId::AGGREGATE_STATE}, LogicalTypeId::INVALID, + AggregateStateFinalize, BindAggregateState, nullptr, nullptr, InitFinalizeState); + result.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + result.serialize = ExportStateScalarSerialize; + result.deserialize = ExportStateScalarDeserialize; + return result; } ScalarFunction ExportAggregateFunction::GetCombine() { - return ScalarFunction("combine", {LogicalTypeId::AGGREGATE_STATE, LogicalTypeId::ANY}, - LogicalTypeId::AGGREGATE_STATE, AggregateStateCombine, false, BindAggregateState, nullptr, - nullptr, InitCombineState); + auto result = + ScalarFunction("combine", {LogicalTypeId::AGGREGATE_STATE, LogicalTypeId::ANY}, LogicalTypeId::AGGREGATE_STATE, + AggregateStateCombine, BindAggregateState, nullptr, nullptr, InitCombineState); + result.null_handling = FunctionNullHandling::SPECIAL_HANDLING; + result.serialize = ExportStateScalarSerialize; + result.deserialize = ExportStateScalarDeserialize; + return result; } } // namespace duckdb @@ -108689,14 +120206,14 @@ static void VersionFunction(DataChunk &input, ExpressionState &state, Vector &re void SystemFun::RegisterFunction(BuiltinFunctions &set) { auto varchar_list_type = LogicalType::LIST(LogicalType::VARCHAR); + ScalarFunction current_query("current_query", {}, LogicalType::VARCHAR, CurrentQueryFunction, BindSystemFunction); + current_query.side_effects = FunctionSideEffects::HAS_SIDE_EFFECTS; + set.AddFunction(current_query); set.AddFunction( - ScalarFunction("current_query", {}, LogicalType::VARCHAR, CurrentQueryFunction, true, BindSystemFunction)); - set.AddFunction( - ScalarFunction("current_schema", {}, LogicalType::VARCHAR, CurrentSchemaFunction, false, BindSystemFunction)); + ScalarFunction("current_schema", {}, LogicalType::VARCHAR, CurrentSchemaFunction, BindSystemFunction)); set.AddFunction(ScalarFunction("current_schemas", {LogicalType::BOOLEAN}, varchar_list_type, CurrentSchemasFunction, - false, BindSystemFunction)); - set.AddFunction( - ScalarFunction("txid_current", {}, LogicalType::BIGINT, TransactionIdCurrent, false, BindSystemFunction)); + BindSystemFunction)); + set.AddFunction(ScalarFunction("txid_current", {}, LogicalType::BIGINT, TransactionIdCurrent, BindSystemFunction)); set.AddFunction(ScalarFunction("version", {}, LogicalType::VARCHAR, VersionFunction)); set.AddFunction(ExportAggregateFunction::GetCombine()); set.AddFunction(ExportAggregateFunction::GetFinalize()); @@ -108729,21 +120246,22 @@ FunctionLocalState::~FunctionLocalState() { } ScalarFunction::ScalarFunction(string name, vector arguments, LogicalType return_type, - scalar_function_t function, bool has_side_effects, bind_scalar_function_t bind, + scalar_function_t function, bind_scalar_function_t bind, dependency_function_t dependency, function_statistics_t statistics, - init_local_state_t init_local_state, LogicalType varargs, bool propagate_null_values) - : BaseScalarFunction(move(name), move(arguments), move(return_type), has_side_effects, move(varargs), - propagate_null_values), + init_local_state_t init_local_state, LogicalType varargs, + FunctionSideEffects side_effects, FunctionNullHandling null_handling) + : BaseScalarFunction(move(name), move(arguments), move(return_type), side_effects, move(varargs), null_handling), function(move(function)), bind(bind), init_local_state(init_local_state), dependency(dependency), - statistics(statistics) { + statistics(statistics), serialize(nullptr), deserialize(nullptr) { } ScalarFunction::ScalarFunction(vector arguments, LogicalType return_type, scalar_function_t function, - bool propagate_null_values, bool has_side_effects, bind_scalar_function_t bind, - dependency_function_t dependency, function_statistics_t statistics, - init_local_state_t init_local_state, LogicalType varargs) - : ScalarFunction(string(), move(arguments), move(return_type), move(function), has_side_effects, bind, dependency, - statistics, init_local_state, move(varargs), propagate_null_values) { + bind_scalar_function_t bind, dependency_function_t dependency, + function_statistics_t statistics, init_local_state_t init_local_state, + LogicalType varargs, FunctionSideEffects side_effects, + FunctionNullHandling null_handling) + : ScalarFunction(string(), move(arguments), move(return_type), move(function), bind, dependency, statistics, + init_local_state, move(varargs), side_effects, null_handling) { } bool ScalarFunction::operator==(const ScalarFunction &rhs) const { @@ -108812,6 +120330,8 @@ void ScalarFunction::NopFunction(DataChunk &input, ExpressionState &state, Vecto + + namespace duckdb { ScalarMacroFunction::ScalarMacroFunction(unique_ptr expression) @@ -108829,6 +120349,26 @@ unique_ptr ScalarMacroFunction::Copy() { return move(result); } +void RemoveQualificationRecursive(unique_ptr &expr) { + if (expr->GetExpressionType() == ExpressionType::COLUMN_REF) { + auto &col_ref = (ColumnRefExpression &)*expr; + auto &col_names = col_ref.column_names; + if (col_names.size() == 2 && col_names[0].find(DummyBinding::DUMMY_NAME) != string::npos) { + col_names.erase(col_names.begin()); + } + } else { + ParsedExpressionIterator::EnumerateChildren( + *expr, [](unique_ptr &child) { RemoveQualificationRecursive(child); }); + } +} + +string ScalarMacroFunction::ToSQL(const string &schema, const string &name) { + // In case of nested macro's we need to fix it a bit + auto expression_copy = expression->Copy(); + RemoveQualificationRecursive(expression_copy); + return MacroFunction::ToSQL(schema, name) + StringUtil::Format("(%s);", expression_copy->ToString()); +} + } // namespace duckdb @@ -108891,6 +120431,7 @@ enum class ArrowDateTimeType : uint8_t { struct ArrowConvertData { ArrowConvertData(LogicalType type) : dictionary_type(type) {}; ArrowConvertData() {}; + //! Hold type of dictionary LogicalType dictionary_type; //! If its a variable size type (e.g., strings, blobs, lists) holds which type it is @@ -108899,16 +120440,23 @@ struct ArrowConvertData { vector date_time_precision; }; -typedef unique_ptr (*stream_factory_produce_t)( - uintptr_t stream_factory_ptr, pair, vector> &project_columns, - TableFilterSet *filters); +struct ArrowProjectedColumns { + unordered_map projection_map; + vector columns; +}; + +struct ArrowStreamParameters { + ArrowProjectedColumns projected_columns; + TableFilterSet *filters; +}; + +typedef unique_ptr (*stream_factory_produce_t)(uintptr_t stream_factory_ptr, + ArrowStreamParameters ¶meters); typedef void (*stream_factory_get_schema_t)(uintptr_t stream_factory_ptr, ArrowSchemaWrapper &schema); -struct ArrowScanFunctionData : public TableFunctionData { - ArrowScanFunctionData(idx_t rows_per_thread_p, stream_factory_produce_t scanner_producer_p, - uintptr_t stream_factory_ptr_p) - : lines_read(0), rows_per_thread(rows_per_thread_p), stream_factory_ptr(stream_factory_ptr_p), - scanner_producer(scanner_producer_p), number_of_rows(0) { +struct ArrowScanFunctionData : public PyTableFunctionData { + ArrowScanFunctionData(stream_factory_produce_t scanner_producer_p, uintptr_t stream_factory_ptr_p) + : lines_read(0), stream_factory_ptr(stream_factory_ptr_p), scanner_producer(scanner_producer_p) { } //! This holds the original list type (col_idx, [ArrowListType,size]) unordered_map> arrow_convert_data; @@ -108919,8 +120467,6 @@ struct ArrowScanFunctionData : public TableFunctionData { uintptr_t stream_factory_ptr; //! Pointer to the scanner factory produce stream_factory_produce_t scanner_producer; - //! Number of rows (Used in cardinality and progress bar) - int64_t number_of_rows; }; struct ArrowScanLocalState : public LocalTableFunctionState { @@ -108965,7 +120511,8 @@ struct ArrowTableFunction { TableFunctionInitInput &input); //! Initialize Local State - static unique_ptr ArrowScanInitLocal(ClientContext &context, TableFunctionInitInput &input, + static unique_ptr ArrowScanInitLocal(ExecutionContext &context, + TableFunctionInitInput &input, GlobalTableFunctionState *global_state); //! Scan Function @@ -109175,10 +120722,8 @@ unique_ptr ArrowTableFunction::ArrowScanBind(ClientContext &contex auto stream_factory_ptr = input.inputs[0].GetPointer(); auto stream_factory_produce = (stream_factory_produce_t)input.inputs[1].GetPointer(); auto stream_factory_get_schema = (stream_factory_get_schema_t)input.inputs[2].GetPointer(); - auto rows_per_thread = input.inputs[3].GetValue(); - pair, vector> project_columns; - auto res = make_unique(rows_per_thread, stream_factory_produce, stream_factory_ptr); + auto res = make_unique(stream_factory_produce, stream_factory_ptr); auto &data = *res; stream_factory_get_schema(stream_factory_ptr, data.schema_root); @@ -109208,25 +120753,22 @@ unique_ptr ArrowTableFunction::ArrowScanBind(ClientContext &contex unique_ptr ProduceArrowScan(const ArrowScanFunctionData &function, const vector &column_ids, TableFilterSet *filters) { //! Generate Projection Pushdown Vector - pair, vector> project_columns; + ArrowStreamParameters parameters; D_ASSERT(!column_ids.empty()); for (idx_t idx = 0; idx < column_ids.size(); idx++) { auto col_idx = column_ids[idx]; if (col_idx != COLUMN_IDENTIFIER_ROW_ID) { auto &schema = *function.schema_root.arrow_schema.children[col_idx]; - project_columns.first[idx] = schema.name; - project_columns.second.emplace_back(schema.name); + parameters.projected_columns.projection_map[idx] = schema.name; + parameters.projected_columns.columns.emplace_back(schema.name); } } - return function.scanner_producer(function.stream_factory_ptr, project_columns, filters); + parameters.filters = filters; + return function.scanner_producer(function.stream_factory_ptr, parameters); } idx_t ArrowTableFunction::ArrowScanMaxThreads(ClientContext &context, const FunctionData *bind_data_p) { - auto &bind_data = (const ArrowScanFunctionData &)*bind_data_p; - if (bind_data.number_of_rows <= 0 || ClientConfig::GetConfig(context).verify_parallelism) { - return context.db->NumberOfThreads(); - } - return ((bind_data.number_of_rows + bind_data.rows_per_thread - 1) / bind_data.rows_per_thread) + 1; + return context.db->NumberOfThreads(); } bool ArrowScanParallelStateNext(ClientContext &context, const FunctionData *bind_data_p, ArrowScanLocalState &state, @@ -109255,7 +120797,7 @@ unique_ptr ArrowTableFunction::ArrowScanInitGlobal(Cli return move(result); } -unique_ptr ArrowTableFunction::ArrowScanInitLocal(ClientContext &context, +unique_ptr ArrowTableFunction::ArrowScanInitLocal(ExecutionContext &context, TableFunctionInitInput &input, GlobalTableFunctionState *global_state_p) { auto &global_state = (ArrowScanGlobalState &)*global_state_p; @@ -109263,7 +120805,7 @@ unique_ptr ArrowTableFunction::ArrowScanInitLocal(Clien auto result = make_unique(move(current_chunk)); result->column_ids = input.column_ids; result->filters = input.filters; - if (!ArrowScanParallelStateNext(context, input.bind_data, *result, global_state)) { + if (!ArrowScanParallelStateNext(context.client, input.bind_data, *result, global_state)) { return nullptr; } return move(result); @@ -109292,28 +120834,15 @@ void ArrowTableFunction::ArrowScanFunction(ClientContext &context, TableFunction } unique_ptr ArrowTableFunction::ArrowScanCardinality(ClientContext &context, const FunctionData *data) { - auto &bind_data = (ArrowScanFunctionData &)*data; - return make_unique(bind_data.number_of_rows, bind_data.number_of_rows); -} - -double ArrowTableFunction::ArrowProgress(ClientContext &context, const FunctionData *bind_data_p, - const GlobalTableFunctionState *global_state) { - auto &bind_data = (const ArrowScanFunctionData &)*bind_data_p; - if (bind_data.number_of_rows == 0) { - return 100; - } - auto percentage = bind_data.lines_read * 100.0 / bind_data.number_of_rows; - return percentage; + return make_unique(); } void ArrowTableFunction::RegisterFunction(BuiltinFunctions &set) { - TableFunction arrow("arrow_scan", - {LogicalType::POINTER, LogicalType::POINTER, LogicalType::POINTER, LogicalType::UBIGINT}, + TableFunction arrow("arrow_scan", {LogicalType::POINTER, LogicalType::POINTER, LogicalType::POINTER}, ArrowScanFunction, ArrowScanBind, ArrowScanInitGlobal, ArrowScanInitLocal); arrow.cardinality = ArrowScanCardinality; arrow.projection_pushdown = true; arrow.filter_pushdown = true; - arrow.table_scan_progress = ArrowProgress; set.AddFunction(arrow); } @@ -109341,17 +120870,16 @@ void ShiftRight(unsigned char *ar, int size, int shift) { } } -void SetValidityMask(Vector &vector, ArrowArray &array, ArrowScanLocalState &scan_state, idx_t size, - int64_t nested_offset, bool add_null = false) { - auto &mask = FlatVector::Validity(vector); +void GetValidityMask(ValidityMask &mask, ArrowArray &array, ArrowScanLocalState &scan_state, idx_t size, + int64_t nested_offset = -1, bool add_null = false) { if (array.null_count != 0 && array.buffers[0]) { - D_ASSERT(vector.GetVectorType() == VectorType::FLAT_VECTOR); auto bit_offset = scan_state.chunk_offset + array.offset; if (nested_offset != -1) { bit_offset = nested_offset; } - auto n_bitmask_bytes = (size + 8 - 1) / 8; mask.EnsureWritable(); +#if STANDARD_VECTOR_SIZE > 64 + auto n_bitmask_bytes = (size + 8 - 1) / 8; if (bit_offset % 8 == 0) { //! just memcpy nullmask memcpy((void *)mask.GetData(), (uint8_t *)array.buffers[0] + bit_offset / 8, n_bitmask_bytes); @@ -109363,6 +120891,19 @@ void SetValidityMask(Vector &vector, ArrowArray &array, ArrowScanLocalState &sca bit_offset % 8); //! why this has to be a right shift is a mystery to me memcpy((void *)mask.GetData(), (data_ptr_t)temp_nullmask.data(), n_bitmask_bytes); } +#else + auto byte_offset = bit_offset / 8; + auto source_data = (uint8_t *)array.buffers[0]; + bit_offset %= 8; + for (idx_t i = 0; i < size; i++) { + mask.Set(i, source_data[byte_offset] & (1 << bit_offset)); + bit_offset++; + if (bit_offset == 8) { + bit_offset = 0; + byte_offset++; + } + } +#endif } if (add_null) { //! We are setting a validity mask of the data part of dictionary vector @@ -109373,23 +120914,11 @@ void SetValidityMask(Vector &vector, ArrowArray &array, ArrowScanLocalState &sca } } -void GetValidityMask(ValidityMask &mask, ArrowArray &array, ArrowScanLocalState &scan_state, idx_t size) { - if (array.null_count != 0 && array.buffers[0]) { - auto bit_offset = scan_state.chunk_offset + array.offset; - auto n_bitmask_bytes = (size + 8 - 1) / 8; - mask.EnsureWritable(); - if (bit_offset % 8 == 0) { - //! just memcpy nullmask - memcpy((void *)mask.GetData(), (uint8_t *)array.buffers[0] + bit_offset / 8, n_bitmask_bytes); - } else { - //! need to re-align nullmask - std::vector temp_nullmask(n_bitmask_bytes + 1); - memcpy(temp_nullmask.data(), (uint8_t *)array.buffers[0] + bit_offset / 8, n_bitmask_bytes + 1); - ShiftRight(temp_nullmask.data(), n_bitmask_bytes + 1, - bit_offset % 8); //! why this has to be a right shift is a mystery to me - memcpy((void *)mask.GetData(), (data_ptr_t)temp_nullmask.data(), n_bitmask_bytes); - } - } +void SetValidityMask(Vector &vector, ArrowArray &array, ArrowScanLocalState &scan_state, idx_t size, + int64_t nested_offset, bool add_null = false) { + D_ASSERT(vector.GetVectorType() == VectorType::FLAT_VECTOR); + auto &mask = FlatVector::Validity(vector); + GetValidityMask(mask, array, scan_state, size, nested_offset, add_null); } void ColumnArrowToDuckDB(Vector &vector, ArrowArray &array, ArrowScanLocalState &scan_state, idx_t size, @@ -109419,7 +120948,7 @@ void ArrowToDuckDBList(Vector &vector, ArrowArray &array, ArrowScanLocalState &s le.length = original_type.second; cur_offset += original_type.second; } - list_size = cur_offset; + list_size = start_offset + cur_offset; } else if (original_type.first == ArrowVariableSizeType::NORMAL) { auto offsets = (uint32_t *)array.buffers[1] + array.offset + scan_state.chunk_offset; if (nested_offset != -1) { @@ -109770,7 +121299,7 @@ void ColumnArrowToDuckDB(Vector &vector, ArrowArray &array, ArrowScanLocalState } auto tgt_ptr = (date_t *)FlatVector::GetData(vector); for (idx_t row = 0; row < size; row++) { - tgt_ptr[row] = date_t(int64_t(src_ptr[row]) / (1000 * 60 * 60 * 24)); + tgt_ptr[row] = date_t(int64_t(src_ptr[row]) / static_cast(1000 * 60 * 60 * 24)); } break; } @@ -110243,6 +121772,9 @@ struct BaseCSVData : public TableFunctionData { vector files; //! The CSV reader options BufferedCSVReaderOptions options; + //! Offsets for generated columns + idx_t filename_col_idx; + idx_t hive_partition_col_idx; void Finalize(); }; @@ -110545,7 +122077,7 @@ struct GlobalWriteCSVData : public GlobalFunctionData { unique_ptr handle; }; -static unique_ptr WriteCSVInitializeLocal(ClientContext &context, FunctionData &bind_data) { +static unique_ptr WriteCSVInitializeLocal(ExecutionContext &context, FunctionData &bind_data) { auto &csv_data = (WriteCSVData &)bind_data; auto local_data = make_unique(); @@ -110553,7 +122085,7 @@ static unique_ptr WriteCSVInitializeLocal(ClientContext &cont vector types; types.resize(csv_data.options.names.size(), LogicalType::VARCHAR); - local_data->cast_chunk.Initialize(types); + local_data->cast_chunk.Initialize(Allocator::Get(context.client), types); return move(local_data); } @@ -110581,7 +122113,7 @@ static unique_ptr WriteCSVInitializeGlobal(ClientContext &co return move(global_data); } -static void WriteCSVSink(ClientContext &context, FunctionData &bind_data, GlobalFunctionData &gstate, +static void WriteCSVSink(ExecutionContext &context, FunctionData &bind_data, GlobalFunctionData &gstate, LocalFunctionData &lstate, DataChunk &input) { auto &csv_data = (WriteCSVData &)bind_data; auto &options = csv_data.options; @@ -110597,13 +122129,22 @@ static void WriteCSVSink(ClientContext &context, FunctionData &bind_data, Global if (csv_data.sql_types[col_idx].id() == LogicalTypeId::VARCHAR) { // VARCHAR, just create a reference cast_chunk.data[col_idx].Reference(input.data[col_idx]); + } else if (options.has_format[LogicalTypeId::DATE] && csv_data.sql_types[col_idx].id() == LogicalTypeId::DATE) { + // use the date format to cast the chunk + csv_data.options.write_date_format[LogicalTypeId::DATE].ConvertDateVector( + input.data[col_idx], cast_chunk.data[col_idx], input.size()); + } else if (options.has_format[LogicalTypeId::TIMESTAMP] && + csv_data.sql_types[col_idx].id() == LogicalTypeId::TIMESTAMP) { + // use the timestamp format to cast the chunk + csv_data.options.write_date_format[LogicalTypeId::TIMESTAMP].ConvertTimestampVector( + input.data[col_idx], cast_chunk.data[col_idx], input.size()); } else { // non varchar column, perform the cast VectorOperations::Cast(input.data[col_idx], cast_chunk.data[col_idx], input.size()); } } - cast_chunk.Normalify(); + cast_chunk.Flatten(); auto &writer = local_data.serializer; // now loop over the vectors and output the values for (idx_t row_idx = 0; row_idx < cast_chunk.size(); row_idx++) { @@ -110639,7 +122180,7 @@ static void WriteCSVSink(ClientContext &context, FunctionData &bind_data, Global //===--------------------------------------------------------------------===// // Combine //===--------------------------------------------------------------------===// -static void WriteCSVCombine(ClientContext &context, FunctionData &bind_data, GlobalFunctionData &gstate, +static void WriteCSVCombine(ExecutionContext &context, FunctionData &bind_data, GlobalFunctionData &gstate, LocalFunctionData &lstate) { auto &local_data = (LocalReadCSVData &)lstate; auto &global_state = (GlobalWriteCSVData &)gstate; @@ -110694,7 +122235,7 @@ struct GlobFunctionBindData : public TableFunctionData { static unique_ptr GlobFunctionBind(ClientContext &context, TableFunctionBindInput &input, vector &return_types, vector &names) { auto &config = DBConfig::GetConfig(context); - if (!config.enable_external_access) { + if (!config.options.enable_external_access) { throw PermissionException("Globbing is disabled through configuration"); } auto result = make_unique(); @@ -110802,6 +122343,10 @@ struct DuckDBDependenciesFun { static void RegisterFunction(BuiltinFunctions &set); }; +struct DuckDBExtensionsFun { + static void RegisterFunction(BuiltinFunctions &set); +}; + struct DuckDBFunctionsFun { static void RegisterFunction(BuiltinFunctions &set); }; @@ -110868,19 +122413,21 @@ struct TestVectorTypesFun { + namespace duckdb { struct PragmaDetailedProfilingOutputOperatorData : public GlobalTableFunctionState { - explicit PragmaDetailedProfilingOutputOperatorData() : chunk_index(0), initialized(false) { + explicit PragmaDetailedProfilingOutputOperatorData() : initialized(false) { } - idx_t chunk_index; + + ColumnDataScanState scan_state; bool initialized; }; struct PragmaDetailedProfilingOutputData : public TableFunctionData { explicit PragmaDetailedProfilingOutputData(vector &types) : types(types) { } - unique_ptr collection; + unique_ptr collection; vector types; }; @@ -110942,7 +122489,7 @@ static void SetValue(DataChunk &output, int index, int op_id, string annotation, output.SetValue(8, index, move(extra_info)); } -static void ExtractFunctions(ChunkCollection &collection, ExpressionInfo &info, DataChunk &chunk, int op_id, +static void ExtractFunctions(ColumnDataCollection &collection, ExpressionInfo &info, DataChunk &chunk, int op_id, int &fun_id) { if (info.hasfunction) { D_ASSERT(info.sample_tuples_count != 0); @@ -110971,12 +122518,12 @@ static void PragmaDetailedProfilingOutputFunction(ClientContext &context, TableF auto &data = (PragmaDetailedProfilingOutputData &)*data_p.bind_data; if (!state.initialized) { - // create a ChunkCollection - auto collection = make_unique(); + // create a ColumnDataCollection + auto collection = make_unique(context, data.types); // create a chunk DataChunk chunk; - chunk.Initialize(data.types); + chunk.Initialize(context, data.types); // Initialize ids int operator_counter = 1; @@ -111016,14 +122563,11 @@ static void PragmaDetailedProfilingOutputFunction(ClientContext &context, TableF } collection->Append(chunk); data.collection = move(collection); + data.collection->InitializeScan(state.scan_state); state.initialized = true; } - if (state.chunk_index >= data.collection->ChunkCount()) { - output.SetCardinality(0); - return; - } - output.Reference(data.collection->GetChunk(state.chunk_index++)); + data.collection->Scan(state.scan_state, output); } void PragmaDetailedProfilingOutput::RegisterFunction(BuiltinFunctions &set) { @@ -111041,19 +122585,21 @@ void PragmaDetailedProfilingOutput::RegisterFunction(BuiltinFunctions &set) { + namespace duckdb { struct PragmaLastProfilingOutputOperatorData : public GlobalTableFunctionState { - PragmaLastProfilingOutputOperatorData() : chunk_index(0), initialized(false) { + PragmaLastProfilingOutputOperatorData() : initialized(false) { } - idx_t chunk_index; + + ColumnDataScanState scan_state; bool initialized; }; struct PragmaLastProfilingOutputData : public TableFunctionData { explicit PragmaLastProfilingOutputData(vector &types) : types(types) { } - unique_ptr collection; + unique_ptr collection; vector types; }; @@ -111096,11 +122642,11 @@ static void PragmaLastProfilingOutputFunction(ClientContext &context, TableFunct auto &state = (PragmaLastProfilingOutputOperatorData &)*data_p.global_state; auto &data = (PragmaLastProfilingOutputData &)*data_p.bind_data; if (!state.initialized) { - // create a ChunkCollection - auto collection = make_unique(); + // create a ColumnDataCollection + auto collection = make_unique(context, data.types); DataChunk chunk; - chunk.Initialize(data.types); + chunk.Initialize(context, data.types); int operator_counter = 1; if (!ClientData::Get(context).query_profiler_history->GetPrevProfilers().empty()) { for (auto op : @@ -111116,14 +122662,11 @@ static void PragmaLastProfilingOutputFunction(ClientContext &context, TableFunct } collection->Append(chunk); data.collection = move(collection); + data.collection->InitializeScan(state.scan_state); state.initialized = true; } - if (state.chunk_index >= data.collection->ChunkCount()) { - output.SetCardinality(0); - return; - } - output.Reference(data.collection->GetChunk(state.chunk_index++)); + data.collection->Scan(state.scan_state, output); } void PragmaLastProfilingOutput::RegisterFunction(BuiltinFunctions &set) { @@ -111177,32 +122720,46 @@ struct RangeFunctionBindData : public TableFunctionData { }; template -static unique_ptr RangeFunctionBind(ClientContext &context, TableFunctionBindInput &input, - vector &return_types, vector &names) { - auto result = make_unique(); - auto &inputs = input.inputs; +static void GenerateRangeParameters(const vector &inputs, RangeFunctionBindData &result) { + for (auto &input : inputs) { + if (input.IsNull()) { + result.start = GENERATE_SERIES ? 1 : 0; + result.end = 0; + result.increment = 1; + return; + } + } if (inputs.size() < 2) { // single argument: only the end is specified - result->start = 0; - result->end = inputs[0].GetValue(); + result.start = 0; + result.end = inputs[0].GetValue(); } else { // two arguments: first two arguments are start and end - result->start = inputs[0].GetValue(); - result->end = inputs[1].GetValue(); + result.start = inputs[0].GetValue(); + result.end = inputs[1].GetValue(); } if (inputs.size() < 3) { - result->increment = 1; + result.increment = 1; } else { - result->increment = inputs[2].GetValue(); + result.increment = inputs[2].GetValue(); } - if (result->increment == 0) { + if (result.increment == 0) { throw BinderException("interval cannot be 0!"); } - if (result->start > result->end && result->increment > 0) { + if (result.start > result.end && result.increment > 0) { throw BinderException("start is bigger than end, but increment is positive: cannot generate infinite series"); - } else if (result->start < result->end && result->increment < 0) { + } else if (result.start < result.end && result.increment < 0) { throw BinderException("start is smaller than end, but increment is negative: cannot generate infinite series"); } +} + +template +static unique_ptr RangeFunctionBind(ClientContext &context, TableFunctionBindInput &input, + vector &return_types, vector &names) { + auto result = make_unique(); + auto &inputs = input.inputs; + GenerateRangeParameters(inputs, *result); + return_types.emplace_back(LogicalType::BIGINT); if (GENERATE_SERIES) { // generate_series has inclusive bounds on the RHS @@ -111424,6 +122981,7 @@ void BuiltinFunctions::RegisterTableFunctions() { + //===----------------------------------------------------------------------===// // DuckDB // @@ -111439,6 +122997,7 @@ void BuiltinFunctions::RegisterTableFunctions() { + namespace duckdb { //! Represents a Table producing function class TableFunctionRef : public TableRef { @@ -111451,6 +123010,9 @@ class TableFunctionRef : public TableRef { // if the function takes a subquery as argument its in here unique_ptr subquery; + // External dependencies of this table funcion + unique_ptr external_dependency; + public: string ToString() const override; @@ -111466,6 +123028,7 @@ class TableFunctionRef : public TableRef { } // namespace duckdb + #include namespace duckdb { @@ -111473,7 +123036,7 @@ namespace duckdb { static unique_ptr ReadCSVBind(ClientContext &context, TableFunctionBindInput &input, vector &return_types, vector &names) { auto &config = DBConfig::GetConfig(context); - if (!config.enable_external_access) { + if (!config.options.enable_external_access) { throw PermissionException("Scanning CSV files is disabled through configuration"); } auto result = make_unique(); @@ -111514,6 +123077,8 @@ static unique_ptr ReadCSVBind(ClientContext &context, TableFunctio options.normalize_names = BooleanValue::Get(kv.second); } else if (loption == "filename") { options.include_file_name = BooleanValue::Get(kv.second); + } else if (loption == "hive_partitioning") { + options.include_parsed_hive_partitions = BooleanValue::Get(kv.second); } else { options.SetReadOption(loption, kv.second, names); } @@ -111538,9 +123103,20 @@ static unique_ptr ReadCSVBind(ClientContext &context, TableFunctio D_ASSERT(return_types.size() == names.size()); } if (result->options.include_file_name) { + result->filename_col_idx = names.size(); return_types.emplace_back(LogicalType::VARCHAR); names.emplace_back("filename"); } + + if (result->options.include_parsed_hive_partitions) { + auto partitions = HivePartitioning::Parse(result->files[0]); + result->hive_partition_col_idx = names.size(); + for (auto &part : partitions) { + return_types.emplace_back(LogicalType::VARCHAR); + names.emplace_back(part.first); + } + } + result->options.names = names; return move(result); } @@ -111560,6 +123136,9 @@ static unique_ptr ReadCSVInit(ClientContext &context, auto result = make_unique(); if (bind_data.initial_reader) { result->csv_reader = move(bind_data.initial_reader); + } else if (bind_data.files.empty()) { + // This can happen when a filename based filter pushdown has eliminated all possible files for this scan. + return move(result); } else { bind_data.options.file_path = bind_data.files[0]; result->csv_reader = make_unique(context, bind_data.options, bind_data.sql_types); @@ -111578,6 +123157,12 @@ static unique_ptr ReadCSVAutoBind(ClientContext &context, TableFun static void ReadCSVFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { auto &bind_data = (ReadCSVData &)*data_p.bind_data; auto &data = (ReadCSVOperatorData &)*data_p.global_state; + + if (!data.csv_reader) { + // no csv_reader was set, this can happen when a filename-based filter has filtered out all possible files + return; + } + do { data.csv_reader->ParseCSV(output); data.bytes_read = data.csv_reader->bytes_in_chunk; @@ -111591,11 +123176,34 @@ static void ReadCSVFunction(ClientContext &context, TableFunctionInput &data_p, break; } } while (true); + if (bind_data.options.include_file_name) { - auto &col = output.data.back(); + auto &col = output.data[bind_data.filename_col_idx]; col.SetValue(0, Value(data.csv_reader->options.file_path)); col.SetVectorType(VectorType::CONSTANT_VECTOR); } + if (bind_data.options.include_parsed_hive_partitions) { + auto partitions = HivePartitioning::Parse(data.csv_reader->options.file_path); + + idx_t i = bind_data.hive_partition_col_idx; + + if (partitions.size() != (bind_data.options.names.size() - bind_data.hive_partition_col_idx)) { + throw IOException("Hive partition count mismatch, expected " + + std::to_string(bind_data.options.names.size() - bind_data.hive_partition_col_idx) + + " hive partitions, got " + std::to_string(partitions.size()) + "\n"); + } + + for (auto &part : partitions) { + if (bind_data.options.names[i] != part.first) { + throw IOException("Hive partition names mismatch, expected '" + bind_data.options.names[i] + + "' but found '" + part.first + "' for file '" + data.csv_reader->options.file_path + + "'"); + } + auto &col = output.data[i++]; + col.SetValue(0, Value(part.second)); + col.SetVectorType(VectorType::CONSTANT_VECTOR); + } + } } static void ReadCSVAddNamedParameters(TableFunction &table_function) { @@ -111616,6 +123224,7 @@ static void ReadCSVAddNamedParameters(TableFunction &table_function) { table_function.named_parameters["normalize_names"] = LogicalType::BOOLEAN; table_function.named_parameters["compression"] = LogicalType::VARCHAR; table_function.named_parameters["filename"] = LogicalType::BOOLEAN; + table_function.named_parameters["hive_partitioning"] = LogicalType::BOOLEAN; table_function.named_parameters["skip"] = LogicalType::BIGINT; table_function.named_parameters["max_line_size"] = LogicalType::VARCHAR; table_function.named_parameters["maximum_line_size"] = LogicalType::VARCHAR; @@ -111631,9 +123240,118 @@ double CSVReaderProgress(ClientContext &context, const FunctionData *bind_data_p return percentage; } +void CSVComplexFilterPushdown(ClientContext &context, LogicalGet &get, FunctionData *bind_data_p, + vector> &filters) { + auto data = (ReadCSVData *)bind_data_p; + + if (data->options.include_parsed_hive_partitions || data->options.include_file_name) { + string first_file = data->files[0]; + + unordered_map column_map; + for (idx_t i = 0; i < get.column_ids.size(); i++) { + column_map.insert({get.names[get.column_ids[i]], i}); + } + + HivePartitioning::ApplyFiltersToFileList(data->files, filters, column_map, get.table_index, + data->options.include_parsed_hive_partitions, + data->options.include_file_name); + + if (data->files.empty() || data->files[0] != first_file) { + data->initial_reader.reset(); + } + } +} + +void BufferedCSVReaderOptions::Serialize(FieldWriter &writer) const { + // common options + writer.WriteField(has_delimiter); + writer.WriteString(delimiter); + writer.WriteField(has_quote); + writer.WriteString(quote); + writer.WriteField(has_escape); + writer.WriteString(escape); + writer.WriteField(has_header); + writer.WriteField(header); + writer.WriteField(ignore_errors); + writer.WriteField(num_cols); + writer.WriteField(buffer_size); + writer.WriteString(null_str); + writer.WriteField(compression); + // read options + writer.WriteList(names); + writer.WriteField(skip_rows); + writer.WriteField(maximum_line_size); + writer.WriteField(normalize_names); + writer.WriteListNoReference(force_not_null); + writer.WriteField(all_varchar); + writer.WriteField(sample_chunk_size); + writer.WriteField(sample_chunks); + writer.WriteField(auto_detect); + writer.WriteString(file_path); + writer.WriteField(include_file_name); + writer.WriteField(include_parsed_hive_partitions); + // write options + writer.WriteListNoReference(force_quote); +} + +void BufferedCSVReaderOptions::Deserialize(FieldReader &reader) { + // common options + has_delimiter = reader.ReadRequired(); + delimiter = reader.ReadRequired(); + has_quote = reader.ReadRequired(); + quote = reader.ReadRequired(); + has_escape = reader.ReadRequired(); + escape = reader.ReadRequired(); + has_header = reader.ReadRequired(); + header = reader.ReadRequired(); + ignore_errors = reader.ReadRequired(); + num_cols = reader.ReadRequired(); + buffer_size = reader.ReadRequired(); + null_str = reader.ReadRequired(); + compression = reader.ReadRequired(); + // read options + names = reader.ReadRequiredList(); + skip_rows = reader.ReadRequired(); + maximum_line_size = reader.ReadRequired(); + normalize_names = reader.ReadRequired(); + force_not_null = reader.ReadRequiredList(); + all_varchar = reader.ReadRequired(); + sample_chunk_size = reader.ReadRequired(); + sample_chunks = reader.ReadRequired(); + auto_detect = reader.ReadRequired(); + file_path = reader.ReadRequired(); + include_file_name = reader.ReadRequired(); + include_parsed_hive_partitions = reader.ReadRequired(); + // write options + force_quote = reader.ReadRequiredList(); +} + +static void CSVReaderSerialize(FieldWriter &writer, const FunctionData *bind_data_p, const TableFunction &function) { + auto &bind_data = (ReadCSVData &)*bind_data_p; + writer.WriteList(bind_data.files); + writer.WriteRegularSerializableList(bind_data.sql_types); + writer.WriteField(bind_data.filename_col_idx); + writer.WriteField(bind_data.hive_partition_col_idx); + bind_data.options.Serialize(writer); +} + +static unique_ptr CSVReaderDeserialize(ClientContext &context, FieldReader &reader, + TableFunction &function) { + auto result_data = make_unique(); + result_data->files = reader.ReadRequiredList(); + result_data->sql_types = reader.ReadRequiredSerializableList(); + result_data->filename_col_idx = reader.ReadRequired(); + result_data->hive_partition_col_idx = reader.ReadRequired(); + result_data->options.Deserialize(reader); + return move(result_data); +} + TableFunction ReadCSVTableFunction::GetFunction() { TableFunction read_csv("read_csv", {LogicalType::VARCHAR}, ReadCSVFunction, ReadCSVBind, ReadCSVInit); read_csv.table_scan_progress = CSVReaderProgress; + read_csv.pushdown_complex_filter = CSVComplexFilterPushdown; + read_csv.serialize = CSVReaderSerialize; + read_csv.deserialize = CSVReaderDeserialize; ReadCSVAddNamedParameters(read_csv); return read_csv; } @@ -111643,6 +123361,9 @@ void ReadCSVTableFunction::RegisterFunction(BuiltinFunctions &set) { TableFunction read_csv_auto("read_csv_auto", {LogicalType::VARCHAR}, ReadCSVFunction, ReadCSVAutoBind, ReadCSVInit); read_csv_auto.table_scan_progress = CSVReaderProgress; + read_csv_auto.pushdown_complex_filter = CSVComplexFilterPushdown; + read_csv_auto.serialize = CSVReaderSerialize; + read_csv_auto.deserialize = CSVReaderDeserialize; ReadCSVAddNamedParameters(read_csv_auto); set.AddFunction(read_csv_auto); } @@ -111669,7 +123390,6 @@ unique_ptr ReadCSVReplacement(ClientContext &context, const st void BuiltinFunctions::RegisterReadFunctions() { CSVCopyFunction::RegisterFunction(*this); ReadCSVTableFunction::RegisterFunction(*this); - auto &config = DBConfig::GetConfig(context); config.replacement_scans.emplace_back(ReadCSVReplacement); } @@ -111752,7 +123472,7 @@ static unique_ptr SummaryFunctionBind(ClientContext &context, Tabl return make_unique(); } -static OperatorResultType SummaryFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &input, +static OperatorResultType SummaryFunction(ExecutionContext &context, TableFunctionInput &data_p, DataChunk &input, DataChunk &output) { output.SetCardinality(input.size()); @@ -112440,6 +124160,152 @@ void DuckDBDependenciesFun::RegisterFunction(BuiltinFunctions &set) { +namespace duckdb { + +struct ExtensionInformation { + string name; + bool loaded = false; + bool installed = false; + string file_path; + string description; +}; + +struct DuckDBExtensionsData : public GlobalTableFunctionState { + DuckDBExtensionsData() : offset(0) { + } + + vector entries; + idx_t offset; +}; + +static unique_ptr DuckDBExtensionsBind(ClientContext &context, TableFunctionBindInput &input, + vector &return_types, vector &names) { + names.emplace_back("extension_name"); + return_types.emplace_back(LogicalType::VARCHAR); + + names.emplace_back("loaded"); + return_types.emplace_back(LogicalType::BOOLEAN); + + names.emplace_back("installed"); + return_types.emplace_back(LogicalType::BOOLEAN); + + names.emplace_back("install_path"); + return_types.emplace_back(LogicalType::VARCHAR); + + names.emplace_back("description"); + return_types.emplace_back(LogicalType::VARCHAR); + + return nullptr; +} + +unique_ptr DuckDBExtensionsInit(ClientContext &context, TableFunctionInitInput &input) { + auto result = make_unique(); + + auto &fs = FileSystem::GetFileSystem(context); + auto &db = DatabaseInstance::GetDatabase(context); + + map installed_extensions; + auto extension_count = ExtensionHelper::DefaultExtensionCount(); + for (idx_t i = 0; i < extension_count; i++) { + auto extension = ExtensionHelper::GetDefaultExtension(i); + ExtensionInformation info; + info.name = extension.name; + info.installed = extension.statically_loaded; + info.loaded = false; + info.file_path = extension.statically_loaded ? "(BUILT-IN)" : string(); + info.description = extension.description; + installed_extensions[info.name] = move(info); + } + + // scan the install directory for installed extensions + auto ext_directory = ExtensionHelper::ExtensionDirectory(context); + fs.ListFiles(ext_directory, [&](const string &path, bool is_directory) { + if (!StringUtil::EndsWith(path, ".duckdb_extension")) { + return; + } + ExtensionInformation info; + info.name = fs.ExtractBaseName(path); + info.loaded = false; + info.file_path = fs.JoinPath(ext_directory, path); + auto entry = installed_extensions.find(info.name); + if (entry == installed_extensions.end()) { + installed_extensions[info.name] = move(info); + } else { + if (!entry->second.loaded) { + entry->second.file_path = info.file_path; + } + entry->second.installed = true; + } + }); + + // now check the list of currently loaded extensions + auto &loaded_extensions = db.LoadedExtensions(); + for (auto &ext_name : loaded_extensions) { + auto entry = installed_extensions.find(ext_name); + if (entry == installed_extensions.end()) { + ExtensionInformation info; + info.name = ext_name; + info.loaded = true; + installed_extensions[ext_name] = move(info); + } else { + entry->second.loaded = true; + } + } + + result->entries.reserve(installed_extensions.size()); + for (auto &kv : installed_extensions) { + result->entries.push_back(move(kv.second)); + } + return move(result); +} + +void DuckDBExtensionsFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { + auto &data = (DuckDBExtensionsData &)*data_p.global_state; + if (data.offset >= data.entries.size()) { + // finished returning values + return; + } + // start returning values + // either fill up the chunk or return all the remaining columns + idx_t count = 0; + while (data.offset < data.entries.size() && count < STANDARD_VECTOR_SIZE) { + auto &entry = data.entries[data.offset]; + + // return values: + // extension_name LogicalType::VARCHAR + output.SetValue(0, count, Value(entry.name)); + // loaded LogicalType::BOOLEAN + output.SetValue(1, count, Value::BOOLEAN(entry.loaded)); + // installed LogicalType::BOOLEAN + output.SetValue(2, count, !entry.installed && entry.loaded ? Value() : Value::BOOLEAN(entry.installed)); + // install_path LogicalType::VARCHAR + output.SetValue(3, count, Value(entry.file_path)); + // description LogicalType::VARCHAR + output.SetValue(4, count, Value(entry.description)); + + data.offset++; + count++; + } + output.SetCardinality(count); +} + +void DuckDBExtensionsFun::RegisterFunction(BuiltinFunctions &set) { + TableFunctionSet functions("duckdb_extensions"); + functions.AddFunction(TableFunction({}, DuckDBExtensionsFunction, DuckDBExtensionsBind, DuckDBExtensionsInit)); + set.AddFunction(functions); +} + +} // namespace duckdb + + + + + + + + + + @@ -112520,7 +124386,7 @@ unique_ptr DuckDBFunctionsInit(ClientContext &context, struct ScalarFunctionExtractor { static idx_t FunctionCount(ScalarFunctionCatalogEntry &entry) { - return entry.functions.size(); + return entry.functions.Size(); } static Value GetFunctionType() { @@ -112532,12 +124398,12 @@ struct ScalarFunctionExtractor { } static Value GetReturnType(ScalarFunctionCatalogEntry &entry, idx_t offset) { - return Value(entry.functions[offset].return_type.ToString()); + return Value(entry.functions.GetFunctionByOffset(offset).return_type.ToString()); } static Value GetParameters(ScalarFunctionCatalogEntry &entry, idx_t offset) { vector results; - for (idx_t i = 0; i < entry.functions[offset].arguments.size(); i++) { + for (idx_t i = 0; i < entry.functions.GetFunctionByOffset(offset).arguments.size(); i++) { results.emplace_back("col" + to_string(i)); } return Value::LIST(LogicalType::VARCHAR, move(results)); @@ -112545,16 +124411,16 @@ struct ScalarFunctionExtractor { static Value GetParameterTypes(ScalarFunctionCatalogEntry &entry, idx_t offset) { vector results; - for (idx_t i = 0; i < entry.functions[offset].arguments.size(); i++) { - results.emplace_back(entry.functions[offset].arguments[i].ToString()); + auto fun = entry.functions.GetFunctionByOffset(offset); + for (idx_t i = 0; i < fun.arguments.size(); i++) { + results.emplace_back(fun.arguments[i].ToString()); } return Value::LIST(LogicalType::VARCHAR, move(results)); } static Value GetVarArgs(ScalarFunctionCatalogEntry &entry, idx_t offset) { - return entry.functions[offset].varargs.id() == LogicalTypeId::INVALID - ? Value() - : Value(entry.functions[offset].varargs.ToString()); + auto fun = entry.functions.GetFunctionByOffset(offset); + return !fun.HasVarArgs() ? Value() : Value(fun.varargs.ToString()); } static Value GetMacroDefinition(ScalarFunctionCatalogEntry &entry, idx_t offset) { @@ -112562,13 +124428,14 @@ struct ScalarFunctionExtractor { } static Value HasSideEffects(ScalarFunctionCatalogEntry &entry, idx_t offset) { - return Value::BOOLEAN(entry.functions[offset].has_side_effects); + return Value::BOOLEAN(entry.functions.GetFunctionByOffset(offset).side_effects == + FunctionSideEffects::HAS_SIDE_EFFECTS); } }; struct AggregateFunctionExtractor { static idx_t FunctionCount(AggregateFunctionCatalogEntry &entry) { - return entry.functions.size(); + return entry.functions.Size(); } static Value GetFunctionType() { @@ -112580,12 +124447,12 @@ struct AggregateFunctionExtractor { } static Value GetReturnType(AggregateFunctionCatalogEntry &entry, idx_t offset) { - return Value(entry.functions[offset].return_type.ToString()); + return Value(entry.functions.GetFunctionByOffset(offset).return_type.ToString()); } static Value GetParameters(AggregateFunctionCatalogEntry &entry, idx_t offset) { vector results; - for (idx_t i = 0; i < entry.functions[offset].arguments.size(); i++) { + for (idx_t i = 0; i < entry.functions.GetFunctionByOffset(offset).arguments.size(); i++) { results.emplace_back("col" + to_string(i)); } return Value::LIST(LogicalType::VARCHAR, move(results)); @@ -112593,16 +124460,16 @@ struct AggregateFunctionExtractor { static Value GetParameterTypes(AggregateFunctionCatalogEntry &entry, idx_t offset) { vector results; - for (idx_t i = 0; i < entry.functions[offset].arguments.size(); i++) { - results.emplace_back(entry.functions[offset].arguments[i].ToString()); + auto fun = entry.functions.GetFunctionByOffset(offset); + for (idx_t i = 0; i < fun.arguments.size(); i++) { + results.emplace_back(fun.arguments[i].ToString()); } return Value::LIST(LogicalType::VARCHAR, move(results)); } static Value GetVarArgs(AggregateFunctionCatalogEntry &entry, idx_t offset) { - return entry.functions[offset].varargs.id() == LogicalTypeId::INVALID - ? Value() - : Value(entry.functions[offset].varargs.ToString()); + auto fun = entry.functions.GetFunctionByOffset(offset); + return !fun.HasVarArgs() ? Value() : Value(fun.varargs.ToString()); } static Value GetMacroDefinition(AggregateFunctionCatalogEntry &entry, idx_t offset) { @@ -112610,7 +124477,8 @@ struct AggregateFunctionExtractor { } static Value HasSideEffects(AggregateFunctionCatalogEntry &entry, idx_t offset) { - return Value::BOOLEAN(entry.functions[offset].has_side_effects); + return Value::BOOLEAN(entry.functions.GetFunctionByOffset(offset).side_effects == + FunctionSideEffects::HAS_SIDE_EFFECTS); } }; @@ -112730,7 +124598,7 @@ struct TableMacroExtractor { struct TableFunctionExtractor { static idx_t FunctionCount(TableFunctionCatalogEntry &entry) { - return entry.functions.size(); + return entry.functions.Size(); } static Value GetFunctionType() { @@ -112747,10 +124615,11 @@ struct TableFunctionExtractor { static Value GetParameters(TableFunctionCatalogEntry &entry, idx_t offset) { vector results; - for (idx_t i = 0; i < entry.functions[offset].arguments.size(); i++) { + auto fun = entry.functions.GetFunctionByOffset(offset); + for (idx_t i = 0; i < fun.arguments.size(); i++) { results.emplace_back("col" + to_string(i)); } - for (auto ¶m : entry.functions[offset].named_parameters) { + for (auto ¶m : fun.named_parameters) { results.emplace_back(param.first); } return Value::LIST(LogicalType::VARCHAR, move(results)); @@ -112758,19 +124627,20 @@ struct TableFunctionExtractor { static Value GetParameterTypes(TableFunctionCatalogEntry &entry, idx_t offset) { vector results; - for (idx_t i = 0; i < entry.functions[offset].arguments.size(); i++) { - results.emplace_back(entry.functions[offset].arguments[i].ToString()); + auto fun = entry.functions.GetFunctionByOffset(offset); + + for (idx_t i = 0; i < fun.arguments.size(); i++) { + results.emplace_back(fun.arguments[i].ToString()); } - for (auto ¶m : entry.functions[offset].named_parameters) { + for (auto ¶m : fun.named_parameters) { results.emplace_back(param.second.ToString()); } return Value::LIST(LogicalType::VARCHAR, move(results)); } static Value GetVarArgs(TableFunctionCatalogEntry &entry, idx_t offset) { - return entry.functions[offset].varargs.id() == LogicalTypeId::INVALID - ? Value() - : Value(entry.functions[offset].varargs.ToString()); + auto fun = entry.functions.GetFunctionByOffset(offset); + return !fun.HasVarArgs() ? Value() : Value(fun.varargs.ToString()); } static Value GetMacroDefinition(TableFunctionCatalogEntry &entry, idx_t offset) { @@ -112784,7 +124654,7 @@ struct TableFunctionExtractor { struct PragmaFunctionExtractor { static idx_t FunctionCount(PragmaFunctionCatalogEntry &entry) { - return entry.functions.size(); + return entry.functions.Size(); } static Value GetFunctionType() { @@ -112801,10 +124671,12 @@ struct PragmaFunctionExtractor { static Value GetParameters(PragmaFunctionCatalogEntry &entry, idx_t offset) { vector results; - for (idx_t i = 0; i < entry.functions[offset].arguments.size(); i++) { + auto fun = entry.functions.GetFunctionByOffset(offset); + + for (idx_t i = 0; i < fun.arguments.size(); i++) { results.emplace_back("col" + to_string(i)); } - for (auto ¶m : entry.functions[offset].named_parameters) { + for (auto ¶m : fun.named_parameters) { results.emplace_back(param.first); } return Value::LIST(LogicalType::VARCHAR, move(results)); @@ -112812,19 +124684,20 @@ struct PragmaFunctionExtractor { static Value GetParameterTypes(PragmaFunctionCatalogEntry &entry, idx_t offset) { vector results; - for (idx_t i = 0; i < entry.functions[offset].arguments.size(); i++) { - results.emplace_back(entry.functions[offset].arguments[i].ToString()); + auto fun = entry.functions.GetFunctionByOffset(offset); + + for (idx_t i = 0; i < fun.arguments.size(); i++) { + results.emplace_back(fun.arguments[i].ToString()); } - for (auto ¶m : entry.functions[offset].named_parameters) { + for (auto ¶m : fun.named_parameters) { results.emplace_back(param.second.ToString()); } return Value::LIST(LogicalType::VARCHAR, move(results)); } static Value GetVarArgs(PragmaFunctionCatalogEntry &entry, idx_t offset) { - return entry.functions[offset].varargs.id() == LogicalTypeId::INVALID - ? Value() - : Value(entry.functions[offset].varargs.ToString()); + auto fun = entry.functions.GetFunctionByOffset(offset); + return !fun.HasVarArgs() ? Value() : Value(fun.varargs.ToString()); } static Value GetMacroDefinition(PragmaFunctionCatalogEntry &entry, idx_t offset) { @@ -114139,7 +126012,7 @@ void AddFunction(BaseScalarFunction &f, idx_t &count, DataChunk &output, bool is output.SetValue(3, count, f.varargs.id() != LogicalTypeId::INVALID ? Value(f.varargs.ToString()) : Value()); output.SetValue(4, count, f.return_type.ToString()); - output.SetValue(5, count, Value::BOOLEAN(f.has_side_effects)); + output.SetValue(5, count, Value::BOOLEAN(f.side_effects == FunctionSideEffects::HAS_SIDE_EFFECTS)); count++; } @@ -114156,22 +126029,24 @@ static void PragmaFunctionsFunction(ClientContext &context, TableFunctionInput & switch (entry->type) { case CatalogType::SCALAR_FUNCTION_ENTRY: { auto &func = (ScalarFunctionCatalogEntry &)*entry; - if (data.offset_in_entry >= func.functions.size()) { + if (data.offset_in_entry >= func.functions.Size()) { data.offset++; data.offset_in_entry = 0; break; } - AddFunction(func.functions[data.offset_in_entry++], count, output, false); + auto entry = func.functions.GetFunctionByOffset(data.offset_in_entry++); + AddFunction(entry, count, output, false); break; } case CatalogType::AGGREGATE_FUNCTION_ENTRY: { auto &aggr = (AggregateFunctionCatalogEntry &)*entry; - if (data.offset_in_entry >= aggr.functions.size()) { + if (data.offset_in_entry >= aggr.functions.Size()) { data.offset++; data.offset_in_entry = 0; break; } - AddFunction(aggr.functions[data.offset_in_entry++], count, output, true); + auto entry = aggr.functions.GetFunctionByOffset(data.offset_in_entry++); + AddFunction(entry, count, output, true); break; } default: @@ -114324,6 +126199,7 @@ void PragmaStorageInfo::RegisterFunction(BuiltinFunctions &set) { + #include namespace duckdb { @@ -114343,6 +126219,7 @@ struct PragmaTableOperatorData : public GlobalTableFunctionState { static unique_ptr PragmaTableInfoBind(ClientContext &context, TableFunctionBindInput &input, vector &return_types, vector &names) { + names.emplace_back("cid"); return_types.emplace_back(LogicalType::INTEGER); @@ -114550,7 +126427,7 @@ vector TestAllTypesFun::GetTestTypes() { result.emplace_back(LogicalType::VARCHAR, "varchar", Value("🦆🦆🦆🦆🦆🦆"), Value("goose")); result.emplace_back(LogicalType::JSON, "json", Value("🦆🦆🦆🦆🦆🦆"), Value("goose")); result.emplace_back(LogicalType::BLOB, "blob", Value::BLOB("thisisalongblob\\x00withnullbytes"), - Value("\\x00\\x00\\x00a")); + Value::BLOB("\\x00\\x00\\x00a")); // enums Vector small_enum(LogicalType::VARCHAR, 2); @@ -114803,7 +126680,7 @@ struct TestVectorFlat { vector result_values = GenerateValues(info, info.type); for (idx_t cur_row = 0; cur_row < result_values.size(); cur_row += STANDARD_VECTOR_SIZE) { auto result = make_unique(); - result->Initialize({info.type}); + result->Initialize(Allocator::DefaultAllocator(), {info.type}); auto cardinality = MinValue(STANDARD_VECTOR_SIZE, result_values.size() - cur_row); for (idx_t i = 0; i < cardinality; i++) { result->data[0].SetValue(i, result_values[cur_row + i]); @@ -114819,7 +126696,7 @@ struct TestVectorConstant { auto values = TestVectorFlat::GenerateValues(info, info.type); for (idx_t cur_row = 0; cur_row < TestVectorFlat::TEST_VECTOR_CARDINALITY; cur_row += STANDARD_VECTOR_SIZE) { auto result = make_unique(); - result->Initialize({info.type}); + result->Initialize(Allocator::DefaultAllocator(), {info.type}); auto cardinality = MinValue(STANDARD_VECTOR_SIZE, TestVectorFlat::TEST_VECTOR_CARDINALITY - cur_row); result->data[0].SetValue(0, values[0]); result->data[0].SetVectorType(VectorType::CONSTANT_VECTOR); @@ -114884,7 +126761,7 @@ struct TestVectorSequence { static void Generate(TestVectorInfo &info) { #if STANDARD_VECTOR_SIZE > 2 auto result = make_unique(); - result->Initialize({info.type}); + result->Initialize(Allocator::DefaultAllocator(), {info.type}); GenerateVector(info, info.type, result->data[0]); result->SetCardinality(3); @@ -114949,7 +126826,7 @@ unique_ptr TestVectorTypesInit(ClientContext &context, } if (bind_data.all_flat) { for (auto &entry : result->entries) { - entry->Normalify(); + entry->Flatten(); entry->Verify(); } } @@ -115121,6 +126998,7 @@ void BuiltinFunctions::RegisterSQLiteFunctions() { DuckDBIndexesFun::RegisterFunction(*this); DuckDBSchemasFun::RegisterFunction(*this); DuckDBDependenciesFun::RegisterFunction(*this); + DuckDBExtensionsFun::RegisterFunction(*this); DuckDBSequencesFun::RegisterFunction(*this); DuckDBSettingsFun::RegisterFunction(*this); DuckDBTablesFun::RegisterFunction(*this); @@ -115146,6 +127024,10 @@ void BuiltinFunctions::RegisterSQLiteFunctions() { + + + + namespace duckdb { //===--------------------------------------------------------------------===// @@ -115184,7 +127066,7 @@ struct TableScanGlobalState : public GlobalTableFunctionState { } }; -static unique_ptr TableScanInitLocal(ClientContext &context, TableFunctionInitInput &input, +static unique_ptr TableScanInitLocal(ExecutionContext &context, TableFunctionInitInput &input, GlobalTableFunctionState *gstate) { auto result = make_unique(); auto &bind_data = (TableScanBindData &)*input.bind_data; @@ -115194,7 +127076,7 @@ static unique_ptr TableScanInitLocal(ClientContext &con col = storage_idx; } result->scan_state.table_filters = input.filters; - TableScanParallelStateNext(context, input.bind_data, result.get(), gstate); + TableScanParallelStateNext(context.client, input.bind_data, result.get(), gstate); return move(result); } @@ -115356,6 +127238,11 @@ void TableScanPushdownComplexFilter(ClientContext &context, LogicalGet &get, Fun auto table = bind_data.table; auto &storage = *table->storage; + auto &config = ClientConfig::GetConfig(context); + if (!config.enable_optimizer) { + // we only push index scans if the optimizer is enabled + return; + } if (bind_data.is_index_scan) { return; } @@ -115468,12 +127355,7 @@ void TableScanPushdownComplexFilter(ClientContext &context, LogicalGet &get, Fun if (index.Scan(transaction, storage, *index_state, STANDARD_VECTOR_SIZE, bind_data.result_ids)) { // use an index scan! bind_data.is_index_scan = true; - get.function.init_local = nullptr; - get.function.init_global = IndexScanInitGlobal; - get.function.function = IndexScanFunction; - get.function.table_scan_progress = nullptr; - get.function.get_batch_index = nullptr; - get.function.filter_pushdown = false; + get.function = TableScanFunction::GetIndexScanFunction(); } else { bind_data.result_ids.clear(); } @@ -115489,6 +127371,53 @@ string TableScanToString(const FunctionData *bind_data_p) { return result; } +static void TableScanSerialize(FieldWriter &writer, const FunctionData *bind_data_p, const TableFunction &function) { + auto &bind_data = (TableScanBindData &)*bind_data_p; + + D_ASSERT(bind_data.chunk_count == 0); + writer.WriteString(bind_data.table->schema->name); + writer.WriteString(bind_data.table->name); + writer.WriteField(bind_data.is_index_scan); + writer.WriteList(bind_data.result_ids); +} + +static unique_ptr TableScanDeserialize(ClientContext &context, FieldReader &reader, + TableFunction &function) { + auto schema_name = reader.ReadRequired(); + auto table_name = reader.ReadRequired(); + auto is_index_scan = reader.ReadRequired(); + auto result_ids = reader.ReadRequiredList(); + + auto &catalog = Catalog::GetCatalog(context); + auto catalog_entry = catalog.GetEntry(context, CatalogType::TABLE_ENTRY, schema_name, table_name); + if (!catalog_entry || catalog_entry->type != CatalogType::TABLE_ENTRY) { + throw SerializationException("Cant find table for %s.%s", schema_name, table_name); + } + + auto result = make_unique((TableCatalogEntry *)catalog_entry); + result->is_index_scan = is_index_scan; + result->result_ids = move(result_ids); + return move(result); +} + +TableFunction TableScanFunction::GetIndexScanFunction() { + TableFunction scan_function("index_scan", {}, IndexScanFunction); + scan_function.init_local = nullptr; + scan_function.init_global = IndexScanInitGlobal; + scan_function.statistics = TableScanStatistics; + scan_function.dependency = TableScanDependency; + scan_function.cardinality = TableScanCardinality; + scan_function.pushdown_complex_filter = nullptr; + scan_function.to_string = TableScanToString; + scan_function.table_scan_progress = nullptr; + scan_function.get_batch_index = nullptr; + scan_function.projection_pushdown = true; + scan_function.filter_pushdown = false; + scan_function.serialize = TableScanSerialize; + scan_function.deserialize = TableScanDeserialize; + return scan_function; +} + TableFunction TableScanFunction::GetFunction() { TableFunction scan_function("seq_scan", {}, TableScanFunc); scan_function.init_local = TableScanInitLocal; @@ -115502,6 +127431,8 @@ TableFunction TableScanFunction::GetFunction() { scan_function.get_batch_index = TableScanGetBatchIndex; scan_function.projection_pushdown = true; scan_function.filter_pushdown = true; + scan_function.serialize = TableScanSerialize; + scan_function.deserialize = TableScanDeserialize; return scan_function; } @@ -115513,6 +127444,18 @@ TableCatalogEntry *TableScanFunction::GetTableEntry(const TableFunction &functio return bind_data.table; } +void TableScanFunction::RegisterFunction(BuiltinFunctions &set) { + TableFunctionSet table_scan_set("seq_scan"); + table_scan_set.AddFunction(GetFunction()); + set.AddFunction(move(table_scan_set)); + + set.AddFunction(GetIndexScanFunction()); +} + +void BuiltinFunctions::RegisterTableScanFunctions() { + TableScanFunction::RegisterFunction(*this); +} + } // namespace duckdb @@ -115539,11 +127482,10 @@ struct UnnestBindData : public FunctionData { } }; -struct UnnestOperatorData : public GlobalTableFunctionState { - UnnestOperatorData() { +struct UnnestGlobalState : public GlobalTableFunctionState { + UnnestGlobalState() { } - unique_ptr operator_state; vector> select_list; idx_t MaxThreads() const override { @@ -115551,6 +127493,13 @@ struct UnnestOperatorData : public GlobalTableFunctionState { } }; +struct UnnestLocalState : public LocalTableFunctionState { + UnnestLocalState() { + } + + unique_ptr operator_state; +}; + static unique_ptr UnnestBind(ClientContext &context, TableFunctionBindInput &input, vector &return_types, vector &names) { if (input.input_table_types.size() != 1 || input.input_table_types[0].id() != LogicalTypeId::LIST) { @@ -115561,10 +127510,18 @@ static unique_ptr UnnestBind(ClientContext &context, TableFunction return make_unique(input.input_table_types[0]); } +static unique_ptr UnnestLocalInit(ExecutionContext &context, TableFunctionInitInput &input, + GlobalTableFunctionState *global_state) { + auto &gstate = (UnnestGlobalState &)*global_state; + + auto result = make_unique(); + result->operator_state = PhysicalUnnest::GetState(context, gstate.select_list); + return move(result); +} + static unique_ptr UnnestInit(ClientContext &context, TableFunctionInitInput &input) { auto &bind_data = (UnnestBindData &)*input.bind_data; - auto result = make_unique(); - result->operator_state = PhysicalUnnest::GetState(context); + auto result = make_unique(); auto ref = make_unique(bind_data.input_type, 0); auto bound_unnest = make_unique(ListType::GetChildType(bind_data.input_type)); bound_unnest->child = move(ref); @@ -115572,14 +127529,15 @@ static unique_ptr UnnestInit(ClientContext &context, T return move(result); } -static OperatorResultType UnnestFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &input, +static OperatorResultType UnnestFunction(ExecutionContext &context, TableFunctionInput &data_p, DataChunk &input, DataChunk &output) { - auto &state = (UnnestOperatorData &)*data_p.global_state; - return PhysicalUnnest::ExecuteInternal(context, input, output, *state.operator_state, state.select_list, false); + auto &state = (UnnestGlobalState &)*data_p.global_state; + auto &lstate = (UnnestLocalState &)*data_p.local_state; + return PhysicalUnnest::ExecuteInternal(context, input, output, *lstate.operator_state, state.select_list, false); } void UnnestTableFunction::RegisterFunction(BuiltinFunctions &set) { - TableFunction unnest_function("unnest", {LogicalTypeId::TABLE}, nullptr, UnnestBind, UnnestInit); + TableFunction unnest_function("unnest", {LogicalTypeId::TABLE}, nullptr, UnnestBind, UnnestInit, UnnestLocalInit); unnest_function.in_out_function = UnnestFunction; set.AddFunction(unnest_function); } @@ -115688,7 +127646,8 @@ TableFunction::TableFunction(string name, vector arguments, table_f : SimpleNamedParameterFunction(move(name), move(arguments)), bind(bind), init_global(init_global), init_local(init_local), function(function), in_out_function(nullptr), statistics(nullptr), dependency(nullptr), cardinality(nullptr), pushdown_complex_filter(nullptr), to_string(nullptr), table_scan_progress(nullptr), - get_batch_index(nullptr), projection_pushdown(false), filter_pushdown(false) { + get_batch_index(nullptr), serialize(nullptr), deserialize(nullptr), projection_pushdown(false), + filter_pushdown(false) { } TableFunction::TableFunction(const vector &arguments, table_function_t function, @@ -115696,7 +127655,11 @@ TableFunction::TableFunction(const vector &arguments, table_functio table_function_init_local_t init_local) : TableFunction(string(), arguments, function, bind, init_global, init_local) { } -TableFunction::TableFunction() : SimpleNamedParameterFunction("", {}) { +TableFunction::TableFunction() + : SimpleNamedParameterFunction("", {}), bind(nullptr), init_global(nullptr), init_local(nullptr), function(nullptr), + in_out_function(nullptr), statistics(nullptr), dependency(nullptr), cardinality(nullptr), + pushdown_complex_filter(nullptr), to_string(nullptr), table_scan_progress(nullptr), get_batch_index(nullptr), + serialize(nullptr), deserialize(nullptr), projection_pushdown(false), filter_pushdown(false) { } } // namespace duckdb @@ -115712,6 +127675,7 @@ TableFunction::TableFunction() : SimpleNamedParameterFunction("", {}) { + namespace duckdb { TableMacroFunction::TableMacroFunction(unique_ptr query_node) @@ -115728,6 +127692,10 @@ unique_ptr TableMacroFunction::Copy() { return move(result); } +string TableMacroFunction::ToSQL(const string &schema, const string &name) { + return MacroFunction::ToSQL(schema, name) + StringUtil::Format("TABLE (%s);", query_node->ToString()); +} + } // namespace duckdb @@ -115743,6 +127711,7 @@ void UDFWrapper::RegisterFunction(string name, vector args, Logical ScalarFunction scalar_function(move(name), move(args), move(ret_type), move(udf_function)); scalar_function.varargs = move(varargs); + scalar_function.null_handling = FunctionNullHandling::SPECIAL_HANDLING; CreateScalarFunctionInfo info(scalar_function); info.schema = DEFAULT_SCHEMA; context.RegisterFunction(&info); @@ -115767,12 +127736,15 @@ void UDFWrapper::RegisterAggrFunction(AggregateFunction aggr_function, ClientCon + namespace duckdb { -BaseAppender::BaseAppender() : column(0) { +BaseAppender::BaseAppender(Allocator &allocator) : allocator(allocator), column(0) { } -BaseAppender::BaseAppender(vector types_p) : types(move(types_p)), column(0) { +BaseAppender::BaseAppender(Allocator &allocator_p, vector types_p) + : allocator(allocator_p), types(move(types_p)), collection(make_unique(allocator, types)), + column(0) { InitializeChunk(); } @@ -115792,7 +127764,7 @@ void BaseAppender::Destructor() { } InternalAppender::InternalAppender(ClientContext &context_p, TableCatalogEntry &table_p) - : BaseAppender(table_p.GetTypes()), context(context_p), table(table_p) { + : BaseAppender(Allocator::DefaultAllocator(), table_p.GetTypes()), context(context_p), table(table_p) { } InternalAppender::~InternalAppender() { @@ -115800,7 +127772,7 @@ InternalAppender::~InternalAppender() { } Appender::Appender(Connection &con, const string &schema_name, const string &table_name) - : BaseAppender(), context(con.context) { + : BaseAppender(Allocator::DefaultAllocator()), context(con.context) { description = con.TableInfo(schema_name, table_name); if (!description) { // table could not be found @@ -115810,6 +127782,7 @@ Appender::Appender(Connection &con, const string &schema_name, const string &tab types.push_back(column.Type()); } InitializeChunk(); + collection = make_unique(allocator, types); } Appender::Appender(Connection &con, const string &table_name) : Appender(con, DEFAULT_SCHEMA, table_name) { @@ -115820,8 +127793,7 @@ Appender::~Appender() { } void BaseAppender::InitializeChunk() { - chunk = make_unique(); - chunk->Initialize(types); + chunk.Initialize(allocator, types); } void BaseAppender::BeginRow() { @@ -115829,19 +127801,19 @@ void BaseAppender::BeginRow() { void BaseAppender::EndRow() { // check that all rows have been appended to - if (column != chunk->ColumnCount()) { + if (column != chunk.ColumnCount()) { throw InvalidInputException("Call to EndRow before all rows have been appended to!"); } column = 0; - chunk->SetCardinality(chunk->size() + 1); - if (chunk->size() >= STANDARD_VECTOR_SIZE) { + chunk.SetCardinality(chunk.size() + 1); + if (chunk.size() >= STANDARD_VECTOR_SIZE) { FlushChunk(); } } template void BaseAppender::AppendValueInternal(Vector &col, SRC input) { - FlatVector::GetData(col)[chunk->size()] = Cast::Operation(input); + FlatVector::GetData(col)[chunk.size()] = Cast::Operation(input); } template @@ -115849,7 +127821,7 @@ void BaseAppender::AppendValueInternal(T input) { if (column >= types.size()) { throw InvalidInputException("Too many appends for chunk!"); } - auto &col = chunk->data[column]; + auto &col = chunk.data[column]; switch (col.GetType().id()) { case LogicalTypeId::BOOLEAN: AppendValueInternal(col, input); @@ -115918,7 +127890,7 @@ void BaseAppender::AppendValueInternal(T input) { AppendValueInternal(col, input); break; case LogicalTypeId::VARCHAR: - FlatVector::GetData(col)[chunk->size()] = StringCast::Operation(input, col); + FlatVector::GetData(col)[chunk.size()] = StringCast::Operation(input, col); break; default: AppendValue(Value::CreateValue(input)); @@ -116023,7 +127995,7 @@ void BaseAppender::Append(interval_t value) { template <> void BaseAppender::Append(Value value) { // NOLINT: template shtuff - if (column >= chunk->ColumnCount()) { + if (column >= chunk.ColumnCount()) { throw InvalidInputException("Too many appends for chunk!"); } AppendValue(value); @@ -116031,15 +128003,15 @@ void BaseAppender::Append(Value value) { // NOLINT: template shtuff template <> void BaseAppender::Append(std::nullptr_t value) { - if (column >= chunk->ColumnCount()) { + if (column >= chunk.ColumnCount()) { throw InvalidInputException("Too many appends for chunk!"); } - auto &col = chunk->data[column++]; - FlatVector::SetNull(col, chunk->size(), true); + auto &col = chunk.data[column++]; + FlatVector::SetNull(col, chunk.size(), true); } void BaseAppender::AppendValue(const Value &value) { - chunk->SetValue(column, chunk->size(), value); + chunk.SetValue(column, chunk.size(), value); column++; } @@ -116047,19 +128019,19 @@ void BaseAppender::AppendDataChunk(DataChunk &chunk) { if (chunk.GetTypes() != types) { throw InvalidInputException("Type mismatch in Append DataChunk and the types required for appender"); } - collection.Append(chunk); - if (collection.ChunkCount() >= FLUSH_COUNT) { + collection->Append(chunk); + if (collection->Count() >= FLUSH_COUNT) { Flush(); } } void BaseAppender::FlushChunk() { - if (chunk->size() == 0) { + if (chunk.size() == 0) { return; } - collection.Append(move(chunk)); - InitializeChunk(); - if (collection.ChunkCount() >= FLUSH_COUNT) { + collection->Append(chunk); + chunk.Reset(); + if (collection->Count() >= FLUSH_COUNT) { Flush(); } } @@ -116071,22 +128043,22 @@ void BaseAppender::Flush() { } FlushChunk(); - if (collection.Count() == 0) { + if (collection->Count() == 0) { return; } - FlushInternal(collection); + FlushInternal(*collection); - collection.Reset(); + collection->Reset(); column = 0; } -void Appender::FlushInternal(ChunkCollection &collection) { +void Appender::FlushInternal(ColumnDataCollection &collection) { context->Append(*description, collection); } -void InternalAppender::FlushInternal(ChunkCollection &collection) { +void InternalAppender::FlushInternal(ColumnDataCollection &collection) { for (auto &chunk : collection.Chunks()) { - table.storage->Append(table, context, *chunk); + table.storage->Append(table, context, chunk); } } @@ -116132,6 +128104,10 @@ struct PreparedStatementWrapper { vector values; }; +struct PendingStatementWrapper { + unique_ptr statement; +}; + struct ArrowResultWrapper { unique_ptr result; unique_ptr current_chunk; @@ -116261,6 +128237,9 @@ duckdb_state duckdb_append_internal(duckdb_appender appender, T value) { auto *appender_instance = (AppenderWrapper *)appender; try { appender_instance->appender->Append(value); + } catch (std::exception &ex) { + appender_instance->error = ex.what(); + return DuckDBError; } catch (...) { return DuckDBError; } @@ -116350,7 +128329,8 @@ duckdb_state duckdb_append_varchar_length(duckdb_appender appender, const char * return duckdb_append_internal(appender, string_t(val, length)); } duckdb_state duckdb_append_blob(duckdb_appender appender, const void *data, idx_t length) { - return duckdb_append_internal(appender, string_t((const char *)data, length)); + auto value = duckdb::Value::BLOB((duckdb::const_data_ptr_t)data, length); + return duckdb_append_internal(appender, value); } duckdb_state duckdb_appender_flush(duckdb_appender appender) { @@ -116370,6 +128350,8 @@ duckdb_state duckdb_append_data_chunk(duckdb_appender appender, duckdb_data_chun } + +using duckdb::ArrowConverter; using duckdb::ArrowResultWrapper; using duckdb::Connection; using duckdb::DataChunk; @@ -116384,7 +128366,7 @@ duckdb_state duckdb_query_arrow(duckdb_connection connection, const char *query, auto wrapper = new ArrowResultWrapper(); wrapper->result = conn->Query(query); *out_result = (duckdb_arrow)wrapper; - return wrapper->result->success ? DuckDBSuccess : DuckDBError; + return !wrapper->result->HasError() ? DuckDBSuccess : DuckDBError; } duckdb_state duckdb_query_arrow_schema(duckdb_arrow result, duckdb_arrow_schema *out_schema) { @@ -116392,8 +128374,8 @@ duckdb_state duckdb_query_arrow_schema(duckdb_arrow result, duckdb_arrow_schema return DuckDBSuccess; } auto wrapper = (ArrowResultWrapper *)result; - QueryResult::ToArrowSchema((ArrowSchema *)*out_schema, wrapper->result->types, wrapper->result->names, - wrapper->timezone_config); + ArrowConverter::ToArrowSchema((ArrowSchema *)*out_schema, wrapper->result->types, wrapper->result->names, + wrapper->timezone_config); return DuckDBSuccess; } @@ -116402,43 +128384,50 @@ duckdb_state duckdb_query_arrow_array(duckdb_arrow result, duckdb_arrow_array *o return DuckDBSuccess; } auto wrapper = (ArrowResultWrapper *)result; - auto success = wrapper->result->TryFetch(wrapper->current_chunk, wrapper->result->error); + auto success = wrapper->result->TryFetch(wrapper->current_chunk, wrapper->result->GetErrorObject()); if (!success) { // LCOV_EXCL_START return DuckDBError; } // LCOV_EXCL_STOP if (!wrapper->current_chunk || wrapper->current_chunk->size() == 0) { return DuckDBSuccess; } - wrapper->current_chunk->ToArrowArray((ArrowArray *)*out_array); + ArrowConverter::ToArrowArray(*wrapper->current_chunk, (ArrowArray *)*out_array); return DuckDBSuccess; } idx_t duckdb_arrow_row_count(duckdb_arrow result) { auto wrapper = (ArrowResultWrapper *)result; - return wrapper->result->collection.Count(); + if (wrapper->result->HasError()) { + return 0; + } + return wrapper->result->RowCount(); } idx_t duckdb_arrow_column_count(duckdb_arrow result) { auto wrapper = (ArrowResultWrapper *)result; - return wrapper->result->types.size(); + return wrapper->result->ColumnCount(); } idx_t duckdb_arrow_rows_changed(duckdb_arrow result) { auto wrapper = (ArrowResultWrapper *)result; + if (wrapper->result->HasError()) { + return 0; + } idx_t rows_changed = 0; - idx_t row_count = wrapper->result->collection.Count(); + auto &collection = wrapper->result->Collection(); + idx_t row_count = collection.Count(); if (row_count > 0 && wrapper->result->properties.return_type == duckdb::StatementReturnType::CHANGED_ROWS) { - auto row_changes = wrapper->result->GetValue(0, 0); - if (!row_changes.IsNull() && row_changes.TryCastAs(LogicalType::BIGINT)) { - rows_changed = row_changes.GetValue(); - } + auto rows = collection.GetRows(); + D_ASSERT(row_count == 1); + D_ASSERT(rows.size() == 1); + rows_changed = rows[0].GetValue(0).GetValue(); } return rows_changed; } const char *duckdb_query_arrow_error(duckdb_arrow result) { auto wrapper = (ArrowResultWrapper *)result; - return wrapper->result->error.c_str(); + return wrapper->result->GetError().c_str(); } void duckdb_destroy_arrow(duckdb_arrow *result) { @@ -116451,7 +128440,7 @@ void duckdb_destroy_arrow(duckdb_arrow *result) { duckdb_state duckdb_execute_prepared_arrow(duckdb_prepared_statement prepared_statement, duckdb_arrow *out_result) { auto wrapper = (PreparedStatementWrapper *)prepared_statement; - if (!wrapper || !wrapper->statement || !wrapper->statement->success || !out_result) { + if (!wrapper || !wrapper->statement || wrapper->statement->HasError() || !out_result) { return DuckDBError; } auto arrow_wrapper = new ArrowResultWrapper(); @@ -116467,7 +128456,7 @@ duckdb_state duckdb_execute_prepared_arrow(duckdb_prepared_statement prepared_st D_ASSERT(result->type == QueryResultType::MATERIALIZED_RESULT); arrow_wrapper->result = duckdb::unique_ptr_cast(move(result)); *out_result = (duckdb_arrow)arrow_wrapper; - return arrow_wrapper->result->success ? DuckDBSuccess : DuckDBError; + return !arrow_wrapper->result->HasError() ? DuckDBSuccess : DuckDBError; } @@ -116552,7 +128541,7 @@ duckdb_data_chunk duckdb_create_data_chunk(duckdb_logical_type *ctypes, idx_t co } auto result = new duckdb::DataChunk(); - result->Initialize(types); + result->Initialize(duckdb::Allocator::DefaultAllocator(), types); return result; } @@ -117317,6 +129306,102 @@ duckdb_logical_type duckdb_struct_type_child_type(duckdb_logical_type type, idx_ + +using duckdb::make_unique; +using duckdb::PendingExecutionResult; +using duckdb::PendingQueryResult; +using duckdb::PendingStatementWrapper; +using duckdb::PreparedStatementWrapper; + +duckdb_state duckdb_pending_prepared(duckdb_prepared_statement prepared_statement, duckdb_pending_result *out_result) { + if (!prepared_statement || !out_result) { + return DuckDBError; + } + auto wrapper = (PreparedStatementWrapper *)prepared_statement; + auto result = new PendingStatementWrapper(); + try { + result->statement = wrapper->statement->PendingQuery(wrapper->values, false); + } catch (const duckdb::Exception &ex) { + result->statement = make_unique(duckdb::PreservedError(ex)); + } catch (std::exception &ex) { + result->statement = make_unique(duckdb::PreservedError(ex)); + } + duckdb_state return_value = !result->statement->HasError() ? DuckDBSuccess : DuckDBError; + *out_result = (duckdb_pending_result)result; + + return return_value; +} + +void duckdb_destroy_pending(duckdb_pending_result *pending_result) { + if (!pending_result || !*pending_result) { + return; + } + auto wrapper = (PendingStatementWrapper *)*pending_result; + if (wrapper->statement) { + wrapper->statement->Close(); + } + delete wrapper; + *pending_result = nullptr; +} + +const char *duckdb_pending_error(duckdb_pending_result pending_result) { + if (!pending_result) { + return nullptr; + } + auto wrapper = (PendingStatementWrapper *)pending_result; + if (!wrapper->statement) { + return nullptr; + } + return wrapper->statement->GetError().c_str(); +} + +duckdb_pending_state duckdb_pending_execute_task(duckdb_pending_result pending_result) { + if (!pending_result) { + return DUCKDB_PENDING_ERROR; + } + auto wrapper = (PendingStatementWrapper *)pending_result; + if (!wrapper->statement) { + return DUCKDB_PENDING_ERROR; + } + if (wrapper->statement->HasError()) { + return DUCKDB_PENDING_ERROR; + } + PendingExecutionResult return_value; + try { + return_value = wrapper->statement->ExecuteTask(); + } catch (const duckdb::Exception &ex) { + wrapper->statement->SetError(duckdb::PreservedError(ex)); + return DUCKDB_PENDING_ERROR; + } catch (std::exception &ex) { + wrapper->statement->SetError(duckdb::PreservedError(ex)); + return DUCKDB_PENDING_ERROR; + } + switch (return_value) { + case PendingExecutionResult::RESULT_READY: + return DUCKDB_PENDING_RESULT_READY; + case PendingExecutionResult::RESULT_NOT_READY: + return DUCKDB_PENDING_RESULT_NOT_READY; + default: + return DUCKDB_PENDING_ERROR; + } +} + +duckdb_state duckdb_execute_pending(duckdb_pending_result pending_result, duckdb_result *out_result) { + if (!pending_result || !out_result) { + return DuckDBError; + } + auto wrapper = (PendingStatementWrapper *)pending_result; + if (!wrapper->statement) { + return DuckDBError; + } + auto result = wrapper->statement->Execute(); + wrapper->statement.reset(); + return duckdb_translate_result(move(result), out_result); +} + + + + using duckdb::Connection; using duckdb::date_t; using duckdb::dtime_t; @@ -117336,20 +129421,20 @@ duckdb_state duckdb_prepare(duckdb_connection connection, const char *query, Connection *conn = (Connection *)connection; wrapper->statement = conn->Prepare(query); *out_prepared_statement = (duckdb_prepared_statement)wrapper; - return wrapper->statement->success ? DuckDBSuccess : DuckDBError; + return !wrapper->statement->HasError() ? DuckDBSuccess : DuckDBError; } const char *duckdb_prepare_error(duckdb_prepared_statement prepared_statement) { auto wrapper = (PreparedStatementWrapper *)prepared_statement; - if (!wrapper || !wrapper->statement || wrapper->statement->success) { + if (!wrapper || !wrapper->statement || !wrapper->statement->HasError()) { return nullptr; } - return wrapper->statement->error.c_str(); + return wrapper->statement->error.Message().c_str(); } idx_t duckdb_nparams(duckdb_prepared_statement prepared_statement) { auto wrapper = (PreparedStatementWrapper *)prepared_statement; - if (!wrapper || !wrapper->statement || !wrapper->statement->success) { + if (!wrapper || !wrapper->statement || wrapper->statement->HasError()) { return 0; } return wrapper->statement->n_param; @@ -117357,19 +129442,28 @@ idx_t duckdb_nparams(duckdb_prepared_statement prepared_statement) { duckdb_type duckdb_param_type(duckdb_prepared_statement prepared_statement, idx_t param_idx) { auto wrapper = (PreparedStatementWrapper *)prepared_statement; - if (!wrapper || !wrapper->statement || !wrapper->statement->success) { + if (!wrapper || !wrapper->statement || wrapper->statement->HasError()) { return DUCKDB_TYPE_INVALID; } auto entry = wrapper->statement->data->value_map.find(param_idx); if (entry == wrapper->statement->data->value_map.end()) { return DUCKDB_TYPE_INVALID; } - return ConvertCPPTypeToC(entry->second[0]->type()); + return ConvertCPPTypeToC(entry->second->return_type); +} + +duckdb_state duckdb_clear_bindings(duckdb_prepared_statement prepared_statement) { + auto wrapper = (PreparedStatementWrapper *)prepared_statement; + if (!wrapper || !wrapper->statement || wrapper->statement->HasError()) { + return DuckDBError; + } + wrapper->values.clear(); + return DuckDBSuccess; } static duckdb_state duckdb_bind_value(duckdb_prepared_statement prepared_statement, idx_t param_idx, Value val) { auto wrapper = (PreparedStatementWrapper *)prepared_statement; - if (!wrapper || !wrapper->statement || !wrapper->statement->success) { + if (!wrapper || !wrapper->statement || wrapper->statement->HasError()) { return DuckDBError; } if (param_idx <= 0 || param_idx > wrapper->statement->n_param) { @@ -117478,7 +129572,7 @@ duckdb_state duckdb_bind_null(duckdb_prepared_statement prepared_statement, idx_ duckdb_state duckdb_execute_prepared(duckdb_prepared_statement prepared_statement, duckdb_result *out_result) { auto wrapper = (PreparedStatementWrapper *)prepared_statement; - if (!wrapper || !wrapper->statement || !wrapper->statement->success) { + if (!wrapper || !wrapper->statement || wrapper->statement->HasError()) { return DuckDBError; } auto result = wrapper->statement->Execute(wrapper->values, false); @@ -117580,237 +129674,239 @@ void duckdb_replacement_scan_add_parameter(duckdb_replacement_scan_info info_p, + namespace duckdb { +struct CBaseConverter { + template + static void NullConvert(DST &target) { + } +}; +struct CStandardConverter : public CBaseConverter { + template + static DST Convert(SRC input) { + return input; + } +}; + +struct CStringConverter { + template + static DST Convert(SRC input) { + auto result = (char *)duckdb_malloc(input.GetSize() + 1); + assert(result); + memcpy((void *)result, input.GetDataUnsafe(), input.GetSize()); + auto write_arr = (char *)result; + write_arr[input.GetSize()] = '\0'; + return result; + } + + template + static void NullConvert(DST &target) { + target = nullptr; + } +}; + +struct CBlobConverter { + template + static DST Convert(SRC input) { + duckdb_blob result; + result.data = (char *)duckdb_malloc(input.GetSize()); + result.size = input.GetSize(); + assert(result.data); + memcpy((void *)result.data, input.GetDataUnsafe(), input.GetSize()); + return result; + } + + template + static void NullConvert(DST &target) { + target.data = nullptr; + target.size = 0; + } +}; + +struct CTimestampMsConverter : public CBaseConverter { + template + static DST Convert(SRC input) { + return Timestamp::FromEpochMs(input.value); + } +}; + +struct CTimestampNsConverter : public CBaseConverter { + template + static DST Convert(SRC input) { + return Timestamp::FromEpochNanoSeconds(input.value); + } +}; + +struct CTimestampSecConverter : public CBaseConverter { + template + static DST Convert(SRC input) { + return Timestamp::FromEpochSeconds(input.value); + } +}; + +struct CHugeintConverter : public CBaseConverter { + template + static DST Convert(SRC input) { + duckdb_hugeint result; + result.lower = input.lower; + result.upper = input.upper; + return result; + } +}; + +struct CIntervalConverter : public CBaseConverter { + template + static DST Convert(SRC input) { + duckdb_interval result; + result.days = input.days; + result.months = input.months; + result.micros = input.micros; + return result; + } +}; + template -void WriteData(duckdb_column *column, ChunkCollection &source, idx_t col) { +struct CDecimalConverter : public CBaseConverter { + template + static DST Convert(SRC input) { + duckdb_hugeint result; + result.lower = input; + result.upper = 0; + return result; + } +}; + +template +void WriteData(duckdb_column *column, ColumnDataCollection &source, const vector &column_ids) { idx_t row = 0; - auto target = (T *)column->__deprecated_data; - for (auto &chunk : source.Chunks()) { - auto source = FlatVector::GetData(chunk->data[col]); - auto &mask = FlatVector::Validity(chunk->data[col]); + auto target = (DST *)column->__deprecated_data; + for (auto &input : source.Chunks(column_ids)) { + auto source = FlatVector::GetData(input.data[0]); + auto &mask = FlatVector::Validity(input.data[0]); - for (idx_t k = 0; k < chunk->size(); k++, row++) { + for (idx_t k = 0; k < input.size(); k++, row++) { if (!mask.RowIsValid(k)) { - continue; + OP::template NullConvert(target[row]); + } else { + target[row] = OP::template Convert(source[k]); } - target[row] = source[k]; } } } duckdb_state deprecated_duckdb_translate_column(MaterializedQueryResult &result, duckdb_column *column, idx_t col) { - idx_t row_count = result.collection.Count(); - column->__deprecated_nullmask = (bool *)duckdb_malloc(sizeof(bool) * result.collection.Count()); + D_ASSERT(!result.HasError()); + auto &collection = result.Collection(); + idx_t row_count = collection.Count(); + column->__deprecated_nullmask = (bool *)duckdb_malloc(sizeof(bool) * collection.Count()); column->__deprecated_data = duckdb_malloc(GetCTypeSize(column->__deprecated_type) * row_count); if (!column->__deprecated_nullmask || !column->__deprecated_data) { // LCOV_EXCL_START // malloc failure return DuckDBError; } // LCOV_EXCL_STOP + vector column_ids {col}; // first convert the nullmask - idx_t row = 0; - for (auto &chunk : result.collection.Chunks()) { - for (idx_t k = 0; k < chunk->size(); k++) { - column->__deprecated_nullmask[row++] = FlatVector::IsNull(chunk->data[col], k); + { + idx_t row = 0; + for (auto &input : collection.Chunks(column_ids)) { + for (idx_t k = 0; k < input.size(); k++) { + column->__deprecated_nullmask[row++] = FlatVector::IsNull(input.data[0], k); + } } } // then write the data switch (result.types[col].id()) { case LogicalTypeId::BOOLEAN: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::TINYINT: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::SMALLINT: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::INTEGER: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::BIGINT: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::UTINYINT: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::USMALLINT: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::UINTEGER: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::UBIGINT: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::FLOAT: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::DOUBLE: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::DATE: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::TIME: case LogicalTypeId::TIME_TZ: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::TIMESTAMP: case LogicalTypeId::TIMESTAMP_TZ: - WriteData(column, result.collection, col); + WriteData(column, collection, column_ids); break; case LogicalTypeId::VARCHAR: { - idx_t row = 0; - auto target = (const char **)column->__deprecated_data; - for (auto &chunk : result.collection.Chunks()) { - auto source = FlatVector::GetData(chunk->data[col]); - for (idx_t k = 0; k < chunk->size(); k++) { - if (!FlatVector::IsNull(chunk->data[col], k)) { - target[row] = (char *)duckdb_malloc(source[k].GetSize() + 1); - assert(target[row]); - memcpy((void *)target[row], source[k].GetDataUnsafe(), source[k].GetSize()); - auto write_arr = (char *)target[row]; - write_arr[source[k].GetSize()] = '\0'; - } else { - target[row] = nullptr; - } - row++; - } - } + WriteData(column, collection, column_ids); break; } case LogicalTypeId::BLOB: { - idx_t row = 0; - auto target = (duckdb_blob *)column->__deprecated_data; - for (auto &chunk : result.collection.Chunks()) { - auto source = FlatVector::GetData(chunk->data[col]); - for (idx_t k = 0; k < chunk->size(); k++) { - if (!FlatVector::IsNull(chunk->data[col], k)) { - target[row].data = (char *)duckdb_malloc(source[k].GetSize()); - target[row].size = source[k].GetSize(); - assert(target[row].data); - memcpy((void *)target[row].data, source[k].GetDataUnsafe(), source[k].GetSize()); - } else { - target[row].data = nullptr; - target[row].size = 0; - } - row++; - } - } + WriteData(column, collection, column_ids); + break; + } + case LogicalTypeId::TIMESTAMP_NS: { + WriteData(column, collection, column_ids); + break; + } + case LogicalTypeId::TIMESTAMP_MS: { + WriteData(column, collection, column_ids); break; } - case LogicalTypeId::TIMESTAMP_NS: - case LogicalTypeId::TIMESTAMP_MS: case LogicalTypeId::TIMESTAMP_SEC: { - idx_t row = 0; - auto target = (timestamp_t *)column->__deprecated_data; - for (auto &chunk : result.collection.Chunks()) { - auto source = FlatVector::GetData(chunk->data[col]); - - for (idx_t k = 0; k < chunk->size(); k++) { - if (!FlatVector::IsNull(chunk->data[col], k)) { - if (result.types[col].id() == LogicalTypeId::TIMESTAMP_NS) { - target[row] = Timestamp::FromEpochNanoSeconds(source[k].value); - } else if (result.types[col].id() == LogicalTypeId::TIMESTAMP_MS) { - target[row] = Timestamp::FromEpochMs(source[k].value); - } else { - D_ASSERT(result.types[col].id() == LogicalTypeId::TIMESTAMP_SEC); - target[row] = Timestamp::FromEpochSeconds(source[k].value); - } - } - row++; - } - } + WriteData(column, collection, column_ids); break; } case LogicalTypeId::HUGEINT: { - idx_t row = 0; - auto target = (duckdb_hugeint *)column->__deprecated_data; - for (auto &chunk : result.collection.Chunks()) { - auto source = FlatVector::GetData(chunk->data[col]); - for (idx_t k = 0; k < chunk->size(); k++) { - if (!FlatVector::IsNull(chunk->data[col], k)) { - target[row].lower = source[k].lower; - target[row].upper = source[k].upper; - } - row++; - } - } + WriteData(column, collection, column_ids); break; } case LogicalTypeId::INTERVAL: { - idx_t row = 0; - auto target = (duckdb_interval *)column->__deprecated_data; - for (auto &chunk : result.collection.Chunks()) { - auto source = FlatVector::GetData(chunk->data[col]); - for (idx_t k = 0; k < chunk->size(); k++) { - if (!FlatVector::IsNull(chunk->data[col], k)) { - target[row].days = source[k].days; - target[row].months = source[k].months; - target[row].micros = source[k].micros; - } - row++; - } - } + WriteData(column, collection, column_ids); break; } case LogicalTypeId::DECIMAL: { // get data - idx_t row = 0; - auto target = (hugeint_t *)column->__deprecated_data; switch (result.types[col].InternalType()) { case PhysicalType::INT16: { - for (auto &chunk : result.collection.Chunks()) { - auto source = FlatVector::GetData(chunk->data[col]); - for (idx_t k = 0; k < chunk->size(); k++) { - if (!FlatVector::IsNull(chunk->data[col], k)) { - target[row].lower = source[k]; - target[row].upper = 0; - } - row++; - } - } + WriteData>(column, collection, column_ids); break; } case PhysicalType::INT32: { - for (auto &chunk : result.collection.Chunks()) { - auto source = FlatVector::GetData(chunk->data[col]); - for (idx_t k = 0; k < chunk->size(); k++) { - if (!FlatVector::IsNull(chunk->data[col], k)) { - target[row].lower = source[k]; - target[row].upper = 0; - } - row++; - } - } + WriteData>(column, collection, column_ids); break; } case PhysicalType::INT64: { - for (auto &chunk : result.collection.Chunks()) { - auto source = FlatVector::GetData(chunk->data[col]); - for (idx_t k = 0; k < chunk->size(); k++) { - if (!FlatVector::IsNull(chunk->data[col], k)) { - target[row].lower = source[k]; - target[row].upper = 0; - } - row++; - } - } + WriteData>(column, collection, column_ids); break; } case PhysicalType::INT128: { - for (auto &chunk : result.collection.Chunks()) { - auto source = FlatVector::GetData(chunk->data[col]); - for (idx_t k = 0; k < chunk->size(); k++) { - if (!FlatVector::IsNull(chunk->data[col], k)) { - target[row].lower = source[k].lower; - target[row].upper = source[k].upper; - } - row++; - } - } + WriteData(column, collection, column_ids); break; } default: @@ -117830,7 +129926,7 @@ duckdb_state duckdb_translate_result(unique_ptr result_p, duckdb_re D_ASSERT(result_p); if (!out) { // no result to write to, only return the status - return result.success ? DuckDBSuccess : DuckDBError; + return !result.HasError() ? DuckDBSuccess : DuckDBError; } memset(out, 0, sizeof(duckdb_result)); @@ -117841,9 +129937,9 @@ duckdb_state duckdb_translate_result(unique_ptr result_p, duckdb_re result_data->result_set_type = CAPIResultSetType::CAPI_RESULT_TYPE_NONE; out->internal_data = result_data; - if (!result.success) { + if (result.HasError()) { // write the error message - out->__deprecated_error_message = (char *)result.error.c_str(); + out->__deprecated_error_message = (char *)result.GetError().c_str(); return DuckDBError; } // copy the data @@ -117858,7 +129954,7 @@ bool deprecated_materialize_result(duckdb_result *result) { return false; } auto result_data = (duckdb::DuckDBResultData *)result->internal_data; - if (!result_data->result->success) { + if (result_data->result->HasError()) { return false; } if (result_data->result_set_type == CAPIResultSetType::CAPI_RESULT_TYPE_DEPRECATED) { @@ -117892,7 +129988,7 @@ bool deprecated_materialize_result(duckdb_result *result) { result->__deprecated_columns[i].__deprecated_type = ConvertCPPTypeToC(result_data->result->types[i]); result->__deprecated_columns[i].__deprecated_name = (char *)result_data->result->names[i].c_str(); } - result->__deprecated_row_count = materialized.collection.Count(); + result->__deprecated_row_count = materialized.RowCount(); if (result->__deprecated_row_count > 0 && materialized.properties.return_type == StatementReturnType::CHANGED_ROWS) { // update total changes @@ -117991,7 +130087,7 @@ idx_t duckdb_row_count(duckdb_result *result) { } auto &result_data = *((duckdb::DuckDBResultData *)result->internal_data); auto &materialized = (duckdb::MaterializedQueryResult &)*result_data.result; - return materialized.collection.Count(); + return materialized.RowCount(); } idx_t duckdb_rows_changed(duckdb_result *result) { @@ -118029,7 +130125,7 @@ const char *duckdb_result_error(duckdb_result *result) { return nullptr; } auto &result_data = *((duckdb::DuckDBResultData *)result->internal_data); - return result_data.result->success ? nullptr : result_data.result->error.c_str(); + return !result_data.result->HasError() ? nullptr : result_data.result->GetError().c_str(); } idx_t duckdb_result_chunk_count(duckdb_result result) { @@ -118042,7 +130138,7 @@ idx_t duckdb_result_chunk_count(duckdb_result result) { } D_ASSERT(result_data.result->type == duckdb::QueryResultType::MATERIALIZED_RESULT); auto &materialized = (duckdb::MaterializedQueryResult &)*result_data.result; - return materialized.collection.ChunkCount(); + return materialized.Collection().ChunkCount(); } duckdb_data_chunk duckdb_result_get_chunk(duckdb_result result, idx_t chunk_idx) { @@ -118055,12 +130151,13 @@ duckdb_data_chunk duckdb_result_get_chunk(duckdb_result result, idx_t chunk_idx) } result_data.result_set_type = duckdb::CAPIResultSetType::CAPI_RESULT_TYPE_MATERIALIZED; auto &materialized = (duckdb::MaterializedQueryResult &)*result_data.result; - if (chunk_idx >= materialized.collection.ChunkCount()) { + auto &collection = materialized.Collection(); + if (chunk_idx >= collection.ChunkCount()) { return nullptr; } auto chunk = duckdb::make_unique(); - chunk->InitializeEmpty(materialized.collection.Types()); - chunk->Reference(*materialized.collection.Chunks()[chunk_idx]); + chunk->Initialize(duckdb::Allocator::DefaultAllocator(), collection.Types()); + collection.FetchChunk(chunk_idx, *chunk); return chunk.release(); } @@ -118069,6 +130166,7 @@ duckdb_data_chunk duckdb_result_get_chunk(duckdb_result result, idx_t chunk_idx) + namespace duckdb { struct CTableFunctionInfo : public TableFunctionInfo { @@ -118100,6 +130198,7 @@ struct CTableBindData : public TableFunctionData { CTableFunctionInfo *info = nullptr; void *bind_data = nullptr; duckdb_delete_callback_t delete_callback = nullptr; + unique_ptr stats; }; struct CTableInternalBindInfo { @@ -118198,7 +130297,7 @@ unique_ptr CTableFunctionInit(ClientContext &context, return move(result); } -unique_ptr CTableFunctionLocalInit(ClientContext &context, TableFunctionInitInput &data_p, +unique_ptr CTableFunctionLocalInit(ExecutionContext &context, TableFunctionInitInput &data_p, GlobalTableFunctionState *gstate) { auto &bind_data = (CTableBindData &)*data_p.bind_data; auto result = make_unique(); @@ -118214,6 +130313,14 @@ unique_ptr CTableFunctionLocalInit(ClientContext &conte return move(result); } +unique_ptr CTableFunctionCardinality(ClientContext &context, const FunctionData *bind_data_p) { + auto &bind_data = (const CTableBindData &)*bind_data_p; + if (!bind_data.stats) { + return nullptr; + } + return make_unique(*bind_data.stats); +} + void CTableFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { auto &bind_data = (CTableBindData &)*data_p.bind_data; auto &global_data = (CTableGlobalInitData &)*data_p.global_state; @@ -118234,6 +130341,7 @@ duckdb_table_function duckdb_create_table_function() { auto function = new duckdb::TableFunction("", {}, duckdb::CTableFunction, duckdb::CTableFunctionBind, duckdb::CTableFunctionInit, duckdb::CTableFunctionLocalInit); function->function_info = duckdb::make_shared(); + function->cardinality = duckdb::CTableFunctionCardinality; return function; } @@ -118382,6 +130490,18 @@ void duckdb_bind_set_bind_data(duckdb_bind_info info, void *bind_data, duckdb_de bind_info->bind_data.delete_callback = destroy; } +void duckdb_bind_set_cardinality(duckdb_bind_info info, idx_t cardinality, bool is_exact) { + if (!info) { + return; + } + auto bind_info = (duckdb::CTableInternalBindInfo *)info; + if (is_exact) { + bind_info->bind_data.stats = duckdb::make_unique(cardinality); + } else { + bind_info->bind_data.stats = duckdb::make_unique(cardinality, cardinality); + } +} + void duckdb_bind_set_error(duckdb_bind_info info, const char *error) { if (!info || !error) { return; @@ -118503,6 +130623,16 @@ void duckdb_function_set_error(duckdb_function_info info, const char *error) { using duckdb::DatabaseData; +struct CAPITaskState { + CAPITaskState(duckdb::DatabaseInstance &db) + : db(db), marker(duckdb::make_unique>(true)), execute_count(0) { + } + + duckdb::DatabaseInstance &db; + duckdb::unique_ptr> marker; + duckdb::atomic execute_count; +}; + void duckdb_execute_tasks(duckdb_database database, idx_t max_tasks) { if (!database) { return; @@ -118512,6 +130642,63 @@ void duckdb_execute_tasks(duckdb_database database, idx_t max_tasks) { scheduler.ExecuteTasks(max_tasks); } +duckdb_task_state duckdb_create_task_state(duckdb_database database) { + if (!database) { + return nullptr; + } + auto wrapper = (DatabaseData *)database; + auto state = new CAPITaskState(*wrapper->database->instance); + return state; +} + +void duckdb_execute_tasks_state(duckdb_task_state state_p) { + if (!state_p) { + return; + } + auto state = (CAPITaskState *)state_p; + auto &scheduler = duckdb::TaskScheduler::GetScheduler(state->db); + state->execute_count++; + scheduler.ExecuteForever(state->marker.get()); +} + +idx_t duckdb_execute_n_tasks_state(duckdb_task_state state_p, idx_t max_tasks) { + if (!state_p) { + return 0; + } + auto state = (CAPITaskState *)state_p; + auto &scheduler = duckdb::TaskScheduler::GetScheduler(state->db); + return scheduler.ExecuteTasks(state->marker.get(), max_tasks); +} + +void duckdb_finish_execution(duckdb_task_state state_p) { + if (!state_p) { + return; + } + auto state = (CAPITaskState *)state_p; + *state->marker = false; + if (state->execute_count > 0) { + // signal to the threads to wake up + auto &scheduler = duckdb::TaskScheduler::GetScheduler(state->db); + scheduler.Signal(state->execute_count); + } +} + +bool duckdb_task_state_is_finished(duckdb_task_state state_p) { + if (!state_p) { + return false; + } + auto state = (CAPITaskState *)state_p; + return !(*state->marker); +} + +void duckdb_destroy_task_state(duckdb_task_state state_p) { + if (!state_p) { + return; + } + auto state = (CAPITaskState *)state_p; + delete state; +} + @@ -118911,6 +131098,7 @@ class ClientContextFileOpener : public FileOpener { + //===----------------------------------------------------------------------===// // DuckDB // @@ -119069,6 +131257,45 @@ class Optimizer { +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/expression/parameter_expression.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { +class ParameterExpression : public ParsedExpression { +public: + ParameterExpression(); + + idx_t parameter_nr; + +public: + bool IsScalar() const override { + return true; + } + bool HasParameter() const override { + return true; + } + + string ToString() const override; + + static bool Equals(const ParameterExpression *a, const ParameterExpression *b); + + unique_ptr Copy() const override; + hash_t Hash() const override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionType type, FieldReader &source); +}; +} // namespace duckdb + //===----------------------------------------------------------------------===// // DuckDB @@ -119117,6 +131344,7 @@ class DropStatement : public SQLStatement { + namespace duckdb { class ClientContext; class PreparedStatementData; @@ -119124,27 +131352,30 @@ class PreparedStatementData; //! The planner creates a logical query plan from the parsed SQL statements //! using the Binder and LogicalPlanGenerator. class Planner { + friend class Binder; + public: explicit Planner(ClientContext &context); - void CreatePlan(unique_ptr statement); - unique_ptr plan; vector names; vector types; - unordered_map>> value_map; - vector parameter_types; + bound_parameter_map_t value_map; + vector parameter_data; shared_ptr binder; ClientContext &context; StatementProperties properties; +public: + void CreatePlan(unique_ptr statement); + static void VerifyPlan(ClientContext &context, unique_ptr &op, + bound_parameter_map_t *map = nullptr); + private: void CreatePlan(SQLStatement &statement); shared_ptr PrepareSQLStatement(unique_ptr statement); - void PlanPrepare(unique_ptr statement); - void PlanExecute(unique_ptr statement); }; } // namespace duckdb @@ -119258,6 +131489,70 @@ class PragmaHandler { +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/statement/prepare_statement.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +class PrepareStatement : public SQLStatement { +public: + PrepareStatement(); + + unique_ptr statement; + string name; + +protected: + PrepareStatement(const PrepareStatement &other); + +public: + unique_ptr Copy() const override; +}; +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/statement/execute_statement.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + +namespace duckdb { + +class ExecuteStatement : public SQLStatement { +public: + ExecuteStatement(); + + string name; + vector> values; + +protected: + ExecuteStatement(const ExecuteStatement &other); + +public: + unique_ptr Copy() const override; +}; +} // namespace duckdb + + + + namespace duckdb { struct ActiveQueryContext { @@ -119320,14 +131615,20 @@ unique_ptr ClientContext::FetchInternal(ClientContextLock &lock, Exec return chunk; } catch (StandardException &ex) { // standard exceptions do not invalidate the current transaction - result.error = ex.what(); + result.SetError(PreservedError(ex)); invalidate_query = false; + } catch (FatalException &ex) { + // fatal exceptions invalidate the entire database + result.SetError(PreservedError(ex)); + auto &db = DatabaseInstance::GetDatabase(*this); + db.Invalidate(); + } catch (const Exception &ex) { + result.SetError(PreservedError(ex)); } catch (std::exception &ex) { - result.error = ex.what(); + result.SetError(PreservedError(ex)); } catch (...) { // LCOV_EXCL_START - result.error = "Unhandled exception in FetchInternal"; + result.SetError(PreservedError("Unhandled exception in FetchInternal")); } // LCOV_EXCL_STOP - result.success = false; CleanupInternal(lock, &result, invalidate_query); return nullptr; } @@ -119335,6 +131636,10 @@ unique_ptr ClientContext::FetchInternal(ClientContextLock &lock, Exec void ClientContext::BeginTransactionInternal(ClientContextLock &lock, bool requires_valid_transaction) { // check if we are on AutoCommit. In this case we should start a transaction D_ASSERT(!active_query); + auto &db = DatabaseInstance::GetDatabase(*this); + if (db.IsInvalidated()) { + throw FatalException("Failed: database has been invalidated!"); + } if (requires_valid_transaction && transaction.HasActiveTransaction() && transaction.ActiveTransaction().IsInvalidated()) { throw Exception("Failed: transaction has been invalidated!"); @@ -119353,11 +131658,11 @@ void ClientContext::BeginQueryInternal(ClientContextLock &lock, const string &qu ActiveTransaction().active_query = db->GetTransactionManager().GetQueryNumber(); } -string ClientContext::EndQueryInternal(ClientContextLock &lock, bool success, bool invalidate_transaction) { +PreservedError ClientContext::EndQueryInternal(ClientContextLock &lock, bool success, bool invalidate_transaction) { client_data->profiler->EndQuery(); D_ASSERT(active_query.get()); - string error; + PreservedError error; try { if (transaction.HasActiveTransaction()) { // Move the query profiler into the history @@ -119383,10 +131688,16 @@ string ClientContext::EndQueryInternal(ClientContextLock &lock, bool success, bo ActiveTransaction().Invalidate(); } } + } catch (FatalException &ex) { + auto &db = DatabaseInstance::GetDatabase(*this); + db.Invalidate(); + error = PreservedError(ex); + } catch (const Exception &ex) { + error = PreservedError(ex); } catch (std::exception &ex) { - error = ex.what(); + error = PreservedError(ex); } catch (...) { // LCOV_EXCL_START - error = "Unhandled exception!"; + error = PreservedError("Unhandled exception!"); } // LCOV_EXCL_STOP active_query.reset(); query_progress = -1; @@ -119403,11 +131714,10 @@ void ClientContext::CleanupInternal(ClientContextLock &lock, BaseQueryResult *re } active_query->progress_bar.reset(); - auto error = EndQueryInternal(lock, result ? result->success : false, invalidate_transaction); - if (result && result->success) { + auto error = EndQueryInternal(lock, result ? !result->HasError() : false, invalidate_transaction); + if (result && !result->HasError()) { // if an error occurred while committing report it in the result - result->error = error; - result->success = error.empty(); + result->SetError(error); } D_ASSERT(!active_query); } @@ -119449,8 +131759,15 @@ unique_ptr ClientContext::FetchResultInternal(ClientContextLock &lo CleanupInternal(lock, result.get(), false); } else { // no result collector - create a materialized result by continuously fetching + auto result_collection = make_unique(Allocator::DefaultAllocator(), pending.types); + D_ASSERT(!result_collection->Types().empty()); auto materialized_result = make_unique( - pending.statement_type, pending.properties, pending.types, pending.names, shared_from_this()); + pending.statement_type, pending.properties, pending.names, move(result_collection), GetClientProperties()); + + auto &collection = materialized_result->Collection(); + D_ASSERT(!collection.Types().empty()); + ColumnDataAppendState append_state; + collection.InitializeAppend(append_state); while (true) { auto chunk = FetchInternal(lock, GetExecutor(), *materialized_result); if (!chunk || chunk->size() == 0) { @@ -119463,13 +131780,24 @@ unique_ptr ClientContext::FetchResultInternal(ClientContextLock &lo } } #endif - materialized_result->collection.Append(*chunk); + collection.Append(append_state, *chunk); } result = move(materialized_result); } return result; } +static bool IsExplainAnalyze(SQLStatement *statement) { + if (!statement) { + return false; + } + if (statement->type != StatementType::EXPLAIN_STATEMENT) { + return false; + } + auto &explain = (ExplainStatement &)*statement; + return explain.explain_type == ExplainType::EXPLAIN_ANALYZE; +} + shared_ptr ClientContext::CreatePreparedStatement(ClientContextLock &lock, const string &query, unique_ptr statement, vector *values) { @@ -119477,21 +131805,19 @@ shared_ptr ClientContext::CreatePreparedStatement(ClientC auto result = make_shared(statement_type); auto &profiler = QueryProfiler::Get(*this); + profiler.StartQuery(query, IsExplainAnalyze(statement.get()), true); profiler.StartPhase("planner"); Planner planner(*this); if (values) { for (auto &value : *values) { - planner.parameter_types.push_back(value.type()); + planner.parameter_data.emplace_back(value); } } planner.CreatePlan(move(statement)); - D_ASSERT(planner.plan); + D_ASSERT(planner.plan || !planner.properties.bound_all_parameters); profiler.EndPhase(); auto plan = move(planner.plan); -#ifdef DEBUG - plan->Verify(); -#endif // extract the result column names from the plan result->properties = planner.properties; result->names = planner.names; @@ -119499,7 +131825,13 @@ shared_ptr ClientContext::CreatePreparedStatement(ClientC result->value_map = move(planner.value_map); result->catalog_version = Transaction::GetTransaction(*this).catalog_version; - if (config.enable_optimizer) { + if (!planner.properties.bound_all_parameters) { + return result; + } +#ifdef DEBUG + plan->Verify(*this); +#endif + if (config.enable_optimizer && plan->RequireOptimizer()) { profiler.StartPhase("optimizer"); Optimizer optimizer(*planner.binder, *this); plan = optimizer.Optimize(move(plan)); @@ -119507,7 +131839,7 @@ shared_ptr ClientContext::CreatePreparedStatement(ClientC profiler.EndPhase(); #ifdef DEBUG - plan->Verify(); + plan->Verify(*this); #endif } @@ -119537,7 +131869,7 @@ unique_ptr ClientContext::PendingPreparedStatement(ClientCon throw Exception("Current transaction is aborted (please ROLLBACK)"); } auto &db_config = DBConfig::GetConfig(*this); - if (db_config.access_mode == AccessMode::READ_ONLY && !statement.properties.read_only) { + if (db_config.options.access_mode == AccessMode::READ_ONLY && !statement.properties.read_only) { throw Exception(StringUtil::Format("Cannot execute statement of type \"%s\" in read-only mode!", StatementTypeToString(statement.statement_type))); } @@ -119584,13 +131916,14 @@ PendingExecutionResult ClientContext::ExecuteTaskInternal(ClientContextLock &loc query_progress = active_query->progress_bar->GetCurrentPercentage(); } return result; + } catch (const Exception &ex) { + result.SetError(PreservedError(ex)); } catch (std::exception &ex) { - result.error = ex.what(); + result.SetError(PreservedError(ex)); } catch (...) { // LCOV_EXCL_START - result.error = "Unhandled exception in ExecuteTaskInternal"; + result.SetError(PreservedError("Unhandled exception in ExecuteTaskInternal")); } // LCOV_EXCL_STOP EndQueryInternal(lock, false, true); - result.success = false; return PendingExecutionResult::EXECUTION_ERROR; } @@ -119669,8 +132002,10 @@ unique_ptr ClientContext::Prepare(unique_ptr st try { InitialCleanup(*lock); return PrepareInternal(*lock, move(statement)); + } catch (const Exception &ex) { + return make_unique(PreservedError(ex)); } catch (std::exception &ex) { - return make_unique(ex.what()); + return make_unique(PreservedError(ex)); } } @@ -119689,8 +132024,10 @@ unique_ptr ClientContext::Prepare(const string &query) { throw Exception("Cannot prepare multiple statements at once!"); } return PrepareInternal(*lock, move(statements[0])); + } catch (const Exception &ex) { + return make_unique(PreservedError(ex)); } catch (std::exception &ex) { - return make_unique(ex.what()); + return make_unique(PreservedError(ex)); } } @@ -119699,8 +132036,10 @@ unique_ptr ClientContext::PendingQueryPreparedInternal(Clien PendingQueryParameters parameters) { try { InitialCleanup(lock); + } catch (const Exception &ex) { + return make_unique(PreservedError(ex)); } catch (std::exception &ex) { - return make_unique(ex.what()); + return make_unique(PreservedError(ex)); } return PendingStatementOrPreparedStatementInternal(lock, query, nullptr, prepared, parameters); } @@ -119716,8 +132055,8 @@ unique_ptr ClientContext::Execute(const string &query, shared_ptr

success) { - return make_unique(pending->error); + if (pending->HasError()) { + return make_unique(pending->GetErrorObject()); } return pending->ExecuteInternal(*lock); } @@ -119734,7 +132073,15 @@ unique_ptr ClientContext::PendingStatementInternal(ClientCon unique_ptr statement, PendingQueryParameters parameters) { // prepare the query for execution - auto prepared = CreatePreparedStatement(lock, query, move(statement)); + auto prepared = CreatePreparedStatement(lock, query, move(statement), parameters.parameters); + if (prepared->properties.parameter_count > 0 && !parameters.parameters) { + string error_message = StringUtil::Format("Expected %lld parameters, but none were supplied", + prepared->properties.parameter_count); + return make_unique(PreservedError(error_message)); + } + if (!prepared->properties.bound_all_parameters) { + return make_unique(PreservedError("Not all parameters were bound")); + } // execute the prepared statement return PendingPreparedStatement(lock, move(prepared), parameters); } @@ -119745,8 +132092,8 @@ unique_ptr ClientContext::RunStatementInternal(ClientContextLock &l PendingQueryParameters parameters; parameters.allow_stream_result = allow_stream_result; auto pending = PendingQueryInternal(lock, move(statement), parameters, verify); - if (!pending->success) { - return make_unique(move(pending->error)); + if (pending->HasError()) { + return make_unique(pending->GetErrorObject()); } return ExecutePendingQueryInternal(lock, *pending); } @@ -119758,22 +132105,11 @@ bool ClientContext::IsActiveResult(ClientContextLock &lock, BaseQueryResult *res return active_query->open_result == result; } -static bool IsExplainAnalyze(SQLStatement *statement) { - if (!statement) { - return false; - } - if (statement->type != StatementType::EXPLAIN_STATEMENT) { - return false; - } - auto &explain = (ExplainStatement &)*statement; - return explain.explain_type == ExplainType::EXPLAIN_ANALYZE; -} - unique_ptr ClientContext::PendingStatementOrPreparedStatementInternal( ClientContextLock &lock, const string &query, unique_ptr statement, shared_ptr &prepared, PendingQueryParameters parameters) { // check if we are on AutoCommit. In this case we should start a transaction. - if (statement && config.query_verification_enabled) { + if (statement && config.AnyVerification()) { // query verification is enabled // create a copy of the statement, and use the copy // this way we verify that the copy correctly copies all properties @@ -119781,13 +132117,15 @@ unique_ptr ClientContext::PendingStatementOrPreparedStatemen switch (statement->type) { case StatementType::SELECT_STATEMENT: { // in case this is a select query, we verify the original statement - string error; + PreservedError error; try { error = VerifyQuery(lock, query, move(statement)); + } catch (const Exception &ex) { + error = PreservedError(ex); } catch (std::exception &ex) { - error = ex.what(); + error = PreservedError(ex); } - if (!error.empty()) { + if (error) { // error in verifying query return make_unique(error); } @@ -119816,7 +132154,19 @@ unique_ptr ClientContext::PendingStatementOrPreparedStatemen shared_ptr &prepared, PendingQueryParameters parameters) { unique_ptr result; - BeginQueryInternal(lock, query); + try { + BeginQueryInternal(lock, query); + } catch (FatalException &ex) { + // fatal exceptions invalidate the entire database + auto &db = DatabaseInstance::GetDatabase(*this); + db.Invalidate(); + result = make_unique(PreservedError(ex)); + return result; + } catch (const Exception &ex) { + return make_unique(PreservedError(ex)); + } catch (std::exception &ex) { + return make_unique(PreservedError(ex)); + } // start the profiler auto &profiler = QueryProfiler::Get(*this); profiler.StartQuery(query, IsExplainAnalyze(statement ? statement.get() : prepared->unbound_statement.get())); @@ -119825,15 +132175,10 @@ unique_ptr ClientContext::PendingStatementOrPreparedStatemen if (statement) { result = PendingStatementInternal(lock, query, move(statement), parameters); } else { - auto &catalog = Catalog::GetCatalog(*this); - if (prepared->unbound_statement && (catalog.GetCatalogVersion() != prepared->catalog_version || - !prepared->properties.bound_all_parameters)) { + if (prepared->RequireRebind(*this, *parameters.parameters)) { // catalog was modified: rebind the statement before execution auto new_prepared = CreatePreparedStatement(lock, query, prepared->unbound_statement->Copy(), parameters.parameters); - if (prepared->types != new_prepared->types && prepared->properties.bound_all_parameters) { - throw BinderException("Rebinding statement after catalog change resulted in change of types"); - } D_ASSERT(new_prepared->properties.bound_all_parameters); new_prepared->unbound_statement = move(prepared->unbound_statement); prepared = move(new_prepared); @@ -119843,13 +132188,23 @@ unique_ptr ClientContext::PendingStatementOrPreparedStatemen } } catch (StandardException &ex) { // standard exceptions do not invalidate the current transaction - result = make_unique(ex.what()); + result = make_unique(PreservedError(ex)); invalidate_query = false; + } catch (FatalException &ex) { + // fatal exceptions invalidate the entire database + auto &db = DatabaseInstance::GetDatabase(*this); + if (!config.query_verification_enabled) { + db.Invalidate(); + } + result = make_unique(PreservedError(ex)); + } catch (const Exception &ex) { + // other types of exceptions do invalidate the current transaction + result = make_unique(PreservedError(ex)); } catch (std::exception &ex) { // other types of exceptions do invalidate the current transaction - result = make_unique(ex.what()); + result = make_unique(PreservedError(ex)); } - if (!result->success) { + if (result->HasError()) { // query failed: abort now EndQueryInternal(lock, false, invalidate_query); return result; @@ -119882,8 +132237,8 @@ void ClientContext::LogQueryInternal(ClientContextLock &, const string &query) { unique_ptr ClientContext::Query(unique_ptr statement, bool allow_stream_result) { auto pending_query = PendingQuery(move(statement), allow_stream_result); - if (!pending_query->success) { - return make_unique(pending_query->error); + if (pending_query->HasError()) { + return make_unique(pending_query->GetErrorObject()); } return pending_query->Execute(); } @@ -119891,7 +132246,7 @@ unique_ptr ClientContext::Query(unique_ptr statement, unique_ptr ClientContext::Query(const string &query, bool allow_stream_result) { auto lock = LockContext(); - string error; + PreservedError error; vector> statements; if (!ParseStatements(*lock, query, statements, error)) { return make_unique(move(error)); @@ -119899,10 +132254,10 @@ unique_ptr ClientContext::Query(const string &query, bool allow_str if (statements.empty()) { // no statements, return empty successful result StatementProperties properties; - vector types; vector names; - return make_unique(StatementType::INVALID_STATEMENT, properties, move(types), - move(names), shared_from_this()); + auto collection = make_unique(Allocator::DefaultAllocator()); + return make_unique(StatementType::INVALID_STATEMENT, properties, move(names), + move(collection), GetClientProperties()); } unique_ptr result; @@ -119914,8 +132269,8 @@ unique_ptr ClientContext::Query(const string &query, bool allow_str parameters.allow_stream_result = allow_stream_result && is_last_statement; auto pending_query = PendingQueryInternal(*lock, move(statement), parameters); unique_ptr current_result; - if (!pending_query->success) { - current_result = make_unique(pending_query->error); + if (pending_query->HasError()) { + current_result = make_unique(pending_query->GetErrorObject()); } else { current_result = ExecutePendingQueryInternal(*lock, *pending_query); } @@ -119934,14 +132289,17 @@ unique_ptr ClientContext::Query(const string &query, bool allow_str } bool ClientContext::ParseStatements(ClientContextLock &lock, const string &query, - vector> &result, string &error) { + vector> &result, PreservedError &error) { try { InitialCleanup(lock); // parse the query and transform it into a set of statements result = ParseStatementsInternal(lock, query); return true; + } catch (const Exception &ex) { + error = PreservedError(ex); + return false; } catch (std::exception &ex) { - error = ex.what(); + error = PreservedError(ex); return false; } } @@ -119949,13 +132307,13 @@ bool ClientContext::ParseStatements(ClientContextLock &lock, const string &query unique_ptr ClientContext::PendingQuery(const string &query, bool allow_stream_result) { auto lock = LockContext(); - string error; + PreservedError error; vector> statements; if (!ParseStatements(*lock, query, statements, error)) { return make_unique(move(error)); } if (statements.size() != 1) { - return make_unique("PendingQuery can only take a single statement"); + return make_unique(PreservedError("PendingQuery can only take a single statement")); } PendingQueryParameters parameters; parameters.allow_stream_result = allow_stream_result; @@ -119994,6 +132352,7 @@ void ClientContext::EnableProfiling() { auto lock = LockContext(); auto &config = ClientConfig::GetConfig(*this); config.enable_profiler = true; + config.emit_profiler_output = true; } void ClientContext::DisableProfiling() { @@ -120002,205 +132361,14 @@ void ClientContext::DisableProfiling() { config.enable_profiler = false; } -struct VerifyStatement { - VerifyStatement(unique_ptr statement_p, string statement_name_p, bool require_equality = true, - bool disable_optimizer = false) - : statement(move(statement_p)), statement_name(move(statement_name_p)), require_equality(require_equality), - disable_optimizer(disable_optimizer), select_list(statement->node->GetSelectList()) { - } - - unique_ptr statement; - string statement_name; - bool require_equality; - bool disable_optimizer; - const vector> &select_list; -}; - -string ClientContext::VerifyQuery(ClientContextLock &lock, const string &query, unique_ptr statement) { - D_ASSERT(statement->type == StatementType::SELECT_STATEMENT); - // aggressive query verification - - // the purpose of this function is to test correctness of otherwise hard to test features: - // Copy() of statements and expressions - // Serialize()/Deserialize() of expressions - // Hash() of expressions - // Equality() of statements and expressions - // ToString() of statements and expressions - // Correctness of plans both with and without optimizers - - vector verify_statements; - - // copy the statement - auto select_stmt = (SelectStatement *)statement.get(); - auto copied_stmt = unique_ptr_cast(select_stmt->Copy()); - auto unoptimized_stmt = unique_ptr_cast(select_stmt->Copy()); - - BufferedSerializer serializer; - select_stmt->Serialize(serializer); - BufferedDeserializer source(serializer); - auto deserialized_stmt = SelectStatement::Deserialize(source); - - auto query_str = select_stmt->ToString(); - Parser parser; - parser.ParseQuery(query_str); - D_ASSERT(parser.statements.size() == 1); - D_ASSERT(parser.statements[0]->type == StatementType::SELECT_STATEMENT); - auto parsed_statement = move(parser.statements[0]); - - verify_statements.emplace_back(unique_ptr_cast(move(statement)), - "Original statement"); - verify_statements.emplace_back(move(copied_stmt), "Copied statement"); - verify_statements.emplace_back(move(deserialized_stmt), "Deserialized statement"); - verify_statements.emplace_back(unique_ptr_cast(move(parsed_statement)), - "Parsed statement", false); - verify_statements.emplace_back(unique_ptr_cast(move(unoptimized_stmt)), - "Unoptimized", true, true); - - // all the statements should be equal - for (idx_t i = 1; i < verify_statements.size(); i++) { - if (!verify_statements[i].require_equality) { - continue; - } - D_ASSERT(verify_statements[i].statement->Equals(verify_statements[0].statement.get())); - } - - // now perform checking on the expressions -#ifdef DEBUG - for (idx_t i = 1; i < verify_statements.size(); i++) { - D_ASSERT(verify_statements[i].select_list.size() == verify_statements[0].select_list.size()); - } - auto expr_count = verify_statements[0].select_list.size(); - auto &orig_expr_list = verify_statements[0].select_list; - for (idx_t i = 0; i < expr_count; i++) { - // run the ToString, to verify that it doesn't crash - auto str = orig_expr_list[i]->ToString(); - for (idx_t v_idx = 0; v_idx < verify_statements.size(); v_idx++) { - if (!verify_statements[v_idx].require_equality && orig_expr_list[i]->HasSubquery()) { - continue; - } - // check that the expressions are equivalent - D_ASSERT(orig_expr_list[i]->Equals(verify_statements[v_idx].select_list[i].get())); - // check that the hashes are equivalent too - D_ASSERT(orig_expr_list[i]->Hash() == verify_statements[v_idx].select_list[i]->Hash()); - - verify_statements[v_idx].select_list[i]->Verify(); - } - D_ASSERT(!orig_expr_list[i]->Equals(nullptr)); - - if (orig_expr_list[i]->HasSubquery()) { - continue; - } - // ToString round trip - auto parsed_list = Parser::ParseExpressionList(str); - D_ASSERT(parsed_list.size() == 1); - D_ASSERT(parsed_list[0]->Equals(orig_expr_list[i].get())); - } - // perform additional checking within the expressions - for (idx_t outer_idx = 0; outer_idx < orig_expr_list.size(); outer_idx++) { - auto hash = orig_expr_list[outer_idx]->Hash(); - for (idx_t inner_idx = 0; inner_idx < orig_expr_list.size(); inner_idx++) { - auto hash2 = orig_expr_list[inner_idx]->Hash(); - if (hash != hash2) { - // if the hashes are not equivalent, the expressions should not be equivalent - D_ASSERT(!orig_expr_list[outer_idx]->Equals(orig_expr_list[inner_idx].get())); - } - } - } -#endif - - // disable profiling if it is enabled - auto &config = ClientConfig::GetConfig(*this); - bool profiling_is_enabled = config.enable_profiler; - if (profiling_is_enabled) { - config.enable_profiler = false; - } - - // see below - auto statement_copy_for_explain = select_stmt->Copy(); - - // execute the original statement - auto optimizer_enabled = config.enable_optimizer; - vector> results; - for (idx_t i = 0; i < verify_statements.size(); i++) { - interrupted = false; - config.enable_optimizer = !verify_statements[i].disable_optimizer; - try { - auto result = RunStatementInternal(lock, query, move(verify_statements[i].statement), false, false); - results.push_back(unique_ptr_cast(move(result))); - } catch (std::exception &ex) { - results.push_back(make_unique(ex.what())); - } - interrupted = false; - } - config.enable_optimizer = optimizer_enabled; - - // check explain, only if q does not already contain EXPLAIN - if (results[0]->success) { - auto explain_q = "EXPLAIN " + query; - auto explain_stmt = make_unique(move(statement_copy_for_explain)); - try { - RunStatementInternal(lock, explain_q, move(explain_stmt), false, false); - } catch (std::exception &ex) { // LCOV_EXCL_START - interrupted = false; - return "EXPLAIN failed but query did not (" + string(ex.what()) + ")"; - } // LCOV_EXCL_STOP - } - - if (profiling_is_enabled) { - config.enable_profiler = true; - } - - // now compare the results - // the results of all runs should be identical - for (idx_t i = 1; i < results.size(); i++) { - auto name = verify_statements[i].statement_name; - if (results[0]->success != results[i]->success) { // LCOV_EXCL_START - string result = name + " differs from original result!\n"; - result += "Original Result:\n" + results[0]->ToString(); - result += name + ":\n" + results[i]->ToString(); - return result; - } // LCOV_EXCL_STOP - if (!results[0]->collection.Equals(results[i]->collection)) { // LCOV_EXCL_START - string result = name + " differs from original result!\n"; - result += "Original Result:\n" + results[0]->ToString(); - result += name + ":\n" + results[i]->ToString(); - return result; - } // LCOV_EXCL_STOP - } - - return ""; -} - -bool ClientContext::UpdateFunctionInfoFromEntry(ScalarFunctionCatalogEntry *existing_function, - CreateScalarFunctionInfo *new_info) { - if (new_info->functions.empty()) { - throw InternalException("Registering function without scalar function definitions!"); - } - bool need_rewrite_entry = false; - idx_t size_new_func = new_info->functions.size(); - for (idx_t exist_idx = 0; exist_idx < existing_function->functions.size(); ++exist_idx) { - bool can_add = true; - for (idx_t new_idx = 0; new_idx < size_new_func; ++new_idx) { - if (new_info->functions[new_idx].Equal(existing_function->functions[exist_idx])) { - can_add = false; - break; - } - } - if (can_add) { - new_info->functions.push_back(existing_function->functions[exist_idx]); - need_rewrite_entry = true; - } - } - return need_rewrite_entry; -} - void ClientContext::RegisterFunction(CreateFunctionInfo *info) { RunFunctionInTransaction([&]() { auto &catalog = Catalog::GetCatalog(*this); auto existing_function = (ScalarFunctionCatalogEntry *)catalog.GetEntry( *this, CatalogType::SCALAR_FUNCTION_ENTRY, info->schema, info->name, true); if (existing_function) { - if (UpdateFunctionInfoFromEntry(existing_function, (CreateScalarFunctionInfo *)info)) { + auto new_info = (CreateScalarFunctionInfo *)info; + if (new_info->functions.MergeFunctionSet(existing_function->functions)) { // function info was updated from catalog entry, rewrite is needed info->on_conflict = OnCreateConflict::REPLACE_ON_CONFLICT; } @@ -120229,6 +132397,10 @@ void ClientContext::RunFunctionInTransactionInternal(ClientContextLock &lock, co transaction.Rollback(); } throw; + } catch (FatalException &ex) { + auto &db = DatabaseInstance::GetDatabase(*this); + db.Invalidate(); + throw; } catch (std::exception &ex) { if (require_new_transaction) { transaction.Rollback(); @@ -120267,7 +132439,7 @@ unique_ptr ClientContext::TableInfo(const string &schema_name, return result; } -void ClientContext::Append(TableDescription &description, ChunkCollection &collection) { +void ClientContext::Append(TableDescription &description, ColumnDataCollection &collection) { RunFunctionInTransaction([&]() { auto &catalog = Catalog::GetCatalog(*this); auto table_entry = catalog.GetEntry(*this, description.schema, description.table); @@ -120281,7 +132453,7 @@ void ClientContext::Append(TableDescription &description, ChunkCollection &colle } } for (auto &chunk : collection.Chunks()) { - table_entry->storage->Append(*table_entry, *this, *chunk); + table_entry->storage->Append(*table_entry, *this, chunk); } }); } @@ -120342,7 +132514,7 @@ unique_ptr ClientContext::Execute(const shared_ptr &relat unique_ptr result; result = RunStatementInternal(*lock, query, move(relation_stmt), false); - if (!result->success) { + if (result->HasError()) { return result; } // verify that the result types and result names of the query match the expected result types/names @@ -120373,7 +132545,7 @@ unique_ptr ClientContext::Execute(const shared_ptr &relat err_str += result->names[i] + " " + result->types[i].ToString(); } err_str += "]"; - return make_unique(err_str); + return make_unique(PreservedError(err_str)); } bool ClientContext::TryGetCurrentSetting(const std::string &key, Value &result) { @@ -120385,29 +132557,33 @@ bool ClientContext::TryGetCurrentSetting(const std::string &key, Value &result) return true; } - // then check the session values + // check the client session values const auto &session_config_map = config.set_variables; - const auto &global_config_map = db_config.set_variables; auto session_value = session_config_map.find(key); bool found_session_value = session_value != session_config_map.end(); - auto global_value = global_config_map.find(key); - bool found_global_value = global_value != global_config_map.end(); - if (!found_session_value && !found_global_value) { - return false; + if (found_session_value) { + result = session_value->second; + return true; } - - result = found_session_value ? session_value->second : global_value->second; - return true; + // finally check the global session values + return db->TryGetCurrentSetting(key, result); } -ParserOptions ClientContext::GetParserOptions() { +ParserOptions ClientContext::GetParserOptions() const { ParserOptions options; options.preserve_identifier_case = ClientConfig::GetConfig(*this).preserve_identifier_case; options.max_expression_depth = ClientConfig::GetConfig(*this).max_expression_depth; + options.extensions = &DBConfig::GetConfig(*this).parser_extensions; return options; } +ClientProperties ClientContext::GetClientProperties() const { + ClientProperties properties; + properties.timezone = ClientConfig::GetConfig(*this).ExtractTimezone(); + return properties; +} + } // namespace duckdb @@ -120429,6 +132605,7 @@ bool ClientContextFileOpener::TryGetCurrentSetting(const string &key, Value &res + namespace duckdb { ClientData::ClientData(ClientContext &context) : catalog_search_path(make_unique(context)) { @@ -120453,6 +132630,184 @@ RandomEngine &RandomEngine::Get(ClientContext &context) { +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/verification/statement_verifier.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + +namespace duckdb { + +enum class VerificationType : uint8_t { + ORIGINAL, + COPIED, + DESERIALIZED, + PARSED, + UNOPTIMIZED, + PREPARED, + EXTERNAL, + + INVALID +}; + +class StatementVerifier { +public: + StatementVerifier(VerificationType type, string name, unique_ptr statement_p); + explicit StatementVerifier(unique_ptr statement_p); + static unique_ptr Create(VerificationType type, const SQLStatement &statement_p); + virtual ~StatementVerifier() noexcept; + + //! Check whether expressions in this verifier and the other verifier match + void CheckExpressions(const StatementVerifier &other) const; + //! Check whether expressions within this verifier match + void CheckExpressions() const; + + //! Run the select statement and store the result + virtual bool Run(ClientContext &context, const string &query, + const std::function(const string &, unique_ptr)> &run); + //! Compare this verifier's results with another verifier + string CompareResults(const StatementVerifier &other); + +public: + const VerificationType type; + const string name; + unique_ptr statement; + const vector> &select_list; + unique_ptr materialized_result; + + virtual bool RequireEquality() const { + return true; + } + + virtual bool DisableOptimizer() const { + return false; + } + + virtual bool ForceExternal() const { + return false; + } +}; + +} // namespace duckdb + + +namespace duckdb { + +PreservedError ClientContext::VerifyQuery(ClientContextLock &lock, const string &query, + unique_ptr statement) { + D_ASSERT(statement->type == StatementType::SELECT_STATEMENT); + // Aggressive query verification + + // The purpose of this function is to test correctness of otherwise hard to test features: + // Copy() of statements and expressions + // Serialize()/Deserialize() of expressions + // Hash() of expressions + // Equality() of statements and expressions + // ToString() of statements and expressions + // Correctness of plans both with and without optimizers + + const auto &stmt = *statement; + vector> statement_verifiers; + unique_ptr prepared_statement_verifier; + if (config.query_verification_enabled) { + statement_verifiers.emplace_back(StatementVerifier::Create(VerificationType::COPIED, stmt)); + statement_verifiers.emplace_back(StatementVerifier::Create(VerificationType::DESERIALIZED, stmt)); + statement_verifiers.emplace_back(StatementVerifier::Create(VerificationType::PARSED, stmt)); + statement_verifiers.emplace_back(StatementVerifier::Create(VerificationType::UNOPTIMIZED, stmt)); + prepared_statement_verifier = StatementVerifier::Create(VerificationType::PREPARED, stmt); + } + if (config.verify_external) { + statement_verifiers.emplace_back(StatementVerifier::Create(VerificationType::EXTERNAL, stmt)); + } + + auto original = make_unique(move(statement)); + for (auto &verifier : statement_verifiers) { + original->CheckExpressions(*verifier); + } + original->CheckExpressions(); + + // See below + auto statement_copy_for_explain = stmt.Copy(); + + // Save settings + bool optimizer_enabled = config.enable_optimizer; + bool profiling_is_enabled = config.enable_profiler; + bool force_external = config.force_external; + + // Disable profiling if it is enabled + if (profiling_is_enabled) { + config.enable_profiler = false; + } + + // Execute the original statement + bool any_failed = original->Run(*this, query, [&](const string &q, unique_ptr s) { + return RunStatementInternal(lock, q, move(s), false, false); + }); + + // Execute the verifiers + for (auto &verifier : statement_verifiers) { + bool failed = verifier->Run(*this, query, [&](const string &q, unique_ptr s) { + return RunStatementInternal(lock, q, move(s), false, false); + }); + any_failed = any_failed || failed; + } + + if (!any_failed && prepared_statement_verifier) { + // If none failed, we execute the prepared statement verifier + bool failed = prepared_statement_verifier->Run(*this, query, [&](const string &q, unique_ptr s) { + return RunStatementInternal(lock, q, move(s), false, false); + }); + if (!failed) { + // PreparedStatementVerifier fails if it runs into a ParameterNotAllowedException, which is OK + statement_verifiers.push_back(move(prepared_statement_verifier)); + } + } + + // Restore config setting + config.enable_optimizer = optimizer_enabled; + config.force_external = force_external; + + // Check explain, only if q does not already contain EXPLAIN + if (original->materialized_result->success) { + auto explain_q = "EXPLAIN " + query; + auto explain_stmt = make_unique(move(statement_copy_for_explain)); + try { + RunStatementInternal(lock, explain_q, move(explain_stmt), false, false); + } catch (std::exception &ex) { // LCOV_EXCL_START + interrupted = false; + return PreservedError("EXPLAIN failed but query did not (" + string(ex.what()) + ")"); + } // LCOV_EXCL_STOP + } + + // Restore profiler setting + if (profiling_is_enabled) { + config.enable_profiler = true; + } + + // Now compare the results + // The results of all runs should be identical + for (auto &verifier : statement_verifiers) { + auto result = original->CompareResults(*verifier); + if (!result.empty()) { + return PreservedError(result); + } + } + + return PreservedError(); +} + +} // namespace duckdb + + + //===----------------------------------------------------------------------===// // DuckDB @@ -120575,6 +132930,14 @@ struct EnableExternalAccessSetting { static Value GetSetting(ClientContext &context); }; +struct AllowUnsignedExtensionsSetting { + static constexpr const char *Name = "allow_unsigned_extensions"; + static constexpr const char *Description = "Allow to load extensions with invalid or missing signatures"; + static constexpr const LogicalTypeId InputType = LogicalTypeId::BOOLEAN; + static void SetGlobal(DatabaseInstance *db, DBConfig &config, const Value ¶meter); + static Value GetSetting(ClientContext &context); +}; + struct EnableObjectCacheSetting { static constexpr const char *Name = "enable_object_cache"; static constexpr const char *Description = "Whether or not object cache is used to cache e.g. Parquet metadata"; @@ -120633,6 +132996,14 @@ struct ForceCompressionSetting { static Value GetSetting(ClientContext &context); }; +struct HomeDirectorySetting { + static constexpr const char *Name = "home_directory"; + static constexpr const char *Description = "Sets the home directory used by the system"; + static constexpr const LogicalTypeId InputType = LogicalTypeId::VARCHAR; + static void SetLocal(ClientContext &context, const Value ¶meter); + static Value GetSetting(ClientContext &context); +}; + struct LogQueryPathSetting { static constexpr const char *Name = "log_query_path"; static constexpr const char *Description = @@ -120789,6 +133160,7 @@ static ConfigurationOption internal_options[] = {DUCKDB_GLOBAL(AccessModeSetting DUCKDB_GLOBAL(DefaultNullOrderSetting), DUCKDB_GLOBAL(DisabledOptimizersSetting), DUCKDB_GLOBAL(EnableExternalAccessSetting), + DUCKDB_GLOBAL(AllowUnsignedExtensionsSetting), DUCKDB_GLOBAL(EnableObjectCacheSetting), DUCKDB_LOCAL(EnableProfilingSetting), DUCKDB_LOCAL(EnableProgressBarSetting), @@ -120796,6 +133168,7 @@ static ConfigurationOption internal_options[] = {DUCKDB_GLOBAL(AccessModeSetting DUCKDB_GLOBAL(ExternalThreadsSetting), DUCKDB_LOCAL(FileSearchPathSetting), DUCKDB_GLOBAL(ForceCompressionSetting), + DUCKDB_LOCAL(HomeDirectorySetting), DUCKDB_LOCAL(LogQueryPathSetting), DUCKDB_LOCAL(MaximumExpressionDepthSetting), DUCKDB_GLOBAL(MaximumMemorySetting), @@ -120924,6 +133297,67 @@ idx_t DBConfig::ParseMemoryLimit(const string &arg) { +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/main/connection_manager.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + +namespace duckdb { +class ClientContext; +class DatabaseInstance; + +class ConnectionManager { +public: + ConnectionManager() { + } + + void AddConnection(ClientContext &context) { + lock_guard lock(connections_lock); + connections.insert(make_pair(&context, weak_ptr(context.shared_from_this()))); + } + + void RemoveConnection(ClientContext &context) { + lock_guard lock(connections_lock); + connections.erase(&context); + } + + vector> GetConnectionList() { + vector> result; + for (auto &it : connections) { + auto connection = it.second.lock(); + if (!connection) { + connections.erase(it.first); + continue; + } else { + result.push_back(move(connection)); + } + } + + return result; + } + + static ConnectionManager &Get(DatabaseInstance &db); + static ConnectionManager &Get(ClientContext &context); + +public: + mutex connections_lock; + unordered_map> connections; +}; + +} // namespace duckdb + + + //===----------------------------------------------------------------------===// // DuckDB // @@ -121001,7 +133435,7 @@ class ReadCSVRelation : public Relation { //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/main/relation/table_relation.hpp +// duckdb/main/relation/table_function_relation.hpp // // //===----------------------------------------------------------------------===// @@ -121010,26 +133444,29 @@ class ReadCSVRelation : public Relation { - namespace duckdb { -class TableRelation : public Relation { +class TableFunctionRelation : public Relation { public: - TableRelation(const std::shared_ptr &context, unique_ptr description); + TableFunctionRelation(const std::shared_ptr &context, string name, vector parameters, + named_parameter_map_t named_parameters, shared_ptr input_relation_p = nullptr); - unique_ptr description; + TableFunctionRelation(const std::shared_ptr &context, string name, vector parameters, + shared_ptr input_relation_p = nullptr); + + string name; + vector parameters; + named_parameter_map_t named_parameters; + vector columns; + shared_ptr input_relation; public: unique_ptr GetQueryNode() override; + unique_ptr GetTableRef() override; const vector &Columns() override; string ToString(idx_t depth) override; string GetAlias() override; - - unique_ptr GetTableRef() override; - - void Update(const string &update, const string &condition = string()) override; - void Delete(const string &condition = string()) override; }; } // namespace duckdb @@ -121037,7 +133474,7 @@ class TableRelation : public Relation { //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/main/relation/table_function_relation.hpp +// duckdb/main/relation/table_relation.hpp // // //===----------------------------------------------------------------------===// @@ -121046,29 +133483,26 @@ class TableRelation : public Relation { + namespace duckdb { -class TableFunctionRelation : public Relation { +class TableRelation : public Relation { public: - TableFunctionRelation(const std::shared_ptr &context, string name, vector parameters, - named_parameter_map_t named_parameters, shared_ptr input_relation_p = nullptr); - - TableFunctionRelation(const std::shared_ptr &context, string name, vector parameters, - shared_ptr input_relation_p = nullptr); + TableRelation(const std::shared_ptr &context, unique_ptr description); - string name; - vector parameters; - named_parameter_map_t named_parameters; - vector columns; - shared_ptr input_relation; + unique_ptr description; public: unique_ptr GetQueryNode() override; - unique_ptr GetTableRef() override; const vector &Columns() override; string ToString(idx_t depth) override; string GetAlias() override; + + unique_ptr GetTableRef() override; + + void Update(const string &update, const string &condition = string()) override; + void Delete(const string &condition = string()) override; }; } // namespace duckdb @@ -121147,65 +133581,6 @@ class ViewRelation : public Relation { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/main/connection_manager.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - - -namespace duckdb { -class ClientContext; -class DatabaseInstance; - -class ConnectionManager { -public: - ConnectionManager() { - } - - void AddConnection(ClientContext &context) { - lock_guard lock(connections_lock); - connections.insert(make_pair(&context, weak_ptr(context.shared_from_this()))); - } - - void RemoveConnection(ClientContext &context) { - lock_guard lock(connections_lock); - connections.erase(&context); - } - - vector> GetConnectionList() { - vector> result; - for (auto &it : connections) { - auto connection = it.second.lock(); - if (!connection) { - connections.erase(it.first); - continue; - } else { - result.push_back(move(connection)); - } - } - - return result; - } - - static ConnectionManager &Get(DatabaseInstance &db); - static ConnectionManager &Get(ClientContext &context); - -public: - mutex connections_lock; - unordered_map> connections; -}; - -} // namespace duckdb - namespace duckdb { @@ -121214,6 +133589,7 @@ Connection::Connection(DatabaseInstance &database) : context(make_sharedconfig.emit_profiler_output = false; #endif } @@ -121229,7 +133605,7 @@ string Connection::GetProfilingInformation(ProfilerPrintFormat format) { if (format == ProfilerPrintFormat::JSON) { return profiler.ToJSON(); } else { - return profiler.ToString(); + return profiler.QueryTreeToString(); } } @@ -121291,7 +133667,7 @@ unique_ptr Connection::Prepare(unique_ptr state unique_ptr Connection::QueryParamsRecursive(const string &query, vector &values) { auto statement = Prepare(query); - if (!statement->success) { + if (statement->HasError()) { return make_unique(statement->error); } return statement->Execute(values, false); @@ -121314,12 +133690,15 @@ unique_ptr Connection::ExtractPlan(const string &query) { } void Connection::Append(TableDescription &description, DataChunk &chunk) { - ChunkCollection collection; + if (chunk.size() == 0) { + return; + } + ColumnDataCollection collection(Allocator::Get(*context), chunk.GetTypes()); collection.Append(chunk); Append(description, collection); } -void Connection::Append(TableDescription &description, ChunkCollection &collection) { +void Connection::Append(TableDescription &description, ColumnDataCollection &collection) { context->Append(description, collection); } @@ -121416,22 +133795,22 @@ shared_ptr Connection::RelationFromQuery(unique_ptr s void Connection::BeginTransaction() { auto result = Query("BEGIN TRANSACTION"); - if (!result->success) { - throw Exception(result->error); + if (result->HasError()) { + result->ThrowError(); } } void Connection::Commit() { auto result = Query("COMMIT"); - if (!result->success) { - throw Exception(result->error); + if (result->HasError()) { + result->ThrowError(); } } void Connection::Rollback() { auto result = Query("ROLLBACK"); - if (!result->success) { - throw Exception(result->error); + if (result->HasError()) { + result->ThrowError(); } } @@ -121442,6 +133821,9 @@ void Connection::SetAutoCommit(bool auto_commit) { bool Connection::IsAutoCommit() { return context->transaction.IsAutoCommit(); } +bool Connection::HasActiveTransaction() { + return context->transaction.HasActiveTransaction(); +} } // namespace duckdb @@ -121505,8 +133887,8 @@ class ObjectCache { cache[key] = move(value); } - static ObjectCache &GetObjectCache(ClientContext &context); - static bool ObjectCacheEnabled(ClientContext &context); + DUCKDB_API static ObjectCache &GetObjectCache(ClientContext &context); + DUCKDB_API static bool ObjectCacheEnabled(ClientContext &context); private: //! Object Cache @@ -121548,7 +133930,7 @@ DatabaseInstance::~DatabaseInstance() { auto &storage = StorageManager::GetStorageManager(*this); if (!storage.InMemory()) { auto &config = storage.db.config; - if (!config.checkpoint_on_shutdown) { + if (!config.options.checkpoint_on_shutdown) { return; } storage.CreateCheckpoint(true); @@ -121593,6 +133975,14 @@ ClientConfig &ClientConfig::GetConfig(ClientContext &context) { return context.config; } +const DBConfig &DBConfig::GetConfig(const DatabaseInstance &db) { + return db.config; +} + +const ClientConfig &ClientConfig::GetConfig(const ClientContext &context) { + return context.config; +} + TransactionManager &TransactionManager::Get(ClientContext &context) { return TransactionManager::Get(DatabaseInstance::GetDatabase(context)); } @@ -121618,22 +134008,22 @@ void DatabaseInstance::Initialize(const char *path, DBConfig *new_config) { DBConfig config; Configure(config); } - if (config.temporary_directory.empty() && path) { + if (config.options.temporary_directory.empty() && path) { // no directory specified: use default temp path - config.temporary_directory = string(path) + ".tmp"; + config.options.temporary_directory = string(path) + ".tmp"; // special treatment for in-memory mode if (strcmp(path, ":memory:") == 0) { - config.temporary_directory = ".tmp"; + config.options.temporary_directory = ".tmp"; } } - if (new_config && !new_config->use_temporary_directory) { + if (new_config && !new_config->options.use_temporary_directory) { // temporary directories explicitly disabled - config.temporary_directory = string(); + config.options.temporary_directory = string(); } - storage = - make_unique(*this, path ? string(path) : string(), config.access_mode == AccessMode::READ_ONLY); + storage = make_unique(*this, path ? string(path) : string(), + config.options.access_mode == AccessMode::READ_ONLY); catalog = make_unique(*this); transaction_manager = make_unique(*this); scheduler = make_unique(*this); @@ -121644,12 +134034,12 @@ void DatabaseInstance::Initialize(const char *path, DBConfig *new_config) { storage->Initialize(); // only increase thread count after storage init because we get races on catalog otherwise - scheduler->SetThreads(config.maximum_threads); + scheduler->SetThreads(config.options.maximum_threads); } DuckDB::DuckDB(const char *path, DBConfig *new_config) : instance(make_shared()) { instance->Initialize(path, new_config); - if (instance->config.load_extensions) { + if (instance->config.options.load_extensions) { ExtensionHelper::LoadAllExtensions(*this); } } @@ -121700,56 +134090,72 @@ Allocator &Allocator::Get(ClientContext &context) { } Allocator &Allocator::Get(DatabaseInstance &db) { - return db.config.allocator; + return *db.config.allocator; } void DatabaseInstance::Configure(DBConfig &new_config) { - config.access_mode = AccessMode::READ_WRITE; - if (new_config.access_mode != AccessMode::UNDEFINED) { - config.access_mode = new_config.access_mode; + config.options.access_mode = AccessMode::READ_WRITE; + if (new_config.options.access_mode != AccessMode::UNDEFINED) { + config.options.access_mode = new_config.options.access_mode; } if (new_config.file_system) { config.file_system = move(new_config.file_system); } else { config.file_system = make_unique(); } - config.maximum_memory = new_config.maximum_memory; - if (config.maximum_memory == (idx_t)-1) { - config.maximum_memory = FileSystem::GetAvailableMemory() * 8 / 10; + config.options.maximum_memory = new_config.options.maximum_memory; + if (config.options.maximum_memory == (idx_t)-1) { + auto memory = FileSystem::GetAvailableMemory(); + if (memory != DConstants::INVALID_INDEX) { + config.options.maximum_memory = memory * 8 / 10; + } } - if (new_config.maximum_threads == (idx_t)-1) { + if (new_config.options.maximum_threads == (idx_t)-1) { #ifndef DUCKDB_NO_THREADS - config.maximum_threads = std::thread::hardware_concurrency(); + config.options.maximum_threads = std::thread::hardware_concurrency(); #else - config.maximum_threads = 1; + config.options.maximum_threads = 1; #endif } else { - config.maximum_threads = new_config.maximum_threads; + config.options.maximum_threads = new_config.options.maximum_threads; } - config.external_threads = new_config.external_threads; - config.load_extensions = new_config.load_extensions; - config.force_compression = new_config.force_compression; + config.options.external_threads = new_config.options.external_threads; + config.options.load_extensions = new_config.options.load_extensions; + config.options.force_compression = new_config.options.force_compression; config.allocator = move(new_config.allocator); - config.checkpoint_wal_size = new_config.checkpoint_wal_size; - config.use_direct_io = new_config.use_direct_io; - config.temporary_directory = new_config.temporary_directory; - config.collation = new_config.collation; - config.default_order_type = new_config.default_order_type; - config.default_null_order = new_config.default_null_order; - config.enable_external_access = new_config.enable_external_access; + if (!config.allocator) { + config.allocator = make_unique(); + } + config.options.checkpoint_wal_size = new_config.options.checkpoint_wal_size; + config.options.use_direct_io = new_config.options.use_direct_io; + config.options.temporary_directory = new_config.options.temporary_directory; + config.options.collation = new_config.options.collation; + config.options.default_order_type = new_config.options.default_order_type; + config.options.default_null_order = new_config.options.default_null_order; + config.options.enable_external_access = new_config.options.enable_external_access; + config.options.allow_unsigned_extensions = new_config.options.allow_unsigned_extensions; config.replacement_scans = move(new_config.replacement_scans); - config.initialize_default_database = new_config.initialize_default_database; - config.disabled_optimizers = move(new_config.disabled_optimizers); + config.options.initialize_default_database = new_config.options.initialize_default_database; + config.options.disabled_optimizers = move(new_config.options.disabled_optimizers); + config.parser_extensions = move(new_config.parser_extensions); } DBConfig &DBConfig::GetConfig(ClientContext &context) { return context.db->config; } +const DBConfig &DBConfig::GetConfig(const ClientContext &context) { + return context.db->config; +} + idx_t DatabaseInstance::NumberOfThreads() { return scheduler->NumberOfThreads(); } +const unordered_set &DatabaseInstance::LoadedExtensions() { + return loaded_extensions; +} + idx_t DuckDB::NumberOfThreads() { return instance->NumberOfThreads(); } @@ -121761,14 +134167,36 @@ void DuckDB::SetExtensionLoaded(const std::string &name) { instance->loaded_extensions.insert(name); } -string ClientConfig::ExtractTimezoneFromConfig(ClientConfig &config) { - if (config.set_variables.find("TimeZone") == config.set_variables.end()) { +bool DatabaseInstance::TryGetCurrentSetting(const std::string &key, Value &result) { + // check the session values + auto &db_config = DBConfig::GetConfig(*this); + const auto &global_config_map = db_config.options.set_variables; + + auto global_value = global_config_map.find(key); + bool found_global_value = global_value != global_config_map.end(); + if (!found_global_value) { + return false; + } + result = global_value->second; + return true; +} + +string ClientConfig::ExtractTimezone() const { + auto entry = set_variables.find("TimeZone"); + if (entry == set_variables.end()) { return "UTC"; } else { - return config.set_variables["TimeZone"].GetValue(); + return entry->second.GetValue(); } } +void DatabaseInstance::Invalidate() { + this->is_invalidated = true; +} +bool DatabaseInstance::IsInvalidated() { + return this->is_invalidated; +} + } // namespace duckdb @@ -121778,31 +134206,45 @@ string ClientConfig::ExtractTimezoneFromConfig(ClientConfig &config) { #if defined(BUILD_ICU_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#define ICU_STATICALLY_LOADED true #include "icu-extension.hpp" +#else +#define ICU_STATICALLY_LOADED false #endif #if defined(BUILD_PARQUET_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#define PARQUET_STATICALLY_LOADED true #include "parquet-extension.hpp" +#else +#define PARQUET_STATICALLY_LOADED false #endif #if defined(BUILD_TPCH_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#define TPCH_STATICALLY_LOADED true #include "tpch-extension.hpp" +#else +#define TPCH_STATICALLY_LOADED false #endif #if defined(BUILD_TPCDS_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#define TPCDS_STATICALLY_LOADED true #include "tpcds-extension.hpp" -#endif - -#if defined(BUILD_SUBSTRAIT_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) -#include "substrait-extension.hpp" +#else +#define TPCDS_STATICALLY_LOADED false #endif #if defined(BUILD_FTS_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#define FTS_STATICALLY_LOADED true #include "fts-extension.hpp" +#else +#define FTS_STATICALLY_LOADED false #endif #if defined(BUILD_HTTPFS_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#define HTTPFS_STATICALLY_LOADED true #include "httpfs-extension.hpp" +#else +#define HTTPFS_STATICALLY_LOADED false #endif #if defined(BUILD_VISUALIZER_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) @@ -121810,7 +134252,10 @@ string ClientConfig::ExtractTimezoneFromConfig(ClientConfig &config) { #endif #if defined(BUILD_JSON_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#define JSON_STATICALLY_LOADED true #include "json-extension.hpp" +#else +#define JSON_STATICALLY_LOADED false #endif #if defined(BUILD_EXCEL_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) @@ -121823,17 +134268,44 @@ string ClientConfig::ExtractTimezoneFromConfig(ClientConfig &config) { namespace duckdb { -void ExtensionHelper::LoadAllExtensions(DuckDB &db) { - unordered_set extensions {"parquet", "icu", "tpch", "tpcds", "fts", "httpfs", - "substrait", "visualizer", "json", "excel", "sqlsmith"}; - for (auto &ext : extensions) { - LoadExtensionInternal(db, ext, true); +//===--------------------------------------------------------------------===// +// Default Extensions +//===--------------------------------------------------------------------===// +static DefaultExtension internal_extensions[] = { + {"icu", "Adds support for time zones and collations using the ICU library", ICU_STATICALLY_LOADED}, + {"parquet", "Adds support for reading and writing parquet files", PARQUET_STATICALLY_LOADED}, + {"tpch", "Adds TPC-H data generation and query support", TPCH_STATICALLY_LOADED}, + {"tpcds", "Adds TPC-DS data generation and query support", TPCDS_STATICALLY_LOADED}, + {"fts", "Adds support for Full-Text Search Indexes", FTS_STATICALLY_LOADED}, + {"httpfs", "Adds support for reading and writing files over a HTTP(S) connection", HTTPFS_STATICALLY_LOADED}, + {"json", "Adds support for JSON operations", JSON_STATICALLY_LOADED}, + {"sqlite_scanner", "Adds support for reading SQLite database files", false}, + {"postgres_scanner", "Adds support for reading from a Postgres database", false}, + {nullptr, nullptr, false}}; + +idx_t ExtensionHelper::DefaultExtensionCount() { + idx_t index; + for (index = 0; internal_extensions[index].name != nullptr; index++) { } + return index; +} + +DefaultExtension ExtensionHelper::GetDefaultExtension(idx_t index) { + D_ASSERT(index < DefaultExtensionCount()); + return internal_extensions[index]; } //===--------------------------------------------------------------------===// // Load Statically Compiled Extension //===--------------------------------------------------------------------===// +void ExtensionHelper::LoadAllExtensions(DuckDB &db) { + unordered_set extensions {"parquet", "icu", "tpch", "tpcds", "fts", + "httpfs", "visualizer", "json", "excel", "sqlsmith"}; + for (auto &ext : extensions) { + LoadExtensionInternal(db, ext, true); + } +} + ExtensionLoadResult ExtensionHelper::LoadExtension(DuckDB &db, const std::string &extension) { return LoadExtensionInternal(db, extension, false); } @@ -121844,12 +134316,12 @@ ExtensionLoadResult ExtensionHelper::LoadExtensionInternal(DuckDB &db, const std if (!initial_load && StringUtil::Contains(DUCKDB_TEST_REMOTE_INSTALL, extension)) { Connection con(db); auto result = con.Query("INSTALL " + extension); - if (!result->success) { + if (result->HasError()) { result->Print(); return ExtensionLoadResult::EXTENSION_UNKNOWN; } result = con.Query("LOAD " + extension); - if (!result->success) { + if (result->HasError()) { result->Print(); return ExtensionLoadResult::EXTENSION_UNKNOWN; } @@ -121857,50 +134329,42 @@ ExtensionLoadResult ExtensionHelper::LoadExtensionInternal(DuckDB &db, const std } #endif if (extension == "parquet") { -#if defined(BUILD_PARQUET_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#if PARQUET_STATICALLY_LOADED db.LoadExtension(); #else // parquet extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "icu") { -#if defined(BUILD_ICU_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#if ICU_STATICALLY_LOADED db.LoadExtension(); #else // icu extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "tpch") { -#if defined(BUILD_TPCH_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#if TPCH_STATICALLY_LOADED db.LoadExtension(); #else // icu extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; -#endif - } else if (extension == "substrait") { -#if defined(BUILD_SUBSTRAIT_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) - - db.LoadExtension(); -#else - // substrait extension required but not build: skip this test - return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "tpcds") { -#if defined(BUILD_TPCDS_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#if TPCDS_STATICALLY_LOADED db.LoadExtension(); #else // icu extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "fts") { -#if defined(BUILD_FTS_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#if FTS_STATICALLY_LOADED db.LoadExtension(); #else // fts extension required but not build: skip this test return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "httpfs") { -#if defined(BUILD_HTTPFS_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#if HTTPFS_STATICALLY_LOADED db.LoadExtension(); #else return ExtensionLoadResult::NOT_LOADED; @@ -121913,7 +134377,7 @@ ExtensionLoadResult ExtensionHelper::LoadExtensionInternal(DuckDB &db, const std return ExtensionLoadResult::NOT_LOADED; #endif } else if (extension == "json") { -#if defined(BUILD_JSON_EXTENSION) && !defined(DISABLE_BUILTIN_EXTENSIONS) +#if JSON_STATICALLY_LOADED db.LoadExtension(); #else // json extension required but not build: skip this test @@ -121940,15 +134404,243 @@ ExtensionLoadResult ExtensionHelper::LoadExtensionInternal(DuckDB &db, const std return ExtensionLoadResult::LOADED_EXTENSION; } +static std::vector public_keys = { + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6aZuHUa1cLR9YDDYaEfi +UDbWY8m2t7b71S+k1ZkXfHqu+5drAxm+dIDzdOHOKZSIdwnJbT3sSqwFoG6PlXF3 +g3dsJjax5qESIhbVvf98nyipwNINxoyHCkcCIPkX17QP2xpnT7V59+CqcfDJXLqB +ymjqoFSlaH8dUCHybM4OXlWnAtVHW/nmw0khF8CetcWn4LxaTUHptByaBz8CasSs +gWpXgSfaHc3R9eArsYhtsVFGyL/DEWgkEHWolxY3Llenhgm/zOf3s7PsAMe7EJX4 +qlSgiXE6OVBXnqd85z4k20lCw/LAOe5hoTMmRWXIj74MudWe2U91J6GrrGEZa7zT +7QIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAq8Gg1S/LI6ApMAYsFc9m +PrkFIY+nc0LXSpxm77twU8D5M0Xkz/Av4f88DQmj1OE3164bEtR7sl7xDPZojFHj +YYyucJxEI97l5OU1d3Pc1BdKXL4+mnW5FlUGj218u8qD+G1hrkySXQkrUzIjPPNw +o6knF3G/xqQF+KI+tc7ajnTni8CAlnUSxfnstycqbVS86m238PLASVPK9/SmIRgO +XCEV+ZNMlerq8EwsW4cJPHH0oNVMcaG+QT4z79roW1rbJghn9ubAVdQU6VLUAikI +b8keUyY+D0XdY9DpDBeiorb1qPYt8BPLOAQrIUAw1CgpMM9KFp9TNvW47KcG4bcB +dQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyYATA9KOQ0Azf97QAPfY +Jc/WeZyE4E1qlRgKWKqNtYSXZqk5At0V7w2ntAWtYSpczFrVepCJ0oPMDpZTigEr +NgOgfo5LEhPx5XmtCf62xY/xL3kgtfz9Mm5TBkuQy4KwY4z1npGr4NYYDXtF7kkf +LQE+FnD8Yr4E0wHBib7ey7aeeKWmwqvUjzDqG+TzaqwzO/RCUsSctqSS0t1oo2hv +4q1ofanUXsV8MXk/ujtgxu7WkVvfiSpK1zRazgeZjcrQFO9qL/pla0vBUxa1U8He +GMLnL0oRfcMg7yKrbIMrvlEl2ZmiR9im44dXJWfY42quObwr1PuEkEoCMcMisSWl +jwIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4RvbWx3zLblDHH/lGUF5 +Q512MT+v3YPriuibROMllv8WiCLAMeJ0QXbVaIzBOeHDeLx8yvoZZN+TENKxtT6u +IfMMneUzxHBqy0AQNfIsSsOnG5nqoeE/AwbS6VqCdH1aLfoCoPffacHYa0XvTcsi +aVlZfr+UzJS+ty8pRmFVi1UKSOADDdK8XfIovJl/zMP2TxYX2Y3fnjeLtl8Sqs2e +P+eHDoy7Wi4EPTyY7tNTCfxwKNHn1HQ5yrv5dgvMxFWIWXGz24yikFvtwLGHe8uJ +Wi+fBX+0PF0diZ6pIthZ149VU8qCqYAXjgpxZ0EZdrsiF6Ewz0cfg20SYApFcmW4 +pwIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyhd5AfwrUohG3O4DE0K9 +O3FmgB7zE4aDnkL8UUfGCh5kdP8q7ewMjekY+c6LwWOmpdJpSwqhfV1q5ZU1l6rk +3hlt03LO3sgs28kcfOVH15hqfxts6Sg5KcRjxStE50ORmXGwXDcS9vqkJ60J1EHA +lcZqbCRSO73ZPLhdepfd0/C6tM0L7Ge6cAE62/MTmYNGv8fDzwQr/kYIJMdoS8Zp +thRpctFZJtPs3b0fffZA/TCLVKMvEVgTWs48751qKid7N/Lm/iEGx/tOf4o23Nec +Pz1IQaGLP+UOLVQbqQBHJWNOqigm7kWhDgs3N4YagWgxPEQ0WVLtFji/ZjlKZc7h +dwIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnFDg3LhyV6BVE2Z3zQvN +6urrKvPhygTa5+wIPGwYTzJ8DfGALqlsX3VOXMvcJTca6SbuwwkoXHuSU5wQxfcs +bt4jTXD3NIoRwQPl+D9IbgIMuX0ACl27rJmr/f9zkY7qui4k1X82pQkxBe+/qJ4r +TBwVNONVx1fekTMnSCEhwg5yU3TNbkObu0qlQeJfuMWLDQbW/8v/qfr/Nz0JqHDN +yYKfKvFMlORxyJYiOyeOsbzNGEhkGQGOmKhRUhS35kD+oA0jqwPwMCM9O4kFg/L8 +iZbpBBX2By1K3msejWMRAewTOyPas6YMQOYq9BMmWQqzVtG5xcaSJwN/YnMpJyqb +sQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1z0RU8vGrfEkrscEoZKA +GiOcGh2EMcKwjQpl4nKuR9H4o/dg+CZregVSHg7MP2f8mhLZZyoFev49oWOV4Rmi +qs99UNxm7DyKW1fF1ovowsUW5lsDoKYLvpuzHo0s4laiV4AnIYP7tHGLdzsnK2Os +Cp5dSuMwKHPZ9N25hXxFB/dRrAdIiXHvbSqr4N29XzfQloQpL3bGHLKY6guFHluH +X5dJ9eirVakWWou7BR2rnD0k9vER6oRdVnJ6YKb5uhWEOQ3NmV961oyr+uiDTcep +qqtGHWuFhENixtiWGjFJJcACwqxEAW3bz9lyrfnPDsHSW/rlQVDIAkik+fOp+R7L +kQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxwO27e1vnbNcpiDg7Wwx +K/w5aEGukXotu3529ieq+O39H0+Bak4vIbzGhDUh3/ElmxaFMAs4PYrWe/hc2WFD +H4JCOoFIn4y9gQeE855DGGFgeIVd1BnSs5S+5wUEMxLNyHdHSmINN6FsoZ535iUg +KdYjRh1iZevezg7ln8o/O36uthu925ehFBXSy6jLJgQlwmq0KxZJE0OAZhuDBM60 +MtIunNa/e5y+Gw3GknFwtRLmn/nEckZx1nEtepYvvUa7UGy+8KuGuhOerCZTutbG +k8liCVgGenRve8unA2LrBbpL+AUf3CrZU/uAxxTqWmw6Z/S6TeW5ozeeyOCh8ii6 +TwIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsGIFOfIQ4RI5qu4klOxf +ge6eXwBMAkuTXyhyIIJDtE8CurnwQvUXVlt+Kf0SfuIFW6MY5ErcWE/vMFbc81IR +9wByOAAV2CTyiLGZT63uE8pN6FSHd6yGYCLjXd3P3cnP3Qj5pBncpLuAUDfHG4wP +bs9jIADw3HysD+eCNja8p7ZC7CzWxTcO7HsEu9deAAU19YywdpagXvQ0pJ9zV5qU +jrHxBygl31t6TmmX+3d+azjGu9Hu36E+5wcSOOhuwAFXDejb40Ixv53ItJ3fZzzH +PF2nj9sQvQ8c5ptjyOvQCBRdqkEWXIVHClxqWb+o59pDIh1G0UGcmiDN7K9Gz5HA +ZQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt9uUnlW/CoUXT68yaZh9 +SeXHzGRCPNEI98Tara+dgYxDX1z7nfOh8o15liT0QsAzx34EewZOxcKCNiV/dZX5 +z4clCkD8uUbZut6IVx8Eu+7Qcd5jZthRc6hQrN9Ltv7ZQEh7KGXOHa53kT2K01ws +4jbVmd/7Nx7y0Yyqhja01pIu/CUaTkODfQxBXwriLdIzp7y/iJeF/TLqCwZWHKQx +QOZnsPEveB1F00Va9MeAtTlXFUJ/TQXquqTjeLj4HuIRtbyuNgWoc0JyF+mcafAl +bnrNEBIfxZhAT81aUCIAzRJp6AqfdeZxnZ/WwohtZQZLXAxFQPTWCcP+Z9M7OIQL +WwIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA56NhfACkeCyZM07l2wmd +iTp24E2tLLKU3iByKlIRWRAvXsOejRMJTHTNHWa3cQ7uLP++Tf2St7ksNsyPMNZy +9QRTLNCYr9rN9loLwdb2sMWxFBwwzCaAOTahGI7GJQy30UB7FEND0X/5U2rZvQij +Q6K+O4aa+K9M5qyOHNMmXywmTnAgWKNaNxQHPRtD2+dSj60T6zXdtIuCrPfcNGg5 +gj07qWGEXX83V/L7nSqCiIVYg/wqds1x52Yjk1nhXYNBTqlnhmOd8LynGxz/sXC7 +h2Q9XsHjXIChW4FHyLIOl6b4zPMBSxzCigYm3QZJWfAkZv5PBRtnq7vhYOLHzLQj +CwIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmfPLe0IWGYC0MZC6YiM3 +QGfhT6zSKB0I2DW44nlBlWUcF+32jW2bFJtgE76qGGKFeU4kJBWYr99ufHoAodNg +M1Ehl/JfQ5KmbC1WIqnFTrgbmqJde79jeCvCpbFLuqnzidwO1PbXDbfRFQcgWaXT +mDVLNNVmLxA0GkCv+kydE2gtcOD9BDceg7F/56TDvclyI5QqAnjE2XIRMPZlXQP4 +oF2kgz4Cn7LxLHYmkU2sS9NYLzHoyUqFplWlxkQjA4eQ0neutV1Ydmc1IX8W7R38 +A7nFtaT8iI8w6Vkv7ijYN6xf5cVBPKZ3Dv7AdwPet86JD5mf5v+r7iwg5xl3r77Z +iwIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoB1kWsX8YmCcFOD9ilBY +xK076HmUAN026uJ8JpmU9Hz+QT1FNXOsnj1h2G6U6btYVIdHUTHy/BvAumrDKqRz +qcEAzCuhxUjPjss54a/Zqu6nQcoIPHuG/Er39oZHIVkPR1WCvWj8wmyYv6T//dPH +unO6tW29sXXxS+J1Gah6vpbtJw1pI/liah1DZzb13KWPDI6ZzviTNnW4S05r6js/ +30He+Yud6aywrdaP/7G90qcrteEFcjFy4Xf+5vG960oKoGoDplwX5poay1oCP9tb +g8AC8VSRAGi3oviTeSWZcrLXS8AtJhGvF48cXQj2q+8YeVKVDpH6fPQxJ9Sh9aeU +awIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4NTMAIYIlCMID00ufy/I +AZXc8pocDx9N1Q5x5/cL3aIpLmx02AKo9BvTJaJuHiTjlwYhPtlhIrHV4HUVTkOX +sISp8B8v9i2I1RIvCTAcvy3gcH6rdRWZ0cdTUiMEqnnxBX9zdzl8oMzZcyauv19D +BeqJvzflIT96b8g8K3mvgJHs9a1j9f0gN8FuTA0c52DouKnrh8UwH7mlrumYerJw +6goJGQuK1HEOt6bcQuvogkbgJWOoEYwjNrPwQvIcP4wyrgSnOHg1yXOFE84oVynJ +czQEOz9ke42I3h8wrnQxilEYBVo2uX8MenqTyfGnE32lPRt3Wv1iEVQls8Cxiuy2 +CQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3bUtfp66OtRyvIF/oucn +id8mo7gvbNEH04QMLO3Ok43dlWgWI3hekJAqOYc0mvoI5anqr98h8FI7aCYZm/bY +vpz0I1aXBaEPh3aWh8f/w9HME7ykBvmhMe3J+VFGWWL4eswfRl//GCtnSMBzDFhM +SaQOTvADWHkC0njeI5yXjf/lNm6fMACP1cnhuvCtnx7VP/DAtvUk9usDKG56MJnZ +UoVM3HHjbJeRwxCdlSWe12ilCdwMRKSDY92Hk38/zBLenH04C3HRQLjBGewACUmx +uvNInehZ4kSYFGa+7UxBxFtzJhlKzGR73qUjpWzZivCe1K0WfRVP5IWsKNCCESJ/ +nQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyV2dE/CRUAUE8ybq/DoS +Lc7QlYXh04K+McbhN724TbHahLTuDk5mR5TAunA8Nea4euRzknKdMFAz1eh9gyy3 +5x4UfXQW1fIZqNo6WNrGxYJgWAXU+pov+OvxsMQWzqS4jrTHDHbblCCLKp1akwJk +aFNyqgjAL373PcqXC+XAn8vHx4xHFoFP5lq4lLcJCOW5ee9v9El3w0USLwS+t1cF +RY3kuV6Njlr4zsRH9iM6/zaSuCALYWJ/JrPEurSJXzFZnWsvn6aQdeNeAn08+z0F +k2NwaauEo0xmLqzqTRGzjHqKKmeefN3/+M/FN2FrApDlxWQfhD2Y3USdAiN547Nj +1wIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvm2+kTrEQWZXuxhWzBdl +PCbQGqbrukbeS6JKSlQLJDC8ayZIxFxatqg1Q8UPyv89MVRsHOGlG1OqFaOEtPjQ +Oo6j/moFwB4GPyJhJHOGpCKa4CLB5clhfDCLJw6ty7PcDU3T6yW4X4Qc5k4LRRWy +yzC8lVHfBdarN+1iEe0ALMOGoeiJjVn6i/AFxktRwgd8njqv/oWQyfjJZXkNMsb6 +7ZDxNVAUrp/WXpE4Kq694bB9xa/pWsqv7FjQJUgTnEzvbN+qXnVPtA7dHcOYYJ8Z +SbrJUfHrf8TS5B54AiopFpWG+hIbjqqdigqabBqFpmjiRDZgDy4zJJj52xJZMnrp +rwIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwEAcVmY3589O02pLA22f +MlarLyJUgy0BeJDG5AUsi17ct8sHZzRiv9zKQVCBk1CtZY//jyqnrM7iCBLWsyby +TiTOtGYHHApaLnNjjtaHdQ6zplhbc3g2XLy+4ab8GNKG3zc8iXpsQM6r+JO5n9pm +V9vollz9dkFxS9l+1P17lZdIgCh9O3EIFJv5QCd5c9l2ezHAan2OhkWhiDtldnH/ +MfRXbz7X5sqlwWLa/jhPtvY45x7dZaCHGqNzbupQZs0vHnAVdDu3vAWDmT/3sXHG +vmGxswKA9tPU0prSvQWLz4LUCnGi/cC5R+fiu+fovFM/BwvaGtqBFIF/1oWVq7bZ +4wIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA25qGwNO1+qHygC8mjm8L +3I66mV/IzslgBDHC91mE8YcI5Fq0sdrtsbUhK3z89wIN/zOhbHX0NEiXm2GxUnsI +vb5tDZXAh7AbTnXTMVbxO/e/8sPLUiObGjDvjVzyzrxOeG87yK/oIiilwk9wTsIb +wMn2Grj4ht9gVKx3oGHYV7STNdWBlzSaJj4Ou7+5M1InjPDRFZG1K31D2d3IHByX +lmcRPZtPFTa5C1uVJw00fI4F4uEFlPclZQlR5yA0G9v+0uDgLcjIUB4eqwMthUWc +dHhlmrPp04LI19eksWHCtG30RzmUaxDiIC7J2Ut0zHDqUe7aXn8tOVI7dE9tTKQD +KQIDAQAB +-----END PUBLIC KEY----- +)", + R"( +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7EC2bx7aRnf3TcRg5gmw +QOKNCUheCelK8hoXLMsKSJqmufyJ+IHUejpXGOpvyYRbACiJ5GiNcww20MVpTBU7 +YESWB2QSU2eEJJXMq84qsZSO8WGmAuKpUckI+hNHKQYJBEDOougV6/vVVEm5c5bc +SLWQo0+/ciQ21Zwz5SwimX8ep1YpqYirO04gcyGZzAfGboXRvdUwA+1bZvuUXdKC +4zsCw2QALlcVpzPwjB5mqA/3a+SPgdLAiLOwWXFDRMnQw44UjsnPJFoXgEZiUpZm +EMS5gLv50CzQqJXK9mNzPuYXNUIc4Pw4ssVWe0OfN3Od90gl5uFUwk/G9lWSYnBN +3wIDAQAB +-----END PUBLIC KEY----- +)"}; + +const vector ExtensionHelper::GetPublicKeys() { + return public_keys; +} + } // namespace duckdb + + #ifndef DISABLE_DUCKDB_REMOTE_INSTALL // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #9 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #10 // See the end of this file for a list // taken from: https://github.com/yhirose/cpp-httplib/blob/v0.10.2/httplib.h @@ -124003,7 +136695,7 @@ inline std::string encode_url(const std::string &s) { for (size_t i = 0; s[i]; i++) { switch (s[i]) { case ' ': result += "%20"; break; - case '+': result += "%2B"; break; +// case '+': result += "%2B"; break; case '\r': result += "%0D"; break; case '\n': result += "%0A"; break; case '\'': result += "%27"; break; @@ -124049,7 +136741,12 @@ inline std::string decode_url(const std::string &s, int val = 0; if (from_hex_to_i(s, i + 1, 2, val)) { // 2 digits hex codes - result += static_cast(val); + if (static_cast(val) == '+'){ + // We don't decode + + result += "%2B"; + } else { + result += static_cast(val); + } i += 2; // '00' } else { result += s[i]; @@ -125648,7 +138345,7 @@ inline void parse_query_text(const std::string &s, Params ¶ms) { }); if (!key.empty()) { - params.emplace(decode_url(key, true), decode_url(val, true)); + params.emplace(decode_url(key, true), decode_url(val, false)); } }); } @@ -128025,7 +140722,7 @@ inline bool ClientImpl::redirect(Request &req, Response &res, Error &error) { return false; } - auto location = detail::decode_url(res.get_header_value("location"), true); + auto location = detail::decode_url(res.get_header_value("location"), false); if (location.empty()) { return false; } const static Regex re( @@ -130156,16 +142853,13 @@ const vector ExtensionHelper::PathComponents() { return vector {".duckdb", "extensions", DuckDB::SourceID(), DuckDB::Platform()}; } -void ExtensionHelper::InstallExtension(DatabaseInstance &db, const string &extension, bool force_install) { - auto &config = DBConfig::GetConfig(db); - if (!config.enable_external_access) { - throw PermissionException("Installing extensions is disabled through configuration"); - } - auto &fs = FileSystem::GetFileSystem(db); - - string local_path = fs.GetHomeDirectory(); +string ExtensionHelper::ExtensionDirectory(ClientContext &context) { + auto &fs = FileSystem::GetFileSystem(context); + string local_path = fs.GetHomeDirectory(FileSystem::GetFileOpener(context)); if (!fs.DirectoryExists(local_path)) { - throw InternalException("Can't find the home directory at " + local_path); + throw IOException("Can't find the home directory at '%s'\nSpecify a home directory using the SET " + "home_directory='/path/to/dir' option.", + local_path); } auto path_components = PathComponents(); for (auto &path_ele : path_components) { @@ -130174,6 +142868,17 @@ void ExtensionHelper::InstallExtension(DatabaseInstance &db, const string &exten fs.CreateDirectory(local_path); } } + return local_path; +} + +void ExtensionHelper::InstallExtension(ClientContext &context, const string &extension, bool force_install) { + auto &config = DBConfig::GetConfig(context); + if (!config.options.enable_external_access) { + throw PermissionException("Installing extensions is disabled through configuration"); + } + auto &fs = FileSystem::GetFileSystem(context); + + string local_path = ExtensionDirectory(context); auto extension_name = fs.ExtractBaseName(extension); @@ -130182,19 +142887,27 @@ void ExtensionHelper::InstallExtension(DatabaseInstance &db, const string &exten return; } + auto uuid = UUID::ToString(UUID::GenerateRandomUUID()); + string temp_path = local_extension_path + ".tmp-" + uuid; + if (fs.FileExists(temp_path)) { + fs.RemoveFile(temp_path); + } auto is_http_url = StringUtil::Contains(extension, "http://"); if (fs.FileExists(extension)) { + std::ifstream in(extension, std::ios::binary); if (in.bad()) { throw IOException("Failed to read extension from \"%s\"", extension); } - std::ofstream out(local_extension_path, std::ios::binary); + std::ofstream out(temp_path, std::ios::binary); out << in.rdbuf(); if (out.bad()) { - throw IOException("Failed to write extension to \"%s\"", local_extension_path); + throw IOException("Failed to write extension to \"%s\"", temp_path); } in.close(); out.close(); + + fs.MoveFile(temp_path, local_extension_path); return; } else if (StringUtil::Contains(extension, "/") && !is_http_url) { throw IOException("Failed to read extension from \"%s\": no such file", extension); @@ -130232,15 +142945,33 @@ void ExtensionHelper::InstallExtension(DatabaseInstance &db, const string &exten DuckDB::SourceID(), DuckDB::Platform())}}; auto res = cli.Get(url_local_part.c_str(), headers); + if (!res || res->status != 200) { - throw IOException("Failed to download extension %s%s", url_base, url_local_part); + // create suggestions + vector candidates; + for (idx_t ext_count = ExtensionHelper::DefaultExtensionCount(), i = 0; i < ext_count; i++) { + candidates.emplace_back(ExtensionHelper::GetDefaultExtension(i).name); + } + auto closest_extensions = StringUtil::TopNLevenshtein(candidates, extension_name); + auto message = StringUtil::CandidatesMessage(closest_extensions, "Candidate extensions"); + for (auto &closest : closest_extensions) { + if (closest == extension_name) { + message = "Extension \"" + extension_name + "\" is an existing extension.\n"; + message += "Are you using a development build? In this case, extensions might not (yet) be uploaded."; + break; + } + } + throw IOException("Failed to download extension \"%s\" at URL \"%s%s\"\n%s", extension_name, url_base, + url_local_part, message); } auto decompressed_body = GZipFileSystem::UncompressGZIPString(res->body); - std::ofstream out(local_extension_path, std::ios::binary); + std::ofstream out(temp_path, std::ios::binary); out.write(decompressed_body.data(), decompressed_body.size()); if (out.bad()) { - throw IOException("Failed to write extension to %s", local_extension_path); + throw IOException("Failed to write extension to %s", temp_path); } + out.close(); + fs.MoveFile(temp_path, local_extension_path); #endif } @@ -130270,23 +143001,23 @@ namespace duckdb { #ifdef _WIN32 -void *dlopen(const char *file, int mode) { +inline void *dlopen(const char *file, int mode) { D_ASSERT(file); return (void *)LoadLibrary(file); } -void *dlsym(void *handle, const char *name) { +inline void *dlsym(void *handle, const char *name) { D_ASSERT(handle); return (void *)GetProcAddress((HINSTANCE)handle, name); } -std::string GetDLError(void) { +inline std::string GetDLError(void) { return LocalFileSystem::GetLastErrorAsString(); } #else -std::string GetDLError(void) { +inline std::string GetDLError(void) { return dlerror(); } @@ -130295,6 +143026,35 @@ std::string GetDLError(void) { } // namespace duckdb + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +//===----------------------------------------------------------------------===// +// DuckDB +// +// mbedtls_wrapper.hpp +// +// +//===----------------------------------------------------------------------===// + + + +#include + +namespace duckdb_mbedtls { +class MbedTlsWrapper { +public: + static std::string ComputeSha256Hash(const std::string& file_content); + static bool IsValidSha256Signature(const std::string& pubkey, const std::string& signature, const std::string& sha256_hash); +}; +} + + +// LICENSE_CHANGE_END + + namespace duckdb { //===--------------------------------------------------------------------===// @@ -130312,17 +143072,18 @@ static T LoadFunctionFromDLL(void *dll, const string &function_name, const strin return (T)function; } -void ExtensionHelper::LoadExternalExtension(DatabaseInstance &db, const string &extension) { - auto &config = DBConfig::GetConfig(db); - if (!config.enable_external_access) { +void ExtensionHelper::LoadExternalExtension(ClientContext &context, const string &extension) { + auto &db = DatabaseInstance::GetDatabase(context); + auto &config = DBConfig::GetConfig(context); + if (!config.options.enable_external_access) { throw PermissionException("Loading external extensions is disabled through configuration"); } - auto &fs = FileSystem::GetFileSystem(db); + auto &fs = FileSystem::GetFileSystem(context); auto filename = fs.ConvertSeparators(extension); // shorthand case if (!StringUtil::Contains(extension, ".") && !StringUtil::Contains(extension, fs.PathSeparator())) { - string local_path = fs.GetHomeDirectory(); + string local_path = fs.GetHomeDirectory(FileSystem::GetFileOpener(context)); auto path_components = PathComponents(); for (auto &path_ele : path_components) { local_path = fs.JoinPath(local_path, path_ele); @@ -130331,11 +143092,44 @@ void ExtensionHelper::LoadExternalExtension(DatabaseInstance &db, const string & } if (!fs.FileExists(filename)) { - throw IOException("File \"%s\" not found", filename); + throw IOException("Extension \"%s\" not found", filename); + } + { + auto handle = fs.OpenFile(filename, FileFlags::FILE_FLAGS_READ); + + // signature is the last 265 bytes of the file + + string signature; + signature.resize(256); + + auto signature_offset = handle->GetFileSize() - signature.size(); + + string file_content; + file_content.resize(signature_offset); + handle->Read((void *)file_content.data(), signature_offset, 0); + + // TODO maybe we should do a stream read / hash update here + handle->Read((void *)signature.data(), signature.size(), signature_offset); + + auto hash = duckdb_mbedtls::MbedTlsWrapper::ComputeSha256Hash(file_content); + + bool any_valid = false; + for (auto &key : ExtensionHelper::GetPublicKeys()) { + if (duckdb_mbedtls::MbedTlsWrapper::IsValidSha256Signature(key, signature, hash)) { + any_valid = true; + break; + } + } + if (!any_valid && !config.options.allow_unsigned_extensions) { + throw IOException( + "Extension \"%s\" could not be loaded because its signature is either missing or " + "invalid and unsigned extensions are disabled by configuration (allow_unsigned_extensions)", + filename); + } } auto lib_hdl = dlopen(filename.c_str(), RTLD_NOW | RTLD_LOCAL); if (!lib_hdl) { - throw IOException("File \"%s\" could not be loaded: %s", filename, GetDLError()); + throw IOException("Extension \"%s\" could not be loaded: %s", filename, GetDLError()); } auto basename = fs.ExtractBaseName(filename); @@ -130391,54 +143185,86 @@ Extension::~Extension() { + namespace duckdb { MaterializedQueryResult::MaterializedQueryResult(StatementType statement_type, StatementProperties properties, - vector types, vector names, - const shared_ptr &context) - : QueryResult(QueryResultType::MATERIALIZED_RESULT, statement_type, properties, move(types), move(names)), - context(context) { -} - -MaterializedQueryResult::MaterializedQueryResult(string error) - : QueryResult(QueryResultType::MATERIALIZED_RESULT, move(error)) { + vector names_p, unique_ptr collection_p, + ClientProperties client_properties) + : QueryResult(QueryResultType::MATERIALIZED_RESULT, statement_type, properties, collection_p->Types(), + move(names_p), move(client_properties)), + collection(move(collection_p)), scan_initialized(false) { } -Value MaterializedQueryResult::GetValue(idx_t column, idx_t index) { - auto &data = collection.GetChunkForRow(index).data[column]; - auto offset_in_chunk = index % STANDARD_VECTOR_SIZE; - return data.GetValue(offset_in_chunk); +MaterializedQueryResult::MaterializedQueryResult(PreservedError error) + : QueryResult(QueryResultType::MATERIALIZED_RESULT, move(error)), scan_initialized(false) { } string MaterializedQueryResult::ToString() { string result; if (success) { result = HeaderToString(); - result += "[ Rows: " + to_string(collection.Count()) + "]\n"; - for (idx_t j = 0; j < collection.Count(); j++) { - for (idx_t i = 0; i < collection.ColumnCount(); i++) { - auto val = collection.GetValue(i, j); + result += "[ Rows: " + to_string(collection->Count()) + "]\n"; + auto &coll = Collection(); + for (auto &row : coll.Rows()) { + for (idx_t col_idx = 0; col_idx < coll.ColumnCount(); col_idx++) { + if (col_idx > 0) { + result += "\t"; + } + auto val = row.GetValue(col_idx); result += val.IsNull() ? "NULL" : val.ToString(); - result += "\t"; } result += "\n"; } result += "\n"; } else { - result = error + "\n"; + result = GetError() + "\n"; } return result; } +Value MaterializedQueryResult::GetValue(idx_t column, idx_t index) { + if (!row_collection) { + row_collection = make_unique(collection->GetRows()); + } + return row_collection->GetValue(column, index); +} + +idx_t MaterializedQueryResult::RowCount() const { + return collection ? collection->Count() : 0; +} + +ColumnDataCollection &MaterializedQueryResult::Collection() { + if (HasError()) { + throw InvalidInputException("Attempting to get collection from an unsuccessful query result\n: Error %s", + GetError()); + } + if (!collection) { + throw InternalException("Missing collection from materialized query result"); + } + return *collection; +} + unique_ptr MaterializedQueryResult::Fetch() { return FetchRaw(); } unique_ptr MaterializedQueryResult::FetchRaw() { - if (!success) { - throw InvalidInputException("Attempting to fetch from an unsuccessful query result\nError: %s", error); + if (HasError()) { + throw InvalidInputException("Attempting to fetch from an unsuccessful query result\nError: %s", GetError()); + } + auto result = make_unique(); + collection->InitializeScanChunk(*result); + if (!scan_initialized) { + // we disallow zero copy so the chunk is independently usable even after the result is destroyed + collection->InitializeScan(scan_state, ColumnDataScanProperties::DISALLOW_ZERO_COPY); + scan_initialized = true; + } + collection->Scan(scan_state, *result); + if (result->size() == 0) { + return nullptr; } - return collection.Fetch(); + return result; } } // namespace duckdb @@ -130455,7 +143281,8 @@ PendingQueryResult::PendingQueryResult(shared_ptr context_p, Prep context(move(context_p)), allow_stream_result(allow_stream_result) { } -PendingQueryResult::PendingQueryResult(string error) : BaseQueryResult(QueryResultType::PENDING_RESULT, move(error)) { +PendingQueryResult::PendingQueryResult(PreservedError error) + : BaseQueryResult(QueryResultType::PENDING_RESULT, move(error)) { } PendingQueryResult::~PendingQueryResult() { @@ -130463,20 +143290,26 @@ PendingQueryResult::~PendingQueryResult() { unique_ptr PendingQueryResult::LockContext() { if (!context) { - throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result\nError: %s", - error); + if (HasError()) { + throw InvalidInputException( + "Attempting to execute an unsuccessful or closed pending query result\nError: %s", GetError()); + } + throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result"); } return context->LockContext(); } void PendingQueryResult::CheckExecutableInternal(ClientContextLock &lock) { - bool invalidated = !success || !context; + bool invalidated = HasError() || !context; if (!invalidated) { invalidated = !context->IsActiveResult(lock, this); } if (invalidated) { - throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result\nError: %s", - error); + if (HasError()) { + throw InvalidInputException( + "Attempting to execute an unsuccessful or closed pending query result\nError: %s", GetError()); + } + throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result"); } } @@ -130494,7 +143327,7 @@ unique_ptr PendingQueryResult::ExecuteInternal(ClientContextLock &l CheckExecutableInternal(lock); while (ExecuteTaskInternal(lock) == PendingExecutionResult::RESULT_NOT_READY) { } - if (!success) { + if (HasError()) { return make_unique(error); } auto result = context->FetchResultInternal(lock, *this); @@ -130525,12 +143358,21 @@ PreparedStatement::PreparedStatement(shared_ptr context, shared_p D_ASSERT(data || !success); } -PreparedStatement::PreparedStatement(string error) : context(nullptr), success(false), error(move(error)) { +PreparedStatement::PreparedStatement(PreservedError error) : context(nullptr), success(false), error(move(error)) { } PreparedStatement::~PreparedStatement() { } +const string &PreparedStatement::GetError() { + D_ASSERT(HasError()); + return error.Message(); +} + +bool PreparedStatement::HasError() const { + return !success; +} + idx_t PreparedStatement::ColumnCount() { D_ASSERT(data); return data->types.size(); @@ -130558,8 +143400,8 @@ const vector &PreparedStatement::GetNames() { unique_ptr PreparedStatement::Execute(vector &values, bool allow_stream_result) { auto pending = PendingQuery(values, allow_stream_result); - if (!pending->success) { - return make_unique(pending->error); + if (pending->HasError()) { + return make_unique(pending->GetErrorObject()); } return pending->Execute(); } @@ -130589,14 +143431,42 @@ PreparedStatementData::PreparedStatementData(StatementType type) : statement_typ PreparedStatementData::~PreparedStatementData() { } -void PreparedStatementData::Bind(vector values) { - // set parameters +void PreparedStatementData::CheckParameterCount(idx_t parameter_count) { const auto required = properties.parameter_count; - D_ASSERT(!unbound_statement || unbound_statement->n_param == properties.parameter_count); - if (values.size() != required) { + if (parameter_count != required) { throw BinderException("Parameter/argument count mismatch for prepared statement. Expected %llu, got %llu", - required, values.size()); + required, parameter_count); } +} + +bool PreparedStatementData::RequireRebind(ClientContext &context, const vector &values) { + CheckParameterCount(values.size()); + if (!unbound_statement) { + // no unbound statement!? cannot rebind? + return false; + } + if (!properties.bound_all_parameters) { + // parameters not yet bound: query always requires a rebind + return true; + } + auto &catalog = Catalog::GetCatalog(context); + if (catalog.GetCatalogVersion() != catalog_version) { + //! context is out of bounds + return true; + } + for (auto &it : value_map) { + const idx_t i = it.first - 1; + if (values[i].type() != it.second->return_type) { + return true; + } + } + return false; +} + +void PreparedStatementData::Bind(vector values) { + // set parameters + D_ASSERT(!unbound_statement || unbound_statement->n_param == properties.parameter_count); + CheckParameterCount(values.size()); // bind the required values for (auto &it : value_map) { @@ -130604,15 +143474,13 @@ void PreparedStatementData::Bind(vector values) { if (i >= values.size()) { throw BinderException("Could not find parameter with index %llu", i + 1); } - D_ASSERT(!it.second.empty()); - if (!values[i].TryCastAs(it.second[0]->type())) { + D_ASSERT(it.second); + if (!values[i].TryCastAs(it.second->return_type)) { throw BinderException( "Type mismatch for binding parameter with index %llu, expected type %s but got type %s", i + 1, - it.second[0]->type().ToString().c_str(), values[i].type().ToString().c_str()); - } - for (auto &target : it.second) { - *target = values[i]; + it.second->return_type.ToString().c_str(), values[i].type().ToString().c_str()); } + it.second->value = values[i]; } } @@ -130621,8 +143489,7 @@ LogicalType PreparedStatementData::GetType(idx_t param_idx) { if (it == value_map.end()) { throw BinderException("Could not find parameter with index %llu", param_idx); } - D_ASSERT(!it->second.empty()); - return it->second[0]->type(); + return it->second->return_type; } } // namespace duckdb @@ -130680,7 +143547,11 @@ bool QueryProfiler::IsDetailedEnabled() const { } ProfilerPrintFormat QueryProfiler::GetPrintFormat() const { - return is_explain_analyze ? ProfilerPrintFormat::NONE : ClientConfig::GetConfig(context).profiler_print_format; + return ClientConfig::GetConfig(context).profiler_print_format; +} + +bool QueryProfiler::PrintOptimizerOutput() const { + return GetPrintFormat() == ProfilerPrintFormat::QUERY_TREE_OPTIMIZER || IsDetailedEnabled(); } string QueryProfiler::GetSaveLocation() const { @@ -130691,13 +143562,22 @@ QueryProfiler &QueryProfiler::Get(ClientContext &context) { return *ClientData::Get(context).profiler; } -void QueryProfiler::StartQuery(string query, bool is_explain_analyze) { +void QueryProfiler::StartQuery(string query, bool is_explain_analyze, bool start_at_optimizer) { if (is_explain_analyze) { StartExplainAnalyze(); } if (!IsEnabled()) { return; } + if (start_at_optimizer && !PrintOptimizerOutput()) { + // This is the StartQuery call before the optimizer, but we don't have to print optimizer output + return; + } + if (running) { + // Called while already running: this should only happen when we print optimizer output + D_ASSERT(PrintOptimizerOutput()); + return; + } this->running = true; this->query = move(query); tree_map.clear(); @@ -130719,7 +143599,7 @@ bool QueryProfiler::OperatorRequiresProfiling(PhysicalOperatorType op_type) { case PhysicalOperatorType::TOP_N: case PhysicalOperatorType::WINDOW: case PhysicalOperatorType::UNNEST: - case PhysicalOperatorType::SIMPLE_AGGREGATE: + case PhysicalOperatorType::UNGROUPED_AGGREGATE: case PhysicalOperatorType::HASH_GROUP_BY: case PhysicalOperatorType::FILTER: case PhysicalOperatorType::PROJECTION: @@ -130768,20 +143648,14 @@ void QueryProfiler::EndQuery() { Finalize(*root); } this->running = false; - auto automatic_print_format = GetPrintFormat(); - // print or output the query profiling after termination, if this is enabled - if (automatic_print_format != ProfilerPrintFormat::NONE) { - // check if this query should be output based on the operator types - string query_info; - if (automatic_print_format == ProfilerPrintFormat::JSON) { - query_info = ToJSON(); - } else if (automatic_print_format == ProfilerPrintFormat::QUERY_TREE) { - query_info = ToString(); - } else if (automatic_print_format == ProfilerPrintFormat::QUERY_TREE_OPTIMIZER) { - query_info = ToString(true); - } + // print or output the query profiling after termination + // EXPLAIN ANALYSE should not be outputted by the profiler + if (IsEnabled() && !is_explain_analyze) { + string query_info = ToString(); auto save_location = GetSaveLocation(); - if (save_location.empty()) { + if (!ClientConfig::GetConfig(context).emit_profiler_output) { + // disable output + } else if (save_location.empty()) { Printer::Print(query_info); Printer::Print("\n"); } else { @@ -130790,6 +143664,18 @@ void QueryProfiler::EndQuery() { } this->is_explain_analyze = false; } +string QueryProfiler::ToString() const { + const auto format = GetPrintFormat(); + switch (format) { + case ProfilerPrintFormat::QUERY_TREE: + case ProfilerPrintFormat::QUERY_TREE_OPTIMIZER: + return QueryTreeToString(); + case ProfilerPrintFormat::JSON: + return ToJSON(); + default: + throw InternalException("Unknown ProfilerPrintFormat \"%s\"", format); + } +} void QueryProfiler::StartPhase(string new_phase) { if (!IsEnabled() || !running) { @@ -130981,13 +143867,13 @@ static string RenderTiming(double timing) { return timing_s + "s"; } -string QueryProfiler::ToString(bool print_optimizer_output) const { +string QueryProfiler::QueryTreeToString() const { std::stringstream str; - ToStream(str, print_optimizer_output); + QueryTreeToStream(str); return str.str(); } -void QueryProfiler::ToStream(std::ostream &ss, bool print_optimizer_output) const { +void QueryProfiler::QueryTreeToStream(std::ostream &ss) const { if (!IsEnabled()) { ss << "Query profiling is disabled. Call " "Connection::EnableProfiling() to enable profiling!"; @@ -131011,7 +143897,7 @@ void QueryProfiler::ToStream(std::ostream &ss, bool print_optimizer_output) cons ss << "│└───────────────────────────────────┘│\n"; ss << "└─────────────────────────────────────┘\n"; // print phase timings - if (print_optimizer_output) { + if (PrintOptimizerOutput()) { bool has_previous_phase = false; for (const auto &entry : GetOrderedPhaseTimings()) { if (!StringUtil::Contains(entry.first, " > ")) { @@ -131238,7 +144124,7 @@ void QueryProfiler::Render(const QueryProfiler::TreeNode &node, std::ostream &ss } void QueryProfiler::Print() { - Printer::Print(ToString()); + Printer::Print(QueryTreeToString()); } vector QueryProfiler::GetOrderedPhaseTimings() const { @@ -131305,8 +144191,6 @@ ExpressionRootInfo::ExpressionRootInfo(ExpressionExecutorState &state, string na root = move(expression_info_p); } } // namespace duckdb -#include - @@ -131321,28 +144205,52 @@ BaseQueryResult::BaseQueryResult(QueryResultType type, StatementType statement_t D_ASSERT(types.size() == names.size()); } -BaseQueryResult::BaseQueryResult(QueryResultType type, string error) : type(type), success(false), error(move(error)) { +BaseQueryResult::BaseQueryResult(QueryResultType type, PreservedError error) + : type(type), success(false), error(move(error)) { } BaseQueryResult::~BaseQueryResult() { } -bool BaseQueryResult::HasError() { +void BaseQueryResult::ThrowError(const string &prepended_message) const { + D_ASSERT(HasError()); + error.Throw(prepended_message); +} + +void BaseQueryResult::SetError(PreservedError error) { + success = !error; + this->error = move(error); +} + +bool BaseQueryResult::HasError() const { + D_ASSERT((bool)error == !success); return !success; } -const string &BaseQueryResult::GetError() { + +const ExceptionType &BaseQueryResult::GetErrorType() const { + return error.Type(); +} + +const std::string &BaseQueryResult::GetError() { + D_ASSERT(HasError()); + return error.Message(); +} + +PreservedError &BaseQueryResult::GetErrorObject() { return error; } + idx_t BaseQueryResult::ColumnCount() { return types.size(); } QueryResult::QueryResult(QueryResultType type, StatementType statement_type, StatementProperties properties, - vector types_p, vector names_p) - : BaseQueryResult(type, statement_type, properties, move(types_p), move(names_p)) { + vector types_p, vector names_p, ClientProperties client_properties_p) + : BaseQueryResult(type, statement_type, properties, move(types_p), move(names_p)), + client_properties(move(client_properties_p)) { } -QueryResult::QueryResult(QueryResultType type, string error) : BaseQueryResult(type, move(error)) { +QueryResult::QueryResult(QueryResultType type, PreservedError error) : BaseQueryResult(type, move(error)) { } QueryResult::~QueryResult() { @@ -131353,7 +144261,7 @@ unique_ptr QueryResult::Fetch() { if (!chunk) { return nullptr; } - chunk->Normalify(); + chunk->Flatten(); return chunk; } @@ -131398,6 +144306,9 @@ bool QueryResult::Equals(QueryResult &other) { // LCOV_EXCL_START if (lvalue.IsNull() && rvalue.IsNull()) { continue; } + if (lvalue.IsNull() != rvalue.IsNull()) { + return false; + } if (lvalue != rvalue) { return false; } @@ -131422,288 +144333,8 @@ string QueryResult::HeaderToString() { result += "\n"; return result; } - -struct DuckDBArrowSchemaHolder { - // unused in children - vector children; - // unused in children - vector children_ptrs; - //! used for nested structures - std::list> nested_children; - std::list> nested_children_ptr; - //! This holds strings created to represent decimal types - vector> owned_type_names; -}; - -static void ReleaseDuckDBArrowSchema(ArrowSchema *schema) { - if (!schema || !schema->release) { - return; - } - schema->release = nullptr; - auto holder = static_cast(schema->private_data); - delete holder; -} - -void InitializeChild(ArrowSchema &child, const string &name = "") { - //! Child is cleaned up by parent - child.private_data = nullptr; - child.release = ReleaseDuckDBArrowSchema; - - //! Store the child schema - child.flags = ARROW_FLAG_NULLABLE; - child.name = name.c_str(); - child.n_children = 0; - child.children = nullptr; - child.metadata = nullptr; - child.dictionary = nullptr; -} -void SetArrowFormat(DuckDBArrowSchemaHolder &root_holder, ArrowSchema &child, const LogicalType &type, - string &config_timezone); - -void SetArrowMapFormat(DuckDBArrowSchemaHolder &root_holder, ArrowSchema &child, const LogicalType &type, - string &config_timezone) { - child.format = "+m"; - //! Map has one child which is a struct - child.n_children = 1; - root_holder.nested_children.emplace_back(); - root_holder.nested_children.back().resize(1); - root_holder.nested_children_ptr.emplace_back(); - root_holder.nested_children_ptr.back().push_back(&root_holder.nested_children.back()[0]); - InitializeChild(root_holder.nested_children.back()[0]); - child.children = &root_holder.nested_children_ptr.back()[0]; - child.children[0]->name = "entries"; - child_list_t struct_child_types; - struct_child_types.push_back(std::make_pair("key", ListType::GetChildType(StructType::GetChildType(type, 0)))); - struct_child_types.push_back(std::make_pair("value", ListType::GetChildType(StructType::GetChildType(type, 1)))); - auto struct_type = LogicalType::STRUCT(move(struct_child_types)); - SetArrowFormat(root_holder, *child.children[0], struct_type, config_timezone); -} - -void SetArrowFormat(DuckDBArrowSchemaHolder &root_holder, ArrowSchema &child, const LogicalType &type, - string &config_timezone) { - switch (type.id()) { - case LogicalTypeId::BOOLEAN: - child.format = "b"; - break; - case LogicalTypeId::TINYINT: - child.format = "c"; - break; - case LogicalTypeId::SMALLINT: - child.format = "s"; - break; - case LogicalTypeId::INTEGER: - child.format = "i"; - break; - case LogicalTypeId::BIGINT: - child.format = "l"; - break; - case LogicalTypeId::UTINYINT: - child.format = "C"; - break; - case LogicalTypeId::USMALLINT: - child.format = "S"; - break; - case LogicalTypeId::UINTEGER: - child.format = "I"; - break; - case LogicalTypeId::UBIGINT: - child.format = "L"; - break; - case LogicalTypeId::FLOAT: - child.format = "f"; - break; - case LogicalTypeId::HUGEINT: - child.format = "d:38,0"; - break; - case LogicalTypeId::DOUBLE: - child.format = "g"; - break; - case LogicalTypeId::UUID: - case LogicalTypeId::JSON: - case LogicalTypeId::VARCHAR: - child.format = "u"; - break; - case LogicalTypeId::DATE: - child.format = "tdD"; - break; - case LogicalTypeId::TIME: - case LogicalTypeId::TIME_TZ: - child.format = "ttu"; - break; - case LogicalTypeId::TIMESTAMP: - child.format = "tsu:"; - break; - case LogicalTypeId::TIMESTAMP_TZ: { - string format = "tsu:" + config_timezone; - unique_ptr format_ptr = unique_ptr(new char[format.size() + 1]); - for (size_t i = 0; i < format.size(); i++) { - format_ptr[i] = format[i]; - } - format_ptr[format.size()] = '\0'; - root_holder.owned_type_names.push_back(move(format_ptr)); - child.format = root_holder.owned_type_names.back().get(); - break; - } - case LogicalTypeId::TIMESTAMP_SEC: - child.format = "tss:"; - break; - case LogicalTypeId::TIMESTAMP_NS: - child.format = "tsn:"; - break; - case LogicalTypeId::TIMESTAMP_MS: - child.format = "tsm:"; - break; - case LogicalTypeId::INTERVAL: - child.format = "tDm"; - break; - case LogicalTypeId::DECIMAL: { - uint8_t width, scale; - type.GetDecimalProperties(width, scale); - string format = "d:" + to_string(width) + "," + to_string(scale); - unique_ptr format_ptr = unique_ptr(new char[format.size() + 1]); - for (size_t i = 0; i < format.size(); i++) { - format_ptr[i] = format[i]; - } - format_ptr[format.size()] = '\0'; - root_holder.owned_type_names.push_back(move(format_ptr)); - child.format = root_holder.owned_type_names.back().get(); - break; - } - case LogicalTypeId::SQLNULL: { - child.format = "n"; - break; - } - case LogicalTypeId::BLOB: { - child.format = "z"; - break; - } - case LogicalTypeId::LIST: { - child.format = "+l"; - child.n_children = 1; - root_holder.nested_children.emplace_back(); - root_holder.nested_children.back().resize(1); - root_holder.nested_children_ptr.emplace_back(); - root_holder.nested_children_ptr.back().push_back(&root_holder.nested_children.back()[0]); - InitializeChild(root_holder.nested_children.back()[0]); - child.children = &root_holder.nested_children_ptr.back()[0]; - child.children[0]->name = "l"; - SetArrowFormat(root_holder, **child.children, ListType::GetChildType(type), config_timezone); - break; - } - case LogicalTypeId::STRUCT: { - child.format = "+s"; - auto &child_types = StructType::GetChildTypes(type); - child.n_children = child_types.size(); - root_holder.nested_children.emplace_back(); - root_holder.nested_children.back().resize(child_types.size()); - root_holder.nested_children_ptr.emplace_back(); - root_holder.nested_children_ptr.back().resize(child_types.size()); - for (idx_t type_idx = 0; type_idx < child_types.size(); type_idx++) { - root_holder.nested_children_ptr.back()[type_idx] = &root_holder.nested_children.back()[type_idx]; - } - child.children = &root_holder.nested_children_ptr.back()[0]; - for (size_t type_idx = 0; type_idx < child_types.size(); type_idx++) { - - InitializeChild(*child.children[type_idx]); - - auto &struct_col_name = child_types[type_idx].first; - unique_ptr name_ptr = unique_ptr(new char[struct_col_name.size() + 1]); - for (size_t i = 0; i < struct_col_name.size(); i++) { - name_ptr[i] = struct_col_name[i]; - } - name_ptr[struct_col_name.size()] = '\0'; - root_holder.owned_type_names.push_back(move(name_ptr)); - - child.children[type_idx]->name = root_holder.owned_type_names.back().get(); - SetArrowFormat(root_holder, *child.children[type_idx], child_types[type_idx].second, config_timezone); - } - break; - } - case LogicalTypeId::MAP: { - SetArrowMapFormat(root_holder, child, type, config_timezone); - break; - } - case LogicalTypeId::ENUM: { - // TODO what do we do with pointer enums here? - switch (EnumType::GetPhysicalType(type)) { - case PhysicalType::UINT8: - child.format = "C"; - break; - case PhysicalType::UINT16: - child.format = "S"; - break; - case PhysicalType::UINT32: - child.format = "I"; - break; - default: - throw InternalException("Unsupported Enum Internal Type"); - } - root_holder.nested_children.emplace_back(); - root_holder.nested_children.back().resize(1); - root_holder.nested_children_ptr.emplace_back(); - root_holder.nested_children_ptr.back().push_back(&root_holder.nested_children.back()[0]); - InitializeChild(root_holder.nested_children.back()[0]); - child.dictionary = root_holder.nested_children_ptr.back()[0]; - child.dictionary->format = "u"; - break; - } - default: - throw InternalException("Unsupported Arrow type " + type.ToString()); - } -} - -void QueryResult::ToArrowSchema(ArrowSchema *out_schema, vector &types, vector &names, - string &config_timezone) { - D_ASSERT(out_schema); - D_ASSERT(types.size() == names.size()); - idx_t column_count = types.size(); - // Allocate as unique_ptr first to cleanup properly on error - auto root_holder = make_unique(); - - // Allocate the children - root_holder->children.resize(column_count); - root_holder->children_ptrs.resize(column_count, nullptr); - for (size_t i = 0; i < column_count; ++i) { - root_holder->children_ptrs[i] = &root_holder->children[i]; - } - out_schema->children = root_holder->children_ptrs.data(); - out_schema->n_children = column_count; - - // Store the schema - out_schema->format = "+s"; // struct apparently - out_schema->flags = 0; - out_schema->metadata = nullptr; - out_schema->name = "duckdb_query_result"; - out_schema->dictionary = nullptr; - - // Configure all child schemas - for (idx_t col_idx = 0; col_idx < column_count; col_idx++) { - - auto &child = root_holder->children[col_idx]; - InitializeChild(child, names[col_idx]); - SetArrowFormat(*root_holder, child, types[col_idx], config_timezone); - } - - // Release ownership to caller - out_schema->private_data = root_holder.release(); - out_schema->release = ReleaseDuckDBArrowSchema; -} - string QueryResult::GetConfigTimezone(QueryResult &query_result) { - switch (query_result.type) { - case QueryResultType::MATERIALIZED_RESULT: { - auto actual_context = ((MaterializedQueryResult &)query_result).context.lock(); - if (!actual_context) { - throw std::runtime_error("This connection is closed"); - } - return ClientConfig::ExtractTimezoneFromConfig(actual_context->config); - } - case QueryResultType::STREAM_RESULT: { - return ClientConfig::ExtractTimezoneFromConfig(((StreamQueryResult &)query_result).context->config); - } - default: - throw std::runtime_error("Can't extract timezone configuration from query type "); - } + return query_result.client_properties.timezone; } } // namespace duckdb @@ -132193,6 +144824,7 @@ class DeleteRelation : public Relation { + namespace duckdb { class DeleteStatement : public SQLStatement { @@ -132203,6 +144835,8 @@ class DeleteStatement : public SQLStatement { unique_ptr table; vector> using_clauses; vector> returning_list; + //! CTEs + CommonTableExpressionMap cte_map; protected: DeleteStatement(const DeleteStatement &other); @@ -132296,6 +144930,7 @@ namespace duckdb { DistinctRelation::DistinctRelation(shared_ptr child_p) : Relation(child_p->context, RelationType::DISTINCT_RELATION), child(move(child_p)) { + D_ASSERT(child.get() != this); vector dummy_columns; context.GetContext()->TryBindRelation(*this, dummy_columns); } @@ -132449,7 +145084,7 @@ class FilterRelation : public Relation { namespace duckdb { -enum class SetOperationType : uint8_t { NONE = 0, UNION = 1, EXCEPT = 2, INTERSECT = 3 }; +enum class SetOperationType : uint8_t { NONE = 0, UNION = 1, EXCEPT = 2, INTERSECT = 3, UNION_BY_NAME = 4 }; } @@ -132545,6 +145180,7 @@ namespace duckdb { FilterRelation::FilterRelation(shared_ptr child_p, unique_ptr condition_p) : Relation(child_p->context, RelationType::FILTER_RELATION), condition(move(condition_p)), child(move(child_p)) { + D_ASSERT(child.get() != this); vector dummy_columns; context.GetContext()->TryBindRelation(*this, dummy_columns); } @@ -132636,6 +145272,7 @@ class InsertRelation : public Relation { + namespace duckdb { class ExpressionListRef; @@ -132656,6 +145293,9 @@ class InsertStatement : public SQLStatement { //! keep track of optional returningList if statement contains a RETURNING keyword vector> returning_list; + //! CTEs + CommonTableExpressionMap cte_map; + protected: InsertStatement(const InsertStatement &other); @@ -132902,6 +145542,7 @@ namespace duckdb { LimitRelation::LimitRelation(shared_ptr child_p, int64_t limit, int64_t offset) : Relation(child_p->context, RelationType::PROJECTION_RELATION), limit(limit), offset(offset), child(move(child_p)) { + D_ASSERT(child.get() != this); } unique_ptr LimitRelation::GetQueryNode() { @@ -132987,6 +145628,7 @@ namespace duckdb { OrderRelation::OrderRelation(shared_ptr child_p, vector orders) : Relation(child_p->context, RelationType::ORDER_RELATION), orders(move(orders)), child(move(child_p)) { + D_ASSERT(child.get() != this); // bind the expressions context.GetContext()->TryBindRelation(*this, this->columns); } @@ -133285,6 +145927,7 @@ class SetOpRelation : public Relation { + namespace duckdb { SetOpRelation::SetOpRelation(shared_ptr left_p, shared_ptr right_p, SetOperationType setop_type_p) @@ -133299,6 +145942,9 @@ SetOpRelation::SetOpRelation(shared_ptr left_p, shared_ptr r unique_ptr SetOpRelation::GetQueryNode() { auto result = make_unique(); + if (setop_type == SetOperationType::EXCEPT || setop_type == SetOperationType::INTERSECT) { + result->modifiers.push_back(make_unique()); + } result->left = left->GetQueryNode(); result->right = right->GetQueryNode(); result->setop_type = setop_type; @@ -133378,6 +146024,7 @@ namespace duckdb { SubqueryRelation::SubqueryRelation(shared_ptr child_p, string alias_p) : Relation(child_p->context, RelationType::SUBQUERY_RELATION), child(move(child_p)), alias(move(alias_p)) { + D_ASSERT(child.get() != this); vector dummy_columns; context.GetContext()->TryBindRelation(*this, dummy_columns); } @@ -133659,6 +146306,7 @@ void TableRelation::Delete(const string &condition) { + namespace duckdb { class UpdateStatement : public SQLStatement { @@ -133672,6 +146320,8 @@ class UpdateStatement : public SQLStatement { vector> expressions; //! keep track of optional returningList if statement contains a RETURNING keyword vector> returning_list; + //! CTEs + CommonTableExpressionMap cte_map; protected: UpdateStatement(const UpdateStatement &other); @@ -134209,8 +146859,9 @@ void Relation::Insert(const string &table_name) { void Relation::Insert(const string &schema_name, const string &table_name) { auto insert = make_shared(shared_from_this(), schema_name, table_name); auto res = insert->Execute(); - if (!res->success) { - throw Exception("Failed to insert into table '" + table_name + "': " + res->error); + if (res->HasError()) { + const string prepended_message = "Failed to insert into table '" + table_name + "': "; + res->ThrowError(prepended_message); } } @@ -134227,24 +146878,27 @@ void Relation::Create(const string &table_name) { void Relation::Create(const string &schema_name, const string &table_name) { auto create = make_shared(shared_from_this(), schema_name, table_name); auto res = create->Execute(); - if (!res->success) { - throw Exception("Failed to create table '" + table_name + "': " + res->error); + if (res->HasError()) { + const string prepended_message = "Failed to create table '" + table_name + "': "; + res->ThrowError(prepended_message); } } void Relation::WriteCSV(const string &csv_file) { auto write_csv = make_shared(shared_from_this(), csv_file); auto res = write_csv->Execute(); - if (!res->success) { - throw Exception("Failed to write '" + csv_file + "': " + res->error); + if (res->HasError()) { + const string prepended_message = "Failed to write '" + csv_file + "': "; + res->ThrowError(prepended_message); } } shared_ptr Relation::CreateView(const string &name, bool replace, bool temporary) { auto view = make_shared(shared_from_this(), name, replace, temporary); auto res = view->Execute(); - if (!res->success) { - throw Exception("Failed to create view '" + name + "': " + res->error); + if (res->HasError()) { + const string prepended_message = "Failed to create view '" + name + "': "; + res->ThrowError(prepended_message); } return shared_from_this(); } @@ -134324,7 +146978,7 @@ vector> Relation::GetAllDependencies() { if (cur->extra_dependencies) { all_dependencies.push_back(cur->extra_dependencies); } - cur = ChildRelation(); + cur = cur->ChildRelation(); } return all_dependencies; } @@ -134352,11 +147006,11 @@ namespace duckdb { void AccessModeSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { auto parameter = StringUtil::Lower(input.ToString()); if (parameter == "automatic") { - config.access_mode = AccessMode::AUTOMATIC; + config.options.access_mode = AccessMode::AUTOMATIC; } else if (parameter == "read_only") { - config.access_mode = AccessMode::READ_ONLY; + config.options.access_mode = AccessMode::READ_ONLY; } else if (parameter == "read_write") { - config.access_mode = AccessMode::READ_WRITE; + config.options.access_mode = AccessMode::READ_WRITE; } else { throw InvalidInputException( "Unrecognized parameter for option ACCESS_MODE \"%s\". Expected READ_ONLY or READ_WRITE.", parameter); @@ -134365,7 +147019,7 @@ void AccessModeSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value AccessModeSetting::GetSetting(ClientContext &context) { auto &config = DBConfig::GetConfig(context); - switch (config.access_mode) { + switch (config.options.access_mode) { case AccessMode::AUTOMATIC: return "automatic"; case AccessMode::READ_ONLY: @@ -134382,12 +147036,12 @@ Value AccessModeSetting::GetSetting(ClientContext &context) { //===--------------------------------------------------------------------===// void CheckpointThresholdSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { idx_t new_limit = DBConfig::ParseMemoryLimit(input.ToString()); - config.checkpoint_wal_size = new_limit; + config.options.checkpoint_wal_size = new_limit; } Value CheckpointThresholdSetting::GetSetting(ClientContext &context) { auto &config = DBConfig::GetConfig(context); - return Value(StringUtil::BytesToHumanReadableString(config.checkpoint_wal_size)); + return Value(StringUtil::BytesToHumanReadableString(config.options.checkpoint_wal_size)); } //===--------------------------------------------------------------------===// @@ -134396,13 +147050,13 @@ Value CheckpointThresholdSetting::GetSetting(ClientContext &context) { void DebugCheckpointAbort::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { auto checkpoint_abort = StringUtil::Lower(input.ToString()); if (checkpoint_abort == "none") { - config.checkpoint_abort = CheckpointAbort::NO_ABORT; + config.options.checkpoint_abort = CheckpointAbort::NO_ABORT; } else if (checkpoint_abort == "before_truncate") { - config.checkpoint_abort = CheckpointAbort::DEBUG_ABORT_BEFORE_TRUNCATE; + config.options.checkpoint_abort = CheckpointAbort::DEBUG_ABORT_BEFORE_TRUNCATE; } else if (checkpoint_abort == "before_header") { - config.checkpoint_abort = CheckpointAbort::DEBUG_ABORT_BEFORE_HEADER; + config.options.checkpoint_abort = CheckpointAbort::DEBUG_ABORT_BEFORE_HEADER; } else if (checkpoint_abort == "after_free_list_write") { - config.checkpoint_abort = CheckpointAbort::DEBUG_ABORT_AFTER_FREE_LIST_WRITE; + config.options.checkpoint_abort = CheckpointAbort::DEBUG_ABORT_AFTER_FREE_LIST_WRITE; } else { throw ParserException( "Unrecognized option for PRAGMA debug_checkpoint_abort, expected none, before_truncate or before_header"); @@ -134439,12 +147093,12 @@ Value DebugForceNoCrossProduct::GetSetting(ClientContext &context) { // Debug Many Free List blocks //===--------------------------------------------------------------------===// void DebugManyFreeListBlocks::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { - config.debug_many_free_list_blocks = input.GetValue(); + config.options.debug_many_free_list_blocks = input.GetValue(); } Value DebugManyFreeListBlocks::GetSetting(ClientContext &context) { auto &config = DBConfig::GetConfig(context); - return Value::BOOLEAN(config.debug_many_free_list_blocks); + return Value::BOOLEAN(config.options.debug_many_free_list_blocks); } //===--------------------------------------------------------------------===// @@ -134453,11 +147107,11 @@ Value DebugManyFreeListBlocks::GetSetting(ClientContext &context) { void DebugWindowMode::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { auto param = StringUtil::Lower(input.ToString()); if (param == "window") { - config.window_mode = WindowAggregationMode::WINDOW; + config.options.window_mode = WindowAggregationMode::WINDOW; } else if (param == "combine") { - config.window_mode = WindowAggregationMode::COMBINE; + config.options.window_mode = WindowAggregationMode::COMBINE; } else if (param == "separate") { - config.window_mode = WindowAggregationMode::SEPARATE; + config.options.window_mode = WindowAggregationMode::SEPARATE; } else { throw ParserException("Unrecognized option for PRAGMA debug_window_mode, expected window, combine or separate"); } @@ -134472,7 +147126,7 @@ Value DebugWindowMode::GetSetting(ClientContext &context) { //===--------------------------------------------------------------------===// void DefaultCollationSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { auto parameter = StringUtil::Lower(input.ToString()); - config.collation = parameter; + config.options.collation = parameter; } void DefaultCollationSetting::SetLocal(ClientContext &context, const Value &input) { @@ -134480,12 +147134,12 @@ void DefaultCollationSetting::SetLocal(ClientContext &context, const Value &inpu // bind the collation to verify that it exists ExpressionBinder::TestCollation(context, parameter); auto &config = DBConfig::GetConfig(context); - config.collation = parameter; + config.options.collation = parameter; } Value DefaultCollationSetting::GetSetting(ClientContext &context) { auto &config = DBConfig::GetConfig(context); - return Value(config.collation); + return Value(config.options.collation); } //===--------------------------------------------------------------------===// @@ -134494,9 +147148,9 @@ Value DefaultCollationSetting::GetSetting(ClientContext &context) { void DefaultOrderSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { auto parameter = StringUtil::Lower(input.ToString()); if (parameter == "ascending" || parameter == "asc") { - config.default_order_type = OrderType::ASCENDING; + config.options.default_order_type = OrderType::ASCENDING; } else if (parameter == "descending" || parameter == "desc") { - config.default_order_type = OrderType::DESCENDING; + config.options.default_order_type = OrderType::DESCENDING; } else { throw InvalidInputException("Unrecognized parameter for option DEFAULT_ORDER \"%s\". Expected ASC or DESC.", parameter); @@ -134505,7 +147159,7 @@ void DefaultOrderSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, cons Value DefaultOrderSetting::GetSetting(ClientContext &context) { auto &config = DBConfig::GetConfig(context); - switch (config.default_order_type) { + switch (config.options.default_order_type) { case OrderType::ASCENDING: return "asc"; case OrderType::DESCENDING: @@ -134522,10 +147176,10 @@ void DefaultNullOrderSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, auto parameter = StringUtil::Lower(input.ToString()); if (parameter == "nulls_first" || parameter == "nulls first" || parameter == "null first" || parameter == "first") { - config.default_null_order = OrderByNullType::NULLS_FIRST; + config.options.default_null_order = OrderByNullType::NULLS_FIRST; } else if (parameter == "nulls_last" || parameter == "nulls last" || parameter == "null last" || parameter == "last") { - config.default_null_order = OrderByNullType::NULLS_LAST; + config.options.default_null_order = OrderByNullType::NULLS_LAST; } else { throw ParserException( "Unrecognized parameter for option NULL_ORDER \"%s\", expected either NULLS FIRST or NULLS LAST", @@ -134535,7 +147189,7 @@ void DefaultNullOrderSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, Value DefaultNullOrderSetting::GetSetting(ClientContext &context) { auto &config = DBConfig::GetConfig(context); - switch (config.default_null_order) { + switch (config.options.default_null_order) { case OrderByNullType::NULLS_FIRST: return "nulls_first"; case OrderByNullType::NULLS_LAST: @@ -134559,13 +147213,13 @@ void DisabledOptimizersSetting::SetGlobal(DatabaseInstance *db, DBConfig &config } disabled_optimizers.insert(OptimizerTypeFromString(param)); } - config.disabled_optimizers = move(disabled_optimizers); + config.options.disabled_optimizers = move(disabled_optimizers); } Value DisabledOptimizersSetting::GetSetting(ClientContext &context) { auto &config = DBConfig::GetConfig(context); string result; - for (auto &optimizer : config.disabled_optimizers) { + for (auto &optimizer : config.options.disabled_optimizers) { if (!result.empty()) { result += ","; } @@ -134582,24 +147236,40 @@ void EnableExternalAccessSetting::SetGlobal(DatabaseInstance *db, DBConfig &conf if (db && new_value) { throw InvalidInputException("Cannot change enable_external_access setting while database is running"); } - config.enable_external_access = new_value; + config.options.enable_external_access = new_value; } Value EnableExternalAccessSetting::GetSetting(ClientContext &context) { auto &config = DBConfig::GetConfig(context); - return Value::BOOLEAN(config.enable_external_access); + return Value::BOOLEAN(config.options.enable_external_access); +} + +//===--------------------------------------------------------------------===// +// Allow Unsigned Extensions +//===--------------------------------------------------------------------===// +void AllowUnsignedExtensionsSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { + auto new_value = input.GetValue(); + if (db && new_value) { + throw InvalidInputException("Cannot change allow_unsigned_extensions setting while database is running"); + } + config.options.allow_unsigned_extensions = new_value; +} + +Value AllowUnsignedExtensionsSetting::GetSetting(ClientContext &context) { + auto &config = DBConfig::GetConfig(context); + return Value::BOOLEAN(config.options.allow_unsigned_extensions); } //===--------------------------------------------------------------------===// // Enable Object Cache //===--------------------------------------------------------------------===// void EnableObjectCacheSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { - config.object_cache_enable = input.GetValue(); + config.options.object_cache_enable = input.GetValue(); } Value EnableObjectCacheSetting::GetSetting(ClientContext &context) { auto &config = DBConfig::GetConfig(context); - return Value::BOOLEAN(config.object_cache_enable); + return Value::BOOLEAN(config.options.object_cache_enable); } //===--------------------------------------------------------------------===// @@ -134620,6 +147290,7 @@ void EnableProfilingSetting::SetLocal(ClientContext &context, const Value &input "Unrecognized print format %s, supported formats: [json, query_tree, query_tree_optimizer]", parameter); } config.enable_profiler = true; + config.emit_profiler_output = true; } Value EnableProfilingSetting::GetSetting(ClientContext &context) { @@ -134628,8 +147299,6 @@ Value EnableProfilingSetting::GetSetting(ClientContext &context) { return Value(); } switch (config.profiler_print_format) { - case ProfilerPrintFormat::NONE: - return Value("none"); case ProfilerPrintFormat::JSON: return Value("json"); case ProfilerPrintFormat::QUERY_TREE: @@ -134686,12 +147355,12 @@ Value ExplainOutputSetting::GetSetting(ClientContext &context) { // External Threads Setting //===--------------------------------------------------------------------===// void ExternalThreadsSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { - config.external_threads = input.GetValue(); + config.options.external_threads = input.GetValue(); } Value ExternalThreadsSetting::GetSetting(ClientContext &context) { auto &config = DBConfig::GetConfig(context); - return Value::BIGINT(config.external_threads); + return Value::BIGINT(config.options.external_threads); } //===--------------------------------------------------------------------===// @@ -134714,14 +147383,14 @@ Value FileSearchPathSetting::GetSetting(ClientContext &context) { void ForceCompressionSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { auto compression = StringUtil::Lower(input.ToString()); if (compression == "none") { - config.force_compression = CompressionType::COMPRESSION_AUTO; + config.options.force_compression = CompressionType::COMPRESSION_AUTO; } else { auto compression_type = CompressionTypeFromString(compression); if (compression_type == CompressionType::COMPRESSION_AUTO) { throw ParserException("Unrecognized option for PRAGMA force_compression, expected none, uncompressed, rle, " "dictionary, pfor, bitpacking or fsst"); } - config.force_compression = compression_type; + config.options.force_compression = compression_type; } } @@ -134729,6 +147398,19 @@ Value ForceCompressionSetting::GetSetting(ClientContext &context) { return Value(); } +//===--------------------------------------------------------------------===// +// Home Directory +//===--------------------------------------------------------------------===// +void HomeDirectorySetting::SetLocal(ClientContext &context, const Value &input) { + auto &config = ClientConfig::GetConfig(context); + config.home_directory = input.IsNull() ? input.ToString() : string(); +} + +Value HomeDirectorySetting::GetSetting(ClientContext &context) { + auto &config = ClientConfig::GetConfig(context); + return Value(config.home_directory); +} + //===--------------------------------------------------------------------===// // Log Query Path //===--------------------------------------------------------------------===// @@ -134765,15 +147447,15 @@ Value MaximumExpressionDepthSetting::GetSetting(ClientContext &context) { // Maximum Memory //===--------------------------------------------------------------------===// void MaximumMemorySetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { - config.maximum_memory = DBConfig::ParseMemoryLimit(input.ToString()); + config.options.maximum_memory = DBConfig::ParseMemoryLimit(input.ToString()); if (db) { - BufferManager::GetBufferManager(*db).SetLimit(config.maximum_memory); + BufferManager::GetBufferManager(*db).SetLimit(config.options.maximum_memory); } } Value MaximumMemorySetting::GetSetting(ClientContext &context) { auto &config = DBConfig::GetConfig(context); - return Value(StringUtil::BytesToHumanReadableString(config.maximum_memory)); + return Value(StringUtil::BytesToHumanReadableString(config.options.maximum_memory)); } //===--------------------------------------------------------------------===// @@ -134806,12 +147488,12 @@ Value PreserveIdentifierCase::GetSetting(ClientContext &context) { // PreserveInsertionOrder //===--------------------------------------------------------------------===// void PreserveInsertionOrder::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { - config.preserve_insertion_order = input.GetValue(); + config.options.preserve_insertion_order = input.GetValue(); } Value PreserveInsertionOrder::GetSetting(ClientContext &context) { auto &config = DBConfig::GetConfig(context); - return Value::BOOLEAN(config.preserve_insertion_order); + return Value::BOOLEAN(config.options.preserve_insertion_order); } //===--------------------------------------------------------------------===// @@ -134853,9 +147535,11 @@ void ProfilingModeSetting::SetLocal(ClientContext &context, const Value &input) if (parameter == "standard") { config.enable_profiler = true; config.enable_detailed_profiling = false; + config.emit_profiler_output = true; } else if (parameter == "detailed") { config.enable_profiler = true; config.enable_detailed_profiling = true; + config.emit_profiler_output = true; } else { throw ParserException("Unrecognized profiling mode \"%s\", supported formats: [standard, detailed]", parameter); } @@ -134912,11 +147596,11 @@ Value SearchPathSetting::GetSetting(ClientContext &context) { // Temp Directory //===--------------------------------------------------------------------===// void TempDirectorySetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { - config.temporary_directory = input.ToString(); - config.use_temporary_directory = !config.temporary_directory.empty(); + config.options.temporary_directory = input.ToString(); + config.options.use_temporary_directory = !config.options.temporary_directory.empty(); if (db) { auto &buffer_manager = BufferManager::GetBufferManager(*db); - buffer_manager.SetTemporaryDirectory(config.temporary_directory); + buffer_manager.SetTemporaryDirectory(config.options.temporary_directory); } } @@ -134929,15 +147613,15 @@ Value TempDirectorySetting::GetSetting(ClientContext &context) { // Threads Setting //===--------------------------------------------------------------------===// void ThreadsSetting::SetGlobal(DatabaseInstance *db, DBConfig &config, const Value &input) { - config.maximum_threads = input.GetValue(); + config.options.maximum_threads = input.GetValue(); if (db) { - TaskScheduler::GetScheduler(*db).SetThreads(config.maximum_threads); + TaskScheduler::GetScheduler(*db).SetThreads(config.options.maximum_threads); } } Value ThreadsSetting::GetSetting(ClientContext &context) { auto &config = DBConfig::GetConfig(context); - return Value::BIGINT(config.maximum_threads); + return Value::BIGINT(config.options.maximum_threads); } } // namespace duckdb @@ -134949,9 +147633,12 @@ Value ThreadsSetting::GetSetting(ClientContext &context) { namespace duckdb { StreamQueryResult::StreamQueryResult(StatementType statement_type, StatementProperties properties, - shared_ptr context, vector types, vector names) - : QueryResult(QueryResultType::STREAM_RESULT, statement_type, properties, move(types), move(names)), - context(move(context)) { + shared_ptr context_p, vector types, + vector names) + : QueryResult(QueryResultType::STREAM_RESULT, statement_type, properties, move(types), move(names), + context_p->GetClientProperties()), + context(move(context_p)) { + D_ASSERT(context); } StreamQueryResult::~StreamQueryResult() { @@ -134963,23 +147650,29 @@ string StreamQueryResult::ToString() { result = HeaderToString(); result += "[[STREAM RESULT]]"; } else { - result = error + "\n"; + result = GetError() + "\n"; } return result; } unique_ptr StreamQueryResult::LockContext() { if (!context) { - throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result\nError: %s", - error); + string error_str = "Attempting to execute an unsuccessful or closed pending query result"; + if (HasError()) { + error_str += StringUtil::Format("\nError: %s", GetError()); + } + throw InvalidInputException(error_str); } return context->LockContext(); } void StreamQueryResult::CheckExecutableInternal(ClientContextLock &lock) { if (!IsOpenInternal(lock)) { - throw InvalidInputException("Attempting to execute an unsuccessful or closed pending query result\nError: %s", - error); + string error_str = "Attempting to execute an unsuccessful or closed pending query result"; + if (HasError()) { + error_str += StringUtil::Format("\nError: %s", GetError()); + } + throw InvalidInputException(error_str); } } @@ -134998,19 +147691,24 @@ unique_ptr StreamQueryResult::FetchRaw() { } unique_ptr StreamQueryResult::Materialize() { - if (!success) { - return make_unique(error); + if (HasError() || !context) { + return make_unique(GetErrorObject()); } - auto result = make_unique(statement_type, properties, types, names, context); + auto collection = make_unique(Allocator::DefaultAllocator(), types); + + ColumnDataAppendState append_state; + collection->InitializeAppend(append_state); while (true) { auto chunk = Fetch(); if (!chunk || chunk->size() == 0) { break; } - result->collection.Append(*chunk); + collection->Append(append_state, *chunk); } - if (!success) { - return make_unique(error); + auto result = + make_unique(statement_type, properties, names, move(collection), client_properties); + if (HasError()) { + return make_unique(GetErrorObject()); } return result; } @@ -135035,6 +147733,798 @@ void StreamQueryResult::Close() { context.reset(); } +} // namespace duckdb + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/optimizer/join_order_optimizer.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/optimizer/cardinality_estimator.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + + +namespace duckdb { + +struct RelationAttributes { + string original_name; + // the relation columns used in join filters + // Needed when iterating over columns and initializing total domain values. + unordered_set columns; + double cardinality; +}; + +struct RelationsToTDom { + //! column binding sets that are equivalent in a join plan. + //! if you have A.x = B.y and B.y = C.z, then one set is {A.x, B.y, C.z}. + column_binding_set_t equivalent_relations; + //! the estimated total domains of the equivalent relations determined using HLL + idx_t tdom_hll; + //! the estimated total domains of each relation without using HLL + idx_t tdom_no_hll; + bool has_tdom_hll; + vector filters; + + RelationsToTDom(column_binding_set_t column_binding_set) + : equivalent_relations(column_binding_set), tdom_hll(0), tdom_no_hll(NumericLimits::Maximum()), + has_tdom_hll(false) {}; +}; + +struct NodeOp { + unique_ptr node; + LogicalOperator *op; + + NodeOp(unique_ptr node, LogicalOperator *op) : node(move(node)), op(op) {}; +}; + +struct Subgraph2Denominator { + unordered_set relations; + double denom; + + Subgraph2Denominator() : relations(), denom(1) {}; +}; + +class CardinalityEstimator { +public: + explicit CardinalityEstimator(ClientContext &context) : context(context) { + } + +private: + ClientContext &context; + + //! A mapping of relation id -> RelationAttributes + unordered_map relation_attributes; + //! A mapping of (relation, bound_column) -> (actual table, actual column) + column_binding_map_t relation_column_to_original_column; + + vector relations_to_tdoms; + + static constexpr double DEFAULT_SELECTIVITY = 0.2; + +public: + static void VerifySymmetry(JoinNode *result, JoinNode *entry); + + void AssertEquivalentRelationSize(); + + //! given a binding of (relation, column) used for DP, and a (table, column) in that catalog + //! Add the key value entry into the relation_column_to_original_column + void AddRelationToColumnMapping(ColumnBinding key, ColumnBinding value); + //! Add a column to the relation_to_columns map. + void AddColumnToRelationMap(idx_t table_index, idx_t column_index); + //! Dump all bindings in relation_column_to_original_column into the child_binding_map + // If you have a non-reorderable join, this function is used to keep track of bindings + // in the child join plan. + void CopyRelationMap(column_binding_map_t &child_binding_map); + void MergeBindings(idx_t, idx_t relation_id, vector> &child_binding_maps); + void AddRelationColumnMapping(LogicalGet *get, idx_t relation_id); + + void InitTotalDomains(); + void UpdateTotalDomains(JoinNode *node, LogicalOperator *op); + void InitEquivalentRelations(vector> *filter_infos); + + void InitCardinalityEstimatorProps(vector *node_ops, vector> *filter_infos); + double EstimateCardinalityWithSet(JoinRelationSet *new_set); + void EstimateBaseTableCardinality(JoinNode *node, LogicalOperator *op); + double EstimateCrossProduct(const JoinNode *left, const JoinNode *right); + static double ComputeCost(JoinNode *left, JoinNode *right, double expected_cardinality); + +private: + bool SingleColumnFilter(FilterInfo *filter_info); + //! Filter & bindings -> list of indexes into the equivalent_relations array. + // The column binding set at each index is an equivalence set. + vector DetermineMatchingEquivalentSets(FilterInfo *filter_info); + + //! Given a filter, add the column bindings to the matching equivalent set at the index + //! given in matching equivalent sets. + //! If there are multiple equivalence sets, they are merged. + void AddToEquivalenceSets(FilterInfo *filter_info, vector matching_equivalent_sets); + + TableFilterSet *GetTableFilters(LogicalOperator *op); + + idx_t InspectConjunctionAND(idx_t cardinality, idx_t column_index, ConjunctionAndFilter *fil, + unique_ptr base_stats); + idx_t InspectConjunctionOR(idx_t cardinality, idx_t column_index, ConjunctionOrFilter *fil, + unique_ptr base_stats); + idx_t InspectTableFilters(idx_t cardinality, LogicalOperator *op, TableFilterSet *table_filters); +}; + +} // namespace duckdb + + +#include + +namespace duckdb { + +class JoinOrderOptimizer { +public: + explicit JoinOrderOptimizer(ClientContext &context) + : context(context), cardinality_estimator(context), full_plan_found(false), must_update_full_plan(false) { + } + + //! Perform join reordering inside a plan + unique_ptr Optimize(unique_ptr plan); + + unique_ptr CreateJoinTree(JoinRelationSet *set, const vector &possible_connections, + JoinNode *left, JoinNode *right); + +private: + ClientContext &context; + //! The total amount of join pairs that have been considered + idx_t pairs = 0; + //! Set of all relations considered in the join optimizer + vector> relations; + //! A mapping of base table index -> index into relations array (relation number) + unordered_map relation_mapping; + //! A structure holding all the created JoinRelationSet objects + JoinRelationSetManager set_manager; + //! The set of edges used in the join optimizer + QueryGraph query_graph; + //! The optimal join plan found for the specific JoinRelationSet* + unordered_map> plans; + + //! The set of filters extracted from the query graph + vector> filters; + //! The set of filter infos created from the extracted filters + vector> filter_infos; + //! A map of all expressions a given expression has to be equivalent to. This is used to add "implied join edges". + //! i.e. in the join A=B AND B=C, the equivalence set of {B} is {A, C}, thus we can add an implied join edge {A <-> + //! C} + expression_map_t> equivalence_sets; + + CardinalityEstimator cardinality_estimator; + + bool full_plan_found; + bool must_update_full_plan; + unordered_set join_nodes_in_full_plan; + + //! Extract the bindings referred to by an Expression + bool ExtractBindings(Expression &expression, unordered_set &bindings); + + //! Get column bindings from a filter + void GetColumnBinding(Expression &expression, ColumnBinding &binding); + + //! Traverse the query tree to find (1) base relations, (2) existing join conditions and (3) filters that can be + //! rewritten into joins. Returns true if there are joins in the tree that can be reordered, false otherwise. + bool ExtractJoinRelations(LogicalOperator &input_op, vector &filter_operators, + LogicalOperator *parent = nullptr); + + //! Emit a pair as a potential join candidate. Returns the best plan found for the (left, right) connection (either + //! the newly created plan, or an existing plan) + JoinNode *EmitPair(JoinRelationSet *left, JoinRelationSet *right, const vector &info); + //! Tries to emit a potential join candidate pair. Returns false if too many pairs have already been emitted, + //! cancelling the dynamic programming step. + bool TryEmitPair(JoinRelationSet *left, JoinRelationSet *right, const vector &info); + + bool EnumerateCmpRecursive(JoinRelationSet *left, JoinRelationSet *right, unordered_set exclusion_set); + //! Emit a relation set node + bool EmitCSG(JoinRelationSet *node); + //! Enumerate the possible connected subgraphs that can be joined together in the join graph + bool EnumerateCSGRecursive(JoinRelationSet *node, unordered_set &exclusion_set); + //! Rewrite a logical query plan given the join plan + unique_ptr RewritePlan(unique_ptr plan, JoinNode *node); + //! Generate cross product edges inside the side + void GenerateCrossProducts(); + //! Perform the join order solving + void SolveJoinOrder(); + //! Solve the join order exactly using dynamic programming. Returns true if it was completed successfully (i.e. did + //! not time-out) + bool SolveJoinOrderExactly(); + //! Solve the join order approximately using a greedy algorithm + void SolveJoinOrderApproximately(); + + void UpdateDPTree(JoinNode *new_plan); + + void UpdateJoinNodesInFullPlan(JoinNode *node); + + std::pair> + GenerateJoins(vector> &extracted_relations, JoinNode *node); +}; + +} // namespace duckdb + + + + + + + + +namespace duckdb { + +static TableCatalogEntry *GetCatalogTableEntry(LogicalOperator *op) { + if (op->type == LogicalOperatorType::LOGICAL_GET) { + auto get = (LogicalGet *)op; + TableCatalogEntry *entry = get->GetTable(); + return entry; + } + for (auto &child : op->children) { + TableCatalogEntry *entry = GetCatalogTableEntry(child.get()); + if (entry != nullptr) { + return entry; + } + } + return nullptr; +} + +bool CardinalityEstimator::SingleColumnFilter(FilterInfo *filter_info) { + if (filter_info->left_set && filter_info->right_set) { + // Both set + return false; + } + // Filter on one relation, (i.e string or range filter on a column). + // Grab the first relation and add it to the the equivalence_relations + D_ASSERT(filter_info->set->count >= 1); + for (const RelationsToTDom &r2tdom : relations_to_tdoms) { + auto &i_set = r2tdom.equivalent_relations; + if (i_set.find(filter_info->left_binding) != i_set.end()) { + // found an equivalent filter + return true; + } + } + auto key = ColumnBinding(filter_info->left_binding.table_index, filter_info->left_binding.column_index); + column_binding_set_t tmp({key}); + relations_to_tdoms.emplace_back(RelationsToTDom(tmp)); + return true; +} + +vector CardinalityEstimator::DetermineMatchingEquivalentSets(FilterInfo *filter_info) { + vector matching_equivalent_sets; + auto equivalent_relation_index = 0; + + for (const RelationsToTDom &r2tdom : relations_to_tdoms) { + auto &i_set = r2tdom.equivalent_relations; + if (i_set.find(filter_info->left_binding) != i_set.end()) { + matching_equivalent_sets.push_back(equivalent_relation_index); + } else if (i_set.find(filter_info->right_binding) != i_set.end()) { + // don't add both left and right to the matching_equivalent_sets + // since both left and right get added to that index anyway. + matching_equivalent_sets.push_back(equivalent_relation_index); + } + equivalent_relation_index++; + } + return matching_equivalent_sets; +} + +void CardinalityEstimator::AddToEquivalenceSets(FilterInfo *filter_info, vector matching_equivalent_sets) { + D_ASSERT(matching_equivalent_sets.size() <= 2); + if (matching_equivalent_sets.size() > 1) { + // an equivalence relation is connecting to sets of equivalence relations + // so push all relations from the second set into the first. Later we will delete + // the second set. + for (ColumnBinding i : relations_to_tdoms.at(matching_equivalent_sets[1]).equivalent_relations) { + relations_to_tdoms.at(matching_equivalent_sets[0]).equivalent_relations.insert(i); + } + relations_to_tdoms.at(matching_equivalent_sets[1]).equivalent_relations.clear(); + relations_to_tdoms.at(matching_equivalent_sets[0]).filters.push_back(filter_info); + // add all values of one set to the other, delete the empty one + } else if (matching_equivalent_sets.size() == 1) { + auto &tdom_i = relations_to_tdoms.at(matching_equivalent_sets.at(0)); + tdom_i.equivalent_relations.insert(filter_info->left_binding); + tdom_i.equivalent_relations.insert(filter_info->right_binding); + tdom_i.filters.push_back(filter_info); + } else if (matching_equivalent_sets.empty()) { + column_binding_set_t tmp; + tmp.insert(filter_info->left_binding); + tmp.insert(filter_info->right_binding); + relations_to_tdoms.emplace_back(RelationsToTDom(tmp)); + relations_to_tdoms.back().filters.push_back(filter_info); + } +} + +void CardinalityEstimator::AddRelationToColumnMapping(ColumnBinding key, ColumnBinding value) { + relation_column_to_original_column[key] = value; +} + +void CardinalityEstimator::CopyRelationMap(column_binding_map_t &child_binding_map) { + for (auto &binding_map : relation_column_to_original_column) { + child_binding_map[binding_map.first] = binding_map.second; + } +} + +void CardinalityEstimator::AddColumnToRelationMap(idx_t table_index, idx_t column_index) { + relation_attributes[table_index].columns.insert(column_index); +} + +void CardinalityEstimator::InitEquivalentRelations(vector> *filter_infos) { + // For each filter, we fill keep track of the index of the equivalent relation set + // the left and right relation needs to be added to. + for (auto &filter : *filter_infos) { + if (SingleColumnFilter(filter.get())) { + continue; + } + D_ASSERT(filter->left_set->count >= 1); + D_ASSERT(filter->right_set->count >= 1); + + auto matching_equivalent_sets = DetermineMatchingEquivalentSets(filter.get()); + AddToEquivalenceSets(filter.get(), matching_equivalent_sets); + } +} + +void CardinalityEstimator::VerifySymmetry(JoinNode *result, JoinNode *entry) { + if (result->GetCardinality() != entry->GetCardinality()) { + // Currently it's possible that some entries are cartesian joins. + // When this is the case, you don't always have symmetry, but + // if the cost of the result is less, then just assure the cardinality + // is also less, then you have the same effect of symmetry. + D_ASSERT(ceil(result->GetCardinality()) <= ceil(entry->GetCardinality()) || + floor(result->GetCardinality()) <= floor(entry->GetCardinality())); + } +} + +void CardinalityEstimator::InitTotalDomains() { + auto remove_start = std::remove_if(relations_to_tdoms.begin(), relations_to_tdoms.end(), + [](RelationsToTDom &r_2_tdom) { return r_2_tdom.equivalent_relations.empty(); }); + relations_to_tdoms.erase(remove_start, relations_to_tdoms.end()); +} + +double CardinalityEstimator::ComputeCost(JoinNode *left, JoinNode *right, double expected_cardinality) { + return expected_cardinality + left->GetCost() + right->GetCost(); +} + +double CardinalityEstimator::EstimateCrossProduct(const JoinNode *left, const JoinNode *right) { + // need to explicity use double here, otherwise auto converts it to an int, then + // there is an autocast in the return. + return left->GetCardinality() >= (NumericLimits::Maximum() / right->GetCardinality()) + ? NumericLimits::Maximum() + : left->GetCardinality() * right->GetCardinality(); +} + +void CardinalityEstimator::AddRelationColumnMapping(LogicalGet *get, idx_t relation_id) { + for (idx_t it = 0; it < get->column_ids.size(); it++) { + auto key = ColumnBinding(relation_id, it); + auto value = ColumnBinding(get->table_index, get->column_ids[it]); + AddRelationToColumnMapping(key, value); + } +} + +void UpdateDenom(Subgraph2Denominator *relation_2_denom, RelationsToTDom *relation_to_tdom) { + relation_2_denom->denom *= + relation_to_tdom->has_tdom_hll ? relation_to_tdom->tdom_hll : relation_to_tdom->tdom_no_hll; +} + +void FindSubgraphMatchAndMerge(Subgraph2Denominator &merge_to, idx_t find_me, + vector::iterator subgraph, + vector::iterator end) { + for (; subgraph != end; subgraph++) { + if (subgraph->relations.count(find_me) >= 1) { + for (auto &relation : subgraph->relations) { + merge_to.relations.insert(relation); + } + subgraph->relations.clear(); + merge_to.denom *= subgraph->denom; + return; + } + } +} + +double CardinalityEstimator::EstimateCardinalityWithSet(JoinRelationSet *new_set) { + double numerator = 1; + unordered_set actual_set; + for (idx_t i = 0; i < new_set->count; i++) { + numerator *= relation_attributes[new_set->relations[i]].cardinality; + actual_set.insert(new_set->relations[i]); + } + vector subgraphs; + bool done = false; + bool found_match = false; + + // Finding the denominator is tricky. You need to go through the tdoms in decreasing order + // Then loop through all filters in the equivalence set of the tdom to see if both the + // left and right relations are in the new set, if so you can use that filter. + // You must also make sure that the filters all relations in the given set, so we use subgraphs + // that should eventually merge into one connected graph that joins all the relations + // TODO: Don't implement a method to cache subgraphs so you don't have to build them up every + // time the cardinality of a new set is requested + + // relations_to_tdoms has already been sorted. + for (auto &relation_2_tdom : relations_to_tdoms) { + // loop through each filter in the tdom. + if (done) { + break; + } + for (auto &filter : relation_2_tdom.filters) { + if (actual_set.count(filter->left_binding.table_index) == 0 || + actual_set.count(filter->right_binding.table_index) == 0) { + continue; + } + // the join filter is on relations in the new set. + found_match = false; + vector::iterator it; + for (it = subgraphs.begin(); it != subgraphs.end(); it++) { + auto left_in = it->relations.count(filter->left_binding.table_index); + auto right_in = it->relations.count(filter->right_binding.table_index); + if (left_in && right_in) { + // if both left and right bindings are in the subgraph, continue. + // This means another filter is connecting relations already in the + // subgraph it, but it has a tdom that is less, and we don't care. + found_match = true; + continue; + } + if (!left_in && !right_in) { + // if both left and right bindings are *not* in the subgraph, continue + // without finding a match. This will trigger the process to add a new + // subgraph + continue; + } + idx_t find_table; + if (left_in) { + find_table = filter->right_binding.table_index; + } else { + D_ASSERT(right_in); + find_table = filter->left_binding.table_index; + } + auto next_subgraph = it + 1; + // iterate through other subgraphs and merge. + FindSubgraphMatchAndMerge(*it, find_table, next_subgraph, subgraphs.end()); + // Now insert the right binding and update denominator with the + // tdom of the filter + it->relations.insert(find_table); + UpdateDenom(&(*it), &relation_2_tdom); + found_match = true; + break; + } + // means that the filter joins relations in the given set, but there is no + // connection to any subgraph in subgraphs. Add a new subgraph, and maybe later there will be + // a connection. + if (!found_match) { + subgraphs.emplace_back(Subgraph2Denominator()); + auto subgraph = &subgraphs.back(); + subgraph->relations.insert(filter->left_binding.table_index); + subgraph->relations.insert(filter->right_binding.table_index); + UpdateDenom(subgraph, &relation_2_tdom); + } + auto remove_start = std::remove_if(subgraphs.begin(), subgraphs.end(), + [](Subgraph2Denominator &s) { return s.relations.empty(); }); + subgraphs.erase(remove_start, subgraphs.end()); + + if (subgraphs.size() == 1 && subgraphs.at(0).relations.size() == new_set->count) { + // You have found enough filters to connect the relations. These are guaranteed + // to be the filters with the highest Tdoms. + done = true; + break; + } + } + } + double denom = 1; + // TODO: It's possible cross-products were added and are not present in the filters in the relation_2_tdom + // structures. When that's the case, multiply the denom structures that have no intersection + for (auto &match : subgraphs) { + // It's possible that in production, one of the D_ASSERTS above will fail and not all subgraphs + // were connected. When this happens, just use the largest denominator of all the subgraphs. + if (match.denom > denom) { + denom = match.denom; + } + } + // can happen if a table has cardinality 0, or a tdom is set to 0 + if (denom == 0) { + denom = 1; + } + return numerator / denom; +} + +static bool IsLogicalFilter(LogicalOperator *op) { + return op->type == LogicalOperatorType::LOGICAL_FILTER; +} + +static LogicalGet *GetLogicalGet(LogicalOperator *op) { + LogicalGet *get = nullptr; + switch (op->type) { + case LogicalOperatorType::LOGICAL_GET: + get = (LogicalGet *)op; + break; + case LogicalOperatorType::LOGICAL_FILTER: + get = GetLogicalGet(op->children.at(0).get()); + break; + case LogicalOperatorType::LOGICAL_PROJECTION: + get = GetLogicalGet(op->children.at(0).get()); + break; + case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: { + LogicalComparisonJoin *join = (LogicalComparisonJoin *)op; + if (join->join_type == JoinType::MARK || join->join_type == JoinType::LEFT) { + auto child = join->children.at(0).get(); + get = GetLogicalGet(child); + } + break; + } + default: + // return null pointer, maybe there is no logical get under this child + break; + } + return get; +} + +void CardinalityEstimator::MergeBindings(idx_t binding_index, idx_t relation_id, + vector> &child_binding_maps) { + for (auto &map_set : child_binding_maps) { + for (auto &mapping : map_set) { + ColumnBinding relation_bindings = mapping.first; + ColumnBinding actual_bindings = mapping.second; + + if (actual_bindings.table_index == binding_index) { + auto key = ColumnBinding(relation_id, relation_bindings.column_index); + AddRelationToColumnMapping(key, actual_bindings); + } + } + } +} + +bool SortTdoms(const RelationsToTDom &a, const RelationsToTDom &b) { + if (a.has_tdom_hll && b.has_tdom_hll) { + return a.tdom_hll > b.tdom_hll; + } + if (a.has_tdom_hll) { + return a.tdom_hll > b.tdom_no_hll; + } + if (b.has_tdom_hll) { + return a.tdom_no_hll > b.tdom_hll; + } + return a.tdom_no_hll > b.tdom_no_hll; +} + +void CardinalityEstimator::InitCardinalityEstimatorProps(vector *node_ops, + vector> *filter_infos) { + InitEquivalentRelations(filter_infos); + InitTotalDomains(); + for (idx_t i = 0; i < node_ops->size(); i++) { + auto join_node = (*node_ops)[i].node.get(); + auto op = (*node_ops)[i].op; + join_node->SetBaseTableCardinality(op->EstimateCardinality(context)); + if (op->type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN) { + auto &join = (LogicalComparisonJoin &)*op; + if (join.join_type == JoinType::LEFT) { + // TODO: inspect child operators to get a more accurate cost + // and cardinality estimation. If an base op is a Logical Comparison join + // it is probably a left join, so cost of the larger table is a fine + // estimate + // No need to update a mark join cost because I say so. + join_node->SetCost(join_node->GetBaseTableCardinality()); + } + } + // update cardinality with filters + EstimateBaseTableCardinality(join_node, op); + UpdateTotalDomains(join_node, op); + } + + // sort relations from greatest tdom to lowest tdom. + std::sort(relations_to_tdoms.begin(), relations_to_tdoms.end(), SortTdoms); +} + +void CardinalityEstimator::UpdateTotalDomains(JoinNode *node, LogicalOperator *op) { + auto relation_id = node->set->relations[0]; + relation_attributes[relation_id].cardinality = node->GetCardinality(); + TableCatalogEntry *catalog_table = nullptr; + auto get = GetLogicalGet(op); + if (get) { + catalog_table = GetCatalogTableEntry(get); + } + + //! Initialize the tdoms for all columns the relation uses in join conditions. + unordered_set::iterator ite; + idx_t count = node->GetBaseTableCardinality(); + + bool direct_filter = false; + for (auto &column : relation_attributes[relation_id].columns) { + //! for every column in the relation, get the count via either HLL, or assume it to be + //! the cardinality + ColumnBinding key = ColumnBinding(relation_id, column); + + if (catalog_table) { + relation_attributes[relation_id].original_name = catalog_table->name; + // Get HLL stats here + auto actual_binding = relation_column_to_original_column[key]; + + // sometimes base stats is null (test_709.test) returns null for base stats while + // there is still a catalog table. Anybody know anything about this? + auto base_stats = catalog_table->storage->GetStatistics(context, actual_binding.column_index); + if (base_stats) { + count = base_stats->GetDistinctCount(); + } + + // means you have a direct filter on a column. The count/total domain for the column + // should be decreased to match the predicted total domain matching the filter. + // We decrease the total domain for all columns in the equivalence set because filter pushdown + // will mean all columns are affected. + if (direct_filter) { + count = node->GetCardinality(); + } + + // HLL has estimation error, count can't be greater than cardinality of the table before filters + if (count > node->GetBaseTableCardinality()) { + count = node->GetBaseTableCardinality(); + } + } else { + // No HLL. So if we know there is a direct filter, reduce count to cardinality with filter + // otherwise assume the total domain is still the cardinality + if (direct_filter) { + count = node->GetCardinality(); + } else { + count = node->GetBaseTableCardinality(); + } + } + + for (auto &relation_to_tdom : relations_to_tdoms) { + column_binding_set_t i_set = relation_to_tdom.equivalent_relations; + if (i_set.count(key) != 1) { + continue; + } + if (catalog_table) { + if (relation_to_tdom.tdom_hll < count) { + relation_to_tdom.tdom_hll = count; + relation_to_tdom.has_tdom_hll = true; + } + if (relation_to_tdom.tdom_no_hll > count) { + relation_to_tdom.tdom_no_hll = count; + } + } else { + // Here we don't have catalog statistics, and the following is how we determine + // the tdom + // 1. If there is any hll data in the equivalence set, use that + // 2. Otherwise, use the table with the smallest cardinality + if (relation_to_tdom.tdom_no_hll > count && !relation_to_tdom.has_tdom_hll) { + relation_to_tdom.tdom_no_hll = count; + } + } + break; + } + } +} + +TableFilterSet *CardinalityEstimator::GetTableFilters(LogicalOperator *op) { + // First check table filters + auto get = GetLogicalGet(op); + return get ? &get->table_filters : nullptr; +} + +idx_t CardinalityEstimator::InspectConjunctionAND(idx_t cardinality, idx_t column_index, ConjunctionAndFilter *filter, + unique_ptr base_stats) { + auto has_equality_filter = false; + auto cardinality_after_filters = cardinality; + for (auto &child_filter : filter->child_filters) { + if (child_filter->filter_type != TableFilterType::CONSTANT_COMPARISON) { + continue; + } + auto comparison_filter = (ConstantFilter &)*child_filter; + if (comparison_filter.comparison_type != ExpressionType::COMPARE_EQUAL) { + continue; + } + auto column_count = 0; + if (base_stats) { + column_count = base_stats->GetDistinctCount(); + } + auto filtered_card = cardinality; + // column_count = 0 when there is no column count (i.e parquet scans) + if (column_count > 0) { + // we want the ceil of cardinality/column_count. We also want to avoid compiler errors + filtered_card = (cardinality + column_count - 1) / column_count; + cardinality_after_filters = filtered_card; + } + if (has_equality_filter) { + cardinality_after_filters = MinValue(filtered_card, cardinality_after_filters); + } + has_equality_filter = true; + } + return cardinality_after_filters; +} + +idx_t CardinalityEstimator::InspectConjunctionOR(idx_t cardinality, idx_t column_index, ConjunctionOrFilter *filter, + unique_ptr base_stats) { + auto has_equality_filter = false; + auto cardinality_after_filters = cardinality; + for (auto &child_filter : filter->child_filters) { + if (child_filter->filter_type != TableFilterType::CONSTANT_COMPARISON) { + continue; + } + auto comparison_filter = (ConstantFilter &)*child_filter; + if (comparison_filter.comparison_type == ExpressionType::COMPARE_EQUAL) { + auto column_count = cardinality_after_filters; + if (base_stats) { + column_count = base_stats->GetDistinctCount(); + } + auto increment = MaxValue(((cardinality + column_count - 1) / column_count), 1); + if (has_equality_filter) { + cardinality_after_filters += increment; + } else { + cardinality_after_filters = increment; + } + has_equality_filter = true; + } + } + D_ASSERT(cardinality_after_filters > 0); + return cardinality_after_filters; +} + +idx_t CardinalityEstimator::InspectTableFilters(idx_t cardinality, LogicalOperator *op, TableFilterSet *table_filters) { + idx_t cardinality_after_filters = cardinality; + auto get = GetLogicalGet(op); + unique_ptr column_statistics; + for (auto &it : table_filters->filters) { + column_statistics = nullptr; + if (get->bind_data && get->function.name.compare("seq_scan") == 0) { + auto &table_scan_bind_data = (TableScanBindData &)*get->bind_data; + column_statistics = get->function.statistics(context, &table_scan_bind_data, it.first); + } + if (it.second->filter_type == TableFilterType::CONJUNCTION_AND) { + auto &filter = (ConjunctionAndFilter &)*it.second; + idx_t cardinality_with_and_filter = + InspectConjunctionAND(cardinality, it.first, &filter, move(column_statistics)); + cardinality_after_filters = MinValue(cardinality_after_filters, cardinality_with_and_filter); + } else if (it.second->filter_type == TableFilterType::CONJUNCTION_OR) { + auto &filter = (ConjunctionOrFilter &)*it.second; + idx_t cardinality_with_or_filter = + InspectConjunctionOR(cardinality, it.first, &filter, move(column_statistics)); + cardinality_after_filters = MinValue(cardinality_after_filters, cardinality_with_or_filter); + } + } + // if the above code didn't find an equality filter (i.e country_code = "[us]") + // and there are other table filters, use default selectivity. + bool has_equality_filter = (cardinality_after_filters != cardinality); + if (!has_equality_filter && !table_filters->filters.empty()) { + cardinality_after_filters = MaxValue(cardinality * DEFAULT_SELECTIVITY, 1); + } + return cardinality_after_filters; +} + +void CardinalityEstimator::EstimateBaseTableCardinality(JoinNode *node, LogicalOperator *op) { + auto has_logical_filter = IsLogicalFilter(op); + auto table_filters = GetTableFilters(op); + + auto card_after_filters = node->GetBaseTableCardinality(); + // Logical Filter on a seq scan + if (has_logical_filter) { + card_after_filters *= DEFAULT_SELECTIVITY; + } else if (table_filters) { + double inspect_result = (double)InspectTableFilters(card_after_filters, op, table_filters); + card_after_filters = MinValue(inspect_result, (double)card_after_filters); + } + node->SetEstimatedCardinality(card_after_filters); +} + } // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -135264,41 +148754,6 @@ class CommonAggregateOptimizer : public LogicalOperatorVisitor { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/parser/expression_map.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - -namespace duckdb { -class Expression; - -struct ExpressionHashFunction { - uint64_t operator()(const BaseExpression *const &expr) const { - return (uint64_t)expr->Hash(); - } -}; - -struct ExpressionEquality { - bool operator()(const BaseExpression *const &a, const BaseExpression *const &b) const { - return a->Equals(b); - } -}; - -template -using expression_map_t = unordered_map; - -using expression_set_t = unordered_set; - -} // namespace duckdb @@ -135823,6 +149278,27 @@ bool Deliminator::RemoveCandidate(unique_ptr *op_ptr, Deliminat } } // namespace duckdb + + + +namespace duckdb { + +double EstimatedProperties::GetCardinality() { + return cardinality; +} +double EstimatedProperties::GetCost() { + return cost; +} + +void EstimatedProperties::SetCardinality(double new_card) { + cardinality = new_card; +} + +void EstimatedProperties::SetCost(double new_cost) { + cost = new_cost; +} + +} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB // @@ -136091,6 +149567,7 @@ idx_t ExpressionHeuristics::Cost(Expression &expr) { + namespace duckdb { unique_ptr ExpressionRewriter::ApplyRules(LogicalOperator &op, const vector &rules, @@ -136125,12 +149602,14 @@ unique_ptr ExpressionRewriter::ApplyRules(LogicalOperator &op, const unique_ptr ExpressionRewriter::ConstantOrNull(unique_ptr child, Value value) { vector> children; + children.push_back(make_unique(value)); children.push_back(move(child)); return ConstantOrNull(move(children), move(value)); } unique_ptr ExpressionRewriter::ConstantOrNull(vector> children, Value value) { auto type = value.type(); + children.insert(children.begin(), make_unique(value)); return make_unique(type, ConstantOrNull::GetFunction(type), move(children), ConstantOrNull::Bind(move(value))); } @@ -136170,214 +149649,6 @@ void ExpressionRewriter::VisitExpression(unique_ptr *expression) { } } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/optimizer/filter_combiner.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/filter/conjunction_filter.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { -class ConjunctionFilter : public TableFilter { -public: - ConjunctionFilter(TableFilterType filter_type_p) : TableFilter(filter_type_p) { - } - - virtual ~ConjunctionFilter() { - } - - //! The filters of this conjunction - vector> child_filters; - -public: - virtual FilterPropagateResult CheckStatistics(BaseStatistics &stats) = 0; - virtual string ToString(const string &column_name) = 0; - - virtual bool Equals(const TableFilter &other) const { - return TableFilter::Equals(other); - } -}; - -class ConjunctionOrFilter : public ConjunctionFilter { -public: - ConjunctionOrFilter(); - -public: - FilterPropagateResult CheckStatistics(BaseStatistics &stats) override; - string ToString(const string &column_name) override; - bool Equals(const TableFilter &other) const override; -}; - -class ConjunctionAndFilter : public ConjunctionFilter { -public: - ConjunctionAndFilter(); - -public: - FilterPropagateResult CheckStatistics(BaseStatistics &stats) override; - string ToString(const string &column_name) override; - bool Equals(const TableFilter &other) const override; -}; - -} // namespace duckdb - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/filter/constant_filter.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - -namespace duckdb { - -class ConstantFilter : public TableFilter { -public: - ConstantFilter(ExpressionType comparison_type, Value constant); - - //! The comparison type (e.g. COMPARE_EQUAL, COMPARE_GREATERTHAN, COMPARE_LESSTHAN, ...) - ExpressionType comparison_type; - //! The constant value to filter on - Value constant; - -public: - FilterPropagateResult CheckStatistics(BaseStatistics &stats) override; - string ToString(const string &column_name) override; - bool Equals(const TableFilter &other) const override; -}; - -} // namespace duckdb - - - -#include -#include - -namespace duckdb { - -enum class ValueComparisonResult { PRUNE_LEFT, PRUNE_RIGHT, UNSATISFIABLE_CONDITION, PRUNE_NOTHING }; -enum class FilterResult { UNSATISFIABLE, SUCCESS, UNSUPPORTED }; - -//! The FilterCombiner combines several filters and generates a logically equivalent set that is more efficient -//! Amongst others: -//! (1) it prunes obsolete filter conditions: i.e. [X > 5 and X > 7] => [X > 7] -//! (2) it generates new filters for expressions in the same equivalence set: i.e. [X = Y and X = 500] => [Y = 500] -//! (3) it prunes branches that have unsatisfiable filters: i.e. [X = 5 AND X > 6] => FALSE, prune branch -class FilterCombiner { -public: - struct ExpressionValueInformation { - Value constant; - ExpressionType comparison_type; - }; - - FilterResult AddFilter(unique_ptr expr); - - void GenerateFilters(const std::function filter)> &callback); - bool HasFilters(); - TableFilterSet GenerateTableScanFilters(vector &column_ids); - // vector> GenerateZonemapChecks(vector &column_ids, vector> - // &pushed_filters); - -private: - FilterResult AddFilter(Expression *expr); - FilterResult AddBoundComparisonFilter(Expression *expr); - FilterResult AddTransitiveFilters(BoundComparisonExpression &comparison); - unique_ptr FindTransitiveFilter(Expression *expr); - // unordered_map> - // FindZonemapChecks(vector &column_ids, unordered_set ¬_constants, Expression *filter); - Expression *GetNode(Expression *expr); - idx_t GetEquivalenceSet(Expression *expr); - FilterResult AddConstantComparison(vector &info_list, ExpressionValueInformation info); - // - // //! Functions used to push and generate OR Filters - // void LookUpConjunctions(Expression *expr); - // bool BFSLookUpConjunctions(BoundConjunctionExpression *conjunction); - // void VerifyOrsToPush(Expression &expr); - // - // bool UpdateConjunctionFilter(BoundComparisonExpression *comparison_expr); - // bool UpdateFilterByColumn(BoundColumnRefExpression *column_ref, BoundComparisonExpression *comparison_expr); - // void GenerateORFilters(TableFilterSet &table_filter, vector &column_ids); - // - // template - // void GenerateConjunctionFilter(BoundConjunctionExpression *conjunction, ConjunctionFilter *last_conj_filter) { - // auto new_filter = NextConjunctionFilter(conjunction); - // auto conj_filter_ptr = (ConjunctionFilter *)new_filter.get(); - // last_conj_filter->child_filters.push_back(move(new_filter)); - // last_conj_filter = conj_filter_ptr; - // } - // - // template - // unique_ptr NextConjunctionFilter(BoundConjunctionExpression *conjunction) { - // unique_ptr conj_filter = make_unique(); - // for (auto &expr : conjunction->children) { - // auto comp_expr = (BoundComparisonExpression *)expr.get(); - // auto &const_expr = - // (comp_expr->left->type == ExpressionType::VALUE_CONSTANT) ? *comp_expr->left : *comp_expr->right; - // auto const_value = ExpressionExecutor::EvaluateScalar(const_expr); - // auto const_filter = make_unique(comp_expr->type, const_value); - // conj_filter->child_filters.push_back(move(const_filter)); - // } - // return move(conj_filter); - // } - -private: - vector> remaining_filters; - - expression_map_t> stored_expressions; - unordered_map equivalence_set_map; - unordered_map> constant_values; - unordered_map> equivalence_map; - idx_t set_index = 0; - // - // //! Structures used for OR Filters - // - // struct ConjunctionsToPush { - // BoundConjunctionExpression *root_or; - // - // // only preserve AND if there is a single column in the expression - // bool preserve_and = true; - // - // // conjunction chain for this column - // vector> conjunctions; - // }; - // - // expression_map_t>> map_col_conjunctions; - // vector vec_colref_insertion_order; - // - // BoundConjunctionExpression *cur_root_or; - // BoundConjunctionExpression *cur_conjunction; - // - // BoundColumnRefExpression *cur_colref_to_push; -}; - -} // namespace duckdb - - @@ -136390,39 +149661,9 @@ class FilterCombiner { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/filter/null_filter.hpp -// -// -//===----------------------------------------------------------------------===// - - - -namespace duckdb { -class IsNullFilter : public TableFilter { -public: - IsNullFilter(); - -public: - FilterPropagateResult CheckStatistics(BaseStatistics &stats) override; - string ToString(const string &column_name) override; -}; - -class IsNotNullFilter : public TableFilter { -public: - IsNotNullFilter(); - -public: - FilterPropagateResult CheckStatistics(BaseStatistics &stats) override; - string ToString(const string &column_name) override; -}; - -} // namespace duckdb @@ -137616,7 +150857,6 @@ ValueComparisonResult CompareValueInformation(ExpressionValueInformation &left, - namespace duckdb { class FilterPullup { @@ -137987,13 +151227,15 @@ void FilterPushdown::Filter::ExtractBindings() { namespace duckdb { +class ClientContext; class Optimizer; class InClauseRewriter : public LogicalOperatorVisitor { public: - explicit InClauseRewriter(Optimizer &optimizer) : optimizer(optimizer) { + explicit InClauseRewriter(ClientContext &context, Optimizer &optimizer) : context(context), optimizer(optimizer) { } + ClientContext &context; Optimizer &optimizer; unique_ptr root; @@ -138069,11 +151311,14 @@ unique_ptr InClauseRewriter::VisitReplace(BoundOperatorExpression &e } // IN clause with many constant children // generate a mark join that replaces this IN expression - // first generate a ChunkCollection from the set of expressions + // first generate a ColumnDataCollection from the set of expressions vector types = {in_type}; - auto collection = make_unique(); + auto collection = make_unique(context, types); + ColumnDataAppendState append_state; + collection->InitializeAppend(append_state); + DataChunk chunk; - chunk.Initialize(types); + chunk.Initialize(context, types); for (idx_t i = 1; i < expr.children.size(); i++) { // resolve this expression to a constant auto value = ExpressionExecutor::EvaluateScalar(*expr.children[i]); @@ -138082,13 +151327,13 @@ unique_ptr InClauseRewriter::VisitReplace(BoundOperatorExpression &e chunk.SetValue(0, index, value); if (chunk.size() == STANDARD_VECTOR_SIZE || i + 1 == expr.children.size()) { // chunk full: append to chunk collection - collection->Append(chunk); + collection->Append(append_state, chunk); chunk.Reset(); } } // now generate a ChunkGet that scans this collection auto chunk_index = optimizer.binder.GenerateTableIndex(); - auto chunk_scan = make_unique(chunk_index, types, move(collection)); + auto chunk_scan = make_unique(chunk_index, types, move(collection)); // then we generate the MARK join with the chunk scan on the RHS auto join = make_unique(JoinType::MARK); @@ -138117,13 +151362,44 @@ unique_ptr InClauseRewriter::VisitReplace(BoundOperatorExpression &e } } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/optimizer/join_order/join_relation.hpp -// -// -//===----------------------------------------------------------------------===// + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -138132,59 +151408,73 @@ unique_ptr InClauseRewriter::VisitReplace(BoundOperatorExpression &e namespace duckdb { -class LogicalOperator; -//! Represents a single relation and any metadata accompanying that relation -struct SingleJoinRelation { - LogicalOperator *op; - LogicalOperator *parent; +JoinNode::JoinNode(JoinRelationSet *set, const double base_cardinality) + : set(set), info(nullptr), has_filter(false), left(nullptr), right(nullptr), base_cardinality(base_cardinality) { + estimated_props = make_unique(base_cardinality, 0); +} - SingleJoinRelation() { - } - SingleJoinRelation(LogicalOperator *op, LogicalOperator *parent) : op(op), parent(parent) { - } -}; +JoinNode::JoinNode(JoinRelationSet *set, NeighborInfo *info, JoinNode *left, JoinNode *right, + const double base_cardinality, double cost) + : set(set), info(info), has_filter(false), left(left), right(right), base_cardinality(base_cardinality) { + estimated_props = make_unique(base_cardinality, cost); +} -//! Set of relations, used in the join graph. -struct JoinRelationSet { - JoinRelationSet(unique_ptr relations, idx_t count) : relations(move(relations)), count(count) { - } +unique_ptr EstimatedProperties::Copy() { + auto result = make_unique(cardinality, cost); + return result; +} - string ToString() const; +double JoinNode::GetCardinality() const { + return estimated_props->GetCardinality(); +} - unique_ptr relations; - idx_t count; +double JoinNode::GetCost() { + return estimated_props->GetCost(); +} - static bool IsSubset(JoinRelationSet *super, JoinRelationSet *sub); -}; +void JoinNode::SetCost(double cost) { + estimated_props->SetCost(cost); +} -//! The JoinRelationTree is a structure holding all the created JoinRelationSet objects and allowing fast lookup on to -//! them -class JoinRelationSetManager { -public: - //! Contains a node with a JoinRelationSet and child relations - // FIXME: this structure is inefficient, could use a bitmap for lookup instead (todo: profile) - struct JoinRelationTreeNode { - unique_ptr relation; - unordered_map> children; - }; +double JoinNode::GetBaseTableCardinality() { + if (set->count > 1) { + throw InvalidInputException("Cannot call get base table cardinality on intermediate join node"); + } + return base_cardinality; +} -public: - //! Create or get a JoinRelationSet from a single node with the given index - JoinRelationSet *GetJoinRelation(idx_t index); - //! Create or get a JoinRelationSet from a set of relation bindings - JoinRelationSet *GetJoinRelation(unordered_set &bindings); - //! Create or get a JoinRelationSet from a (sorted, duplicate-free!) list of relations - JoinRelationSet *GetJoinRelation(unique_ptr relations, idx_t count); - //! Union two sets of relations together and create a new relation set - JoinRelationSet *Union(JoinRelationSet *left, JoinRelationSet *right); - // //! Create the set difference of left \ right (i.e. all elements in left that are not in right) - // JoinRelationSet *Difference(JoinRelationSet *left, JoinRelationSet *right); +void JoinNode::SetBaseTableCardinality(double base_card) { + base_cardinality = base_card; +} -private: - JoinRelationTreeNode root; -}; +void JoinNode::SetEstimatedCardinality(double estimated_card) { + estimated_props->SetCardinality(estimated_card); +} +string JoinNode::ToString() { + if (!set) { + return ""; + } + string result = "-------------------------------\n"; + result += set->ToString() + "\n"; + result += "card = " + to_string(GetCardinality()) + "\n"; + bool is_cartesian = false; + if (left && right) { + is_cartesian = (GetCardinality() == left->GetCardinality() * right->GetCardinality()); + } + result += "cartesian = " + to_string(is_cartesian) + "\n"; + result += "cost = " + to_string(estimated_props->GetCost()) + "\n"; + result += "left = \n"; + if (left) { + result += left->ToString(); + } + result += "right = \n"; + if (right) { + result += right->ToString(); + } + return result; +} } // namespace duckdb @@ -138332,76 +151622,6 @@ JoinRelationSet *JoinRelationSetManager::Union(JoinRelationSet *left, JoinRelati // } } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/optimizer/join_order/query_graph.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - - - -#include - -namespace duckdb { -class Expression; -class LogicalOperator; - -struct FilterInfo { - idx_t filter_index; - JoinRelationSet *left_set = nullptr; - JoinRelationSet *right_set = nullptr; - JoinRelationSet *set = nullptr; -}; - -struct FilterNode { - vector filters; - unordered_map> children; -}; - -struct NeighborInfo { - JoinRelationSet *neighbor; - vector filters; -}; - -//! The QueryGraph contains edges between relations and allows edges to be created/queried -class QueryGraph { -public: - //! Contains a node with info about neighboring relations and child edge infos - struct QueryEdge { - vector> neighbors; - unordered_map> children; - }; - -public: - string ToString() const; - void Print(); - - //! Create an edge in the edge_set - void CreateEdge(JoinRelationSet *left, JoinRelationSet *right, FilterInfo *info); - //! Returns a connection if there is an edge that connects these two sets, or nullptr otherwise - NeighborInfo *GetConnection(JoinRelationSet *node, JoinRelationSet *other); - //! Enumerate the neighbors of a specific node that do not belong to any of the exclusion_set. Note that if a - //! neighbor has multiple nodes, this function will return the lowest entry in that set. - vector GetNeighbors(JoinRelationSet *node, unordered_set &exclusion_set); - //! Enumerate all neighbors of a given JoinRelationSet node - void EnumerateNeighbors(JoinRelationSet *node, const std::function &callback); - -private: - //! Get the QueryEdge of a specific node - QueryEdge *GetQueryEdge(JoinRelationSet *left); - - QueryEdge root; -}; - -} // namespace duckdb @@ -138520,29 +151740,18 @@ vector QueryGraph::GetNeighbors(JoinRelationSet *node, unordered_set QueryGraph::GetConnections(JoinRelationSet *node, JoinRelationSet *other) { + vector connections; EnumerateNeighbors(node, [&](NeighborInfo *info) -> bool { if (JoinRelationSet::IsSubset(other, info->neighbor)) { - connection = info; - return true; + connections.push_back(info); } return false; }); - return connection; + return connections; } } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/optimizer/join_order_optimizer.hpp -// -// -//===----------------------------------------------------------------------===// - - - @@ -138551,152 +151760,21 @@ NeighborInfo *QueryGraph::GetConnection(JoinRelationSet *node, JoinRelationSet * -#include - -namespace duckdb { - -class JoinOrderOptimizer { -public: - //! Represents a node in the join plan - struct JoinNode { - JoinRelationSet *set; - NeighborInfo *info; - idx_t cardinality; - idx_t cost; - JoinNode *left; - JoinNode *right; +#include - //! Create a leaf node in the join tree - JoinNode(JoinRelationSet *set, idx_t cardinality) - : set(set), info(nullptr), cardinality(cardinality), cost(cardinality), left(nullptr), right(nullptr) { - } - //! Create an intermediate node in the join tree - JoinNode(JoinRelationSet *set, NeighborInfo *info, JoinNode *left, JoinNode *right, idx_t cardinality, - idx_t cost) - : set(set), info(info), cardinality(cardinality), cost(cost), left(left), right(right) { - } - }; +namespace std { -public: - explicit JoinOrderOptimizer(ClientContext &context) : context(context) { +//! A JoinNode is defined by the relations it joins. +template <> +struct hash { + inline string operator()(const duckdb::JoinNode &join_node) const { + return join_node.set->ToString(); } - - //! Perform join reordering inside a plan - unique_ptr Optimize(unique_ptr plan); - -private: - ClientContext &context; - //! The total amount of join pairs that have been considered - idx_t pairs = 0; - //! Set of all relations considered in the join optimizer - vector> relations; - //! A mapping of base table index -> index into relations array (relation number) - unordered_map relation_mapping; - //! A structure holding all the created JoinRelationSet objects - JoinRelationSetManager set_manager; - //! The set of edges used in the join optimizer - QueryGraph query_graph; - //! The optimal join plan found for the specific JoinRelationSet* - unordered_map> plans; - //! The set of filters extracted from the query graph - vector> filters; - //! The set of filter infos created from the extracted filters - vector> filter_infos; - //! A map of all expressions a given expression has to be equivalent to. This is used to add "implied join edges". - //! i.e. in the join A=B AND B=C, the equivalence set of {B} is {A, C}, thus we can add an implied join edge {A <-> - //! C} - expression_map_t> equivalence_sets; - - //! Extract the bindings referred to by an Expression - bool ExtractBindings(Expression &expression, unordered_set &bindings); - //! Traverse the query tree to find (1) base relations, (2) existing join conditions and (3) filters that can be - //! rewritten into joins. Returns true if there are joins in the tree that can be reordered, false otherwise. - bool ExtractJoinRelations(LogicalOperator &input_op, vector &filter_operators, - LogicalOperator *parent = nullptr); - //! Emit a pair as a potential join candidate. Returns the best plan found for the (left, right) connection (either - //! the newly created plan, or an existing plan) - JoinNode *EmitPair(JoinRelationSet *left, JoinRelationSet *right, NeighborInfo *info); - //! Tries to emit a potential join candidate pair. Returns false if too many pairs have already been emitted, - //! cancelling the dynamic programming step. - bool TryEmitPair(JoinRelationSet *left, JoinRelationSet *right, NeighborInfo *info); - - bool EnumerateCmpRecursive(JoinRelationSet *left, JoinRelationSet *right, unordered_set exclusion_set); - //! Emit a relation set node - bool EmitCSG(JoinRelationSet *node); - //! Enumerate the possible connected subgraphs that can be joined together in the join graph - bool EnumerateCSGRecursive(JoinRelationSet *node, unordered_set &exclusion_set); - //! Rewrite a logical query plan given the join plan - unique_ptr RewritePlan(unique_ptr plan, JoinNode *node); - //! Generate cross product edges inside the side - void GenerateCrossProducts(); - //! Perform the join order solving - void SolveJoinOrder(); - //! Solve the join order exactly using dynamic programming. Returns true if it was completed successfully (i.e. did - //! not time-out) - bool SolveJoinOrderExactly(); - //! Solve the join order approximately using a greedy algorithm - void SolveJoinOrderApproximately(); - - unique_ptr ResolveJoinConditions(unique_ptr op); - std::pair> - GenerateJoins(vector> &extracted_relations, JoinNode *node); }; - -} // namespace duckdb - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -#include +} // namespace std namespace duckdb { -using JoinNode = JoinOrderOptimizer::JoinNode; - //! Returns true if A and B are disjoint, false otherwise template static bool Disjoint(unordered_set &a, unordered_set &b) { @@ -138716,6 +151794,9 @@ bool JoinOrderOptimizer::ExtractBindings(Expression &expression, unordered_set PushFilter(unique_ptr node, unique_ptr expr) { // push an expression into a filter // first check if we have any filter to push it into @@ -138809,9 +151905,18 @@ bool JoinOrderOptimizer::ExtractJoinRelations(LogicalOperator &input_op, vector< // e.g. suppose we have (left LEFT OUTER JOIN right WHERE right IS NOT NULL), the join can generate // new NULL values in the right side, so pushing this condition through the join leads to incorrect results // for this reason, we just start a new JoinOptimizer pass in each of the children of the join + + // Keep track of all of the filter bindings the new join order optimizer makes + vector> child_binding_maps; + idx_t child_bindings_it = 0; for (auto &child : op->children) { + child_binding_maps.emplace_back(column_binding_map_t()); JoinOrderOptimizer optimizer(context); child = optimizer.Optimize(move(child)); + // save the relation bindings from the optimized child. These later all get added to the + // parent cardinality_estimator relation column binding map. + optimizer.cardinality_estimator.CopyRelationMap(child_binding_maps.at(child_bindings_it)); + child_bindings_it += 1; } // after this we want to treat this node as one "end node" (like e.g. a base relation) // however the join refers to multiple base relations @@ -138822,8 +151927,11 @@ bool JoinOrderOptimizer::ExtractJoinRelations(LogicalOperator &input_op, vector< LogicalJoin::GetTableReferences(*op, bindings); // now create the relation that refers to all these bindings auto relation = make_unique(&input_op, parent); + auto relation_id = relations.size(); + // Add binding information from the nonreorderable join to this relation. for (idx_t it : bindings) { - relation_mapping[it] = relations.size(); + cardinality_estimator.MergeBindings(it, relation_id, child_binding_maps); + relation_mapping[it] = relation_id; } relations.push_back(move(relation)); return true; @@ -138838,14 +151946,21 @@ bool JoinOrderOptimizer::ExtractJoinRelations(LogicalOperator &input_op, vector< // base table scan, add to set of relations auto get = (LogicalGet *)op; auto relation = make_unique(&input_op, parent); - relation_mapping[get->table_index] = relations.size(); + idx_t relation_id = relations.size(); + //! make sure the optimizer has knowledge of the exact column bindings as well. + auto table_index = get->table_index; + relation_mapping[table_index] = relation_id; + cardinality_estimator.AddRelationColumnMapping(get, relation_id); relations.push_back(move(relation)); return true; } else if (op->type == LogicalOperatorType::LOGICAL_EXPRESSION_GET) { // base table scan, add to set of relations auto get = (LogicalExpressionGet *)op; auto relation = make_unique(&input_op, parent); - relation_mapping[get->table_index] = relations.size(); + idx_t relation_id = relations.size(); + //! make sure the optimizer has knowledge of the exact column bindings as well. + auto table_index = get->table_index; + relation_mapping[table_index] = relation_id; relations.push_back(move(relation)); return true; } else if (op->type == LogicalOperatorType::LOGICAL_DUMMY_SCAN) { @@ -138877,31 +151992,55 @@ static void UpdateExclusionSet(JoinRelationSet *node, unordered_set &excl } //! Create a new JoinTree node by joining together two previous JoinTree nodes -static unique_ptr CreateJoinTree(JoinRelationSet *set, NeighborInfo *info, JoinNode *left, JoinNode *right) { +unique_ptr JoinOrderOptimizer::CreateJoinTree(JoinRelationSet *set, + const vector &possible_connections, + JoinNode *left, JoinNode *right) { // for the hash join we want the right side (build side) to have the smallest cardinality // also just a heuristic but for now... // FIXME: we should probably actually benchmark that as well // FIXME: should consider different join algorithms, should we pick a join algorithm here as well? (probably) - if (left->cardinality < right->cardinality) { - return CreateJoinTree(set, info, right, left); - } - // the expected cardinality is the max of the child cardinalities - // FIXME: we should obviously use better cardinality estimation here - // but for now we just assume foreign key joins only - idx_t expected_cardinality; - if (info->filters.empty()) { + double expected_cardinality; + NeighborInfo *best_connection = nullptr; + auto plan = plans.find(set); + // if we have already calculated an expected cardinality for this set, + // just re-use that cardinality + if (left->GetCardinality() < right->GetCardinality()) { + return CreateJoinTree(set, possible_connections, right, left); + } + if (plan != plans.end()) { + expected_cardinality = plan->second->GetCardinality(); + best_connection = possible_connections.back(); + } else if (possible_connections.empty()) { // cross product - expected_cardinality = left->cardinality * right->cardinality; + expected_cardinality = cardinality_estimator.EstimateCrossProduct(left, right); } else { // normal join, expect foreign key join - expected_cardinality = MaxValue(left->cardinality, right->cardinality); + expected_cardinality = cardinality_estimator.EstimateCardinalityWithSet(set); + best_connection = possible_connections.back(); } - // cost is expected_cardinality plus the cost of the previous plans - idx_t cost = expected_cardinality; - return make_unique(set, info, left, right, expected_cardinality, cost); + + auto cost = CardinalityEstimator::ComputeCost(left, right, expected_cardinality); + auto result = make_unique(set, best_connection, left, right, expected_cardinality, cost); + D_ASSERT(cost >= expected_cardinality); + return result; +} + +void JoinOrderOptimizer::UpdateJoinNodesInFullPlan(JoinNode *node) { + if (!node) { + return; + } + if (node->set->count == relations.size()) { + join_nodes_in_full_plan.clear(); + } + if (node->set->count < relations.size()) { + join_nodes_in_full_plan.insert(node->set->ToString()); + } + UpdateJoinNodesInFullPlan(node->left); + UpdateJoinNodesInFullPlan(node->right); } -JoinNode *JoinOrderOptimizer::EmitPair(JoinRelationSet *left, JoinRelationSet *right, NeighborInfo *info) { +JoinNode *JoinOrderOptimizer::EmitPair(JoinRelationSet *left, JoinRelationSet *right, + const vector &info) { // get the left and right join plans auto &left_plan = plans[left]; auto &right_plan = plans[right]; @@ -138910,18 +152049,46 @@ JoinNode *JoinOrderOptimizer::EmitPair(JoinRelationSet *left, JoinRelationSet *r auto new_plan = CreateJoinTree(new_set, info, left_plan.get(), right_plan.get()); // check if this plan is the optimal plan we found for this set of relations auto entry = plans.find(new_set); - if (entry == plans.end() || new_plan->cost < entry->second->cost) { + if (entry == plans.end() || new_plan->GetCost() < entry->second->GetCost()) { // the plan is the optimal plan, move it into the dynamic programming tree auto result = new_plan.get(); + + //! make sure plans are symmetric for cardinality estimation + if (entry != plans.end()) { + cardinality_estimator.VerifySymmetry(result, entry->second.get()); + } + if (full_plan_found && + join_nodes_in_full_plan.find(new_plan->set->ToString()) != join_nodes_in_full_plan.end()) { + must_update_full_plan = true; + } + if (new_set->count == relations.size()) { + full_plan_found = true; + // If we find a full plan, we need to keep track of which nodes are in the full plan. + // It's possible the DP algorithm updates one of these nodes, then goes on to solve + // the order approximately. In the approximate algorithm, it's not guaranteed that the + // node references are updated. If the original full plan is determined to still have + // the lowest cost, it's possible to get use-after-free errors. + // If we know a node in the full plan is updated, we can prevent ourselves from exiting the + // DP algorithm until the last plan updated is a full plan + UpdateJoinNodesInFullPlan(result); + if (must_update_full_plan) { + must_update_full_plan = false; + } + } + plans[new_set] = move(new_plan); return result; } return entry->second.get(); } -bool JoinOrderOptimizer::TryEmitPair(JoinRelationSet *left, JoinRelationSet *right, NeighborInfo *info) { +bool JoinOrderOptimizer::TryEmitPair(JoinRelationSet *left, JoinRelationSet *right, + const vector &info) { pairs++; - if (pairs >= 2000) { + // If a full plan is created, it's possible a node in the plan gets updated. When this happens, make sure you keep + // emitting pairs until you emit another final plan. Another final plan is guaranteed to be produced because of + // our symmetry guarantees. + if (pairs >= 10000 && !must_update_full_plan) { // when the amount of pairs gets too large we exit the dynamic programming and resort to a greedy algorithm // FIXME: simple heuristic currently // at 10K pairs stop searching exactly and switch to heuristic @@ -138946,15 +152113,19 @@ bool JoinOrderOptimizer::EmitCSG(JoinRelationSet *node) { if (neighbors.empty()) { return true; } - // we iterate over the neighbors ordered by their first node - sort(neighbors.begin(), neighbors.end()); + + //! Neighbors should be reversed when iterating over them. + std::sort(neighbors.begin(), neighbors.end(), std::greater_equal()); + for (idx_t i = 0; i < neighbors.size() - 1; i++) { + D_ASSERT(neighbors[i] >= neighbors[i + 1]); + } for (auto neighbor : neighbors) { // since the GetNeighbors only returns the smallest element in a list, the entry might not be connected to // (only!) this neighbor, hence we have to do a connectedness check before we can emit it auto neighbor_relation = set_manager.GetJoinRelation(neighbor); - auto connection = query_graph.GetConnection(node, neighbor_relation); - if (connection) { - if (!TryEmitPair(node, neighbor_relation, connection)) { + auto connections = query_graph.GetConnections(node, neighbor_relation); + if (!connections.empty()) { + if (!TryEmitPair(node, neighbor_relation, connections)) { return false; } } @@ -138979,9 +152150,9 @@ bool JoinOrderOptimizer::EnumerateCmpRecursive(JoinRelationSet *left, JoinRelati // emit the combinations of this node and its neighbors auto combined_set = set_manager.Union(right, neighbor); if (combined_set->count > right->count && plans.find(combined_set) != plans.end()) { - auto connection = query_graph.GetConnection(left, combined_set); - if (connection) { - if (!TryEmitPair(left, combined_set, connection)) { + auto connections = query_graph.GetConnections(left, combined_set); + if (!connections.empty()) { + if (!TryEmitPair(left, combined_set, connections)) { return false; } } @@ -139001,12 +152172,11 @@ bool JoinOrderOptimizer::EnumerateCmpRecursive(JoinRelationSet *left, JoinRelati } bool JoinOrderOptimizer::EnumerateCSGRecursive(JoinRelationSet *node, unordered_set &exclusion_set) { - // find neighbors of S under the exlusion set + // find neighbors of S under the exclusion set auto neighbors = query_graph.GetNeighbors(node, exclusion_set); if (neighbors.empty()) { return true; } - // now first emit the connected subgraphs of the neighbors vector union_sets; union_sets.resize(neighbors.size()); for (idx_t i = 0; i < neighbors.size(); i++) { @@ -139023,8 +152193,11 @@ bool JoinOrderOptimizer::EnumerateCSGRecursive(JoinRelationSet *node, unordered_ // recursively enumerate the sets unordered_set new_exclusion_set = exclusion_set; for (idx_t i = 0; i < neighbors.size(); i++) { - // updated the set of excluded entries with this neighbor + // Reset the exclusion set so that the algorithm considers all combinations + // of the exclusion_set with a subset of neighbors. + new_exclusion_set = exclusion_set; new_exclusion_set.insert(neighbors[i]); + // updated the set of excluded entries with this neighbor if (!EnumerateCSGRecursive(union_sets[i], new_exclusion_set)) { return false; } @@ -139055,6 +152228,99 @@ bool JoinOrderOptimizer::SolveJoinOrderExactly() { return true; } +static vector> AddSuperSets(vector> current, + const vector &all_neighbors) { + vector> ret; + for (auto &neighbor : all_neighbors) { + for (auto &neighbor_set : current) { + auto max_val = std::max_element(neighbor_set.begin(), neighbor_set.end()); + if (*max_val >= neighbor) { + continue; + } + if (neighbor_set.count(neighbor) == 0) { + unordered_set new_set; + for (auto &n : neighbor_set) { + new_set.insert(n); + } + new_set.insert(neighbor); + ret.push_back(new_set); + } + } + } + return ret; +} + +// works by first creating all sets with cardinality 1 +// then iterates over each previously create group of subsets and will only add a neighbor if the neighbor +// is greater than all relations in the set. +static vector> GetAllNeighborSets(JoinRelationSet *new_set, unordered_set &exclusion_set, + vector neighbors) { + vector> ret; + sort(neighbors.begin(), neighbors.end()); + vector> added; + for (auto &neighbor : neighbors) { + added.push_back(unordered_set({neighbor})); + ret.push_back(unordered_set({neighbor})); + } + do { + added = AddSuperSets(added, neighbors); + for (auto &d : added) { + ret.push_back(d); + } + } while (!added.empty()); +#if DEBUG + // drive by test to make sure we have an accurate amount of + // subsets, and that each neighbor is in a correct amount + // of those subsets. + D_ASSERT(ret.size() == pow(2, neighbors.size()) - 1); + for (auto &n : neighbors) { + idx_t count = 0; + for (auto &set : ret) { + if (set.count(n) >= 1) { + count += 1; + } + } + D_ASSERT(count == pow(2, neighbors.size() - 1)); + } +#endif + return ret; +} + +void JoinOrderOptimizer::UpdateDPTree(JoinNode *new_plan) { + auto new_set = new_plan->set; + // now update every plan that uses this plan + unordered_set exclusion_set; + for (idx_t i = 0; i < new_set->count; i++) { + exclusion_set.insert(new_set->relations[i]); + } + auto neighbors = query_graph.GetNeighbors(new_set, exclusion_set); + auto all_neighbors = GetAllNeighborSets(new_set, exclusion_set, neighbors); + for (auto neighbor : all_neighbors) { + auto neighbor_relation = set_manager.GetJoinRelation(neighbor); + auto combined_set = set_manager.Union(new_set, neighbor_relation); + + auto combined_set_plan = plans.find(combined_set); + if (combined_set_plan == plans.end()) { + continue; + } + + double combined_set_plan_cost = combined_set_plan->second->GetCost(); + auto connections = query_graph.GetConnections(new_set, neighbor_relation); + // recurse and update up the tree if the combined set produces a plan with a lower cost + // only recurse on neighbor relations that have plans. + auto &right_plan = plans[neighbor_relation]; + if (!right_plan) { + continue; + } + auto updated_plan = EmitPair(new_set, neighbor_relation, connections); + // <= because the child node has already been replaced. You need to + // replace the parent node as well in this case + if (updated_plan->GetCost() < combined_set_plan_cost) { + UpdateDPTree(updated_plan); + } + } +} + void JoinOrderOptimizer::SolveJoinOrderApproximately() { // at this point, we exited the dynamic programming but did not compute the final join order because it took too // long instead, we use a greedy heuristic to obtain a join ordering now we use Greedy Operator Ordering to @@ -139074,11 +152340,17 @@ void JoinOrderOptimizer::SolveJoinOrderApproximately() { for (idx_t j = i + 1; j < join_relations.size(); j++) { auto right = join_relations[j]; // check if we can connect these two relations - auto connection = query_graph.GetConnection(left, right); - if (connection) { - // we can! check the cost of this connection + auto connection = query_graph.GetConnections(left, right); + if (!connection.empty()) { + // we can check the cost of this connection auto node = EmitPair(left, right, connection); - if (!best_connection || node->cost < best_connection->cost) { + + // update the DP tree in case a plan created by the DP algorithm uses the node + // that was potentially just updated by EmitPair. You will get a use-after-free + // error if future plans rely on the old node that was just replaced. + UpdateDPTree(node); + + if (!best_connection || node->GetCost() < best_connection->GetCost()) { // best pair found so far best_connection = node; best_left = i; @@ -139097,7 +152369,7 @@ void JoinOrderOptimizer::SolveJoinOrderApproximately() { auto current_plan = plans[join_relations[i]].get(); // check if the cardinality is smaller than the smallest two found so far for (idx_t j = 0; j < 2; j++) { - if (!smallest_plans[j] || smallest_plans[j]->cardinality > current_plan->cardinality) { + if (!smallest_plans[j] || smallest_plans[j]->GetCardinality() > current_plan->GetCardinality()) { smallest_plans[j] = current_plan; smallest_index[j] = i; break; @@ -139114,12 +152386,14 @@ void JoinOrderOptimizer::SolveJoinOrderApproximately() { // create a cross product edge (i.e. edge with empty filter) between these two sets in the query graph query_graph.CreateEdge(left, right, nullptr); // now emit the pair and continue with the algorithm - auto connection = query_graph.GetConnection(left, right); - D_ASSERT(connection); + auto connections = query_graph.GetConnections(left, right); + D_ASSERT(!connections.empty()); - best_connection = EmitPair(left, right, connection); + best_connection = EmitPair(left, right, connections); best_left = smallest_index[0]; best_right = smallest_index[1]; + + UpdateDPTree(best_connection); // the code below assumes best_right > best_left if (best_left > best_right) { std::swap(best_left, best_right); @@ -139185,10 +152459,7 @@ JoinOrderOptimizer::GenerateJoins(vector> &extracted if (node->info->filters.empty()) { // no filters, create a cross product - auto join = make_unique(); - join->children.push_back(move(left.second)); - join->children.push_back(move(right.second)); - result_operator = move(join); + result_operator = LogicalCrossProduct::Create(move(left.second), move(right.second)); } else { // we have filters, create a join node auto join = make_unique(JoinType::INNER); @@ -139224,6 +152495,7 @@ JoinOrderOptimizer::GenerateJoins(vector> &extracted } left_node = left.first; right_node = right.first; + right_node = right.first; result_relation = set_manager.Union(left_node, right_node); } else { // base node, get the entry from the list of extracted relations @@ -139232,6 +152504,10 @@ JoinOrderOptimizer::GenerateJoins(vector> &extracted result_relation = node->set; result_operator = move(extracted_relations[node->set->relations[0]]); } + auto max_idx_t = NumericLimits::Maximum() - 10000; + result_operator->estimated_cardinality = MinValue(node->GetCardinality(), max_idx_t); + result_operator->has_estimated_cardinality = true; + result_operator->estimated_props = node->estimated_props->Copy(); // check if we should do a pushdown on this node // basically, any remaining filter that is a subset of the current relation will no longer be used in joins // hence we should push it here @@ -139414,6 +152690,8 @@ unique_ptr JoinOrderOptimizer::Optimize(unique_ptr left_bindings, right_bindings; ExtractBindings(*comparison->left, left_bindings); ExtractBindings(*comparison->right, right_bindings); + GetColumnBinding(*comparison->left, filter_info->left_binding); + GetColumnBinding(*comparison->right, filter_info->right_binding); if (!left_bindings.empty() && !right_bindings.empty()) { // both the left and the right side have bindings // first create the relation sets, if they do not exist @@ -139438,10 +152716,17 @@ unique_ptr JoinOrderOptimizer::Optimize(unique_ptr nodes_ops; for (idx_t i = 0; i < relations.size(); i++) { auto &rel = *relations[i]; auto node = set_manager.GetJoinRelation(i); - plans[node] = make_unique(node, rel.op->EstimateCardinality(context)); + nodes_ops.emplace_back(NodeOp(make_unique(node, 0), rel.op)); + } + + cardinality_estimator.InitCardinalityEstimatorProps(&nodes_ops, &filter_infos); + + for (auto &node_op : nodes_ops) { + plans[node_op.node->set] = move(node_op.node); } // now we perform the actual dynamic programming to compute the final result SolveJoinOrder(); @@ -139458,7 +152743,8 @@ unique_ptr JoinOrderOptimizer::Optimize(unique_ptr PropagateStatistics(unique_ptr &node_ptr); - -private: - //! Propagate statistics through an operator - unique_ptr PropagateStatistics(LogicalOperator &node, unique_ptr *node_ptr); - - unique_ptr PropagateStatistics(LogicalFilter &op, unique_ptr *node_ptr); - unique_ptr PropagateStatistics(LogicalGet &op, unique_ptr *node_ptr); - unique_ptr PropagateStatistics(LogicalJoin &op, unique_ptr *node_ptr); - unique_ptr PropagateStatistics(LogicalProjection &op, unique_ptr *node_ptr); - void PropagateStatistics(LogicalComparisonJoin &op, unique_ptr *node_ptr); - void PropagateStatistics(LogicalAnyJoin &op, unique_ptr *node_ptr); - unique_ptr PropagateStatistics(LogicalSetOperation &op, unique_ptr *node_ptr); - unique_ptr PropagateStatistics(LogicalAggregate &op, unique_ptr *node_ptr); - unique_ptr PropagateStatistics(LogicalCrossProduct &op, unique_ptr *node_ptr); - unique_ptr PropagateStatistics(LogicalLimit &op, unique_ptr *node_ptr); - unique_ptr PropagateStatistics(LogicalOrder &op, unique_ptr *node_ptr); - unique_ptr PropagateStatistics(LogicalWindow &op, unique_ptr *node_ptr); - - unique_ptr PropagateChildren(LogicalOperator &node, unique_ptr *node_ptr); - - //! Return statistics from a constant value - unique_ptr StatisticsFromValue(const Value &input); - //! Run a comparison with two sets of statistics, returns if the comparison will always returns true/false or not - FilterPropagateResult PropagateComparison(BaseStatistics &left, BaseStatistics &right, ExpressionType comparison); - - //! Update filter statistics from a filter with a constant - void UpdateFilterStatistics(BaseStatistics &input, ExpressionType comparison_type, const Value &constant); - //! Update statistics from a filter between two stats - void UpdateFilterStatistics(BaseStatistics &lstats, BaseStatistics &rstats, ExpressionType comparison_type); - //! Update filter statistics from a generic comparison - void UpdateFilterStatistics(Expression &left, Expression &right, ExpressionType comparison_type); - //! Update filter statistics from an expression - void UpdateFilterStatistics(Expression &condition); - //! Set the statistics of a specific column binding to not contain null values - void SetStatisticsNotNull(ColumnBinding binding); - - //! Run a comparison between the statistics and the table filter; returns the prune result - FilterPropagateResult PropagateTableFilter(BaseStatistics &stats, TableFilter &filter); - //! Update filter statistics from a TableFilter - void UpdateFilterStatistics(BaseStatistics &input, TableFilter &filter); - - //! Add cardinalities together (i.e. new max is stats.max + new_stats.max): used for union - void AddCardinalities(unique_ptr &stats, NodeStatistics &new_stats); - //! Multiply the cardinalities together (i.e. new max cardinality is stats.max * new_stats.max): used for - //! joins/cross products - void MultiplyCardinalities(unique_ptr &stats, NodeStatistics &new_stats); - - unique_ptr PropagateExpression(unique_ptr &expr); - unique_ptr PropagateExpression(Expression &expr, unique_ptr *expr_ptr); - - unique_ptr PropagateExpression(BoundAggregateExpression &expr, unique_ptr *expr_ptr); - unique_ptr PropagateExpression(BoundBetweenExpression &expr, unique_ptr *expr_ptr); - unique_ptr PropagateExpression(BoundCaseExpression &expr, unique_ptr *expr_ptr); - unique_ptr PropagateExpression(BoundCastExpression &expr, unique_ptr *expr_ptr); - unique_ptr PropagateExpression(BoundConjunctionExpression &expr, unique_ptr *expr_ptr); - unique_ptr PropagateExpression(BoundFunctionExpression &expr, unique_ptr *expr_ptr); - unique_ptr PropagateExpression(BoundComparisonExpression &expr, unique_ptr *expr_ptr); - unique_ptr PropagateExpression(BoundConstantExpression &expr, unique_ptr *expr_ptr); - unique_ptr PropagateExpression(BoundColumnRefExpression &expr, unique_ptr *expr_ptr); - unique_ptr PropagateExpression(BoundOperatorExpression &expr, unique_ptr *expr_ptr); - - void PropagateAndCompress(unique_ptr &expr, unique_ptr &stats); - - void ReplaceWithEmptyResult(unique_ptr &node); - bool ExpressionIsConstant(Expression &expr, const Value &val); - bool ExpressionIsConstantOrNull(Expression &expr, const Value &val); - -private: - ClientContext &context; - //! The map of ColumnBinding -> statistics for the various nodes - column_binding_map_t> statistics_map; - //! Node stats for the current node - unique_ptr node_stats; -}; - -} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -140116,6 +153296,7 @@ class TopN { + //===----------------------------------------------------------------------===// // DuckDB // @@ -140196,7 +153377,7 @@ Optimizer::Optimizer(Binder &binder, ClientContext &context) : context(context), void Optimizer::RunOptimizer(OptimizerType type, const std::function &callback) { auto &config = DBConfig::GetConfig(context); - if (config.disabled_optimizers.find(type) != config.disabled_optimizers.end()) { + if (config.options.disabled_optimizers.find(type) != config.options.disabled_optimizers.end()) { // optimizer is marked as disabled: skip return; } @@ -140229,7 +153410,7 @@ unique_ptr Optimizer::Optimize(unique_ptr plan }); RunOptimizer(OptimizerType::IN_CLAUSE, [&]() { - InClauseRewriter rewriter(*this); + InClauseRewriter rewriter(context, *this); plan = rewriter.Rewrite(move(plan)); }); @@ -140285,6 +153466,14 @@ unique_ptr Optimizer::Optimize(unique_ptr plan plan = expression_heuristics.Rewrite(move(plan)); }); + for (auto &optimizer_extension : DBConfig::GetConfig(context).optimizer_extensions) { + RunOptimizer(OptimizerType::EXTENSION, [&]() { + optimizer_extension.optimize_function(context, optimizer_extension.optimizer_info.get(), plan); + }); + } + + Planner::VerifyPlan(context, plan); + return plan; } @@ -140344,7 +153533,8 @@ namespace duckdb { unique_ptr FilterPullup::PullupFromLeft(unique_ptr op) { D_ASSERT(op->type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN || - op->type == LogicalOperatorType::LOGICAL_ANY_JOIN || op->type == LogicalOperatorType::LOGICAL_EXCEPT); + op->type == LogicalOperatorType::LOGICAL_ANY_JOIN || op->type == LogicalOperatorType::LOGICAL_EXCEPT || + op->type == LogicalOperatorType::LOGICAL_DELIM_JOIN); FilterPullup left_pullup(true, can_add_column); FilterPullup right_pullup(false, can_add_column); @@ -140582,7 +153772,7 @@ unique_ptr FilterPushdown::PushdownCrossProduct(unique_ptrfilter)); } @@ -140633,12 +153823,24 @@ unique_ptr FilterPushdown::PushdownFilter(unique_ptr FilterPushdown::PushdownGet(unique_ptr op) { D_ASSERT(op->type == LogicalOperatorType::LOGICAL_GET); auto &get = (LogicalGet &)*op; + if (get.function.pushdown_complex_filter || get.function.filter_pushdown) { + // this scan supports some form of filter push-down + // check if there are any parameters + // if there are, invalidate them to force a re-bind on execution + for (auto &filter : filters) { + if (filter->filter->HasParameter()) { + // there is a parameter in the filters! invalidate it + BoundParameterExpression::InvalidateRecursive(*filter->filter); + } + } + } if (get.function.pushdown_complex_filter) { // for the remaining filters, check if we can push any of them into the scan as well vector> expressions; @@ -140734,9 +153936,7 @@ unique_ptr FilterPushdown::PushdownInnerJoin(unique_ptr(); - cross_product->children.push_back(move(op->children[0])); - cross_product->children.push_back(move(op->children[1])); + auto cross_product = LogicalCrossProduct::Create(move(op->children[0]), move(op->children[1])); // then push down cross product return PushdownCrossProduct(move(cross_product)); } @@ -140752,7 +153952,6 @@ unique_ptr FilterPushdown::PushdownInnerJoin(unique_ptr RegexRangeFilter::Rewrite(unique_ptr + namespace duckdb { @@ -141638,24 +154837,42 @@ unique_ptr ComparisonSimplificationRule::Apply(LogicalOperator &op, } if (column_ref_expr->expression_class == ExpressionClass::BOUND_CAST) { //! Here we check if we can apply the expression on the constant side + //! We can do this if the cast itself is invertible and casting the constant is + //! invertible in practice. auto cast_expression = (BoundCastExpression *)column_ref_expr; auto target_type = cast_expression->source_type(); if (!BoundCastExpression::CastIsInvertible(target_type, cast_expression->return_type)) { return nullptr; } - auto new_constant = constant_value.TryCastAs(target_type); - if (new_constant) { - auto child_expression = move(cast_expression->child); - auto new_constant_expr = make_unique(constant_value); - //! We can cast, now we change our column_ref_expression from an operator cast to a column reference - if (column_ref_left) { - expr->left = move(child_expression); - expr->right = move(new_constant_expr); - } else { - expr->left = move(new_constant_expr); - expr->right = move(child_expression); + + // Can we cast the constant at all? + string error_message; + Value cast_constant; + auto new_constant = constant_value.TryCastAs(target_type, cast_constant, &error_message, true); + if (!new_constant) { + return nullptr; + } + + // Is the constant cast invertible? + if (!BoundCastExpression::CastIsInvertible(cast_expression->return_type, target_type)) { + // Is it actually invertible? + Value uncast_constant; + if (!cast_constant.TryCastAs(constant_value.type(), uncast_constant, &error_message, true) || + uncast_constant != constant_value) { + return nullptr; } } + + //! We can cast, now we change our column_ref_expression from an operator cast to a column reference + auto child_expression = move(cast_expression->child); + auto new_constant_expr = make_unique(cast_constant); + if (column_ref_left) { + expr->left = move(child_expression); + expr->right = move(new_constant_expr); + } else { + expr->left = move(new_constant_expr); + expr->right = move(child_expression); + } } return nullptr; } @@ -141875,7 +155092,7 @@ unique_ptr DatePartSimplificationRule::Apply(LogicalOperator &op, ve if (!function) { throw BinderException(error); } - return move(function); + return function; } } // namespace duckdb @@ -142662,7 +155879,7 @@ unique_ptr MoveConstantsRule::Apply(LogicalOperator &op, vector MoveConstantsRule::Apply(LogicalOperator &op, vector MoveConstantsRule::Apply(LogicalOperator &op, vector StatisticsPropagator::PropagateExpression(BoundConjun } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/storage/statistics/distinct_statistics.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - -namespace duckdb { -class Serializer; -class Deserializer; -class Vector; - -class DistinctStatistics : public BaseStatistics { -public: - DistinctStatistics(); - explicit DistinctStatistics(unique_ptr log, idx_t sample_count, idx_t total_count); - - //! The HLL of the table - unique_ptr log; - //! How many values have been sampled into the HLL - atomic sample_count; - //! How many values have been inserted (before sampling) - atomic total_count; - -public: - void Merge(const BaseStatistics &other) override; - - unique_ptr Copy() const override; - - void Serialize(Serializer &serializer) const override; - void Serialize(FieldWriter &writer) const override; - - static unique_ptr Deserialize(Deserializer &source); - static unique_ptr Deserialize(FieldReader &reader); - - void Update(Vector &update, idx_t count); - void Update(VectorData &update_data, const LogicalType &ptype, idx_t count); - - string ToString() const override; - idx_t GetCount() const; - -private: - //! For distinct statistics we sample the input to speed up insertions - static constexpr const double SAMPLE_RATE = 0.1; -}; - -} // namespace duckdb @@ -144833,8 +157996,8 @@ void StatisticsPropagator::PropagateStatistics(LogicalComparisonJoin &join, uniq case JoinType::OUTER: { // inner/left/right/full outer join, replace with cross product // since the condition is always true, left/right/outer join are equivalent to inner join here - auto cross_product = make_unique(); - cross_product->children = move(join.children); + auto cross_product = + LogicalCrossProduct::Create(move(join.children[0]), move(join.children[1])); *node_ptr = move(cross_product); return; } @@ -145176,6 +158339,7 @@ unique_ptr StatisticsPropagator::PropagateStatistics(LogicalOper case LogicalOperatorType::LOGICAL_ANY_JOIN: case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: case LogicalOperatorType::LOGICAL_JOIN: + case LogicalOperatorType::LOGICAL_DELIM_JOIN: return PropagateStatistics((LogicalJoin &)node, node_ptr); case LogicalOperatorType::LOGICAL_UNION: case LogicalOperatorType::LOGICAL_EXCEPT: @@ -145344,6 +158508,62 @@ void Event::SetTasks(vector> tasks) { +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parallel/pipeline_complete_event.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { +class Executor; + +class PipelineCompleteEvent : public Event { +public: + PipelineCompleteEvent(Executor &executor, bool complete_pipeline_p); + + bool complete_pipeline; + +public: + void Schedule() override; + void FinalizeFinish() override; +}; + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parallel/pipeline_event.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +class PipelineEvent : public Event { +public: + PipelineEvent(shared_ptr pipeline); + + //! The pipeline that this event belongs to + shared_ptr pipeline; + +public: + void Schedule() override; + void FinishEvent() override; +}; + +} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -145453,36 +158673,6 @@ class PipelineExecutor { } // namespace duckdb - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/parallel/pipeline_event.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { - -class PipelineEvent : public Event { -public: - PipelineEvent(shared_ptr pipeline); - - //! The pipeline that this event belongs to - shared_ptr pipeline; - -public: - void Schedule() override; - void FinishEvent() override; -}; - -} // namespace duckdb - //===----------------------------------------------------------------------===// // DuckDB // @@ -145513,34 +158703,6 @@ class PipelineFinishEvent : public Event { } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/parallel/pipeline_complete_event.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - -namespace duckdb { -class Executor; - -class PipelineCompleteEvent : public Event { -public: - PipelineCompleteEvent(Executor &executor, bool complete_pipeline_p); - - bool complete_pipeline; - -public: - void Schedule() override; - void FinalizeFinish() override; -}; - -} // namespace duckdb - @@ -145569,61 +158731,118 @@ struct PipelineEventStack { Event *pipeline_complete_event; }; -Pipeline *Executor::ScheduleUnionPipeline(const shared_ptr &pipeline, const Pipeline *parent, - event_map_t &event_map, vector> &events) { - pipeline->Ready(); +using event_map_t = unordered_map; + +struct ScheduleEventData { + ScheduleEventData(const vector> &pipelines, + unordered_map>> &child_pipelines, + unordered_map>> &union_pipelines, + vector> &events, bool initial_schedule) + : pipelines(pipelines), child_pipelines(child_pipelines), union_pipelines(union_pipelines), events(events), + initial_schedule(initial_schedule) { + } + const vector> &pipelines; + unordered_map>> &child_pipelines; + unordered_map>> &union_pipelines; + unordered_map> scheduled_pipelines; + vector> &events; + bool initial_schedule; + event_map_t event_map; +}; + +void Executor::SchedulePipeline(const shared_ptr &pipeline, ScheduleEventData &event_data, + vector &scheduled_pipelines) { D_ASSERT(pipeline); - auto pipeline_event = make_shared(pipeline); - auto parent_stack_entry = event_map.find(parent); - D_ASSERT(parent_stack_entry != event_map.end()); + auto &event_map = event_data.event_map; + auto &events = event_data.events; + auto &union_pipelines = event_data.union_pipelines; + pipeline->Ready(); - auto &parent_stack = parent_stack_entry->second; + auto pipeline_event = make_shared(pipeline); PipelineEventStack stack; stack.pipeline_event = pipeline_event.get(); - stack.pipeline_finish_event = parent_stack.pipeline_finish_event; - stack.pipeline_complete_event = parent_stack.pipeline_complete_event; + if (!scheduled_pipelines.empty()) { + // this pipeline has a parent pipeline - i.e. it is scheduled as part of a `UNION` + // set up the events + auto parent = scheduled_pipelines.back(); + auto parent_stack_entry = event_map.find(parent); + D_ASSERT(parent_stack_entry != event_map.end()); + + auto &parent_stack = parent_stack_entry->second; + stack.pipeline_finish_event = parent_stack.pipeline_finish_event; + stack.pipeline_complete_event = parent_stack.pipeline_complete_event; + + stack.pipeline_event->AddDependency(*parent_stack.pipeline_event); + parent_stack.pipeline_finish_event->AddDependency(*pipeline_event); + } else { + // stand-alone pipeline + auto pipeline_finish_event = make_shared(pipeline); + auto pipeline_complete_event = + make_shared(pipeline->executor, event_data.initial_schedule); - stack.pipeline_event->AddDependency(*parent_stack.pipeline_event); - parent_stack.pipeline_finish_event->AddDependency(*pipeline_event); + pipeline_finish_event->AddDependency(*pipeline_event); + pipeline_complete_event->AddDependency(*pipeline_finish_event); + + stack.pipeline_finish_event = pipeline_finish_event.get(); + stack.pipeline_complete_event = pipeline_complete_event.get(); + + events.push_back(move(pipeline_finish_event)); + events.push_back(move(pipeline_complete_event)); + } events.push_back(move(pipeline_event)); event_map.insert(make_pair(pipeline.get(), stack)); - auto parent_pipeline = pipeline.get(); - + scheduled_pipelines.push_back(pipeline.get()); auto union_entry = union_pipelines.find(pipeline.get()); if (union_entry != union_pipelines.end()) { for (auto &entry : union_entry->second) { - parent_pipeline = ScheduleUnionPipeline(entry, parent_pipeline, event_map, events); + SchedulePipeline(entry, event_data, scheduled_pipelines); } } - - return parent_pipeline; } -void Executor::ScheduleChildPipeline(Pipeline *parent, const shared_ptr &pipeline, event_map_t &event_map, - vector> &events) { +void Executor::ScheduleChildPipeline(Pipeline *parent, const shared_ptr &pipeline, + ScheduleEventData &event_data) { + auto &events = event_data.events; pipeline->Ready(); auto child_ptr = pipeline.get(); - auto dependencies = child_dependencies.find(child_ptr); - D_ASSERT(union_pipelines.find(child_ptr) == union_pipelines.end()); - D_ASSERT(dependencies != child_dependencies.end()); + D_ASSERT(event_data.union_pipelines.find(child_ptr) == event_data.union_pipelines.end()); // create the pipeline event and the event stack auto pipeline_event = make_shared(pipeline); + auto &event_map = event_data.event_map; auto parent_entry = event_map.find(parent); + D_ASSERT(parent_entry != event_map.end()); + PipelineEventStack stack; stack.pipeline_event = pipeline_event.get(); stack.pipeline_finish_event = parent_entry->second.pipeline_finish_event; stack.pipeline_complete_event = parent_entry->second.pipeline_complete_event; - // set up the dependencies for this child pipeline unordered_set finish_events; - for (auto &dep : dependencies->second) { + + vector remaining_pipelines; + unordered_set already_scheduled; + remaining_pipelines.push_back(parent); + for (idx_t i = 0; i < remaining_pipelines.size(); i++) { + auto dep = remaining_pipelines[i]; + if (already_scheduled.find(dep) != already_scheduled.end()) { + continue; + } + already_scheduled.insert(dep); + + auto dep_scheduled = event_data.scheduled_pipelines.find(dep); + if (dep_scheduled != event_data.scheduled_pipelines.end()) { + for (auto &next_dep : dep_scheduled->second) { + remaining_pipelines.push_back(next_dep); + } + } + auto dep_entry = event_map.find(dep); D_ASSERT(dep_entry != event_map.end()); D_ASSERT(dep_entry->second.pipeline_event); @@ -145635,62 +158854,33 @@ void Executor::ScheduleChildPipeline(Pipeline *parent, const shared_ptrAddDependency(*stack.pipeline_event); finish_events.insert(finish_event); } + + event_data.scheduled_pipelines[dep].push_back(child_ptr); } events.push_back(move(pipeline_event)); event_map.insert(make_pair(child_ptr, stack)); } -void Executor::SchedulePipeline(const shared_ptr &pipeline, event_map_t &event_map, - vector> &events, bool complete_pipeline) { - D_ASSERT(pipeline); - - pipeline->Ready(); - - auto pipeline_event = make_shared(pipeline); - auto pipeline_finish_event = make_shared(pipeline); - auto pipeline_complete_event = make_shared(pipeline->executor, complete_pipeline); - - PipelineEventStack stack; - stack.pipeline_event = pipeline_event.get(); - stack.pipeline_finish_event = pipeline_finish_event.get(); - stack.pipeline_complete_event = pipeline_complete_event.get(); - - pipeline_finish_event->AddDependency(*pipeline_event); - pipeline_complete_event->AddDependency(*pipeline_finish_event); - - events.push_back(move(pipeline_event)); - events.push_back(move(pipeline_finish_event)); - events.push_back(move(pipeline_complete_event)); - - event_map.insert(make_pair(pipeline.get(), stack)); - - auto union_entry = union_pipelines.find(pipeline.get()); - if (union_entry != union_pipelines.end()) { - auto parent_pipeline = pipeline.get(); - for (auto &entry : union_entry->second) { - parent_pipeline = ScheduleUnionPipeline(entry, parent_pipeline, event_map, events); - } - } -} - -void Executor::ScheduleEventsInternal(const vector> &pipelines, - unordered_map>> &child_pipelines, - vector> &events, bool main_schedule) { +void Executor::ScheduleEventsInternal(ScheduleEventData &event_data) { + auto &events = event_data.events; D_ASSERT(events.empty()); // create all the required pipeline events - event_map_t event_map; - for (auto &pipeline : pipelines) { - SchedulePipeline(pipeline, event_map, events, main_schedule); + auto &event_map = event_data.event_map; + for (auto &pipeline : event_data.pipelines) { + vector scheduled_pipelines; + SchedulePipeline(pipeline, event_data, scheduled_pipelines); + + event_data.scheduled_pipelines[pipeline.get()] = move(scheduled_pipelines); } // schedule child pipelines - for (auto &entry : child_pipelines) { + for (auto &entry : event_data.child_pipelines) { // iterate in reverse order // since child entries are added from top to bottom // dependencies are in reverse order (bottom to top) for (idx_t i = entry.second.size(); i > 0; i--) { auto &child_entry = entry.second[i - 1]; - ScheduleChildPipeline(entry.first, child_entry, event_map, events); + ScheduleChildPipeline(entry.first, child_entry, event_data); } } // set up the dependencies between pipeline events @@ -145715,12 +158905,15 @@ void Executor::ScheduleEventsInternal(const vector> &pipeli } void Executor::ScheduleEvents() { - ScheduleEventsInternal(pipelines, child_pipelines, events); + ScheduleEventData event_data(pipelines, child_pipelines, union_pipelines, events, true); + ScheduleEventsInternal(event_data); } void Executor::ReschedulePipelines(const vector> &pipelines, vector> &events) { unordered_map>> child_pipelines; - ScheduleEventsInternal(pipelines, child_pipelines, events, false); + unordered_map>> union_pipelines; + ScheduleEventData event_data(pipelines, child_pipelines, union_pipelines, events, false); + ScheduleEventsInternal(event_data); } void Executor::ExtractPipelines(shared_ptr &pipeline, vector> &result) { @@ -145738,8 +158931,8 @@ void Executor::ExtractPipelines(shared_ptr &pipeline, vectorsecond) { - ExtractPipelines(entry, result); + for (auto entry = child_entry->second.rbegin(); entry != child_entry->second.rend(); ++entry) { + ExtractPipelines(*entry, result); } child_pipelines.erase(pipeline_ptr); } @@ -145749,6 +158942,7 @@ bool Executor::NextExecutor() { if (root_pipeline_idx >= root_pipelines.size()) { return false; } + root_pipelines[root_pipeline_idx]->Reset(); root_executor = make_unique(context, *root_pipelines[root_pipeline_idx]); root_pipeline_idx++; return true; @@ -145930,7 +159124,6 @@ void Executor::Reset() { events.clear(); union_pipelines.clear(); child_pipelines.clear(); - child_dependencies.clear(); execution_result = PendingExecutionResult::RESULT_NOT_READY; } @@ -145939,7 +159132,6 @@ void Executor::AddChildPipeline(Pipeline *current) { // found another operator that is a source // schedule a child pipeline auto child_pipeline = make_shared(*this); - auto child_pipeline_ptr = child_pipeline.get(); child_pipeline->sink = current->sink; child_pipeline->operators = current->operators; child_pipeline->source = current->operators.back(); @@ -145948,15 +159140,6 @@ void Executor::AddChildPipeline(Pipeline *current) { vector dependencies; dependencies.push_back(current); - auto child_entry = child_pipelines.find(current); - if (child_entry != child_pipelines.end()) { - for (auto ¤t_child : child_entry->second) { - D_ASSERT(child_dependencies.find(current_child.get()) != child_dependencies.end()); - child_dependencies[current_child.get()].push_back(child_pipeline_ptr); - } - } - D_ASSERT(child_dependencies.find(child_pipeline_ptr) == child_dependencies.end()); - child_dependencies.insert(make_pair(child_pipeline_ptr, move(dependencies))); child_pipelines[current].push_back(move(child_pipeline)); } @@ -145965,12 +159148,12 @@ vector Executor::GetTypes() { return physical_plan->GetTypes(); } -void Executor::PushError(ExceptionType type, const string &exception) { +void Executor::PushError(PreservedError exception) { lock_guard elock(executor_lock); // interrupt execution of any other pipelines that belong to this executor context.interrupted = true; // push the exception onto the stack - exceptions.emplace_back(type, exception); + exceptions.push_back(move(exception)); } bool Executor::HasError() { @@ -145986,30 +159169,7 @@ void Executor::ThrowException() { void Executor::ThrowExceptionInternal() { // LCOV_EXCL_START D_ASSERT(!exceptions.empty()); auto &entry = exceptions[0]; - switch (entry.first) { - case ExceptionType::TRANSACTION: - throw TransactionException(entry.second); - case ExceptionType::CATALOG: - throw CatalogException(entry.second); - case ExceptionType::PARSER: - throw ParserException(entry.second); - case ExceptionType::BINDER: - throw BinderException(entry.second); - case ExceptionType::INTERRUPT: - throw InterruptException(); - case ExceptionType::FATAL: - throw FatalException(entry.second); - case ExceptionType::INTERNAL: - throw InternalException(entry.second); - case ExceptionType::IO: - throw IOException(entry.second); - case ExceptionType::CONSTRAINT: - throw ConstraintException(entry.second); - case ExceptionType::CONVERSION: - throw ConversionException(entry.second); - default: - throw Exception(entry.second); - } + entry.Throw(); } // LCOV_EXCL_STOP void Executor::Flush(ThreadContext &tcontext) { @@ -146089,11 +159249,11 @@ TaskExecutionResult ExecutorTask::Execute(TaskExecutionMode mode) { try { return ExecuteTask(mode); } catch (Exception &ex) { - executor.PushError(ex.type, ex.what()); + executor.PushError(PreservedError(ex)); } catch (std::exception &ex) { - executor.PushError(ExceptionType::UNKNOWN_TYPE, ex.what()); + executor.PushError(PreservedError(ex)); } catch (...) { // LCOV_EXCL_START - executor.PushError(ExceptionType::UNKNOWN_TYPE, "Unknown exception in Finalize!"); + executor.PushError(PreservedError("Unknown exception in Finalize!")); } // LCOV_EXCL_STOP return TaskExecutionResult::TASK_ERROR; } @@ -146149,7 +159309,8 @@ class PipelineTask : public ExecutorTask { } }; -Pipeline::Pipeline(Executor &executor_p) : executor(executor_p), ready(false), source(nullptr), sink(nullptr) { +Pipeline::Pipeline(Executor &executor_p) + : executor(executor_p), ready(false), initialized(false), source(nullptr), sink(nullptr) { } ClientContext &Pipeline::GetClientContext() { @@ -146158,10 +159319,13 @@ ClientContext &Pipeline::GetClientContext() { bool Pipeline::GetProgress(double ¤t_percentage, idx_t &source_cardinality) { D_ASSERT(source); - + source_cardinality = source->estimated_cardinality; + if (!initialized) { + current_percentage = 0; + return true; + } auto &client = executor.context; current_percentage = source->GetProgress(client, *source_state); - source_cardinality = source->estimated_cardinality; return current_percentage >= 0; } @@ -146196,7 +159360,7 @@ bool Pipeline::ScheduleParallel(shared_ptr &event) { bool Pipeline::IsOrderDependent() const { auto &config = DBConfig::GetConfig(executor.context); - if (!config.preserve_insertion_order) { + if (!config.options.preserve_insertion_order) { return false; } if (sink && sink->IsOrderDependent()) { @@ -146216,6 +159380,7 @@ bool Pipeline::IsOrderDependent() const { void Pipeline::Schedule(shared_ptr &event) { D_ASSERT(ready); D_ASSERT(sink); + Reset(); if (!ScheduleParallel(event)) { // could not parallelize this pipeline: push a sequential task instead ScheduleSequentialTask(event); @@ -146253,8 +159418,8 @@ void Pipeline::Reset() { op->op_state = op->GetGlobalOperatorState(GetClientContext()); } } - ResetSource(); + initialized = true; } void Pipeline::ResetSource() { @@ -146267,7 +159432,6 @@ void Pipeline::Ready() { } ready = true; std::reverse(operators.begin(), operators.end()); - Reset(); } void Pipeline::Finalize(Event &event) { @@ -146276,11 +159440,11 @@ void Pipeline::Finalize(Event &event) { auto sink_state = sink->Finalize(*this, event, executor.context, *sink->sink_state); sink->sink_state->state = sink_state; } catch (Exception &ex) { // LCOV_EXCL_START - executor.PushError(ex.type, ex.what()); + executor.PushError(PreservedError(ex)); } catch (std::exception &ex) { - executor.PushError(ExceptionType::UNKNOWN_TYPE, ex.what()); + executor.PushError(PreservedError(ex)); } catch (...) { - executor.PushError(ExceptionType::UNKNOWN_TYPE, "Unknown exception in Finalize!"); + executor.PushError(PreservedError("Unknown exception in Finalize!")); } // LCOV_EXCL_STOP } @@ -146355,10 +159519,6 @@ unordered_map>> &PipelineBuildState::Get unordered_map>> &PipelineBuildState::GetChildPipelines(Executor &executor) { return executor.child_pipelines; } -unordered_map> &PipelineBuildState::GetChildDependencies(Executor &executor) { - return executor.child_dependencies; -} - vector PipelineBuildState::GetPipelineOperators(Pipeline &pipeline) { return pipeline.operators; } @@ -146423,9 +159583,9 @@ PipelineExecutor::PipelineExecutor(ClientContext &context_p, Pipeline &pipeline_ auto prev_operator = i == 0 ? pipeline.source : pipeline.operators[i - 1]; auto current_operator = pipeline.operators[i]; auto chunk = make_unique(); - chunk->Initialize(prev_operator->GetTypes()); + chunk->Initialize(Allocator::Get(context.client), prev_operator->GetTypes()); intermediate_chunks.push_back(move(chunk)); - intermediate_states.push_back(current_operator->GetOperatorState(context.client)); + intermediate_states.push_back(current_operator->GetOperatorState(context)); if (can_cache_in_pipeline && current_operator->RequiresCache()) { auto &cache_types = current_operator->GetTypes(); bool can_cache = true; @@ -146439,7 +159599,7 @@ PipelineExecutor::PipelineExecutor(ClientContext &context_p, Pipeline &pipeline_ continue; } cached_chunks[i] = make_unique(); - cached_chunks[i]->Initialize(current_operator->GetTypes()); + cached_chunks[i]->Initialize(Allocator::Get(context.client), current_operator->GetTypes()); } if (current_operator->IsSink() && current_operator->sink_state->state == SinkFinalizeType::NO_OUTPUT_POSSIBLE) { // one of the operators has already figured out no output is possible @@ -146587,7 +159747,7 @@ void PipelineExecutor::CacheChunk(DataChunk ¤t_chunk, idx_t operator_idx) if (chunk_cache.size() >= (STANDARD_VECTOR_SIZE - CACHE_THRESHOLD)) { // chunk cache full: return it current_chunk.Move(chunk_cache); - chunk_cache.Initialize(pipeline.operators[operator_idx]->GetTypes()); + chunk_cache.Initialize(Allocator::Get(context.client), pipeline.operators[operator_idx]->GetTypes()); } else { // chunk cache not full: probe again current_chunk.Reset(); @@ -146620,7 +159780,12 @@ void PipelineExecutor::ExecutePull(DataChunk &result) { } } } - } catch (std::exception &ex) { // LCOV_EXCL_START + } catch (const Exception &ex) { // LCOV_EXCL_START + if (executor.HasError()) { + executor.ThrowException(); + } + throw; + } catch (std::exception &ex) { if (executor.HasError()) { executor.ThrowException(); } @@ -146748,7 +159913,7 @@ void PipelineExecutor::FetchFromSource(DataChunk &result) { void PipelineExecutor::InitializeChunk(DataChunk &chunk) { PhysicalOperator *last_op = pipeline.operators.empty() ? pipeline.source : pipeline.operators.back(); - chunk.Initialize(last_op->GetTypes()); + chunk.Initialize(Allocator::DefaultAllocator(), last_op->GetTypes()); } void PipelineExecutor::StartOperator(PhysicalOperator *op) { @@ -146794,7 +159959,7 @@ void PipelineFinishEvent::FinishEvent() { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #10 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #12 // See the end of this file for a list // Provides a C++11 implementation of a multi-producer, multi-consumer lock-free queue. @@ -150471,7 +163636,7 @@ inline void swap(typename ConcurrentQueue::ImplicitProducerKVP& a, ty // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #10 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #12 // See the end of this file for a list // Provides an efficient implementation of a semaphore (LightweightSemaphore). @@ -151029,7 +164194,7 @@ void TaskScheduler::ExecuteForever(atomic *marker) { unique_ptr task; // loop until the marker is set to false while (*marker) { - // wait for a signal with a timeout; the timeout allows us to periodically check + // wait for a signal with a timeout queue->semaphore.wait(); if (queue->q.try_dequeue(task)) { task->Execute(TaskExecutionMode::PROCESS_ALL); @@ -151041,6 +164206,25 @@ void TaskScheduler::ExecuteForever(atomic *marker) { #endif } +idx_t TaskScheduler::ExecuteTasks(atomic *marker, idx_t max_tasks) { +#ifndef DUCKDB_NO_THREADS + idx_t completed_tasks = 0; + // loop until the marker is set to false + while (*marker && completed_tasks < max_tasks) { + unique_ptr task; + if (!queue->q.try_dequeue(task)) { + return completed_tasks; + } + task->Execute(TaskExecutionMode::PROCESS_ALL); + task.reset(); + completed_tasks++; + } + return completed_tasks; +#else + throw NotImplementedException("DuckDB was compiled without threads! Background thread loop is not allowed."); +#endif +} + void TaskScheduler::ExecuteTasks(idx_t max_tasks) { #ifndef DUCKDB_NO_THREADS unique_ptr task; @@ -151069,7 +164253,7 @@ static void ThreadExecuteTasks(TaskScheduler *scheduler, atomic *marker) { int32_t TaskScheduler::NumberOfThreads() { auto &config = DBConfig::GetConfig(db); - return threads.size() + config.external_threads + 1; + return threads.size() + config.options.external_threads + 1; } void TaskScheduler::SetThreads(int32_t n) { @@ -151085,6 +164269,12 @@ void TaskScheduler::SetThreads(int32_t n) { #endif } +void TaskScheduler::Signal(idx_t n) { +#ifndef DUCKDB_NO_THREADS + queue->semaphore.signal(n); +#endif +} + void TaskScheduler::SetThreadsInternal(int32_t n) { #ifndef DUCKDB_NO_THREADS if (threads.size() == idx_t(n - 1)) { @@ -151096,7 +164286,7 @@ void TaskScheduler::SetThreadsInternal(int32_t n) { for (idx_t i = 0; i < threads.size(); i++) { *markers[i] = false; } - queue->semaphore.signal(threads.size()); + Signal(threads.size()); // now join the threads to ensure they are fully stopped before erasing them for (idx_t i = 0; i < threads.size(); i++) { threads[i]->internal_thread->join(); @@ -151369,6 +164559,14 @@ void ColumnDefinition::GetListOfDependencies(vector &dependencies) const InnerGetListOfDependencies(*generated_expression, dependencies); } +string ColumnDefinition::GetName() { + return name; +} + +LogicalType ColumnDefinition::GetType() { + return type; +} + void ColumnDefinition::SetGeneratedExpression(unique_ptr expression) { category = TableColumnType::GENERATED; @@ -151742,7 +164940,8 @@ unique_ptr BetweenExpression::Deserialize(ExpressionType type, return make_unique(move(input), move(lower), move(upper)); } -} // namespace duckdb//===----------------------------------------------------------------------===// +} // namespace duckdb +//===----------------------------------------------------------------------===// // DuckDB // // duckdb/parser/expression/case_expression.hpp @@ -152102,9 +165301,7 @@ namespace duckdb { ComparisonExpression::ComparisonExpression(ExpressionType type, unique_ptr left, unique_ptr right) - : ParsedExpression(type, ExpressionClass::COMPARISON) { - this->left = move(left); - this->right = move(right); + : ParsedExpression(type, ExpressionClass::COMPARISON), left(move(left)), right(move(right)) { } string ComparisonExpression::ToString() const { @@ -152223,7 +165420,7 @@ string ConstantExpression::ToString() const { } bool ConstantExpression::Equals(const ConstantExpression *a, const ConstantExpression *b) { - return !ValueOperations::DistinctFrom(a->value, b->value); + return a->value.type() == b->value.type() && !ValueOperations::DistinctFrom(a->value, b->value); } hash_t ConstantExpression::Hash() const { @@ -152426,83 +165623,46 @@ void FunctionExpression::Verify() const { } } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/parser/expression/lambda_expression.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { - -//! LambdaExpression represents either: -//! 1. A lambda operator that can be used for e.g. mapping an expression to a list -//! 2. An OperatorExpression with the "->" operator -//! Lambda expressions are written in the form of "capture -> expr", e.g. "x -> x + 1" -class LambdaExpression : public ParsedExpression { -public: - LambdaExpression(unique_ptr lhs, unique_ptr rhs); - - unique_ptr lhs; - unique_ptr rhs; - -public: - string ToString() const override; - - static bool Equals(const LambdaExpression *a, const LambdaExpression *b); - hash_t Hash() const override; - - unique_ptr Copy() const override; - void Serialize(FieldWriter &writer) const override; - static unique_ptr Deserialize(ExpressionType type, FieldReader &source); -}; - -} // namespace duckdb namespace duckdb { -LambdaExpression::LambdaExpression(unique_ptr lhs, unique_ptr rhs) - : ParsedExpression(ExpressionType::LAMBDA, ExpressionClass::LAMBDA), lhs(move(lhs)), rhs(move(rhs)) { +LambdaExpression::LambdaExpression(unique_ptr lhs, unique_ptr expr) + : ParsedExpression(ExpressionType::LAMBDA, ExpressionClass::LAMBDA), lhs(move(lhs)), expr(move(expr)) { } string LambdaExpression::ToString() const { - return lhs->ToString() + " -> " + rhs->ToString(); + return lhs->ToString() + " -> " + expr->ToString(); } bool LambdaExpression::Equals(const LambdaExpression *a, const LambdaExpression *b) { - return a->lhs->Equals(b->lhs.get()) && a->rhs->Equals(b->rhs.get()); + return a->lhs->Equals(b->lhs.get()) && a->expr->Equals(b->expr.get()); } hash_t LambdaExpression::Hash() const { + hash_t result = lhs->Hash(); ParsedExpression::Hash(); - result = CombineHash(result, rhs->Hash()); + result = CombineHash(result, expr->Hash()); return result; } unique_ptr LambdaExpression::Copy() const { - return make_unique(lhs->Copy(), rhs->Copy()); + return make_unique(lhs->Copy(), expr->Copy()); } void LambdaExpression::Serialize(FieldWriter &writer) const { writer.WriteSerializable(*lhs); - writer.WriteSerializable(*rhs); + writer.WriteSerializable(*expr); } unique_ptr LambdaExpression::Deserialize(ExpressionType type, FieldReader &reader) { auto lhs = reader.ReadRequiredSerializable(); - auto rhs = reader.ReadRequiredSerializable(); - return make_unique(move(lhs), move(rhs)); + auto expr = reader.ReadRequiredSerializable(); + return make_unique(move(lhs), move(expr)); } } // namespace duckdb @@ -152565,7 +165725,15 @@ class OperatorExpression : public ParsedExpression { child_list += ")"; return "(" + in_child + op_type + child_list + ")"; } - case ExpressionType::OPERATOR_NOT: + case ExpressionType::OPERATOR_NOT: { + string result = "("; + result += ExpressionTypeToString(entry.type); + result += " "; + result += StringUtil::Join(entry.children, entry.children.size(), ", ", + [](const unique_ptr &child) { return child->ToString(); }); + result += ")"; + return result; + } case ExpressionType::GROUPING_FUNCTION: case ExpressionType::OPERATOR_COALESCE: { string result = ExpressionTypeToString(entry.type); @@ -152585,7 +165753,9 @@ class OperatorExpression : public ParsedExpression { return entry.children[0]->ToString() + "[" + entry.children[1]->ToString() + ":" + entry.children[2]->ToString() + "]"; case ExpressionType::STRUCT_EXTRACT: { - D_ASSERT(entry.children[1]->type == ExpressionType::VALUE_CONSTANT); + if (entry.children[1]->type != ExpressionType::VALUE_CONSTANT) { + return string(); + } auto child_string = entry.children[1]->ToString(); D_ASSERT(child_string.size() >= 3); D_ASSERT(child_string[0] == '\'' && child_string[child_string.size() - 1] == '\''); @@ -152664,42 +165834,6 @@ unique_ptr OperatorExpression::Deserialize(ExpressionType type } } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/parser/expression/parameter_expression.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - -namespace duckdb { -class ParameterExpression : public ParsedExpression { -public: - ParameterExpression(); - - idx_t parameter_nr; - -public: - bool IsScalar() const override { - return true; - } - bool HasParameter() const override { - return true; - } - - string ToString() const override; - - unique_ptr Copy() const override; - hash_t Hash() const override; - - void Serialize(FieldWriter &writer) const override; - static unique_ptr Deserialize(ExpressionType type, FieldReader &source); -}; -} // namespace duckdb @@ -152724,6 +165858,10 @@ unique_ptr ParameterExpression::Copy() const { return move(copy); } +bool ParameterExpression::Equals(const ParameterExpression *a, const ParameterExpression *b) { + return a->parameter_nr == b->parameter_nr; +} + hash_t ParameterExpression::Hash() const { hash_t result = ParsedExpression::Hash(); return CombineHash(duckdb::Hash(parameter_nr), result); @@ -153150,7 +166288,7 @@ unique_ptr WindowExpression::Deserialize(ExpressionType type, auto order_count = reader.ReadRequired(); auto &source = reader.GetSource(); for (idx_t i = 0; i < order_count; i++) { - expr->orders.push_back(OrderByNode::Deserialize((source))); + expr->orders.push_back(OrderByNode::Deserialize(source)); } expr->start = reader.ReadRequired(); expr->end = reader.ReadRequired(); @@ -153274,10 +166412,12 @@ string KeywordHelper::WriteOptionallyQuoted(const string &text, char quote) { + + namespace duckdb { -AlterInfo::AlterInfo(AlterType type, string schema_p, string name_p) - : type(type), schema(move(schema_p)), name(move(name_p)) { +AlterInfo::AlterInfo(AlterType type, string schema_p, string name_p, bool if_exists) + : type(type), if_exists(if_exists), schema(move(schema_p)), name(move(name_p)) { } AlterInfo::~AlterInfo() { @@ -153314,8 +166454,8 @@ unique_ptr AlterInfo::Deserialize(Deserializer &source) { // ChangeOwnershipInfo //===--------------------------------------------------------------------===// ChangeOwnershipInfo::ChangeOwnershipInfo(CatalogType entry_catalog_type, string entry_schema_p, string entry_name_p, - string owner_schema_p, string owner_name_p) - : AlterInfo(AlterType::CHANGE_OWNERSHIP, move(entry_schema_p), move(entry_name_p)), + string owner_schema_p, string owner_name_p, bool if_exists) + : AlterInfo(AlterType::CHANGE_OWNERSHIP, move(entry_schema_p), move(entry_name_p), if_exists), entry_catalog_type(entry_catalog_type), owner_schema(move(owner_schema_p)), owner_name(move(owner_name_p)) { } @@ -153324,7 +166464,8 @@ CatalogType ChangeOwnershipInfo::GetCatalogType() const { } unique_ptr ChangeOwnershipInfo::Copy() const { - return make_unique_base(entry_catalog_type, schema, name, owner_schema, owner_name); + return make_unique_base(entry_catalog_type, schema, name, owner_schema, owner_name, + if_exists); } void ChangeOwnershipInfo::Serialize(FieldWriter &writer) const { @@ -153334,8 +166475,8 @@ void ChangeOwnershipInfo::Serialize(FieldWriter &writer) const { //===--------------------------------------------------------------------===// // AlterTableInfo //===--------------------------------------------------------------------===// -AlterTableInfo::AlterTableInfo(AlterTableType type, string schema_p, string table_p) - : AlterInfo(AlterType::ALTER_TABLE, move(move(schema_p)), move(table_p)), alter_table_type(type) { +AlterTableInfo::AlterTableInfo(AlterTableType type, string schema_p, string table_p, bool if_exists) + : AlterInfo(AlterType::ALTER_TABLE, move(move(schema_p)), move(table_p), if_exists), alter_table_type(type) { } AlterTableInfo::~AlterTableInfo() { } @@ -153348,6 +166489,7 @@ void AlterTableInfo::Serialize(FieldWriter &writer) const { writer.WriteField(alter_table_type); writer.WriteString(schema); writer.WriteString(name); + writer.WriteField(if_exists); SerializeAlterTable(writer); } @@ -153355,22 +166497,28 @@ unique_ptr AlterTableInfo::Deserialize(FieldReader &reader) { auto type = reader.ReadRequired(); auto schema = reader.ReadRequired(); auto table = reader.ReadRequired(); + auto if_exists = reader.ReadRequired(); + unique_ptr info; switch (type) { case AlterTableType::RENAME_COLUMN: - return RenameColumnInfo::Deserialize(reader, schema, table); + return RenameColumnInfo::Deserialize(reader, schema, table, if_exists); case AlterTableType::RENAME_TABLE: - return RenameTableInfo::Deserialize(reader, schema, table); + return RenameTableInfo::Deserialize(reader, schema, table, if_exists); case AlterTableType::ADD_COLUMN: - return AddColumnInfo::Deserialize(reader, schema, table); + return AddColumnInfo::Deserialize(reader, schema, table, if_exists); case AlterTableType::REMOVE_COLUMN: - return RemoveColumnInfo::Deserialize(reader, schema, table); + return RemoveColumnInfo::Deserialize(reader, schema, table, if_exists); case AlterTableType::ALTER_COLUMN_TYPE: - return ChangeColumnTypeInfo::Deserialize(reader, schema, table); + return ChangeColumnTypeInfo::Deserialize(reader, schema, table, if_exists); case AlterTableType::SET_DEFAULT: - return SetDefaultInfo::Deserialize(reader, schema, table); + return SetDefaultInfo::Deserialize(reader, schema, table, if_exists); case AlterTableType::FOREIGN_KEY_CONSTRAINT: - return AlterForeignKeyInfo::Deserialize(reader, schema, table); + return AlterForeignKeyInfo::Deserialize(reader, schema, table, if_exists); + case AlterTableType::SET_NOT_NULL: + return SetNotNullInfo::Deserialize(reader, schema, table, if_exists); + case AlterTableType::DROP_NOT_NULL: + return DropNotNullInfo::Deserialize(reader, schema, table, if_exists); default: throw SerializationException("Unknown alter table type for deserialization!"); } @@ -153379,15 +166527,16 @@ unique_ptr AlterTableInfo::Deserialize(FieldReader &reader) { //===--------------------------------------------------------------------===// // RenameColumnInfo //===--------------------------------------------------------------------===// -RenameColumnInfo::RenameColumnInfo(string schema_p, string table_p, string old_name_p, string new_name_p) - : AlterTableInfo(AlterTableType::RENAME_COLUMN, move(schema_p), move(table_p)), old_name(move(old_name_p)), - new_name(move(new_name_p)) { +RenameColumnInfo::RenameColumnInfo(string schema_p, string table_p, bool if_exists_p, string old_name_p, + string new_name_p) + : AlterTableInfo(AlterTableType::RENAME_COLUMN, move(schema_p), move(table_p), if_exists_p), + old_name(move(old_name_p)), new_name(move(new_name_p)) { } RenameColumnInfo::~RenameColumnInfo() { } unique_ptr RenameColumnInfo::Copy() const { - return make_unique_base(schema, name, old_name, new_name); + return make_unique_base(schema, name, if_exists, old_name, new_name); } void RenameColumnInfo::SerializeAlterTable(FieldWriter &writer) const { @@ -153395,96 +166544,104 @@ void RenameColumnInfo::SerializeAlterTable(FieldWriter &writer) const { writer.WriteString(new_name); } -unique_ptr RenameColumnInfo::Deserialize(FieldReader &reader, string schema, string table) { +unique_ptr RenameColumnInfo::Deserialize(FieldReader &reader, string schema, string table, bool if_exists) { auto old_name = reader.ReadRequired(); auto new_name = reader.ReadRequired(); - return make_unique(move(schema), move(table), old_name, new_name); + return make_unique(move(schema), move(table), if_exists, old_name, new_name); } //===--------------------------------------------------------------------===// // RenameTableInfo //===--------------------------------------------------------------------===// -RenameTableInfo::RenameTableInfo(string schema_p, string table_p, string new_name_p) - : AlterTableInfo(AlterTableType::RENAME_TABLE, move(schema_p), move(table_p)), new_table_name(move(new_name_p)) { +RenameTableInfo::RenameTableInfo(string schema_p, string table_p, bool if_exists, string new_name_p) + : AlterTableInfo(AlterTableType::RENAME_TABLE, move(schema_p), move(table_p), if_exists), + new_table_name(move(new_name_p)) { } RenameTableInfo::~RenameTableInfo() { } unique_ptr RenameTableInfo::Copy() const { - return make_unique_base(schema, name, new_table_name); + return make_unique_base(schema, name, if_exists, new_table_name); } void RenameTableInfo::SerializeAlterTable(FieldWriter &writer) const { writer.WriteString(new_table_name); } -unique_ptr RenameTableInfo::Deserialize(FieldReader &reader, string schema, string table) { +unique_ptr RenameTableInfo::Deserialize(FieldReader &reader, string schema, string table, bool if_exists) { auto new_name = reader.ReadRequired(); - return make_unique(move(schema), move(table), new_name); + return make_unique(move(schema), move(table), if_exists, new_name); } //===--------------------------------------------------------------------===// // AddColumnInfo //===--------------------------------------------------------------------===// -AddColumnInfo::AddColumnInfo(string schema_p, string table_p, ColumnDefinition new_column) - : AlterTableInfo(AlterTableType::ADD_COLUMN, move(schema_p), move(table_p)), new_column(move(new_column)) { +AddColumnInfo::AddColumnInfo(string schema_p, string table_p, bool if_exists_p, ColumnDefinition new_column, + bool if_column_not_exists) + : AlterTableInfo(AlterTableType::ADD_COLUMN, move(schema_p), move(table_p), if_exists_p), + new_column(move(new_column)), if_column_not_exists(if_column_not_exists) { } + AddColumnInfo::~AddColumnInfo() { } unique_ptr AddColumnInfo::Copy() const { - return make_unique_base(schema, name, new_column.Copy()); + return make_unique_base(schema, name, if_exists, new_column.Copy(), if_column_not_exists); } void AddColumnInfo::SerializeAlterTable(FieldWriter &writer) const { writer.WriteSerializable(new_column); + writer.WriteField(if_column_not_exists); } -unique_ptr AddColumnInfo::Deserialize(FieldReader &reader, string schema, string table) { +unique_ptr AddColumnInfo::Deserialize(FieldReader &reader, string schema, string table, bool if_exists) { auto new_column = reader.ReadRequiredSerializable(); - return make_unique(move(schema), move(table), move(new_column)); + auto if_column_not_exists = reader.ReadRequired(); + return make_unique(move(schema), move(table), if_exists, move(new_column), if_column_not_exists); } //===--------------------------------------------------------------------===// // RemoveColumnInfo //===--------------------------------------------------------------------===// -RemoveColumnInfo::RemoveColumnInfo(string schema, string table, string removed_column, bool if_exists, bool cascade) - : AlterTableInfo(AlterTableType::REMOVE_COLUMN, move(schema), move(table)), removed_column(move(removed_column)), - if_exists(if_exists), cascade(cascade) { +RemoveColumnInfo::RemoveColumnInfo(string schema, string table, bool if_exists, string removed_column, + bool if_column_exists, bool cascade) + : AlterTableInfo(AlterTableType::REMOVE_COLUMN, move(schema), move(table), if_exists), + removed_column(move(removed_column)), if_column_exists(if_column_exists), cascade(cascade) { } RemoveColumnInfo::~RemoveColumnInfo() { } unique_ptr RemoveColumnInfo::Copy() const { - return make_unique_base(schema, name, removed_column, if_exists, cascade); + return make_unique_base(schema, name, if_exists, removed_column, if_column_exists, + cascade); } void RemoveColumnInfo::SerializeAlterTable(FieldWriter &writer) const { writer.WriteString(removed_column); - writer.WriteField(if_exists); + writer.WriteField(if_column_exists); writer.WriteField(cascade); } -unique_ptr RemoveColumnInfo::Deserialize(FieldReader &reader, string schema, string table) { +unique_ptr RemoveColumnInfo::Deserialize(FieldReader &reader, string schema, string table, bool if_exists) { auto new_name = reader.ReadRequired(); - auto if_exists = reader.ReadRequired(); + auto if_column_exists = reader.ReadRequired(); auto cascade = reader.ReadRequired(); - return make_unique(move(schema), move(table), new_name, if_exists, cascade); + return make_unique(move(schema), move(table), if_exists, new_name, if_column_exists, cascade); } //===--------------------------------------------------------------------===// // ChangeColumnTypeInfo //===--------------------------------------------------------------------===// -ChangeColumnTypeInfo::ChangeColumnTypeInfo(string schema_p, string table_p, string column_name, LogicalType target_type, - unique_ptr expression) - : AlterTableInfo(AlterTableType::ALTER_COLUMN_TYPE, move(schema_p), move(table_p)), column_name(move(column_name)), - target_type(move(target_type)), expression(move(expression)) { +ChangeColumnTypeInfo::ChangeColumnTypeInfo(string schema_p, string table_p, bool if_exists_p, string column_name, + LogicalType target_type, unique_ptr expression) + : AlterTableInfo(AlterTableType::ALTER_COLUMN_TYPE, move(schema_p), move(table_p), if_exists_p), + column_name(move(column_name)), target_type(move(target_type)), expression(move(expression)) { } ChangeColumnTypeInfo::~ChangeColumnTypeInfo() { } unique_ptr ChangeColumnTypeInfo::Copy() const { - return make_unique_base(schema, name, column_name, target_type, + return make_unique_base(schema, name, if_exists, column_name, target_type, expression->Copy()); } @@ -153494,27 +166651,28 @@ void ChangeColumnTypeInfo::SerializeAlterTable(FieldWriter &writer) const { writer.WriteOptional(expression); } -unique_ptr ChangeColumnTypeInfo::Deserialize(FieldReader &reader, string schema, string table) { +unique_ptr ChangeColumnTypeInfo::Deserialize(FieldReader &reader, string schema, string table, + bool if_exists) { auto column_name = reader.ReadRequired(); auto target_type = reader.ReadRequiredSerializable(); auto expression = reader.ReadOptional(nullptr); - return make_unique(move(schema), move(table), move(column_name), move(target_type), + return make_unique(move(schema), move(table), if_exists, move(column_name), move(target_type), move(expression)); } //===--------------------------------------------------------------------===// // SetDefaultInfo //===--------------------------------------------------------------------===// -SetDefaultInfo::SetDefaultInfo(string schema_p, string table_p, string column_name_p, +SetDefaultInfo::SetDefaultInfo(string schema_p, string table_p, bool if_exists_p, string column_name_p, unique_ptr new_default) - : AlterTableInfo(AlterTableType::SET_DEFAULT, move(schema_p), move(table_p)), column_name(move(column_name_p)), - expression(move(new_default)) { + : AlterTableInfo(AlterTableType::SET_DEFAULT, move(schema_p), move(table_p), if_exists_p), + column_name(move(column_name_p)), expression(move(new_default)) { } SetDefaultInfo::~SetDefaultInfo() { } unique_ptr SetDefaultInfo::Copy() const { - return make_unique_base(schema, name, column_name, + return make_unique_base(schema, name, if_exists, column_name, expression ? expression->Copy() : nullptr); } @@ -153523,28 +166681,74 @@ void SetDefaultInfo::SerializeAlterTable(FieldWriter &writer) const { writer.WriteOptional(expression); } -unique_ptr SetDefaultInfo::Deserialize(FieldReader &reader, string schema, string table) { +unique_ptr SetDefaultInfo::Deserialize(FieldReader &reader, string schema, string table, bool if_exists) { auto column_name = reader.ReadRequired(); auto new_default = reader.ReadOptional(nullptr); - return make_unique(move(schema), move(table), move(column_name), move(new_default)); + return make_unique(move(schema), move(table), if_exists, move(column_name), move(new_default)); +} + +//===--------------------------------------------------------------------===// +// SetNotNullInfo +//===--------------------------------------------------------------------===// +SetNotNullInfo::SetNotNullInfo(string schema_p, string table_p, bool if_exists_p, string column_name_p) + : AlterTableInfo(AlterTableType::SET_NOT_NULL, move(schema_p), move(table_p), if_exists_p), + column_name(move(column_name_p)) { +} +SetNotNullInfo::~SetNotNullInfo() { +} + +unique_ptr SetNotNullInfo::Copy() const { + return make_unique_base(schema, name, if_exists, column_name); +} + +void SetNotNullInfo::SerializeAlterTable(FieldWriter &writer) const { + writer.WriteString(column_name); +} + +unique_ptr SetNotNullInfo::Deserialize(FieldReader &reader, string schema, string table, bool if_exists) { + auto column_name = reader.ReadRequired(); + return make_unique(move(schema), move(table), if_exists, move(column_name)); +} + +//===--------------------------------------------------------------------===// +// DropNotNullInfo +//===--------------------------------------------------------------------===// +DropNotNullInfo::DropNotNullInfo(string schema_p, string table_p, bool if_exists_p, string column_name_p) + : AlterTableInfo(AlterTableType::DROP_NOT_NULL, move(schema_p), move(table_p), if_exists_p), + column_name(move(column_name_p)) { +} +DropNotNullInfo::~DropNotNullInfo() { +} + +unique_ptr DropNotNullInfo::Copy() const { + return make_unique_base(schema, name, if_exists, column_name); +} + +void DropNotNullInfo::SerializeAlterTable(FieldWriter &writer) const { + writer.WriteString(column_name); +} + +unique_ptr DropNotNullInfo::Deserialize(FieldReader &reader, string schema, string table, bool if_exists) { + auto column_name = reader.ReadRequired(); + return make_unique(move(schema), move(table), if_exists, move(column_name)); } //===--------------------------------------------------------------------===// // AlterForeignKeyInfo //===--------------------------------------------------------------------===// -AlterForeignKeyInfo::AlterForeignKeyInfo(string schema_p, string table_p, string fk_table, vector pk_columns, - vector fk_columns, vector pk_keys, vector fk_keys, - AlterForeignKeyType type_p) - : AlterTableInfo(AlterTableType::FOREIGN_KEY_CONSTRAINT, move(schema_p), move(table_p)), fk_table(move(fk_table)), - pk_columns(move(pk_columns)), fk_columns(move(fk_columns)), pk_keys(move(pk_keys)), fk_keys(move(fk_keys)), - type(type_p) { +AlterForeignKeyInfo::AlterForeignKeyInfo(string schema_p, string table_p, bool if_exists_p, string fk_table, + vector pk_columns, vector fk_columns, vector pk_keys, + vector fk_keys, AlterForeignKeyType type_p) + : AlterTableInfo(AlterTableType::FOREIGN_KEY_CONSTRAINT, move(schema_p), move(table_p), if_exists_p), + fk_table(move(fk_table)), pk_columns(move(pk_columns)), fk_columns(move(fk_columns)), pk_keys(move(pk_keys)), + fk_keys(move(fk_keys)), type(type_p) { } AlterForeignKeyInfo::~AlterForeignKeyInfo() { } unique_ptr AlterForeignKeyInfo::Copy() const { - return make_unique_base(schema, name, fk_table, pk_columns, fk_columns, pk_keys, - fk_keys, type); + return make_unique_base(schema, name, if_exists, fk_table, pk_columns, fk_columns, + pk_keys, fk_keys, type); } void AlterForeignKeyInfo::SerializeAlterTable(FieldWriter &writer) const { @@ -153556,22 +166760,23 @@ void AlterForeignKeyInfo::SerializeAlterTable(FieldWriter &writer) const { writer.WriteField(type); } -unique_ptr AlterForeignKeyInfo::Deserialize(FieldReader &reader, string schema, string table) { +unique_ptr AlterForeignKeyInfo::Deserialize(FieldReader &reader, string schema, string table, + bool if_exists) { auto fk_table = reader.ReadRequired(); auto pk_columns = reader.ReadRequiredList(); auto fk_columns = reader.ReadRequiredList(); auto pk_keys = reader.ReadRequiredList(); auto fk_keys = reader.ReadRequiredList(); auto type = reader.ReadRequired(); - return make_unique(move(schema), move(table), move(fk_table), move(pk_columns), + return make_unique(move(schema), move(table), if_exists, move(fk_table), move(pk_columns), move(fk_columns), move(pk_keys), move(fk_keys), type); } //===--------------------------------------------------------------------===// // Alter View //===--------------------------------------------------------------------===// -AlterViewInfo::AlterViewInfo(AlterViewType type, string schema_p, string view_p) - : AlterInfo(AlterType::ALTER_VIEW, move(schema_p), move(view_p)), alter_view_type(type) { +AlterViewInfo::AlterViewInfo(AlterViewType type, string schema_p, string view_p, bool if_exists_p) + : AlterInfo(AlterType::ALTER_VIEW, move(schema_p), move(view_p), if_exists_p), alter_view_type(type) { } AlterViewInfo::~AlterViewInfo() { } @@ -153584,6 +166789,7 @@ void AlterViewInfo::Serialize(FieldWriter &writer) const { writer.WriteField(alter_view_type); writer.WriteString(schema); writer.WriteString(name); + writer.WriteField(if_exists); SerializeAlterView(writer); } @@ -153591,10 +166797,11 @@ unique_ptr AlterViewInfo::Deserialize(FieldReader &reader) { auto type = reader.ReadRequired(); auto schema = reader.ReadRequired(); auto view = reader.ReadRequired(); + auto if_exists = reader.ReadRequired(); unique_ptr info; switch (type) { case AlterViewType::RENAME_VIEW: - return RenameViewInfo::Deserialize(reader, schema, view); + return RenameViewInfo::Deserialize(reader, schema, view, if_exists); default: throw SerializationException("Unknown alter view type for deserialization!"); } @@ -153603,24 +166810,180 @@ unique_ptr AlterViewInfo::Deserialize(FieldReader &reader) { //===--------------------------------------------------------------------===// // RenameViewInfo //===--------------------------------------------------------------------===// -RenameViewInfo::RenameViewInfo(string schema_p, string view_p, string new_name_p) - : AlterViewInfo(AlterViewType::RENAME_VIEW, move(schema_p), move(view_p)), new_view_name(move(new_name_p)) { +RenameViewInfo::RenameViewInfo(string schema_p, string view_p, bool if_exists_p, string new_name_p) + : AlterViewInfo(AlterViewType::RENAME_VIEW, move(schema_p), move(view_p), if_exists_p), + new_view_name(move(new_name_p)) { } RenameViewInfo::~RenameViewInfo() { } unique_ptr RenameViewInfo::Copy() const { - return make_unique_base(schema, name, new_view_name); + return make_unique_base(schema, name, if_exists, new_view_name); } void RenameViewInfo::SerializeAlterView(FieldWriter &writer) const { writer.WriteString(new_view_name); } -unique_ptr RenameViewInfo::Deserialize(FieldReader &reader, string schema, string view) { +unique_ptr RenameViewInfo::Deserialize(FieldReader &reader, string schema, string view, bool if_exists) { auto new_name = reader.ReadRequired(); - return make_unique(move(schema), move(view), new_name); + return make_unique(move(schema), move(view), if_exists, new_name); +} +} // namespace duckdb + + + + +namespace duckdb { + +unique_ptr CreateIndexInfo::Copy() const { + auto result = make_unique(); + CopyProperties(*result); + result->index_type = index_type; + result->index_name = index_name; + result->constraint_type = constraint_type; + result->table = unique_ptr_cast(table->Copy()); + for (auto &expr : expressions) { + result->expressions.push_back(expr->Copy()); + } + result->column_ids = column_ids; + return move(result); +} + +void CreateIndexInfo::SerializeInternal(Serializer &serializer) const { + FieldWriter writer(serializer); + writer.WriteField(index_type); + writer.WriteString(index_name); + writer.WriteField(constraint_type); + + writer.WriteSerializableList(expressions); + writer.WriteSerializableList(parsed_expressions); + // table->Serialize(writer); + writer.Finalize(); +} + +unique_ptr CreateIndexInfo::Deserialize(Deserializer &deserializer) { + auto result = make_unique(); + result->DeserializeBase(deserializer); + + FieldReader reader(deserializer); + result->index_type = reader.ReadRequired(); + result->index_name = reader.ReadRequired(); + result->constraint_type = reader.ReadRequired(); + + result->expressions = reader.ReadRequiredSerializableList(); + result->parsed_expressions = reader.ReadRequiredSerializableList(); + + // TODO(stephwang): review below for unique_ptr table + // unique_ptr table; + // table = BaseTableRef::Deserialize(reader); + // result->table = unique_ptr_cast(move(table)); + + reader.Finalize(); + + return result; +} +} // namespace duckdb + + + + + + + +namespace duckdb { +void CreateInfo::DeserializeBase(Deserializer &deserializer) { + this->schema = deserializer.Read(); + this->on_conflict = deserializer.Read(); + this->temporary = deserializer.Read(); + this->internal = deserializer.Read(); + this->sql = deserializer.Read(); +} + +void CreateInfo::Serialize(Serializer &serializer) const { + serializer.Write(type); + serializer.WriteString(schema); + serializer.Write(on_conflict); + serializer.Write(temporary); + serializer.Write(internal); + serializer.WriteString(sql); + SerializeInternal(serializer); +} + +unique_ptr CreateInfo::Deserialize(Deserializer &deserializer) { + auto type = deserializer.Read(); + switch (type) { + case CatalogType::INDEX_ENTRY: + return CreateIndexInfo::Deserialize(deserializer); + case CatalogType::TABLE_ENTRY: + return CreateTableInfo::Deserialize(deserializer); + case CatalogType::SCHEMA_ENTRY: + return CreateSchemaInfo::Deserialize(deserializer); + case CatalogType::VIEW_ENTRY: + return CreateViewInfo::Deserialize(deserializer); + default: + throw NotImplementedException("Cannot deserialize '%s'", CatalogTypeToString(type)); + } +} + +void CreateInfo::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 + + +namespace duckdb { + +CreateTableInfo::CreateTableInfo() : CreateInfo(CatalogType::TABLE_ENTRY, INVALID_SCHEMA) { +} + +CreateTableInfo::CreateTableInfo(string schema_p, string name_p) + : CreateInfo(CatalogType::TABLE_ENTRY, move(schema_p)), table(move(name_p)) { +} + +void CreateTableInfo::SerializeInternal(Serializer &serializer) const { + FieldWriter writer(serializer); + writer.WriteString(table); + writer.WriteRegularSerializableList(columns); + writer.WriteSerializableList(constraints); + writer.WriteOptional(query); + writer.Finalize(); } + +unique_ptr CreateTableInfo::Deserialize(Deserializer &deserializer) { + auto result = make_unique(); + result->DeserializeBase(deserializer); + + FieldReader reader(deserializer); + result->table = reader.ReadRequired(); + result->columns = reader.ReadRequiredSerializableList(); + result->constraints = reader.ReadRequiredSerializableList(); + result->query = reader.ReadOptional(nullptr); + reader.Finalize(); + + return result; +} + +unique_ptr CreateTableInfo::Copy() const { + auto result = make_unique(schema, table); + CopyProperties(*result); + for (auto &column : columns) { + result->columns.push_back(column.Copy()); + } + for (auto &constraint : constraints) { + result->constraints.push_back(constraint->Copy()); + } + if (query) { + result->query = unique_ptr_cast(query->Copy()); + } + return move(result); +} + } // namespace duckdb @@ -153709,6 +167072,7 @@ bool SampleOptions::Equals(SampleOptions *a, SampleOptions *b) { + namespace duckdb { @@ -153781,7 +167145,7 @@ bool ParsedExpression::Equals(const BaseExpression *other) const { case ExpressionClass::OPERATOR: return OperatorExpression::Equals((OperatorExpression *)this, (OperatorExpression *)other); case ExpressionClass::PARAMETER: - return true; + return ParameterExpression::Equals((ParameterExpression *)this, (ParameterExpression *)other); case ExpressionClass::POSITIONAL_REFERENCE: return PositionalReferenceExpression::Equals((PositionalReferenceExpression *)this, (PositionalReferenceExpression *)other); @@ -153871,7 +167235,8 @@ unique_ptr ParsedExpression::Deserialize(Deserializer &source) result = WindowExpression::Deserialize(type, reader); break; default: - throw SerializationException("Unsupported type for expression deserialization!"); + throw SerializationException("Unsupported type for expression deserialization: '%s'!", + ExpressionClassToString(expression_class)); } result->alias = alias; reader.Finalize(); @@ -154054,7 +167419,7 @@ void ParsedExpressionIterator::EnumerateChildren( case ExpressionClass::LAMBDA: { auto &lambda_expr = (LambdaExpression &)expr; callback(lambda_expr.lhs); - callback(lambda_expr.rhs); + callback(lambda_expr.expr); break; } case ExpressionClass::OPERATOR: { @@ -154182,7 +167547,9 @@ void ParsedExpressionIterator::EnumerateTableRefChildren( auto &j_ref = (JoinRef &)ref; EnumerateTableRefChildren(*j_ref.left, callback); EnumerateTableRefChildren(*j_ref.right, callback); - callback(j_ref.condition); + if (j_ref.condition) { + callback(j_ref.condition); + } break; } case TableReferenceType::SUBQUERY: { @@ -154248,7 +167615,7 @@ void ParsedExpressionIterator::EnumerateQueryNodeChildren( EnumerateQueryNodeModifiers(node, callback); } - for (auto &kv : node.cte_map) { + for (auto &kv : node.cte_map.map) { EnumerateQueryNodeChildren(*kv.second->query->node, callback); } } @@ -154277,8 +167644,9 @@ void ParsedExpressionIterator::EnumerateQueryNodeChildren( + // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list // this is a bit of a mess from c.h, port.h and some others. Upside is it makes the parser compile with minimal @@ -154390,7 +167758,7 @@ typedef enum PGPostgresAttributIdentityTypes { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -154419,7 +167787,7 @@ typedef enum PGPostgresAttributIdentityTypes { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -154530,7 +167898,7 @@ uint32_t bms_hash_value(const PGBitmapset *a); // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -154583,7 +167951,7 @@ typedef enum PGLockWaitPolicy { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -154607,7 +167975,7 @@ typedef enum PGLockWaitPolicy { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -154680,7 +168048,7 @@ typedef int16_t PGAttrNumber; // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -154724,7 +168092,7 @@ typedef int16_t PGAttrNumber; // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -157181,7 +170549,7 @@ typedef struct PGOnConflictExpr { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -158392,7 +171760,7 @@ typedef struct PGUpdateStmt { * whether it is a simple or compound SELECT. * ---------------------- */ -typedef enum PGSetOperation { PG_SETOP_NONE = 0, PG_SETOP_UNION, PG_SETOP_INTERSECT, PG_SETOP_EXCEPT } PGSetOperation; +typedef enum PGSetOperation { PG_SETOP_NONE = 0, PG_SETOP_UNION, PG_SETOP_INTERSECT, PG_SETOP_EXCEPT, PG_SETOP_UNION_BY_NAME } PGSetOperation; typedef struct PGSelectStmt { PGNodeTag type; @@ -159218,7 +172586,8 @@ typedef struct PGSampleOptions { PGNodeTag type; PGNode *sample_size; /* the size of the sample to take */ char *method; /* sample method, or NULL for default */ - int seed; /* seed, or NULL for default; */ + bool has_seed; /* if the sample method has seed */ + int seed; /* the seed value if set; */ int location; /* token location, or -1 if unknown */ } PGSampleOptions; @@ -159237,7 +172606,7 @@ typedef struct PGLimitPercent { */ typedef struct PGLambdaFunction { PGNodeTag type; - PGNode *lhs; /* list of input parameters */ + PGNode *lhs; /* parameter expression */ PGNode *rhs; /* lambda expression */ int location; /* token location, or -1 if unknown */ } PGLambdaFunction; @@ -159372,7 +172741,7 @@ class Transformer { //! Transform a Postgres duckdb_libpgquery::T_PGImportStmt node into a PragmaStatement unique_ptr TransformImport(duckdb_libpgquery::PGNode *node); unique_ptr TransformExplain(duckdb_libpgquery::PGNode *node); - unique_ptr TransformVacuum(duckdb_libpgquery::PGNode *node); + unique_ptr TransformVacuum(duckdb_libpgquery::PGNode *node); unique_ptr TransformShow(duckdb_libpgquery::PGNode *node); unique_ptr TransformShowSelect(duckdb_libpgquery::PGNode *node); @@ -159407,6 +172776,7 @@ class Transformer { unique_ptr TransformValue(duckdb_libpgquery::PGValue val); //! Transform a Postgres operator into an Expression unique_ptr TransformAExpr(duckdb_libpgquery::PGAExpr *root); + unique_ptr TransformAExprInternal(duckdb_libpgquery::PGAExpr *root); //! Transform a Postgres abstract expression into an Expression unique_ptr TransformExpression(duckdb_libpgquery::PGNode *node); //! Transform a Postgres function call into an Expression @@ -159453,7 +172823,7 @@ class Transformer { //===--------------------------------------------------------------------===// OnCreateConflict TransformOnConflict(duckdb_libpgquery::PGOnCreateConflict conflict); string TransformAlias(duckdb_libpgquery::PGAlias *root, vector &column_name_alias); - void TransformCTE(duckdb_libpgquery::PGWithClause *de_with_clause, QueryNode &select); + void TransformCTE(duckdb_libpgquery::PGWithClause *de_with_clause, CommonTableExpressionMap &cte_map); unique_ptr TransformRecursiveCTE(duckdb_libpgquery::PGCommonTableExpr *node, CommonTableExpressionInfo &info); @@ -159531,6 +172901,36 @@ vector ReadPgListToString(duckdb_libpgquery::PGList *column_list); +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/statement/extension_statement.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +class ExtensionStatement : public SQLStatement { +public: + ExtensionStatement(ParserExtension extension, unique_ptr parse_data); + + //! The ParserExtension this statement was generated from + ParserExtension extension; + //! The parse data for this specific statement + unique_ptr parse_data; + +public: + unique_ptr Copy() const override; +}; + +} // namespace duckdb + @@ -159538,7 +172938,7 @@ vector ReadPgListToString(duckdb_libpgquery::PGList *column_list); // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list //===----------------------------------------------------------------------===// @@ -159557,7 +172957,7 @@ vector ReadPgListToString(duckdb_libpgquery::PGList *column_list); // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list @@ -159628,8 +173028,9 @@ class PostgresParser { + // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -159690,6 +173091,22 @@ void Parser::ParseQuery(const string &query) { parser.Parse(query); if (!parser.success) { + if (options.extensions) { + for (auto &ext : *options.extensions) { + D_ASSERT(ext.parse_function); + auto result = ext.parse_function(ext.parser_info.get(), query); + if (result.type == ParserExtensionResultType::PARSE_SUCCESSFUL) { + auto statement = make_unique(ext, move(result.parse_data)); + statement->stmt_length = query.size(); + statement->stmt_location = 0; + statements.push_back(move(statement)); + return; + } + if (result.type == ParserExtensionResultType::DISPLAY_EXTENSION_ERROR) { + throw ParserException(result.error); + } + } + } throw ParserException(QueryErrorContext::Format(query, parser.error_message, parser.error_location - 1)); } @@ -159811,12 +173228,12 @@ vector Parser::ParseOrderList(const string &select_list, ParserOpti } auto &select = (SelectStatement &)*parser.statements[0]; if (select.node->type != QueryNodeType::SELECT_NODE) { - throw InternalException("Expected a single SELECT node"); + throw ParserException("Expected a single SELECT node"); } auto &select_node = (SelectNode &)*select.node; if (select_node.modifiers.empty() || select_node.modifiers[0]->type != ResultModifierType::ORDER_MODIFIER || select_node.modifiers.size() != 1) { - throw InternalException("Expected a single ORDER clause"); + throw ParserException("Expected a single ORDER clause"); } auto &order = (OrderModifier &)*select_node.modifiers[0]; return move(order.orders); @@ -159854,7 +173271,7 @@ vector>> Parser::ParseValuesList(const strin } auto &select_node = (SelectNode &)*select.node; if (!select_node.from_table || select_node.from_table->type != TableReferenceType::EXPRESSION_LIST) { - throw InternalException("Expected a single VALUES statement"); + throw ParserException("Expected a single VALUES statement"); } auto &values_list = (ExpressionListRef &)*select_node.from_table; return move(values_list.values); @@ -160077,7 +173494,7 @@ SelectNode::SelectNode() string SelectNode::ToString() const { string result; - result = CTEToString(); + result = cte_map.ToString(); result += "SELECT "; // search for a distinct modifier @@ -160275,6 +173692,7 @@ unique_ptr SelectNode::Deserialize(FieldReader &reader) { } result->groups.grouping_sets.push_back(grouping_set); } + result->aggregate_handling = reader.ReadRequired(); result->having = reader.ReadOptional(nullptr); result->sample = reader.ReadOptional(nullptr); @@ -160286,11 +173704,12 @@ unique_ptr SelectNode::Deserialize(FieldReader &reader) { + namespace duckdb { string SetOperationNode::ToString() const { string result; - result = CTEToString(); + result = cte_map.ToString(); result += "(" + left->ToString() + ") "; bool is_distinct = false; for (idx_t modifier_idx = 0; modifier_idx < modifiers.size(); modifier_idx++) { @@ -160304,6 +173723,9 @@ string SetOperationNode::ToString() const { case SetOperationType::UNION: result += is_distinct ? "UNION" : "UNION ALL"; break; + case SetOperationType::UNION_BY_NAME: + result += is_distinct ? "UNION BY NAME" : "UNION ALL BY NAME"; + break; case SetOperationType::EXCEPT: D_ASSERT(is_distinct); result += "EXCEPT"; @@ -160373,13 +173795,29 @@ unique_ptr SetOperationNode::Deserialize(FieldReader &reader) { namespace duckdb { -string QueryNode::CTEToString() const { - if (cte_map.empty()) { +CommonTableExpressionMap::CommonTableExpressionMap() { +} + +CommonTableExpressionMap CommonTableExpressionMap::Copy() const { + CommonTableExpressionMap res; + for (auto &kv : this->map) { + auto kv_info = make_unique(); + for (auto &al : kv.second->aliases) { + kv_info->aliases.push_back(al); + } + kv_info->query = unique_ptr_cast(kv.second->query->Copy()); + res.map[kv.first] = move(kv_info); + } + return res; +} + +string CommonTableExpressionMap::ToString() const { + if (map.empty()) { return string(); } // check if there are any recursive CTEs bool has_recursive = false; - for (auto &kv : cte_map) { + for (auto &kv : map) { if (kv.second->query->node->type == QueryNodeType::RECURSIVE_CTE_NODE) { has_recursive = true; break; @@ -160390,7 +173828,7 @@ string QueryNode::CTEToString() const { result += "RECURSIVE "; } bool first_cte = true; - for (auto &kv : cte_map) { + for (auto &kv : map) { if (!first_cte) { result += ", "; } @@ -160467,12 +173905,12 @@ bool QueryNode::Equals(const QueryNode *other) const { } } // WITH clauses (CTEs) - if (cte_map.size() != other->cte_map.size()) { + if (cte_map.map.size() != other->cte_map.map.size()) { return false; } - for (auto &entry : cte_map) { - auto other_entry = other->cte_map.find(entry.first); - if (other_entry == other->cte_map.end()) { + for (auto &entry : cte_map.map) { + auto other_entry = other->cte_map.map.find(entry.first); + if (other_entry == other->cte_map.map.end()) { return false; } if (entry.second->aliases != other_entry->second->aliases) { @@ -160489,13 +173927,13 @@ void QueryNode::CopyProperties(QueryNode &other) const { for (auto &modifier : modifiers) { other.modifiers.push_back(modifier->Copy()); } - for (auto &kv : cte_map) { + for (auto &kv : cte_map.map) { auto kv_info = make_unique(); for (auto &al : kv.second->aliases) { kv_info->aliases.push_back(al); } kv_info->query = unique_ptr_cast(kv.second->query->Copy()); - other.cte_map[kv.first] = move(kv_info); + other.cte_map.map[kv.first] = move(kv_info); } } @@ -160504,9 +173942,9 @@ void QueryNode::Serialize(Serializer &main_serializer) const { writer.WriteField(type); writer.WriteSerializableList(modifiers); // cte_map - writer.WriteField((uint32_t)cte_map.size()); + writer.WriteField((uint32_t)cte_map.map.size()); auto &serializer = writer.GetSerializer(); - for (auto &cte : cte_map) { + for (auto &cte : cte_map.map) { serializer.WriteString(cte.first); serializer.WriteStringVector(cte.second->aliases); cte.second->query->Serialize(serializer); @@ -160523,15 +173961,14 @@ unique_ptr QueryNode::Deserialize(Deserializer &main_source) { // cte_map auto cte_count = reader.ReadRequired(); auto &source = reader.GetSource(); - unordered_map> cte_map; + unordered_map> new_map; for (idx_t i = 0; i < cte_count; i++) { auto name = source.Read(); auto info = make_unique(); source.ReadStringVector(info->aliases); info->query = SelectStatement::Deserialize(source); - cte_map[name] = move(info); + new_map[name] = move(info); } - unique_ptr result; switch (type) { case QueryNodeType::SELECT_NODE: @@ -160547,7 +173984,7 @@ unique_ptr QueryNode::Deserialize(Deserializer &main_source) { throw SerializationException("Could not deserialize Query Node: unknown type!"); } result->modifiers = move(modifiers); - result->cte_map = move(cte_map); + result->cte_map.map = move(new_map); reader.Finalize(); return result; } @@ -160906,6 +174343,7 @@ unique_ptr CreateStatement::Copy() const { } // namespace duckdb + namespace duckdb { DeleteStatement::DeleteStatement() : SQLStatement(StatementType::DELETE_STATEMENT) { @@ -160918,10 +174356,12 @@ DeleteStatement::DeleteStatement(const DeleteStatement &other) : SQLStatement(ot for (const auto &using_clause : other.using_clauses) { using_clauses.push_back(using_clause->Copy()); } + cte_map = other.cte_map.Copy(); } string DeleteStatement::ToString() const { string result; + result = cte_map.ToString(); result += "DELETE FROM "; result += table->ToString(); if (!using_clauses.empty()) { @@ -160969,36 +174409,6 @@ unique_ptr DropStatement::Copy() const { } } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/parser/statement/execute_statement.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - -namespace duckdb { - -class ExecuteStatement : public SQLStatement { -public: - ExecuteStatement(); - - string name; - vector> values; - -protected: - ExecuteStatement(const ExecuteStatement &other); - -public: - unique_ptr Copy() const override; -}; -} // namespace duckdb namespace duckdb { @@ -161082,6 +174492,19 @@ unique_ptr ExportStatement::Copy() const { } // namespace duckdb +namespace duckdb { + +ExtensionStatement::ExtensionStatement(ParserExtension extension_p, unique_ptr parse_data_p) + : SQLStatement(StatementType::EXTENSION_STATEMENT), extension(move(extension_p)), parse_data(move(parse_data_p)) { +} + +unique_ptr ExtensionStatement::Copy() const { + return make_unique(extension, parse_data->Copy()); +} + +} // namespace duckdb + + namespace duckdb { @@ -161093,11 +174516,13 @@ InsertStatement::InsertStatement(const InsertStatement &other) : SQLStatement(other), select_statement(unique_ptr_cast(other.select_statement->Copy())), columns(other.columns), table(other.table), schema(other.schema) { + cte_map = other.cte_map.Copy(); } string InsertStatement::ToString() const { string result; - result = "INSERT INTO "; + result = cte_map.ToString(); + result += "INSERT INTO "; if (!schema.empty()) { result += KeywordHelper::WriteOptionallyQuoted(schema) + "."; } @@ -161144,7 +174569,7 @@ ExpressionListRef *InsertStatement::GetValuesList() const { if (node.where_clause || node.qualify || node.having) { return nullptr; } - if (!node.cte_map.empty()) { + if (!node.cte_map.map.empty()) { return nullptr; } if (!node.groups.grouping_sets.empty()) { @@ -161221,35 +174646,6 @@ unique_ptr PragmaStatement::Copy() const { } } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/parser/statement/prepare_statement.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { - -class PrepareStatement : public SQLStatement { -public: - PrepareStatement(); - - unique_ptr statement; - string name; - -protected: - PrepareStatement(const PrepareStatement &other); - -public: - unique_ptr Copy() const override; -}; -} // namespace duckdb namespace duckdb { @@ -161450,6 +174846,7 @@ unique_ptr TransactionStatement::Copy() const { } // namespace duckdb + namespace duckdb { UpdateStatement::UpdateStatement() : SQLStatement(StatementType::UPDATE_STATEMENT) { @@ -161466,11 +174863,13 @@ UpdateStatement::UpdateStatement(const UpdateStatement &other) for (auto &expr : other.expressions) { expressions.emplace_back(expr->Copy()); } + cte_map = other.cte_map.Copy(); } string UpdateStatement::ToString() const { string result; - result = "UPDATE "; + result = cte_map.ToString(); + result += "UPDATE "; result += table->ToString(); result += " SET "; D_ASSERT(columns.size() == expressions.size()); @@ -161523,12 +174922,12 @@ namespace duckdb { class VacuumStatement : public SQLStatement { public: - VacuumStatement(); + explicit VacuumStatement(const VacuumOptions &options); unique_ptr info; protected: - VacuumStatement(const VacuumStatement &other) : SQLStatement(other) {}; + VacuumStatement(const VacuumStatement &other); public: unique_ptr Copy() const override; @@ -161539,7 +174938,11 @@ class VacuumStatement : public SQLStatement { namespace duckdb { -VacuumStatement::VacuumStatement() : SQLStatement(StatementType::VACUUM_STATEMENT) { +VacuumStatement::VacuumStatement(const VacuumOptions &options) + : SQLStatement(StatementType::VACUUM_STATEMENT), info(make_unique(options)) { +} + +VacuumStatement::VacuumStatement(const VacuumStatement &other) : SQLStatement(other), info(other.info->Copy()) { } unique_ptr VacuumStatement::Copy() const { @@ -162900,11 +176303,11 @@ static string SQLValueOpToString(duckdb_libpgquery::PGSQLValueFunctionOp op) { case duckdb_libpgquery::PG_SVFOP_CURRENT_DATE: return "current_date"; case duckdb_libpgquery::PG_SVFOP_CURRENT_TIME: - return "current_time"; + return "get_current_time"; case duckdb_libpgquery::PG_SVFOP_CURRENT_TIME_N: return "current_time_n"; case duckdb_libpgquery::PG_SVFOP_CURRENT_TIMESTAMP: - return "current_timestamp"; + return "get_current_timestamp"; case duckdb_libpgquery::PG_SVFOP_CURRENT_TIMESTAMP_N: return "current_timestamp_n"; case duckdb_libpgquery::PG_SVFOP_LOCALTIME: @@ -163102,11 +176505,14 @@ unique_ptr Transformer::TransformNullTest(duckdb_libpgquery::P namespace duckdb { unique_ptr Transformer::TransformLambda(duckdb_libpgquery::PGLambdaFunction *node) { - if (!node->lhs) { - throw ParserException("Lambda function must have parameters"); - } + + D_ASSERT(node->lhs); + D_ASSERT(node->rhs); + auto lhs = TransformExpression(node->lhs); auto rhs = TransformExpression(node->rhs); + D_ASSERT(lhs); + D_ASSERT(rhs); return make_unique(move(lhs), move(rhs)); } @@ -163170,7 +176576,7 @@ unique_ptr Transformer::TransformBinaryOperator(const string & } } -unique_ptr Transformer::TransformAExpr(duckdb_libpgquery::PGAExpr *root) { +unique_ptr Transformer::TransformAExprInternal(duckdb_libpgquery::PGAExpr *root) { D_ASSERT(root); auto name = string((reinterpret_cast(root->name->head->data.ptr_value))->val.str); @@ -163318,6 +176724,14 @@ unique_ptr Transformer::TransformAExpr(duckdb_libpgquery::PGAE } } +unique_ptr Transformer::TransformAExpr(duckdb_libpgquery::PGAExpr *root) { + auto result = TransformAExprInternal(root); + if (result) { + result->query_location = root->location; + } + return result; +} + } // namespace duckdb @@ -163361,6 +176775,7 @@ unique_ptr Transformer::TransformPositionalReference(duckdb_li + namespace duckdb { unique_ptr Transformer::TransformSubquery(duckdb_libpgquery::PGSubLink *root) { @@ -163390,12 +176805,14 @@ unique_ptr Transformer::TransformSubquery(duckdb_libpgquery::P string((reinterpret_cast(root->operName->head->data.ptr_value))->val.str); subquery_expr->comparison_type = OperatorToExpressionType(operator_name); } - D_ASSERT(subquery_expr->comparison_type == ExpressionType::COMPARE_EQUAL || - subquery_expr->comparison_type == ExpressionType::COMPARE_NOTEQUAL || - subquery_expr->comparison_type == ExpressionType::COMPARE_GREATERTHAN || - subquery_expr->comparison_type == ExpressionType::COMPARE_GREATERTHANOREQUALTO || - subquery_expr->comparison_type == ExpressionType::COMPARE_LESSTHAN || - subquery_expr->comparison_type == ExpressionType::COMPARE_LESSTHANOREQUALTO); + if (subquery_expr->comparison_type != ExpressionType::COMPARE_EQUAL && + subquery_expr->comparison_type != ExpressionType::COMPARE_NOTEQUAL && + subquery_expr->comparison_type != ExpressionType::COMPARE_GREATERTHAN && + subquery_expr->comparison_type != ExpressionType::COMPARE_GREATERTHANOREQUALTO && + subquery_expr->comparison_type != ExpressionType::COMPARE_LESSTHAN && + subquery_expr->comparison_type != ExpressionType::COMPARE_LESSTHANOREQUALTO) { + throw ParserException("ANY and ALL operators require one of =,<>,>,<,>=,<= comparisons!"); + } if (root->subLinkType == duckdb_libpgquery::PG_ALL_SUBLINK) { // ALL sublink is equivalent to NOT(ANY) with inverted comparison // e.g. [= ALL()] is equivalent to [NOT(<> ANY())] @@ -163411,6 +176828,46 @@ unique_ptr Transformer::TransformSubquery(duckdb_libpgquery::P subquery_expr->subquery_type = SubqueryType::SCALAR; break; } + case duckdb_libpgquery::PG_ARRAY_SUBLINK: { + auto subquery_table_alias = "__subquery"; + auto subquery_column_alias = "__arr_element"; + + // ARRAY expression + // wrap subquery into "SELECT CASE WHEN ARRAY_AGG(i) IS NULL THEN [] ELSE ARRAY_AGG(i) END FROM (...) tbl(i)" + auto select_node = make_unique(); + + // ARRAY_AGG(i) + vector> children; + children.push_back( + make_unique_base(subquery_column_alias, subquery_table_alias)); + auto aggr = make_unique("array_agg", move(children)); + // ARRAY_AGG(i) IS NULL + auto agg_is_null = make_unique(ExpressionType::OPERATOR_IS_NULL, aggr->Copy()); + // empty list + vector> list_children; + auto empty_list = make_unique("list_value", move(list_children)); + // CASE + auto case_expr = make_unique(); + CaseCheck check; + check.when_expr = move(agg_is_null); + check.then_expr = move(empty_list); + case_expr->case_checks.push_back(move(check)); + case_expr->else_expr = move(aggr); + + select_node->select_list.push_back(move(case_expr)); + + // FROM (...) tbl(i) + auto child_subquery = make_unique(move(subquery_expr->subquery), subquery_table_alias); + child_subquery->column_name_alias.emplace_back(subquery_column_alias); + select_node->from_table = move(child_subquery); + + auto new_subquery = make_unique(); + new_subquery->node = move(select_node); + subquery_expr->subquery = move(new_subquery); + + subquery_expr->subquery_type = SubqueryType::SCALAR; + break; + } default: throw NotImplementedException("Subquery of type %d not implemented\n", (int)root->subLinkType); } @@ -164265,7 +177722,7 @@ string Transformer::TransformAlias(duckdb_libpgquery::PGAlias *root, vectorquery); auto cte_name = string(cte->ctename); - auto it = select.cte_map.find(cte_name); - if (it != select.cte_map.end()) { + auto it = cte_map.map.find(cte_name); + if (it != cte_map.map.end()) { // can't have two CTEs with same name throw ParserException("Duplicate CTE name \"%s\"", cte_name); } - select.cte_map[cte_name] = move(info); + cte_map.map[cte_name] = move(info); } } @@ -164635,7 +178092,9 @@ unique_ptr Transformer::TransformSampleOptions(duckdb_libpgquery: if (sample_options.method) { result->method = GetSampleMethod(sample_options.method); } - result->seed = sample_options.seed == 0 ? -1 : sample_options.seed; + if (sample_options.has_seed) { + result->seed = sample_options.seed; + } return result; } @@ -164660,7 +178119,9 @@ LogicalType Transformer::TransformTypeName(duckdb_libpgquery::PGTypeName *type_n LogicalTypeId base_type = TransformStringToLogicalTypeId(name); LogicalType result_type; - if (base_type == LogicalTypeId::STRUCT) { + if (base_type == LogicalTypeId::LIST) { + throw ParserException("LIST is not valid as a stand-alone type"); + } else if (base_type == LogicalTypeId::STRUCT) { if (!type_name->typmods || type_name->typmods->length == 0) { throw ParserException("Struct needs a name and entries"); } @@ -164793,6 +178254,31 @@ LogicalType Transformer::TransformTypeName(duckdb_libpgquery::PGTypeName *type_n } } // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/enum_class_hash.hpp +// +// +//===----------------------------------------------------------------------===// + + + +#include + +namespace duckdb { +/* For compatibility with older C++ STL, an explicit hash class + is required for enums with C++ sets and maps */ +struct EnumClassHash { + template + std::size_t operator()(T t) const { + return static_cast(t); + } +}; +} // namespace duckdb + + + @@ -164812,12 +178298,18 @@ unique_ptr Transformer::TransformAlterSequence(duckdb_libpgquery throw InternalException("Expected an argument for ALTER SEQUENCE."); } + unordered_set used; duckdb_libpgquery::PGListCell *cell = nullptr; for_each_cell(cell, stmt->options->head) { auto *def_elem = reinterpret_cast(cell->data.ptr_value); string opt_name = string(def_elem->defname); if (opt_name == "owned_by") { + if (used.find(SequenceInfo::SEQ_OWN) != used.end()) { + throw ParserException("Owned by value should be passed as most once"); + } + used.insert(SequenceInfo::SEQ_OWN); + auto val = (duckdb_libpgquery::PGValue *)def_elem->arg; if (!val) { throw InternalException("Expected an argument for option %s", opt_name); @@ -164846,12 +178338,13 @@ unique_ptr Transformer::TransformAlterSequence(duckdb_libpgquery throw InternalException("Wrong argument for %s. Expected either . or ", opt_name); } auto info = make_unique(CatalogType::SEQUENCE_ENTRY, sequence_schema, sequence_name, - owner_schema, owner_name); + owner_schema, owner_name, stmt->missing_ok); result->info = move(info); } else { throw NotImplementedException("ALTER SEQUENCE option not supported yet!"); } } + result->info->if_exists = stmt->missing_ok; return result; } } // namespace duckdb @@ -164860,6 +178353,7 @@ unique_ptr Transformer::TransformAlterSequence(duckdb_libpgquery + namespace duckdb { unique_ptr Transformer::TransformAlter(duckdb_libpgquery::PGNode *node) { @@ -164867,8 +178361,11 @@ unique_ptr Transformer::TransformAlter(duckdb_libpgquery::PGNode D_ASSERT(stmt); D_ASSERT(stmt->relation); - auto result = make_unique(); + if (stmt->cmds->length != 1) { + throw ParserException("Only one ALTER command per statement is supported"); + } + auto result = make_unique(); auto qname = TransformQualifiedName(stmt->relation); // first we check the type of ALTER @@ -164878,6 +178375,10 @@ unique_ptr Transformer::TransformAlter(duckdb_libpgquery::PGNode switch (command->subtype) { case duckdb_libpgquery::PG_AT_AddColumn: { auto cdef = (duckdb_libpgquery::PGColumnDef *)command->def; + + if (stmt->relkind != duckdb_libpgquery::PG_OBJECT_TABLE) { + throw ParserException("Adding columns is only supported for tables"); + } if (cdef->category == duckdb_libpgquery::COL_GENERATED) { throw ParserException("Adding generated columns after table creation is not supported yet"); } @@ -164892,37 +178393,57 @@ unique_ptr Transformer::TransformAlter(duckdb_libpgquery::PGNode throw ParserException("Adding columns with constraints not yet supported"); } } - result->info = make_unique(qname.schema, qname.name, move(centry)); + result->info = make_unique(qname.schema, qname.name, stmt->missing_ok, move(centry), + command->missing_ok); break; } case duckdb_libpgquery::PG_AT_DropColumn: { bool cascade = command->behavior == duckdb_libpgquery::PG_DROP_CASCADE; - result->info = - make_unique(qname.schema, qname.name, command->name, command->missing_ok, cascade); + + if (stmt->relkind != duckdb_libpgquery::PG_OBJECT_TABLE) { + throw ParserException("Dropping columns is only supported for tables"); + } + result->info = make_unique(qname.schema, qname.name, stmt->missing_ok, command->name, + command->missing_ok, cascade); break; } case duckdb_libpgquery::PG_AT_ColumnDefault: { auto expr = TransformExpression(command->def); - result->info = make_unique(qname.schema, qname.name, command->name, move(expr)); + + if (stmt->relkind != duckdb_libpgquery::PG_OBJECT_TABLE) { + throw ParserException("Alter column's default is only supported for tables"); + } + result->info = + make_unique(qname.schema, qname.name, stmt->missing_ok, command->name, move(expr)); break; } case duckdb_libpgquery::PG_AT_AlterColumnType: { auto cdef = (duckdb_libpgquery::PGColumnDef *)command->def; auto column_definition = TransformColumnDefinition(cdef); - unique_ptr expr; + + if (stmt->relkind != duckdb_libpgquery::PG_OBJECT_TABLE) { + throw ParserException("Alter column's type is only supported for tables"); + } if (cdef->raw_default) { expr = TransformExpression(cdef->raw_default); } else { auto colref = make_unique(command->name); expr = make_unique(column_definition.Type(), move(colref)); } - result->info = make_unique(qname.schema, qname.name, command->name, + result->info = make_unique(qname.schema, qname.name, stmt->missing_ok, command->name, column_definition.Type(), move(expr)); break; } + case duckdb_libpgquery::PG_AT_SetNotNull: { + result->info = make_unique(qname.schema, qname.name, stmt->missing_ok, command->name); + break; + } + case duckdb_libpgquery::PG_AT_DropNotNull: { + result->info = make_unique(qname.schema, qname.name, stmt->missing_ok, command->name); + break; + } case duckdb_libpgquery::PG_AT_DropConstraint: - case duckdb_libpgquery::PG_AT_DropNotNull: default: throw NotImplementedException("ALTER TABLE option not supported yet!"); } @@ -165091,7 +178612,6 @@ unique_ptr Transformer::TransformCreateFunction(duckdb_libpgque auto qname = TransformQualifiedName(stmt->name); unique_ptr macro_func; - ; // function can be null here if (stmt->function) { @@ -165177,8 +178697,12 @@ unique_ptr Transformer::TransformCreateIndex(duckdb_libpgquery: D_ASSERT(stmt); auto result = make_unique(); auto info = make_unique(); + if (stmt->unique) { + info->constraint_type = IndexConstraintType::UNIQUE; + } else { + info->constraint_type = IndexConstraintType::NONE; + } - info->unique = stmt->unique; info->on_conflict = TransformOnConflict(stmt->onconflict); for (auto cell = stmt->indexParams->head; cell != nullptr; cell = cell->next) { @@ -165210,7 +178734,10 @@ unique_ptr Transformer::TransformCreateIndex(duckdb_libpgquery: if (stmt->idxname) { info->index_name = stmt->idxname; } else { - throw NotImplementedException("Index wout a name not supported yet!"); + throw NotImplementedException("Index without a name not supported yet!"); + } + for (auto &expr : info->expressions) { + info->parsed_expressions.emplace_back(expr->Copy()); } result->info = move(info); return result; @@ -165255,6 +178782,8 @@ unique_ptr Transformer::TransformCreateSchema(duckdb_libpgquery + + namespace duckdb { unique_ptr Transformer::TransformCreateSequence(duckdb_libpgquery::PGNode *node) { @@ -165268,27 +178797,35 @@ unique_ptr Transformer::TransformCreateSequence(duckdb_libpgque info->name = qname.name; if (stmt->options) { + unordered_set used; duckdb_libpgquery::PGListCell *cell = nullptr; for_each_cell(cell, stmt->options->head) { auto *def_elem = reinterpret_cast(cell->data.ptr_value); string opt_name = string(def_elem->defname); - auto val = (duckdb_libpgquery::PGValue *)def_elem->arg; - if (def_elem->defaction == duckdb_libpgquery::PG_DEFELEM_UNSPEC && !val) { // e.g. NO MINVALUE - continue; - } - D_ASSERT(val); - int64_t opt_value; - if (val->type == duckdb_libpgquery::T_PGInteger) { - opt_value = val->val.ival; - } else if (val->type == duckdb_libpgquery::T_PGFloat) { - if (!TryCast::Operation(string_t(val->val.str), opt_value, true)) { + bool nodef = def_elem->defaction == duckdb_libpgquery::PG_DEFELEM_UNSPEC && !val; // e.g. NO MINVALUE + int64_t opt_value = 0; + + if (val) { + if (val->type == duckdb_libpgquery::T_PGInteger) { + opt_value = val->val.ival; + } else if (val->type == duckdb_libpgquery::T_PGFloat) { + if (!TryCast::Operation(string_t(val->val.str), opt_value, true)) { + throw ParserException("Expected an integer argument for option %s", opt_name); + } + } else { throw ParserException("Expected an integer argument for option %s", opt_name); } - } else { - throw ParserException("Expected an integer argument for option %s", opt_name); } if (opt_name == "increment") { + if (used.find(SequenceInfo::SEQ_INC) != used.end()) { + throw ParserException("Increment value should be passed as most once"); + } + used.insert(SequenceInfo::SEQ_INC); + if (nodef) { + continue; + } + info->increment = opt_value; if (info->increment == 0) { throw ParserException("Increment must not be zero"); @@ -165301,18 +178838,50 @@ unique_ptr Transformer::TransformCreateSequence(duckdb_libpgque info->max_value = NumericLimits::Maximum(); } } else if (opt_name == "minvalue") { + if (used.find(SequenceInfo::SEQ_MIN) != used.end()) { + throw ParserException("Minvalue should be passed as most once"); + } + used.insert(SequenceInfo::SEQ_MIN); + if (nodef) { + continue; + } + info->min_value = opt_value; if (info->increment > 0) { info->start_value = info->min_value; } } else if (opt_name == "maxvalue") { + if (used.find(SequenceInfo::SEQ_MAX) != used.end()) { + throw ParserException("Maxvalue should be passed as most once"); + } + used.insert(SequenceInfo::SEQ_MAX); + if (nodef) { + continue; + } + info->max_value = opt_value; if (info->increment < 0) { info->start_value = info->max_value; } } else if (opt_name == "start") { + if (used.find(SequenceInfo::SEQ_START) != used.end()) { + throw ParserException("Start value should be passed as most once"); + } + used.insert(SequenceInfo::SEQ_START); + if (nodef) { + continue; + } + info->start_value = opt_value; } else if (opt_name == "cycle") { + if (used.find(SequenceInfo::SEQ_CYCLE) != used.end()) { + throw ParserException("Cycle value should be passed as most once"); + } + used.insert(SequenceInfo::SEQ_CYCLE); + if (nodef) { + continue; + } + info->cycle = opt_value > 0; } else { throw ParserException("Unrecognized option \"%s\" for CREATE SEQUENCE", opt_name); @@ -165540,8 +179109,15 @@ Vector ReadPgListToVector(duckdb_libpgquery::PGList *column_list, idx_t &size) { size = 0; for (auto c = column_list->head; c != nullptr; c = lnext(c)) { - auto target = (duckdb_libpgquery::PGResTarget *)(c->data.ptr_value); - result_ptr[size++] = StringVector::AddStringOrBlob(result, target->name); + auto &type_val = *((duckdb_libpgquery::PGAConst *)c->data.ptr_value); + auto entry_value_node = (duckdb_libpgquery::PGValue)(type_val.val); + if (entry_value_node.type != duckdb_libpgquery::T_PGString) { + throw ParserException("Expected a string constant as value"); + } + + auto entry_value = string(entry_value_node.val.str); + D_ASSERT(!entry_value.empty()); + result_ptr[size++] = StringVector::AddStringOrBlob(result, entry_value); } return result; } @@ -165577,6 +179153,7 @@ unique_ptr Transformer::TransformCreateType(duckdb_libpgquery:: + namespace duckdb { unique_ptr Transformer::TransformCreateView(duckdb_libpgquery::PGNode *node) { @@ -165642,6 +179219,9 @@ unique_ptr Transformer::TransformDelete(duckdb_libpgquery::PGNo auto stmt = reinterpret_cast(node); D_ASSERT(stmt); auto result = make_unique(); + if (stmt->withClause) { + TransformCTE(reinterpret_cast(stmt->withClause), result->cte_map); + } result->condition = TransformExpression(stmt->whereClause); result->table = TransformRangeVar(stmt->relation); @@ -165818,8 +179398,14 @@ unique_ptr Transformer::TransformInsert(duckdb_libpgquery::PGNo if (stmt->onConflictClause && stmt->onConflictClause->action != duckdb_libpgquery::PG_ONCONFLICT_NONE) { throw ParserException("ON CONFLICT IGNORE/UPDATE clauses are not supported"); } + if (!stmt->selectStmt) { + throw ParserException("DEFAULT VALUES clause is not supported!"); + } auto result = make_unique(); + if (stmt->withClause) { + TransformCTE(reinterpret_cast(stmt->withClause), result->cte_map); + } // first check if there are any columns specified if (stmt->cols) { @@ -166033,14 +179619,14 @@ unique_ptr Transformer::TransformRename(duckdb_libpgquery::PGNod // get the old name and the new name string old_name = stmt->subname; string new_name = stmt->newname; - info = make_unique(schema, table, old_name, new_name); + info = make_unique(schema, table, stmt->missing_ok, old_name, new_name); break; } case duckdb_libpgquery::PG_OBJECT_TABLE: { // change table name // get the table and schema - string schema = DEFAULT_SCHEMA; + string schema = INVALID_SCHEMA; string table; D_ASSERT(stmt->relation->relname); if (stmt->relation->relname) { @@ -166050,7 +179636,7 @@ unique_ptr Transformer::TransformRename(duckdb_libpgquery::PGNod schema = stmt->relation->schemaname; } string new_name = stmt->newname; - info = make_unique(schema, table, new_name); + info = make_unique(schema, table, stmt->missing_ok, new_name); break; } @@ -166058,7 +179644,7 @@ unique_ptr Transformer::TransformRename(duckdb_libpgquery::PGNod // change view name // get the view and schema - string schema = DEFAULT_SCHEMA; + string schema = INVALID_SCHEMA; string view; D_ASSERT(stmt->relation->relname); if (stmt->relation->relname) { @@ -166068,7 +179654,7 @@ unique_ptr Transformer::TransformRename(duckdb_libpgquery::PGNod schema = stmt->relation->schemaname; } string new_name = stmt->newname; - info = make_unique(schema, view, new_name); + info = make_unique(schema, view, stmt->missing_ok, new_name); break; } case duckdb_libpgquery::PG_OBJECT_DATABASE: @@ -166076,6 +179662,7 @@ unique_ptr Transformer::TransformRename(duckdb_libpgquery::PGNod throw NotImplementedException("Schema element not supported yet!"); } D_ASSERT(info); + info->if_exists = stmt->missing_ok; auto result = make_unique(); result->info = move(info); @@ -166129,7 +179716,7 @@ unique_ptr Transformer::TransformSelectNode(duckdb_libpgquery::PGSele node = make_unique(); auto result = (SelectNode *)node.get(); if (stmt->withClause) { - TransformCTE(reinterpret_cast(stmt->withClause), *node); + TransformCTE(reinterpret_cast(stmt->withClause), node->cte_map); } if (stmt->windowClause) { for (auto window_ele = stmt->windowClause->head; window_ele != nullptr; window_ele = window_ele->next) { @@ -166187,11 +179774,12 @@ unique_ptr Transformer::TransformSelectNode(duckdb_libpgquery::PGSele } case duckdb_libpgquery::PG_SETOP_UNION: case duckdb_libpgquery::PG_SETOP_EXCEPT: - case duckdb_libpgquery::PG_SETOP_INTERSECT: { + case duckdb_libpgquery::PG_SETOP_INTERSECT: + case duckdb_libpgquery::PG_SETOP_UNION_BY_NAME: { node = make_unique(); auto result = (SetOperationNode *)node.get(); if (stmt->withClause) { - TransformCTE(reinterpret_cast(stmt->withClause), *node); + TransformCTE(reinterpret_cast(stmt->withClause), node->cte_map); } result->left = TransformSelectNode(stmt->larg); result->right = TransformSelectNode(stmt->rarg); @@ -166211,6 +179799,10 @@ unique_ptr Transformer::TransformSelectNode(duckdb_libpgquery::PGSele case duckdb_libpgquery::PG_SETOP_INTERSECT: result->setop_type = SetOperationType::INTERSECT; break; + case duckdb_libpgquery::PG_SETOP_UNION_BY_NAME: + select_distinct = !stmt->all; + result->setop_type = SetOperationType::UNION_BY_NAME; + break; default: throw Exception("Unexpected setop type"); } @@ -166410,6 +180002,9 @@ unique_ptr Transformer::TransformUpdate(duckdb_libpgquery::PGNo D_ASSERT(stmt); auto result = make_unique(); + if (stmt->withClause) { + TransformCTE(reinterpret_cast(stmt->withClause), result->cte_map); + } result->table = TransformRangeVar(stmt->relation); if (stmt->fromClause) { @@ -166438,12 +180033,55 @@ unique_ptr Transformer::TransformUpdate(duckdb_libpgquery::PGNo namespace duckdb { -unique_ptr Transformer::TransformVacuum(duckdb_libpgquery::PGNode *node) { +VacuumOptions ParseOptions(int options) { + VacuumOptions result; + if (options & duckdb_libpgquery::PGVacuumOption::PG_VACOPT_VACUUM) { + result.vacuum = true; + } + if (options & duckdb_libpgquery::PGVacuumOption::PG_VACOPT_ANALYZE) { + result.analyze = true; + } + if (options & duckdb_libpgquery::PGVacuumOption::PG_VACOPT_VERBOSE) { + throw NotImplementedException("Verbose vacuum option"); + } + if (options & duckdb_libpgquery::PGVacuumOption::PG_VACOPT_FREEZE) { + throw NotImplementedException("Freeze vacuum option"); + } + if (options & duckdb_libpgquery::PGVacuumOption::PG_VACOPT_FULL) { + throw NotImplementedException("Full vacuum option"); + } + if (options & duckdb_libpgquery::PGVacuumOption::PG_VACOPT_NOWAIT) { + throw NotImplementedException("No Wait vacuum option"); + } + if (options & duckdb_libpgquery::PGVacuumOption::PG_VACOPT_SKIPTOAST) { + throw NotImplementedException("Skip Toast vacuum option"); + } + if (options & duckdb_libpgquery::PGVacuumOption::PG_VACOPT_DISABLE_PAGE_SKIPPING) { + throw NotImplementedException("Disable Page Skipping vacuum option"); + } + return result; +} + +unique_ptr Transformer::TransformVacuum(duckdb_libpgquery::PGNode *node) { auto stmt = reinterpret_cast(node); D_ASSERT(stmt); - (void)stmt; - auto result = make_unique(); - return result; + + auto result = make_unique(ParseOptions(stmt->options)); + + if (stmt->relation) { + result->info->ref = TransformRangeVar(stmt->relation); + result->info->has_table = true; + } + + if (stmt->va_cols) { + D_ASSERT(result->info->has_table); + for (auto col_node = stmt->va_cols->head; col_node != nullptr; col_node = col_node->next) { + result->info->columns.emplace_back( + reinterpret_cast(col_node->data.ptr_value)->val.str); + } + } + + return move(result); } } // namespace duckdb @@ -166601,6 +180239,9 @@ unique_ptr Transformer::TransformRangeSubselect(duckdb_libpgquery::PGR if (!subquery) { return nullptr; } + if (root->lateral) { + throw NotImplementedException("LATERAL not implemented"); + } auto result = make_unique(move(subquery)); result->alias = TransformAlias(root->alias, result->column_name_alias); if (root->sample) { @@ -166698,6 +180339,36 @@ unique_ptr Transformer::TransformTableRefNode(duckdb_libpgquery::PGNod +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/statement/logical_plan_statement.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +class LogicalPlanStatement : public SQLStatement { +public: + explicit LogicalPlanStatement(unique_ptr plan_p) + : SQLStatement(StatementType::LOGICAL_PLAN_STATEMENT), plan(move(plan_p)) {}; + + unique_ptr plan; + +public: + unique_ptr Copy() const override { + throw NotImplementedException("PLAN_STATEMENT"); + } +}; + +} // namespace duckdb + @@ -166868,8 +180539,6 @@ unique_ptr Transformer::TransformStatementInternal(duckdb_libpgque - - #include namespace duckdb { @@ -167211,16 +180880,45 @@ void BindContext::GenerateAllColumnExpressions(StarExpression &expr, } } else { // SELECT tbl.* case + // SELECT struct.* case string error; auto binding = GetBinding(expr.relation_name, error); + bool is_struct_ref = false; if (!binding) { - throw BinderException(error); - } - for (auto &column_name : binding->names) { - if (CheckExclusionList(expr, binding, column_name, new_select_list, excluded_columns)) { - continue; + auto binding_name = GetMatchingBinding(expr.relation_name); + if (binding_name.empty()) { + throw BinderException(error); + } + binding = bindings[binding_name].get(); + is_struct_ref = true; + } + + if (is_struct_ref) { + auto col_idx = binding->GetBindingIndex(expr.relation_name); + auto col_type = binding->types[col_idx]; + if (col_type.id() != LogicalTypeId::STRUCT) { + throw BinderException(StringUtil::Format( + "Cannot extract field from expression \"%s\" because it is not a struct", expr.ToString())); + } + auto &struct_children = StructType::GetChildTypes(col_type); + vector column_names(3); + column_names[0] = binding->alias; + column_names[1] = expr.relation_name; + for (auto &child : struct_children) { + if (CheckExclusionList(expr, binding, child.first, new_select_list, excluded_columns)) { + continue; + } + column_names[2] = child.first; + new_select_list.push_back(make_unique(column_names)); + } + } else { + for (auto &column_name : binding->names) { + if (CheckExclusionList(expr, binding, column_name, new_select_list, excluded_columns)) { + continue; + } + + new_select_list.push_back(make_unique(column_name, binding->alias)); } - new_select_list.push_back(make_unique(column_name, binding->alias)); } } for (auto &excluded : expr.exclude_list) { @@ -167459,35 +181157,6 @@ class SelectBinder : public ExpressionBinder { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/bound_tableref.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - -namespace duckdb { - -class BoundTableRef { -public: - explicit BoundTableRef(TableReferenceType type) : type(type) { - } - virtual ~BoundTableRef() { - } - - //! The type of table reference - TableReferenceType type; - //! The sample options (if any) - unique_ptr sample; -}; -} // namespace duckdb @@ -167620,7 +181289,8 @@ BindResult SelectBinder::BindAggregate(FunctionExpression &aggr, AggregateFuncti if (ordered_set_agg) { auto &config = DBConfig::GetConfig(context); const auto &order = aggr.order_bys->orders[0]; - const auto sense = (order.type == OrderType::ORDER_DEFAULT) ? config.default_order_type : order.type; + const auto sense = + (order.type == OrderType::ORDER_DEFAULT) ? config.options.default_order_type : order.type; invert_fractions = (sense == OrderType::DESCENDING); } } @@ -167711,13 +181381,12 @@ BindResult SelectBinder::BindAggregate(FunctionExpression &aggr, AggregateFuncti } // bind the aggregate - bool cast_parameters; - idx_t best_function = Function::BindFunction(func->name, func->functions, types, error, cast_parameters); + idx_t best_function = Function::BindFunction(func->name, func->functions, types, error); if (best_function == DConstants::INVALID_INDEX) { throw BinderException(binder.FormatError(aggr, error)); } // found a matching function! - auto &bound_function = func->functions[best_function]; + auto bound_function = func->functions.GetFunctionByOffset(best_function); // Bind any sort columns, unless the aggregate is order-insensitive auto order_bys = make_unique(); @@ -167725,15 +181394,17 @@ BindResult SelectBinder::BindAggregate(FunctionExpression &aggr, AggregateFuncti auto &config = DBConfig::GetConfig(context); for (auto &order : aggr.order_bys->orders) { auto &order_expr = (BoundExpression &)*order.expression; - const auto sense = (order.type == OrderType::ORDER_DEFAULT) ? config.default_order_type : order.type; - const auto null_order = - (order.null_order == OrderByNullType::ORDER_DEFAULT) ? config.default_null_order : order.null_order; + const auto sense = + (order.type == OrderType::ORDER_DEFAULT) ? config.options.default_order_type : order.type; + const auto null_order = (order.null_order == OrderByNullType::ORDER_DEFAULT) + ? config.options.default_null_order + : order.null_order; order_bys->orders.emplace_back(BoundOrderByNode(sense, null_order, move(order_expr.expr))); } } - auto aggregate = AggregateFunction::BindAggregateFunction( - context, bound_function, move(children), move(bound_filter), aggr.distinct, move(order_bys), cast_parameters); + auto aggregate = AggregateFunction::BindAggregateFunction(context, bound_function, move(children), + move(bound_filter), aggr.distinct, move(order_bys)); if (aggr.export_state) { aggregate = ExportAggregateFunction::Bind(move(aggregate)); } @@ -167766,6 +181437,7 @@ BindResult SelectBinder::BindAggregate(FunctionExpression &aggr, AggregateFuncti + namespace duckdb { BindResult ExpressionBinder::BindExpression(BetweenExpression &expr, idx_t depth) { @@ -167888,14 +181560,8 @@ BindResult ExpressionBinder::BindExpression(CastExpression &expr, idx_t depth) { } child.expr = make_unique(move(child.expr), expr.cast_type, true); } else { - if (child.expr->type == ExpressionType::VALUE_PARAMETER) { - auto ¶meter = (BoundParameterExpression &)*child.expr; - // parameter: move types into the parameter expression itself - parameter.return_type = expr.cast_type; - } else { - // otherwise add a cast to the target type - child.expr = BoundCastExpression::AddCastToType(move(child.expr), expr.cast_type); - } + // otherwise add a cast to the target type + child.expr = BoundCastExpression::AddCastToType(move(child.expr), expr.cast_type); } return BindResult(move(child.expr)); } @@ -167903,6 +181569,7 @@ BindResult ExpressionBinder::BindExpression(CastExpression &expr, idx_t depth) { + namespace duckdb { BindResult ExpressionBinder::BindExpression(CollateExpression &expr, idx_t depth) { @@ -167912,6 +181579,9 @@ BindResult ExpressionBinder::BindExpression(CollateExpression &expr, idx_t depth return BindResult(error); } auto &child = (BoundExpression &)*expr.child; + if (child.expr->HasParameter()) { + throw ParameterNotResolvedException(); + } if (child.expr->return_type.id() != LogicalTypeId::VARCHAR) { throw BinderException("collations are only supported for type varchar"); } @@ -167990,17 +181660,40 @@ unique_ptr ExpressionBinder::QualifyColumnName(const string &c return move(coalesce); } } - // no table name: find a binding that contains this + + // find a binding that contains this + string table_name = binder.bind_context.GetMatchingBinding(column_name); + + // throw an error if a macro conflicts with a column name + auto is_macro_column = false; if (binder.macro_binding != nullptr && binder.macro_binding->HasMatchingBinding(column_name)) { - // priority to macro parameter bindings TODO: throw a warning when this name conflicts - D_ASSERT(!binder.macro_binding->alias.empty()); - return make_unique(column_name, binder.macro_binding->alias); - } else { - // see if it's a column - string table_name = binder.bind_context.GetMatchingBinding(column_name); + is_macro_column = true; if (!table_name.empty()) { - return binder.bind_context.CreateColumnReference(table_name, column_name); + throw BinderException("Conflicting column names for column " + column_name + "!"); + } + } + + if (lambda_bindings) { + for (idx_t i = 0; i < lambda_bindings->size(); i++) { + if ((*lambda_bindings)[i].HasMatchingBinding(column_name)) { + + // throw an error if a lambda conflicts with a column name or a macro + if (!table_name.empty() || is_macro_column) { + throw BinderException("Conflicting column names for column " + column_name + "!"); + } + + D_ASSERT(!(*lambda_bindings)[i].alias.empty()); + return make_unique(column_name, (*lambda_bindings)[i].alias); + } } + } + + if (is_macro_column) { + D_ASSERT(!binder.macro_binding->alias.empty()); + return make_unique(column_name, binder.macro_binding->alias); + } + // see if it's a column + if (table_name.empty()) { // it's not, find candidates and error auto similar_bindings = binder.bind_context.GetSimilarBindings(column_name); string candidate_str = StringUtil::CandidatesMessage(similar_bindings, "Candidate bindings"); @@ -168008,6 +181701,7 @@ unique_ptr ExpressionBinder::QualifyColumnName(const string &c StringUtil::Format("Referenced column \"%s\" not found in FROM clause!%s", column_name, candidate_str); return nullptr; } + return binder.bind_context.CreateColumnReference(table_name, column_name); } void ExpressionBinder::QualifyColumnNames(unique_ptr &expr) { @@ -168186,12 +181880,29 @@ BindResult ExpressionBinder::BindExpression(ColumnRefExpression &colref_p, idx_t // individual column reference // resolve to either a base table or a subquery expression // if it was a macro parameter, let macro_binding bind it to the argument + // if it was a lambda parameter, let lambda_bindings bind it to the argument + BindResult result; - if (binder.macro_binding && table_name == binder.macro_binding->alias) { - result = binder.macro_binding->Bind(colref, depth); - } else { - result = binder.bind_context.BindColumn(colref, depth); + + auto found_lambda_binding = false; + if (lambda_bindings) { + for (idx_t i = 0; i < lambda_bindings->size(); i++) { + if (table_name == (*lambda_bindings)[i].alias) { + result = (*lambda_bindings)[i].Bind(colref, depth); + found_lambda_binding = true; + break; + } + } + } + + if (!found_lambda_binding) { + if (binder.macro_binding && table_name == binder.macro_binding->alias) { + result = binder.macro_binding->Bind(colref, depth); + } else { + result = binder.bind_context.BindColumn(colref, depth); + } } + if (!result.HasError()) { BoundColumnReferenceInfo ref; ref.name = colref.column_names.back(); @@ -168220,6 +181931,7 @@ BindResult ExpressionBinder::BindExpression(ColumnRefExpression &colref_p, idx_t + namespace duckdb { unique_ptr ExpressionBinder::PushCollation(ClientContext &context, unique_ptr source, @@ -168227,7 +181939,7 @@ unique_ptr ExpressionBinder::PushCollation(ClientContext &context, u // replace default collation with system collation string collation; if (collation_p.empty()) { - collation = DBConfig::GetConfig(context).collation; + collation = DBConfig::GetConfig(context).options.collation; } else { collation = collation_p; } @@ -168394,6 +182106,7 @@ BindResult ExpressionBinder::BindExpression(ConstantExpression &expr, idx_t dept + namespace duckdb { BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t depth, @@ -168410,10 +182123,23 @@ BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t auto &catalog = Catalog::GetCatalog(context); auto func = catalog.GetEntry(context, CatalogType::SCALAR_FUNCTION_ENTRY, function.schema, function.function_name, false, error_context); + switch (func->type) { case CatalogType::SCALAR_FUNCTION_ENTRY: // scalar function + + // check for lambda parameters, ignore ->> operator (JSON extension) + if (function.function_name != "->>") { + for (auto &child : function.children) { + if (child->expression_class == ExpressionClass::LAMBDA) { + return BindLambdaFunction(function, (ScalarFunctionCatalogEntry *)func, depth); + } + } + } + + // other scalar function return BindFunction(function, (ScalarFunctionCatalogEntry *)func, depth); + case CatalogType::MACRO_ENTRY: // macro function return BindMacro(function, (ScalarMacroCatalogEntry *)func, depth, expr_ptr); @@ -168424,11 +182150,15 @@ BindResult ExpressionBinder::BindExpression(FunctionExpression &function, idx_t } BindResult ExpressionBinder::BindFunction(FunctionExpression &function, ScalarFunctionCatalogEntry *func, idx_t depth) { + // bind the children of the function expression string error; + + // bind of each child for (idx_t i = 0; i < function.children.size(); i++) { BindChild(function.children[i], depth, error); } + if (!error.empty()) { return BindResult(error); } @@ -168445,13 +182175,105 @@ BindResult ExpressionBinder::BindFunction(FunctionExpression &function, ScalarFu children.push_back(move(child.expr)); } unique_ptr result = - ScalarFunction::BindScalarFunction(context, *func, move(children), error, function.is_operator); + ScalarFunction::BindScalarFunction(context, *func, move(children), error, function.is_operator, &binder); if (!result) { throw BinderException(binder.FormatError(function, error)); } return BindResult(move(result)); } +BindResult ExpressionBinder::BindLambdaFunction(FunctionExpression &function, ScalarFunctionCatalogEntry *func, + idx_t depth) { + + // bind the children of the function expression + string error; + + if (function.children.size() != 2) { + throw BinderException("Invalid function arguments!"); + } + D_ASSERT(function.children[1]->GetExpressionClass() == ExpressionClass::LAMBDA); + + // bind the list parameter + BindChild(function.children[0], depth, error); + if (!error.empty()) { + return BindResult(error); + } + + // get the logical type of the children of the list + auto &list_child = (BoundExpression &)*function.children[0]; + + if (list_child.expr->return_type.id() != LogicalTypeId::LIST && + list_child.expr->return_type.id() != LogicalTypeId::SQLNULL && + list_child.expr->return_type.id() != LogicalTypeId::UNKNOWN) { + throw BinderException(" Invalid LIST argument to " + function.function_name + "!"); + } + + LogicalType list_child_type = list_child.expr->return_type.id(); + if (list_child.expr->return_type.id() != LogicalTypeId::SQLNULL && + list_child.expr->return_type.id() != LogicalTypeId::UNKNOWN) { + list_child_type = ListType::GetChildType(list_child.expr->return_type); + } + + // bind the lambda parameter + auto &lambda_expr = (LambdaExpression &)*function.children[1]; + BindResult bind_lambda_result = BindExpression(lambda_expr, depth, true, list_child_type); + + if (bind_lambda_result.HasError()) { + error = bind_lambda_result.error; + } else { + // successfully bound: replace the node with a BoundExpression + auto alias = function.children[1]->alias; + function.children[1] = make_unique(move(bind_lambda_result.expression)); + auto be = (BoundExpression *)function.children[1].get(); + D_ASSERT(be); + be->alias = alias; + if (!alias.empty()) { + be->expr->alias = alias; + } + } + + if (!error.empty()) { + return BindResult(error); + } + if (binder.GetBindingMode() == BindingMode::EXTRACT_NAMES) { + return BindResult(make_unique(Value(LogicalType::SQLNULL))); + } + + // all children bound successfully + // extract the children and types + vector> children; + for (idx_t i = 0; i < function.children.size(); i++) { + auto &child = (BoundExpression &)*function.children[i]; + D_ASSERT(child.expr); + children.push_back(move(child.expr)); + } + + // capture the (lambda) columns + auto &bound_lambda_expr = (BoundLambdaExpression &)*children.back(); + CaptureLambdaColumns(bound_lambda_expr.captures, list_child_type, bound_lambda_expr.lambda_expr, + children[0]->alias); + + unique_ptr result = + ScalarFunction::BindScalarFunction(context, *func, move(children), error, function.is_operator, &binder); + if (!result) { + throw BinderException(binder.FormatError(function, error)); + } + + // remove the lambda expression from the children + auto &bound_function_expr = (BoundFunctionExpression &)*result; + auto lambda = move(bound_function_expr.children.back()); + bound_function_expr.children.pop_back(); + auto &bound_lambda = (BoundLambdaExpression &)*lambda; + + // push back the captures into the children vector and the correct return types into the bound_function arguments + for (auto &capture : bound_lambda.captures) { + bound_function_expr.function.arguments.push_back(capture->return_type); + bound_function_expr.children.push_back(move(capture)); + } + + return BindResult(move(result)); +} + BindResult ExpressionBinder::BindAggregate(FunctionExpression &expr, AggregateFunctionCatalogEntry *function, idx_t depth) { return BindResult(binder.FormatError(expr, UnsupportedAggregateMessage())); @@ -168474,37 +182296,158 @@ string ExpressionBinder::UnsupportedUnnestMessage() { + + + + + + + namespace duckdb { -// static string ExtractColumnFromLambda(ParsedExpression &expr) { -// if (expr.type != ExpressionType::COLUMN_REF) { -// throw ParserException("Lambda parameter must be a column name"); -// } -// auto &colref = (ColumnRefExpression &)expr; -// if (colref.IsQualified()) { -// throw ParserException("Lambda parameter must be an unqualified name (e.g. 'x', not 'a.x')"); -// } -// return colref.column_names[0]; -// } +BindResult ExpressionBinder::BindExpression(LambdaExpression &expr, idx_t depth, const bool is_lambda, + const LogicalType &list_child_type) { -BindResult ExpressionBinder::BindExpression(LambdaExpression &expr, idx_t depth) { - string error; + if (!is_lambda) { + // this is for binding JSON + auto lhs_expr = expr.lhs->Copy(); + OperatorExpression arrow_expr(ExpressionType::ARROW, move(lhs_expr), expr.expr->Copy()); + return BindExpression(arrow_expr, depth); + } - // FIXME: decide from the context whether this is actually a LambdaExpression - // If it is, bind it as a lambda here - // // set up the lambda capture - // FIXME: need to get the type from the list for binding - // lambda_capture = expr.capture_name; - // // bind the child - // BindChild(expr.expression, depth, error); - // // clear the lambda capture - // lambda_capture = ""; - // if (!error.empty()) { - // return BindResult(error); - // } - // expr.Print(); - OperatorExpression arrow_expr(ExpressionType::ARROW, move(expr.lhs), move(expr.rhs)); - return ExpressionBinder::BindExpression(arrow_expr, depth); + // binding the lambda expression + D_ASSERT(expr.lhs); + if (expr.lhs->expression_class != ExpressionClass::FUNCTION && + expr.lhs->expression_class != ExpressionClass::COLUMN_REF) { + throw BinderException( + "Invalid parameter list! Parameters must be comma-separated column names, e.g. x or (x, y)."); + } + + // move the lambda parameters to the params vector + if (expr.lhs->expression_class == ExpressionClass::COLUMN_REF) { + expr.params.push_back(move(expr.lhs)); + } else { + auto &func_expr = (FunctionExpression &)*expr.lhs; + for (idx_t i = 0; i < func_expr.children.size(); i++) { + expr.params.push_back(move(func_expr.children[i])); + } + } + D_ASSERT(!expr.params.empty()); + + // create dummy columns for the lambda parameters (lhs) + vector column_types; + vector column_names; + vector params_strings; + + // positional parameters as column references + for (idx_t i = 0; i < expr.params.size(); i++) { + + if (expr.params[i]->GetExpressionClass() != ExpressionClass::COLUMN_REF) { + throw BinderException("Parameter must be a column name."); + } + + auto column_ref = (ColumnRefExpression &)*expr.params[i]; + if (column_ref.IsQualified()) { + throw BinderException("Invalid parameter name '%s': must be unqualified", column_ref.ToString()); + } + + column_types.emplace_back(list_child_type); + column_names.push_back(column_ref.GetColumnName()); + params_strings.push_back(expr.params[i]->ToString()); + } + + // base table alias + auto params_alias = StringUtil::Join(params_strings, ", "); + if (params_strings.size() > 1) { + params_alias = "(" + params_alias + ")"; + } + + // create a lambda binding and push it to the lambda bindings vector + vector local_bindings; + if (!lambda_bindings) { + lambda_bindings = &local_bindings; + } + DummyBinding new_lambda_binding(column_types, column_names, params_alias); + lambda_bindings->push_back(new_lambda_binding); + + // bind the parameter expressions + for (idx_t i = 0; i < expr.params.size(); i++) { + auto result = BindExpression(&expr.params[i], depth, false); + D_ASSERT(!result.HasError()); + } + + auto result = BindExpression(&expr.expr, depth, false); + lambda_bindings->pop_back(); + + // successfully bound a subtree of nested lambdas, set this to nullptr in case other parts of the + // query also contain lambdas + if (lambda_bindings->empty()) { + lambda_bindings = nullptr; + } + + if (result.HasError()) { + throw BinderException(result.error); + } + + return BindResult(make_unique(ExpressionType::LAMBDA, LogicalType::LAMBDA, + move(result.expression), params_strings.size())); +} + +void ExpressionBinder::TransformCapturedLambdaColumn(unique_ptr &original, + unique_ptr &replacement, + vector> &captures, + LogicalType &list_child_type, string &alias) { + + // check if the original expression is a lambda parameter + bool is_lambda_parameter = false; + if (original->expression_class == ExpressionClass::BOUND_COLUMN_REF) { + + // determine if this is the lambda parameter + auto &bound_col_ref = (BoundColumnRefExpression &)*original; + if (bound_col_ref.binding.table_index == DConstants::INVALID_INDEX) { + is_lambda_parameter = true; + } + } + + if (is_lambda_parameter) { + // this is a lambda parameter, so the replacement refers to the first argument, which is the list + replacement = make_unique(alias, list_child_type, 0); + + } else { + // this is not a lambda parameter, so we need to create a new argument for the arguments vector + replacement = + make_unique(original->alias, original->return_type, captures.size() + 1); + captures.push_back(move(original)); + } +} + +void ExpressionBinder::CaptureLambdaColumns(vector> &captures, LogicalType &list_child_type, + unique_ptr &expr, string &alias) { + + if (expr->expression_class == ExpressionClass::BOUND_SUBQUERY) { + throw InvalidInputException("Subqueries are not supported in lambda expressions!"); + } + + // these expression classes do not have children, transform them + if (expr->expression_class == ExpressionClass::BOUND_CONSTANT || + expr->expression_class == ExpressionClass::BOUND_COLUMN_REF || + expr->expression_class == ExpressionClass::BOUND_PARAMETER) { + + // move the expr because we are going to replace it + auto original = move(expr); + unique_ptr replacement; + + TransformCapturedLambdaColumn(original, replacement, captures, list_child_type, alias); + + // replace the expression + expr = move(replacement); + + } else { + // recursively enumerate the children of the expression + ExpressionIterator::EnumerateChildren(*expr, [&](unique_ptr &child) { + CaptureLambdaColumns(captures, list_child_type, child, alias); + }); + } } } // namespace duckdb @@ -168526,7 +182469,10 @@ void ExpressionBinder::ReplaceMacroParametersRecursive(unique_ptrHasMatchingBinding(colref.GetColumnName()); } @@ -168553,7 +182499,6 @@ void ExpressionBinder::ReplaceMacroParametersRecursive(unique_ptr *expr) { - // recast function so we can access the scalar member function->expression auto ¯o_def = (ScalarMacroFunction &)*macro_func->function; @@ -168583,8 +182528,8 @@ BindResult ExpressionBinder::BindMacro(FunctionExpression &function, ScalarMacro // now push the defaults into the positionals positionals.push_back(move(defaults[it->first])); } - auto new_macro_binding = make_unique(types, names, macro_func->name); - new_macro_binding->arguments = move(positionals); + auto new_macro_binding = make_unique(types, names, macro_func->name); + new_macro_binding->arguments = &positionals; macro_binding = new_macro_binding.get(); // replace current expression with stored macro expression, and replace params @@ -168603,6 +182548,7 @@ BindResult ExpressionBinder::BindMacro(FunctionExpression &function, ScalarMacro + namespace duckdb { static LogicalType ResolveNotType(OperatorExpression &op, vector &children) { @@ -168635,6 +182581,9 @@ static LogicalType ResolveOperatorType(OperatorExpression &op, vectorexpr->return_type.IsValid()) { + throw ParameterNotResolvedException(); + } return LogicalType::BOOLEAN; case ExpressionType::COMPARE_IN: case ExpressionType::COMPARE_NOT_IN: @@ -168740,17 +182689,38 @@ BindResult ExpressionBinder::BindExpression(OperatorExpression &op, idx_t depth) + namespace duckdb { BindResult ExpressionBinder::BindExpression(ParameterExpression &expr, idx_t depth) { D_ASSERT(expr.parameter_nr > 0); auto bound_parameter = make_unique(expr.parameter_nr); + bound_parameter->alias = expr.alias; if (!binder.parameters) { - throw std::runtime_error("Unexpected prepared parameter. This type of statement can't be prepared!"); - } - binder.parameters->push_back(bound_parameter.get()); - if (binder.parameter_types && expr.parameter_nr <= binder.parameter_types->size()) { - bound_parameter->return_type = (*binder.parameter_types)[expr.parameter_nr - 1]; + throw BinderException("Unexpected prepared parameter. This type of statement can't be prepared!"); + } + auto parameter_idx = expr.parameter_nr; + // check if a parameter value has already been supplied + if (parameter_idx <= binder.parameters->parameter_data.size()) { + // it has! emit a constant directly + auto &data = binder.parameters->parameter_data[parameter_idx - 1]; + auto constant = make_unique(data.value); + constant->alias = expr.alias; + return BindResult(move(constant)); + } + auto entry = binder.parameters->parameters.find(parameter_idx); + if (entry == binder.parameters->parameters.end()) { + // no entry yet: create a new one + auto data = make_shared(); + data->return_type = binder.parameters->GetReturnType(parameter_idx - 1); + bound_parameter->return_type = data->return_type; + bound_parameter->parameter_data = data; + binder.parameters->parameters[parameter_idx] = move(data); + } else { + // a prepared statement with this parameter index was already there: use it + auto &data = entry->second; + bound_parameter->parameter_data = data; + bound_parameter->return_type = binder.parameters->GetReturnType(parameter_idx - 1); } return BindResult(move(bound_parameter)); } @@ -168883,6 +182853,7 @@ BindResult ExpressionBinder::BindExpression(SubqueryExpression &expr, idx_t dept + namespace duckdb { BindResult SelectBinder::BindUnnest(FunctionExpression &function, idx_t depth) { @@ -168904,7 +182875,8 @@ BindResult SelectBinder::BindUnnest(FunctionExpression &function, idx_t depth) { auto &child = (BoundExpression &)*function.children[0]; auto &child_type = child.expr->return_type; - if (child_type.id() != LogicalTypeId::LIST && child_type.id() != LogicalTypeId::SQLNULL) { + if (child_type.id() != LogicalTypeId::LIST && child_type.id() != LogicalTypeId::SQLNULL && + child_type.id() != LogicalTypeId::UNKNOWN) { return BindResult(binder.FormatError(function, "Unnest() can only be applied to lists and NULL")); } @@ -168915,6 +182887,8 @@ BindResult SelectBinder::BindUnnest(FunctionExpression &function, idx_t depth) { auto return_type = LogicalType(LogicalTypeId::SQLNULL); if (child_type.id() == LogicalTypeId::LIST) { return_type = ListType::GetChildType(child_type); + } else if (child_type.id() == LogicalTypeId::UNKNOWN) { + throw ParameterNotResolvedException(); } auto result = make_unique(return_type); @@ -169000,11 +182974,11 @@ static LogicalType ResolveWindowExpressionType(ExpressionType window_type, const } static inline OrderType ResolveOrderType(const DBConfig &config, OrderType type) { - return (type == OrderType::ORDER_DEFAULT) ? config.default_order_type : type; + return (type == OrderType::ORDER_DEFAULT) ? config.options.default_order_type : type; } static inline OrderByNullType ResolveNullOrder(const DBConfig &config, OrderByNullType null_order) { - return (null_order == OrderByNullType::ORDER_DEFAULT) ? config.default_null_order : null_order; + return (null_order == OrderByNullType::ORDER_DEFAULT) ? config.options.default_null_order : null_order; } static unique_ptr GetExpression(unique_ptr &expr) { @@ -169138,7 +183112,7 @@ BindResult SelectBinder::BindWindow(WindowExpression &window, idx_t depth) { throw BinderException(binder.FormatError(window, error)); } // found a matching function! bind it as an aggregate - auto &bound_function = func->functions[best_function]; + auto bound_function = func->functions.GetFunctionByOffset(best_function); auto bound_aggregate = AggregateFunction::BindAggregateFunction(context, bound_function, move(children)); // create the aggregate aggregate = make_unique(bound_aggregate->function); @@ -169566,6 +183540,7 @@ class OrderBinder { private: unique_ptr CreateProjectionReference(ParsedExpression &expr, idx_t index); + unique_ptr BindConstant(ParsedExpression &expr, const Value &val); private: vector binders; @@ -169621,7 +183596,7 @@ unique_ptr Binder::BindLimit(OrderBinder &order_binder, Lim Value val; result->limit = BindDelimiter(context, order_binder, move(limit_mod.limit), LogicalType::BIGINT, val); if (!result->limit) { - result->limit_val = val.GetValue(); + result->limit_val = val.IsNull() ? NumericLimits::Maximum() : val.GetValue(); if (result->limit_val < 0) { throw BinderException("LIMIT cannot be negative"); } @@ -169631,7 +183606,7 @@ unique_ptr Binder::BindLimit(OrderBinder &order_binder, Lim Value val; result->offset = BindDelimiter(context, order_binder, move(limit_mod.offset), LogicalType::BIGINT, val); if (!result->offset) { - result->offset_val = val.GetValue(); + result->offset_val = val.IsNull() ? 0 : val.GetValue(); if (result->offset_val < 0) { throw BinderException("OFFSET cannot be negative"); } @@ -169646,7 +183621,7 @@ unique_ptr Binder::BindLimitPercent(OrderBinder &order_bind Value val; result->limit = BindDelimiter(context, order_binder, move(limit_mod.limit), LogicalType::DOUBLE, val); if (!result->limit) { - result->limit_percent = val.GetValue(); + result->limit_percent = val.IsNull() ? 100 : val.GetValue(); if (result->limit_percent < 0.0) { throw Exception("Limit percentage can't be negative value"); } @@ -169656,7 +183631,7 @@ unique_ptr Binder::BindLimitPercent(OrderBinder &order_bind Value val; result->offset = BindDelimiter(context, order_binder, move(limit_mod.offset), LogicalType::BIGINT, val); if (!result->offset) { - result->offset_val = val.GetValue(); + result->offset_val = val.IsNull() ? 0 : val.GetValue(); } } return move(result); @@ -169708,9 +183683,11 @@ void Binder::BindModifiers(OrderBinder &order_binder, QueryNode &statement, Boun if (!order_expression) { continue; } - auto type = order_node.type == OrderType::ORDER_DEFAULT ? config.default_order_type : order_node.type; - auto null_order = order_node.null_order == OrderByNullType::ORDER_DEFAULT ? config.default_null_order - : order_node.null_order; + auto type = + order_node.type == OrderType::ORDER_DEFAULT ? config.options.default_order_type : order_node.type; + auto null_order = order_node.null_order == OrderByNullType::ORDER_DEFAULT + ? config.options.default_null_order + : order_node.null_order; bound_order->orders.emplace_back(type, null_order, move(order_expression)); } if (!bound_order->orders.empty()) { @@ -169770,7 +183747,7 @@ void Binder::BindModifierTypes(BoundQueryNode &result, const vector } for (auto &target_distinct : distinct.target_distincts) { auto &bound_colref = (BoundColumnRefExpression &)*target_distinct; - auto sql_type = sql_types[bound_colref.binding.column_index]; + const auto &sql_type = sql_types[bound_colref.binding.column_index]; if (sql_type.id() == LogicalTypeId::VARCHAR) { target_distinct = ExpressionBinder::PushCollation(context, move(target_distinct), StringType::GetCollation(sql_type), true); @@ -169800,7 +183777,7 @@ void Binder::BindModifierTypes(BoundQueryNode &result, const vector throw BinderException("Ambiguous name in ORDER BY!"); } D_ASSERT(bound_colref.binding.column_index < sql_types.size()); - auto sql_type = sql_types[bound_colref.binding.column_index]; + const auto &sql_type = sql_types[bound_colref.binding.column_index]; bound_colref.return_type = sql_types[bound_colref.binding.column_index]; if (sql_type.id() == LogicalTypeId::VARCHAR) { order_node.expression = ExpressionBinder::PushCollation(context, move(order_node.expression), @@ -169933,12 +183910,16 @@ unique_ptr Binder::BindNode(SelectNode &statement) { SelectBinder select_binder(*this, context, *result, info); vector internal_sql_types; for (idx_t i = 0; i < statement.select_list.size(); i++) { + bool is_window = statement.select_list[i]->IsWindow(); LogicalType result_type; auto expr = select_binder.Bind(statement.select_list[i], &result_type); if (statement.aggregate_handling == AggregateHandling::FORCE_AGGREGATES && select_binder.HasBoundColumns()) { if (select_binder.BoundAggregates()) { throw BinderException("Cannot mix aggregates with non-aggregated columns!"); } + if (is_window) { + throw BinderException("Cannot group on a window clause"); + } // we are forcing aggregates, and the node has columns bound // this entry becomes a group auto group_ref = make_unique( @@ -169995,6 +183976,9 @@ unique_ptr Binder::BindNode(SelectNode &statement) { + + + //===----------------------------------------------------------------------===// // DuckDB // @@ -170031,6 +184015,16 @@ class BoundSetOperationNode : public BoundQueryNode { //! The binder used by the right side of the set operation shared_ptr right_binder; + //! Exprs used by the UNION BY NAME opeartons to add a new projection + vector> left_reorder_exprs; + vector> right_reorder_exprs; + + //! The exprs of the child node may be rearranged(UNION BY NAME), + //! this vector records the new index of the expression after rearrangement + //! used by GatherAlias(...) function to create new reorder index + vector left_reorder_idx; + vector right_reorder_idx; + public: idx_t GetRootIndex() override { return setop_index; @@ -170040,17 +184034,34 @@ class BoundSetOperationNode : public BoundQueryNode { } // namespace duckdb - - namespace duckdb { static void GatherAliases(BoundQueryNode &node, case_insensitive_map_t &aliases, - expression_map_t &expressions) { + expression_map_t &expressions, const vector &reorder_idx) { if (node.type == QueryNodeType::SET_OPERATION_NODE) { // setop, recurse auto &setop = (BoundSetOperationNode &)node; - GatherAliases(*setop.left, aliases, expressions); - GatherAliases(*setop.right, aliases, expressions); + + // create new reorder index + if (setop.setop_type == SetOperationType::UNION_BY_NAME) { + vector new_left_reorder_idx(setop.left_reorder_idx.size()); + vector new_right_reorder_idx(setop.right_reorder_idx.size()); + for (idx_t i = 0; i < setop.left_reorder_idx.size(); ++i) { + new_left_reorder_idx[i] = reorder_idx[setop.left_reorder_idx[i]]; + } + + for (idx_t i = 0; i < setop.right_reorder_idx.size(); ++i) { + new_right_reorder_idx[i] = reorder_idx[setop.right_reorder_idx[i]]; + } + + // use new reorder index + GatherAliases(*setop.left, aliases, expressions, new_left_reorder_idx); + GatherAliases(*setop.right, aliases, expressions, new_right_reorder_idx); + return; + } + + GatherAliases(*setop.left, aliases, expressions, reorder_idx); + GatherAliases(*setop.right, aliases, expressions, reorder_idx); } else { // query node D_ASSERT(node.type == QueryNodeType::SELECT_NODE); @@ -170061,10 +184072,14 @@ static void GatherAliases(BoundQueryNode &node, case_insensitive_map_t &a auto &expr = select.original_expressions[i]; // first check if the alias is already in there auto entry = aliases.find(name); + + idx_t index = reorder_idx[i]; + if (entry != aliases.end()) { // the alias already exists // check if there is a conflict - if (entry->second != i) { + + if (entry->second != index) { // there is a conflict // we place "-1" in the aliases map at this location // "-1" signifies that there is an ambiguous reference @@ -170072,24 +184087,130 @@ static void GatherAliases(BoundQueryNode &node, case_insensitive_map_t &a } } else { // the alias is not in there yet, just assign it - aliases[name] = i; + aliases[name] = index; } // now check if the node is already in the set of expressions auto expr_entry = expressions.find(expr.get()); if (expr_entry != expressions.end()) { // the node is in there // repeat the same as with the alias: if there is an ambiguity we insert "-1" - if (expr_entry->second != i) { + if (expr_entry->second != index) { expressions[expr.get()] = DConstants::INVALID_INDEX; } } else { // not in there yet, just place it in there - expressions[expr.get()] = i; + expressions[expr.get()] = index; } } } } +static void BuildUnionByNameInfo(BoundSetOperationNode &result, bool can_contain_nulls) { + D_ASSERT(result.setop_type == SetOperationType::UNION_BY_NAME); + case_insensitive_map_t left_names_map; + case_insensitive_map_t right_names_map; + + BoundQueryNode *left_node = result.left.get(); + BoundQueryNode *right_node = result.right.get(); + + // Build a name_map to use to check if a name exists + // We throw a binder exception if two same name in the SELECT list + for (idx_t i = 0; i < left_node->names.size(); ++i) { + if (left_names_map.find(left_node->names[i]) != left_names_map.end()) { + throw BinderException("UNION(ALL) BY NAME operation doesn't support same name in SELECT list"); + } + left_names_map[left_node->names[i]] = i; + } + + for (idx_t i = 0; i < right_node->names.size(); ++i) { + if (right_names_map.find(right_node->names[i]) != right_names_map.end()) { + throw BinderException("UNION(ALL) BY NAME operation doesn't support same name in SELECT list"); + } + if (left_names_map.find(right_node->names[i]) == left_names_map.end()) { + result.names.push_back(right_node->names[i]); + } + right_names_map[right_node->names[i]] = i; + } + + idx_t new_size = result.names.size(); + bool need_reorder = false; + vector left_reorder_idx(left_node->names.size()); + vector right_reorder_idx(right_node->names.size()); + + // Construct return type and reorder_idxs + // reorder_idxs is used to gather correct alias_map + // and expression_map in GatherAlias(...) + for (idx_t i = 0; i < new_size; ++i) { + auto left_index = left_names_map.find(result.names[i]); + auto right_index = right_names_map.find(result.names[i]); + bool left_exist = left_index != left_names_map.end(); + bool right_exist = right_index != right_names_map.end(); + LogicalType result_type; + if (left_exist && right_exist) { + result_type = LogicalType::MaxLogicalType(left_node->types[left_index->second], + right_node->types[right_index->second]); + if (left_index->second != i || right_index->second != i) { + need_reorder = true; + } + left_reorder_idx[left_index->second] = i; + right_reorder_idx[right_index->second] = i; + } else if (left_exist) { + result_type = left_node->types[left_index->second]; + need_reorder = true; + left_reorder_idx[left_index->second] = i; + } else { + D_ASSERT(right_exist); + result_type = right_node->types[right_index->second]; + need_reorder = true; + right_reorder_idx[right_index->second] = i; + } + + if (!can_contain_nulls) { + if (ExpressionBinder::ContainsNullType(result_type)) { + result_type = ExpressionBinder::ExchangeNullType(result_type); + } + } + + result.types.push_back(result_type); + } + + result.left_reorder_idx = move(left_reorder_idx); + result.right_reorder_idx = move(right_reorder_idx); + + // If reorder is required, collect reorder expressions for push projection + // into the two child nodes of union node + if (need_reorder) { + for (idx_t i = 0; i < new_size; ++i) { + auto left_index = left_names_map.find(result.names[i]); + auto right_index = right_names_map.find(result.names[i]); + bool left_exist = left_index != left_names_map.end(); + bool right_exist = right_index != right_names_map.end(); + unique_ptr left_reorder_expr; + unique_ptr right_reorder_expr; + if (left_exist && right_exist) { + left_reorder_expr = make_unique( + left_node->types[left_index->second], ColumnBinding(left_node->GetRootIndex(), left_index->second)); + right_reorder_expr = make_unique( + right_node->types[right_index->second], + ColumnBinding(right_node->GetRootIndex(), right_index->second)); + } else if (left_exist) { + left_reorder_expr = make_unique( + left_node->types[left_index->second], ColumnBinding(left_node->GetRootIndex(), left_index->second)); + // create null value here + right_reorder_expr = make_unique(Value(result.types[i])); + } else { + D_ASSERT(right_exist); + left_reorder_expr = make_unique(Value(result.types[i])); + right_reorder_expr = make_unique( + right_node->types[right_index->second], + ColumnBinding(right_node->GetRootIndex(), right_index->second)); + } + result.left_reorder_exprs.push_back(move(left_reorder_expr)); + result.right_reorder_exprs.push_back(move(right_reorder_expr)); + } + } +} + unique_ptr Binder::BindNode(SetOperationNode &statement) { auto result = make_unique(); result->setop_type = statement.setop_type; @@ -170104,26 +184225,10 @@ unique_ptr Binder::BindNode(SetOperationNode &statement) { result->left_binder = Binder::CreateBinder(context, this); result->left_binder->can_contain_nulls = true; result->left = result->left_binder->BindNode(*statement.left); - result->right_binder = Binder::CreateBinder(context, this); result->right_binder->can_contain_nulls = true; result->right = result->right_binder->BindNode(*statement.right); - if (!statement.modifiers.empty()) { - // handle the ORDER BY/DISTINCT clauses - - // we recursively visit the children of this node to extract aliases and expressions that can be referenced in - // the ORDER BY - case_insensitive_map_t alias_map; - expression_map_t expression_map; - GatherAliases(*result, alias_map, expression_map); - - // now we perform the actual resolution of the ORDER BY/DISTINCT expressions - OrderBinder order_binder({result->left_binder.get(), result->right_binder.get()}, result->setop_index, - alias_map, expression_map, statement.left->GetSelectList().size()); - BindModifiers(order_binder, statement, *result); - } - result->names = result->left->names; // move the correlated expressions from the child binders to this binder @@ -170131,20 +184236,50 @@ unique_ptr Binder::BindNode(SetOperationNode &statement) { MoveCorrelatedExpressions(*result->right_binder); // now both sides have been bound we can resolve types - if (result->left->types.size() != result->right->types.size()) { + if (result->setop_type != SetOperationType::UNION_BY_NAME && + result->left->types.size() != result->right->types.size()) { throw BinderException("Set operations can only apply to expressions with the " "same number of result columns"); } - // figure out the types of the setop result by picking the max of both - for (idx_t i = 0; i < result->left->types.size(); i++) { - auto result_type = LogicalType::MaxLogicalType(result->left->types[i], result->right->types[i]); - if (!can_contain_nulls) { - if (ExpressionBinder::ContainsNullType(result_type)) { - result_type = ExpressionBinder::ExchangeNullType(result_type); + if (result->setop_type == SetOperationType::UNION_BY_NAME) { + BuildUnionByNameInfo(*result, can_contain_nulls); + + } else { + // figure out the types of the setop result by picking the max of both + for (idx_t i = 0; i < result->left->types.size(); i++) { + auto result_type = LogicalType::MaxLogicalType(result->left->types[i], result->right->types[i]); + if (!can_contain_nulls) { + if (ExpressionBinder::ContainsNullType(result_type)) { + result_type = ExpressionBinder::ExchangeNullType(result_type); + } } + result->types.push_back(result_type); } - result->types.push_back(result_type); + } + + if (!statement.modifiers.empty()) { + // handle the ORDER BY/DISTINCT clauses + + // we recursively visit the children of this node to extract aliases and expressions that can be referenced + // in the ORDER BY + case_insensitive_map_t alias_map; + expression_map_t expression_map; + + if (result->setop_type == SetOperationType::UNION_BY_NAME) { + GatherAliases(*result->left, alias_map, expression_map, result->left_reorder_idx); + GatherAliases(*result->right, alias_map, expression_map, result->right_reorder_idx); + } else { + vector reorder_idx; + for (idx_t i = 0; i < result->names.size(); i++) { + reorder_idx.push_back(i); + } + GatherAliases(*result, alias_map, expression_map, reorder_idx); + } + // now we perform the actual resolution of the ORDER BY/DISTINCT expressions + OrderBinder order_binder({result->left_binder.get(), result->right_binder.get()}, result->setop_index, + alias_map, expression_map, result->names.size()); + BindModifiers(order_binder, statement, *result); } // finally bind the types of the ORDER/DISTINCT clause expressions @@ -170206,10 +184341,10 @@ unique_ptr Binder::BindTableMacro(FunctionExpression &function, Table // now push the defaults into the positionals positionals.push_back(move(defaults[it->first])); } - auto new_macro_binding = make_unique(types, names, macro_func->name); - new_macro_binding->arguments = move(positionals); + auto new_macro_binding = make_unique(types, names, macro_func->name); + new_macro_binding->arguments = &positionals; - // We need an EXpressionBinder So that we can call ExpressionBinder::ReplaceMacroParametersRecursive() + // We need an ExpressionBinder so that we can call ExpressionBinder::ReplaceMacroParametersRecursive() auto eb = ExpressionBinder(*this, this->context); eb.macro_binding = new_macro_binding.get(); @@ -170509,18 +184644,43 @@ unique_ptr Binder::CreatePlan(BoundSetOperationNode &node) { auto left_node = node.left_binder->CreatePlan(*node.left); auto right_node = node.right_binder->CreatePlan(*node.right); + // Add a new projection to child node + D_ASSERT(node.left_reorder_exprs.size() == node.right_reorder_exprs.size()); + if (!node.left_reorder_exprs.empty()) { + D_ASSERT(node.setop_type == SetOperationType::UNION_BY_NAME); + vector left_types; + vector right_types; + // We are going to add a new projection operator, so collect the type + // of reorder exprs in order to call CastLogicalOperatorToTypes() + for (idx_t i = 0; i < node.left_reorder_exprs.size(); ++i) { + left_types.push_back(node.left_reorder_exprs[i]->return_type); + right_types.push_back(node.right_reorder_exprs[i]->return_type); + } + + auto left_projection = make_unique(GenerateTableIndex(), move(node.left_reorder_exprs)); + left_projection->children.push_back(move(left_node)); + left_node = move(left_projection); + + auto right_projection = make_unique(GenerateTableIndex(), move(node.right_reorder_exprs)); + right_projection->children.push_back(move(right_node)); + right_node = move(right_projection); + + left_node = CastLogicalOperatorToTypes(left_types, node.types, move(left_node)); + right_node = CastLogicalOperatorToTypes(right_types, node.types, move(right_node)); + } else { + left_node = CastLogicalOperatorToTypes(node.left->types, node.types, move(left_node)); + right_node = CastLogicalOperatorToTypes(node.right->types, node.types, move(right_node)); + } + // check if there are any unplanned subqueries left in either child has_unplanned_subqueries = node.left_binder->has_unplanned_subqueries || node.right_binder->has_unplanned_subqueries; - // for both the left and right sides, cast them to the same types - left_node = CastLogicalOperatorToTypes(node.left->types, node.types, move(left_node)); - right_node = CastLogicalOperatorToTypes(node.right->types, node.types, move(right_node)); - // create actual logical ops for setops LogicalOperatorType logical_type; switch (node.setop_type) { case SetOperationType::UNION: + case SetOperationType::UNION_BY_NAME: logical_type = LogicalOperatorType::LOGICAL_UNION; break; case SetOperationType::EXCEPT: @@ -170531,6 +184691,7 @@ unique_ptr Binder::CreatePlan(BoundSetOperationNode &node) { logical_type = LogicalOperatorType::LOGICAL_INTERSECT; break; } + auto root = make_unique(node.setop_index, node.types.size(), move(left_node), move(right_node), logical_type); @@ -170548,7 +184709,6 @@ unique_ptr Binder::CreatePlan(BoundSetOperationNode &node) { - //===----------------------------------------------------------------------===// // DuckDB // @@ -170569,7 +184729,8 @@ namespace duckdb { //! The FlattenDependentJoins class is responsible for pushing the dependent join down into the plan to create a //! flattened subquery struct FlattenDependentJoins { - FlattenDependentJoins(Binder &binder, const vector &correlated, bool any_join = false); + FlattenDependentJoins(Binder &binder, const vector &correlated, bool perform_delim = true, + bool any_join = false); //! Detects which Logical Operators have correlated expressions that they are dependent upon, filling the //! has_correlated_expressions map. @@ -170588,6 +184749,7 @@ struct FlattenDependentJoins { const vector &correlated_columns; vector delim_types; + bool perform_delim; bool any_join; private: @@ -170599,6 +184761,9 @@ struct FlattenDependentJoins { + + + namespace duckdb { static unique_ptr PlanUncorrelatedSubquery(Binder &binder, BoundSubqueryExpression &expr, @@ -170640,10 +184805,7 @@ static unique_ptr PlanUncorrelatedSubquery(Binder &binder, BoundSubq // we add it to the main query by adding a cross product // FIXME: should use something else besides cross product as we always add only one scalar constant - auto cross_product = make_unique(); - cross_product->AddChild(move(root)); - cross_product->AddChild(move(plan)); - root = move(cross_product); + root = LogicalCrossProduct::Create(move(root), move(plan)); // we replace the original subquery with a ColumnRefExpression referring to the result of the projection (either // TRUE or FALSE) @@ -170681,10 +184843,7 @@ static unique_ptr PlanUncorrelatedSubquery(Binder &binder, BoundSubq // FIXME: should use something else besides cross product as we always add only one scalar constant and cross // product is not optimized for this. D_ASSERT(root); - auto cross_product = make_unique(); - cross_product->AddChild(move(root)); - cross_product->AddChild(move(plan)); - root = move(cross_product); + root = LogicalCrossProduct::Create(move(root), move(plan)); // we replace the original subquery with a BoundColumnRefExpression referring to the first result of the // aggregation @@ -170720,8 +184879,25 @@ static unique_ptr PlanUncorrelatedSubquery(Binder &binder, BoundSubq } static unique_ptr CreateDuplicateEliminatedJoin(vector &correlated_columns, - JoinType join_type) { + JoinType join_type, + unique_ptr original_plan, + bool perform_delim) { auto delim_join = make_unique(join_type); + if (!perform_delim) { + // if we are not performing a delim join, we push a row_number() OVER() window operator on the LHS + // and perform all duplicate elimination on that row number instead + D_ASSERT(correlated_columns[0].type.id() == LogicalTypeId::BIGINT); + auto window = make_unique(correlated_columns[0].binding.table_index); + auto row_number = make_unique(ExpressionType::WINDOW_ROW_NUMBER, LogicalType::BIGINT, + nullptr, nullptr); + row_number->start = WindowBoundary::UNBOUNDED_PRECEDING; + row_number->end = WindowBoundary::CURRENT_ROW_ROWS; + row_number->alias = "delim_index"; + window->expressions.push_back(move(row_number)); + window->AddChild(move(original_plan)); + original_plan = move(window); + } + delim_join->AddChild(move(original_plan)); for (idx_t i = 0; i < correlated_columns.size(); i++) { auto &col = correlated_columns[i]; delim_join->duplicate_eliminated_columns.push_back( @@ -170732,8 +184908,9 @@ static unique_ptr CreateDuplicateEliminatedJoin(vector &correlated_columns, - vector bindings, idx_t base_offset) { - for (idx_t i = 0; i < correlated_columns.size(); i++) { + vector bindings, idx_t base_offset, bool perform_delim) { + auto col_count = perform_delim ? correlated_columns.size() : 1; + for (idx_t i = 0; i < col_count; i++) { auto &col = correlated_columns[i]; JoinCondition cond; cond.left = make_unique(col.name, col.type, col.binding); @@ -170743,10 +184920,50 @@ static void CreateDelimJoinConditions(LogicalDelimJoin &delim_join, vector &correlated_columns) { + if (!ClientConfig::GetConfig(binder.context).enable_optimizer) { + // if optimizations are disabled we always do a delim join + return true; + } + bool perform_delim = true; + for (auto &col : correlated_columns) { + if (!PerformDelimOnType(col.type)) { + perform_delim = false; + break; + } + } + if (perform_delim) { + return true; + } + auto binding = ColumnBinding(binder.GenerateTableIndex(), 0); + auto type = LogicalType::BIGINT; + auto name = "delim_index"; + CorrelatedColumnInfo info(binding, type, name, 0); + correlated_columns.insert(correlated_columns.begin(), move(info)); + return false; +} + static unique_ptr PlanCorrelatedSubquery(Binder &binder, BoundSubqueryExpression &expr, unique_ptr &root, unique_ptr plan) { auto &correlated_columns = expr.binder->correlated_columns; + // FIXME: there should be a way of disabling decorrelation for ANY queries as well, but not for now... + bool perform_delim = + expr.subquery_type == SubqueryType::ANY ? true : PerformDuplicateElimination(binder, correlated_columns); D_ASSERT(expr.IsCorrelated()); // correlated subquery // for a more in-depth explanation of this code, read the paper "Unnesting Arbitrary Subqueries" @@ -170763,15 +184980,15 @@ static unique_ptr PlanCorrelatedSubquery(Binder &binder, BoundSubque // NULL values are equal in this join because we join on the correlated columns ONLY // and e.g. in the query: SELECT (SELECT 42 FROM integers WHERE i1.i IS NULL LIMIT 1) FROM integers i1; // the input value NULL will generate the value 42, and we need to join NULL on the LHS with NULL on the RHS - auto delim_join = CreateDuplicateEliminatedJoin(correlated_columns, JoinType::SINGLE); - // the left side is the original plan // this is the side that will be duplicate eliminated and pushed into the RHS - delim_join->AddChild(move(root)); + auto delim_join = + CreateDuplicateEliminatedJoin(correlated_columns, JoinType::SINGLE, move(root), perform_delim); + // the right side initially is a DEPENDENT join between the duplicate eliminated scan and the subquery // HOWEVER: we do not explicitly create the dependent join // instead, we eliminate the dependent join by pushing it down into the right side of the plan - FlattenDependentJoins flatten(binder, correlated_columns); + FlattenDependentJoins flatten(binder, correlated_columns, perform_delim); // first we check which logical operators have correlated expressions in the first place flatten.DetectCorrelatedExpressions(plan.get()); @@ -170784,7 +185001,7 @@ static unique_ptr PlanCorrelatedSubquery(Binder &binder, BoundSubque auto plan_columns = dependent_join->GetColumnBindings(); // now create the join conditions - CreateDelimJoinConditions(*delim_join, correlated_columns, plan_columns, flatten.delim_offset); + CreateDelimJoinConditions(*delim_join, correlated_columns, plan_columns, flatten.delim_offset, perform_delim); delim_join->AddChild(move(dependent_join)); root = move(delim_join); // finally push the BoundColumnRefExpression referring to the data element returned by the join @@ -170795,12 +185012,10 @@ static unique_ptr PlanCorrelatedSubquery(Binder &binder, BoundSubque // correlated EXISTS query // this query is similar to the correlated SCALAR query, except we use a MARK join here idx_t mark_index = binder.GenerateTableIndex(); - auto delim_join = CreateDuplicateEliminatedJoin(correlated_columns, JoinType::MARK); + auto delim_join = CreateDuplicateEliminatedJoin(correlated_columns, JoinType::MARK, move(root), perform_delim); delim_join->mark_index = mark_index; - // LHS - delim_join->AddChild(move(root)); // RHS - FlattenDependentJoins flatten(binder, correlated_columns); + FlattenDependentJoins flatten(binder, correlated_columns, perform_delim); flatten.DetectCorrelatedExpressions(plan.get()); auto dependent_join = flatten.PushDownDependentJoin(move(plan)); @@ -170808,7 +185023,7 @@ static unique_ptr PlanCorrelatedSubquery(Binder &binder, BoundSubque auto plan_columns = dependent_join->GetColumnBindings(); // now we create the join conditions between the dependent join and the original table - CreateDelimJoinConditions(*delim_join, correlated_columns, plan_columns, flatten.delim_offset); + CreateDelimJoinConditions(*delim_join, correlated_columns, plan_columns, flatten.delim_offset, perform_delim); delim_join->AddChild(move(dependent_join)); root = move(delim_join); // finally push the BoundColumnRefExpression referring to the marker @@ -170824,10 +185039,8 @@ static unique_ptr PlanCorrelatedSubquery(Binder &binder, BoundSubque // as the MARK join has one extra join condition (the original condition, of the ANY expression, e.g. // [i=ANY(...)]) idx_t mark_index = binder.GenerateTableIndex(); - auto delim_join = CreateDuplicateEliminatedJoin(correlated_columns, JoinType::MARK); + auto delim_join = CreateDuplicateEliminatedJoin(correlated_columns, JoinType::MARK, move(root), perform_delim); delim_join->mark_index = mark_index; - // LHS - delim_join->AddChild(move(root)); // RHS FlattenDependentJoins flatten(binder, correlated_columns, true); flatten.DetectCorrelatedExpressions(plan.get()); @@ -170837,7 +185050,7 @@ static unique_ptr PlanCorrelatedSubquery(Binder &binder, BoundSubque auto plan_columns = dependent_join->GetColumnBindings(); // now we create the join conditions between the dependent join and the original table - CreateDelimJoinConditions(*delim_join, correlated_columns, plan_columns, flatten.delim_offset); + CreateDelimJoinConditions(*delim_join, correlated_columns, plan_columns, flatten.delim_offset, perform_delim); // add the actual condition based on the ANY/ALL predicate JoinCondition compare_cond; compare_cond.left = move(expr.child); @@ -170861,9 +185074,11 @@ class RecursiveSubqueryPlanner : public LogicalOperatorVisitor { void VisitOperator(LogicalOperator &op) override { if (!op.children.empty()) { root = move(op.children[0]); + D_ASSERT(root); VisitOperatorExpressions(op); op.children[0] = move(root); for (idx_t i = 0; i < op.children.size(); i++) { + D_ASSERT(op.children[i]); VisitOperator(*op.children[i]); } } @@ -171009,7 +185224,7 @@ namespace duckdb { BoundStatement Binder::BindCopyTo(CopyStatement &stmt) { // COPY TO a file auto &config = DBConfig::GetConfig(context); - if (!config.enable_external_access) { + if (!config.options.enable_external_access) { throw PermissionException("COPY TO is disabled by configuration"); } BoundStatement result; @@ -171051,7 +185266,7 @@ BoundStatement Binder::BindCopyTo(CopyStatement &stmt) { BoundStatement Binder::BindCopyFrom(CopyStatement &stmt) { auto &config = DBConfig::GetConfig(context); - if (!config.enable_external_access) { + if (!config.options.enable_external_access) { throw PermissionException("COPY FROM is disabled by configuration"); } BoundStatement result; @@ -171220,33 +185435,6 @@ struct BoundCreateFunctionInfo { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/tableref/bound_basetableref.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { -class TableCatalogEntry; - -//! Represents a TableReference to a base table in the schema -class BoundBaseTableRef : public BoundTableRef { -public: - BoundBaseTableRef(TableCatalogEntry *table, unique_ptr get) - : BoundTableRef(TableReferenceType::BASE_TABLE), table(table), get(move(get)) { - } - - TableCatalogEntry *table; - unique_ptr get; -}; -} // namespace duckdb @@ -171325,7 +185513,7 @@ SchemaCatalogEntry *Binder::BindCreateFunctionInfo(CreateInfo &info) { dummy_types.push_back(val.value.type()); dummy_names.push_back(it->first); } - auto this_macro_binding = make_unique(dummy_types, dummy_names, base.name); + auto this_macro_binding = make_unique(dummy_types, dummy_names, base.name); macro_binding = this_macro_binding.get(); ExpressionBinder::QualifyColumnNames(*this, scalar_function.expression); @@ -171373,33 +185561,70 @@ void Binder::BindLogicalType(ClientContext &context, LogicalType &type, const st } } -static void FindMatchingPrimaryKeyColumns(vector> &constraints, ForeignKeyConstraint &fk) { - if (!fk.pk_columns.empty()) { - return; - } +static void FindMatchingPrimaryKeyColumns(const vector &columns, + const vector> &constraints, ForeignKeyConstraint &fk) { // find the matching primary key constraint + bool found_constraint = false; + // if no columns are defined, we will automatically try to bind to the primary key + bool find_primary_key = fk.pk_columns.empty(); for (auto &constr : constraints) { if (constr->type != ConstraintType::UNIQUE) { continue; } auto &unique = (UniqueConstraint &)*constr; - if (!unique.is_primary_key) { + if (find_primary_key && !unique.is_primary_key) { continue; } - idx_t column_count; + found_constraint = true; + + vector pk_names; if (unique.index != DConstants::INVALID_INDEX) { - fk.info.pk_keys.push_back(unique.index); - column_count = 1; + pk_names.push_back(columns[unique.index].Name()); } else { - fk.pk_columns = unique.columns; - column_count = unique.columns.size(); + pk_names = unique.columns; + } + if (pk_names.size() != fk.fk_columns.size()) { + // the number of referencing and referenced columns for foreign keys must be the same + continue; + } + if (find_primary_key) { + // found matching primary key + fk.pk_columns = pk_names; + return; } - if (column_count != fk.fk_columns.size()) { - throw BinderException("The number of referencing and referenced columns for foreign keys must be the same"); + if (fk.pk_columns != pk_names) { + // Name mismatch + continue; } + // found match return; } - throw BinderException("there is no primary key for referenced table \"%s\"", fk.info.table); + // no match found! examine why + if (!found_constraint) { + // no unique constraint or primary key + string search_term = find_primary_key ? "primary key" : "primary key or unique constraint"; + throw BinderException("Failed to create foreign key: there is no %s for referenced table \"%s\"", search_term, + fk.info.table); + } + // check if all the columns exist + for (auto &name : fk.pk_columns) { + bool found = false; + for (auto &col : columns) { + if (col.Name() == name) { + found = true; + break; + } + } + if (!found) { + throw BinderException( + "Failed to create foreign key: referenced table \"%s\" does not have a column named \"%s\"", + fk.info.table, name); + } + } + auto fk_names = StringUtil::Join(fk.pk_columns, ","); + throw BinderException("Failed to create foreign key: referenced table \"%s\" does not have a primary key or unique " + "constraint on the columns %s", + fk.info.table, fk_names); } void ExpressionContainsGeneratedColumn(const ParsedExpression &expr, const unordered_set &gcols, @@ -171564,13 +185789,13 @@ BoundStatement Binder::Bind(CreateStatement &stmt) { D_ASSERT(fk.info.pk_keys.empty()); if (create_info.table == fk.info.table) { fk.info.type = ForeignKeyType::FK_TYPE_SELF_REFERENCE_TABLE; - FindMatchingPrimaryKeyColumns(create_info.constraints, fk); + FindMatchingPrimaryKeyColumns(create_info.columns, create_info.constraints, fk); } else { // have to resolve referenced table auto pk_table_entry_ptr = catalog.GetEntry(context, fk.info.schema, fk.info.table); fk_schemas.insert(pk_table_entry_ptr->schema); D_ASSERT(fk.info.pk_keys.empty()); - FindMatchingPrimaryKeyColumns(pk_table_entry_ptr->constraints, fk); + FindMatchingPrimaryKeyColumns(pk_table_entry_ptr->columns, pk_table_entry_ptr->constraints, fk); for (auto &keyname : fk.pk_columns) { auto entry = pk_table_entry_ptr->name_map.find(keyname); if (entry == pk_table_entry_ptr->name_map.end()) { @@ -171745,6 +185970,7 @@ static void BindConstraints(Binder &binder, BoundCreateTableInfo &info) { auto &base = (CreateTableInfo &)*info.base; bool has_primary_key = false; + unordered_set not_null_columns; vector primary_keys; for (idx_t i = 0; i < base.constraints.size(); i++) { auto &cond = base.constraints[i]; @@ -171757,6 +185983,7 @@ static void BindConstraints(Binder &binder, BoundCreateTableInfo &info) { auto ¬_null = (NotNullConstraint &)*cond; auto &col = base.columns[not_null.index]; info.bound_constraints.push_back(make_unique(col.StorageOid())); + not_null_columns.insert(not_null.index); break; } case ConstraintType::UNIQUE: { @@ -171844,6 +186071,10 @@ static void BindConstraints(Binder &binder, BoundCreateTableInfo &info) { if (has_primary_key) { // if there is a primary key index, also create a NOT NULL constraint for each of the columns for (auto &column_index : primary_keys) { + if (not_null_columns.count(column_index)) { + //! No need to create a NotNullConstraint, it's already present + continue; + } auto &column = base.columns[column_index]; base.constraints.push_back(make_unique(column_index)); info.bound_constraints.push_back(make_unique(column.StorageOid())); @@ -172038,6 +186269,9 @@ BoundStatement Binder::Bind(DeleteStatement &stmt) { properties.read_only = false; } + // Add CTEs as bindable + AddCTEMap(stmt.cte_map); + // plan any tables from the various using clauses if (!stmt.using_clauses.empty()) { unique_ptr child_operator; @@ -172047,19 +186281,13 @@ BoundStatement Binder::Bind(DeleteStatement &stmt) { auto op = CreatePlan(*bound_node); if (child_operator) { // already bound a child: create a cross product to unify the two - auto cross_product = make_unique(); - cross_product->children.push_back(move(child_operator)); - cross_product->children.push_back(move(op)); - child_operator = move(cross_product); + child_operator = LogicalCrossProduct::Create(move(child_operator), move(op)); } else { child_operator = move(op); } } if (child_operator) { - auto cross_product = make_unique(); - cross_product->children.push_back(move(root)); - cross_product->children.push_back(move(child_operator)); - root = move(cross_product); + root = LogicalCrossProduct::Create(move(root), move(child_operator)); } } @@ -172160,6 +186388,73 @@ BoundStatement Binder::Bind(DropStatement &stmt) { + + + + + +namespace duckdb { + +BoundStatement Binder::Bind(ExecuteStatement &stmt) { + auto parameter_count = stmt.n_param; + + // bind the prepared statement + auto &client_data = ClientData::Get(context); + + auto entry = client_data.prepared_statements.find(stmt.name); + if (entry == client_data.prepared_statements.end()) { + throw BinderException("Prepared statement \"%s\" does not exist", stmt.name); + } + + // check if we need to rebind the prepared statement + // this happens if the catalog changes, since in this case e.g. tables we relied on may have been deleted + auto prepared = entry->second; + + // bind any supplied parameters + vector bind_values; + auto constant_binder = Binder::CreateBinder(context); + constant_binder->SetCanContainNulls(true); + for (idx_t i = 0; i < stmt.values.size(); i++) { + ConstantBinder cbinder(*constant_binder, context, "EXECUTE statement"); + auto bound_expr = cbinder.Bind(stmt.values[i]); + + Value value = ExpressionExecutor::EvaluateScalar(*bound_expr, true); + bind_values.push_back(move(value)); + } + unique_ptr rebound_plan; + if (prepared->RequireRebind(context, bind_values)) { + // catalog was modified or statement does not have clear types: rebind the statement before running the execute + Planner prepared_planner(context); + for (idx_t i = 0; i < bind_values.size(); i++) { + prepared_planner.parameter_data.emplace_back(bind_values[i]); + } + prepared = prepared_planner.PrepareSQLStatement(entry->second->unbound_statement->Copy()); + rebound_plan = move(prepared_planner.plan); + D_ASSERT(prepared->properties.bound_all_parameters); + } + // copy the properties of the prepared statement into the planner + this->properties = prepared->properties; + this->properties.parameter_count = parameter_count; + BoundStatement result; + result.names = prepared->names; + result.types = prepared->types; + + prepared->Bind(move(bind_values)); + if (rebound_plan) { + auto execute_plan = make_unique(move(prepared)); + execute_plan->children.push_back(move(rebound_plan)); + result.plan = move(execute_plan); + } else { + result.plan = make_unique(move(prepared)); + } + return result; +} + +} // namespace duckdb + + + + namespace duckdb { BoundStatement Binder::Bind(ExplainStatement &stmt) { @@ -172270,7 +186565,7 @@ void ReorderTableEntries(vector &tables) { BoundStatement Binder::Bind(ExportStatement &stmt) { // COPY TO a file auto &config = DBConfig::GetConfig(context); - if (!config.enable_external_access) { + if (!config.options.enable_external_access) { throw PermissionException("COPY TO is disabled through configuration"); } BoundStatement result; @@ -172389,6 +186684,37 @@ BoundStatement Binder::Bind(ExportStatement &stmt) { +namespace duckdb { + +BoundStatement Binder::Bind(ExtensionStatement &stmt) { + BoundStatement result; + + // perform the planning of the function + D_ASSERT(stmt.extension.plan_function); + auto parse_result = stmt.extension.plan_function(stmt.extension.parser_info.get(), context, move(stmt.parse_data)); + + properties.read_only = parse_result.read_only; + properties.requires_valid_transaction = parse_result.requires_valid_transaction; + properties.return_type = parse_result.return_type; + + // create the plan as a scan of the given table function + result.plan = BindTableFunction(parse_result.function, move(parse_result.parameters)); + D_ASSERT(result.plan->type == LogicalOperatorType::LOGICAL_GET); + auto &get = (LogicalGet &)*result.plan; + result.names = get.names; + result.types = get.returned_types; + get.column_ids.clear(); + for (idx_t i = 0; i < get.returned_types.size(); i++) { + get.column_ids.push_back(i); + } + return result; +} + +} // namespace duckdb + + + + //===----------------------------------------------------------------------===// @@ -172453,6 +186779,9 @@ BoundStatement Binder::Bind(InsertStatement &stmt) { auto insert = make_unique(table); + // Add CTEs as bindable + AddCTEMap(stmt.cte_map); + idx_t generated_column_count = 0; vector named_column_map; if (!stmt.columns.empty()) { @@ -172598,6 +186927,26 @@ BoundStatement Binder::Bind(LoadStatement &stmt) { } // namespace duckdb +#include + +namespace duckdb { + +BoundStatement Binder::Bind(LogicalPlanStatement &stmt) { + BoundStatement result; + result.types = stmt.plan->types; + for (idx_t i = 0; i < result.types.size(); i++) { + result.names.push_back(StringUtil::Format("col%d", i)); + } + result.plan = move(stmt.plan); + properties.allow_stream_result = true; + properties.return_type = StatementReturnType::QUERY_RESULT; // TODO could also be something else + + return result; +} + +} // namespace duckdb + + @@ -172613,7 +186962,7 @@ BoundStatement Binder::Bind(PragmaStatement &stmt) { if (bound_idx == DConstants::INVALID_INDEX) { throw BinderException(FormatError(stmt.stmt_location, error)); } - auto &bound_function = entry->functions[bound_idx]; + auto bound_function = entry->functions.GetFunctionByOffset(bound_idx); if (!bound_function.function) { throw BinderException("PRAGMA function does not have a function specified"); } @@ -172637,6 +186986,36 @@ BoundStatement Binder::Bind(PragmaStatement &stmt) { +namespace duckdb { + +BoundStatement Binder::Bind(PrepareStatement &stmt) { + Planner prepared_planner(context); + auto prepared_data = prepared_planner.PrepareSQLStatement(move(stmt.statement)); + + auto prepare = make_unique(stmt.name, move(prepared_data), move(prepared_planner.plan)); + // we can prepare in read-only mode: prepared statements are not written to the catalog + properties.read_only = true; + // we can always prepare, even if the transaction has been invalidated + // this is required because most clients ALWAYS invoke prepared statements + properties.requires_valid_transaction = false; + properties.allow_stream_result = false; + properties.bound_all_parameters = true; + properties.parameter_count = 0; + properties.return_type = StatementReturnType::NOTHING; + + BoundStatement result; + result.names = {"Success"}; + result.types = {LogicalType::BOOLEAN}; + result.plan = move(prepare); + return result; +} + +} // namespace duckdb + + + + + namespace duckdb { @@ -172725,7 +187104,8 @@ BoundStatement Binder::Bind(AlterStatement &stmt) { result.names = {"Success"}; result.types = {LogicalType::BOOLEAN}; Catalog &catalog = Catalog::GetCatalog(context); - auto entry = catalog.GetEntry(context, stmt.info->GetCatalogType(), stmt.info->schema, stmt.info->name, true); + auto entry = catalog.GetEntry(context, stmt.info->GetCatalogType(), stmt.info->schema, stmt.info->name, + stmt.info->if_exists); if (entry && !entry->temporary) { // we can only alter temporary tables/views in read-only mode properties.read_only = false; @@ -173074,6 +187454,9 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) { auto &table_binding = (BoundBaseTableRef &)*bound_table; auto table = table_binding.table; + // Add CTEs as bindable + AddCTEMap(stmt.cte_map); + if (stmt.from_table) { BoundCrossProductRef bound_crossproduct; bound_crossproduct.left = move(bound_table); @@ -173182,13 +187565,61 @@ BoundStatement Binder::Bind(UpdateStatement &stmt) { + + + namespace duckdb { BoundStatement Binder::Bind(VacuumStatement &stmt) { BoundStatement result; + + unique_ptr root; + + if (stmt.info->has_table) { + D_ASSERT(!stmt.info->table); + D_ASSERT(stmt.info->column_id_map.empty()); + auto bound_table = Bind(*stmt.info->ref); + if (bound_table->type != TableReferenceType::BASE_TABLE) { + throw InvalidInputException("Can only vacuum/analyze base tables!"); + } + auto ref = unique_ptr_cast(move(bound_table)); + stmt.info->table = ref->table; + + auto &columns = stmt.info->columns; + vector> select_list; + if (columns.empty()) { + // Empty means ALL columns should be vacuumed/analyzed + auto &get = (LogicalGet &)*ref->get; + columns.insert(columns.end(), get.names.begin(), get.names.end()); + } + for (auto &col_name : columns) { + ColumnRefExpression colref(col_name, ref->table->name); + auto result = bind_context.BindColumn(colref, 0); + if (result.HasError()) { + throw BinderException(result.error); + } + select_list.push_back(move(result.expression)); + } + auto table_scan = CreatePlan(*ref); + D_ASSERT(table_scan->type == LogicalOperatorType::LOGICAL_GET); + auto &get = (LogicalGet &)*table_scan; + for (idx_t i = 0; i < get.column_ids.size(); i++) { + stmt.info->column_id_map[i] = get.column_ids[i]; + } + + auto projection = make_unique(GenerateTableIndex(), move(select_list)); + projection->children.push_back(move(table_scan)); + + root = move(projection); + } + auto vacuum = make_unique(LogicalOperatorType::LOGICAL_VACUUM, move(stmt.info)); + if (root) { + vacuum->children.push_back(move(root)); + } + result.names = {"Success"}; result.types = {LogicalType::BOOLEAN}; - result.plan = make_unique(LogicalOperatorType::LOGICAL_VACUUM, move(stmt.info)); + result.plan = move(vacuum); properties.return_type = StatementReturnType::NOTHING; return result; } @@ -173922,8 +188353,9 @@ unique_ptr Binder::Bind(SubqueryRef &ref, CommonTableExpressionIn namespace duckdb { static bool IsTableInTableOutFunction(TableFunctionCatalogEntry &table_function) { - return table_function.functions.size() == 1 && table_function.functions[0].arguments.size() == 1 && - table_function.functions[0].arguments[0].id() == LogicalTypeId::TABLE; + auto fun = table_function.functions.GetFunctionByOffset(0); + return table_function.functions.Size() == 1 && fun.arguments.size() == 1 && + fun.arguments[0].id() == LogicalTypeId::TABLE; } bool Binder::BindTableInTableOutFunction(vector> &expressions, @@ -173989,6 +188421,9 @@ bool Binder::BindTableFunctionParameters(TableFunctionCatalogEntry &table_functi ConstantBinder binder(*this, context, "TABLE FUNCTION parameter"); LogicalType sql_type; auto expr = binder.Bind(child, &sql_type); + if (expr->HasParameter()) { + throw ParameterNotResolvedException(); + } if (!expr->IsFoldable()) { error = "Table function requires a constant parameter"; return false; @@ -174009,9 +188444,64 @@ bool Binder::BindTableFunctionParameters(TableFunctionCatalogEntry &table_functi return true; } +unique_ptr +Binder::BindTableFunctionInternal(TableFunction &table_function, const string &function_name, vector parameters, + named_parameter_map_t named_parameters, vector input_table_types, + vector input_table_names, const vector &column_name_alias, + unique_ptr external_dependency) { + auto bind_index = GenerateTableIndex(); + // perform the binding + unique_ptr bind_data; + vector return_types; + vector return_names; + if (table_function.bind) { + TableFunctionBindInput bind_input(parameters, named_parameters, input_table_types, input_table_names, + table_function.function_info.get()); + bind_data = table_function.bind(context, bind_input, return_types, return_names); + if (table_function.name == "pandas_scan" || table_function.name == "arrow_scan") { + auto arrow_bind = (PyTableFunctionData *)bind_data.get(); + arrow_bind->external_dependency = move(external_dependency); + } + } + if (return_types.size() != return_names.size()) { + throw InternalException( + "Failed to bind \"%s\": Table function return_types and return_names must be of the same size", + table_function.name); + } + if (return_types.empty()) { + throw InternalException("Failed to bind \"%s\": Table function must return at least one column", + table_function.name); + } + // overwrite the names with any supplied aliases + for (idx_t i = 0; i < column_name_alias.size() && i < return_names.size(); i++) { + return_names[i] = column_name_alias[i]; + } + for (idx_t i = 0; i < return_names.size(); i++) { + if (return_names[i].empty()) { + return_names[i] = "C" + to_string(i); + } + } + auto get = make_unique(bind_index, table_function, move(bind_data), return_types, return_names); + get->parameters = parameters; + get->named_parameters = named_parameters; + get->input_table_types = input_table_types; + get->input_table_names = input_table_names; + // now add the table function to the bind context so its columns can be bound + bind_context.AddTableFunction(bind_index, function_name, return_names, return_types, *get); + return move(get); +} + +unique_ptr Binder::BindTableFunction(TableFunction &function, vector parameters) { + named_parameter_map_t named_parameters; + vector input_table_types; + vector input_table_names; + vector column_name_aliases; + return BindTableFunctionInternal(function, function.name, move(parameters), move(named_parameters), + move(input_table_types), move(input_table_names), column_name_aliases, nullptr); +} + unique_ptr Binder::Bind(TableFunctionRef &ref) { QueryErrorContext error_context(root_statement, ref.query_location); - auto bind_index = GenerateTableIndex(); D_ASSERT(ref.function->type == ExpressionType::FUNCTION); auto fexpr = (FunctionExpression *)ref.function.get(); @@ -174064,7 +188554,7 @@ unique_ptr Binder::Bind(TableFunctionRef &ref) { if (best_function_idx == DConstants::INVALID_INDEX) { throw BinderException(FormatError(ref, error)); } - auto &table_function = function->functions[best_function_idx]; + auto table_function = function->functions.GetFunctionByOffset(best_function_idx); // now check the named parameters BindNamedParameters(table_function.named_parameters, named_parameters, error_context, table_function.name); @@ -174085,38 +188575,9 @@ unique_ptr Binder::Bind(TableFunctionRef &ref) { input_table_types = subquery->subquery->types; input_table_names = subquery->subquery->names; } - - // perform the binding - unique_ptr bind_data; - vector return_types; - vector return_names; - if (table_function.bind) { - TableFunctionBindInput bind_input(parameters, named_parameters, input_table_types, input_table_names, - table_function.function_info.get()); - bind_data = table_function.bind(context, bind_input, return_types, return_names); - } - if (return_types.size() != return_names.size()) { - throw InternalException( - "Failed to bind \"%s\": Table function return_types and return_names must be of the same size", - table_function.name); - } - if (return_types.empty()) { - throw InternalException("Failed to bind \"%s\": Table function must return at least one column", - table_function.name); - } - // overwrite the names with any supplied aliases - for (idx_t i = 0; i < ref.column_name_alias.size() && i < return_names.size(); i++) { - return_names[i] = ref.column_name_alias[i]; - } - for (idx_t i = 0; i < return_names.size(); i++) { - if (return_names[i].empty()) { - return_names[i] = "C" + to_string(i); - } - } - auto get = make_unique(bind_index, table_function, move(bind_data), return_types, return_names); - // now add the table function to the bind context so its columns can be bound - bind_context.AddTableFunction(bind_index, ref.alias.empty() ? fexpr->function_name : ref.alias, return_names, - return_types, *get); + auto get = BindTableFunctionInternal(table_function, ref.alias.empty() ? fexpr->function_name : ref.alias, + move(parameters), move(named_parameters), move(input_table_types), + move(input_table_names), ref.column_name_alias, move(ref.external_dependency)); if (subquery) { get->children.push_back(Binder::CreatePlan(*subquery)); } @@ -174143,15 +188604,10 @@ unique_ptr Binder::CreatePlan(BoundBaseTableRef &ref) { namespace duckdb { unique_ptr Binder::CreatePlan(BoundCrossProductRef &expr) { - auto cross_product = make_unique(); - auto left = CreatePlan(*expr.left); auto right = CreatePlan(*expr.right); - cross_product->AddChild(move(left)); - cross_product->AddChild(move(right)); - - return move(cross_product); + return LogicalCrossProduct::Create(move(left), move(right)); } } // namespace duckdb @@ -174374,12 +188830,7 @@ unique_ptr Binder::CreatePlan(BoundJoinRef &ref) { if (ref.type == JoinType::INNER && (ref.condition->HasSubquery() || HasCorrelatedColumns(*ref.condition))) { // inner join, generate a cross product + filter // this will be later turned into a proper join by the join order optimizer - auto cross_product = make_unique(); - - cross_product->AddChild(move(left)); - cross_product->AddChild(move(right)); - - unique_ptr root = move(cross_product); + auto root = LogicalCrossProduct::Create(move(left), move(right)); auto filter = make_unique(move(ref.condition)); // visit the expressions in the filter @@ -174479,9 +188930,9 @@ unique_ptr Binder::CreatePlan(BoundTableFunction &ref) { -#include +#include namespace duckdb { @@ -174492,16 +188943,17 @@ shared_ptr Binder::CreateBinder(ClientContext &context, Binder *parent, Binder::Binder(bool, ClientContext &context, shared_ptr parent_p, bool inherit_ctes_p) : context(context), parent(move(parent_p)), bound_tables(0), inherit_ctes(inherit_ctes_p) { parameters = nullptr; - parameter_types = nullptr; if (parent) { - // We have to inherit macro parameter bindings from the parent binder, if there is a parent. + + // We have to inherit macro and lambda parameter bindings and from the parent binder, if there is a parent. macro_binding = parent->macro_binding; + lambda_bindings = parent->lambda_bindings; + if (inherit_ctes) { // We have to inherit CTE bindings from the parent bind_context, if there is a parent. bind_context.SetCTEBindings(parent->bind_context.GetCTEBindings()); bind_context.cte_references = parent->bind_context.cte_references; parameters = parent->parameters; - parameter_types = parent->parameter_types; } } } @@ -174545,17 +188997,29 @@ BoundStatement Binder::Bind(SQLStatement &statement) { return Bind((SetStatement &)statement); case StatementType::LOAD_STATEMENT: return Bind((LoadStatement &)statement); + case StatementType::EXTENSION_STATEMENT: + return Bind((ExtensionStatement &)statement); + case StatementType::PREPARE_STATEMENT: + return Bind((PrepareStatement &)statement); + case StatementType::EXECUTE_STATEMENT: + return Bind((ExecuteStatement &)statement); + case StatementType::LOGICAL_PLAN_STATEMENT: + return Bind((LogicalPlanStatement &)statement); default: // LCOV_EXCL_START throw NotImplementedException("Unimplemented statement type \"%s\" for Bind", StatementTypeToString(statement.type)); } // LCOV_EXCL_STOP } -unique_ptr Binder::BindNode(QueryNode &node) { - // first we visit the set of CTEs and add them to the bind context - for (auto &cte_it : node.cte_map) { +void Binder::AddCTEMap(CommonTableExpressionMap &cte_map) { + for (auto &cte_it : cte_map.map) { AddCTE(cte_it.first, cte_it.second.get()); } +} + +unique_ptr Binder::BindNode(QueryNode &node) { + // first we visit the set of CTEs and add them to the bind context + AddCTEMap(node.cte_map); // now we bind the node unique_ptr result; switch (node.type) { @@ -174781,12 +189245,14 @@ bool Binder::HasMatchingBinding(const string &table_name, const string &column_n bool Binder::HasMatchingBinding(const string &schema_name, const string &table_name, const string &column_name, string &error_message) { - Binding *binding; + Binding *binding = nullptr; + D_ASSERT(!lambda_bindings); if (macro_binding && table_name == macro_binding->alias) { binding = macro_binding; } else { binding = bind_context.GetBinding(table_name, error_message); } + if (!binding) { return false; } @@ -174821,6 +189287,10 @@ BindingMode Binder::GetBindingMode() { return mode; } +void Binder::SetCanContainNulls(bool can_contain_nulls_p) { + can_contain_nulls = can_contain_nulls_p; +} + void Binder::AddTableName(string table_name) { if (parent) { parent->AddTableName(move(table_name)); @@ -174900,6 +189370,7 @@ BoundStatement Binder::BindReturning(vector> return } // namespace duckdb + namespace duckdb { BoundResultModifier::BoundResultModifier(ResultModifierType type) : type(type) { @@ -174950,6 +189421,24 @@ string BoundOrderByNode::ToString() const { return str; } +void BoundOrderByNode::Serialize(Serializer &serializer) const { + FieldWriter writer(serializer); + writer.WriteField(type); + writer.WriteField(null_order); + writer.WriteSerializable(*expression); + // TODO statistics + writer.Finalize(); +} + +BoundOrderByNode BoundOrderByNode::Deserialize(Deserializer &source, PlanDeserializationState &state) { + FieldReader reader(source); + auto type = reader.ReadRequired(); + auto null_order = reader.ReadRequired(); + auto expression = reader.ReadRequiredSerializable(state); + reader.Finalize(); + return BoundOrderByNode(type, null_order, move(expression)); +} + BoundLimitModifier::BoundLimitModifier() : BoundResultModifier(ResultModifierType::LIMIT_MODIFIER) { } @@ -174971,6 +189460,108 @@ BoundLimitPercentModifier::BoundLimitPercentModifier() +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/function/function_serialization.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +class FunctionSerializer { +public: + template + static void SerializeBase(FieldWriter &writer, const FUNC &function, FunctionData *bind_info) { + D_ASSERT(!function.name.empty()); + writer.WriteString(function.name); + writer.WriteRegularSerializableList(function.arguments); + writer.WriteRegularSerializableList(function.original_arguments); + bool serialize = function.serialize; + writer.WriteField(serialize); + if (serialize) { + D_ASSERT(function.deserialize); + function.serialize(writer, bind_info, function); + } + } + + template + static void Serialize(FieldWriter &writer, const FUNC &function, const LogicalType &return_type, + const vector> &children, FunctionData *bind_info) { + SerializeBase(writer, function, bind_info); + writer.WriteSerializable(return_type); + writer.WriteSerializableList(children); + } + + template + static FUNC DeserializeBaseInternal(FieldReader &reader, PlanDeserializationState &state, CatalogType type, + unique_ptr &bind_info, bool &has_deserialize) { + auto &context = state.context; + auto name = reader.ReadRequired(); + auto arguments = reader.ReadRequiredSerializableList(); + // note: original_arguments are optional (can be list of size 0) + auto original_arguments = reader.ReadRequiredSerializableList(); + + auto &catalog = Catalog::GetCatalog(context); + auto func_catalog = catalog.GetEntry(context, type, DEFAULT_SCHEMA, name); + if (!func_catalog || func_catalog->type != type) { + throw InternalException("Cant find catalog entry for function %s", name); + } + + auto functions = (CATALOG_ENTRY *)func_catalog; + auto function = + functions->functions.GetFunctionByArguments(original_arguments.empty() ? arguments : original_arguments); + function.arguments = move(arguments); + function.original_arguments = move(original_arguments); + + has_deserialize = reader.ReadRequired(); + if (has_deserialize) { + if (!function.deserialize) { + throw SerializationException("Function requires deserialization but no deserialization function for %s", + function.name); + } + bind_info = function.deserialize(context, reader, function); + } else { + D_ASSERT(!function.serialize); + D_ASSERT(!function.deserialize); + } + return function; + } + template + static FUNC DeserializeBase(FieldReader &reader, PlanDeserializationState &state, CatalogType type, + unique_ptr &bind_info) { + bool has_deserialize; + return DeserializeBaseInternal(reader, state, type, bind_info, has_deserialize); + } + + template + static FUNC Deserialize(FieldReader &reader, ExpressionDeserializationState &state, CatalogType type, + vector> &children, unique_ptr &bind_info) { + bool has_deserialize; + auto function = + DeserializeBaseInternal(reader, state.gstate, type, bind_info, has_deserialize); + auto return_type = reader.ReadRequiredSerializable(); + children = reader.ReadRequiredSerializableList(state.gstate); + + // we re-bind the function only if the function did not have an explicit deserialize method + auto &context = state.gstate.context; + if (!has_deserialize && function.bind) { + bind_info = function.bind(context, function, children); + } + function.return_type = return_type; + return function; + } +}; + +} // namespace duckdb + + namespace duckdb { BoundAggregateExpression::BoundAggregateExpression(AggregateFunction function, vector> children, @@ -175023,7 +189614,8 @@ bool BoundAggregateExpression::Equals(const BaseExpression *other_p) const { } bool BoundAggregateExpression::PropagatesNullValues() const { - return !function.propagates_null_values ? false : Expression::PropagatesNullValues(); + return function.null_handling == FunctionNullHandling::SPECIAL_HANDLING ? false + : Expression::PropagatesNullValues(); } unique_ptr BoundAggregateExpression::Copy() { @@ -175039,10 +189631,29 @@ unique_ptr BoundAggregateExpression::Copy() { return move(copy); } +void BoundAggregateExpression::Serialize(FieldWriter &writer) const { + writer.WriteField(distinct); + writer.WriteOptional(filter); + FunctionSerializer::Serialize(writer, function, return_type, children, bind_info.get()); +} + +unique_ptr BoundAggregateExpression::Deserialize(ExpressionDeserializationState &state, + FieldReader &reader) { + auto distinct = reader.ReadRequired(); + auto filter = reader.ReadOptional(nullptr, state.gstate); + vector> children; + unique_ptr bind_info; + auto function = FunctionSerializer::Deserialize( + reader, state, CatalogType::AGGREGATE_FUNCTION_ENTRY, children, bind_info); + + return make_unique(function, move(children), move(filter), move(bind_info), distinct); +} + } // namespace duckdb + namespace duckdb { BoundBetweenExpression::BoundBetweenExpression(unique_ptr input, unique_ptr lower, @@ -175080,10 +189691,28 @@ unique_ptr BoundBetweenExpression::Copy() { return move(copy); } +void BoundBetweenExpression::Serialize(FieldWriter &writer) const { + writer.WriteOptional(input); + writer.WriteOptional(lower); + writer.WriteOptional(upper); + writer.WriteField(lower_inclusive); + writer.WriteField(upper_inclusive); +} + +unique_ptr BoundBetweenExpression::Deserialize(ExpressionDeserializationState &state, FieldReader &reader) { + auto input = reader.ReadOptional(nullptr, state.gstate); + auto lower = reader.ReadOptional(nullptr, state.gstate); + auto upper = reader.ReadOptional(nullptr, state.gstate); + auto lower_inclusive = reader.ReadRequired(); + auto upper_inclusive = reader.ReadRequired(); + return make_unique(move(input), move(lower), move(upper), lower_inclusive, upper_inclusive); +} + } // namespace duckdb + namespace duckdb { BoundCaseExpression::BoundCaseExpression(LogicalType type) @@ -175140,11 +189769,48 @@ unique_ptr BoundCaseExpression::Copy() { return move(new_case); } +void BoundCaseCheck::Serialize(Serializer &serializer) const { + FieldWriter writer(serializer); + writer.WriteSerializable(*when_expr); + writer.WriteSerializable(*then_expr); + writer.Finalize(); +} + +BoundCaseCheck BoundCaseCheck::Deserialize(Deserializer &source, PlanDeserializationState &state) { + FieldReader reader(source); + auto when_expr = reader.ReadRequiredSerializable(state); + auto then_expr = reader.ReadRequiredSerializable(state); + reader.Finalize(); + BoundCaseCheck result; + result.when_expr = move(when_expr); + result.then_expr = move(then_expr); + return result; +} + +void BoundCaseExpression::Serialize(FieldWriter &writer) const { + writer.WriteSerializable(return_type); + writer.WriteRegularSerializableList(case_checks); + writer.WriteSerializable(*else_expr); +} + +unique_ptr BoundCaseExpression::Deserialize(ExpressionDeserializationState &state, FieldReader &reader) { + auto return_type = reader.ReadRequiredSerializable(); + auto case_checks = reader.ReadRequiredSerializableList(state.gstate); + auto else_expr = reader.ReadRequiredSerializable(state.gstate); + + auto result = make_unique(return_type); + result->else_expr = move(else_expr); + result->case_checks = move(case_checks); + return move(result); +} + } // namespace duckdb + + namespace duckdb { BoundCastExpression::BoundCastExpression(unique_ptr child_p, LogicalType target_type_p, bool try_cast_p) @@ -175152,30 +189818,67 @@ BoundCastExpression::BoundCastExpression(unique_ptr child_p, Logical try_cast(try_cast_p) { } +unique_ptr AddCastExpressionInternal(unique_ptr expr, const LogicalType &target_type, + bool try_cast) { + if (expr->return_type == target_type) { + return expr; + } + auto &expr_type = expr->return_type; + if (target_type.id() == LogicalTypeId::LIST && expr_type.id() == LogicalTypeId::LIST) { + auto &target_list = ListType::GetChildType(target_type); + auto &expr_list = ListType::GetChildType(expr_type); + if (target_list.id() == LogicalTypeId::ANY || expr_list == target_list) { + return expr; + } + } + return make_unique(move(expr), target_type, try_cast); +} + unique_ptr BoundCastExpression::AddCastToType(unique_ptr expr, const LogicalType &target_type, bool try_cast) { D_ASSERT(expr); if (expr->expression_class == ExpressionClass::BOUND_PARAMETER) { auto ¶meter = (BoundParameterExpression &)*expr; + if (!target_type.IsValid()) { + // invalidate the parameter + parameter.parameter_data->return_type = LogicalType::INVALID; + parameter.return_type = target_type; + return expr; + } + if (parameter.parameter_data->return_type.id() == LogicalTypeId::INVALID) { + // we don't know the type of this parameter + parameter.return_type = target_type; + return expr; + } + if (parameter.parameter_data->return_type.id() == LogicalTypeId::UNKNOWN) { + // prepared statement parameter cast - but there is no type, convert the type + parameter.parameter_data->return_type = target_type; + parameter.return_type = target_type; + return expr; + } + // prepared statement parameter already has a type + if (parameter.parameter_data->return_type == target_type) { + // this type! we are done + parameter.return_type = parameter.parameter_data->return_type; + return expr; + } + // invalidate the type + parameter.parameter_data->return_type = LogicalType::INVALID; parameter.return_type = target_type; + return expr; } else if (expr->expression_class == ExpressionClass::BOUND_DEFAULT) { + D_ASSERT(target_type.IsValid()); auto &def = (BoundDefaultExpression &)*expr; def.return_type = target_type; - } else if (expr->return_type != target_type) { - auto &expr_type = expr->return_type; - if (target_type.id() == LogicalTypeId::LIST && expr_type.id() == LogicalTypeId::LIST) { - auto &target_list = ListType::GetChildType(target_type); - auto &expr_list = ListType::GetChildType(expr_type); - if (target_list.id() == LogicalTypeId::ANY || expr_list == target_list) { - return expr; - } - } - return make_unique(move(expr), target_type, try_cast); } - return expr; + if (!target_type.IsValid()) { + return expr; + } + return AddCastExpressionInternal(move(expr), target_type, try_cast); } bool BoundCastExpression::CastIsInvertible(const LogicalType &source_type, const LogicalType &target_type) { + D_ASSERT(source_type.IsValid() && target_type.IsValid()); if (source_type.id() == LogicalTypeId::BOOLEAN || target_type.id() == LogicalTypeId::BOOLEAN) { return false; } @@ -175213,7 +189916,6 @@ bool BoundCastExpression::CastIsInvertible(const LogicalType &source_type, const } if (source_type.id() == LogicalTypeId::VARCHAR) { switch (target_type.id()) { - case LogicalTypeId::DATE: case LogicalTypeId::TIME: case LogicalTypeId::TIMESTAMP: case LogicalTypeId::TIMESTAMP_NS: @@ -175268,12 +189970,26 @@ unique_ptr BoundCastExpression::Copy() { return move(copy); } +void BoundCastExpression::Serialize(FieldWriter &writer) const { + writer.WriteSerializable(*child); + writer.WriteSerializable(return_type); + writer.WriteField(try_cast); +} + +unique_ptr BoundCastExpression::Deserialize(ExpressionDeserializationState &state, FieldReader &reader) { + auto child = reader.ReadRequiredSerializable(state.gstate); + auto target_type = reader.ReadRequiredSerializable(); + auto try_cast = reader.ReadRequired(); + return make_unique(move(child), move(target_type), try_cast); +} + } // namespace duckdb + namespace duckdb { BoundColumnRefExpression::BoundColumnRefExpression(string alias_p, LogicalType type, ColumnBinding binding, idx_t depth) @@ -175312,10 +190028,30 @@ string BoundColumnRefExpression::ToString() const { return "#[" + to_string(binding.table_index) + "." + to_string(binding.column_index) + "]"; } +void BoundColumnRefExpression::Serialize(FieldWriter &writer) const { + writer.WriteString(alias); + writer.WriteSerializable(return_type); + writer.WriteField(binding.table_index); + writer.WriteField(binding.column_index); + writer.WriteField(depth); +} + +unique_ptr BoundColumnRefExpression::Deserialize(ExpressionDeserializationState &state, + FieldReader &reader) { + auto alias = reader.ReadRequired(); + auto return_type = reader.ReadRequiredSerializable(); + auto table_index = reader.ReadRequired(); + auto column_index = reader.ReadRequired(); + auto depth = reader.ReadRequired(); + + return make_unique(alias, return_type, ColumnBinding(table_index, column_index), depth); +} + } // namespace duckdb + namespace duckdb { BoundComparisonExpression::BoundComparisonExpression(ExpressionType type, unique_ptr left, @@ -175348,11 +190084,24 @@ unique_ptr BoundComparisonExpression::Copy() { return move(copy); } +void BoundComparisonExpression::Serialize(FieldWriter &writer) const { + writer.WriteOptional(left); + writer.WriteOptional(right); +} + +unique_ptr BoundComparisonExpression::Deserialize(ExpressionDeserializationState &state, + FieldReader &reader) { + auto left = reader.ReadOptional(nullptr, state.gstate); + auto right = reader.ReadOptional(nullptr, state.gstate); + return make_unique(state.type, move(left), move(right)); +} + } // namespace duckdb + namespace duckdb { BoundConjunctionExpression::BoundConjunctionExpression(ExpressionType type) @@ -175391,6 +190140,18 @@ unique_ptr BoundConjunctionExpression::Copy() { return move(copy); } +void BoundConjunctionExpression::Serialize(FieldWriter &writer) const { + writer.WriteSerializableList(children); +} + +unique_ptr BoundConjunctionExpression::Deserialize(ExpressionDeserializationState &state, + FieldReader &reader) { + auto children = reader.ReadRequiredSerializableList(state.gstate); + auto res = make_unique(state.type); + res->children = move(children); + return move(res); +} + } // namespace duckdb @@ -175413,7 +190174,7 @@ bool BoundConstantExpression::Equals(const BaseExpression *other_p) const { return false; } auto other = (BoundConstantExpression *)other_p; - return !ValueOperations::DistinctFrom(value, other->value); + return value.type() == other->value.type() && !ValueOperations::DistinctFrom(value, other->value); } hash_t BoundConstantExpression::Hash() const { @@ -175427,10 +190188,62 @@ unique_ptr BoundConstantExpression::Copy() { return move(copy); } +void BoundConstantExpression::Serialize(FieldWriter &writer) const { + value.Serialize(writer.GetSerializer()); +} + +unique_ptr BoundConstantExpression::Deserialize(ExpressionDeserializationState &state, + FieldReader &reader) { + auto value = Value::Deserialize(reader.GetSource()); + return make_unique(value); +} + } // namespace duckdb +namespace duckdb { + +void BoundDefaultExpression::Serialize(FieldWriter &writer) const { + throw NotImplementedException(ExpressionTypeToString(type)); +} + +} // namespace duckdb + + +namespace duckdb { + +BoundExpression::BoundExpression(unique_ptr expr) + : ParsedExpression(ExpressionType::INVALID, ExpressionClass::BOUND_EXPRESSION), expr(move(expr)) { +} + +string BoundExpression::ToString() const { + if (!expr) { + throw InternalException("ToString(): BoundExpression does not have a child"); + } + return expr->ToString(); +} + +bool BoundExpression::Equals(const BaseExpression *other) const { + return false; +} +hash_t BoundExpression::Hash() const { + return 0; +} + +unique_ptr BoundExpression::Copy() const { + throw SerializationException("Cannot copy or serialize bound expression"); +} + +void BoundExpression::Serialize(FieldWriter &writer) const { + throw SerializationException("Cannot copy or serialize bound expression"); +} + +} // namespace duckdb + + + + @@ -175445,12 +190258,12 @@ BoundFunctionExpression::BoundFunctionExpression(LogicalType return_type, Scalar } bool BoundFunctionExpression::HasSideEffects() const { - return function.has_side_effects ? true : Expression::HasSideEffects(); + return function.side_effects == FunctionSideEffects::HAS_SIDE_EFFECTS ? true : Expression::HasSideEffects(); } bool BoundFunctionExpression::IsFoldable() const { // functions with side effects cannot be folded: they have to be executed once for every row - return function.has_side_effects ? false : Expression::IsFoldable(); + return function.side_effects == FunctionSideEffects::HAS_SIDE_EFFECTS ? false : Expression::IsFoldable(); } string BoundFunctionExpression::ToString() const { @@ -175458,7 +190271,8 @@ string BoundFunctionExpression::ToString() const { is_operator); } bool BoundFunctionExpression::PropagatesNullValues() const { - return !function.propagates_null_values ? false : Expression::PropagatesNullValues(); + return function.null_handling == FunctionNullHandling::SPECIAL_HANDLING ? false + : Expression::PropagatesNullValues(); } hash_t BoundFunctionExpression::Hash() const { @@ -175500,12 +190314,78 @@ void BoundFunctionExpression::Verify() const { D_ASSERT(!function.name.empty()); } +void BoundFunctionExpression::Serialize(FieldWriter &writer) const { + D_ASSERT(!function.name.empty()); + D_ASSERT(return_type == function.return_type); + writer.WriteField(is_operator); + FunctionSerializer::Serialize(writer, function, return_type, children, bind_info.get()); +} + +unique_ptr BoundFunctionExpression::Deserialize(ExpressionDeserializationState &state, + FieldReader &reader) { + auto is_operator = reader.ReadRequired(); + vector> children; + unique_ptr bind_info; + auto function = FunctionSerializer::Deserialize( + reader, state, CatalogType::SCALAR_FUNCTION_ENTRY, children, bind_info); + + auto return_type = function.return_type; + return make_unique(move(return_type), move(function), move(children), move(bind_info), + is_operator); +} +} // namespace duckdb + + + + +namespace duckdb { + +BoundLambdaExpression::BoundLambdaExpression(ExpressionType type_p, LogicalType return_type_p, + unique_ptr lambda_expr_p, idx_t parameter_count_p) + : Expression(type_p, ExpressionClass::BOUND_LAMBDA, move(return_type_p)), lambda_expr(move(lambda_expr_p)), + parameter_count(parameter_count_p) { +} + +string BoundLambdaExpression::ToString() const { + return lambda_expr->ToString(); +} + +bool BoundLambdaExpression::Equals(const BaseExpression *other_p) const { + if (!Expression::Equals(other_p)) { + return false; + } + auto other = (BoundLambdaExpression *)other_p; + if (!Expression::Equals(lambda_expr.get(), other->lambda_expr.get())) { + return false; + } + if (!ExpressionUtil::ListEquals(captures, other->captures)) { + return false; + } + if (parameter_count != other->parameter_count) { + return false; + } + return true; +} + +unique_ptr BoundLambdaExpression::Copy() { + auto copy = make_unique(type, return_type, lambda_expr->Copy(), parameter_count); + for (auto &capture : captures) { + copy->captures.push_back(capture->Copy()); + } + return move(copy); +} + +void BoundLambdaExpression::Serialize(FieldWriter &writer) const { + throw NotImplementedException(ExpressionTypeToString(type)); +} + } // namespace duckdb + namespace duckdb { BoundOperatorExpression::BoundOperatorExpression(ExpressionType type, LogicalType return_type) @@ -175536,17 +190416,51 @@ unique_ptr BoundOperatorExpression::Copy() { return move(copy); } +void BoundOperatorExpression::Serialize(FieldWriter &writer) const { + writer.WriteSerializable(return_type); + writer.WriteSerializableList(children); +} + +unique_ptr BoundOperatorExpression::Deserialize(ExpressionDeserializationState &state, + FieldReader &reader) { + auto return_type = reader.ReadRequiredSerializable(); + auto children = reader.ReadRequiredSerializableList(state.gstate); + + auto result = make_unique(state.type, return_type); + result->children = move(children); + return move(result); +} + } // namespace duckdb + + namespace duckdb { BoundParameterExpression::BoundParameterExpression(idx_t parameter_nr) : Expression(ExpressionType::VALUE_PARAMETER, ExpressionClass::BOUND_PARAMETER, LogicalType(LogicalTypeId::UNKNOWN)), - parameter_nr(parameter_nr), value(nullptr) { + parameter_nr(parameter_nr) { +} + +void BoundParameterExpression::Invalidate(Expression &expr) { + if (expr.type != ExpressionType::VALUE_PARAMETER) { + throw InternalException("BoundParameterExpression::Invalidate requires a parameter as input"); + } + auto &bound_parameter = (BoundParameterExpression &)expr; + bound_parameter.return_type = LogicalTypeId::SQLNULL; + bound_parameter.parameter_data->return_type = LogicalTypeId::INVALID; +} + +void BoundParameterExpression::InvalidateRecursive(Expression &expr) { + if (expr.type == ExpressionType::VALUE_PARAMETER) { + Invalidate(expr); + return; + } + ExpressionIterator::EnumerateChildren(expr, [&](Expression &child) { InvalidateRecursive(child); }); } bool BoundParameterExpression::IsScalar() const { @@ -175560,7 +190474,7 @@ bool BoundParameterExpression::IsFoldable() const { } string BoundParameterExpression::ToString() const { - return to_string(parameter_nr); + return "$" + to_string(parameter_nr); } bool BoundParameterExpression::Equals(const BaseExpression *other_p) const { @@ -175579,12 +190493,38 @@ hash_t BoundParameterExpression::Hash() const { unique_ptr BoundParameterExpression::Copy() { auto result = make_unique(parameter_nr); - result->value = value; + result->parameter_data = parameter_data; result->return_type = return_type; result->CopyProperties(*this); return move(result); } +void BoundParameterExpression::Serialize(FieldWriter &writer) const { + writer.WriteField(parameter_nr); + writer.WriteSerializable(return_type); + writer.WriteSerializable(*parameter_data); +} + +unique_ptr BoundParameterExpression::Deserialize(ExpressionDeserializationState &state, + FieldReader &reader) { + auto &global_parameter_set = state.gstate.parameter_data; + auto parameter_nr = reader.ReadRequired(); + auto result = make_unique(parameter_nr); + result->return_type = reader.ReadRequiredSerializable(); + auto parameter_data = reader.ReadRequiredSerializable>(); + // check if we have already deserialized a parameter with this number + auto entry = global_parameter_set.find(parameter_nr); + if (entry == global_parameter_set.end()) { + // we have not - store the entry we deserialized from this parameter expression + global_parameter_set[parameter_nr] = parameter_data; + } else { + // we have! use the previously deserialized entry + parameter_data = entry->second; + } + result->parameter_data = move(parameter_data); + return move(result); +} + } // namespace duckdb @@ -175592,6 +190532,7 @@ unique_ptr BoundParameterExpression::Copy() { + namespace duckdb { BoundReferenceExpression::BoundReferenceExpression(string alias, LogicalType type, idx_t index) @@ -175625,6 +190566,20 @@ unique_ptr BoundReferenceExpression::Copy() { return make_unique(alias, return_type, index); } +void BoundReferenceExpression::Serialize(FieldWriter &writer) const { + writer.WriteString(alias); + writer.WriteSerializable(return_type); + writer.WriteField(index); +} + +unique_ptr BoundReferenceExpression::Deserialize(ExpressionDeserializationState &state, + FieldReader &reader) { + auto alias = reader.ReadRequired(); + auto return_type = reader.ReadRequiredSerializable(); + auto index = reader.ReadRequired(); + return make_unique(alias, return_type, index); +} + } // namespace duckdb @@ -175654,12 +190609,17 @@ bool BoundSubqueryExpression::PropagatesNullValues() const { return false; } +void BoundSubqueryExpression::Serialize(FieldWriter &writer) const { + throw NotImplementedException(ExpressionTypeToString(type)); +} + } // namespace duckdb + namespace duckdb { BoundUnnestExpression::BoundUnnestExpression(LogicalType return_type) @@ -175696,6 +190656,20 @@ unique_ptr BoundUnnestExpression::Copy() { return move(copy); } +void BoundUnnestExpression::Serialize(FieldWriter &writer) const { + writer.WriteSerializable(return_type); + writer.WriteSerializable(*child); +} + +unique_ptr BoundUnnestExpression::Deserialize(ExpressionDeserializationState &state, FieldReader &reader) { + auto return_type = reader.ReadRequiredSerializable(); + auto child = reader.ReadRequiredSerializable(state.gstate); + + auto result = make_unique(return_type); + result->child = move(child); + return move(result); +} + } // namespace duckdb @@ -175703,6 +190677,8 @@ unique_ptr BoundUnnestExpression::Copy() { + + namespace duckdb { BoundWindowExpression::BoundWindowExpression(ExpressionType type, LogicalType return_type, @@ -175821,6 +190797,60 @@ unique_ptr BoundWindowExpression::Copy() { return move(new_window); } +void BoundWindowExpression::Serialize(FieldWriter &writer) const { + writer.WriteField(aggregate.get()); + if (aggregate) { + D_ASSERT(return_type == aggregate->return_type); + FunctionSerializer::Serialize(writer, *aggregate, return_type, children, bind_info.get()); + } else { + // children and return_type are written as part of the aggregate function otherwise + writer.WriteSerializableList(children); + writer.WriteSerializable(return_type); + } + writer.WriteSerializableList(partitions); + writer.WriteRegularSerializableList(orders); + // FIXME: partitions_stats + writer.WriteOptional(filter_expr); + writer.WriteField(ignore_nulls); + writer.WriteField(start); + writer.WriteField(end); + writer.WriteOptional(start_expr); + writer.WriteOptional(end_expr); + writer.WriteOptional(offset_expr); + writer.WriteOptional(default_expr); +} + +unique_ptr BoundWindowExpression::Deserialize(ExpressionDeserializationState &state, FieldReader &reader) { + auto has_aggregate = reader.ReadRequired(); + unique_ptr aggregate; + unique_ptr bind_info; + vector> children; + LogicalType return_type; + if (has_aggregate) { + auto aggr_function = FunctionSerializer::Deserialize( + reader, state, CatalogType::AGGREGATE_FUNCTION_ENTRY, children, bind_info); + aggregate = make_unique(move(aggr_function)); + return_type = aggregate->return_type; + } else { + children = reader.ReadRequiredSerializableList(state.gstate); + return_type = reader.ReadRequiredSerializable(); + } + auto result = make_unique(state.type, return_type, move(aggregate), move(bind_info)); + + result->partitions = reader.ReadRequiredSerializableList(state.gstate); + result->orders = reader.ReadRequiredSerializableList(state.gstate); + result->filter_expr = reader.ReadOptional(nullptr, state.gstate); + result->ignore_nulls = reader.ReadRequired(); + result->start = reader.ReadRequired(); + result->end = reader.ReadRequired(); + result->start_expr = reader.ReadOptional(nullptr, state.gstate); + result->end_expr = reader.ReadOptional(nullptr, state.gstate); + result->offset_expr = reader.ReadOptional(nullptr, state.gstate); + result->default_expr = reader.ReadOptional(nullptr, state.gstate); + result->children = move(children); + return move(result); +} + } // namespace duckdb @@ -175829,6 +190859,8 @@ unique_ptr BoundWindowExpression::Copy() { + + namespace duckdb { Expression::Expression(ExpressionType type, ExpressionClass expression_class, LogicalType return_type) @@ -175916,6 +190948,76 @@ hash_t Expression::Hash() const { return hash; } +void Expression::Serialize(Serializer &serializer) const { + FieldWriter writer(serializer); + writer.WriteField(expression_class); + writer.WriteField(type); + writer.WriteString(alias); + Serialize(writer); + writer.Finalize(); +} + +unique_ptr Expression::Deserialize(Deserializer &source, PlanDeserializationState &gstate) { + FieldReader reader(source); + auto expression_class = reader.ReadRequired(); + auto type = reader.ReadRequired(); + auto alias = reader.ReadRequired(); + + ExpressionDeserializationState state(gstate, type); + + unique_ptr result; + switch (expression_class) { + case ExpressionClass::BOUND_REF: + result = BoundReferenceExpression::Deserialize(state, reader); + break; + case ExpressionClass::BOUND_COLUMN_REF: + result = BoundColumnRefExpression::Deserialize(state, reader); + break; + case ExpressionClass::BOUND_AGGREGATE: + result = BoundAggregateExpression::Deserialize(state, reader); + break; + case ExpressionClass::BOUND_BETWEEN: + result = BoundBetweenExpression::Deserialize(state, reader); + break; + case ExpressionClass::BOUND_CONSTANT: + result = BoundConstantExpression::Deserialize(state, reader); + break; + case ExpressionClass::BOUND_FUNCTION: + result = BoundFunctionExpression::Deserialize(state, reader); + break; + case ExpressionClass::BOUND_CAST: + result = BoundCastExpression::Deserialize(state, reader); + break; + case ExpressionClass::BOUND_CASE: + result = BoundCaseExpression::Deserialize(state, reader); + break; + case ExpressionClass::BOUND_CONJUNCTION: + result = BoundConjunctionExpression::Deserialize(state, reader); + break; + case ExpressionClass::BOUND_COMPARISON: + result = BoundComparisonExpression::Deserialize(state, reader); + break; + case ExpressionClass::BOUND_OPERATOR: + result = BoundOperatorExpression::Deserialize(state, reader); + break; + case ExpressionClass::BOUND_WINDOW: + result = BoundWindowExpression::Deserialize(state, reader); + break; + case ExpressionClass::BOUND_UNNEST: + result = BoundUnnestExpression::Deserialize(state, reader); + break; + case ExpressionClass::BOUND_PARAMETER: + result = BoundParameterExpression::Deserialize(state, reader); + break; + default: + throw SerializationException("Unsupported type for expression deserialization %s", + ExpressionTypeToString(type)); + } + result->alias = alias; + reader.Finalize(); + return result; +} + } // namespace duckdb @@ -176072,8 +191174,11 @@ BindResult ColumnAliasBinder::BindAlias(ExpressionBinder &enclosing_binder, Colu return BindResult(StringUtil::Format("Alias %s is not found.", expr.ToString())); } + if (in_alias) { + return BindResult("Cannot resolve self-referential alias"); + } + // found an alias: bind the alias expression - D_ASSERT(!in_alias); auto expression = node.original_expressions[alias_entry->second]->Copy(); in_alias = true; auto result = enclosing_binder.BindExpression(&expression, depth, root_expression); @@ -176083,6 +191188,7 @@ BindResult ColumnAliasBinder::BindAlias(ExpressionBinder &enclosing_binder, Colu } // namespace duckdb + namespace duckdb { ConstantBinder::ConstantBinder(Binder &binder, ClientContext &context, string clause) @@ -176106,7 +191212,7 @@ BindResult ConstantBinder::BindExpression(unique_ptr *expr_ptr } string ConstantBinder::UnsupportedAggregateMessage() { - return clause + "cannot contain aggregates!"; + return clause + " cannot contain aggregates!"; } } // namespace duckdb @@ -176134,6 +191240,8 @@ BindResult GroupBinder::BindExpression(unique_ptr *expr_ptr, i return BindColumnRef((ColumnRefExpression &)expr); case ExpressionClass::CONSTANT: return BindConstant((ConstantExpression &)expr); + case ExpressionClass::PARAMETER: + throw ParameterNotAllowedException("Parameter not supported in GROUP BY clause"); default: break; } @@ -176322,6 +191430,9 @@ string InsertBinder::UnsupportedAggregateMessage() { + + + namespace duckdb { OrderBinder::OrderBinder(vector binders, idx_t projection_index, case_insensitive_map_t &alias_map, @@ -176341,7 +191452,9 @@ unique_ptr OrderBinder::CreateProjectionReference(ParsedExpression & if (extra_list && index < extra_list->size()) { alias = extra_list->at(index)->ToString(); } else { - alias = expr.GetName(); + if (!expr.alias.empty()) { + alias = expr.alias; + } } return make_unique(move(alias), LogicalType::INVALID, ColumnBinding(projection_index, index)); @@ -176353,6 +191466,22 @@ unique_ptr OrderBinder::CreateExtraReference(unique_ptr OrderBinder::BindConstant(ParsedExpression &expr, const Value &val) { + // ORDER BY a constant + if (!val.type().IsIntegral()) { + // non-integral expression, we just leave the constant here. + // ORDER BY has no effect + // CONTROVERSIAL: maybe we should throw an error + return nullptr; + } + // INTEGER constant: we use the integer as an index into the select list (e.g. ORDER BY 1) + auto index = (idx_t)val.GetValue(); + if (index < 1 || index > max_count) { + throw BinderException("ORDER term out of range - should be between 1 and %lld", (idx_t)max_count); + } + return CreateProjectionReference(expr, index - 1); +} + unique_ptr OrderBinder::Bind(unique_ptr expr) { // in the ORDER BY clause we do not bind children // we bind ONLY to the select list @@ -176364,19 +191493,7 @@ unique_ptr OrderBinder::Bind(unique_ptr expr) { // ORDER BY constant // is the ORDER BY expression a constant integer? (e.g. ORDER BY 1) auto &constant = (ConstantExpression &)*expr; - // ORDER BY a constant - if (!constant.value.type().IsIntegral()) { - // non-integral expression, we just leave the constant here. - // ORDER BY has no effect - // CONTROVERSIAL: maybe we should throw an error - return nullptr; - } - // INTEGER constant: we use the integer as an index into the select list (e.g. ORDER BY 1) - auto index = (idx_t)constant.value.GetValue(); - if (index < 1 || index > max_count) { - throw BinderException("ORDER term out of range - should be between 1 and %lld", (idx_t)max_count); - } - return CreateProjectionReference(*expr, index - 1); + return BindConstant(*expr, constant.value); } case ExpressionClass::COLUMN_REF: { // COLUMN REF expression @@ -176396,8 +191513,14 @@ unique_ptr OrderBinder::Bind(unique_ptr expr) { } case ExpressionClass::POSITIONAL_REFERENCE: { auto &posref = (PositionalReferenceExpression &)*expr; + if (posref.index < 1 || posref.index > max_count) { + throw BinderException("ORDER term out of range - should be between 1 and %lld", (idx_t)max_count); + } return CreateProjectionReference(*expr, posref.index - 1); } + case ExpressionClass::PARAMETER: { + throw ParameterNotAllowedException("Parameter not supported in ORDER BY clause"); + } default: break; } @@ -176779,7 +191902,7 @@ BindResult ExpressionBinder::BindExpression(unique_ptr *expr, // binding function expression has extra parameter needed for macro's return BindExpression((FunctionExpression &)expr_ref, depth, expr); case ExpressionClass::LAMBDA: - return BindExpression((LambdaExpression &)expr_ref, depth); + return BindExpression((LambdaExpression &)expr_ref, depth, false, LogicalTypeId::INVALID); case ExpressionClass::OPERATOR: return BindExpression((OperatorExpression &)expr_ref, depth); case ExpressionClass::SUBQUERY: @@ -176916,6 +192039,9 @@ unique_ptr ExpressionBinder::Bind(unique_ptr &expr result = BoundCastExpression::AddCastToType(move(result), result_type); } } + if (result->return_type.id() == LogicalTypeId::UNKNOWN) { + throw ParameterNotResolvedException(); + } } if (result_type) { *result_type = result->return_type; @@ -177202,6 +192328,7 @@ void ExpressionIterator::EnumerateQueryNodeChildren(BoundQueryNode &node, } // namespace duckdb + namespace duckdb { ConjunctionOrFilter::ConjunctionOrFilter() : ConjunctionFilter(TableFilterType::CONJUNCTION_OR) { @@ -177248,6 +192375,16 @@ bool ConjunctionOrFilter::Equals(const TableFilter &other_p) const { return true; } +void ConjunctionOrFilter::Serialize(FieldWriter &writer) const { + writer.WriteSerializableList(child_filters); +} + +unique_ptr ConjunctionOrFilter::Deserialize(FieldReader &source) { + auto res = make_unique(); + res->child_filters = source.ReadRequiredSerializableList(); + return move(res); +} + ConjunctionAndFilter::ConjunctionAndFilter() : ConjunctionFilter(TableFilterType::CONJUNCTION_AND) { } @@ -177293,11 +192430,22 @@ bool ConjunctionAndFilter::Equals(const TableFilter &other_p) const { return true; } +void ConjunctionAndFilter::Serialize(FieldWriter &writer) const { + writer.WriteSerializableList(child_filters); +} + +unique_ptr ConjunctionAndFilter::Deserialize(FieldReader &source) { + auto res = make_unique(); + res->child_filters = source.ReadRequiredSerializableList(); + return move(res); +} + } // namespace duckdb + namespace duckdb { ConstantFilter::ConstantFilter(ExpressionType comparison_type_p, Value constant_p) @@ -177339,6 +192487,17 @@ bool ConstantFilter::Equals(const TableFilter &other_p) const { return other.comparison_type == comparison_type && other.constant == constant; } +void ConstantFilter::Serialize(FieldWriter &writer) const { + writer.WriteField(comparison_type); + writer.WriteSerializable(constant); +} + +unique_ptr ConstantFilter::Deserialize(FieldReader &source) { + auto comparision_type = source.ReadRequired(); + auto constant = source.ReadRequiredSerializable(); + return make_unique(comparision_type, constant); +} + } // namespace duckdb @@ -177383,6 +192542,20 @@ string IsNotNullFilter::ToString(const string &column_name) { return column_name + " IS NOT NULL"; } +void IsNotNullFilter::Serialize(FieldWriter &writer) const { +} + +unique_ptr IsNotNullFilter::Deserialize(FieldReader &source) { + return make_unique(); +} + +void IsNullFilter::Serialize(FieldWriter &writer) const { +} + +unique_ptr IsNullFilter::Deserialize(FieldReader &source) { + return make_unique(); +} + } // namespace duckdb @@ -177391,6 +192564,8 @@ string IsNotNullFilter::ToString(const string &column_name) { + + namespace duckdb { unique_ptr JoinCondition::CreateExpression(JoinCondition cond) { @@ -177398,6 +192573,44 @@ unique_ptr JoinCondition::CreateExpression(JoinCondition cond) { return move(bound_comparison); } +unique_ptr JoinCondition::CreateExpression(vector conditions) { + unique_ptr result; + for (auto &cond : conditions) { + auto expr = CreateExpression(move(cond)); + if (!result) { + result = move(expr); + } else { + auto conj = + make_unique(ExpressionType::CONJUNCTION_AND, move(expr), move(result)); + result = move(conj); + } + } + return result; +} + +//! Serializes a JoinCondition to a stand-alone binary blob +void JoinCondition::Serialize(Serializer &serializer) const { + FieldWriter writer(serializer); + writer.WriteOptional(left); + writer.WriteOptional(right); + writer.WriteField(comparison); + writer.Finalize(); +} + +//! Deserializes a blob back into a JoinCondition +JoinCondition JoinCondition::Deserialize(Deserializer &source, PlanDeserializationState &state) { + auto result = JoinCondition(); + + FieldReader reader(source); + auto left = reader.ReadOptional(nullptr, state); + auto right = reader.ReadOptional(nullptr, state); + result.left = move(left); + result.right = move(right); + result.comparison = reader.ReadRequired(); + reader.Finalize(); + return result; +} + JoinSide JoinSide::CombineJoinSide(JoinSide left, JoinSide right) { if (left == JoinSide::NONE) { return right; @@ -177478,8 +192691,28 @@ JoinSide JoinSide::GetJoinSide(const unordered_set &bindings, unordered_s + + + namespace duckdb { +const uint64_t PLAN_SERIALIZATION_VERSION = 1; + +LogicalOperator::LogicalOperator(LogicalOperatorType type) + : type(type), estimated_cardinality(0), has_estimated_cardinality(false) { +} + +LogicalOperator::LogicalOperator(LogicalOperatorType type, vector> expressions) + : type(type), expressions(move(expressions)), estimated_cardinality(0), has_estimated_cardinality(false) { +} + +LogicalOperator::~LogicalOperator() { +} + +vector LogicalOperator::GetColumnBindings() { + return {ColumnBinding(0, 0)}; +} + string LogicalOperator::GetName() const { return LogicalOperatorToString(type); } @@ -177550,7 +192783,7 @@ string LogicalOperator::ToString() const { return renderer.ToString(*this); } -void LogicalOperator::Verify() { +void LogicalOperator::Verify(ClientContext &context) { #ifdef DEBUG // verify expressions for (idx_t expr_idx = 0; expr_idx < expressions.size(); expr_idx++) { @@ -177575,18 +192808,236 @@ void LogicalOperator::Verify() { } } D_ASSERT(!str.empty()); + + // verify that serialization + deserialization round-trips correctly + if (expressions[expr_idx]->HasParameter()) { + continue; + } + BufferedSerializer serializer; + try { + expressions[expr_idx]->Serialize(serializer); + } catch (NotImplementedException &ex) { + // ignore for now (FIXME) + return; + } + + auto data = serializer.GetData(); + auto deserializer = BufferedDeserializer(data.data.get(), data.size); + + PlanDeserializationState state(context); + auto deserialized_expression = Expression::Deserialize(deserializer, state); + // FIXME: expressions might not be equal yet because of statistics propagation + continue; + D_ASSERT(Expression::Equals(expressions[expr_idx].get(), deserialized_expression.get())); + D_ASSERT(expressions[expr_idx]->Hash() == deserialized_expression->Hash()); } D_ASSERT(!ToString().empty()); for (auto &child : children) { - child->Verify(); + child->Verify(context); } #endif } +void LogicalOperator::AddChild(unique_ptr child) { + D_ASSERT(child); + children.push_back(move(child)); +} + +idx_t LogicalOperator::EstimateCardinality(ClientContext &context) { + // simple estimator, just take the max of the children + if (has_estimated_cardinality) { + return estimated_cardinality; + } + idx_t max_cardinality = 0; + for (auto &child : children) { + max_cardinality = MaxValue(child->EstimateCardinality(context), max_cardinality); + } + has_estimated_cardinality = true; + return max_cardinality; +} + void LogicalOperator::Print() { Printer::Print(ToString()); } +void LogicalOperator::Serialize(Serializer &serializer) const { + FieldWriter writer(serializer); + writer.WriteField(type); + writer.WriteSerializableList(children); + + Serialize(writer); + writer.Finalize(); +} + +unique_ptr LogicalOperator::Deserialize(Deserializer &deserializer, PlanDeserializationState &gstate) { + unique_ptr result; + + FieldReader reader(deserializer); + auto type = reader.ReadRequired(); + auto children = reader.ReadRequiredSerializableList(gstate); + + LogicalDeserializationState state(gstate, type, children); + switch (type) { + case LogicalOperatorType::LOGICAL_PROJECTION: + result = LogicalProjection::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_FILTER: + result = LogicalFilter::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY: + result = LogicalAggregate::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_WINDOW: + result = LogicalWindow::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_UNNEST: + result = LogicalUnnest::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_LIMIT: + result = LogicalLimit::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_ORDER_BY: + result = LogicalOrder::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_TOP_N: + result = LogicalTopN::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_COPY_TO_FILE: + result = LogicalCopyToFile::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_DISTINCT: + result = LogicalDistinct::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_SAMPLE: + result = LogicalSample::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_LIMIT_PERCENT: + result = LogicalLimitPercent::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_GET: + result = LogicalGet::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_CHUNK_GET: + result = LogicalColumnDataGet::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_DELIM_GET: + result = LogicalDelimGet::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_EXPRESSION_GET: + result = LogicalExpressionGet::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_DUMMY_SCAN: + result = LogicalDummyScan::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_EMPTY_RESULT: + result = LogicalEmptyResult::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_CTE_REF: + result = LogicalCTERef::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_JOIN: + throw InternalException("LogicalJoin deserialize not supported"); + case LogicalOperatorType::LOGICAL_DELIM_JOIN: + result = LogicalDelimJoin::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_COMPARISON_JOIN: + result = LogicalComparisonJoin::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_ANY_JOIN: + result = LogicalAnyJoin::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_CROSS_PRODUCT: + result = LogicalCrossProduct::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_UNION: + result = LogicalSetOperation::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_EXCEPT: + result = LogicalSetOperation::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_INTERSECT: + result = LogicalSetOperation::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_RECURSIVE_CTE: + result = LogicalRecursiveCTE::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_INSERT: + result = LogicalInsert::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_DELETE: + result = LogicalDelete::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_UPDATE: + result = LogicalUpdate::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_ALTER: + result = LogicalSimple::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_CREATE_TABLE: + result = LogicalCreateTable::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_CREATE_INDEX: + result = LogicalCreateIndex::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_CREATE_SEQUENCE: + result = LogicalCreate::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_CREATE_VIEW: + result = LogicalCreate::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_CREATE_SCHEMA: + result = LogicalCreate::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_CREATE_MACRO: + result = LogicalCreate::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_DROP: + result = LogicalSimple::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_PRAGMA: + result = LogicalPragma::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_TRANSACTION: + result = LogicalSimple::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_CREATE_TYPE: + result = LogicalCreate::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_EXPLAIN: + result = LogicalExplain::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_SHOW: + result = LogicalShow::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_PREPARE: + result = LogicalPrepare::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_EXECUTE: + result = LogicalExecute::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_EXPORT: + result = LogicalExport::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_VACUUM: + result = LogicalSimple::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_SET: + result = LogicalSet::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_LOAD: + result = LogicalSimple::Deserialize(state, reader); + break; + case LogicalOperatorType::LOGICAL_INVALID: + /* no default here to trigger a warning if we forget to implement deserialize for a new operator */ + throw SerializationException("Invalid type for operator deserialization"); + } + + reader.Finalize(); + result->children = move(children); + + return result; +} + } // namespace duckdb @@ -177855,6 +193306,7 @@ unique_ptr LogicalOperatorVisitor::VisitReplace(BoundUnnestExpressio + namespace duckdb { LogicalAggregate::LogicalAggregate(idx_t group_index, idx_t aggregate_index, vector> select_list) @@ -177908,9 +193360,55 @@ string LogicalAggregate::ParamsToString() const { return result; } +void LogicalAggregate::Serialize(FieldWriter &writer) const { + writer.WriteSerializableList(expressions); + + writer.WriteField(group_index); + writer.WriteField(aggregate_index); + writer.WriteField(groupings_index); + writer.WriteSerializableList(groups); + writer.WriteField(grouping_sets.size()); + for (auto &entry : grouping_sets) { + writer.WriteList(entry); + } + writer.WriteField(grouping_functions.size()); + for (auto &entry : grouping_functions) { + writer.WriteList(entry); + } + + // TODO statistics +} + +unique_ptr LogicalAggregate::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto expressions = reader.ReadRequiredSerializableList(state.gstate); + + auto group_index = reader.ReadRequired(); + auto aggregate_index = reader.ReadRequired(); + auto groupings_index = reader.ReadRequired(); + auto groups = reader.ReadRequiredSerializableList(state.gstate); + auto grouping_sets_size = reader.ReadRequired(); + vector grouping_sets; + for (idx_t i = 0; i < grouping_sets_size; i++) { + grouping_sets.push_back(reader.ReadRequiredSet()); + } + vector> grouping_functions; + auto grouping_functions_size = reader.ReadRequired(); + for (idx_t i = 0; i < grouping_functions_size; i++) { + grouping_functions.push_back(reader.ReadRequiredList()); + } + auto result = make_unique(group_index, aggregate_index, move(expressions)); + result->groupings_index = groupings_index; + result->groups = move(groups); + result->grouping_functions = move(grouping_functions); + result->grouping_sets = move(grouping_sets); + + return move(result); +} + } // namespace duckdb + namespace duckdb { LogicalAnyJoin::LogicalAnyJoin(JoinType type) : LogicalJoin(type, LogicalOperatorType::LOGICAL_ANY_JOIN) { @@ -177920,11 +193418,65 @@ string LogicalAnyJoin::ParamsToString() const { return condition->ToString(); } +void LogicalAnyJoin::Serialize(FieldWriter &writer) const { + writer.WriteField(join_type); + writer.WriteOptional(condition); +} + +unique_ptr LogicalAnyJoin::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto join_type = reader.ReadRequired(); + auto condition = reader.ReadOptional(nullptr, state.gstate); + auto result = make_unique(join_type); + result->condition = move(condition); + return move(result); +} + +} // namespace duckdb + + + + +namespace duckdb { + +LogicalColumnDataGet::LogicalColumnDataGet(idx_t table_index, vector types, + unique_ptr collection) + : LogicalOperator(LogicalOperatorType::LOGICAL_CHUNK_GET), table_index(table_index), collection(move(collection)) { + D_ASSERT(types.size() > 0); + chunk_types = move(types); +} + +vector LogicalColumnDataGet::GetColumnBindings() { + return GenerateColumnBindings(table_index, chunk_types.size()); +} + +void LogicalColumnDataGet::Serialize(FieldWriter &writer) const { + writer.WriteField(table_index); + writer.WriteRegularSerializableList(chunk_types); + writer.WriteField(collection->ChunkCount()); + for (auto &chunk : collection->Chunks()) { + chunk.Serialize(writer.GetSerializer()); + } +} + +unique_ptr LogicalColumnDataGet::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto table_index = reader.ReadRequired(); + auto chunk_types = reader.ReadRequiredSerializableList(); + auto chunk_count = reader.ReadRequired(); + auto collection = make_unique(state.gstate.context, chunk_types); + for (idx_t i = 0; i < chunk_count; i++) { + DataChunk chunk; + chunk.Deserialize(reader.GetSource()); + collection->Append(chunk); + } + return make_unique(table_index, move(chunk_types), move(collection)); +} + } // namespace duckdb + namespace duckdb { LogicalComparisonJoin::LogicalComparisonJoin(JoinType join_type, LogicalOperatorType logical_type) @@ -177943,12 +193495,169 @@ string LogicalComparisonJoin::ParamsToString() const { return result; } +void LogicalComparisonJoin::Serialize(FieldWriter &writer) const { + LogicalJoin::Serialize(writer); + writer.WriteRegularSerializableList(conditions); + writer.WriteRegularSerializableList(delim_types); +} + +void LogicalComparisonJoin::Deserialize(LogicalComparisonJoin &comparison_join, LogicalDeserializationState &state, + FieldReader &reader) { + LogicalJoin::Deserialize(comparison_join, state, reader); + comparison_join.conditions = reader.ReadRequiredSerializableList(state.gstate); + comparison_join.delim_types = reader.ReadRequiredSerializableList(); +} + +unique_ptr LogicalComparisonJoin::Deserialize(LogicalDeserializationState &state, + FieldReader &reader) { + auto result = make_unique(JoinType::INVALID, state.type); + LogicalComparisonJoin::Deserialize(*result, state, reader); + return move(result); +} + +} // namespace duckdb + + + + + + +namespace duckdb { + +void LogicalCopyToFile::Serialize(FieldWriter &writer) const { + writer.WriteString(file_path); + writer.WriteField(use_tmp_file); + writer.WriteField(is_file_and_exists); + + D_ASSERT(!function.name.empty()); + writer.WriteString(function.name); + + writer.WriteField(bind_data != nullptr); + if (bind_data && !function.serialize) { + throw InvalidInputException("Can't serialize copy function %s", function.name); + } + + function.serialize(writer, *bind_data, function); +} + +unique_ptr LogicalCopyToFile::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto file_path = reader.ReadRequired(); + auto use_tmp_file = reader.ReadRequired(); + auto is_file_and_exists = reader.ReadRequired(); + + auto copy_func_name = reader.ReadRequired(); + + auto has_bind_data = reader.ReadRequired(); + + auto &context = state.gstate.context; + auto &catalog = Catalog::GetCatalog(context); + auto func_catalog = catalog.GetEntry(context, CatalogType::COPY_FUNCTION_ENTRY, DEFAULT_SCHEMA, copy_func_name); + if (!func_catalog || func_catalog->type != CatalogType::COPY_FUNCTION_ENTRY) { + throw InternalException("Cant find catalog entry for function %s", copy_func_name); + } + auto copy_func_catalog_entry = (CopyFunctionCatalogEntry *)func_catalog; + CopyFunction copy_func = copy_func_catalog_entry->function; + + unique_ptr bind_data; + if (has_bind_data) { + if (!copy_func.deserialize) { + throw SerializationException("Have bind info but no deserialization function for %s", copy_func.name); + } + bind_data = copy_func.deserialize(context, reader, copy_func); + } + + auto result = make_unique(copy_func, move(bind_data)); + result->file_path = file_path; + result->use_tmp_file = use_tmp_file; + result->is_file_and_exists = is_file_and_exists; + return move(result); +} + +} // namespace duckdb + + +namespace duckdb { + +void LogicalCreate::Serialize(FieldWriter &writer) const { + info->Serialize(writer.GetSerializer()); +} + +unique_ptr LogicalCreate::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto &context = state.gstate.context; + auto info = CreateInfo::Deserialize(reader.GetSource()); + + auto &catalog = Catalog::GetCatalog(context); + // TODO(stephwang): review if below is necessary or just not pass schema_catalog_entry + SchemaCatalogEntry *schema_catalog_entry = catalog.GetSchema(context, info->schema, true); + + return make_unique(state.type, move(info), schema_catalog_entry); +} + +} // namespace duckdb + + + + + +namespace duckdb { + +void LogicalCreateIndex::Serialize(FieldWriter &writer) const { + table.Serialize(writer.GetSerializer()); + writer.WriteList(column_ids); + writer.WriteSerializableList(unbound_expressions); + writer.WriteOptional(info); +} + +unique_ptr LogicalCreateIndex::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto &context = state.gstate.context; + auto catalog_info = TableCatalogEntry::Deserialize(reader.GetSource(), context); + auto &catalog = Catalog::GetCatalog(context); + TableCatalogEntry *table = catalog.GetEntry(context, catalog_info->schema, catalog_info->table); + + auto column_ids = reader.ReadRequiredList(); + + auto unbound_expressions = reader.ReadRequiredSerializableList(state.gstate); + + auto create_info = reader.ReadOptional(nullptr); + if (create_info->type != CatalogType::INDEX_ENTRY) { + throw InternalException("Unexpected type: '%s', expected '%s'", CatalogTypeToString(create_info->type), + CatalogTypeToString(CatalogType::INDEX_ENTRY)); + } + + CreateInfo *raw_create_info_ptr = create_info.release(); + CreateIndexInfo *raw_create_index_info_ptr = static_cast(raw_create_info_ptr); + unique_ptr uptr_create_index_info = unique_ptr {raw_create_index_info_ptr}; + + auto info = unique_ptr {static_cast(create_info.release())}; + return make_unique(*table, column_ids, move(unbound_expressions), move(info)); +} + } // namespace duckdb namespace duckdb { -LogicalCrossProduct::LogicalCrossProduct() : LogicalOperator(LogicalOperatorType::LOGICAL_CROSS_PRODUCT) { +void LogicalCreateTable::Serialize(FieldWriter &writer) const { + writer.WriteSerializable(*info); +} + +unique_ptr LogicalCreateTable::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto info = reader.ReadRequiredSerializable(state.gstate); + auto schema = info->schema; + return make_unique(schema, move(info)); +} + +} // namespace duckdb + + +namespace duckdb { + +LogicalCrossProduct::LogicalCrossProduct(unique_ptr left, unique_ptr right) + : LogicalOperator(LogicalOperatorType::LOGICAL_CROSS_PRODUCT) { + D_ASSERT(left); + D_ASSERT(right); + children.push_back(move(left)); + children.push_back(move(right)); } vector LogicalCrossProduct::GetColumnBindings() { @@ -177963,10 +193672,122 @@ void LogicalCrossProduct::ResolveTypes() { types.insert(types.end(), children[1]->types.begin(), children[1]->types.end()); } +unique_ptr LogicalCrossProduct::Create(unique_ptr left, + unique_ptr right) { + if (left->type == LogicalOperatorType::LOGICAL_DUMMY_SCAN) { + return right; + } + if (right->type == LogicalOperatorType::LOGICAL_DUMMY_SCAN) { + return left; + } + return make_unique(move(left), move(right)); +} + +void LogicalCrossProduct::Serialize(FieldWriter &writer) const { +} + +unique_ptr LogicalCrossProduct::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + // TODO(stephwang): review if unique_ptr plan is needed + auto result = unique_ptr(new LogicalCrossProduct()); + return move(result); +} + +} // namespace duckdb + + + +namespace duckdb { + +void LogicalCTERef::Serialize(FieldWriter &writer) const { + writer.WriteField(table_index); + writer.WriteField(cte_index); + writer.WriteRegularSerializableList(chunk_types); + writer.WriteList(bound_columns); +} + +unique_ptr LogicalCTERef::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto table_index = reader.ReadRequired(); + auto cte_index = reader.ReadRequired(); + auto chunk_types = reader.ReadRequiredSerializableList(); + auto bound_columns = reader.ReadRequiredList(); + return make_unique(table_index, cte_index, chunk_types, bound_columns); +} + } // namespace duckdb +namespace duckdb { + +void LogicalDelete::Serialize(FieldWriter &writer) const { + table->Serialize(writer.GetSerializer()); + writer.WriteField(table_index); + writer.WriteField(return_chunk); +} + +unique_ptr LogicalDelete::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto &context = state.gstate.context; + auto info = TableCatalogEntry::Deserialize(reader.GetSource(), context); + + auto &catalog = Catalog::GetCatalog(context); + + TableCatalogEntry *table_catalog_entry = catalog.GetEntry(context, info->schema, info->table); + + auto result = make_unique(table_catalog_entry); + result->table_index = reader.ReadRequired(); + result->return_chunk = reader.ReadRequired(); + return move(result); +} + +} // namespace duckdb + + + +namespace duckdb { + +void LogicalDelimGet::Serialize(FieldWriter &writer) const { + writer.WriteField(table_index); + writer.WriteRegularSerializableList(chunk_types); +} + +unique_ptr LogicalDelimGet::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto table_index = reader.ReadRequired(); + auto chunk_types = reader.ReadRequiredSerializableList(); + return make_unique(table_index, chunk_types); +} + +} // namespace duckdb + + + +namespace duckdb { + +LogicalDelimJoin::LogicalDelimJoin(JoinType type) + : LogicalComparisonJoin(type, LogicalOperatorType::LOGICAL_DELIM_JOIN) { +} + +void LogicalDelimJoin::Serialize(FieldWriter &writer) const { + LogicalComparisonJoin::Serialize(writer); + if (type == LogicalOperatorType::LOGICAL_COMPARISON_JOIN) { + D_ASSERT(duplicate_eliminated_columns.empty()); + // if the delim join has no delim columns anymore it is turned into a regular comparison join + return; + } + writer.WriteSerializableList(duplicate_eliminated_columns); +} + +unique_ptr LogicalDelimJoin::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto result = make_unique(JoinType::INVALID); + LogicalComparisonJoin::Deserialize(*result, state, reader); + result->duplicate_eliminated_columns = reader.ReadRequiredSerializableList(state.gstate); + return move(result); +} + +} // namespace duckdb + + + + namespace duckdb { string LogicalDistinct::ParamsToString() const { @@ -177978,10 +193799,34 @@ string LogicalDistinct::ParamsToString() const { return result; } +void LogicalDistinct::Serialize(FieldWriter &writer) const { + writer.WriteSerializableList(distinct_targets); +} + +unique_ptr LogicalDistinct::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto distinct_targets = reader.ReadRequiredSerializableList(state.gstate); + return make_unique(move(distinct_targets)); +} } // namespace duckdb + +namespace duckdb { + +void LogicalDummyScan::Serialize(FieldWriter &writer) const { + writer.WriteField(table_index); +} + +unique_ptr LogicalDummyScan::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto table_index = reader.ReadRequired(); + return make_unique(table_index); +} + +} // namespace duckdb + + + namespace duckdb { LogicalEmptyResult::LogicalEmptyResult(unique_ptr op) @@ -177993,6 +193838,99 @@ LogicalEmptyResult::LogicalEmptyResult(unique_ptr op) this->return_types = op->types; } +LogicalEmptyResult::LogicalEmptyResult() : LogicalOperator(LogicalOperatorType::LOGICAL_EMPTY_RESULT) { +} + +void LogicalEmptyResult::Serialize(FieldWriter &writer) const { + writer.WriteRegularSerializableList(return_types); + writer.WriteList(bindings); +} + +unique_ptr LogicalEmptyResult::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto return_types = reader.ReadRequiredSerializableList(); + auto bindings = reader.ReadRequiredList(); + auto result = unique_ptr(new LogicalEmptyResult()); + result->return_types = return_types; + result->bindings = bindings; + return move(result); +} + +} // namespace duckdb + + +namespace duckdb { + +void LogicalExecute::Serialize(FieldWriter &writer) const { + throw NotImplementedException(LogicalOperatorToString(type)); +} + +unique_ptr LogicalExecute::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + throw NotImplementedException(LogicalOperatorToString(state.type)); +} +} // namespace duckdb + + + +namespace duckdb { + +void LogicalExplain::Serialize(FieldWriter &writer) const { + writer.WriteField(explain_type); + writer.WriteString(physical_plan); + writer.WriteString(logical_plan_unopt); + writer.WriteString(logical_plan_opt); +} + +unique_ptr LogicalExplain::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto explain_type = reader.ReadRequired(); + // TODO(stephwang) review if unique_ptr plan is needed + auto result = unique_ptr(new LogicalExplain(explain_type)); + result->physical_plan = reader.ReadRequired(); + result->logical_plan_unopt = reader.ReadRequired(); + result->logical_plan_opt = reader.ReadRequired(); + return move(result); +} +} // namespace duckdb + + +namespace duckdb { + +void LogicalExport::Serialize(FieldWriter &writer) const { + throw NotImplementedException(LogicalOperatorToString(type)); +} + +unique_ptr LogicalExport::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + throw NotImplementedException(LogicalOperatorToString(state.type)); +} + +} // namespace duckdb + + + +namespace duckdb { + +void LogicalExpressionGet::Serialize(FieldWriter &writer) const { + writer.WriteField(table_index); + writer.WriteRegularSerializableList(expr_types); + + writer.WriteField(expressions.size()); + for (auto &entry : expressions) { + writer.WriteSerializableList(entry); + } +} + +unique_ptr LogicalExpressionGet::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto table_index = reader.ReadRequired(); + auto expr_types = reader.ReadRequiredSerializableList(); + + auto expressions_size = reader.ReadRequired(); + vector>> expressions; + for (idx_t i = 0; i < expressions_size; i++) { + expressions.push_back(reader.ReadRequiredSerializableList(state.gstate)); + } + + return make_unique(table_index, expr_types, move(expressions)); +} + } // namespace duckdb @@ -178039,6 +193977,20 @@ bool LogicalFilter::SplitPredicates(vector> &expressions) return found_conjunction; } +void LogicalFilter::Serialize(FieldWriter &writer) const { + writer.WriteSerializableList(expressions); + writer.WriteList(projection_map); +} + +unique_ptr LogicalFilter::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto expressions = reader.ReadRequiredSerializableList(state.gstate); + auto projection_map = reader.ReadRequiredList(); + auto result = make_unique(); + result->expressions = move(expressions); + result->projection_map = move(projection_map); + return move(result); +} + } // namespace duckdb @@ -178048,6 +194000,9 @@ bool LogicalFilter::SplitPredicates(vector> &expressions) + + + namespace duckdb { LogicalGet::LogicalGet(idx_t table_index, TableFunction function, unique_ptr bind_data, @@ -178114,12 +194069,149 @@ idx_t LogicalGet::EstimateCardinality(ClientContext &context) { return 1; } +void LogicalGet::Serialize(FieldWriter &writer) const { + writer.WriteField(table_index); + writer.WriteRegularSerializableList(returned_types); + writer.WriteList(names); + writer.WriteList(column_ids); + writer.WriteSerializable(table_filters); + + FunctionSerializer::SerializeBase(writer, function, bind_data.get()); + if (!function.serialize) { + D_ASSERT(!function.deserialize); + // no serialize method: serialize input values and named_parameters for rebinding purposes + writer.WriteRegularSerializableList(parameters); + writer.WriteField(named_parameters.size()); + for (auto &pair : named_parameters) { + writer.WriteString(pair.first); + writer.WriteSerializable(pair.second); + } + writer.WriteRegularSerializableList(input_table_types); + writer.WriteList(input_table_names); + } +} + +unique_ptr LogicalGet::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto table_index = reader.ReadRequired(); + auto returned_types = reader.ReadRequiredSerializableList(); + auto returned_names = reader.ReadRequiredList(); + auto column_ids = reader.ReadRequiredList(); + auto table_filters = reader.ReadRequiredSerializable(); + + unique_ptr bind_data; + bool has_deserialize; + auto function = FunctionSerializer::DeserializeBaseInternal( + reader, state.gstate, CatalogType::TABLE_FUNCTION_ENTRY, bind_data, has_deserialize); + + vector parameters; + named_parameter_map_t named_parameters; + vector input_table_types; + vector input_table_names; + if (!has_deserialize) { + D_ASSERT(!bind_data); + parameters = reader.ReadRequiredSerializableList(); + + auto named_parameters_size = reader.ReadRequired(); + for (idx_t i = 0; i < named_parameters_size; i++) { + auto first = reader.ReadRequired(); + auto second = reader.ReadRequiredSerializable(); + auto pair = make_pair(first, second); + named_parameters.insert(pair); + } + + input_table_types = reader.ReadRequiredSerializableList(); + input_table_names = reader.ReadRequiredList(); + TableFunctionBindInput input(parameters, named_parameters, input_table_types, input_table_names, + function.function_info.get()); + + vector bind_return_types; + vector bind_names; + bind_data = function.bind(state.gstate.context, input, bind_return_types, bind_names); + if (returned_types != bind_return_types) { + throw SerializationException( + "Table function deserialization failure - bind returned different return types than were serialized"); + } + // names can actually be different because of aliases - only the sizes cannot be different + if (returned_names.size() != bind_names.size()) { + throw SerializationException( + "Table function deserialization failure - bind returned different returned names than were serialized"); + } + } + + auto result = make_unique(table_index, function, move(bind_data), returned_types, returned_names); + result->column_ids = move(column_ids); + result->table_filters = move(*table_filters); + result->parameters = move(parameters); + result->named_parameters = move(named_parameters); + result->input_table_types = input_table_types; + result->input_table_names = input_table_names; + return move(result); +} + +} // namespace duckdb + + + + + +namespace duckdb { + +void LogicalInsert::Serialize(FieldWriter &writer) const { + writer.WriteField(insert_values.size()); + for (auto &entry : insert_values) { + writer.WriteSerializableList(entry); + } + + writer.WriteList(column_index_map); + writer.WriteRegularSerializableList(expected_types); + table->Serialize(writer.GetSerializer()); + writer.WriteField(table_index); + writer.WriteField(return_chunk); + writer.WriteSerializableList(bound_defaults); +} + +unique_ptr LogicalInsert::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto &context = state.gstate.context; + auto insert_values_size = reader.ReadRequired(); + vector>> insert_values; + for (idx_t i = 0; i < insert_values_size; ++i) { + insert_values.push_back(reader.ReadRequiredSerializableList(state.gstate)); + } + + auto column_index_map = reader.ReadRequiredList(); + auto expected_types = reader.ReadRequiredSerializableList(); + auto info = TableCatalogEntry::Deserialize(reader.GetSource(), context); + auto table_index = reader.ReadRequired(); + auto return_chunk = reader.ReadRequired(); + auto bound_defaults = reader.ReadRequiredSerializableList(state.gstate); + + auto &catalog = Catalog::GetCatalog(context); + + TableCatalogEntry *table_catalog_entry = catalog.GetEntry(context, info->schema, info->table); + + if (!table_catalog_entry) { + throw InternalException("Cant find catalog entry for table %s", info->table); + } + + auto result = make_unique(table_catalog_entry); + result->type = state.type; + result->table = table_catalog_entry; + result->table_index = table_index; + result->return_chunk = return_chunk; + result->insert_values = move(insert_values); + result->column_index_map = column_index_map; + result->expected_types = expected_types; + result->bound_defaults = move(bound_defaults); + return move(result); +} + } // namespace duckdb + namespace duckdb { LogicalJoin::LogicalJoin(JoinType join_type, LogicalOperatorType logical_type) @@ -178175,9 +194267,26 @@ void LogicalJoin::GetExpressionBindings(Expression &expr, unordered_set & ExpressionIterator::EnumerateChildren(expr, [&](Expression &child) { GetExpressionBindings(child, bindings); }); } +void LogicalJoin::Serialize(FieldWriter &writer) const { + writer.WriteField(join_type); + writer.WriteField(mark_index); + writer.WriteList(left_projection_map); + writer.WriteList(right_projection_map); + // writer.WriteSerializableList(join_stats); +} + +void LogicalJoin::Deserialize(LogicalJoin &join, LogicalDeserializationState &state, FieldReader &reader) { + join.join_type = reader.ReadRequired(); + join.mark_index = reader.ReadRequired(); + join.left_projection_map = reader.ReadRequiredList(); + join.right_projection_map = reader.ReadRequiredList(); + // join.join_stats = reader.ReadRequiredSerializableList(reader.GetSource()); +} + } // namespace duckdb + namespace duckdb { LogicalLimit::LogicalLimit(int64_t limit_val, int64_t offset_val, unique_ptr limit, @@ -178202,9 +194311,85 @@ void LogicalLimit::ResolveTypes() { types = children[0]->types; } +void LogicalLimit::Serialize(FieldWriter &writer) const { + writer.WriteField(limit_val); + writer.WriteField(offset_val); + writer.WriteOptional(limit); + writer.WriteOptional(offset); +} + +unique_ptr LogicalLimit::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto limit_val = reader.ReadRequired(); + auto offset_val = reader.ReadRequired(); + auto limit = reader.ReadOptional(nullptr, state.gstate); + auto offset = reader.ReadOptional(nullptr, state.gstate); + return make_unique(limit_val, offset_val, move(limit), move(offset)); +} } // namespace duckdb + +namespace duckdb { + +void LogicalLimitPercent::Serialize(FieldWriter &writer) const { + writer.WriteField(limit_percent); + writer.WriteField(offset_val); + writer.WriteOptional(limit); + writer.WriteOptional(offset); +} + +unique_ptr LogicalLimitPercent::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto limit_percent = reader.ReadRequired(); + auto offset_val = reader.ReadRequired(); + auto limit = reader.ReadOptional(nullptr, state.gstate); + auto offset = reader.ReadOptional(nullptr, state.gstate); + return make_unique(limit_percent, offset_val, move(limit), move(offset)); +} +} // namespace duckdb + + + +namespace duckdb { + +void LogicalOrder::Serialize(FieldWriter &writer) const { + writer.WriteRegularSerializableList(orders); +} + +unique_ptr LogicalOrder::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto orders = reader.ReadRequiredSerializableList(state.gstate); + return make_unique(move(orders)); +} + +} // namespace duckdb + + +namespace duckdb { + +void LogicalPragma::Serialize(FieldWriter &writer) const { + throw NotImplementedException(LogicalOperatorToString(type)); +} + +unique_ptr LogicalPragma::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + throw NotImplementedException(LogicalOperatorToString(state.type)); +} + +} // namespace duckdb + + +namespace duckdb { + +void LogicalPrepare::Serialize(FieldWriter &writer) const { + throw NotImplementedException(LogicalOperatorToString(type)); +} + +unique_ptr LogicalPrepare::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + throw NotImplementedException(LogicalOperatorToString(state.type)); +} + +} // namespace duckdb + + + namespace duckdb { LogicalProjection::LogicalProjection(idx_t table_index, vector> select_list) @@ -178221,9 +194406,41 @@ void LogicalProjection::ResolveTypes() { } } +void LogicalProjection::Serialize(FieldWriter &writer) const { + writer.WriteField(table_index); + writer.WriteSerializableList(expressions); +} + +unique_ptr LogicalProjection::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto table_index = reader.ReadRequired(); + auto expressions = reader.ReadRequiredSerializableList(state.gstate); + return make_unique(table_index, move(expressions)); +} + } // namespace duckdb + +namespace duckdb { + +void LogicalRecursiveCTE::Serialize(FieldWriter &writer) const { + writer.WriteField(table_index); + writer.WriteField(column_count); + writer.WriteField(union_all); +} + +unique_ptr LogicalRecursiveCTE::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto table_index = reader.ReadRequired(); + auto column_count = reader.ReadRequired(); + auto union_all = reader.ReadRequired(); + // TODO(stephwang): review if unique_ptr plan is needed + return unique_ptr(new LogicalRecursiveCTE(table_index, column_count, union_all, state.type)); +} + +} // namespace duckdb + + + namespace duckdb { LogicalSample::LogicalSample(unique_ptr sample_options_p, unique_ptr child) @@ -178252,9 +194469,108 @@ void LogicalSample::ResolveTypes() { types = children[0]->types; } +void LogicalSample::Serialize(FieldWriter &writer) const { + sample_options->Serialize(writer.GetSerializer()); +} + +unique_ptr LogicalSample::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto sample_options = SampleOptions::Deserialize(reader.GetSource()); + // TODO(stephwang): review how to pass child LogicalOperator + auto result = make_unique(move(sample_options), nullptr); + return move(result); +} +} // namespace duckdb + + + +namespace duckdb { + +void LogicalSet::Serialize(FieldWriter &writer) const { + writer.WriteString(name); + value.Serialize(writer.GetSerializer()); + writer.WriteField(scope); +} + +unique_ptr LogicalSet::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto name = reader.ReadRequired(); + auto value = Value::Deserialize(reader.GetSource()); + auto scope = reader.ReadRequired(); + return make_unique(name, value, scope); +} + +} // namespace duckdb + + + +namespace duckdb { + +void LogicalSetOperation::Serialize(FieldWriter &writer) const { + writer.WriteField(table_index); + writer.WriteField(column_count); +} + +unique_ptr LogicalSetOperation::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto table_index = reader.ReadRequired(); + auto column_count = reader.ReadRequired(); + // TODO(stephwang): review if unique_ptr plan is needed + return unique_ptr(new LogicalSetOperation(table_index, column_count, state.type)); +} } // namespace duckdb + +namespace duckdb { + +void LogicalShow::Serialize(FieldWriter &writer) const { + writer.WriteRegularSerializableList(types_select); + writer.WriteList(aliases); +} + +unique_ptr LogicalShow::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto types_select = reader.ReadRequiredSerializableList(); + auto aliases = reader.ReadRequiredList(); + + // TODO(stephwang): review if we need to pass unique_ptr plan + auto result = unique_ptr(new LogicalShow()); + result->types_select = types_select; + result->aliases = aliases; + return move(result); +} +} // namespace duckdb + + +namespace duckdb { + +void LogicalSimple::Serialize(FieldWriter &writer) const { + throw NotImplementedException(LogicalOperatorToString(type)); +} + +unique_ptr LogicalSimple::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + throw NotImplementedException(LogicalOperatorToString(state.type)); +} + +} // namespace duckdb + + + +namespace duckdb { + +void LogicalTopN::Serialize(FieldWriter &writer) const { + writer.WriteRegularSerializableList(orders); + writer.WriteField(offset); + writer.WriteField(limit); +} + +unique_ptr LogicalTopN::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto orders = reader.ReadRequiredSerializableList(state.gstate); + auto offset = reader.ReadRequired(); + auto limit = reader.ReadRequired(); + return make_unique(move(orders), limit, offset); +} +} // namespace duckdb + + + namespace duckdb { vector LogicalUnnest::GetColumnBindings() { @@ -178272,9 +194588,59 @@ void LogicalUnnest::ResolveTypes() { } } +void LogicalUnnest::Serialize(FieldWriter &writer) const { + writer.WriteField(unnest_index); + writer.WriteSerializableList(expressions); +} + +unique_ptr LogicalUnnest::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto unnest_index = reader.ReadRequired(); + auto expressions = reader.ReadRequiredSerializableList(state.gstate); + auto result = make_unique(unnest_index); + result->expressions = move(expressions); + return move(result); +} } // namespace duckdb + + + +namespace duckdb { + +void LogicalUpdate::Serialize(FieldWriter &writer) const { + table->Serialize(writer.GetSerializer()); + writer.WriteField(table_index); + writer.WriteField(return_chunk); + writer.WriteList(columns); + writer.WriteSerializableList(bound_defaults); + writer.WriteField(update_is_del_and_insert); +} + +unique_ptr LogicalUpdate::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto &context = state.gstate.context; + auto info = TableCatalogEntry::Deserialize(reader.GetSource(), context); + auto &catalog = Catalog::GetCatalog(context); + + TableCatalogEntry *table_catalog_entry = catalog.GetEntry(context, info->schema, info->table); + + if (!table_catalog_entry) { + throw InternalException("Cant find catalog entry for table %s", info->table); + } + + auto result = make_unique(table_catalog_entry); + result->table_index = reader.ReadRequired(); + result->return_chunk = reader.ReadRequired(); + result->columns = reader.ReadRequiredList(); + result->bound_defaults = reader.ReadRequiredSerializableList(state.gstate); + result->update_is_del_and_insert = reader.ReadRequired(); + return move(result); +} + +} // namespace duckdb + + + namespace duckdb { vector LogicalWindow::GetColumnBindings() { @@ -178292,12 +194658,91 @@ void LogicalWindow::ResolveTypes() { } } +void LogicalWindow::Serialize(FieldWriter &writer) const { + writer.WriteField(window_index); + writer.WriteSerializableList(expressions); +} + +unique_ptr LogicalWindow::Deserialize(LogicalDeserializationState &state, FieldReader &reader) { + auto window_index = reader.ReadRequired(); + auto result = make_unique(window_index); + result->expressions = reader.ReadRequiredSerializableList(state.gstate); + return move(result); +} + } // namespace duckdb +namespace duckdb { +void BoundCreateTableInfo::Serialize(Serializer &serializer) const { + D_ASSERT(schema); + schema->Serialize(serializer); + serializer.WriteOptional(base); + + // TODO[YLM]: Review if we want/need to serialize more of the fields. + //! The map of column names -> column index, used during binding + // case_insensitive_map_t name_map; + + //! Column dependency manager of the table + // ColumnDependencyManager column_dependency_manager; + + serializer.WriteList(constraints); + serializer.WriteList(bound_constraints); + serializer.WriteList(bound_defaults); + + //! Dependents of the table (in e.g. default values) + // unordered_set dependencies; + + //! The existing table data on disk (if any) + // unique_ptr data; + + //! CREATE TABLE from QUERY + serializer.WriteOptional(query); + + //! Indexes created by this table + // vector indexes; +} + +unique_ptr BoundCreateTableInfo::Deserialize(Deserializer &source, + PlanDeserializationState &state) { + auto create_info = SchemaCatalogEntry::Deserialize(source); + auto schema_name = create_info->schema; + auto result = make_unique(move(create_info)); + auto &context = state.context; + result->schema = Catalog::GetCatalog(context).GetSchema(context, schema_name); + result->base = source.ReadOptional(); + + source.ReadList(result->constraints); + source.ReadList(result->bound_constraints); + source.ReadList(result->bound_defaults, state); + + result->query = source.ReadOptional(state); + return result; +} +} // namespace duckdb + + + +namespace duckdb { + +PlanDeserializationState::PlanDeserializationState(ClientContext &context) : context(context) { +} +PlanDeserializationState::~PlanDeserializationState() { +} + +LogicalDeserializationState::LogicalDeserializationState(PlanDeserializationState &gstate, LogicalOperatorType type, + vector> &children) + : gstate(gstate), type(type), children(children) { +} + +ExpressionDeserializationState::ExpressionDeserializationState(PlanDeserializationState &gstate, ExpressionType type) + : gstate(gstate), type(type) { +} + +} // namespace duckdb @@ -178316,45 +194761,63 @@ namespace duckdb { Planner::Planner(ClientContext &context) : binder(Binder::CreateBinder(context)), context(context) { } +static void CheckTreeDepth(const LogicalOperator &op, idx_t max_depth, idx_t depth = 0) { + if (depth >= max_depth) { + throw ParserException("Maximum tree depth of %lld exceeded in logical planner", max_depth); + } + for (auto &child : op.children) { + CheckTreeDepth(*child, max_depth, depth + 1); + } +} + void Planner::CreatePlan(SQLStatement &statement) { auto &profiler = QueryProfiler::Get(context); auto parameter_count = statement.n_param; - vector bound_parameters; + BoundParameterMap bound_parameters(parameter_data); // first bind the tables and columns to the catalog - profiler.StartPhase("binder"); - binder->parameters = &bound_parameters; - binder->parameter_types = ¶meter_types; - auto bound_statement = binder->Bind(statement); - profiler.EndPhase(); + bool parameters_resolved = true; + try { + profiler.StartPhase("binder"); + binder->parameters = &bound_parameters; + auto bound_statement = binder->Bind(statement); + profiler.EndPhase(); + this->names = bound_statement.names; + this->types = bound_statement.types; + this->plan = move(bound_statement.plan); + + auto max_tree_depth = ClientConfig::GetConfig(context).max_expression_depth; + CheckTreeDepth(*plan, max_tree_depth); + } catch (const ParameterNotResolvedException &ex) { + // parameter types could not be resolved + this->names = {"unknown"}; + this->types = {LogicalTypeId::UNKNOWN}; + this->plan = nullptr; + parameters_resolved = false; + } catch (const Exception &ex) { + throw; + } catch (std::exception &ex) { + throw; + } this->properties = binder->properties; this->properties.parameter_count = parameter_count; - this->names = bound_statement.names; - this->types = bound_statement.types; - this->plan = move(bound_statement.plan); - properties.bound_all_parameters = true; + properties.bound_all_parameters = parameters_resolved; + + Planner::VerifyPlan(context, plan, &bound_parameters.parameters); // set up a map of parameter number -> value entries - for (auto &expr : bound_parameters) { + for (auto &kv : bound_parameters.parameters) { + auto parameter_index = kv.first; + auto ¶meter_data = kv.second; // check if the type of the parameter could be resolved - if (expr->return_type.id() == LogicalTypeId::INVALID || expr->return_type.id() == LogicalTypeId::UNKNOWN) { + if (!parameter_data->return_type.IsValid()) { properties.bound_all_parameters = false; continue; } - auto value = make_unique(expr->return_type); - expr->value = value.get(); - // check if the parameter number has been used before - auto entry = value_map.find(expr->parameter_nr); - if (entry == value_map.end()) { - // not used before, create vector - value_map[expr->parameter_nr] = vector>(); - } else if (entry->second.back()->type() != value->type()) { - // used before, but types are inconsistent - throw BinderException("Inconsistent types found for parameter with index %llu", expr->parameter_nr); - } - value_map[expr->parameter_nr].push_back(move(value)); + parameter_data->value = Value(parameter_data->return_type); + value_map[parameter_index] = parameter_data; } } @@ -178373,91 +194836,6 @@ shared_ptr Planner::PrepareSQLStatement(unique_ptr statement) { - auto &stmt = (ExecuteStatement &)*statement; - auto parameter_count = stmt.n_param; - - // bind the prepared statement - auto &client_data = ClientData::Get(context); - - auto entry = client_data.prepared_statements.find(stmt.name); - if (entry == client_data.prepared_statements.end()) { - throw BinderException("Prepared statement \"%s\" does not exist", stmt.name); - } - - // check if we need to rebind the prepared statement - // this happens if the catalog changes, since in this case e.g. tables we relied on may have been deleted - auto prepared = entry->second; - auto &catalog = Catalog::GetCatalog(context); - bool rebound = false; - - // bind any supplied parameters - vector bind_values; - for (idx_t i = 0; i < stmt.values.size(); i++) { - ConstantBinder cbinder(*binder, context, "EXECUTE statement"); - auto bound_expr = cbinder.Bind(stmt.values[i]); - - Value value = ExpressionExecutor::EvaluateScalar(*bound_expr); - bind_values.push_back(move(value)); - } - bool all_bound = prepared->properties.bound_all_parameters; - if (catalog.GetCatalogVersion() != entry->second->catalog_version || !all_bound) { - // catalog was modified or statement does not have clear types: rebind the statement before running the execute - for (auto &value : bind_values) { - parameter_types.push_back(value.type()); - } - prepared = PrepareSQLStatement(entry->second->unbound_statement->Copy()); - if (all_bound && prepared->types != entry->second->types) { - throw BinderException("Rebinding statement \"%s\" after catalog change resulted in change of types", - stmt.name); - } - D_ASSERT(prepared->properties.bound_all_parameters); - rebound = true; - } - // copy the properties of the prepared statement into the planner - this->properties = prepared->properties; - this->properties.parameter_count = parameter_count; - this->names = prepared->names; - this->types = prepared->types; - - // add casts to the prepared statement parameters as required - for (idx_t i = 0; i < bind_values.size(); i++) { - if (prepared->value_map.count(i + 1) == 0) { - continue; - } - bind_values[i] = bind_values[i].CastAs(prepared->GetType(i + 1)); - } - - prepared->Bind(move(bind_values)); - if (rebound) { - auto execute_plan = make_unique(move(prepared)); - execute_plan->children.push_back(move(plan)); - this->plan = move(execute_plan); - return; - } - - this->plan = make_unique(move(prepared)); -} - -void Planner::PlanPrepare(unique_ptr statement) { - auto &stmt = (PrepareStatement &)*statement; - auto prepared_data = PrepareSQLStatement(move(stmt.statement)); - - auto prepare = make_unique(stmt.name, move(prepared_data), move(plan)); - // we can prepare in read-only mode: prepared statements are not written to the catalog - properties.read_only = true; - // we can always prepare, even if the transaction has been invalidated - // this is required because most clients ALWAYS invoke prepared statements - properties.requires_valid_transaction = false; - properties.allow_stream_result = false; - properties.bound_all_parameters = true; - properties.parameter_count = 0; - properties.return_type = StatementReturnType::NOTHING; - this->names = {"Success"}; - this->types = {LogicalType::BOOLEAN}; - this->plan = move(prepare); -} - void Planner::CreatePlan(unique_ptr statement) { D_ASSERT(statement); switch (statement->type) { @@ -178479,19 +194857,79 @@ void Planner::CreatePlan(unique_ptr statement) { case StatementType::SHOW_STATEMENT: case StatementType::SET_STATEMENT: case StatementType::LOAD_STATEMENT: - CreatePlan(*statement); - break; - case StatementType::EXECUTE_STATEMENT: - PlanExecute(move(statement)); - break; + case StatementType::EXTENSION_STATEMENT: case StatementType::PREPARE_STATEMENT: - PlanPrepare(move(statement)); + case StatementType::EXECUTE_STATEMENT: + case StatementType::LOGICAL_PLAN_STATEMENT: + CreatePlan(*statement); break; default: throw NotImplementedException("Cannot plan statement of type %s!", StatementTypeToString(statement->type)); } } +static bool OperatorSupportsSerialization(LogicalOperator &op) { + switch (op.type) { + case LogicalOperatorType::LOGICAL_INSERT: + case LogicalOperatorType::LOGICAL_UPDATE: + case LogicalOperatorType::LOGICAL_DELETE: + case LogicalOperatorType::LOGICAL_PREPARE: + case LogicalOperatorType::LOGICAL_EXECUTE: + case LogicalOperatorType::LOGICAL_ALTER: + case LogicalOperatorType::LOGICAL_CREATE_TABLE: + case LogicalOperatorType::LOGICAL_CREATE_INDEX: + case LogicalOperatorType::LOGICAL_CREATE_SEQUENCE: + case LogicalOperatorType::LOGICAL_CREATE_VIEW: + case LogicalOperatorType::LOGICAL_CREATE_SCHEMA: + case LogicalOperatorType::LOGICAL_CREATE_MACRO: + case LogicalOperatorType::LOGICAL_DROP: + case LogicalOperatorType::LOGICAL_PRAGMA: + case LogicalOperatorType::LOGICAL_TRANSACTION: + case LogicalOperatorType::LOGICAL_CREATE_TYPE: + case LogicalOperatorType::LOGICAL_EXPLAIN: + case LogicalOperatorType::LOGICAL_COPY_TO_FILE: + case LogicalOperatorType::LOGICAL_LOAD: + case LogicalOperatorType::LOGICAL_VACUUM: + // unsupported (for now) + return false; + default: + break; + } + for (auto &child : op.children) { + if (!OperatorSupportsSerialization(*child)) { + return false; + } + } + return true; +} + +void Planner::VerifyPlan(ClientContext &context, unique_ptr &op, bound_parameter_map_t *map) { + if (!op || !ClientConfig::GetConfig(context).verify_serializer) { + return; + } + //! SELECT only for now + if (!OperatorSupportsSerialization(*op)) { + return; + } + + BufferedSerializer serializer; + try { + op->Serialize(serializer); + } catch (NotImplementedException &ex) { + // ignore for now (FIXME) + return; + } + auto data = serializer.GetData(); + auto deserializer = BufferedDeserializer(data.data.get(), data.size); + + PlanDeserializationState state(context); + auto new_plan = LogicalOperator::Deserialize(deserializer, state); + if (map) { + *map = move(state.parameter_data); + } + op = move(new_plan); +} + } // namespace duckdb @@ -178519,14 +194957,13 @@ void PragmaHandler::HandlePragmaStatementsInternal(vectortype == StatementType::PRAGMA_STATEMENT) { // PRAGMA statement: check if we need to replace it by a new set of statements PragmaHandler handler(context); - auto new_query = handler.HandlePragma(statements[i].get()); //*((PragmaStatement &)*statements[i]).info + auto new_query = handler.HandlePragma(statements[i].get()); if (!new_query.empty()) { // this PRAGMA statement gets replaced by a new query string // push the new query string through the parser again and add it to the transformer Parser parser(context.GetParserOptions()); parser.ParseQuery(new_query); // insert the new statements and remove the old statement - // FIXME: off by one here maybe? for (idx_t j = 0; j < parser.statements.size(); j++) { new_statements.push_back(move(parser.statements[j])); } @@ -178563,7 +195000,7 @@ string PragmaHandler::HandlePragma(SQLStatement *statement) { // PragmaInfo &inf if (bound_idx == DConstants::INVALID_INDEX) { throw BinderException(error); } - auto &bound_function = entry->functions[bound_idx]; + auto bound_function = entry->functions.GetFunctionByOffset(bound_idx); if (bound_function.query) { QueryErrorContext error_context(statement, statement->stmt_location); Binder::BindNamedParameters(bound_function.named_parameters, info.named_parameters, error_context, @@ -178582,6 +195019,9 @@ string PragmaHandler::HandlePragma(SQLStatement *statement) { // PragmaInfo &inf + + + //===----------------------------------------------------------------------===// // DuckDB // @@ -178675,14 +195115,11 @@ class RewriteCountAggregates : public LogicalOperatorVisitor { } // namespace duckdb - - - namespace duckdb { FlattenDependentJoins::FlattenDependentJoins(Binder &binder, const vector &correlated, - bool any_join) - : binder(binder), correlated_columns(correlated), any_join(any_join) { + bool perform_delim, bool any_join) + : binder(binder), correlated_columns(correlated), perform_delim(perform_delim), any_join(any_join) { for (idx_t i = 0; i < correlated_columns.size(); i++) { auto &col = correlated_columns[i]; correlated_map[col.binding] = i; @@ -178744,14 +195181,11 @@ unique_ptr FlattenDependentJoins::PushDownDependentJoinInternal if (!entry->second) { // we reached a node without correlated expressions // we can eliminate the dependent join now and create a simple cross product - auto cross_product = make_unique(); // now create the duplicate eliminated scan for this node auto delim_index = binder.GenerateTableIndex(); this->base_binding = ColumnBinding(delim_index, 0); auto delim_scan = make_unique(delim_index, delim_types); - cross_product->children.push_back(move(delim_scan)); - cross_product->children.push_back(move(plan)); - return move(cross_product); + return LogicalCrossProduct::Create(move(delim_scan), move(plan)); } switch (plan->type) { case LogicalOperatorType::LOGICAL_UNNEST: @@ -178782,8 +195216,9 @@ unique_ptr FlattenDependentJoins::PushDownDependentJoinInternal // now we add all the columns of the delim_scan to the projection list auto proj = (LogicalProjection *)plan.get(); for (idx_t i = 0; i < correlated_columns.size(); i++) { + auto &col = correlated_columns[i]; auto colref = make_unique( - correlated_columns[i].type, ColumnBinding(base_binding.table_index, base_binding.column_index + i)); + col.name, col.type, ColumnBinding(base_binding.table_index, base_binding.column_index + i)); plan->expressions.push_back(move(colref)); } @@ -178804,15 +195239,42 @@ unique_ptr FlattenDependentJoins::PushDownDependentJoinInternal RewriteCorrelatedExpressions rewriter(base_binding, correlated_map); rewriter.VisitOperator(*plan); // now we add all the columns of the delim_scan to the grouping operators AND the projection list - for (idx_t i = 0; i < correlated_columns.size(); i++) { + idx_t delim_table_index; + idx_t delim_column_offset; + idx_t delim_data_offset; + auto new_group_count = perform_delim ? correlated_columns.size() : 1; + for (idx_t i = 0; i < new_group_count; i++) { + auto &col = correlated_columns[i]; auto colref = make_unique( - correlated_columns[i].type, ColumnBinding(base_binding.table_index, base_binding.column_index + i)); + col.name, col.type, ColumnBinding(base_binding.table_index, base_binding.column_index + i)); for (auto &set : aggr.grouping_sets) { set.insert(aggr.groups.size()); } aggr.groups.push_back(move(colref)); } - if (aggr.groups.size() == correlated_columns.size()) { + if (!perform_delim) { + // if we are not performing the duplicate elimination, we have only added the row_id column to the grouping + // operators in this case, we push a FIRST aggregate for each of the remaining expressions + delim_table_index = aggr.aggregate_index; + delim_column_offset = aggr.expressions.size(); + delim_data_offset = aggr.groups.size(); + for (idx_t i = 0; i < correlated_columns.size(); i++) { + auto &col = correlated_columns[i]; + auto first_aggregate = FirstFun::GetFunction(col.type); + auto colref = make_unique( + col.name, col.type, ColumnBinding(base_binding.table_index, base_binding.column_index + i)); + vector> aggr_children; + aggr_children.push_back(move(colref)); + auto first_fun = make_unique(move(first_aggregate), move(aggr_children), + nullptr, nullptr, false); + aggr.expressions.push_back(move(first_fun)); + } + } else { + delim_table_index = aggr.group_index; + delim_column_offset = aggr.groups.size() - correlated_columns.size(); + delim_data_offset = aggr.groups.size(); + } + if (aggr.groups.size() == new_group_count) { // we have to perform a LEFT OUTER JOIN between the result of this aggregate and the delim scan // FIXME: this does not always have to be a LEFT OUTER JOIN, depending on whether aggr.expressions return // NULL or a value @@ -178828,13 +195290,12 @@ unique_ptr FlattenDependentJoins::PushDownDependentJoinInternal auto delim_scan = make_unique(left_index, delim_types); join->children.push_back(move(delim_scan)); join->children.push_back(move(plan)); - for (idx_t i = 0; i < correlated_columns.size(); i++) { + for (idx_t i = 0; i < new_group_count; i++) { + auto &col = correlated_columns[i]; JoinCondition cond; - cond.left = - make_unique(correlated_columns[i].type, ColumnBinding(left_index, i)); + cond.left = make_unique(col.name, col.type, ColumnBinding(left_index, i)); cond.right = make_unique( - correlated_columns[i].type, - ColumnBinding(aggr.group_index, (aggr.groups.size() - correlated_columns.size()) + i)); + correlated_columns[i].type, ColumnBinding(delim_table_index, delim_column_offset + i)); cond.comparison = ExpressionType::COMPARE_NOT_DISTINCT_FROM; join->conditions.push_back(move(cond)); } @@ -178850,16 +195311,15 @@ unique_ptr FlattenDependentJoins::PushDownDependentJoinInternal } } // now we update the delim_index - base_binding.table_index = left_index; this->delim_offset = base_binding.column_index = 0; this->data_offset = 0; return move(join); } else { // update the delim_index - base_binding.table_index = aggr.group_index; - this->delim_offset = base_binding.column_index = aggr.groups.size() - correlated_columns.size(); - this->data_offset = aggr.groups.size(); + base_binding.table_index = delim_table_index; + this->delim_offset = base_binding.column_index = delim_column_offset; + this->data_offset = delim_data_offset; return plan; } } @@ -178994,22 +195454,78 @@ unique_ptr FlattenDependentJoins::PushDownDependentJoinInternal } case LogicalOperatorType::LOGICAL_LIMIT: { auto &limit = (LogicalLimit &)*plan; - if (limit.offset_val > 0) { - throw ParserException("OFFSET not supported in correlated subquery"); - } - if (limit.limit) { - throw ParserException("Non-constant limit not supported in correlated subquery"); - } - plan->children[0] = PushDownDependentJoinInternal(move(plan->children[0]), parent_propagate_null_values); - if (limit.limit_val == 0) { - // limit = 0 means we return zero columns here - return plan; + if (limit.limit || limit.offset) { + throw ParserException("Non-constant limit or offset not supported in correlated subquery"); + } + auto rownum_alias = "limit_rownum"; + unique_ptr child; + unique_ptr order_by; + + // check if the direct child of this LIMIT node is an ORDER BY node, if so, keep it separate + // this is done for an optimization to avoid having to compute the total order + if (plan->children[0]->type == LogicalOperatorType::LOGICAL_ORDER_BY) { + order_by = unique_ptr_cast(move(plan->children[0])); + child = PushDownDependentJoinInternal(move(order_by->children[0]), parent_propagate_null_values); } else { - // limit > 0 does nothing - return move(plan->children[0]); + child = PushDownDependentJoinInternal(move(plan->children[0]), parent_propagate_null_values); + } + auto child_column_count = child->GetColumnBindings().size(); + // we push a row_number() OVER (PARTITION BY [correlated columns]) + auto window_index = binder.GenerateTableIndex(); + auto window = make_unique(window_index); + auto row_number = make_unique(ExpressionType::WINDOW_ROW_NUMBER, LogicalType::BIGINT, + nullptr, nullptr); + auto partition_count = perform_delim ? correlated_columns.size() : 1; + for (idx_t i = 0; i < partition_count; i++) { + auto &col = correlated_columns[i]; + auto colref = make_unique( + col.name, col.type, ColumnBinding(base_binding.table_index, base_binding.column_index + i)); + row_number->partitions.push_back(move(colref)); + } + if (order_by) { + // optimization: if there is an ORDER BY node followed by a LIMIT + // rather than computing the entire order, we push the ORDER BY expressions into the row_num computation + // this way, the order only needs to be computed per partition + row_number->orders = move(order_by->orders); + } + row_number->start = WindowBoundary::UNBOUNDED_PRECEDING; + row_number->end = WindowBoundary::CURRENT_ROW_ROWS; + window->expressions.push_back(move(row_number)); + window->children.push_back(move(child)); + + // add a filter based on the row_number + // the filter we add is "row_number > offset AND row_number <= offset + limit" + auto filter = make_unique(); + unique_ptr condition; + auto row_num_ref = + make_unique(rownum_alias, LogicalType::BIGINT, ColumnBinding(window_index, 0)); + + int64_t upper_bound_limit = NumericLimits::Maximum(); + TryAddOperator::Operation(limit.offset_val, limit.limit_val, upper_bound_limit); + auto upper_bound = make_unique(Value::BIGINT(upper_bound_limit)); + condition = make_unique(ExpressionType::COMPARE_LESSTHANOREQUALTO, + row_num_ref->Copy(), move(upper_bound)); + // we only need to add "row_number >= offset + 1" if offset is bigger than 0 + if (limit.offset_val > 0) { + auto lower_bound = make_unique(Value::BIGINT(limit.offset_val)); + auto lower_comp = make_unique(ExpressionType::COMPARE_GREATERTHAN, + row_num_ref->Copy(), move(lower_bound)); + auto conj = make_unique(ExpressionType::CONJUNCTION_AND, move(lower_comp), + move(condition)); + condition = move(conj); + } + filter->expressions.push_back(move(condition)); + filter->children.push_back(move(window)); + // we prune away the row_number after the filter clause using the projection map + for (idx_t i = 0; i < child_column_count; i++) { + filter->projection_map.push_back(i); } + return move(filter); } case LogicalOperatorType::LOGICAL_LIMIT_PERCENT: { + // NOTE: limit percent could be supported in a manner similar to the LIMIT above + // but instead of filtering by an exact number of rows, the limit should be expressed as + // COUNT computed over the partition multiplied by the percentage throw ParserException("Limit percent operator not supported in correlated subquery"); } case LogicalOperatorType::LOGICAL_WINDOW: { @@ -179068,7 +195584,8 @@ unique_ptr FlattenDependentJoins::PushDownDependentJoinInternal return plan; } case LogicalOperatorType::LOGICAL_ORDER_BY: - throw ParserException("ORDER BY not supported in correlated subquery"); + plan->children[0] = PushDownDependentJoin(move(plan->children[0])); + return plan; default: throw InternalException("Logical operator type \"%s\" for dependent join", LogicalOperatorToString(plan->type)); } @@ -179419,30 +195936,30 @@ string TableBinding::ColumnNotFoundError(const string &column_name) const { return StringUtil::Format("Table \"%s\" does not have a column named \"%s\"", alias, column_name); } -MacroBinding::MacroBinding(vector types_p, vector names_p, string macro_name_p) - : Binding(BindingType::MACRO, MacroBinding::MACRO_NAME, move(types_p), move(names_p), -1), - macro_name(move(macro_name_p)) { +DummyBinding::DummyBinding(vector types_p, vector names_p, string dummy_name_p) + : Binding(BindingType::DUMMY, DummyBinding::DUMMY_NAME + dummy_name_p, move(types_p), move(names_p), -1), + dummy_name(move(dummy_name_p)) { } -BindResult MacroBinding::Bind(ColumnRefExpression &colref, idx_t depth) { +BindResult DummyBinding::Bind(ColumnRefExpression &colref, idx_t depth) { column_t column_index; if (!TryGetBindingIndex(colref.GetColumnName(), column_index)) { - throw InternalException("Column %s not found in macro", colref.GetColumnName()); + throw InternalException("Column %s not found in bindings", colref.GetColumnName()); } ColumnBinding binding; binding.table_index = index; binding.column_index = column_index; - // we are binding a parameter to create the macro, no arguments are supplied + // we are binding a parameter to create the dummy binding, no arguments are supplied return BindResult(make_unique(colref.GetName(), types[column_index], binding, depth)); } -unique_ptr MacroBinding::ParamToArg(ColumnRefExpression &colref) { +unique_ptr DummyBinding::ParamToArg(ColumnRefExpression &colref) { column_t column_index; if (!TryGetBindingIndex(colref.GetColumnName(), column_index)) { throw InternalException("Column %s not found in macro", colref.GetColumnName()); } - auto arg = arguments[column_index]->Copy(); + auto arg = (*arguments)[column_index]->Copy(); arg->alias = colref.alias; return arg; } @@ -179451,6 +195968,9 @@ unique_ptr MacroBinding::ParamToArg(ColumnRefExpression &colre + + + namespace duckdb { void TableFilterSet::PushFilter(idx_t column_index, unique_ptr filter) { @@ -179472,6 +195992,139 @@ void TableFilterSet::PushFilter(idx_t column_index, unique_ptr filt } } +//! Serializes a LogicalType to a stand-alone binary blob +void TableFilterSet::Serialize(Serializer &serializer) const { + serializer.Write(filters.size()); + for (auto &entry : filters) { + serializer.Write(entry.first); + entry.second->Serialize(serializer); + } +} + +//! Deserializes a blob back into an LogicalType +unique_ptr TableFilterSet::Deserialize(Deserializer &source) { + auto len = source.Read(); + auto res = make_unique(); + for (idx_t i = 0; i < len; i++) { + auto key = source.Read(); + auto value = TableFilter::Deserialize(source); + res->filters[key] = move(value); + } + return res; +} + +//! Serializes a LogicalType to a stand-alone binary blob +void TableFilter::Serialize(Serializer &serializer) const { + FieldWriter writer(serializer); + writer.WriteField(filter_type); + Serialize(writer); + writer.Finalize(); +} + +//! Deserializes a blob back into an LogicalType +unique_ptr TableFilter::Deserialize(Deserializer &source) { + unique_ptr result; + + FieldReader reader(source); + auto filter_type = reader.ReadRequired(); + switch (filter_type) { + case TableFilterType::CONSTANT_COMPARISON: + result = ConstantFilter::Deserialize(reader); + break; + case TableFilterType::CONJUNCTION_AND: + result = ConjunctionAndFilter::Deserialize(reader); + break; + case TableFilterType::CONJUNCTION_OR: + result = ConjunctionOrFilter::Deserialize(reader); + break; + case TableFilterType::IS_NOT_NULL: + result = IsNotNullFilter::Deserialize(reader); + break; + case TableFilterType::IS_NULL: + result = IsNullFilter::Deserialize(reader); + break; + default: + throw NotImplementedException("Unsupported table filter type for deserialization"); + } + reader.Finalize(); + return result; +} + +} // namespace duckdb + + + +namespace duckdb { + +ArenaChunk::ArenaChunk(Allocator &allocator, idx_t size) : current_position(0), maximum_size(size), prev(nullptr) { + D_ASSERT(size > 0); + data = allocator.Allocate(size); +} +ArenaChunk::~ArenaChunk() { + if (next) { + auto current_next = move(next); + while (current_next) { + current_next = move(current_next->next); + } + } +} + +ArenaAllocator::ArenaAllocator(Allocator &allocator, idx_t initial_capacity) : allocator(allocator) { + head = nullptr; + tail = nullptr; + current_capacity = initial_capacity; +} + +ArenaAllocator::~ArenaAllocator() { +} + +data_ptr_t ArenaAllocator::Allocate(idx_t len) { + D_ASSERT(!head || head->current_position <= head->maximum_size); + if (!head || head->current_position + len > head->maximum_size) { + do { + current_capacity *= 2; + } while (current_capacity < len); + auto new_chunk = make_unique(allocator, current_capacity); + if (head) { + head->prev = new_chunk.get(); + new_chunk->next = move(head); + } else { + tail = new_chunk.get(); + } + head = move(new_chunk); + } + D_ASSERT(head->current_position + len <= head->maximum_size); + auto result = head->data.get() + head->current_position; + head->current_position += len; + return result; +} + +void ArenaAllocator::Destroy() { + head = nullptr; + tail = nullptr; + current_capacity = ARENA_ALLOCATOR_INITIAL_CAPACITY; +} + +void ArenaAllocator::Move(ArenaAllocator &other) { + D_ASSERT(!other.head); + other.tail = tail; + other.head = move(head); + other.current_capacity = current_capacity; + Destroy(); +} + +ArenaChunk *ArenaAllocator::GetHead() { + return head.get(); +} + +ArenaChunk *ArenaAllocator::GetTail() { + return tail; +} + +bool ArenaAllocator::IsEmpty() { + return head == nullptr; +} + } // namespace duckdb @@ -179493,18 +196146,61 @@ Block::Block(FileBuffer &source, block_id_t id) : FileBuffer(source, FileBufferT namespace duckdb { +BufferHandle::BufferHandle() : handle(nullptr), node(nullptr) { +} + BufferHandle::BufferHandle(shared_ptr handle, FileBuffer *node) : handle(move(handle)), node(node) { } +BufferHandle::BufferHandle(BufferHandle &&other) noexcept { + std::swap(node, other.node); + std::swap(handle, other.handle); +} + +BufferHandle &BufferHandle::operator=(BufferHandle &&other) noexcept { + std::swap(node, other.node); + std::swap(handle, other.handle); + return *this; +} + BufferHandle::~BufferHandle() { - auto &buffer_manager = BufferManager::GetBufferManager(handle->db); - buffer_manager.Unpin(handle); + Destroy(); +} + +bool BufferHandle::IsValid() const { + return node != nullptr; +} + +data_ptr_t BufferHandle::Ptr() const { + D_ASSERT(IsValid()); + return node->buffer; } data_ptr_t BufferHandle::Ptr() { + D_ASSERT(IsValid()); return node->buffer; } +block_id_t BufferHandle::GetBlockId() const { + D_ASSERT(handle); + return handle->BlockId(); +} + +void BufferHandle::Destroy() { + if (!handle || !IsValid()) { + return; + } + auto &buffer_manager = BufferManager::GetBufferManager(handle->db); + buffer_manager.Unpin(handle); + handle.reset(); + node = nullptr; +} + +FileBuffer &BufferHandle::GetFileBuffer() { + D_ASSERT(node); + return *node; +} + } // namespace duckdb @@ -179520,11 +196216,18 @@ ManagedBuffer::ManagedBuffer(DatabaseInstance &db, idx_t size, bool can_destroy, D_ASSERT(size >= Storage::BLOCK_SIZE); } +ManagedBuffer::ManagedBuffer(DatabaseInstance &db, FileBuffer &source, bool can_destroy, block_id_t id) + : FileBuffer(source, FileBufferType::MANAGED_BUFFER), db(db), can_destroy(can_destroy), id(id) { + D_ASSERT(id >= MAXIMUM_BLOCK); + D_ASSERT(size >= Storage::BLOCK_SIZE); +} + } // namespace duckdb + //===----------------------------------------------------------------------===// // DuckDB // @@ -179600,10 +196303,19 @@ class ConcurrentQueue { #endif + namespace duckdb { +struct BufferAllocatorData : PrivateAllocatorData { + explicit BufferAllocatorData(BufferManager &manager) : manager(manager) { + } + + BufferManager &manager; +}; + BlockHandle::BlockHandle(DatabaseInstance &db, block_id_t block_id_p) - : db(db), readers(0), block_id(block_id_p), buffer(nullptr), eviction_timestamp(0), can_destroy(false) { + : db(db), readers(0), block_id(block_id_p), buffer(nullptr), eviction_timestamp(0), can_destroy(false), + unswizzled(nullptr) { eviction_timestamp = 0; state = BlockState::BLOCK_UNLOADED; memory_usage = Storage::BLOCK_ALLOC_SIZE; @@ -179611,7 +196323,7 @@ BlockHandle::BlockHandle(DatabaseInstance &db, block_id_t block_id_p) BlockHandle::BlockHandle(DatabaseInstance &db, block_id_t block_id_p, unique_ptr buffer_p, bool can_destroy_p, idx_t block_size) - : db(db), readers(0), block_id(block_id_p), eviction_timestamp(0), can_destroy(can_destroy_p) { + : db(db), readers(0), block_id(block_id_p), eviction_timestamp(0), can_destroy(can_destroy_p), unswizzled(nullptr) { D_ASSERT(block_size >= Storage::BLOCK_SIZE); buffer = move(buffer_p); state = BlockState::BLOCK_LOADED; @@ -179620,6 +196332,8 @@ BlockHandle::BlockHandle(DatabaseInstance &db, block_id_t block_id_p, unique_ptr BlockHandle::~BlockHandle() { auto &buffer_manager = BufferManager::GetBufferManager(db); + // being destroyed, so any unswizzled pointers are just binary junk now. + unswizzled = nullptr; // no references remain to this block: erase if (state == BlockState::BLOCK_LOADED) { // the block is still loaded in memory: erase it @@ -179629,36 +196343,75 @@ BlockHandle::~BlockHandle() { buffer_manager.UnregisterBlock(block_id, can_destroy); } -unique_ptr BlockHandle::Load(shared_ptr &handle) { +unique_ptr AllocateBlock(Allocator &allocator, unique_ptr reusable_buffer, block_id_t block_id) { + if (reusable_buffer) { + // re-usable buffer: re-use it + if (reusable_buffer->type == FileBufferType::BLOCK) { + // we can reuse the buffer entirely + auto &block = (Block &)*reusable_buffer; + block.id = block_id; + return unique_ptr_cast(move(reusable_buffer)); + } + auto block = make_unique(*reusable_buffer, block_id); + reusable_buffer.reset(); + return block; + } else { + // no re-usable buffer: allocate a new block + return make_unique(allocator, block_id); + } +} + +unique_ptr AllocateManagedBuffer(DatabaseInstance &db, unique_ptr reusable_buffer, + idx_t size, bool can_destroy, block_id_t id) { + if (reusable_buffer) { + // re-usable buffer: re-use it + if (reusable_buffer->type == FileBufferType::MANAGED_BUFFER) { + // we can reuse the buffer entirely + auto &managed = (ManagedBuffer &)*reusable_buffer; + managed.id = id; + managed.can_destroy = can_destroy; + return unique_ptr_cast(move(reusable_buffer)); + } + auto buffer = make_unique(db, *reusable_buffer, can_destroy, id); + reusable_buffer.reset(); + return buffer; + } else { + // no re-usable buffer: allocate a new buffer + return make_unique(db, size, can_destroy, id); + } +} + +BufferHandle BlockHandle::Load(shared_ptr &handle, unique_ptr reusable_buffer) { if (handle->state == BlockState::BLOCK_LOADED) { // already loaded D_ASSERT(handle->buffer); - return make_unique(handle, handle->buffer.get()); + return BufferHandle(handle, handle->buffer.get()); } auto &buffer_manager = BufferManager::GetBufferManager(handle->db); auto &block_manager = BlockManager::GetBlockManager(handle->db); if (handle->block_id < MAXIMUM_BLOCK) { - auto block = make_unique(Allocator::Get(handle->db), handle->block_id); + auto block = AllocateBlock(Allocator::Get(handle->db), move(reusable_buffer), handle->block_id); block_manager.Read(*block); handle->buffer = move(block); } else { if (handle->can_destroy) { - return nullptr; + return BufferHandle(); } else { - handle->buffer = buffer_manager.ReadTemporaryBuffer(handle->block_id); + handle->buffer = buffer_manager.ReadTemporaryBuffer(handle->block_id, move(reusable_buffer)); } } handle->state = BlockState::BLOCK_LOADED; - return make_unique(handle, handle->buffer.get()); + return BufferHandle(handle, handle->buffer.get()); } -void BlockHandle::Unload() { +unique_ptr BlockHandle::UnloadAndTakeBlock() { auto &buffer_manager = BufferManager::GetBufferManager(db); if (state == BlockState::BLOCK_UNLOADED) { // already unloaded: nothing to do - return; + return nullptr; } + D_ASSERT(!unswizzled); D_ASSERT(CanUnload()); D_ASSERT(memory_usage >= Storage::BLOCK_ALLOC_SIZE); @@ -179666,9 +196419,14 @@ void BlockHandle::Unload() { // temporary block that cannot be destroyed: write to temporary file buffer_manager.WriteTemporaryBuffer((ManagedBuffer &)*buffer); } - buffer.reset(); buffer_manager.current_memory -= memory_usage; state = BlockState::BLOCK_UNLOADED; + return move(buffer); +} + +void BlockHandle::Unload() { + auto block = UnloadAndTakeBlock(); + block.reset(); } bool BlockHandle::CanUnload() { @@ -179691,6 +196449,8 @@ bool BlockHandle::CanUnload() { } struct BufferEvictionNode { + BufferEvictionNode() { + } BufferEvictionNode(weak_ptr handle_p, idx_t timestamp_p) : handle(move(handle_p)), timestamp(timestamp_p) { D_ASSERT(!handle.expired()); @@ -179722,30 +196482,25 @@ struct BufferEvictionNode { } }; -typedef duckdb_moodycamel::ConcurrentQueue> eviction_queue_t; +typedef duckdb_moodycamel::ConcurrentQueue eviction_queue_t; struct EvictionQueue { eviction_queue_t q; }; +class TemporaryFileManager; + class TemporaryDirectoryHandle { public: - TemporaryDirectoryHandle(DatabaseInstance &db, string path_p) : db(db), temp_directory(move(path_p)) { - auto &fs = FileSystem::GetFileSystem(db); - if (!temp_directory.empty()) { - fs.CreateDirectory(temp_directory); - } - } - ~TemporaryDirectoryHandle() { - auto &fs = FileSystem::GetFileSystem(db); - if (!temp_directory.empty()) { - fs.RemoveDirectory(temp_directory); - } - } + TemporaryDirectoryHandle(DatabaseInstance &db, string path_p); + ~TemporaryDirectoryHandle(); + + TemporaryFileManager &GetTempFile(); private: DatabaseInstance &db; string temp_directory; + unique_ptr temp_file; }; void BufferManager::SetTemporaryDirectory(string new_dir) { @@ -179757,7 +196512,9 @@ void BufferManager::SetTemporaryDirectory(string new_dir) { BufferManager::BufferManager(DatabaseInstance &db, string tmp, idx_t maximum_memory) : db(db), current_memory(0), maximum_memory(maximum_memory), temp_directory(move(tmp)), - queue(make_unique()), temporary_id(MAXIMUM_BLOCK) { + queue(make_unique()), temporary_id(MAXIMUM_BLOCK), + buffer_allocator(BufferAllocatorAllocate, BufferAllocatorFree, BufferAllocatorRealloc, + make_unique(*this)) { } BufferManager::~BufferManager() { @@ -179795,19 +196552,15 @@ shared_ptr BufferManager::ConvertToPersistent(BlockManager &block_m D_ASSERT(new_block->state == BlockState::BLOCK_UNLOADED); D_ASSERT(new_block->readers == 0); -#ifdef DEBUG - lock_guard b_lock(blocks_lock); -#endif - // move the data from the old block into data for the new block new_block->state = BlockState::BLOCK_LOADED; new_block->buffer = make_unique(*old_block->buffer, block_id); // clear the old buffer and unload it - old_handle.reset(); old_block->buffer.reset(); old_block->state = BlockState::BLOCK_UNLOADED; old_block->memory_usage = 0; + old_handle.Destroy(); old_block.reset(); // persist the new block to disk @@ -179821,19 +196574,20 @@ shared_ptr BufferManager::ConvertToPersistent(BlockManager &block_m shared_ptr BufferManager::RegisterMemory(idx_t block_size, bool can_destroy) { auto alloc_size = block_size + Storage::BLOCK_HEADER_SIZE; // first evict blocks until we have enough memory to store this buffer - if (!EvictBlocks(alloc_size, maximum_memory)) { - throw OutOfMemoryException("could not allocate block of %lld bytes%s", alloc_size, InMemoryWarning()); + unique_ptr reusable_buffer; + if (!EvictBlocks(alloc_size, maximum_memory, &reusable_buffer)) { + throw OutOfMemoryException("could not allocate block of %lld bytes (%lld/%lld used) %s", alloc_size, + GetUsedMemory(), GetMaxMemory(), InMemoryWarning()); } - // allocate the buffer auto temp_id = ++temporary_id; - auto buffer = make_unique(db, block_size, can_destroy, temp_id); + auto buffer = AllocateManagedBuffer(db, move(reusable_buffer), block_size, can_destroy, temp_id); // create a new block pointer for this block return make_shared(db, temp_id, move(buffer), can_destroy, block_size); } -unique_ptr BufferManager::Allocate(idx_t block_size) { +BufferHandle BufferManager::Allocate(idx_t block_size) { auto block = RegisterMemory(block_size, true); return Pin(block); } @@ -179862,7 +196616,7 @@ void BufferManager::ReAllocate(shared_ptr &handle, idx_t block_size handle->memory_usage = alloc_size; } -unique_ptr BufferManager::Pin(shared_ptr &handle) { +BufferHandle BufferManager::Pin(shared_ptr &handle) { idx_t required_memory; { // lock the block @@ -179876,7 +196630,8 @@ unique_ptr BufferManager::Pin(shared_ptr &handle) { required_memory = handle->memory_usage; } // evict blocks until we have space for the current block - if (!EvictBlocks(required_memory, maximum_memory)) { + unique_ptr reusable_buffer; + if (!EvictBlocks(required_memory, maximum_memory, &reusable_buffer)) { throw OutOfMemoryException("failed to pin block of size %lld%s", required_memory, InMemoryWarning()); } // lock the handle again and repeat the check (in case anybody loaded in the mean time) @@ -179891,14 +196646,14 @@ unique_ptr BufferManager::Pin(shared_ptr &handle) { // now we can actually load the current block D_ASSERT(handle->readers == 0); handle->readers = 1; - return handle->Load(handle); + return handle->Load(handle, move(reusable_buffer)); } void BufferManager::AddToEvictionQueue(shared_ptr &handle) { D_ASSERT(handle->readers == 0); handle->eviction_timestamp++; PurgeQueue(); - queue->q.enqueue(make_unique(weak_ptr(handle), handle->eviction_timestamp)); + queue->q.enqueue(BufferEvictionNode(weak_ptr(handle), handle->eviction_timestamp)); } void BufferManager::Unpin(shared_ptr &handle) { @@ -179910,10 +196665,10 @@ void BufferManager::Unpin(shared_ptr &handle) { } } -bool BufferManager::EvictBlocks(idx_t extra_memory, idx_t memory_limit) { +bool BufferManager::EvictBlocks(idx_t extra_memory, idx_t memory_limit, unique_ptr *buffer) { PurgeQueue(); - unique_ptr node; + BufferEvictionNode node; current_memory += extra_memory; while (current_memory > memory_limit) { // get a block to unpin from the queue @@ -179922,30 +196677,36 @@ bool BufferManager::EvictBlocks(idx_t extra_memory, idx_t memory_limit) { return false; } // get a reference to the underlying block pointer - auto handle = node->TryGetBlockHandle(); + auto handle = node.TryGetBlockHandle(); if (!handle) { continue; } // we might be able to free this block: grab the mutex and check if we can free it lock_guard lock(handle->lock); - if (!node->CanUnload(*handle)) { + if (!node.CanUnload(*handle)) { // something changed in the mean-time, bail out continue; } // hooray, we can unload the block - // release the memory and mark the block as unloaded - handle->Unload(); + if (buffer && handle->buffer->AllocSize() == extra_memory) { + // we can actually re-use the memory directly! + *buffer = handle->UnloadAndTakeBlock(); + return true; + } else { + // release the memory and mark the block as unloaded + handle->Unload(); + } } return true; } void BufferManager::PurgeQueue() { - unique_ptr node; + BufferEvictionNode node; while (true) { if (!queue->q.try_dequeue(node)) { break; } - auto handle = node->TryGetBlockHandle(); + auto handle = node.TryGetBlockHandle(); if (!handle) { continue; } else { @@ -179989,6 +196750,323 @@ void BufferManager::SetLimit(idx_t limit) { } } +//===--------------------------------------------------------------------===// +// Temporary File Management +//===--------------------------------------------------------------------===// +unique_ptr ReadTemporaryBufferInternal(DatabaseInstance &db, FileHandle &handle, idx_t position, + idx_t size, block_id_t id, + unique_ptr reusable_buffer) { + auto buffer = AllocateManagedBuffer(db, move(reusable_buffer), size, false, id); + buffer->Read(handle, position); + return buffer; +} + +struct TemporaryFileIndex { + explicit TemporaryFileIndex(idx_t file_index = DConstants::INVALID_INDEX, + idx_t block_index = DConstants::INVALID_INDEX) + : file_index(file_index), block_index(block_index) { + } + + idx_t file_index; + idx_t block_index; + +public: + bool IsValid() { + return block_index != DConstants::INVALID_INDEX; + } +}; + +struct BlockIndexManager { + BlockIndexManager() : max_index(0) { + } + +public: + //! Obtains a new block index from the index manager + idx_t GetNewBlockIndex() { + auto index = GetNewBlockIndexInternal(); + indexes_in_use.insert(index); + return index; + } + + //! Removes an index from the block manager + //! Returns true if the max_index has been altered + bool RemoveIndex(idx_t index) { + // remove this block from the set of blocks + indexes_in_use.erase(index); + free_indexes.insert(index); + // check if we can truncate the file + + // get the max_index in use right now + auto max_index_in_use = indexes_in_use.empty() ? 0 : *indexes_in_use.rbegin(); + if (max_index_in_use < max_index) { + // max index in use is lower than the max_index + // reduce the max_index + max_index = max_index_in_use + 1; + // we can remove any free_indexes that are larger than the current max_index + while (!free_indexes.empty()) { + auto max_entry = *free_indexes.rbegin(); + if (max_entry < max_index) { + break; + } + free_indexes.erase(max_entry); + } + return true; + } + return false; + } + + idx_t GetMaxIndex() { + return max_index; + } + + bool HasFreeBlocks() { + return !free_indexes.empty(); + } + +private: + idx_t GetNewBlockIndexInternal() { + if (free_indexes.empty()) { + return max_index++; + } + auto entry = free_indexes.begin(); + auto index = *entry; + free_indexes.erase(entry); + return index; + } + + idx_t max_index; + set free_indexes; + set indexes_in_use; +}; + +class TemporaryFileHandle { + constexpr static idx_t MAX_ALLOWED_INDEX = 4000; + +public: + TemporaryFileHandle(DatabaseInstance &db, const string &temp_directory, idx_t index) + : db(db), file_index(index), path(FileSystem::GetFileSystem(db).JoinPath( + temp_directory, "duckdb_temp_storage-" + to_string(index) + ".tmp")) { + } + +public: + struct TemporaryFileLock { + explicit TemporaryFileLock(mutex &mutex) : lock(mutex) { + } + + lock_guard lock; + }; + +public: + TemporaryFileIndex TryGetBlockIndex() { + TemporaryFileLock lock(file_lock); + if (index_manager.GetMaxIndex() >= MAX_ALLOWED_INDEX && index_manager.HasFreeBlocks()) { + // file is at capacity + return TemporaryFileIndex(); + } + // open the file handle if it does not yet exist + CreateFileIfNotExists(lock); + // fetch a new block index to write to + auto block_index = index_manager.GetNewBlockIndex(); + return TemporaryFileIndex(file_index, block_index); + } + + void WriteTemporaryFile(ManagedBuffer &buffer, TemporaryFileIndex index) { + D_ASSERT(buffer.size == Storage::BLOCK_SIZE); + buffer.Write(*handle, GetPositionInFile(index.block_index)); + } + + unique_ptr ReadTemporaryBuffer(block_id_t id, idx_t block_index, + unique_ptr reusable_buffer) { + auto buffer = ReadTemporaryBufferInternal(db, *handle, GetPositionInFile(block_index), Storage::BLOCK_SIZE, id, + move(reusable_buffer)); + { + // remove the block (and potentially truncate the temp file) + TemporaryFileLock lock(file_lock); + D_ASSERT(handle); + RemoveTempBlockIndex(lock, block_index); + } + return move(buffer); + } + + bool DeleteIfEmpty() { + TemporaryFileLock lock(file_lock); + if (index_manager.GetMaxIndex() > 0) { + // there are still blocks in this file + return false; + } + // the file is empty: delete it + handle.reset(); + auto &fs = FileSystem::GetFileSystem(db); + fs.RemoveFile(path); + return true; + } + +private: + void CreateFileIfNotExists(TemporaryFileLock &) { + if (handle) { + return; + } + auto &fs = FileSystem::GetFileSystem(db); + handle = fs.OpenFile(path, FileFlags::FILE_FLAGS_READ | FileFlags::FILE_FLAGS_WRITE | + FileFlags::FILE_FLAGS_FILE_CREATE); + } + + void RemoveTempBlockIndex(TemporaryFileLock &, idx_t index) { + // remove the block index from the index manager + if (index_manager.RemoveIndex(index)) { + // the max_index that is currently in use has decreased + // as a result we can truncate the file + auto max_index = index_manager.GetMaxIndex(); + auto &fs = FileSystem::GetFileSystem(db); + fs.Truncate(*handle, GetPositionInFile(max_index + 1)); + } + } + + idx_t GetPositionInFile(idx_t index) { + return index * Storage::BLOCK_ALLOC_SIZE; + } + +private: + DatabaseInstance &db; + unique_ptr handle; + idx_t file_index; + string path; + mutex file_lock; + BlockIndexManager index_manager; +}; + +class TemporaryFileManager { +public: + TemporaryFileManager(DatabaseInstance &db, const string &temp_directory_p) + : db(db), temp_directory(temp_directory_p) { + } + +public: + struct TemporaryManagerLock { + explicit TemporaryManagerLock(mutex &mutex) : lock(mutex) { + } + + lock_guard lock; + }; + + void WriteTemporaryBuffer(ManagedBuffer &buffer) { + D_ASSERT(buffer.size == Storage::BLOCK_SIZE); + TemporaryFileIndex index; + TemporaryFileHandle *handle = nullptr; + + { + TemporaryManagerLock lock(manager_lock); + // first check if we can write to an open existing file + for (auto &entry : files) { + auto &temp_file = entry.second; + index = temp_file->TryGetBlockIndex(); + if (index.IsValid()) { + handle = entry.second.get(); + break; + } + } + if (!handle) { + // no existing handle to write to; we need to create & open a new file + auto new_file_index = index_manager.GetNewBlockIndex(); + auto new_file = make_unique(db, temp_directory, new_file_index); + handle = new_file.get(); + files[new_file_index] = move(new_file); + + index = handle->TryGetBlockIndex(); + } + D_ASSERT(used_blocks.find(buffer.id) == used_blocks.end()); + used_blocks[buffer.id] = index; + } + D_ASSERT(handle); + D_ASSERT(index.IsValid()); + handle->WriteTemporaryFile(buffer, index); + } + + bool HasTemporaryBuffer(block_id_t block_id) { + lock_guard lock(manager_lock); + return used_blocks.find(block_id) != used_blocks.end(); + } + + unique_ptr ReadTemporaryBuffer(block_id_t id, unique_ptr reusable_buffer) { + TemporaryFileIndex index; + TemporaryFileHandle *handle; + { + TemporaryManagerLock lock(manager_lock); + index = GetTempBlockIndex(lock, id); + handle = GetFileHandle(lock, index.file_index); + } + auto buffer = handle->ReadTemporaryBuffer(id, index.block_index, move(reusable_buffer)); + { + // remove the block (and potentially erase the temp file) + TemporaryManagerLock lock(manager_lock); + EraseUsedBlock(lock, id, handle, index.file_index); + } + return buffer; + } + + void DeleteTemporaryBuffer(block_id_t id) { + TemporaryManagerLock lock(manager_lock); + auto index = GetTempBlockIndex(lock, id); + auto handle = GetFileHandle(lock, index.file_index); + EraseUsedBlock(lock, id, handle, index.file_index); + } + +private: + void EraseUsedBlock(TemporaryManagerLock &lock, block_id_t id, TemporaryFileHandle *handle, idx_t file_index) { + used_blocks.erase(id); + if (handle->DeleteIfEmpty()) { + EraseFileHandle(lock, file_index); + } + } + + TemporaryFileHandle *GetFileHandle(TemporaryManagerLock &, idx_t index) { + return files[index].get(); + } + + TemporaryFileIndex GetTempBlockIndex(TemporaryManagerLock &, block_id_t id) { + D_ASSERT(used_blocks.find(id) != used_blocks.end()); + return used_blocks[id]; + } + + void EraseFileHandle(TemporaryManagerLock &, idx_t file_index) { + files.erase(file_index); + index_manager.RemoveIndex(file_index); + } + +private: + DatabaseInstance &db; + mutex manager_lock; + //! The temporary directory + string temp_directory; + //! The set of active temporary file handles + unordered_map> files; + //! map of block_id -> temporary file position + unordered_map used_blocks; + //! Manager of in-use temporary file indexes + BlockIndexManager index_manager; +}; + +TemporaryDirectoryHandle::TemporaryDirectoryHandle(DatabaseInstance &db, string path_p) + : db(db), temp_directory(move(path_p)), temp_file(make_unique(db, temp_directory)) { + auto &fs = FileSystem::GetFileSystem(db); + if (!temp_directory.empty()) { + fs.CreateDirectory(temp_directory); + } +} +TemporaryDirectoryHandle::~TemporaryDirectoryHandle() { + // first release any temporary files + temp_file.reset(); + // then delete the temporary file directory + auto &fs = FileSystem::GetFileSystem(db); + if (!temp_directory.empty()) { + fs.RemoveDirectory(temp_directory); + } +} + +TemporaryFileManager &TemporaryDirectoryHandle::GetTempFile() { + return *temp_file; +} + string BufferManager::GetTemporaryPath(block_id_t id) { auto &fs = FileSystem::GetFileSystem(db); return fs.JoinPath(temp_directory, to_string(id) + ".block"); @@ -180009,8 +197087,12 @@ void BufferManager::RequireTemporaryDirectory() { void BufferManager::WriteTemporaryBuffer(ManagedBuffer &buffer) { RequireTemporaryDirectory(); + if (buffer.size == Storage::BLOCK_SIZE) { + temp_directory_handle->GetTempFile().WriteTemporaryBuffer(buffer); + return; + } - D_ASSERT(buffer.size >= Storage::BLOCK_SIZE); + D_ASSERT(buffer.size > Storage::BLOCK_SIZE); // get the path to write to auto path = GetTemporaryPath(buffer.id); // create the file and write the size followed by the buffer contents @@ -180020,9 +197102,12 @@ void BufferManager::WriteTemporaryBuffer(ManagedBuffer &buffer) { buffer.Write(*handle, sizeof(idx_t)); } -unique_ptr BufferManager::ReadTemporaryBuffer(block_id_t id) { +unique_ptr BufferManager::ReadTemporaryBuffer(block_id_t id, unique_ptr reusable_buffer) { D_ASSERT(!temp_directory.empty()); D_ASSERT(temp_directory_handle.get()); + if (temp_directory_handle->GetTempFile().HasTemporaryBuffer(id)) { + return temp_directory_handle->GetTempFile().ReadTemporaryBuffer(id, move(reusable_buffer)); + } idx_t block_size; // open the temporary file and read the size auto path = GetTemporaryPath(id); @@ -180031,8 +197116,7 @@ unique_ptr BufferManager::ReadTemporaryBuffer(block_id_t id) { handle->Read(&block_size, sizeof(idx_t), 0); // now allocate a buffer of this size and read the data into that buffer - auto buffer = make_unique(db, block_size, false, id); - buffer->Read(*handle, sizeof(idx_t)); + auto buffer = ReadTemporaryBufferInternal(db, *handle, sizeof(idx_t), block_size, id, move(reusable_buffer)); handle.reset(); DeleteTemporaryFile(id); @@ -180040,7 +197124,20 @@ unique_ptr BufferManager::ReadTemporaryBuffer(block_id_t id) { } void BufferManager::DeleteTemporaryFile(block_id_t id) { - if (temp_directory.empty() || !temp_directory_handle) { + if (temp_directory.empty()) { + // no temporary directory specified: nothing to delete + return; + } + { + lock_guard temp_handle_guard(temp_handle_lock); + if (!temp_directory_handle) { + // temporary directory was not initialized yet: nothing to delete + return; + } + } + // check if we should delete the file from the shared pool of files, or from the general file system + if (temp_directory_handle->GetTempFile().HasTemporaryBuffer(id)) { + temp_directory_handle->GetTempFile().DeleteTemporaryBuffer(id); return; } auto &fs = FileSystem::GetFileSystem(db); @@ -180060,6 +197157,40 @@ string BufferManager::InMemoryWarning() { "\nOr set PRAGMA temp_directory='/path/to/tmp.tmp'"; } +//===--------------------------------------------------------------------===// +// Buffer Allocator +//===--------------------------------------------------------------------===// +data_ptr_t BufferManager::BufferAllocatorAllocate(PrivateAllocatorData *private_data, idx_t size) { + auto &data = (BufferAllocatorData &)*private_data; + if (!data.manager.EvictBlocks(size, data.manager.maximum_memory)) { + throw OutOfMemoryException("failed to allocate data of size %lld%s", size, data.manager.InMemoryWarning()); + } + return Allocator::Get(data.manager.db).AllocateData(size); +} + +void BufferManager::BufferAllocatorFree(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t size) { + auto &data = (BufferAllocatorData &)*private_data; + data.manager.current_memory -= size; + return Allocator::Get(data.manager.db).FreeData(pointer, size); +} + +data_ptr_t BufferManager::BufferAllocatorRealloc(PrivateAllocatorData *private_data, data_ptr_t pointer, idx_t old_size, + idx_t size) { + auto &data = (BufferAllocatorData &)*private_data; + data.manager.current_memory -= old_size; + data.manager.current_memory += size; + return Allocator::Get(data.manager.db).ReallocateData(pointer, old_size, size); +} + +Allocator &BufferAllocator::Get(ClientContext &context) { + auto &manager = BufferManager::GetBufferManager(context); + return manager.GetBufferAllocator(); +} + +Allocator &BufferManager::GetBufferAllocator() { + return buffer_allocator; +} + } // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -180085,50 +197216,10 @@ string BufferManager::InMemoryWarning() { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/storage/meta_block_writer.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - -namespace duckdb { -class DatabaseInstance; - -//! This struct is responsible for writing metadata to disk -class MetaBlockWriter : public Serializer { -public: - MetaBlockWriter(DatabaseInstance &db, block_id_t initial_block_id = INVALID_BLOCK); - ~MetaBlockWriter() override; - - DatabaseInstance &db; - unique_ptr block; - set written_blocks; - idx_t offset; - -public: - BlockPointer GetBlockPointer(); - void Flush(); - - void WriteData(const_data_ptr_t buffer, idx_t write_size) override; - -protected: - virtual block_id_t GetNextBlockId(); -}; - -} // namespace duckdb - - - namespace duckdb { class DatabaseInstance; class ClientContext; @@ -180196,6 +197287,7 @@ class CheckpointManager { void WriteSequence(SequenceCatalogEntry &table); void WriteMacro(ScalarMacroCatalogEntry &table); void WriteTableMacro(TableMacroCatalogEntry &table); + void WriteIndex(IndexCatalogEntry &index_catalog); void WriteType(TypeCatalogEntry &table); void ReadSchema(ClientContext &context, MetaBlockReader &reader); @@ -180204,6 +197296,7 @@ class CheckpointManager { void ReadSequence(ClientContext &context, MetaBlockReader &reader); void ReadMacro(ClientContext &context, MetaBlockReader &reader); void ReadTableMacro(ClientContext &context, MetaBlockReader &reader); + void ReadIndex(ClientContext &context, MetaBlockReader &reader); void ReadType(ClientContext &context, MetaBlockReader &reader); private: @@ -180232,45 +197325,6 @@ class TableDataReader { } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/storage/meta_block_reader.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - -namespace duckdb { -class BlockHandle; -class BufferHandle; -class DatabaseInstance; - -//! This struct is responsible for reading meta data from disk -class MetaBlockReader : public Deserializer { -public: - MetaBlockReader(DatabaseInstance &db, block_id_t block); - ~MetaBlockReader() override; - - DatabaseInstance &db; - shared_ptr block; - unique_ptr handle; - idx_t offset; - block_id_t next_block; - -public: - //! Read content of size read_size into the buffer - void ReadData(data_ptr_t buffer, idx_t read_size) override; - -private: - void ReadNewBlock(block_id_t id); -}; -} // namespace duckdb @@ -180293,7 +197347,7 @@ TableDataReader::TableDataReader(MetaBlockReader &reader, BoundCreateTableInfo & void TableDataReader::ReadTableData() { auto &columns = info.Base().columns; - D_ASSERT(columns.size() > 0); + D_ASSERT(!columns.empty()); // deserialize the total table statistics info.data->column_stats.reserve(columns.size()); @@ -180342,13 +197396,16 @@ class TableDataWriter { public: TableDataWriter(DatabaseInstance &db, CheckpointManager &checkpoint_manager, TableCatalogEntry &table, - MetaBlockWriter &meta_writer); + MetaBlockWriter &table_data_writer, MetaBlockWriter &meta_data_writer); ~TableDataWriter(); - BlockPointer WriteTableData(); + void WriteTableData(); + MetaBlockWriter &GetTableWriter() { + return table_data_writer; + } MetaBlockWriter &GetMetaWriter() { - return meta_writer; + return meta_data_writer; } CheckpointManager &GetCheckpointManager() { @@ -180360,7 +197417,10 @@ class TableDataWriter { private: CheckpointManager &checkpoint_manager; TableCatalogEntry &table; - MetaBlockWriter &meta_writer; + // Writes the actual table data + MetaBlockWriter &table_data_writer; + // Writes the metadata of the table + MetaBlockWriter &meta_data_writer; }; } // namespace duckdb @@ -180375,16 +197435,17 @@ class TableDataWriter { namespace duckdb { TableDataWriter::TableDataWriter(DatabaseInstance &, CheckpointManager &checkpoint_manager, TableCatalogEntry &table, - MetaBlockWriter &meta_writer) - : checkpoint_manager(checkpoint_manager), table(table), meta_writer(meta_writer) { + MetaBlockWriter &table_data_writer, MetaBlockWriter &meta_data_writer) + : checkpoint_manager(checkpoint_manager), table(table), table_data_writer(table_data_writer), + meta_data_writer(meta_data_writer) { } TableDataWriter::~TableDataWriter() { } -BlockPointer TableDataWriter::WriteTableData() { +void TableDataWriter::WriteTableData() { // start scanning the table and append the data to the uncompressed segments - return table.storage->Checkpoint(*this); + table.storage->Checkpoint(*this); } CompressionType TableDataWriter::GetColumnCompressionType(idx_t i) { @@ -180472,7 +197533,7 @@ class WriteOverflowStringsToDisk : public OverflowStringWriter { DatabaseInstance &db; //! Temporary buffer - unique_ptr handle; + BufferHandle handle; //! The block on-disk to which we are writing block_id_t block_id; //! The offset within the current block @@ -180492,6 +197553,7 @@ class WriteOverflowStringsToDisk : public OverflowStringWriter { + namespace duckdb { WriteOverflowStringsToDisk::WriteOverflowStringsToDisk(DatabaseInstance &db) @@ -180501,34 +197563,45 @@ WriteOverflowStringsToDisk::WriteOverflowStringsToDisk(DatabaseInstance &db) WriteOverflowStringsToDisk::~WriteOverflowStringsToDisk() { auto &block_manager = BlockManager::GetBlockManager(db); if (offset > 0) { - block_manager.Write(*handle->node, block_id); + block_manager.Write(handle.GetFileBuffer(), block_id); } } void WriteOverflowStringsToDisk::WriteString(string_t string, block_id_t &result_block, int32_t &result_offset) { auto &buffer_manager = BufferManager::GetBufferManager(db); auto &block_manager = BlockManager::GetBlockManager(db); - if (!handle) { + if (!handle.IsValid()) { handle = buffer_manager.Allocate(Storage::BLOCK_SIZE); } // first write the length of the string - if (block_id == INVALID_BLOCK || offset + sizeof(uint32_t) >= STRING_SPACE) { + if (block_id == INVALID_BLOCK || offset + 2 * sizeof(uint32_t) >= STRING_SPACE) { AllocateNewBlock(block_manager.GetFreeBlockId()); } result_block = block_id; result_offset = offset; - // write the length field - auto string_length = string.GetSize(); - Store(string_length, handle->node->buffer + offset); - offset += sizeof(uint32_t); + // GZIP the string + auto uncompressed_size = string.GetSize(); + MiniZStream s; + size_t compressed_size = 0; + compressed_size = s.MaxCompressedLength(uncompressed_size); + auto compressed_buf = unique_ptr(new data_t[compressed_size]); + s.Compress((const char *)string.GetDataUnsafe(), uncompressed_size, (char *)compressed_buf.get(), &compressed_size); + string_t compressed_string((const char *)compressed_buf.get(), compressed_size); + + // store sizes + auto data_ptr = handle.Ptr(); + Store(compressed_size, data_ptr + offset); + Store(uncompressed_size, data_ptr + offset + sizeof(uint32_t)); + // now write the remainder of the string - auto strptr = string.GetDataUnsafe(); - uint32_t remaining = string_length; + offset += 2 * sizeof(uint32_t); + auto strptr = compressed_string.GetDataUnsafe(); + uint32_t remaining = compressed_size; while (remaining > 0) { uint32_t to_write = MinValue(remaining, STRING_SPACE - offset); if (to_write > 0) { - memcpy(handle->node->buffer + offset, strptr, to_write); + memcpy(data_ptr + offset, strptr, to_write); remaining -= to_write; offset += to_write; @@ -180538,7 +197611,7 @@ void WriteOverflowStringsToDisk::WriteString(string_t string, block_id_t &result // there is still remaining stuff to write // first get the new block id and write it to the end of the previous block auto new_block_id = block_manager.GetFreeBlockId(); - Store(new_block_id, handle->node->buffer + offset); + Store(new_block_id, data_ptr + offset); // now write the current block to disk and allocate a new block AllocateNewBlock(new_block_id); } @@ -180549,7 +197622,7 @@ void WriteOverflowStringsToDisk::AllocateNewBlock(block_id_t new_block_id) { auto &block_manager = BlockManager::GetBlockManager(db); if (block_id != INVALID_BLOCK) { // there is an old block, write it first - block_manager.Write(*handle->node, block_id); + block_manager.Write(handle.GetFileBuffer(), block_id); } offset = 0; block_id = new_block_id; @@ -180575,6 +197648,12 @@ void WriteOverflowStringsToDisk::AllocateNewBlock(block_id_t new_block_id) { + + + + + + @@ -180632,7 +197711,7 @@ void CheckpointManager::CreateCheckpoint() { wal->WriteCheckpoint(meta_block); wal->Flush(); - if (config.checkpoint_abort == CheckpointAbort::DEBUG_ABORT_BEFORE_HEADER) { + if (config.options.checkpoint_abort == CheckpointAbort::DEBUG_ABORT_BEFORE_HEADER) { throw IOException("Checkpoint aborted before header write because of PRAGMA checkpoint_abort flag"); } @@ -180641,7 +197720,7 @@ void CheckpointManager::CreateCheckpoint() { header.meta_block = meta_block; block_manager.WriteHeader(header); - if (config.checkpoint_abort == CheckpointAbort::DEBUG_ABORT_BEFORE_TRUNCATE) { + if (config.options.checkpoint_abort == CheckpointAbort::DEBUG_ABORT_BEFORE_TRUNCATE) { throw IOException("Checkpoint aborted before truncate because of PRAGMA checkpoint_abort flag"); } @@ -180733,6 +197812,12 @@ void CheckpointManager::WriteSchema(SchemaCatalogEntry &schema) { } }); + vector indexes; + schema.Scan(CatalogType::INDEX_ENTRY, [&](CatalogEntry *entry) { + D_ASSERT(!entry->internal); + indexes.push_back((IndexCatalogEntry *)entry); + }); + FieldWriter writer(*metadata_writer); writer.WriteField(custom_types.size()); writer.WriteField(sequences.size()); @@ -180740,6 +197825,7 @@ void CheckpointManager::WriteSchema(SchemaCatalogEntry &schema) { writer.WriteField(views.size()); writer.WriteField(macros.size()); writer.WriteField(table_macros.size()); + writer.WriteField(indexes.size()); writer.Finalize(); // write the custom_types @@ -180753,24 +197839,28 @@ void CheckpointManager::WriteSchema(SchemaCatalogEntry &schema) { } // reorder tables because of foreign key constraint ReorderTableEntries(tables); - // now write the tables + // Write the tables for (auto &table : tables) { WriteTable(*table); } - // now write the views + // Write the views for (auto &view : views) { WriteView(*view); } - // finally write the macro's + // Write the macros for (auto ¯o : macros) { WriteMacro(*macro); } - // finally write the macro's + // Write the table's macros for (auto ¯o : table_macros) { WriteTableMacro(*macro); } + // Write the indexes + for (auto &index : indexes) { + WriteIndex(*index); + } } void CheckpointManager::ReadSchema(ClientContext &context, MetaBlockReader &reader) { @@ -180790,6 +197880,7 @@ void CheckpointManager::ReadSchema(ClientContext &context, MetaBlockReader &read uint32_t view_count = field_reader.ReadRequired(); uint32_t macro_count = field_reader.ReadRequired(); uint32_t table_macro_count = field_reader.ReadRequired(); + uint32_t table_index_count = field_reader.ReadRequired(); field_reader.Finalize(); // now read the enums @@ -180818,6 +197909,9 @@ void CheckpointManager::ReadSchema(ClientContext &context, MetaBlockReader &read for (uint32_t i = 0; i < table_macro_count; i++) { ReadTableMacro(context, reader); } + for (uint32_t i = 0; i < table_index_count; i++) { + ReadIndex(context, reader); + } } //===--------------------------------------------------------------------===// @@ -180828,7 +197922,7 @@ void CheckpointManager::WriteView(ViewCatalogEntry &view) { } void CheckpointManager::ReadView(ClientContext &context, MetaBlockReader &reader) { - auto info = ViewCatalogEntry::Deserialize(reader); + auto info = ViewCatalogEntry::Deserialize(reader, context); auto &catalog = Catalog::GetCatalog(db); catalog.CreateView(context, info.get()); @@ -180848,6 +197942,77 @@ void CheckpointManager::ReadSequence(ClientContext &context, MetaBlockReader &re catalog.CreateSequence(context, info.get()); } +//===--------------------------------------------------------------------===// +// Indexes +//===--------------------------------------------------------------------===// +void CheckpointManager::WriteIndex(IndexCatalogEntry &index_catalog) { + // Write the index data and metadata + // Serialize the necessary meta data for index catalog construction. + auto root_offset = index_catalog.index->Serialize(*tabledata_writer); + index_catalog.Serialize(*metadata_writer); + // Serialize the Block id and offset of root node + metadata_writer->Write(root_offset.block_id); + metadata_writer->Write(root_offset.offset); +} + +void CheckpointManager::ReadIndex(ClientContext &context, MetaBlockReader &reader) { + + // Deserialize the index meta data + auto info = IndexCatalogEntry::Deserialize(reader, context); + + // Create index in the catalog + auto &catalog = Catalog::GetCatalog(db); + auto schema_catalog = catalog.GetSchema(context, info->schema); + auto table_catalog = + (TableCatalogEntry *)catalog.GetEntry(context, CatalogType::TABLE_ENTRY, info->schema, info->table->table_name); + auto index_catalog = (IndexCatalogEntry *)schema_catalog->CreateIndex(context, info.get(), table_catalog); + index_catalog->info = table_catalog->storage->info; + // Here we just gotta read the root node + auto root_block_id = reader.Read(); + auto root_offset = reader.Read(); + + // create an adaptive radix tree around the expressions + vector> unbound_expressions; + vector> parsed_expressions; + + for (auto &p_exp : info->parsed_expressions) { + parsed_expressions.push_back(p_exp->Copy()); + } + + auto binder = Binder::CreateBinder(context); + auto table_ref = (TableRef *)info->table.get(); + auto bound_table = binder->Bind(*table_ref); + D_ASSERT(bound_table->type == TableReferenceType::BASE_TABLE); + IndexBinder idx_binder(*binder, context); + unbound_expressions.reserve(parsed_expressions.size()); + for (auto &expr : parsed_expressions) { + unbound_expressions.push_back(idx_binder.Bind(expr)); + } + + if (parsed_expressions.empty()) { + // If no parsed_expressions are present, this means this is a PK/FK index, so we create the necessary bound + // column refs + unbound_expressions.reserve(info->column_ids.size()); + for (idx_t key_nr = 0; key_nr < info->column_ids.size(); key_nr++) { + unbound_expressions.push_back(make_unique( + table_catalog->columns[info->column_ids[key_nr]].GetName(), + table_catalog->columns[info->column_ids[key_nr]].GetType(), ColumnBinding(0, key_nr))); + } + } + + switch (info->index_type) { + case IndexType::ART: { + auto art = make_unique(info->column_ids, move(unbound_expressions), info->constraint_type, db, + root_block_id, root_offset); + index_catalog->index = art.get(); + table_catalog->storage->info->indexes.AddIndex(move(art)); + break; + } + default: + throw InternalException("Can't read this index type"); + } +} + //===--------------------------------------------------------------------===// // Custom Types //===--------------------------------------------------------------------===// @@ -180870,7 +198035,7 @@ void CheckpointManager::WriteMacro(ScalarMacroCatalogEntry ¯o) { } void CheckpointManager::ReadMacro(ClientContext &context, MetaBlockReader &reader) { - auto info = ScalarMacroCatalogEntry::Deserialize(reader); + auto info = ScalarMacroCatalogEntry::Deserialize(reader, context); auto &catalog = Catalog::GetCatalog(db); catalog.CreateFunction(context, info.get()); } @@ -180880,7 +198045,7 @@ void CheckpointManager::WriteTableMacro(TableMacroCatalogEntry ¯o) { } void CheckpointManager::ReadTableMacro(ClientContext &context, MetaBlockReader &reader) { - auto info = TableMacroCatalogEntry::Deserialize(reader); + auto info = TableMacroCatalogEntry::Deserialize(reader, context); auto &catalog = Catalog::GetCatalog(db); catalog.CreateFunction(context, info.get()); } @@ -180892,17 +198057,13 @@ void CheckpointManager::WriteTable(TableCatalogEntry &table) { // write the table meta data table.Serialize(*metadata_writer); // now we need to write the table data - TableDataWriter writer(db, *this, table, *tabledata_writer); - auto pointer = writer.WriteTableData(); - - //! write the block pointer for the table info - metadata_writer->Write(pointer.block_id); - metadata_writer->Write(pointer.offset); + TableDataWriter writer(db, *this, table, *tabledata_writer, *metadata_writer); + writer.WriteTableData(); } void CheckpointManager::ReadTable(ClientContext &context, MetaBlockReader &reader) { // deserialize the table meta data - auto info = TableCatalogEntry::Deserialize(reader); + auto info = TableCatalogEntry::Deserialize(reader, context); // bind the info auto binder = Binder::CreateBinder(context); auto bound_info = binder->BindCreateTableInfo(move(info)); @@ -180915,6 +198076,14 @@ void CheckpointManager::ReadTable(ClientContext &context, MetaBlockReader &reade TableDataReader data_reader(table_data_reader, *bound_info); data_reader.ReadTableData(); + // Get any indexes block info + idx_t num_indexes = reader.Read(); + for (idx_t i = 0; i < num_indexes; i++) { + auto idx_block_id = reader.Read(); + auto idx_offset = reader.Read(); + bound_info->indexes.emplace_back(idx_block_id, idx_offset); + } + // finally create the table in the catalog auto &catalog = Catalog::GetCatalog(db); catalog.CreateTable(context, bound_info.get()); @@ -181006,7 +198175,7 @@ void PartialBlock::FlushToDisk(DatabaseInstance &db) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #12 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #14 // See the end of this file for a list /** @@ -181019,7 +198188,7 @@ void PartialBlock::FlushToDisk(DatabaseInstance &db) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #12 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #14 // See the end of this file for a list /** @@ -182249,6 +199418,13 @@ class BitpackingPrimitives { return FindMinimumBitWidth(values, count); } + // Calculates the minimum required number of bits per value that can store all values, + // given a predetermined minimum and maximum value of the buffer + template + inline static bitpacking_width_t MinimumBitWidth(T minimum, T maximum) { + return FindMinimumBitWidth(minimum, maximum); + } + template inline static idx_t GetRequiredSize(idx_t count, bitpacking_width_t width) { count = RoundUpToAlgorithmGroupSize(count); @@ -182337,6 +199513,18 @@ class BitpackingPrimitives { } } + // Sign bit extension + template ::type> + static void SignExtend(data_ptr_t dst, bitpacking_width_t width) { + T const mask = ((T_U)1) << (width - 1); + for (idx_t i = 0; i < BitpackingPrimitives::BITPACKING_ALGORITHM_GROUP_SIZE; ++i) { + T value = Load(dst + i * sizeof(T)); + value = value & ((((T_U)1) << width) - ((T_U)1)); + T result = (value ^ mask) - mask; + Store(result, dst + i * sizeof(T)); + } + } + template static void UnPackGroup(data_ptr_t dst, data_ptr_t src, bitpacking_width_t width, bool skip_sign_extension = false) { @@ -182360,33 +199548,14 @@ class BitpackingPrimitives { // Prevent compression at widths that are ineffective template static bitpacking_width_t GetEffectiveWidth(bitpacking_width_t width) { - if (width > 56) { - return 64; - } - - if (width > 28 && (std::is_same::value || std::is_same::value)) { - return 32; - } - - else if (width > 14 && (std::is_same::value || std::is_same::value)) { - return 16; + auto bits_of_type = sizeof(T) * 8; + auto type_size = sizeof(T); + if (width + type_size > bits_of_type) { + return bits_of_type; } - return width; } - // Sign bit extension - template ::type> - static void SignExtend(data_ptr_t dst, bitpacking_width_t width) { - T const mask = ((T_U)1) << (width - 1); - for (idx_t i = 0; i < BitpackingPrimitives::BITPACKING_ALGORITHM_GROUP_SIZE; ++i) { - T value = Load(dst + i * sizeof(T)); - value = value & ((((T_U)1) << width) - ((T_U)1)); - T result = (value ^ mask) - mask; - Store(result, dst + i * sizeof(T)); - } - } - template static void PackGroup(data_ptr_t dst, T *values, bitpacking_width_t width) { if (std::is_same::value || std::is_same::value) { @@ -182474,9 +199643,7 @@ struct ColumnCheckpointState { unique_ptr global_stats; public: - virtual unique_ptr GetStatistics() { - return global_stats->Copy(); - } + virtual unique_ptr GetStatistics(); virtual void FlushSegment(unique_ptr segment, idx_t segment_size); virtual void FlushToDisk(); @@ -182553,7 +199720,7 @@ class ColumnData { virtual void InitializeAppend(ColumnAppendState &state); //! Append a vector of type [type] to the end of the column virtual void Append(BaseStatistics &stats, ColumnAppendState &state, Vector &vector, idx_t count); - virtual void AppendData(BaseStatistics &stats, ColumnAppendState &state, VectorData &vdata, idx_t count); + virtual void AppendData(BaseStatistics &stats, ColumnAppendState &state, UnifiedVectorFormat &vdata, idx_t count); //! Revert a set of appends to the ColumnData virtual void RevertAppend(row_t start_row); @@ -182652,17 +199819,19 @@ class ColumnDataCheckpointer { + #include namespace duckdb { // Note that optimizations in scanning only work if this value is equal to STANDARD_VECTOR_SIZE, however we keep them // separated to prevent the code from break on lower vector sizes -static constexpr const idx_t BITPACKING_WIDTH_GROUP_SIZE = 1024; +static constexpr const idx_t BITPACKING_METADATA_GROUP_SIZE = 1024; struct EmptyBitpackingWriter { template - static void Operation(T *values, bool *validity, bitpacking_width_t width, idx_t count, void *data_ptr) { + static void Operation(T *values, bool *validity, bitpacking_width_t width, T frame_of_reference, idx_t count, + void *data_ptr) { } }; @@ -182670,39 +199839,95 @@ template struct BitpackingState { public: BitpackingState() : compression_buffer_idx(0), total_size(0), data_ptr(nullptr) { + ResetMinMax(); } - T compression_buffer[BITPACKING_WIDTH_GROUP_SIZE]; - bool compression_buffer_validity[BITPACKING_WIDTH_GROUP_SIZE]; + T compression_buffer[BITPACKING_METADATA_GROUP_SIZE]; + bool compression_buffer_validity[BITPACKING_METADATA_GROUP_SIZE]; idx_t compression_buffer_idx; idx_t total_size; void *data_ptr; + bool min_max_set; + T minimum; + T maximum; + public: - template + void SubtractFrameOfReference(const T &frame_of_reference) { + for (idx_t i = 0; i < compression_buffer_idx; i++) { + compression_buffer[i] -= frame_of_reference; + } + } + + void ResetMinMax() { + min_max_set = false; + //! We set these to 0, in case all values are NULL, in which case the min and max will never be set. + minimum = 0; + maximum = 0; + } + + bool TryUpdateMinMax(T value) { + bool updated = false; + if (!min_max_set || value < minimum) { + minimum = value; + updated = true; + } + if (!min_max_set || value > maximum) { + maximum = value; + updated = true; + } + min_max_set = min_max_set || updated; + //! Only when either of the values are updated, do we need to test the overflow + if (updated) { + T ignore; + return TrySubtractOperator::Operation(maximum, minimum, ignore); + } + return true; + } + + T GetFrameOfReference() { + return minimum; + } + T Maximum() { + return maximum; + } + + template ::type> void Flush() { - bitpacking_width_t width = BitpackingPrimitives::MinimumBitWidth(compression_buffer, compression_buffer_idx); - OP::Operation(compression_buffer, compression_buffer_validity, width, compression_buffer_idx, data_ptr); - total_size += (BITPACKING_WIDTH_GROUP_SIZE * width) / 8 + sizeof(bitpacking_width_t); + T frame_of_reference = GetFrameOfReference(); + SubtractFrameOfReference(frame_of_reference); + + //! Because of FOR, we can guarantee that all values are positive + T_U adjusted_maximum = T_U(Maximum() - frame_of_reference); + + bitpacking_width_t width = BitpackingPrimitives::MinimumBitWidth((T_U)0, adjusted_maximum); + OP::template Operation(compression_buffer, compression_buffer_validity, width, frame_of_reference, + compression_buffer_idx, data_ptr); + total_size += (BITPACKING_METADATA_GROUP_SIZE * width) / 8 + sizeof(bitpacking_width_t) + sizeof(T); compression_buffer_idx = 0; + ResetMinMax(); } template - void Update(T *data, ValidityMask &validity, idx_t idx) { + bool Update(T *data, ValidityMask &validity, idx_t idx) { if (validity.RowIsValid(idx)) { compression_buffer_validity[compression_buffer_idx] = true; compression_buffer[compression_buffer_idx++] = data[idx]; + if (!TryUpdateMinMax(data[idx])) { + return false; + } } else { // We write zero for easy bitwidth analysis of the compression buffer later compression_buffer_validity[compression_buffer_idx] = false; compression_buffer[compression_buffer_idx++] = 0; } - if (compression_buffer_idx == BITPACKING_WIDTH_GROUP_SIZE) { + if (compression_buffer_idx == BITPACKING_METADATA_GROUP_SIZE) { // Calculate bitpacking width; Flush(); } + return true; } }; @@ -182722,15 +199947,16 @@ unique_ptr BitpackingInitAnalyze(ColumnData &col_data, PhysicalTyp template bool BitpackingAnalyze(AnalyzeState &state, Vector &input, idx_t count) { auto &analyze_state = (BitpackingAnalyzeState &)state; - VectorData vdata; - input.Orrify(count, vdata); + UnifiedVectorFormat vdata; + input.ToUnifiedFormat(count, vdata); auto data = (T *)vdata.data; for (idx_t i = 0; i < count; i++) { auto idx = vdata.sel->get_index(i); - analyze_state.state.template Update(data, vdata.validity, idx); + if (!analyze_state.state.template Update(data, vdata.validity, idx)) { + return false; + } } - return true; } @@ -182760,23 +199986,29 @@ struct BitpackingCompressState : public CompressionState { ColumnDataCheckpointer &checkpointer; CompressionFunction *function; unique_ptr current_segment; - unique_ptr handle; + BufferHandle handle; // Ptr to next free spot in segment; data_ptr_t data_ptr; - // Ptr to next free spot for storing bitwidths (growing downwards). - data_ptr_t width_ptr; + // Ptr to next free spot for storing bitwidths and frame-of-references (growing downwards). + data_ptr_t metadata_ptr; BitpackingState state; public: struct BitpackingWriter { + template - static void Operation(VALUE_TYPE *values, bool *validity, bitpacking_width_t width, idx_t count, - void *data_ptr) { + static void Operation(VALUE_TYPE *values, bool *validity, bitpacking_width_t width, + VALUE_TYPE frame_of_reference, idx_t count, void *data_ptr) { auto state = (BitpackingCompressState *)data_ptr; + auto total_bits_needed = (width * BITPACKING_METADATA_GROUP_SIZE); + D_ASSERT(total_bits_needed % 8 == 0); + auto total_bytes_needed = total_bits_needed / 8; + total_bytes_needed += sizeof(bitpacking_width_t); + total_bytes_needed += sizeof(VALUE_TYPE); - if (state->RemainingSize() < (width * BITPACKING_WIDTH_GROUP_SIZE) / 8 + sizeof(bitpacking_width_t)) { + if (state->RemainingSize() < total_bytes_needed) { // Segment is full auto row_start = state->current_segment->start + state->current_segment->count; state->FlushSegment(); @@ -182785,17 +200017,17 @@ struct BitpackingCompressState : public CompressionState { for (idx_t i = 0; i < count; i++) { if (validity[i]) { - NumericStatistics::Update(state->current_segment->stats, values[i]); + NumericStatistics::Update(state->current_segment->stats, values[i] + frame_of_reference); } } - state->WriteValues(values, width, count); + state->WriteValues(values, width, frame_of_reference, count); } }; - // Space remaining between the width_ptr growing down and data ptr growing up + // Space remaining between the metadata_ptr growing down and data ptr growing up idx_t RemainingSize() { - return width_ptr - data_ptr; + return metadata_ptr - data_ptr; } void CreateEmptySegment(idx_t row_start) { @@ -182807,12 +200039,12 @@ struct BitpackingCompressState : public CompressionState { auto &buffer_manager = BufferManager::GetBufferManager(db); handle = buffer_manager.Pin(current_segment->block); - data_ptr = handle->Ptr() + current_segment->GetBlockOffset() + BitpackingPrimitives::BITPACKING_HEADER_SIZE; - width_ptr = - handle->Ptr() + current_segment->GetBlockOffset() + Storage::BLOCK_SIZE - sizeof(bitpacking_width_t); + data_ptr = handle.Ptr() + current_segment->GetBlockOffset() + BitpackingPrimitives::BITPACKING_HEADER_SIZE; + metadata_ptr = + handle.Ptr() + current_segment->GetBlockOffset() + Storage::BLOCK_SIZE - sizeof(bitpacking_width_t); } - void Append(VectorData &vdata, idx_t count) { + void Append(UnifiedVectorFormat &vdata, idx_t count) { // TODO Optimization: avoid use of compression buffer if we can compress straight to result vector auto data = (T *)vdata.data; @@ -182822,29 +200054,32 @@ struct BitpackingCompressState : public CompressionState { } } - void WriteValues(T *values, bitpacking_width_t width, idx_t count) { - // TODO we can optimize this by stopping early if count < BITPACKING_WIDTH_GROUP_SIZE + void WriteValues(T *values, bitpacking_width_t width, T frame_of_reference, idx_t count) { + // TODO we can optimize this by stopping early if count < BITPACKING_METADATA_GROUP_SIZE BitpackingPrimitives::PackBuffer(data_ptr, values, count, width); - data_ptr += (BITPACKING_WIDTH_GROUP_SIZE * width) / 8; + data_ptr += (BITPACKING_METADATA_GROUP_SIZE * width) / 8; - Store(width, width_ptr); - width_ptr -= sizeof(bitpacking_width_t); + Store(width, metadata_ptr); + metadata_ptr -= sizeof(T); + Store(frame_of_reference, metadata_ptr); + metadata_ptr -= sizeof(bitpacking_width_t); current_segment->count += count; } void FlushSegment() { auto &state = checkpointer.GetCheckpointState(); + auto dataptr = handle.Ptr(); - // Compact the segment by moving the widths next to the data. - idx_t minimal_widths_offset = AlignValue(data_ptr - handle->node->buffer); - idx_t widths_size = handle->node->buffer + Storage::BLOCK_SIZE - width_ptr - 1; - idx_t total_segment_size = minimal_widths_offset + widths_size; - memmove(handle->node->buffer + minimal_widths_offset, width_ptr + 1, widths_size); + // Compact the segment by moving the metadata next to the data. + idx_t metadata_offset = AlignValue(data_ptr - dataptr); + idx_t metadata_size = dataptr + Storage::BLOCK_SIZE - metadata_ptr - 1; + idx_t total_segment_size = metadata_offset + metadata_size; + memmove(dataptr + metadata_offset, metadata_ptr + 1, metadata_size); - // Store the offset of the first width (which is at the highest address). - Store(minimal_widths_offset + widths_size - 1, handle->node->buffer); - handle.reset(); + // Store the offset of the metadata of the first group (which is at the highest address). + Store(metadata_offset + metadata_size - 1, dataptr); + handle.Destroy(); state.FlushSegment(move(current_segment), total_segment_size); } @@ -182865,8 +200100,8 @@ unique_ptr BitpackingInitCompression(ColumnDataCheckpointer &c template void BitpackingCompress(CompressionState &state_p, Vector &scan_vector, idx_t count) { auto &state = (BitpackingCompressState &)state_p; - VectorData vdata; - scan_vector.Orrify(count, vdata); + UnifiedVectorFormat vdata; + scan_vector.ToUnifiedFormat(count, vdata); state.Append(vdata, count); } @@ -182885,51 +200120,54 @@ struct BitpackingScanState : public SegmentScanState { explicit BitpackingScanState(ColumnSegment &segment) { auto &buffer_manager = BufferManager::GetBufferManager(segment.db); handle = buffer_manager.Pin(segment.block); - - current_width_group_ptr = - handle->node->buffer + segment.GetBlockOffset() + BitpackingPrimitives::BITPACKING_HEADER_SIZE; + auto dataptr = handle.Ptr(); + current_metadata_group_ptr = dataptr + segment.GetBlockOffset() + BitpackingPrimitives::BITPACKING_HEADER_SIZE; // load offset to bitpacking widths pointer - auto bitpacking_widths_offset = Load(handle->node->buffer + segment.GetBlockOffset()); - bitpacking_width_ptr = handle->node->buffer + segment.GetBlockOffset() + bitpacking_widths_offset; + auto bitpacking_metadata_offset = Load(dataptr + segment.GetBlockOffset()); + bitpacking_metadata_ptr = dataptr + segment.GetBlockOffset() + bitpacking_metadata_offset; - // load the bitwidth of the first vector - LoadCurrentBitWidth(); + // load the metadata of the first vector + LoadCurrentMetaData(); } - unique_ptr handle; + BufferHandle handle; void (*decompress_function)(data_ptr_t, data_ptr_t, bitpacking_width_t, bool skip_sign_extension); T decompression_buffer[BitpackingPrimitives::BITPACKING_ALGORITHM_GROUP_SIZE]; idx_t position_in_group = 0; - data_ptr_t current_width_group_ptr; - data_ptr_t bitpacking_width_ptr; + data_ptr_t current_metadata_group_ptr; + data_ptr_t bitpacking_metadata_ptr; bitpacking_width_t current_width; + T current_frame_of_reference; public: - void LoadCurrentBitWidth() { - D_ASSERT(bitpacking_width_ptr > handle->node->buffer && - bitpacking_width_ptr < handle->node->buffer + Storage::BLOCK_SIZE); - current_width = Load(bitpacking_width_ptr); + //! Loads the current group header, and sets pointer to next header + void LoadCurrentMetaData() { + D_ASSERT(bitpacking_metadata_ptr > handle.Ptr() && + bitpacking_metadata_ptr < handle.Ptr() + Storage::BLOCK_SIZE); + current_width = Load(bitpacking_metadata_ptr); + bitpacking_metadata_ptr -= sizeof(T); + current_frame_of_reference = Load(bitpacking_metadata_ptr); + bitpacking_metadata_ptr -= sizeof(bitpacking_width_t); LoadDecompressFunction(); } void Skip(ColumnSegment &segment, idx_t skip_count) { while (skip_count > 0) { - if (position_in_group + skip_count < BITPACKING_WIDTH_GROUP_SIZE) { + if (position_in_group + skip_count < BITPACKING_METADATA_GROUP_SIZE) { // We're not leaving this bitpacking group, we can perform all skips. position_in_group += skip_count; break; } else { // The skip crosses the current bitpacking group, we skip the remainder of this group. - auto skipping = BITPACKING_WIDTH_GROUP_SIZE - position_in_group; + auto skipping = BITPACKING_METADATA_GROUP_SIZE - position_in_group; position_in_group = 0; - current_width_group_ptr += (current_width * BITPACKING_WIDTH_GROUP_SIZE) / 8; + current_metadata_group_ptr += (current_width * BITPACKING_METADATA_GROUP_SIZE) / 8; - // Update width pointer and load new width - bitpacking_width_ptr -= sizeof(bitpacking_width_t); - LoadCurrentBitWidth(); + // Load new width + LoadCurrentMetaData(); skip_count -= skipping; } @@ -182947,6 +200185,16 @@ unique_ptr BitpackingInitScan(ColumnSegment &segment) { return move(result); } +template +static void ApplyFrameOfReference(T *dst, T frame_of_reference, idx_t size) { + if (!frame_of_reference) { + return; + } + for (idx_t i = 0; i < size; i++) { + dst[i] += frame_of_reference; + } +} + //===--------------------------------------------------------------------===// // Scan base data //===--------------------------------------------------------------------===// @@ -182959,31 +200207,28 @@ void BitpackingScanPartial(ColumnSegment &segment, ColumnScanState &state, idx_t result.SetVectorType(VectorType::FLAT_VECTOR); // Fast path for when no compression was used, we can do a single memcopy - if (STANDARD_VECTOR_SIZE == BITPACKING_WIDTH_GROUP_SIZE) { - if (scan_state.current_width == sizeof(T) * 8 && scan_count <= BITPACKING_WIDTH_GROUP_SIZE && - scan_state.position_in_group == 0) { - - memcpy(result_data + result_offset, scan_state.current_width_group_ptr, scan_count * sizeof(T)); - scan_state.current_width_group_ptr += scan_count * sizeof(T); - scan_state.bitpacking_width_ptr -= sizeof(bitpacking_width_t); - scan_state.LoadCurrentBitWidth(); + if (STANDARD_VECTOR_SIZE == BITPACKING_METADATA_GROUP_SIZE) { + if (scan_state.current_frame_of_reference == 0 && scan_state.current_width == sizeof(T) * 8 && + scan_count <= BITPACKING_METADATA_GROUP_SIZE && scan_state.position_in_group == 0) { + + memcpy(result_data + result_offset, scan_state.current_metadata_group_ptr, scan_count * sizeof(T)); + scan_state.current_metadata_group_ptr += scan_count * sizeof(T); + scan_state.LoadCurrentMetaData(); return; } } - // Determine if we can skip sign extension during compression - auto &nstats = (NumericStatistics &)*segment.stats.statistics; - bool skip_sign_extend = std::is_signed::value && nstats.min >= 0; + //! Because FOR offsets all our values to be 0 or above, we can always skip sign extension here + bool skip_sign_extend = true; idx_t scanned = 0; while (scanned < scan_count) { - // Exhausted this width group, move pointers to next group and load bitwidth for next group. - if (scan_state.position_in_group >= BITPACKING_WIDTH_GROUP_SIZE) { + // Exhausted this metadata group, move pointers to next group and load metadata for next group. + if (scan_state.position_in_group >= BITPACKING_METADATA_GROUP_SIZE) { scan_state.position_in_group = 0; - scan_state.bitpacking_width_ptr -= sizeof(bitpacking_width_t); - scan_state.current_width_group_ptr += (scan_state.current_width * BITPACKING_WIDTH_GROUP_SIZE) / 8; - scan_state.LoadCurrentBitWidth(); + scan_state.current_metadata_group_ptr += (scan_state.current_width * BITPACKING_METADATA_GROUP_SIZE) / 8; + scan_state.LoadCurrentMetaData(); } idx_t offset_in_compression_group = @@ -182994,7 +200239,7 @@ void BitpackingScanPartial(ColumnSegment &segment, ColumnScanState &state, idx_t // Calculate start of compression algorithm group data_ptr_t current_position_ptr = - scan_state.current_width_group_ptr + scan_state.position_in_group * scan_state.current_width / 8; + scan_state.current_metadata_group_ptr + scan_state.position_in_group * scan_state.current_width / 8; data_ptr_t decompression_group_start_pointer = current_position_ptr - offset_in_compression_group * scan_state.current_width / 8; @@ -183013,7 +200258,7 @@ void BitpackingScanPartial(ColumnSegment &segment, ColumnScanState &state, idx_t memcpy(current_result_ptr, scan_state.decompression_buffer + offset_in_compression_group, to_scan * sizeof(T)); } - + ApplyFrameOfReference((T *)current_result_ptr, scan_state.current_frame_of_reference, to_scan); scanned += to_scan; scan_state.position_in_group += to_scan; } @@ -183040,16 +200285,18 @@ void BitpackingFetchRow(ColumnSegment &segment, ColumnFetchState &state, row_t r scan_state.position_in_group % BitpackingPrimitives::BITPACKING_ALGORITHM_GROUP_SIZE; data_ptr_t decompression_group_start_pointer = - scan_state.current_width_group_ptr + + scan_state.current_metadata_group_ptr + (scan_state.position_in_group - offset_in_compression_group) * scan_state.current_width / 8; - auto &nstats = (NumericStatistics &)*segment.stats.statistics; - bool skip_sign_extend = std::is_signed::value && nstats.min >= 0; + //! Because FOR offsets all our values to be 0 or above, we can always skip sign extension here + bool skip_sign_extend = true; scan_state.decompress_function((data_ptr_t)scan_state.decompression_buffer, decompression_group_start_pointer, scan_state.current_width, skip_sign_extend); *current_result_ptr = *(T *)(scan_state.decompression_buffer + offset_in_compression_group); + //! Apply FOR to result + *current_result_ptr += scan_state.current_frame_of_reference; } template void BitpackingSkip(ColumnSegment &segment, ColumnScanState &state, idx_t skip_count) { @@ -183112,6 +200359,44 @@ bool BitpackingFun::TypeIsSupported(PhysicalType type) { } // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/string_map_set.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + + +namespace duckdb { + +struct StringHash { + std::size_t operator()(const string_t &k) const { + return Hash(k); + } +}; + +struct StringEquality { + bool operator()(const string_t &a, const string_t &b) const { + return Equals::Operation(a, b); + } +}; + +template +using string_map_t = unordered_map; + +using string_set_t = unordered_set; + +} // namespace duckdb + + @@ -183195,7 +200480,7 @@ struct StringDictionaryContainer { }; struct StringScanState : public SegmentScanState { - unique_ptr handle; + BufferHandle handle; }; struct UncompressedStringStorage { @@ -183207,7 +200492,7 @@ struct UncompressedStringStorage { //! Base size of big string marker (block id + offset) static constexpr idx_t BIG_STRING_MARKER_BASE_SIZE = sizeof(block_id_t) + sizeof(int32_t); //! The marker size of the big string - static constexpr idx_t BIG_STRING_MARKER_SIZE = BIG_STRING_MARKER_BASE_SIZE + sizeof(uint16_t); + static constexpr idx_t BIG_STRING_MARKER_SIZE = BIG_STRING_MARKER_BASE_SIZE; //! The size below which the segment is compacted on flushing static constexpr size_t COMPACTION_FLUSH_LIMIT = (size_t)Storage::BLOCK_SIZE / 5 * 4; @@ -183223,35 +200508,41 @@ struct UncompressedStringStorage { idx_t result_idx); static unique_ptr StringInitSegment(ColumnSegment &segment, block_id_t block_id); - static idx_t StringAppend(ColumnSegment &segment, SegmentStatistics &stats, VectorData &data, idx_t offset, + static idx_t StringAppend(ColumnSegment &segment, SegmentStatistics &stats, UnifiedVectorFormat &data, idx_t offset, idx_t count) { return StringAppendBase(segment, stats, data, offset, count); } template - static idx_t StringAppendBase(ColumnSegment &segment, SegmentStatistics &stats, VectorData &data, idx_t offset, - idx_t count, std::unordered_map *seen_strings = nullptr) { + static idx_t StringAppendBase(ColumnSegment &segment, SegmentStatistics &stats, UnifiedVectorFormat &data, + idx_t offset, idx_t count, + std::unordered_map *seen_strings = nullptr) { auto &buffer_manager = BufferManager::GetBufferManager(segment.db); auto handle = buffer_manager.Pin(segment.block); D_ASSERT(segment.GetBlockOffset() == 0); auto source_data = (string_t *)data.data; - auto result_data = (int32_t *)(handle->node->buffer + DICTIONARY_HEADER_SIZE); + auto result_data = (int32_t *)(handle.Ptr() + DICTIONARY_HEADER_SIZE); for (idx_t i = 0; i < count; i++) { auto source_idx = data.sel->get_index(offset + i); auto target_idx = segment.count.load(); - idx_t remaining_space = RemainingSpace(segment, *handle); + idx_t remaining_space = RemainingSpace(segment, handle); if (remaining_space < sizeof(int32_t)) { // string index does not fit in the block at all return i; } remaining_space -= sizeof(int32_t); + auto dictionary = GetDictionary(segment, handle); if (!data.validity.RowIsValid(source_idx)) { - // null value is stored as -1 - result_data[target_idx] = 0; + // null value is stored as a copy of the last value, this is done to be able to efficiently do the + // string_length calculation + if (target_idx > 0) { + result_data[target_idx] = result_data[target_idx - 1]; + } else { + result_data[target_idx] = 0; + } } else { - auto dictionary = GetDictionary(segment, *handle); - auto end = handle->node->buffer + dictionary.end; + auto end = handle.Ptr() + dictionary.end; dictionary.Verify(); @@ -183274,7 +200565,7 @@ struct UncompressedStringStorage { // Unknown string, continue // non-null value, check if we can fit it within the block idx_t string_length = source_data[source_idx].GetSize(); - idx_t dictionary_length = string_length + sizeof(uint16_t); + idx_t dictionary_length = string_length; // determine whether or not we have space in the block for this string bool use_overflow_block = false; @@ -183307,20 +200598,21 @@ struct UncompressedStringStorage { // string fits in block, append to dictionary and increment dictionary position D_ASSERT(string_length < NumericLimits::Maximum()); dictionary.size += required_space; - auto dict_pos = end - dictionary.size; // first write the length as u16 - Store(string_length, dict_pos); + auto dict_pos = end - dictionary.size; // now write the actual string data into the dictionary - memcpy(dict_pos + sizeof(uint16_t), source_data[source_idx].GetDataUnsafe(), string_length); + memcpy(dict_pos, source_data[source_idx].GetDataUnsafe(), string_length); } - D_ASSERT(RemainingSpace(segment, *handle) <= Storage::BLOCK_SIZE); + D_ASSERT(RemainingSpace(segment, handle) <= Storage::BLOCK_SIZE); // place the dictionary offset into the set of vectors dictionary.Verify(); - result_data[target_idx] = dictionary.size; + // note: for overflow strings we write negative value + result_data[target_idx] = use_overflow_block ? -1 * dictionary.size : dictionary.size; + if (DUPLICATE_ELIMINATE) { seen_strings->insert({source_data[source_idx].GetString(), dictionary.size}); } - SetDictionary(segment, *handle, dictionary); + SetDictionary(segment, handle, dictionary); } } segment.count++; @@ -183342,36 +200634,32 @@ struct UncompressedStringStorage { static void WriteString(ColumnSegment &segment, string_t string, block_id_t &result_block, int32_t &result_offset); static void WriteStringMemory(ColumnSegment &segment, string_t string, block_id_t &result_block, int32_t &result_offset); - static string_t ReadString(ColumnSegment &segment, Vector &result, block_id_t block, int32_t offset); - static string_t ReadString(data_ptr_t target, int32_t offset); + static string_t ReadOverflowString(ColumnSegment &segment, Vector &result, block_id_t block, int32_t offset); + static string_t ReadString(data_ptr_t target, int32_t offset, uint32_t string_length); + static string_t ReadStringWithLength(data_ptr_t target, int32_t offset); static void WriteStringMarker(data_ptr_t target, block_id_t block_id, int32_t offset); static void ReadStringMarker(data_ptr_t target, block_id_t &block_id, int32_t &offset); static string_location_t FetchStringLocation(StringDictionaryContainer dict, data_ptr_t baseptr, int32_t dict_offset); static string_t FetchStringFromDict(ColumnSegment &segment, StringDictionaryContainer dict, Vector &result, - data_ptr_t baseptr, int32_t dict_offset); + data_ptr_t baseptr, int32_t dict_offset, uint32_t string_length); static string_t FetchString(ColumnSegment &segment, StringDictionaryContainer dict, Vector &result, - data_ptr_t baseptr, string_location_t location); + data_ptr_t baseptr, string_location_t location, uint32_t string_length); }; } // namespace duckdb -namespace duckdb { -struct StringHash { - std::size_t operator()(const string &k) const { - return Hash(k.c_str(), k.size()); - } -}; +namespace duckdb { // Abstract class for keeping compression state either for compression or size analysis class DictionaryCompressionState : public CompressionState { public: bool UpdateState(Vector &scan_vector, idx_t count) { - VectorData vdata; - scan_vector.Orrify(count, vdata); + UnifiedVectorFormat vdata; + scan_vector.ToUnifiedFormat(count, vdata); auto data = (string_t *)vdata.data; Verify(); @@ -183487,6 +200775,28 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { CreateEmptySegment(checkpointer.GetRowGroup().start); } + ColumnDataCheckpointer &checkpointer; + CompressionFunction *function; + + // State regarding current segment + unique_ptr current_segment; + BufferHandle current_handle; + StringDictionaryContainer current_dictionary; + data_ptr_t current_end_ptr; + + // Buffers and map for current segment + StringHeap heap; + string_map_t current_string_map; + std::vector index_buffer; + std::vector selection_buffer; + + bitpacking_width_t current_width = 0; + bitpacking_width_t next_width = 0; + + // Result of latest LookupString call + uint32_t latest_lookup_result; + +public: void CreateEmptySegment(idx_t row_start) { auto &db = checkpointer.GetDatabase(); auto &type = checkpointer.GetType(); @@ -183507,30 +200817,10 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { // Reset the pointers into the current segment auto &buffer_manager = BufferManager::GetBufferManager(current_segment->db); current_handle = buffer_manager.Pin(current_segment->block); - current_dictionary = DictionaryCompressionStorage::GetDictionary(*current_segment, *current_handle); - current_end_ptr = current_handle->node->buffer + current_dictionary.end; + current_dictionary = DictionaryCompressionStorage::GetDictionary(*current_segment, current_handle); + current_end_ptr = current_handle.Ptr() + current_dictionary.end; } - ColumnDataCheckpointer &checkpointer; - CompressionFunction *function; - - // State regarding current segment - unique_ptr current_segment; - unique_ptr current_handle; - StringDictionaryContainer current_dictionary; - data_ptr_t current_end_ptr; - - // Buffers and map for current segment - std::unordered_map current_string_map; - std::vector index_buffer; - std::vector selection_buffer; - - bitpacking_width_t current_width = 0; - bitpacking_width_t next_width = 0; - - // Result of latest LookupString call - uint32_t latest_lookup_result; - void Verify() override { current_dictionary.Verify(); D_ASSERT(current_segment->count == selection_buffer.size()); @@ -183541,7 +200831,7 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { } bool LookupString(string_t str) override { - auto search = current_string_map.find(str.GetString()); + auto search = current_string_map.find(str); auto has_result = search != current_string_map.end(); if (has_result) { @@ -183563,8 +200853,12 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { // Update buffers and map index_buffer.push_back(current_dictionary.size); selection_buffer.push_back(index_buffer.size() - 1); - current_string_map.insert({str.GetString(), index_buffer.size() - 1}); - DictionaryCompressionStorage::SetDictionary(*current_segment, *current_handle, current_dictionary); + if (str.IsInlined()) { + current_string_map.insert({str, index_buffer.size() - 1}); + } else { + current_string_map.insert({heap.AddBlob(str), index_buffer.size() - 1}); + } + DictionaryCompressionStorage::SetDictionary(*current_segment, current_handle, current_dictionary); current_width = next_width; current_segment->count++; @@ -183617,7 +200911,7 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { index_buffer_size + current_dictionary.size; // calculate ptr and offsets - auto base_ptr = handle->node->buffer; + auto base_ptr = handle.Ptr(); auto header_ptr = (dictionary_compression_header_t *)base_ptr; auto compressed_selection_buffer_offset = DictionaryCompressionStorage::DICTIONARY_HEADER_SIZE; auto index_buffer_offset = compressed_selection_buffer_offset + compressed_selection_buffer_size; @@ -183654,7 +200948,7 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { current_dictionary.end -= move_amount; D_ASSERT(current_dictionary.end == total_size); // write the new dictionary (with the updated "end") - DictionaryCompressionStorage::SetDictionary(*current_segment, *handle, current_dictionary); + DictionaryCompressionStorage::SetDictionary(*current_segment, handle, current_dictionary); return total_size; } }; @@ -183662,8 +200956,8 @@ struct DictionaryCompressionCompressState : public DictionaryCompressionState { //===--------------------------------------------------------------------===// // Analyze //===--------------------------------------------------------------------===// -struct DictionaryCompressionAnalyzeState : public AnalyzeState, DictionaryCompressionState { - DictionaryCompressionAnalyzeState() +struct DictionaryAnalyzeState : public DictionaryCompressionState { + DictionaryAnalyzeState() : segment_count(0), current_tuple_count(0), current_unique_count(0), current_dict_size(0), current_width(0), next_width(0) { } @@ -183672,19 +200966,24 @@ struct DictionaryCompressionAnalyzeState : public AnalyzeState, DictionaryCompre idx_t current_tuple_count; idx_t current_unique_count; size_t current_dict_size; - std::unordered_set current_set; + StringHeap heap; + string_set_t current_set; bitpacking_width_t current_width; bitpacking_width_t next_width; bool LookupString(string_t str) override { - return current_set.count(str.GetString()); + return current_set.count(str); } void AddNewString(string_t str) override { current_tuple_count++; current_unique_count++; current_dict_size += str.GetSize(); - current_set.insert(str.GetString()); + if (str.IsInlined()) { + current_set.insert(str); + } else { + current_set.insert(heap.AddBlob(str)); + } current_width = next_width; } @@ -183718,17 +201017,25 @@ struct DictionaryCompressionAnalyzeState : public AnalyzeState, DictionaryCompre void Verify() override {}; }; +struct DictionaryCompressionAnalyzeState : public AnalyzeState { + DictionaryCompressionAnalyzeState() : analyze_state(make_unique()) { + } + + unique_ptr analyze_state; +}; + unique_ptr DictionaryCompressionStorage::StringInitAnalyze(ColumnData &col_data, PhysicalType type) { return make_unique(); } bool DictionaryCompressionStorage::StringAnalyze(AnalyzeState &state_p, Vector &input, idx_t count) { auto &state = (DictionaryCompressionAnalyzeState &)state_p; - return state.UpdateState(input, count); + return state.analyze_state->UpdateState(input, count); } idx_t DictionaryCompressionStorage::StringFinalAnalyze(AnalyzeState &state_p) { - auto &state = (DictionaryCompressionAnalyzeState &)state_p; + auto &analyze_state = (DictionaryCompressionAnalyzeState &)state_p; + auto &state = *analyze_state.analyze_state; auto width = BitpackingPrimitives::MinimumBitWidth(state.current_unique_count + 1); auto req_space = @@ -183759,7 +201066,7 @@ void DictionaryCompressionStorage::FinalizeCompress(CompressionState &state_p) { // Scan //===--------------------------------------------------------------------===// struct CompressedStringScanState : public StringScanState { - unique_ptr handle; + BufferHandle handle; buffer_ptr dictionary; bitpacking_width_t current_width; buffer_ptr sel_vec; @@ -183771,10 +201078,10 @@ unique_ptr DictionaryCompressionStorage::StringInitScan(Column auto &buffer_manager = BufferManager::GetBufferManager(segment.db); state->handle = buffer_manager.Pin(segment.block); - auto baseptr = state->handle->node->buffer + segment.GetBlockOffset(); + auto baseptr = state->handle.Ptr() + segment.GetBlockOffset(); // Load header values - auto dict = DictionaryCompressionStorage::GetDictionary(segment, *(state->handle)); + auto dict = DictionaryCompressionStorage::GetDictionary(segment, state->handle); auto header_ptr = (dictionary_compression_header_t *)baseptr; auto index_buffer_offset = Load((data_ptr_t)&header_ptr->index_buffer_offset); auto index_buffer_count = Load((data_ptr_t)&header_ptr->index_buffer_count); @@ -183804,8 +201111,8 @@ void DictionaryCompressionStorage::StringScanPartial(ColumnSegment &segment, Col auto &scan_state = (CompressedStringScanState &)*state.scan_state; auto start = segment.GetRelativeIndex(state.row_index); - auto baseptr = scan_state.handle->node->buffer + segment.GetBlockOffset(); - auto dict = DictionaryCompressionStorage::GetDictionary(segment, *scan_state.handle); + auto baseptr = scan_state.handle.Ptr() + segment.GetBlockOffset(); + auto dict = DictionaryCompressionStorage::GetDictionary(segment, scan_state.handle); auto header_ptr = (dictionary_compression_header_t *)baseptr; auto index_buffer_offset = Load((data_ptr_t)&header_ptr->index_buffer_offset); @@ -183879,24 +201186,11 @@ void DictionaryCompressionStorage::StringFetchRow(ColumnSegment &segment, Column Vector &result, idx_t result_idx) { // fetch a single row from the string segment // first pin the main buffer if it is not already pinned - auto primary_id = segment.block->BlockId(); + auto &handle = state.GetOrInsertHandle(segment); - BufferHandle *handle_ptr; - auto entry = state.handles.find(primary_id); - if (entry == state.handles.end()) { - // not pinned yet: pin it - auto &buffer_manager = BufferManager::GetBufferManager(segment.db); - auto handle = buffer_manager.Pin(segment.block); - handle_ptr = handle.get(); - state.handles[primary_id] = move(handle); - } else { - // already pinned: use the pinned handle - handle_ptr = entry->second.get(); - } - - auto baseptr = handle_ptr->node->buffer + segment.GetBlockOffset(); + auto baseptr = handle.Ptr() + segment.GetBlockOffset(); auto header_ptr = (dictionary_compression_header_t *)baseptr; - auto dict = DictionaryCompressionStorage::GetDictionary(segment, *handle_ptr); + auto dict = DictionaryCompressionStorage::GetDictionary(segment, handle); auto index_buffer_offset = Load((data_ptr_t)&header_ptr->index_buffer_offset); auto width = (bitpacking_width_t)(Load((data_ptr_t)&header_ptr->bitpacking_width)); auto index_buffer_ptr = (uint32_t *)(baseptr + index_buffer_offset); @@ -183939,7 +201233,7 @@ idx_t DictionaryCompressionStorage::RequiredSpace(idx_t current_count, idx_t ind } StringDictionaryContainer DictionaryCompressionStorage::GetDictionary(ColumnSegment &segment, BufferHandle &handle) { - auto header_ptr = (dictionary_compression_header_t *)(handle.node->buffer + segment.GetBlockOffset()); + auto header_ptr = (dictionary_compression_header_t *)(handle.Ptr() + segment.GetBlockOffset()); StringDictionaryContainer container; container.size = Load((data_ptr_t)&header_ptr->dict_size); container.end = Load((data_ptr_t)&header_ptr->dict_end); @@ -183948,7 +201242,7 @@ StringDictionaryContainer DictionaryCompressionStorage::GetDictionary(ColumnSegm void DictionaryCompressionStorage::SetDictionary(ColumnSegment &segment, BufferHandle &handle, StringDictionaryContainer container) { - auto header_ptr = (dictionary_compression_header_t *)(handle.node->buffer + segment.GetBlockOffset()); + auto header_ptr = (dictionary_compression_header_t *)(handle.Ptr() + segment.GetBlockOffset()); Store(container.size, (data_ptr_t)&header_ptr->dict_size); Store(container.end, (data_ptr_t)&header_ptr->dict_end); } @@ -184005,6 +201299,7 @@ bool DictionaryCompressionFun::TypeIsSupported(PhysicalType type) { + namespace duckdb { //===--------------------------------------------------------------------===// @@ -184069,8 +201364,8 @@ unique_ptr UncompressedFunctions::InitCompression(ColumnDataCh void UncompressedFunctions::Compress(CompressionState &state_p, Vector &data, idx_t count) { auto &state = (UncompressedCompressState &)state_p; - VectorData vdata; - data.Orrify(count, vdata); + UnifiedVectorFormat vdata; + data.ToUnifiedFormat(count, vdata); ColumnAppendState append_state; idx_t offset = 0; @@ -184100,7 +201395,7 @@ void UncompressedFunctions::FinalizeCompress(CompressionState &state_p) { // Scan //===--------------------------------------------------------------------===// struct FixedSizeScanState : public SegmentScanState { - unique_ptr handle; + BufferHandle handle; }; unique_ptr FixedSizeInitScan(ColumnSegment &segment) { @@ -184119,7 +201414,7 @@ void FixedSizeScanPartial(ColumnSegment &segment, ColumnScanState &state, idx_t auto &scan_state = (FixedSizeScanState &)*state.scan_state; auto start = segment.GetRelativeIndex(state.row_index); - auto data = scan_state.handle->node->buffer + segment.GetBlockOffset(); + auto data = scan_state.handle.Ptr() + segment.GetBlockOffset(); auto source_data = data + start * sizeof(T); // copy the data from the base table @@ -184132,7 +201427,7 @@ void FixedSizeScan(ColumnSegment &segment, ColumnScanState &state, idx_t scan_co auto &scan_state = (FixedSizeScanState &)*state.scan_state; auto start = segment.GetRelativeIndex(state.row_index); - auto data = scan_state.handle->node->buffer + segment.GetBlockOffset(); + auto data = scan_state.handle.Ptr() + segment.GetBlockOffset(); auto source_data = data + start * sizeof(T); result.SetVectorType(VectorType::FLAT_VECTOR); @@ -184155,7 +201450,7 @@ void FixedSizeFetchRow(ColumnSegment &segment, ColumnFetchState &state, row_t ro auto handle = buffer_manager.Pin(segment.block); // first fetch the data from the base table - auto data_ptr = handle->node->buffer + segment.GetBlockOffset() + row_id * sizeof(T); + auto data_ptr = handle.Ptr() + segment.GetBlockOffset() + row_id * sizeof(T); memcpy(FlatVector::GetData(result) + result_idx * sizeof(T), data_ptr, sizeof(T)); } @@ -184164,7 +201459,7 @@ void FixedSizeFetchRow(ColumnSegment &segment, ColumnFetchState &state, row_t ro // Append //===--------------------------------------------------------------------===// template -static void AppendLoop(SegmentStatistics &stats, data_ptr_t target, idx_t target_offset, VectorData &adata, +static void AppendLoop(SegmentStatistics &stats, data_ptr_t target, idx_t target_offset, UnifiedVectorFormat &adata, idx_t offset, idx_t count) { auto sdata = (T *)adata.data; auto tdata = (T *)target; @@ -184193,8 +201488,8 @@ static void AppendLoop(SegmentStatistics &stats, data_ptr_t target, idx_t target } template <> -void AppendLoop(SegmentStatistics &stats, data_ptr_t target, idx_t target_offset, VectorData &adata, - idx_t offset, idx_t count) { +void AppendLoop(SegmentStatistics &stats, data_ptr_t target, idx_t target_offset, + UnifiedVectorFormat &adata, idx_t offset, idx_t count) { auto sdata = (list_entry_t *)adata.data; auto tdata = (list_entry_t *)target; for (idx_t i = 0; i < count; i++) { @@ -184205,12 +201500,13 @@ void AppendLoop(SegmentStatistics &stats, data_ptr_t target, idx_t } template -idx_t FixedSizeAppend(ColumnSegment &segment, SegmentStatistics &stats, VectorData &data, idx_t offset, idx_t count) { +idx_t FixedSizeAppend(ColumnSegment &segment, SegmentStatistics &stats, UnifiedVectorFormat &data, idx_t offset, + idx_t count) { auto &buffer_manager = BufferManager::GetBufferManager(segment.db); auto handle = buffer_manager.Pin(segment.block); D_ASSERT(segment.GetBlockOffset() == 0); - auto target_ptr = handle->node->buffer; + auto target_ptr = handle.Ptr(); idx_t max_tuple_count = Storage::BLOCK_SIZE / sizeof(T); idx_t copy_count = MinValue(count, max_tuple_count - segment.count); @@ -184290,26 +201586,6 @@ unique_ptr ConstantInitScan(ColumnSegment &segment) { return nullptr; } -//===--------------------------------------------------------------------===// -// Scan base data -//===--------------------------------------------------------------------===// -void ConstantScanFunctionValidity(ColumnSegment &segment, ColumnScanState &state, idx_t scan_count, Vector &result) { - auto &validity = (ValidityStatistics &)*segment.stats.statistics; - if (validity.has_null) { - result.SetVectorType(VectorType::CONSTANT_VECTOR); - ConstantVector::SetNull(result, true); - } -} - -template -void ConstantScanFunction(ColumnSegment &segment, ColumnScanState &state, idx_t scan_count, Vector &result) { - auto &nstats = (NumericStatistics &)*segment.stats.statistics; - - auto data = FlatVector::GetData(result); - data[0] = nstats.min.GetValueUnsafe(); - result.SetVectorType(VectorType::CONSTANT_VECTOR); -} - //===--------------------------------------------------------------------===// // Scan Partial //===--------------------------------------------------------------------===// @@ -184345,6 +201621,31 @@ void ConstantScanPartial(ColumnSegment &segment, ColumnScanState &state, idx_t s ConstantFillFunction(segment, result, result_offset, scan_count); } +//===--------------------------------------------------------------------===// +// Scan base data +//===--------------------------------------------------------------------===// +void ConstantScanFunctionValidity(ColumnSegment &segment, ColumnScanState &state, idx_t scan_count, Vector &result) { + auto &validity = (ValidityStatistics &)*segment.stats.statistics; + if (validity.has_null) { + if (result.GetVectorType() == VectorType::CONSTANT_VECTOR) { + result.SetVectorType(VectorType::CONSTANT_VECTOR); + ConstantVector::SetNull(result, true); + } else { + result.Flatten(scan_count); + ConstantFillFunctionValidity(segment, result, 0, scan_count); + } + } +} + +template +void ConstantScanFunction(ColumnSegment &segment, ColumnScanState &state, idx_t scan_count, Vector &result) { + auto &nstats = (NumericStatistics &)*segment.stats.statistics; + + auto data = FlatVector::GetData(result); + data[0] = nstats.min.GetValueUnsafe(); + result.SetVectorType(VectorType::CONSTANT_VECTOR); +} + //===--------------------------------------------------------------------===// // Fetch //===--------------------------------------------------------------------===// @@ -184525,8 +201826,8 @@ unique_ptr RLEInitAnalyze(ColumnData &col_data, PhysicalType type) template bool RLEAnalyze(AnalyzeState &state, Vector &input, idx_t count) { auto &rle_state = (RLEAnalyzeState &)state; - VectorData vdata; - input.Orrify(count, vdata); + UnifiedVectorFormat vdata; + input.ToUnifiedFormat(count, vdata); auto data = (T *)vdata.data; for (idx_t i = 0; i < count; i++) { @@ -184587,7 +201888,7 @@ struct RLECompressState : public CompressionState { handle = buffer_manager.Pin(current_segment->block); } - void Append(VectorData &vdata, idx_t count) { + void Append(UnifiedVectorFormat &vdata, idx_t count) { auto data = (T *)vdata.data; for (idx_t i = 0; i < count; i++) { auto idx = vdata.sel->get_index(i); @@ -184597,7 +201898,7 @@ struct RLECompressState : public CompressionState { void WriteValue(T value, rle_count_t count, bool is_null) { // write the RLE entry - auto handle_ptr = handle->Ptr() + RLEConstants::RLE_HEADER_SIZE; + auto handle_ptr = handle.Ptr() + RLEConstants::RLE_HEADER_SIZE; auto data_pointer = (T *)handle_ptr; auto index_pointer = (rle_count_t *)(handle_ptr + max_rle_count * sizeof(T)); data_pointer[entry_count] = value; @@ -184626,10 +201927,11 @@ struct RLECompressState : public CompressionState { idx_t original_rle_offset = RLEConstants::RLE_HEADER_SIZE + max_rle_count * sizeof(T); idx_t minimal_rle_offset = AlignValue(RLEConstants::RLE_HEADER_SIZE + sizeof(T) * entry_count); idx_t total_segment_size = minimal_rle_offset + counts_size; - memmove(handle->node->buffer + minimal_rle_offset, handle->node->buffer + original_rle_offset, counts_size); + auto data_ptr = handle.Ptr(); + memmove(data_ptr + minimal_rle_offset, data_ptr + original_rle_offset, counts_size); // store the final RLE offset within the segment - Store(minimal_rle_offset, handle->node->buffer); - handle.reset(); + Store(minimal_rle_offset, data_ptr); + handle.Destroy(); auto &state = checkpointer.GetCheckpointState(); state.FlushSegment(move(current_segment), total_segment_size); @@ -184645,7 +201947,7 @@ struct RLECompressState : public CompressionState { ColumnDataCheckpointer &checkpointer; CompressionFunction *function; unique_ptr current_segment; - unique_ptr handle; + BufferHandle handle; RLEState state; idx_t entry_count = 0; @@ -184660,8 +201962,8 @@ unique_ptr RLEInitCompression(ColumnDataCheckpointer &checkpoi template void RLECompress(CompressionState &state_p, Vector &scan_vector, idx_t count) { auto &state = (RLECompressState &)state_p; - VectorData vdata; - scan_vector.Orrify(count, vdata); + UnifiedVectorFormat vdata; + scan_vector.ToUnifiedFormat(count, vdata); state.Append(vdata, count); } @@ -184682,12 +201984,12 @@ struct RLEScanState : public SegmentScanState { handle = buffer_manager.Pin(segment.block); entry_pos = 0; position_in_entry = 0; - rle_count_offset = Load(handle->node->buffer + segment.GetBlockOffset()); + rle_count_offset = Load(handle.Ptr() + segment.GetBlockOffset()); D_ASSERT(rle_count_offset <= Storage::BLOCK_SIZE); } void Skip(ColumnSegment &segment, idx_t skip_count) { - auto data = handle->node->buffer + segment.GetBlockOffset(); + auto data = handle.Ptr() + segment.GetBlockOffset(); auto index_pointer = (rle_count_t *)(data + rle_count_offset); for (idx_t i = 0; i < skip_count; i++) { @@ -184702,7 +202004,7 @@ struct RLEScanState : public SegmentScanState { } } - unique_ptr handle; + BufferHandle handle; uint32_t rle_offset; idx_t entry_pos; idx_t position_in_entry; @@ -184729,7 +202031,7 @@ void RLEScanPartial(ColumnSegment &segment, ColumnScanState &state, idx_t scan_c idx_t result_offset) { auto &scan_state = (RLEScanState &)*state.scan_state; - auto data = scan_state.handle->node->buffer + segment.GetBlockOffset(); + auto data = scan_state.handle.Ptr() + segment.GetBlockOffset(); auto data_pointer = (T *)(data + RLEConstants::RLE_HEADER_SIZE); auto index_pointer = (rle_count_t *)(data + scan_state.rle_count_offset); @@ -184762,7 +202064,7 @@ void RLEFetchRow(ColumnSegment &segment, ColumnFetchState &state, row_t row_id, RLEScanState scan_state(segment); scan_state.Skip(segment, row_id); - auto data = scan_state.handle->node->buffer + segment.GetBlockOffset(); + auto data = scan_state.handle.Ptr() + segment.GetBlockOffset(); auto data_pointer = (T *)(data + RLEConstants::RLE_HEADER_SIZE); auto result_data = FlatVector::GetData(result); result_data[result_idx] = data_pointer[scan_state.entry_pos]; @@ -184831,6 +202133,9 @@ bool RLEFun::TypeIsSupported(PhysicalType type) { } // namespace duckdb + + + namespace duckdb { //===--------------------------------------------------------------------===// @@ -184861,8 +202166,8 @@ unique_ptr UncompressedStringStorage::StringInitAnalyze(ColumnData bool UncompressedStringStorage::StringAnalyze(AnalyzeState &state_p, Vector &input, idx_t count) { auto &state = (StringAnalyzeState &)state_p; - VectorData vdata; - input.Orrify(count, vdata); + UnifiedVectorFormat vdata; + input.ToUnifiedFormat(count, vdata); state.count += count; auto data = (string_t *)vdata.data; @@ -184903,13 +202208,19 @@ void UncompressedStringStorage::StringScanPartial(ColumnSegment &segment, Column auto &scan_state = (StringScanState &)*state.scan_state; auto start = segment.GetRelativeIndex(state.row_index); - auto baseptr = scan_state.handle->node->buffer + segment.GetBlockOffset(); - auto dict = GetDictionary(segment, *scan_state.handle); + auto baseptr = scan_state.handle.Ptr() + segment.GetBlockOffset(); + auto dict = GetDictionary(segment, scan_state.handle); auto base_data = (int32_t *)(baseptr + DICTIONARY_HEADER_SIZE); auto result_data = FlatVector::GetData(result); + int32_t previous_offset = start > 0 ? base_data[start - 1] : 0; + for (idx_t i = 0; i < scan_count; i++) { - result_data[result_offset + i] = FetchStringFromDict(segment, dict, result, baseptr, base_data[start + i]); + // std::abs used since offsets can be negative to indicate big strings + uint32_t string_length = std::abs(base_data[start + i]) - std::abs(previous_offset); + result_data[result_offset + i] = + FetchStringFromDict(segment, dict, result, baseptr, base_data[start + i], string_length); + previous_offset = base_data[start + i]; } } @@ -184921,30 +202232,42 @@ void UncompressedStringStorage::StringScan(ColumnSegment &segment, ColumnScanSta //===--------------------------------------------------------------------===// // Fetch //===--------------------------------------------------------------------===// -void UncompressedStringStorage::StringFetchRow(ColumnSegment &segment, ColumnFetchState &state, row_t row_id, - Vector &result, idx_t result_idx) { - // fetch a single row from the string segment - // first pin the main buffer if it is not already pinned +BufferHandle &ColumnFetchState::GetOrInsertHandle(ColumnSegment &segment) { auto primary_id = segment.block->BlockId(); - BufferHandle *handle_ptr; - auto entry = state.handles.find(primary_id); - if (entry == state.handles.end()) { + auto entry = handles.find(primary_id); + if (entry == handles.end()) { // not pinned yet: pin it auto &buffer_manager = BufferManager::GetBufferManager(segment.db); auto handle = buffer_manager.Pin(segment.block); - handle_ptr = handle.get(); - state.handles[primary_id] = move(handle); + auto entry = handles.insert(make_pair(primary_id, move(handle))); + return entry.first->second; } else { // already pinned: use the pinned handle - handle_ptr = entry->second.get(); + return entry->second; } - auto baseptr = handle_ptr->node->buffer + segment.GetBlockOffset(); - auto dict = GetDictionary(segment, *handle_ptr); +} + +void UncompressedStringStorage::StringFetchRow(ColumnSegment &segment, ColumnFetchState &state, row_t row_id, + Vector &result, idx_t result_idx) { + // fetch a single row from the string segment + // first pin the main buffer if it is not already pinned + auto &handle = state.GetOrInsertHandle(segment); + + auto baseptr = handle.Ptr() + segment.GetBlockOffset(); + auto dict = GetDictionary(segment, handle); auto base_data = (int32_t *)(baseptr + DICTIONARY_HEADER_SIZE); auto result_data = FlatVector::GetData(result); - result_data[result_idx] = FetchStringFromDict(segment, dict, result, baseptr, base_data[row_id]); + auto dict_offset = base_data[row_id]; + uint32_t string_length; + if ((idx_t)row_id == 0) { + // edge case where this is the first string in the dict + string_length = std::abs(dict_offset); + } else { + string_length = std::abs(dict_offset) - std::abs(base_data[row_id - 1]); + } + result_data[result_idx] = FetchStringFromDict(segment, dict, result, baseptr, dict_offset, string_length); } //===--------------------------------------------------------------------===// @@ -184958,7 +202281,7 @@ unique_ptr UncompressedStringStorage::StringInitSegment( StringDictionaryContainer dictionary; dictionary.size = 0; dictionary.end = Storage::BLOCK_SIZE; - SetDictionary(segment, *handle, dictionary); + SetDictionary(segment, handle, dictionary); } return make_unique(); } @@ -184966,7 +202289,7 @@ unique_ptr UncompressedStringStorage::StringInitSegment( idx_t UncompressedStringStorage::FinalizeAppend(ColumnSegment &segment, SegmentStatistics &stats) { auto &buffer_manager = BufferManager::GetBufferManager(segment.db); auto handle = buffer_manager.Pin(segment.block); - auto dict = GetDictionary(segment, *handle); + auto dict = GetDictionary(segment, handle); D_ASSERT(dict.end == Storage::BLOCK_SIZE); // compute the total size required to store this segment auto offset_size = DICTIONARY_HEADER_SIZE + segment.count * sizeof(int32_t); @@ -184978,11 +202301,12 @@ idx_t UncompressedStringStorage::FinalizeAppend(ColumnSegment &segment, SegmentS // the block has space left: figure out how much space we can save auto move_amount = Storage::BLOCK_SIZE - total_size; // move the dictionary so it lines up exactly with the offsets - memmove(handle->node->buffer + offset_size, handle->node->buffer + dict.end - dict.size, dict.size); + auto dataptr = handle.Ptr(); + memmove(dataptr + offset_size, dataptr + dict.end - dict.size, dict.size); dict.end -= move_amount; D_ASSERT(dict.end == total_size); // write the new dictionary (with the updated "end") - SetDictionary(segment, *handle, dict); + SetDictionary(segment, handle, dict); return total_size; } @@ -185006,13 +202330,13 @@ CompressionFunction StringUncompressed::GetFunction(PhysicalType data_type) { //===--------------------------------------------------------------------===// void UncompressedStringStorage::SetDictionary(ColumnSegment &segment, BufferHandle &handle, StringDictionaryContainer container) { - auto startptr = handle.node->buffer + segment.GetBlockOffset(); + auto startptr = handle.Ptr() + segment.GetBlockOffset(); Store(container.size, startptr); Store(container.end, startptr + sizeof(uint32_t)); } StringDictionaryContainer UncompressedStringStorage::GetDictionary(ColumnSegment &segment, BufferHandle &handle) { - auto startptr = handle.node->buffer + segment.GetBlockOffset(); + auto startptr = handle.Ptr() + segment.GetBlockOffset(); StringDictionaryContainer container; container.size = Load(startptr); container.end = Load(startptr + sizeof(uint32_t)); @@ -185043,7 +202367,7 @@ void UncompressedStringStorage::WriteStringMemory(ColumnSegment &segment, string int32_t &result_offset) { uint32_t total_length = string.GetSize() + sizeof(uint32_t); shared_ptr block; - unique_ptr handle; + BufferHandle handle; auto &buffer_manager = BufferManager::GetBufferManager(segment.db); auto &state = (UncompressedStringSegmentState &)*segment.GetSegmentState(); @@ -185071,15 +202395,15 @@ void UncompressedStringStorage::WriteStringMemory(ColumnSegment &segment, string result_offset = state.head->offset; // copy the string and the length there - auto ptr = handle->node->buffer + state.head->offset; + auto ptr = handle.Ptr() + state.head->offset; Store(string.GetSize(), ptr); ptr += sizeof(uint32_t); memcpy(ptr, string.GetDataUnsafe(), string.GetSize()); state.head->offset += total_length; } -string_t UncompressedStringStorage::ReadString(ColumnSegment &segment, Vector &result, block_id_t block, - int32_t offset) { +string_t UncompressedStringStorage::ReadOverflowString(ColumnSegment &segment, Vector &result, block_id_t block, + int32_t offset) { D_ASSERT(block != INVALID_BLOCK); D_ASSERT(offset < Storage::BLOCK_SIZE); @@ -185091,50 +202415,71 @@ string_t UncompressedStringStorage::ReadString(ColumnSegment &segment, Vector &r auto block_handle = buffer_manager.RegisterBlock(block); auto handle = buffer_manager.Pin(block_handle); - uint32_t length = Load(handle->node->buffer + offset); - uint32_t remaining = length; - offset += sizeof(uint32_t); - - // allocate a buffer to store the string - auto alloc_size = MaxValue(Storage::BLOCK_SIZE, length + sizeof(uint32_t)); - auto target_handle = buffer_manager.Allocate(alloc_size); - auto target_ptr = target_handle->node->buffer; - // write the length in this block as well - Store(length, target_ptr); - target_ptr += sizeof(uint32_t); - // now append the string to the single buffer - while (remaining > 0) { - idx_t to_write = MinValue(remaining, Storage::BLOCK_SIZE - sizeof(block_id_t) - offset); - memcpy(target_ptr, handle->node->buffer + offset, to_write); + // read header + uint32_t compressed_size = Load(handle.Ptr() + offset); + uint32_t uncompressed_size = Load(handle.Ptr() + offset + sizeof(uint32_t)); + uint32_t remaining = compressed_size; + offset += 2 * sizeof(uint32_t); - remaining -= to_write; - offset += to_write; - target_ptr += to_write; - if (remaining > 0) { - // read the next block - block_id_t next_block = Load(handle->node->buffer + offset); - block_handle = buffer_manager.RegisterBlock(next_block); - handle = buffer_manager.Pin(block_handle); - offset = 0; + data_ptr_t decompression_ptr; + std::unique_ptr decompression_buffer; + + // If string is in single block we decompress straight from it, else we copy first + if (remaining <= Storage::BLOCK_SIZE - sizeof(block_id_t) - offset) { + decompression_ptr = handle.Ptr() + offset; + } else { + decompression_buffer = std::unique_ptr(new data_t[compressed_size]); + auto target_ptr = decompression_buffer.get(); + + // now append the string to the single buffer + while (remaining > 0) { + idx_t to_write = MinValue(remaining, Storage::BLOCK_SIZE - sizeof(block_id_t) - offset); + memcpy(target_ptr, handle.Ptr() + offset, to_write); + + remaining -= to_write; + offset += to_write; + target_ptr += to_write; + if (remaining > 0) { + // read the next block + block_id_t next_block = Load(handle.Ptr() + offset); + block_handle = buffer_manager.RegisterBlock(next_block); + handle = buffer_manager.Pin(block_handle); + offset = 0; + } } + decompression_ptr = decompression_buffer.get(); } - auto final_buffer = target_handle->node->buffer; - StringVector::AddHandle(result, move(target_handle)); - return ReadString(final_buffer, 0); + // overflow strings on disk are gzipped, decompress here + auto decompressed_target_handle = + buffer_manager.Allocate(MaxValue(Storage::BLOCK_SIZE, uncompressed_size)); + auto decompressed_target_ptr = decompressed_target_handle.Ptr(); + MiniZStream s; + s.Decompress((const char *)decompression_ptr, compressed_size, (char *)decompressed_target_ptr, + uncompressed_size); + + auto final_buffer = decompressed_target_handle.Ptr(); + StringVector::AddHandle(result, move(decompressed_target_handle)); + return ReadString(final_buffer, 0, uncompressed_size); } else { // read the overflow string from memory // first pin the handle, if it is not pinned yet auto entry = state.overflow_blocks.find(block); D_ASSERT(entry != state.overflow_blocks.end()); auto handle = buffer_manager.Pin(entry->second->block); - auto final_buffer = handle->node->buffer; + auto final_buffer = handle.Ptr(); StringVector::AddHandle(result, move(handle)); - return ReadString(final_buffer, offset); + return ReadStringWithLength(final_buffer, offset); } } -string_t UncompressedStringStorage::ReadString(data_ptr_t target, int32_t offset) { +string_t UncompressedStringStorage::ReadString(data_ptr_t target, int32_t offset, uint32_t string_length) { + auto ptr = target + offset; + auto str_ptr = (char *)(ptr); + return string_t(str_ptr, string_length); +} + +string_t UncompressedStringStorage::ReadStringWithLength(data_ptr_t target, int32_t offset) { auto ptr = target + offset; auto str_length = Load(ptr); auto str_ptr = (char *)(ptr + sizeof(uint32_t)); @@ -185142,16 +202487,12 @@ string_t UncompressedStringStorage::ReadString(data_ptr_t target, int32_t offset } void UncompressedStringStorage::WriteStringMarker(data_ptr_t target, block_id_t block_id, int32_t offset) { - uint16_t length = BIG_STRING_MARKER; - memcpy(target, &length, sizeof(uint16_t)); - target += sizeof(uint16_t); memcpy(target, &block_id, sizeof(block_id_t)); target += sizeof(block_id_t); memcpy(target, &offset, sizeof(int32_t)); } void UncompressedStringStorage::ReadStringMarker(data_ptr_t target, block_id_t &block_id, int32_t &offset) { - target += sizeof(uint16_t); memcpy(&block_id, target, sizeof(block_id_t)); target += sizeof(block_id_t); memcpy(&offset, target, sizeof(int32_t)); @@ -185159,37 +202500,31 @@ void UncompressedStringStorage::ReadStringMarker(data_ptr_t target, block_id_t & string_location_t UncompressedStringStorage::FetchStringLocation(StringDictionaryContainer dict, data_ptr_t baseptr, int32_t dict_offset) { - D_ASSERT(dict_offset >= 0 && dict_offset <= Storage::BLOCK_SIZE); - if (dict_offset == 0) { - return string_location_t(INVALID_BLOCK, 0); - } - // look up result in dictionary - auto dict_end = baseptr + dict.end; - auto dict_pos = dict_end - dict_offset; - auto string_length = Load(dict_pos); - string_location_t result; - if (string_length == BIG_STRING_MARKER) { - ReadStringMarker(dict_pos, result.block_id, result.offset); + D_ASSERT(dict_offset >= -1 * Storage::BLOCK_SIZE && dict_offset <= Storage::BLOCK_SIZE); + if (dict_offset < 0) { + string_location_t result; + ReadStringMarker(baseptr + dict.end - (-1 * dict_offset), result.block_id, result.offset); + return result; } else { - result.block_id = INVALID_BLOCK; - result.offset = dict_offset; + return string_location_t(INVALID_BLOCK, dict_offset); } - return result; } string_t UncompressedStringStorage::FetchStringFromDict(ColumnSegment &segment, StringDictionaryContainer dict, - Vector &result, data_ptr_t baseptr, int32_t dict_offset) { + Vector &result, data_ptr_t baseptr, int32_t dict_offset, + uint32_t string_length) { // fetch base data D_ASSERT(dict_offset <= Storage::BLOCK_SIZE); string_location_t location = FetchStringLocation(dict, baseptr, dict_offset); - return FetchString(segment, dict, result, baseptr, location); + return FetchString(segment, dict, result, baseptr, location, string_length); } string_t UncompressedStringStorage::FetchString(ColumnSegment &segment, StringDictionaryContainer dict, Vector &result, - data_ptr_t baseptr, string_location_t location) { + data_ptr_t baseptr, string_location_t location, + uint32_t string_length) { if (location.block_id != INVALID_BLOCK) { // big string marker: read from separate block - return ReadString(segment, result, location.block_id, location.offset); + return ReadOverflowString(segment, result, location.block_id, location.offset); } else { if (location.offset == 0) { return string_t(nullptr, 0); @@ -185197,9 +202532,8 @@ string_t UncompressedStringStorage::FetchString(ColumnSegment &segment, StringDi // normal string: read string from this block auto dict_end = baseptr + dict.end; auto dict_pos = dict_end - location.offset; - auto string_length = Load(dict_pos); - auto str_ptr = (char *)(dict_pos + sizeof(uint16_t)); + auto str_ptr = (char *)(dict_pos); return string_t(str_ptr, string_length); } } @@ -185445,7 +202779,7 @@ idx_t ValidityFinalAnalyze(AnalyzeState &state_p) { // Scan //===--------------------------------------------------------------------===// struct ValidityScanState : public SegmentScanState { - unique_ptr handle; + BufferHandle handle; }; unique_ptr ValidityInitScan(ColumnSegment &segment) { @@ -185466,7 +202800,7 @@ void ValidityScanPartial(ColumnSegment &segment, ColumnScanState &state, idx_t s auto &scan_state = (ValidityScanState &)*state.scan_state; auto &result_mask = FlatVector::Validity(result); - auto buffer_ptr = scan_state.handle->node->buffer + segment.GetBlockOffset(); + auto buffer_ptr = scan_state.handle.Ptr() + segment.GetBlockOffset(); auto input_data = (validity_t *)buffer_ptr; #ifdef DEBUG @@ -185581,7 +202915,7 @@ void ValidityScanPartial(ColumnSegment &segment, ColumnScanState &state, idx_t s } void ValidityScan(ColumnSegment &segment, ColumnScanState &state, idx_t scan_count, Vector &result) { - result.Normalify(scan_count); + result.Flatten(scan_count); auto start = segment.GetRelativeIndex(state.row_index); if (start % ValidityMask::BITS_PER_VALUE == 0) { @@ -185591,7 +202925,7 @@ void ValidityScan(ColumnSegment &segment, ColumnScanState &state, idx_t scan_cou // note: this is only an optimization which avoids having to do messy bitshifting in the common case // it is not required for correctness auto &result_mask = FlatVector::Validity(result); - auto buffer_ptr = scan_state.handle->node->buffer + segment.GetBlockOffset(); + auto buffer_ptr = scan_state.handle.Ptr() + segment.GetBlockOffset(); auto input_data = (validity_t *)buffer_ptr; auto result_data = (validity_t *)result_mask.GetData(); idx_t start_offset = start / ValidityMask::BITS_PER_VALUE; @@ -185620,7 +202954,7 @@ void ValidityFetchRow(ColumnSegment &segment, ColumnFetchState &state, row_t row D_ASSERT(row_id >= 0 && row_id < row_t(segment.count)); auto &buffer_manager = BufferManager::GetBufferManager(segment.db); auto handle = buffer_manager.Pin(segment.block); - auto dataptr = handle->node->buffer + segment.GetBlockOffset(); + auto dataptr = handle.Ptr() + segment.GetBlockOffset(); ValidityMask mask((validity_t *)dataptr); auto &result_mask = FlatVector::Validity(result); if (!mask.RowIsValidUnsafe(row_id)) { @@ -185635,12 +202969,13 @@ unique_ptr ValidityInitSegment(ColumnSegment &segment, b auto &buffer_manager = BufferManager::GetBufferManager(segment.db); if (block_id == INVALID_BLOCK) { auto handle = buffer_manager.Pin(segment.block); - memset(handle->node->buffer, 0xFF, Storage::BLOCK_SIZE); + memset(handle.Ptr(), 0xFF, Storage::BLOCK_SIZE); } return nullptr; } -idx_t ValidityAppend(ColumnSegment &segment, SegmentStatistics &stats, VectorData &data, idx_t offset, idx_t vcount) { +idx_t ValidityAppend(ColumnSegment &segment, SegmentStatistics &stats, UnifiedVectorFormat &data, idx_t offset, + idx_t vcount) { D_ASSERT(segment.GetBlockOffset() == 0); auto &validity_stats = (ValidityStatistics &)*stats.statistics; @@ -185655,7 +202990,7 @@ idx_t ValidityAppend(ColumnSegment &segment, SegmentStatistics &stats, VectorDat auto &buffer_manager = BufferManager::GetBufferManager(segment.db); auto handle = buffer_manager.Pin(segment.block); - ValidityMask mask((validity_t *)handle->node->buffer); + ValidityMask mask((validity_t *)handle.Ptr()); for (idx_t i = 0; i < append_count; i++) { auto idx = data.sel->get_index(offset + i); if (!data.validity.RowIsValidUnsafe(idx)) { @@ -185684,7 +203019,7 @@ void ValidityRevertAppend(ColumnSegment &segment, idx_t start_row) { idx_t byte_pos = start_bit / 8; idx_t bit_start = byte_pos * 8; idx_t bit_end = (byte_pos + 1) * 8; - ValidityMask mask((validity_t *)handle->node->buffer + byte_pos); + ValidityMask mask((validity_t *)handle.Ptr() + byte_pos); for (idx_t i = start_bit; i < bit_end; i++) { mask.SetValid(i - bit_start); } @@ -185693,7 +203028,7 @@ void ValidityRevertAppend(ColumnSegment &segment, idx_t start_row) { revert_start = start_bit / 8; } // for the rest, we just memset - memset(handle->node->buffer + revert_start, 0xFF, Storage::BLOCK_SIZE - revert_start); + memset(handle.Ptr() + revert_start, 0xFF, Storage::BLOCK_SIZE - revert_start); } //===--------------------------------------------------------------------===// @@ -185726,6 +203061,7 @@ CompressionFunction ValidityUncompressed::GetFunction(PhysicalType data_type) { + //===----------------------------------------------------------------------===// // DuckDB // @@ -185785,7 +203121,7 @@ class StandardColumnData : public ColumnData { idx_t ScanCount(ColumnScanState &state, Vector &result, idx_t count) override; void InitializeAppend(ColumnAppendState &state) override; - void AppendData(BaseStatistics &stats, ColumnAppendState &state, VectorData &vdata, idx_t count) override; + void AppendData(BaseStatistics &stats, ColumnAppendState &state, UnifiedVectorFormat &vdata, idx_t count) override; void RevertAppend(row_t start_row) override; idx_t Fetch(ColumnScanState &state, row_t row_id, Vector &result) override; void FetchRow(Transaction &transaction, ColumnFetchState &state, row_t row_id, Vector &result, @@ -185820,7 +203156,6 @@ class StandardColumnData : public ColumnData { - namespace duckdb { DataTable::DataTable(DatabaseInstance &db, const string &schema, const string &table, @@ -185889,7 +203224,7 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, ColumnDefinition auto &transaction = Transaction::GetTransaction(context); - ExpressionExecutor executor; + ExpressionExecutor executor(Allocator::Get(context)); DataChunk dummy_chunk; Vector result(new_column_type); if (!default_value) { @@ -185972,6 +203307,29 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, idx_t removed_co parent.is_root = false; } +// Alter column to add new constraint +DataTable::DataTable(ClientContext &context, DataTable &parent, unique_ptr constraint) + : info(parent.info), db(parent.db), total_rows(parent.total_rows.load()), row_groups(parent.row_groups), + is_root(true) { + + lock_guard parent_lock(parent.append_lock); + for (auto &column_def : parent.column_definitions) { + column_definitions.emplace_back(column_def.Copy()); + } + for (idx_t i = 0; i < column_definitions.size(); i++) { + column_stats.push_back(parent.column_stats[i]); + } + + // Verify the new constraint against current persistent/local data + VerifyNewConstraint(context, parent, constraint.get()); + + // Get the local data ownership from old dt + auto &transaction = Transaction::GetTransaction(context); + transaction.storage.MoveStorage(&parent, this); + // this table replaces the previous table, hence the parent is no longer the root DataTable + parent.is_root = false; +} + DataTable::DataTable(ClientContext &context, DataTable &parent, idx_t changed_idx, const LogicalType &target_type, vector bound_columns, Expression &cast_expr) : info(parent.info), db(parent.db), total_rows(parent.total_rows.load()), is_root(true) { @@ -186014,10 +203372,11 @@ DataTable::DataTable(ClientContext &context, DataTable &parent, idx_t changed_id scan_types.push_back(parent.column_definitions[bound_columns[i]].Type()); } } + auto &allocator = Allocator::Get(context); DataChunk scan_chunk; - scan_chunk.Initialize(scan_types); + scan_chunk.Initialize(allocator, scan_types); - ExpressionExecutor executor; + ExpressionExecutor executor(allocator); executor.AddExpression(cast_expr); TableScanState scan_state; @@ -186243,7 +203602,7 @@ static void VerifyGeneratedExpressionSuccess(TableCatalogEntry &table, DataChunk column_t index) { auto &col = table.columns[index]; D_ASSERT(col.Generated()); - ExpressionExecutor executor(expr); + ExpressionExecutor executor(Allocator::DefaultAllocator(), expr); Vector result(col.Type()); try { executor.ExecuteExpression(chunk, result); @@ -186253,7 +203612,7 @@ static void VerifyGeneratedExpressionSuccess(TableCatalogEntry &table, DataChunk } static void VerifyCheckConstraint(TableCatalogEntry &table, Expression &expr, DataChunk &chunk) { - ExpressionExecutor executor(expr); + ExpressionExecutor executor(Allocator::DefaultAllocator(), expr); Vector result(LogicalType::INTEGER); try { executor.ExecuteExpression(chunk, result); @@ -186262,8 +203621,8 @@ static void VerifyCheckConstraint(TableCatalogEntry &table, Expression &expr, Da } catch (...) { // LCOV_EXCL_START throw ConstraintException("CHECK constraint failed: %s (Unknown Error)", table.name); } // LCOV_EXCL_STOP - VectorData vdata; - result.Orrify(chunk.size(), vdata); + UnifiedVectorFormat vdata; + result.ToUnifiedFormat(chunk.size(), vdata); auto dataptr = (int32_t *)vdata.data; for (idx_t i = 0; i < chunk.size(); i++) { @@ -186274,7 +203633,7 @@ static void VerifyCheckConstraint(TableCatalogEntry &table, Expression &expr, Da } } -static bool IsForeignKeyIndex(const vector &fk_keys, Index &index, ForeignKeyType fk_type) { +bool DataTable::IsForeignKeyIndex(const vector &fk_keys, Index &index, ForeignKeyType fk_type) { if (fk_type == ForeignKeyType::FK_TYPE_PRIMARY_KEY_TABLE ? !index.IsUnique() : !index.IsForeign()) { return false; } @@ -186296,17 +203655,6 @@ static bool IsForeignKeyIndex(const vector &fk_keys, Index &index, Foreig return true; } -Index *TableIndexList::FindForeignKeyIndex(const vector &fk_keys, ForeignKeyType fk_type) { - Index *result = nullptr; - Scan([&](Index &index) { - if (IsForeignKeyIndex(fk_keys, index, fk_type)) { - result = &index; - } - return false; - }); - return result; -} - static void VerifyForeignKeyConstraint(const BoundForeignKeyConstraint &bfk, ClientContext &context, DataChunk &chunk, bool is_append) { const vector *src_keys_ptr = &bfk.info.fk_keys; @@ -186362,7 +203710,7 @@ static void VerifyForeignKeyConstraint(const BoundForeignKeyConstraint &bfk, Cli if (transaction_check) { vector> &transact_index_vec = transaction.storage.GetIndexes(data_table); for (idx_t i = 0; i < transact_index_vec.size(); i++) { - if (IsForeignKeyIndex(*dst_keys_ptr, *transact_index_vec[i], fk_type)) { + if (DataTable::IsForeignKeyIndex(*dst_keys_ptr, *transact_index_vec[i], fk_type)) { if (is_append) { transact_index_vec[i]->VerifyAppendForeignKey(dst_chunk, tran_err_msgs.data()); } else { @@ -186414,6 +203762,59 @@ static void VerifyDeleteForeignKeyConstraint(const BoundForeignKeyConstraint &bf VerifyForeignKeyConstraint(bfk, context, chunk, false); } +void DataTable::VerifyNewConstraint(ClientContext &context, DataTable &parent, const Constraint *constraint) { + if (constraint->type != ConstraintType::NOT_NULL) { + throw NotImplementedException("FIXME: ALTER COLUMN with such constraint is not supported yet"); + } + // scan the original table, check if there's any null value + auto ¬_null_constraint = (NotNullConstraint &)*constraint; + auto &transaction = Transaction::GetTransaction(context); + vector scan_types; + scan_types.push_back(parent.column_definitions[not_null_constraint.index].Type()); + DataChunk scan_chunk; + auto &allocator = Allocator::Get(context); + scan_chunk.Initialize(allocator, scan_types); + + CreateIndexScanState state; + vector cids; + cids.push_back(not_null_constraint.index); + // Use ScanCreateIndex to scan the latest committed data + InitializeCreateIndexScan(state, cids); + while (true) { + scan_chunk.Reset(); + ScanCreateIndex(state, scan_chunk, TableScanType::TABLE_SCAN_COMMITTED_ROWS); + if (scan_chunk.size() == 0) { + break; + } + // Check constraint + if (VectorOperations::HasNull(scan_chunk.data[0], scan_chunk.size())) { + throw ConstraintException("NOT NULL constraint failed: %s.%s", info->table, + column_definitions[not_null_constraint.index].GetName()); + } + } + + TableScanState scan_state; + scan_state.column_ids.push_back(not_null_constraint.index); + scan_state.max_row = total_rows; + + // For local storage + transaction.storage.InitializeScan(&parent, scan_state.local_state, nullptr); + if (scan_state.local_state.GetStorage()) { + while (scan_state.local_state.chunk_index <= scan_state.local_state.max_index) { + scan_chunk.Reset(); + transaction.storage.Scan(scan_state.local_state, scan_state.column_ids, scan_chunk); + if (scan_chunk.size() == 0) { + break; + } + // Check constraint + if (VectorOperations::HasNull(scan_chunk.data[0], scan_chunk.size())) { + throw ConstraintException("NOT NULL constraint failed: %s.%s", info->table, + column_definitions[not_null_constraint.index].GetName()); + } + } + } +} + void DataTable::VerifyAppendConstraints(TableCatalogEntry &table, ClientContext &context, DataChunk &chunk) { auto binder = Binder::CreateBinder(context); auto bound_columns = unordered_set(); @@ -186523,7 +203924,7 @@ void DataTable::Append(Transaction &transaction, DataChunk &chunk, TableAppendSt // merge the stats lock_guard stats_guard(stats_lock); for (idx_t i = 0; i < column_definitions.size(); i++) { - column_stats[i]->stats->Merge(*current_row_group->GetStatistics(i)); + current_row_group->MergeIntoStatistics(i, *column_stats[i]->stats); } } state.remaining_append_count -= append_count; @@ -186572,7 +203973,7 @@ void DataTable::ScanTableSegment(idx_t row_start, idx_t count, const std::functi types.push_back(col.Type()); } DataChunk chunk; - chunk.Initialize(types); + chunk.Initialize(Allocator::Get(db), types); CreateIndexScanState state; @@ -186605,6 +204006,9 @@ void DataTable::ScanTableSegment(idx_t row_start, idx_t count, const std::functi } void DataTable::WriteToLog(WriteAheadLog &log, idx_t row_start, idx_t count) { + if (log.skip_writing) { + return; + } log.WriteSetTable(info->schema, info->table); ScanTableSegment(row_start, count, [&](DataChunk &chunk) { log.WriteInsert(chunk); }); } @@ -186768,11 +204172,10 @@ void DataTable::RemoveFromIndexes(Vector &row_identifiers, idx_t count) { state.column_ids.push_back(i); } DataChunk result; - result.Initialize(types); + result.Initialize(Allocator::Get(db), types); row_group->InitializeScanWithOffset(state.row_group_scan_state, row_group_vector_idx); - row_group->ScanCommitted(state.row_group_scan_state, result, - TableScanType::TABLE_SCAN_COMMITTED_ROWS_DISALLOW_UPDATES); + row_group->ScanCommitted(state.row_group_scan_state, result, TableScanType::TABLE_SCAN_COMMITTED_ROWS); result.Slice(sel, count); info->indexes.Scan([&](Index &index) { @@ -186813,7 +204216,7 @@ idx_t DataTable::Delete(TableCatalogEntry &table, ClientContext &context, Vector auto &transaction = Transaction::GetTransaction(context); - row_identifiers.Normalify(count); + row_identifiers.Flatten(count); auto ids = FlatVector::GetData(row_identifiers); auto first_id = ids[0]; @@ -186829,7 +204232,7 @@ idx_t DataTable::Delete(TableCatalogEntry &table, ClientContext &context, Vector col_ids.push_back(column_definitions[i].StorageOid()); types.emplace_back(column_definitions[i].Type()); } - verify_chunk.Initialize(types); + verify_chunk.Initialize(Allocator::Get(context), types); Fetch(transaction, verify_chunk, col_ids, row_identifiers, count, fetch_state); } VerifyDeleteConstraints(table, context, verify_chunk); @@ -186965,8 +204368,8 @@ void DataTable::Update(TableCatalogEntry &table, ClientContext &context, Vector // now perform the actual update auto &transaction = Transaction::GetTransaction(context); - updates.Normalify(); - row_ids.Normalify(count); + updates.Flatten(); + row_ids.Flatten(count); auto ids = FlatVector::GetData(row_ids); auto first_id = FlatVector::GetValue(row_ids, 0); if (first_id >= MAX_ROW_ID) { @@ -187023,8 +204426,8 @@ void DataTable::UpdateColumn(TableCatalogEntry &table, ClientContext &context, V // now perform the actual update auto &transaction = Transaction::GetTransaction(context); - updates.Normalify(); - row_ids.Normalify(updates.size()); + updates.Flatten(); + row_ids.Flatten(updates.size()); auto first_id = FlatVector::GetValue(row_ids, 0); if (first_id >= MAX_ROW_ID) { throw NotImplementedException("Cannot update a column-path on transaction local data"); @@ -187066,8 +204469,10 @@ bool DataTable::ScanCreateIndex(CreateIndexScanState &state, DataChunk &result, } void DataTable::AddIndex(unique_ptr index, const vector> &expressions) { + auto &allocator = Allocator::Get(db); + DataChunk result; - result.Initialize(index->logical_types); + result.Initialize(allocator, index->logical_types); DataChunk intermediate; vector intermediate_types; @@ -187078,7 +204483,7 @@ void DataTable::AddIndex(unique_ptr index, const vector index, const vectorInitializeLock(lock); - ExpressionExecutor executor(expressions); + ExpressionExecutor executor(allocator, expressions); while (true) { intermediate.Reset(); + result.Reset(); // scan a new chunk from the table to index ScanCreateIndex(state, intermediate, TableScanType::TABLE_SCAN_COMMITTED_ROWS_OMIT_PERMANENTLY_DELETED); if (intermediate.size() == 0) { @@ -187123,10 +204529,16 @@ unique_ptr DataTable::GetStatistics(ClientContext &context, colu return column_stats[column_id]->stats->Copy(); } +void DataTable::SetStatistics(column_t column_id, const std::function &set_fun) { + D_ASSERT(column_id != COLUMN_IDENTIFIER_ROW_ID); + lock_guard stats_guard(stats_lock); + set_fun(*column_stats[column_id]->stats); +} + //===--------------------------------------------------------------------===// // Checkpoint //===--------------------------------------------------------------------===// -BlockPointer DataTable::Checkpoint(TableDataWriter &writer) { +void DataTable::Checkpoint(TableDataWriter &writer) { // checkpoint each individual row group // FIXME: we might want to combine adjacent row groups in case they have had deletions... vector> global_stats; @@ -187143,18 +204555,33 @@ BlockPointer DataTable::Checkpoint(TableDataWriter &writer) { } // store the current position in the metadata writer // this is where the row groups for this table start - auto &meta_writer = writer.GetMetaWriter(); - auto pointer = meta_writer.GetBlockPointer(); + auto &data_writer = writer.GetTableWriter(); + auto pointer = data_writer.GetBlockPointer(); for (auto &stats : global_stats) { - stats->Serialize(meta_writer); + stats->Serialize(data_writer); } // now start writing the row group pointers to disk - meta_writer.Write(row_group_pointers.size()); + data_writer.Write(row_group_pointers.size()); for (auto &row_group_pointer : row_group_pointers) { - RowGroup::Serialize(row_group_pointer, meta_writer); + RowGroup::Serialize(row_group_pointer, data_writer); + } + // Now we serialize indexes in the tabledata_writer + auto blocks_info = info->indexes.SerializeIndexes(data_writer); + + // metadata writing time + auto &metadata_writer = writer.GetMetaWriter(); + + // write the block pointer for the table info + metadata_writer.Write(pointer.block_id); + metadata_writer.Write(pointer.offset); + + // Write-off block ids and offsets of indexes + metadata_writer.Write(blocks_info.size()); + for (auto &block_info : blocks_info) { + metadata_writer.Write(block_info.block_id); + metadata_writer.Write(block_info.offset); } - return pointer; } void DataTable::CommitDropColumn(idx_t index) { @@ -187208,7 +204635,8 @@ namespace duckdb { Index::Index(IndexType type, const vector &column_ids_p, const vector> &unbound_expressions, IndexConstraintType constraint_type_p) - : type(type), column_ids(column_ids_p), constraint_type(constraint_type_p) { + : type(type), column_ids(column_ids_p), constraint_type(constraint_type_p), + executor(Allocator::DefaultAllocator()) { for (auto &expr : unbound_expressions) { types.push_back(expr->return_type.InternalType()); logical_types.push_back(expr->return_type); @@ -187263,6 +204691,10 @@ bool Index::IndexIsUpdated(const vector &column_ids) const { return false; } +BlockPointer Index::Serialize(duckdb::MetaBlockWriter &writer) { + throw NotImplementedException("The implementation of this index serialization does not exist."); +} + } // namespace duckdb @@ -187277,7 +204709,8 @@ bool Index::IndexIsUpdated(const vector &column_ids) const { namespace duckdb { -LocalTableStorage::LocalTableStorage(DataTable &table) : table(table), active_scans(0) { +LocalTableStorage::LocalTableStorage(DataTable &table) + : table(table), allocator(Allocator::Get(table.db)), collection(allocator), active_scans(0) { Clear(); } @@ -187340,7 +204773,7 @@ void LocalTableStorage::Clear() { for (auto &expr : art.unbound_expressions) { unbound_expressions.push_back(expr->Copy()); } - indexes.push_back(make_unique(art.column_ids, move(unbound_expressions), art.constraint_type)); + indexes.push_back(make_unique(art.column_ids, move(unbound_expressions), art.constraint_type, art.db)); } return false; }); @@ -187496,8 +204929,8 @@ idx_t LocalStorage::Delete(DataTable *table, Vector &row_ids, idx_t count) { // Slice out the rows that are being deleted from the storage Chunk auto &chunk = storage->collection.GetChunk(chunk_idx); - VectorData row_ids_data; - row_ids.Orrify(count, row_ids_data); + UnifiedVectorFormat row_ids_data; + row_ids.ToUnifiedFormat(count, row_ids_data); auto row_identifiers = (const row_t *)row_ids_data.data; SelectionVector sel(count); for (idx_t i = 0; i < count; ++i) { @@ -187545,8 +204978,8 @@ idx_t LocalStorage::Delete(DataTable *table, Vector &row_ids, idx_t count) { template static void TemplatedUpdateLoop(Vector &data_vector, Vector &update_vector, Vector &row_ids, idx_t count, idx_t base_index) { - VectorData udata; - update_vector.Orrify(count, udata); + UnifiedVectorFormat udata; + update_vector.ToUnifiedFormat(count, udata); auto target = FlatVector::GetData(data_vector); auto &mask = FlatVector::Validity(data_vector); @@ -187630,7 +205063,7 @@ bool LocalStorage::ScanTableStorage(DataTable &table, LocalTableStorage &storage } DataChunk chunk; - chunk.Initialize(table.GetTypes()); + chunk.Initialize(storage.allocator, table.GetTypes()); // initialize the scan LocalScanState state; @@ -187701,6 +205134,17 @@ void LocalStorage::Commit(LocalStorage::CommitState &commit_state, Transaction & table_storage.clear(); } +void LocalStorage::MoveStorage(DataTable *old_dt, DataTable *new_dt) { + // check if there are any pending appends for the old version of the table + auto entry = table_storage.find(old_dt); + if (entry == table_storage.end()) { + return; + } + // take over the storage from the old entry + auto new_storage = move(entry->second); + table_storage.erase(entry); + table_storage[new_dt] = move(new_storage); +} void LocalStorage::AddColumn(DataTable *old_dt, DataTable *new_dt, ColumnDefinition &new_column, Expression *default_value) { // check if there are any pending appends for the old version of the table @@ -187713,7 +205157,8 @@ void LocalStorage::AddColumn(DataTable *old_dt, DataTable *new_dt, ColumnDefinit // now add the new column filled with the default value to all chunks const auto &new_column_type = new_column.Type(); - ExpressionExecutor executor; + auto &allocator = Allocator::DefaultAllocator(); + ExpressionExecutor executor(allocator); DataChunk dummy_chunk; if (default_value) { executor.AddExpression(*default_value); @@ -187729,7 +205174,7 @@ void LocalStorage::AddColumn(DataTable *old_dt, DataTable *new_dt, ColumnDefinit } else { FlatVector::Validity(result).SetAllInvalid(chunk.size()); } - result.Normalify(chunk.size()); + result.Flatten(chunk.size()); chunk.data.push_back(move(result)); } @@ -187752,8 +205197,8 @@ void LocalStorage::FetchChunk(DataTable *table, Vector &row_ids, idx_t count, Da idx_t chunk_idx = GetChunk(row_ids); auto &chunk = storage->collection.GetChunk(chunk_idx); - VectorData row_ids_data; - row_ids.Orrify(count, row_ids_data); + UnifiedVectorFormat row_ids_data; + row_ids.ToUnifiedFormat(count, row_ids_data); auto row_identifiers = (const row_t *)row_ids_data.data; SelectionVector sel(count); for (idx_t i = 0; i < count; ++i) { @@ -187779,8 +205224,7 @@ vector> &LocalStorage::GetIndexes(DataTable *table) { namespace duckdb { -MetaBlockReader::MetaBlockReader(DatabaseInstance &db, block_id_t block_id) - : db(db), handle(nullptr), offset(0), next_block(-1) { +MetaBlockReader::MetaBlockReader(DatabaseInstance &db, block_id_t block_id) : db(db), offset(0), next_block(-1) { ReadNewBlock(block_id); } @@ -187788,12 +205232,12 @@ MetaBlockReader::~MetaBlockReader() { } void MetaBlockReader::ReadData(data_ptr_t buffer, idx_t read_size) { - while (offset + read_size > handle->node->size) { + while (offset + read_size > handle.GetFileBuffer().size) { // cannot read entire entry from block // first read what we can from this block - idx_t to_read = handle->node->size - offset; + idx_t to_read = handle.GetFileBuffer().size - offset; if (to_read > 0) { - memcpy(buffer, handle->node->buffer + offset, to_read); + memcpy(buffer, handle.Ptr() + offset, to_read); read_size -= to_read; buffer += to_read; } @@ -187801,7 +205245,7 @@ void MetaBlockReader::ReadData(data_ptr_t buffer, idx_t read_size) { ReadNewBlock(next_block); } // we have enough left in this block to read from the buffer - memcpy(buffer, handle->node->buffer + offset, read_size); + memcpy(buffer, handle.Ptr() + offset, read_size); offset += read_size; } @@ -187813,7 +205257,7 @@ void MetaBlockReader::ReadNewBlock(block_id_t id) { block = buffer_manager.RegisterBlock(id); handle = buffer_manager.Pin(block); - next_block = Load(handle->node->buffer); + next_block = Load(handle.Ptr()); D_ASSERT(next_block >= -1); offset = sizeof(block_id_t); } @@ -188289,7 +205733,7 @@ vector SingleFileBlockManager::GetFreeListBlocks() { auto space_in_block = Storage::BLOCK_SIZE - 4 * sizeof(block_id_t); auto total_blocks = (total_size + space_in_block - 1) / space_in_block; auto &config = DBConfig::GetConfig(db); - if (config.debug_many_free_list_blocks) { + if (config.options.debug_many_free_list_blocks) { total_blocks++; } D_ASSERT(total_size > 0); @@ -188369,7 +205813,7 @@ void SingleFileBlockManager::WriteHeader(DatabaseHeader header) { header.block_count = max_block; auto &config = DBConfig::GetConfig(db); - if (config.checkpoint_abort == CheckpointAbort::DEBUG_ABORT_AFTER_FREE_LIST_WRITE) { + if (config.options.checkpoint_abort == CheckpointAbort::DEBUG_ABORT_AFTER_FREE_LIST_WRITE) { throw IOException("Checkpoint aborted after free list write because of PRAGMA checkpoint_abort flag"); } @@ -188462,6 +205906,14 @@ void BaseStatistics::Merge(const BaseStatistics &other) { } } +idx_t BaseStatistics::GetDistinctCount() { + if (distinct_stats) { + auto &d_stats = (DistinctStatistics &)*distinct_stats; + return d_stats.GetCount(); + } + return 0; +} + unique_ptr BaseStatistics::CreateEmpty(LogicalType type, StatisticsType stats_type) { unique_ptr result; switch (type.InternalType()) { @@ -188634,7 +206086,7 @@ unique_ptr DistinctStatistics::Copy() const { void DistinctStatistics::Merge(const BaseStatistics &other_p) { BaseStatistics::Merge(other_p); auto &other = (const DistinctStatistics &)other_p; - log->Merge(*other.log); + log = log->Merge(*other.log); sample_count += other.sample_count; total_count += other.total_count; } @@ -188664,18 +206116,21 @@ unique_ptr DistinctStatistics::Deserialize(FieldReader &read return make_unique(HyperLogLog::Deserialize(reader), sample_count, total_count); } -void DistinctStatistics::Update(Vector &v, idx_t count) { - VectorData vdata; - v.Orrify(count, vdata); - Update(vdata, v.GetType(), count); +void DistinctStatistics::Update(Vector &v, idx_t count, bool sample) { + UnifiedVectorFormat vdata; + v.ToUnifiedFormat(count, vdata); + Update(vdata, v.GetType(), count, sample); } -void DistinctStatistics::Update(VectorData &vdata, const LogicalType &type, idx_t count) { +void DistinctStatistics::Update(UnifiedVectorFormat &vdata, const LogicalType &type, idx_t count, bool sample) { if (count == 0) { return; } + total_count += count; - count = MinValue(idx_t(SAMPLE_RATE * MaxValue(STANDARD_VECTOR_SIZE, count)), count); + if (sample) { + count = MinValue(idx_t(SAMPLE_RATE * MaxValue(STANDARD_VECTOR_SIZE, count)), count); + } sample_count += count; uint64_t indices[STANDARD_VECTOR_SIZE]; @@ -188768,8 +206223,8 @@ void ListStatistics::Verify(Vector &vector, const SelectionVector &sel, idx_t co if (child_stats) { auto &child_entry = ListVector::GetEntry(vector); - VectorData vdata; - vector.Orrify(count, vdata); + UnifiedVectorFormat vdata; + vector.ToUnifiedFormat(count, vdata); auto list_data = (list_entry_t *)vdata.data; idx_t total_list_count = 0; @@ -188944,8 +206399,8 @@ string NumericStatistics::ToString() const { template void NumericStatistics::TemplatedVerify(Vector &vector, const SelectionVector &sel, idx_t count) const { - VectorData vdata; - vector.Orrify(count, vdata); + UnifiedVectorFormat vdata; + vector.ToUnifiedFormat(count, vdata); auto data = (T *)vdata.data; for (idx_t i = 0; i < count; i++) { @@ -189209,8 +206664,8 @@ void StringStatistics::Verify(Vector &vector, const SelectionVector &sel, idx_t string_t min_string((const char *)min, MAX_STRING_MINMAX_SIZE); string_t max_string((const char *)max, MAX_STRING_MINMAX_SIZE); - VectorData vdata; - vector.Orrify(count, vdata); + UnifiedVectorFormat vdata; + vector.ToUnifiedFormat(count, vdata); auto data = (string_t *)vdata.data; for (idx_t i = 0; i < count; i++) { auto idx = sel.get_index(i); @@ -189422,8 +206877,8 @@ void ValidityStatistics::Verify(Vector &vector, const SelectionVector &sel, idx_ // nothing to verify return; } - VectorData vdata; - vector.Orrify(count, vdata); + UnifiedVectorFormat vdata; + vector.ToUnifiedFormat(count, vdata); for (idx_t i = 0; i < count; i++) { auto idx = sel.get_index(i); auto index = vdata.sel->get_index(idx); @@ -189452,7 +206907,7 @@ string ValidityStatistics::ToString() const { namespace duckdb { -const uint64_t VERSION_NUMBER = 33; +const uint64_t VERSION_NUMBER = 38; } // namespace duckdb @@ -189574,7 +207029,6 @@ class InMemoryBlockManager : public BlockManager { - namespace duckdb { StorageManager::StorageManager(DatabaseInstance &db, string path, bool read_only) @@ -189597,7 +207051,7 @@ ObjectCache &ObjectCache::GetObjectCache(ClientContext &context) { } bool ObjectCache::ObjectCacheEnabled(ClientContext &context) { - return context.db->config.object_cache_enable; + return context.db->config.options.object_cache_enable; } bool StorageManager::InMemory() { @@ -189609,22 +207063,22 @@ void StorageManager::Initialize() { if (in_memory && read_only) { throw CatalogException("Cannot launch in-memory database in read-only mode!"); } + auto &config = DBConfig::GetConfig(db); + auto &catalog = Catalog::GetCatalog(db); + buffer_manager = make_unique(db, config.options.temporary_directory, config.options.maximum_memory); // first initialize the base system catalogs // these are never written to the WAL Connection con(db); con.BeginTransaction(); - auto &config = DBConfig::GetConfig(db); - auto &catalog = Catalog::GetCatalog(*con.context); - // create the default schema CreateSchemaInfo info; info.schema = DEFAULT_SCHEMA; info.internal = true; catalog.CreateSchema(*con.context, &info); - if (config.initialize_default_database) { + if (config.options.initialize_default_database) { // initialize default functions BuiltinFunctions builtin(*con.context, catalog); builtin.Initialize(); @@ -189638,7 +207092,6 @@ void StorageManager::Initialize() { LoadDatabase(); } else { block_manager = make_unique(); - buffer_manager = make_unique(db, config.temporary_directory, config.maximum_memory); } } @@ -189659,14 +207112,12 @@ void StorageManager::LoadDatabase() { fs.RemoveFile(wal_path); } // initialize the block manager while creating a new db file - block_manager = make_unique(db, path, read_only, true, config.use_direct_io); - buffer_manager = make_unique(db, config.temporary_directory, config.maximum_memory); + block_manager = make_unique(db, path, read_only, true, config.options.use_direct_io); } else { // initialize the block manager while loading the current db file - auto sf_bm = make_unique(db, path, read_only, false, config.use_direct_io); + auto sf_bm = make_unique(db, path, read_only, false, config.options.use_direct_io); auto sf = sf_bm.get(); block_manager = move(sf_bm); - buffer_manager = make_unique(db, config.temporary_directory, config.maximum_memory); sf->LoadFreeList(); //! Load from storage @@ -189691,7 +207142,7 @@ void StorageManager::CreateCheckpoint(bool delete_wal, bool force_checkpoint) { if (InMemory() || read_only || !wal.initialized) { return; } - if (wal.GetWALSize() > 0 || db.config.force_checkpoint || force_checkpoint) { + if (wal.GetWALSize() > 0 || db.config.options.force_checkpoint || force_checkpoint) { // we only need to checkpoint if there is anything in the WAL CheckpointManager checkpointer(db); checkpointer.CreateCheckpoint(); @@ -190054,6 +207505,11 @@ ColumnCheckpointState::ColumnCheckpointState(RowGroup &row_group, ColumnData &co ColumnCheckpointState::~ColumnCheckpointState() { } +unique_ptr ColumnCheckpointState::GetStatistics() { + D_ASSERT(global_stats); + return move(global_stats); +} + void ColumnCheckpointState::FlushSegment(unique_ptr segment, idx_t segment_size) { D_ASSERT(segment_size <= Storage::BLOCK_SIZE); auto tuple_count = segment->count.load(); @@ -190129,7 +207585,7 @@ void ColumnCheckpointState::FlushSegment(unique_ptr segment, idx_ // pin the new block auto new_handle = buffer_manager.Pin(partial_block->block); // memcpy the contents of the old block to the new block - memcpy(new_handle->Ptr() + offset_in_block, old_handle->Ptr(), segment_size); + memcpy(new_handle.Ptr() + offset_in_block, old_handle.Ptr(), segment_size); } else { // convert the segment into a persistent segment that points to this block segment->ConvertToPersistent(block_id); @@ -190146,7 +207602,7 @@ void ColumnCheckpointState::FlushSegment(unique_ptr segment, idx_ } void ColumnCheckpointState::FlushToDisk() { - auto &meta_writer = writer.GetMetaWriter(); + auto &meta_writer = writer.GetTableWriter(); meta_writer.Write(data_pointers.size()); // then write the data pointers themselves @@ -190437,7 +207893,7 @@ idx_t ColumnData::ScanVector(Transaction *transaction, idx_t vector_index, Colum if (!ALLOW_UPDATES && updates->HasUncommittedUpdates(vector_index)) { throw TransactionException("Cannot create index with outstanding updates"); } - result.Normalify(scan_count); + result.Flatten(scan_count); if (SCAN_COMMITTED) { updates->FetchCommitted(vector_index, result); } else { @@ -190474,7 +207930,7 @@ void ColumnData::ScanCommittedRange(idx_t row_group_start, idx_t offset_in_row_g InitializeScanWithOffset(child_state, row_group_start + offset_in_row_group); auto scan_count = ScanVector(child_state, result, count); if (updates) { - result.Normalify(scan_count); + result.Flatten(scan_count); updates->FetchCommittedRange(offset_in_row_group, count, result); } } @@ -190491,7 +207947,7 @@ idx_t ColumnData::ScanCount(ColumnScanState &state, Vector &result, idx_t count) void ColumnData::Select(Transaction &transaction, idx_t vector_index, ColumnScanState &state, Vector &result, SelectionVector &sel, idx_t &count, const TableFilter &filter) { idx_t scan_count = Scan(transaction, vector_index, state, result); - result.Normalify(scan_count); + result.Flatten(scan_count); ColumnSegment::FilterSelection(sel, result, filter, count, FlatVector::Validity(result)); } @@ -190540,8 +207996,8 @@ void ColumnScanState::NextVector() { } void ColumnData::Append(BaseStatistics &stats, ColumnAppendState &state, Vector &vector, idx_t count) { - VectorData vdata; - vector.Orrify(count, vdata); + UnifiedVectorFormat vdata; + vector.ToUnifiedFormat(count, vdata); AppendData(stats, state, vdata, count); } @@ -190565,7 +208021,7 @@ void ColumnData::InitializeAppend(ColumnAppendState &state) { state.current->InitializeAppend(state); } -void ColumnData::AppendData(BaseStatistics &stats, ColumnAppendState &state, VectorData &vdata, idx_t count) { +void ColumnData::AppendData(BaseStatistics &stats, ColumnAppendState &state, UnifiedVectorFormat &vdata, idx_t count) { idx_t offset = 0; while (true) { // append the data from the vector @@ -190643,7 +208099,7 @@ void ColumnData::Update(Transaction &transaction, idx_t column_index, Vector &up ColumnScanState state; auto fetch_count = Fetch(state, row_ids[0], base_vector); - base_vector.Normalify(fetch_count); + base_vector.Flatten(fetch_count); updates->Update(transaction, column_index, update_vector, row_ids, update_count, base_vector); } @@ -190686,7 +208142,7 @@ void ColumnData::CheckpointScan(ColumnSegment *segment, ColumnScanState &state, Vector &scan_vector) { segment->Scan(state, count, scan_vector, 0, true); if (updates) { - scan_vector.Normalify(count); + scan_vector.Flatten(count); updates->FetchCommittedRange(state.row_index - row_group_start, count, scan_vector); } } @@ -190906,7 +208362,8 @@ void ColumnDataCheckpointer::ScanSegments(const std::function &compression_functions, CompressionType compression_type) { +CompressionType ForceCompression(vector &compression_functions, + CompressionType compression_type) { // On of the force_compression flags has been set // check if this compression method is available bool found = false; @@ -190919,25 +208376,31 @@ void ForceCompression(vector &compression_functions, Comp if (found) { // the force_compression method is available // clear all other compression methods + // except the uncompressed method, so we can fall back on that for (idx_t i = 0; i < compression_functions.size(); i++) { + if (compression_functions[i]->type == CompressionType::COMPRESSION_UNCOMPRESSED) { + continue; + } if (compression_functions[i]->type != compression_type) { compression_functions[i] = nullptr; } } } + return found ? compression_type : CompressionType::COMPRESSION_AUTO; } unique_ptr ColumnDataCheckpointer::DetectBestCompressionMethod(idx_t &compression_idx) { D_ASSERT(!compression_functions.empty()); auto &config = DBConfig::GetConfig(GetDatabase()); + CompressionType forced_method = CompressionType::COMPRESSION_AUTO; auto compression_type = checkpoint_info.compression_type; if (compression_type != CompressionType::COMPRESSION_AUTO) { - ForceCompression(compression_functions, compression_type); + forced_method = ForceCompression(compression_functions, compression_type); } if (compression_type == CompressionType::COMPRESSION_AUTO && - config.force_compression != CompressionType::COMPRESSION_AUTO) { - ForceCompression(compression_functions, config.force_compression); + config.options.force_compression != CompressionType::COMPRESSION_AUTO) { + forced_method = ForceCompression(compression_functions, config.options.force_compression); } // set up the analyze states for each compression method vector> analyze_states; @@ -190975,12 +208438,18 @@ unique_ptr ColumnDataCheckpointer::DetectBestCompressionMethod(idx if (!compression_functions[i]) { continue; } + //! Check if the method type is the forced method (if forced is used) + bool forced_method_found = compression_functions[i]->type == forced_method; auto score = compression_functions[i]->final_analyze(*analyze_states[i]); - if (score < best_score) { + if (score < best_score || forced_method_found) { compression_idx = i; best_score = score; state = move(analyze_states[i]); } + //! If we have found the forced method, we're done + if (forced_method_found) { + break; + } } return state; } @@ -191009,7 +208478,7 @@ void ColumnDataCheckpointer::WriteToDisk() { auto analyze_state = DetectBestCompressionMethod(compression_idx); if (!analyze_state) { - throw InternalException("No suitable compression/storage method found to store column"); + throw FatalException("No suitable compression/storage method found to store column"); } // now that we have analyzed the compression functions we can start writing to disk @@ -191019,7 +208488,6 @@ void ColumnDataCheckpointer::WriteToDisk() { [&](Vector &scan_vector, idx_t count) { best_function->compress(*compress_state, scan_vector, count); }); best_function->compress_finalize(*compress_state); - // now we actually write the data to disk owned_segment.reset(); } @@ -191099,7 +208567,6 @@ void ColumnDataCheckpointer::Checkpoint(unique_ptr segment) { - #include namespace duckdb { @@ -191201,7 +208668,7 @@ void ColumnSegment::InitializeAppend(ColumnAppendState &state) { //===--------------------------------------------------------------------===// // Append //===--------------------------------------------------------------------===// -idx_t ColumnSegment::Append(ColumnAppendState &state, VectorData &append_data, idx_t offset, idx_t count) { +idx_t ColumnSegment::Append(ColumnAppendState &state, UnifiedVectorFormat &append_data, idx_t offset, idx_t count) { D_ASSERT(segment_type == ColumnSegmentType::TRANSIENT); if (!function->append) { throw InternalException("Attempting to append to a segment without append method"); @@ -191355,10 +208822,11 @@ static void FilterSelectionSwitch(T *vec, T *predicate, SelectionVector &sel, id } template -static idx_t TemplatedNullSelection(SelectionVector &sel, idx_t approved_tuple_count, ValidityMask &mask) { +static idx_t TemplatedNullSelection(SelectionVector &sel, idx_t &approved_tuple_count, ValidityMask &mask) { if (mask.AllValid()) { // no NULL values if (IS_NULL) { + approved_tuple_count = 0; return 0; } else { return approved_tuple_count; @@ -191373,6 +208841,7 @@ static idx_t TemplatedNullSelection(SelectionVector &sel, idx_t approved_tuple_c } } sel.Initialize(result_sel); + approved_tuple_count = result_count; return result_count; } } @@ -191696,7 +209165,7 @@ void ListColumnData::Append(BaseStatistics &stats_p, ColumnAppendState &state, V D_ASSERT(count > 0); auto &stats = (ListStatistics &)stats_p; - vector.Normalify(count); + vector.Flatten(count); auto &list_validity = FlatVector::Validity(vector); // construct the list_entry_t entries to append to the column data @@ -191728,7 +209197,7 @@ void ListColumnData::Append(BaseStatistics &stats_p, ColumnAppendState &state, V child_count); #endif - VectorData vdata; + UnifiedVectorFormat vdata; vdata.validity = list_validity; vdata.sel = FlatVector::IncrementalSelectionVector(); vdata.data = (data_ptr_t)append_offsets.get(); @@ -192505,7 +209974,7 @@ void RowGroup::Update(Transaction &transaction, DataChunk &update_chunk, row_t * D_ASSERT(columns[column]->type.id() == update_chunk.data[i].GetType().id()); if (offset > 0) { Vector sliced_vector(update_chunk.data[i], offset); - sliced_vector.Normalify(count); + sliced_vector.Flatten(count); columns[column]->Update(transaction, column, sliced_vector, ids + offset, count); } else { columns[column]->Update(transaction, column, update_chunk.data[i], ids, count); @@ -192533,14 +210002,22 @@ unique_ptr RowGroup::GetStatistics(idx_t column_idx) { return stats[column_idx]->statistics->Copy(); } -void RowGroup::MergeStatistics(idx_t column_idx, BaseStatistics &other) { +void RowGroup::MergeStatistics(idx_t column_idx, const BaseStatistics &other) { D_ASSERT(column_idx < stats.size()); lock_guard slock(stats_lock); stats[column_idx]->statistics->Merge(other); } +void RowGroup::MergeIntoStatistics(idx_t column_idx, BaseStatistics &other) { + D_ASSERT(column_idx < stats.size()); + + lock_guard slock(stats_lock); + other.Merge(*stats[column_idx]->statistics); +} + RowGroupPointer RowGroup::Checkpoint(TableDataWriter &writer, vector> &global_stats) { + RowGroupPointer row_group_pointer; vector> states; states.reserve(columns.size()); @@ -192555,22 +210032,21 @@ RowGroupPointer RowGroup::Checkpoint(TableDataWriter &writer, vectorMerge(*stats); + row_group_pointer.statistics.push_back(move(stats)); states.push_back(move(checkpoint_state)); } // construct the row group pointer and write the column meta data to disk D_ASSERT(states.size() == columns.size()); - RowGroupPointer row_group_pointer; row_group_pointer.row_start = start; row_group_pointer.tuple_count = count; for (auto &state : states) { // get the current position of the meta data writer - auto &meta_writer = writer.GetMetaWriter(); + auto &meta_writer = writer.GetTableWriter(); auto pointer = meta_writer.GetBlockPointer(); // store the stats and the data pointers in the row group pointers row_group_pointer.data_pointers.push_back(pointer); - row_group_pointer.statistics.push_back(state->GetStatistics()); // now flush the actual column data to disk state->FlushToDisk(); @@ -192924,7 +210400,8 @@ void StandardColumnData::InitializeAppend(ColumnAppendState &state) { state.child_appends.push_back(move(child_append)); } -void StandardColumnData::AppendData(BaseStatistics &stats, ColumnAppendState &state, VectorData &vdata, idx_t count) { +void StandardColumnData::AppendData(BaseStatistics &stats, ColumnAppendState &state, UnifiedVectorFormat &vdata, + idx_t count) { ColumnData::AppendData(stats, state, vdata, count); validity.AppendData(*stats.validity_stats, state.child_appends[0], vdata, count); @@ -193002,9 +210479,9 @@ struct StandardColumnCheckpointState : public ColumnCheckpointState { public: unique_ptr GetStatistics() override { - auto stats = global_stats->Copy(); - stats->validity_stats = validity_state->GetStatistics(); - return stats; + D_ASSERT(global_stats); + global_stats->validity_stats = validity_state->GetStatistics(); + return move(global_stats); } void FlushToDisk() override { @@ -193161,7 +210638,7 @@ void StructColumnData::InitializeAppend(ColumnAppendState &state) { } void StructColumnData::Append(BaseStatistics &stats, ColumnAppendState &state, Vector &vector, idx_t count) { - vector.Normalify(count); + vector.Flatten(count); // append the null values validity.Append(*stats.validity_stats, state.child_appends[0], vector, count); @@ -193174,7 +210651,7 @@ void StructColumnData::Append(BaseStatistics &stats, ColumnAppendState &state, V if (!struct_validity.AllValid()) { // we set the child entries of the struct to NULL // for any values in which the struct itself is NULL - child_entries[i]->Normalify(count); + child_entries[i]->Flatten(count); auto &child_validity = FlatVector::Validity(*child_entries[i]); child_validity.Combine(struct_validity, count); @@ -193416,6 +210893,7 @@ struct UpdateInfo { } // namespace duckdb + namespace duckdb { static UpdateSegment::initialize_update_function_t GetInitializeUpdateFunction(PhysicalType type); @@ -194038,10 +211516,14 @@ static void InitializeUpdateData(UpdateInfo *base_info, Vector &base_data, Updat } auto base_array_data = FlatVector::GetData(base_data); + auto &base_validity = FlatVector::Validity(base_data); auto base_tuple_data = (T *)base_info->tuple_data; for (idx_t i = 0; i < base_info->N; i++) { - base_tuple_data[i] = - UpdateSelectElement::Operation(base_info->segment, base_array_data[base_info->tuples[i]]); + auto base_idx = base_info->tuples[i]; + if (!base_validity.RowIsValid(base_idx)) { + continue; + } + base_tuple_data[i] = UpdateSelectElement::Operation(base_info->segment, base_array_data[base_idx]); } } @@ -194455,7 +211937,7 @@ void UpdateSegment::Update(Transaction &transaction, idx_t column_index, Vector // obtain an exclusive lock auto write_lock = lock.GetExclusiveLock(); - update.Normalify(count); + update.Flatten(count); // update statistics SelectionVector sel; @@ -194621,6 +212103,58 @@ bool ValidityColumnData::CheckZonemap(ColumnScanState &state, TableFilter &filte +namespace duckdb { +void TableIndex::AddIndex(unique_ptr index) { + D_ASSERT(index); + lock_guard lock(indexes_lock); + indexes.push_back(move(index)); +} +void TableIndex::RemoveIndex(Index *index) { + D_ASSERT(index); + lock_guard lock(indexes_lock); + + for (idx_t index_idx = 0; index_idx < indexes.size(); index_idx++) { + auto &index_entry = indexes[index_idx]; + if (index_entry.get() == index) { + indexes.erase(indexes.begin() + index_idx); + break; + } + } +} + +bool TableIndex::Empty() { + lock_guard lock(indexes_lock); + return indexes.empty(); +} + +idx_t TableIndex::Count() { + lock_guard lock(indexes_lock); + return indexes.size(); +} + +Index *TableIndex::FindForeignKeyIndex(const vector &fk_keys, ForeignKeyType fk_type) { + Index *result = nullptr; + Scan([&](Index &index) { + if (DataTable::IsForeignKeyIndex(fk_keys, index, fk_type)) { + result = &index; + } + return false; + }); + return result; +} + +vector TableIndex::SerializeIndexes(duckdb::MetaBlockWriter &writer) { + vector blocks_info; + for (auto &index : indexes) { + blocks_info.emplace_back(index->Serialize(writer)); + } + return blocks_info; +} + +} // namespace duckdb + + + @@ -194851,7 +212385,7 @@ void ReplayState::ReplayEntry(WALType entry_type) { // Replay Table //===--------------------------------------------------------------------===// void ReplayState::ReplayCreateTable() { - auto info = TableCatalogEntry::Deserialize(source); + auto info = TableCatalogEntry::Deserialize(source, context); if (deserialize_only) { return; } @@ -194891,7 +212425,7 @@ void ReplayState::ReplayAlter() { // Replay View //===--------------------------------------------------------------------===// void ReplayState::ReplayCreateView() { - auto entry = ViewCatalogEntry::Deserialize(source); + auto entry = ViewCatalogEntry::Deserialize(source, context); if (deserialize_only) { return; } @@ -195014,7 +212548,7 @@ void ReplayState::ReplaySequenceValue() { // Replay Macro //===--------------------------------------------------------------------===// void ReplayState::ReplayCreateMacro() { - auto entry = ScalarMacroCatalogEntry::Deserialize(source); + auto entry = ScalarMacroCatalogEntry::Deserialize(source, context); if (deserialize_only) { return; } @@ -195040,7 +212574,7 @@ void ReplayState::ReplayDropMacro() { // Replay Table Macro //===--------------------------------------------------------------------===// void ReplayState::ReplayCreateTableMacro() { - auto entry = TableMacroCatalogEntry::Deserialize(source); + auto entry = TableMacroCatalogEntry::Deserialize(source, context); if (deserialize_only) { return; } @@ -195599,6 +213133,7 @@ namespace duckdb { class CatalogEntry; class DataChunk; class WriteAheadLog; +class ClientContext; struct DataTableInfo; struct DeleteInfo; @@ -195606,7 +213141,7 @@ struct UpdateInfo; class CommitState { public: - explicit CommitState(transaction_t commit_id, WriteAheadLog *log = nullptr); + explicit CommitState(ClientContext &context, transaction_t commit_id, WriteAheadLog *log = nullptr); WriteAheadLog *log; transaction_t commit_id; @@ -195618,6 +213153,9 @@ class CommitState { unique_ptr delete_chunk; unique_ptr update_chunk; +private: + ClientContext &context; + public: template void CommitEntry(UndoFlags type, data_ptr_t data); @@ -195675,8 +213213,8 @@ struct AppendInfo { namespace duckdb { -CommitState::CommitState(transaction_t commit_id, WriteAheadLog *log) - : log(log), commit_id(commit_id), current_table_info(nullptr) { +CommitState::CommitState(ClientContext &context, transaction_t commit_id, WriteAheadLog *log) + : log(log), commit_id(commit_id), current_table_info(nullptr), context(context) { } void CommitState::SwitchTable(DataTableInfo *table_info, UndoFlags new_op) { @@ -195804,7 +213342,7 @@ void CommitState::WriteDelete(DeleteInfo *info) { if (!delete_chunk) { delete_chunk = make_unique(); vector delete_types = {LogicalType::ROW_TYPE}; - delete_chunk->Initialize(delete_types); + delete_chunk->Initialize(Allocator::DefaultAllocator(), delete_types); } auto rows = FlatVector::GetData(delete_chunk->data[0]); for (idx_t i = 0; i < info->count; i++) { @@ -195832,7 +213370,7 @@ void CommitState::WriteUpdate(UpdateInfo *info) { update_types.emplace_back(LogicalType::ROW_TYPE); update_chunk = make_unique(); - update_chunk->Initialize(update_types); + update_chunk->Initialize(Allocator::DefaultAllocator(), update_types); // fetch the updated values from the base segment info->segment->FetchCommitted(info->vector_index, update_chunk->data[0]); @@ -196051,11 +213589,17 @@ void RollbackState::RollbackEntry(UndoFlags type, data_ptr_t data) { - #include namespace duckdb { +Transaction::Transaction(weak_ptr context_p, transaction_t start_time, transaction_t transaction_id, + timestamp_t start_timestamp, idx_t catalog_version) + : context(move(context_p)), start_time(start_time), transaction_id(transaction_id), commit_id(0), + highest_active_query(0), active_query(MAXIMUM_QUERY_ID), start_timestamp(start_timestamp), + catalog_version(catalog_version), storage(*this), is_invalidated(false), undo_buffer(context.lock()) { +} + Transaction &Transaction::GetTransaction(ClientContext &context) { return context.ActiveTransaction(); } @@ -196120,7 +213664,7 @@ bool Transaction::AutomaticCheckpoint(DatabaseInstance &db) { auto initial_size = log->GetWALSize(); idx_t expected_wal_size = initial_size + storage.EstimatedSize() + undo_buffer.EstimatedSize(); - return expected_wal_size > config.checkpoint_wal_size; + return expected_wal_size > config.options.checkpoint_wal_size; } string Transaction::Commit(DatabaseInstance &db, transaction_t commit_id, bool checkpoint) noexcept { @@ -196596,62 +214140,29 @@ void TransactionManager::RemoveTransaction(Transaction *transaction) noexcept { #include namespace duckdb { -constexpr uint32_t DEFAULT_UNDO_CHUNK_SIZE = 4096 * 3; constexpr uint32_t UNDO_ENTRY_HEADER_SIZE = sizeof(UndoFlags) + sizeof(uint32_t); -static idx_t AlignLength(idx_t len) { - return (len + 7) / 8 * 8; -} - -UndoBuffer::UndoBuffer() { - head = make_unique(0); - tail = head.get(); -} - -UndoChunk::UndoChunk(idx_t size) : current_position(0), maximum_size(size), prev(nullptr) { - if (size > 0) { - data = unique_ptr(new data_t[maximum_size]); - } -} -UndoChunk::~UndoChunk() { - if (next) { - auto current_next = move(next); - while (current_next) { - current_next = move(current_next->next); - } - } -} - -data_ptr_t UndoChunk::WriteEntry(UndoFlags type, uint32_t len) { - len = AlignLength(len); - D_ASSERT(sizeof(UndoFlags) + sizeof(len) == 8); - Store(type, data.get() + current_position); - current_position += sizeof(UndoFlags); - Store(len, data.get() + current_position); - current_position += sizeof(uint32_t); - - data_ptr_t result = data.get() + current_position; - current_position += len; - return result; +UndoBuffer::UndoBuffer(const shared_ptr &context_p) + : context(*context_p), allocator(BufferAllocator::Get(*context_p)) { + D_ASSERT(context_p); } data_ptr_t UndoBuffer::CreateEntry(UndoFlags type, idx_t len) { D_ASSERT(len <= NumericLimits::Maximum()); - idx_t needed_space = AlignLength(len + UNDO_ENTRY_HEADER_SIZE); - if (head->current_position + needed_space >= head->maximum_size) { - auto new_chunk = - make_unique(needed_space > DEFAULT_UNDO_CHUNK_SIZE ? needed_space : DEFAULT_UNDO_CHUNK_SIZE); - head->prev = new_chunk.get(); - new_chunk->next = move(head); - head = move(new_chunk); - } - return head->WriteEntry(type, len); + len = AlignValue(len); + idx_t needed_space = len + UNDO_ENTRY_HEADER_SIZE; + auto data = allocator.Allocate(needed_space); + Store(type, data); + data += sizeof(UndoFlags); + Store(len, data); + data += sizeof(uint32_t); + return data; } template void UndoBuffer::IterateEntries(UndoBuffer::IteratorState &state, T &&callback) { // iterate in insertion order: start with the tail - state.current = tail; + state.current = allocator.GetTail(); while (state.current) { state.start = state.current->data.get(); state.end = state.start + state.current->current_position; @@ -196671,7 +214182,7 @@ void UndoBuffer::IterateEntries(UndoBuffer::IteratorState &state, T &&callback) template void UndoBuffer::IterateEntries(UndoBuffer::IteratorState &state, UndoBuffer::IteratorState &end_state, T &&callback) { // iterate in insertion order: start with the tail - state.current = tail; + state.current = allocator.GetTail(); while (state.current) { state.start = state.current->data.get(); state.end = @@ -196695,7 +214206,7 @@ void UndoBuffer::IterateEntries(UndoBuffer::IteratorState &state, UndoBuffer::It template void UndoBuffer::ReverseIterateEntries(T &&callback) { // iterate in reverse insertion order: start with the head - auto current = head.get(); + auto current = allocator.GetHead(); while (current) { data_ptr_t start = current->data.get(); data_ptr_t end = start + current->current_position; @@ -196718,12 +214229,12 @@ void UndoBuffer::ReverseIterateEntries(T &&callback) { } bool UndoBuffer::ChangesMade() { - return head->maximum_size > 0; + return !allocator.IsEmpty(); } idx_t UndoBuffer::EstimatedSize() { idx_t estimated_size = 0; - auto node = head.get(); + auto node = allocator.GetHead(); while (node) { estimated_size += node->current_position; node = node->next.get(); @@ -196746,7 +214257,7 @@ void UndoBuffer::Cleanup() { } void UndoBuffer::Commit(UndoBuffer::IteratorState &iterator_state, WriteAheadLog *log, transaction_t commit_id) { - CommitState state(commit_id, log); + CommitState state(context, commit_id, log); if (log) { // commit WITH write ahead log IterateEntries(iterator_state, [&](UndoFlags type, data_ptr_t data) { state.CommitEntry(type, data); }); @@ -196757,7 +214268,7 @@ void UndoBuffer::Commit(UndoBuffer::IteratorState &iterator_state, WriteAheadLog } void UndoBuffer::RevertCommit(UndoBuffer::IteratorState &end_state, transaction_t transaction_id) { - CommitState state(transaction_id, nullptr); + CommitState state(context, transaction_id, nullptr); UndoBuffer::IteratorState start_state; IterateEntries(start_state, end_state, [&](UndoFlags type, data_ptr_t data) { state.RevertCommit(type, data); }); } @@ -196768,10 +214279,494 @@ void UndoBuffer::Rollback() noexcept { ReverseIterateEntries([&](UndoFlags type, data_ptr_t data) { state.RollbackEntry(type, data); }); } } // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/verification/copied_statement_verifier.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { + +class CopiedStatementVerifier : public StatementVerifier { +public: + explicit CopiedStatementVerifier(unique_ptr statement_p); + static unique_ptr Create(const SQLStatement &statement_p); +}; + +} // namespace duckdb + + +namespace duckdb { + +CopiedStatementVerifier::CopiedStatementVerifier(unique_ptr statement_p) + : StatementVerifier(VerificationType::COPIED, "Copied", move(statement_p)) { +} + +unique_ptr CopiedStatementVerifier::Create(const SQLStatement &statement) { + return make_unique(statement.Copy()); +} + +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/verification/deserialized_statement_verifier.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { + +class DeserializedStatementVerifier : public StatementVerifier { +public: + explicit DeserializedStatementVerifier(unique_ptr statement_p); + static unique_ptr Create(const SQLStatement &statement); +}; + +} // namespace duckdb + + + + +namespace duckdb { + +DeserializedStatementVerifier::DeserializedStatementVerifier(unique_ptr statement_p) + : StatementVerifier(VerificationType::DESERIALIZED, "Deserialized", move(statement_p)) { +} + +unique_ptr DeserializedStatementVerifier::Create(const SQLStatement &statement) { + auto &select_stmt = (SelectStatement &)statement; + BufferedSerializer serializer; + select_stmt.Serialize(serializer); + BufferedDeserializer source(serializer); + return make_unique(SelectStatement::Deserialize(source)); +} + +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/verification/external_statement_verifier.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { + +class ExternalStatementVerifier : public StatementVerifier { +public: + explicit ExternalStatementVerifier(unique_ptr statement_p); + static unique_ptr Create(const SQLStatement &statement); + + bool ForceExternal() const override { + return true; + } +}; + +} // namespace duckdb + + +namespace duckdb { + +ExternalStatementVerifier::ExternalStatementVerifier(unique_ptr statement_p) + : StatementVerifier(VerificationType::EXTERNAL, "External", move(statement_p)) { +} + +unique_ptr ExternalStatementVerifier::Create(const SQLStatement &statement) { + return make_unique(statement.Copy()); +} + +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/verification/parsed_statement_verifier.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { + +class ParsedStatementVerifier : public StatementVerifier { +public: + explicit ParsedStatementVerifier(unique_ptr statement_p); + static unique_ptr Create(const SQLStatement &statement); + + bool RequireEquality() const override { + return false; + } +}; + +} // namespace duckdb + + + + +namespace duckdb { + +ParsedStatementVerifier::ParsedStatementVerifier(unique_ptr statement_p) + : StatementVerifier(VerificationType::PARSED, "Parsed", move(statement_p)) { +} + +unique_ptr ParsedStatementVerifier::Create(const SQLStatement &statement) { + auto query_str = statement.ToString(); + Parser parser; + parser.ParseQuery(query_str); + D_ASSERT(parser.statements.size() == 1); + D_ASSERT(parser.statements[0]->type == StatementType::SELECT_STATEMENT); + return make_unique(move(parser.statements[0])); +} + +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/verification/prepared_statement_verifier.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { + +class PreparedStatementVerifier : public StatementVerifier { +public: + explicit PreparedStatementVerifier(unique_ptr statement_p); + static unique_ptr Create(const SQLStatement &statement_p); + + bool Run(ClientContext &context, const string &query, + const std::function(const string &, unique_ptr)> &run) override; + +private: + vector> values; + unique_ptr prepare_statement; + unique_ptr execute_statement; + unique_ptr dealloc_statement; + +private: + void Extract(); + void ConvertConstants(unique_ptr &child); +}; + +} // namespace duckdb + + + + + + + + + +namespace duckdb { + +PreparedStatementVerifier::PreparedStatementVerifier(unique_ptr statement_p) + : StatementVerifier(VerificationType::PREPARED, "Prepared", move(statement_p)) { +} + +unique_ptr PreparedStatementVerifier::Create(const SQLStatement &statement) { + return make_unique(statement.Copy()); +} + +void PreparedStatementVerifier::Extract() { + auto &select = *statement; + // replace all the constants from the select statement and replace them with parameter expressions + ParsedExpressionIterator::EnumerateQueryNodeChildren( + *select.node, [&](unique_ptr &child) { ConvertConstants(child); }); + statement->n_param = values.size(); + // create the PREPARE and EXECUTE statements + string name = "__duckdb_verification_prepared_statement"; + auto prepare = make_unique(); + prepare->name = name; + prepare->statement = move(statement); + + auto execute = make_unique(); + execute->name = name; + execute->values = move(values); + + auto dealloc = make_unique(); + dealloc->info->type = CatalogType::PREPARED_STATEMENT; + dealloc->info->name = string(name); + + prepare_statement = move(prepare); + execute_statement = move(execute); + dealloc_statement = move(dealloc); +} + +void PreparedStatementVerifier::ConvertConstants(unique_ptr &child) { + if (child->type == ExpressionType::VALUE_CONSTANT) { + // constant: extract the constant value + auto alias = child->alias; + child->alias = string(); + // check if the value already exists + idx_t index = values.size(); + for (idx_t v_idx = 0; v_idx < values.size(); v_idx++) { + if (values[v_idx]->Equals(child.get())) { + // duplicate value! refer to the original value + index = v_idx; + break; + } + } + if (index == values.size()) { + values.push_back(move(child)); + } + // replace it with an expression + auto parameter = make_unique(); + parameter->parameter_nr = index + 1; + parameter->alias = alias; + child = move(parameter); + return; + } + ParsedExpressionIterator::EnumerateChildren(*child, + [&](unique_ptr &child) { ConvertConstants(child); }); +} + +bool PreparedStatementVerifier::Run( + ClientContext &context, const string &query, + const std::function(const string &, unique_ptr)> &run) { + bool failed = false; + // verify that we can extract all constants from the query and run the query as a prepared statement + // create the PREPARE and EXECUTE statements + Extract(); + // execute the prepared statements + try { + auto prepare_result = run(string(), move(prepare_statement)); + if (prepare_result->HasError()) { + prepare_result->ThrowError("Failed prepare during verify: "); + } + auto execute_result = run(string(), move(execute_statement)); + if (execute_result->HasError()) { + execute_result->ThrowError("Failed execute during verify: "); + } + materialized_result = unique_ptr_cast(move(execute_result)); + } catch (const Exception &ex) { + if (ex.type != ExceptionType::PARAMETER_NOT_ALLOWED) { + materialized_result = make_unique(PreservedError(ex)); + } + failed = true; + } catch (std::exception &ex) { + materialized_result = make_unique(PreservedError(ex)); + failed = true; + } + run(string(), move(dealloc_statement)); + context.interrupted = false; + + return failed; +} + +} // namespace duckdb + + + + + + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/verification/unoptimized_statement_verifier.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { + +class UnoptimizedStatementVerifier : public StatementVerifier { +public: + explicit UnoptimizedStatementVerifier(unique_ptr statement_p); + static unique_ptr Create(const SQLStatement &statement_p); + + bool DisableOptimizer() const override { + return true; + } +}; + +} // namespace duckdb + + +namespace duckdb { + +StatementVerifier::StatementVerifier(VerificationType type, string name, unique_ptr statement_p) + : type(type), name(move(name)), statement(unique_ptr_cast(move(statement_p))), + select_list(statement->node->GetSelectList()) { +} + +StatementVerifier::StatementVerifier(unique_ptr statement_p) + : StatementVerifier(VerificationType::ORIGINAL, "Original", move(statement_p)) { +} + +StatementVerifier::~StatementVerifier() noexcept { +} + +unique_ptr StatementVerifier::Create(VerificationType type, const SQLStatement &statement_p) { + switch (type) { + case VerificationType::COPIED: + return CopiedStatementVerifier::Create(statement_p); + case VerificationType::DESERIALIZED: + return DeserializedStatementVerifier::Create(statement_p); + case VerificationType::PARSED: + return ParsedStatementVerifier::Create(statement_p); + case VerificationType::UNOPTIMIZED: + return UnoptimizedStatementVerifier::Create(statement_p); + case VerificationType::PREPARED: + return PreparedStatementVerifier::Create(statement_p); + case VerificationType::EXTERNAL: + return ExternalStatementVerifier::Create(statement_p); + case VerificationType::INVALID: + default: + throw InternalException("Invalid statement verification type!"); + } +} + +void StatementVerifier::CheckExpressions(const StatementVerifier &other) const { + // Only the original statement should check other statements + D_ASSERT(type == VerificationType::ORIGINAL); + + // Check equality + if (other.RequireEquality()) { + D_ASSERT(statement->Equals(other.statement.get())); + } + +#ifdef DEBUG + // Now perform checking on the expressions + D_ASSERT(select_list.size() == other.select_list.size()); + const auto expr_count = select_list.size(); + if (other.RequireEquality()) { + for (idx_t i = 0; i < expr_count; i++) { + D_ASSERT(!select_list[i]->Equals(nullptr)); + // Run the ToString, to verify that it doesn't crash + select_list[i]->ToString(); + + if (select_list[i]->HasSubquery()) { + continue; + } + + // Check that the expressions are equivalent + D_ASSERT(select_list[i]->Equals(other.select_list[i].get())); + // Check that the hashes are equivalent too + D_ASSERT(select_list[i]->Hash() == other.select_list[i]->Hash()); + + other.select_list[i]->Verify(); + } + } +#endif +} + +void StatementVerifier::CheckExpressions() const { +#ifdef DEBUG + D_ASSERT(type == VerificationType::ORIGINAL); + // Perform additional checking within the expressions + const auto expr_count = select_list.size(); + for (idx_t outer_idx = 0; outer_idx < expr_count; outer_idx++) { + auto hash = select_list[outer_idx]->Hash(); + for (idx_t inner_idx = 0; inner_idx < expr_count; inner_idx++) { + auto hash2 = select_list[inner_idx]->Hash(); + if (hash != hash2) { + // if the hashes are not equivalent, the expressions should not be equivalent + D_ASSERT(!select_list[outer_idx]->Equals(select_list[inner_idx].get())); + } + } + } +#endif +} + +bool StatementVerifier::Run( + ClientContext &context, const string &query, + const std::function(const string &, unique_ptr)> &run) { + bool failed = false; + + context.interrupted = false; + context.config.enable_optimizer = !DisableOptimizer(); + context.config.force_external = ForceExternal(); + try { + auto result = run(query, move(statement)); + if (result->HasError()) { + failed = true; + } + materialized_result = unique_ptr_cast(move(result)); + } catch (const Exception &ex) { + failed = true; + materialized_result = make_unique(PreservedError(ex)); + } catch (std::exception &ex) { + failed = true; + materialized_result = make_unique(PreservedError(ex)); + } + context.interrupted = false; + + return failed; +} + +string StatementVerifier::CompareResults(const StatementVerifier &other) { + D_ASSERT(type == VerificationType::ORIGINAL); + string error; + if (materialized_result->HasError() != other.materialized_result->HasError()) { // LCOV_EXCL_START + string result = other.name + " statement differs from original result!\n"; + result += "Original Result:\n" + materialized_result->ToString(); + result += other.name + ":\n" + other.materialized_result->ToString(); + return result; + } // LCOV_EXCL_STOP + if (materialized_result->HasError()) { + return ""; + } + if (!ColumnDataCollection::ResultEquals(materialized_result->Collection(), other.materialized_result->Collection(), + error)) { // LCOV_EXCL_START + string result = other.name + " statement differs from original result!\n"; + result += "Original Result:\n" + materialized_result->ToString(); + result += other.name + ":\n" + other.materialized_result->ToString(); + result += "\n\n---------------------------------\n" + error; + return result; + } // LCOV_EXCL_STOP + + return ""; +} + +} // namespace duckdb + + +namespace duckdb { + +UnoptimizedStatementVerifier::UnoptimizedStatementVerifier(unique_ptr statement_p) + : StatementVerifier(VerificationType::UNOPTIMIZED, "Unoptimized", move(statement_p)) { +} + +unique_ptr UnoptimizedStatementVerifier::Create(const SQLStatement &statement_p) { + return make_unique(statement_p.Copy()); +} + +} // namespace duckdb // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2 // See the end of this file for a list // Formatting library for C++ @@ -196784,7 +214779,7 @@ void UndoBuffer::Rollback() noexcept { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2 // See the end of this file for a list // Formatting library for C++ - implementation @@ -198181,7 +216176,7 @@ FMT_END_NAMESPACE // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #4 // See the end of this file for a list /************************************************************************** @@ -205733,7 +223728,7 @@ mz_bool mz_zip_end(mz_zip_archive *pZip) // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2008 The RE2 Authors. All Rights Reserved. @@ -205765,7 +223760,7 @@ mz_bool mz_zip_end(mz_zip_archive *pZip) // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2018 The RE2 Authors. All Rights Reserved. @@ -205830,7 +223825,7 @@ class PODArray { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2007 The RE2 Authors. All Rights Reserved. @@ -205857,7 +223852,7 @@ class PODArray { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2006 The RE2 Authors. All Rights Reserved. @@ -206259,7 +224254,7 @@ template bool SparseArray::less(const IndexValue& a, // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2006 The RE2 Authors. All Rights Reserved. @@ -207301,7 +225296,7 @@ bool Prog::SearchBitState(const StringPiece& text, // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2007 The RE2 Authors. All Rights Reserved. @@ -207328,7 +225323,7 @@ bool Prog::SearchBitState(const StringPiece& text, // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2006 The RE2 Authors. All Rights Reserved. @@ -208844,7 +226839,7 @@ Prog* Prog::CompileSet(Regexp* re, RE2::Anchor anchor, int64_t max_mem) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2008 The RE2 Authors. All Rights Reserved. @@ -208889,7 +226884,7 @@ Prog* Prog::CompileSet(Regexp* re, RE2::Anchor anchor, int64_t max_mem) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2016 The RE2 Authors. All Rights Reserved. @@ -208940,7 +226935,7 @@ class HashMix { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2007 The RE2 Authors. All Rights Reserved. @@ -209084,7 +227079,7 @@ class WriterMutexLock { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2016 The RE2 Authors. All Rights Reserved. @@ -211160,7 +229155,7 @@ bool Prog::PossibleMatchRange(std::string* min, std::string* max, int maxlen) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2009 The RE2 Authors. All Rights Reserved. @@ -211170,7 +229165,7 @@ bool Prog::PossibleMatchRange(std::string* min, std::string* max, int maxlen) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2009 The RE2 Authors. All Rights Reserved. @@ -211296,7 +229291,7 @@ class FilteredRE2 { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2009 The RE2 Authors. All Rights Reserved. @@ -211414,7 +229409,7 @@ class Prefilter { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2009 The RE2 Authors. All Rights Reserved. @@ -211674,7 +229669,7 @@ void FilteredRE2::PrintPrefilter(int regexpid) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2008 The RE2 Authors. All Rights Reserved. @@ -211870,7 +229865,7 @@ static bool CanBeEmptyString(Regexp* re) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2006-2007 The RE2 Authors. All Rights Reserved. @@ -212593,7 +230588,7 @@ void Prog::Fanout(SparseArray* fanout) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2008 The RE2 Authors. All Rights Reserved. @@ -213177,7 +231172,7 @@ bool Prog::IsOnePass() { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2006 The RE2 Authors. All Rights Reserved. @@ -213217,7 +231212,7 @@ bool Prog::IsOnePass() { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2008 The RE2 Authors. All Rights Reserved. @@ -213305,7 +231300,7 @@ extern Rune ApplyFold(const CaseFold *f, Rune r); // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2008 The RE2 Authors. All Rights Reserved. @@ -215813,7 +233808,7 @@ Regexp* Regexp::Parse(const StringPiece& s, ParseFlags global_flags, // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // GENERATED BY make_perl_groups.pl; DO NOT EDIT. @@ -215941,7 +233936,7 @@ const int num_posix_groups = 28; // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2009 The RE2 Authors. All Rights Reserved. @@ -216642,7 +234637,7 @@ Prefilter* Prefilter::FromRE2(const RE2* re2) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2009 The RE2 Authors. All Rights Reserved. @@ -217053,7 +235048,7 @@ std::string PrefilterTree::DebugNodeString(Prefilter* node) const { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2007 The RE2 Authors. All Rights Reserved. @@ -217077,7 +235072,7 @@ std::string PrefilterTree::DebugNodeString(Prefilter* node) const { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2016 The RE2 Authors. All Rights Reserved. @@ -218103,7 +236098,7 @@ void Prog::ComputeHints(std::vector* flat, int begin, int end) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2003-2009 The RE2 Authors. All Rights Reserved. @@ -219347,7 +237342,7 @@ DEFINE_INTEGER_PARSER(ulonglong) // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2006 The RE2 Authors. All Rights Reserved. @@ -220327,7 +238322,7 @@ CharClass* CharClassBuilder::GetCharClass() { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2010 The RE2 Authors. All Rights Reserved. @@ -220337,7 +238332,7 @@ CharClass* CharClassBuilder::GetCharClass() { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2010 The RE2 Authors. All Rights Reserved. @@ -220578,7 +238573,7 @@ bool RE2::Set::Match(const StringPiece& text, std::vector* v, // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2006 The RE2 Authors. All Rights Reserved. @@ -221243,7 +239238,7 @@ Regexp* SimplifyWalker::SimplifyCharClass(Regexp* re) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2004 The RE2 Authors. All Rights Reserved. @@ -221317,7 +239312,7 @@ std::ostream& operator<<(std::ostream& o, const StringPiece& p) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 2006 The RE2 Authors. All Rights Reserved. @@ -221675,7 +239670,7 @@ static void AppendCCRange(std::string* t, Rune lo, Rune hi) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list @@ -222251,7 +240246,7 @@ const int num_unicode_tolower = 194; // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list @@ -228319,7 +246314,7 @@ const int num_unicode_groups = 184; // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list /* @@ -228588,7 +246583,7 @@ utfrune(const char *s, Rune c) // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #6 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #5 // See the end of this file for a list // Copyright 1999-2005 The RE2 Authors. All Rights Reserved. @@ -228761,7 +246756,7 @@ void StringAppendF(std::string* dst, const char* format, ...) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1 // See the end of this file for a list /* hyperloglog.c - Redis HyperLogLog probabilistic cardinality approximation. @@ -228802,7 +246797,7 @@ void StringAppendF(std::string* dst, const char* format, ...) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1 // See the end of this file for a list /* SDSLib 2.0 -- A C dynamic strings library @@ -230316,7 +248311,7 @@ static inline int AddToLog(void *log, const uint64_t &index, const uint8_t &coun return duckdb_hll::hllDenseSet(hdr->registers + 1, index, count); } -void AddToLogsInternal(VectorData &vdata, idx_t count, uint64_t indices[], uint8_t counts[], void ***logs[], +void AddToLogsInternal(UnifiedVectorFormat &vdata, idx_t count, uint64_t indices[], uint8_t counts[], void ***logs[], const SelectionVector *log_sel) { // 'logs' is an array of pointers to AggregateStates // AggregateStates have a pointer to a HyperLogLog object @@ -230329,7 +248324,7 @@ void AddToLogsInternal(VectorData &vdata, idx_t count, uint64_t indices[], uint8 } } -void AddToSingleLogInternal(VectorData &vdata, idx_t count, uint64_t indices[], uint8_t counts[], void *log) { +void AddToSingleLogInternal(UnifiedVectorFormat &vdata, idx_t count, uint64_t indices[], uint8_t counts[], void *log) { const auto o = (duckdb_hll::robj *)log; duckdb_hll::hllhdr *hdr = (duckdb_hll::hllhdr *)o->ptr; D_ASSERT(hdr->encoding == HLL_DENSE); @@ -230349,7 +248344,7 @@ void AddToSingleLogInternal(VectorData &vdata, idx_t count, uint64_t indices[], // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #7 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1 // See the end of this file for a list /* SDSLib 2.0 -- A C dynamic strings library @@ -231472,7 +249467,7 @@ void sdfree(void *ptr) { free(ptr); } // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #12 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #14 // See the end of this file for a list @@ -232765,7 +250760,7 @@ void __fastpack64(const uint64_t *__restrict in, uint32_t *__restrict out) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3 // See the end of this file for a list /* -*- mode: c; c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil -*- */ @@ -232825,7 +250820,7 @@ namespace duckdb { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3 // See the end of this file for a list static const utf8proc_uint16_t utf8proc_sequences[] = { @@ -248479,7 +266474,7 @@ UTF8PROC_DLLEXPORT utf8proc_uint8_t *utf8proc_NFKC_Casefold(const utf8proc_uint8 // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #2 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #3 // See the end of this file for a list @@ -248611,7 +266606,7 @@ size_t Utf8Proc::RenderWidth(const char *s, size_t len, size_t pos) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list #include @@ -248621,7 +266616,7 @@ size_t Utf8Proc::RenderWidth(const char *s, size_t len, size_t pos) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list @@ -248947,7 +266942,7 @@ PGNode *newNode(size_t size, PGNodeTag type) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list @@ -248957,7 +266952,7 @@ PGNode *newNode(size_t size, PGNodeTag type) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -248996,7 +266991,7 @@ bool get_preserve_identifier_case(); // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -249086,7 +267081,7 @@ void PostgresParser::SetPreserveIdentifierCase(bool preserve) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*-------------------------------------------------------------------- @@ -249634,7 +267629,7 @@ int length(const PGList *list); // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*-------------------------------------------------------------------- @@ -249675,7 +267670,7 @@ int length(const PGList *list); // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -249710,7 +267705,7 @@ typedef struct PGFunctionCallInfoData *PGFunctionCallInfo; // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -249788,7 +267783,7 @@ PGGroupingSet *makeGroupingSet(GroupingSetKind kind, PGList *content, int locati // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -250135,7 +268130,7 @@ PGGroupingSet *makeGroupingSet(GroupingSetKind kind, PGList *content, int locati // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*-------------------------------------------------------------------- @@ -250217,7 +268212,7 @@ PGValue *makeString(const char *str) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /* A Bison parser, made by GNU Bison 2.3. */ @@ -250308,478 +268303,479 @@ PGValue *makeString(const char *str) { DOT_DOT = 267, COLON_EQUALS = 268, EQUALS_GREATER = 269, - LAMBDA_ARROW = 270, - POWER_OF = 271, - LESS_EQUALS = 272, - GREATER_EQUALS = 273, - NOT_EQUALS = 274, - ABORT_P = 275, - ABSOLUTE_P = 276, - ACCESS = 277, - ACTION = 278, - ADD_P = 279, - ADMIN = 280, - AFTER = 281, - AGGREGATE = 282, - ALL = 283, - ALSO = 284, - ALTER = 285, - ALWAYS = 286, - ANALYSE = 287, - ANALYZE = 288, - AND = 289, - ANY = 290, - ARRAY = 291, - AS = 292, - ASC_P = 293, - ASSERTION = 294, - ASSIGNMENT = 295, - ASYMMETRIC = 296, - AT = 297, - ATTACH = 298, - ATTRIBUTE = 299, - AUTHORIZATION = 300, - BACKWARD = 301, - BEFORE = 302, - BEGIN_P = 303, - BETWEEN = 304, - BIGINT = 305, - BINARY = 306, - BIT = 307, - BOOLEAN_P = 308, - BOTH = 309, - BY = 310, - CACHE = 311, - CALL_P = 312, - CALLED = 313, - CASCADE = 314, - CASCADED = 315, - CASE = 316, - CAST = 317, - CATALOG_P = 318, - CHAIN = 319, - CHAR_P = 320, - CHARACTER = 321, - CHARACTERISTICS = 322, - CHECK_P = 323, - CHECKPOINT = 324, - CLASS = 325, - CLOSE = 326, - CLUSTER = 327, - COALESCE = 328, - COLLATE = 329, - COLLATION = 330, - COLUMN = 331, - COLUMNS = 332, - COMMENT = 333, - COMMENTS = 334, - COMMIT = 335, - COMMITTED = 336, - COMPRESSION = 337, - CONCURRENTLY = 338, - CONFIGURATION = 339, - CONFLICT = 340, - CONNECTION = 341, - CONSTRAINT = 342, - CONSTRAINTS = 343, - CONTENT_P = 344, - CONTINUE_P = 345, - CONVERSION_P = 346, - COPY = 347, - COST = 348, - CREATE_P = 349, - CROSS = 350, - CSV = 351, - CUBE = 352, - CURRENT_P = 353, - CURRENT_CATALOG = 354, - CURRENT_DATE = 355, - CURRENT_ROLE = 356, - CURRENT_SCHEMA = 357, - CURRENT_TIME = 358, - CURRENT_TIMESTAMP = 359, - CURRENT_USER = 360, - CURSOR = 361, - CYCLE = 362, - DATA_P = 363, - DATABASE = 364, - DAY_P = 365, - DAYS_P = 366, - DEALLOCATE = 367, - DEC = 368, - DECIMAL_P = 369, - DECLARE = 370, - DEFAULT = 371, - DEFAULTS = 372, - DEFERRABLE = 373, - DEFERRED = 374, - DEFINER = 375, - DELETE_P = 376, - DELIMITER = 377, - DELIMITERS = 378, - DEPENDS = 379, - DESC_P = 380, - DESCRIBE = 381, - DETACH = 382, - DICTIONARY = 383, - DISABLE_P = 384, - DISCARD = 385, - DISTINCT = 386, - DO = 387, - DOCUMENT_P = 388, - DOMAIN_P = 389, - DOUBLE_P = 390, - DROP = 391, - EACH = 392, - ELSE = 393, - ENABLE_P = 394, - ENCODING = 395, - ENCRYPTED = 396, - END_P = 397, - ENUM_P = 398, - ESCAPE = 399, - EVENT = 400, - EXCEPT = 401, - EXCLUDE = 402, - EXCLUDING = 403, - EXCLUSIVE = 404, - EXECUTE = 405, - EXISTS = 406, - EXPLAIN = 407, - EXPORT_P = 408, - EXPORT_STATE = 409, - EXTENSION = 410, - EXTERNAL = 411, - EXTRACT = 412, - FALSE_P = 413, - FAMILY = 414, - FETCH = 415, - FILTER = 416, - FIRST_P = 417, - FLOAT_P = 418, - FOLLOWING = 419, - FOR = 420, - FORCE = 421, - FOREIGN = 422, - FORWARD = 423, - FREEZE = 424, - FROM = 425, - FULL = 426, - FUNCTION = 427, - FUNCTIONS = 428, - GENERATED = 429, - GLOB = 430, - GLOBAL = 431, - GRANT = 432, - GRANTED = 433, - GROUP_P = 434, - GROUPING = 435, - GROUPING_ID = 436, - HANDLER = 437, - HAVING = 438, - HEADER_P = 439, - HOLD = 440, - HOUR_P = 441, - HOURS_P = 442, - IDENTITY_P = 443, - IF_P = 444, - IGNORE_P = 445, - ILIKE = 446, - IMMEDIATE = 447, - IMMUTABLE = 448, - IMPLICIT_P = 449, - IMPORT_P = 450, - IN_P = 451, - INCLUDING = 452, - INCREMENT = 453, - INDEX = 454, - INDEXES = 455, - INHERIT = 456, - INHERITS = 457, - INITIALLY = 458, - INLINE_P = 459, - INNER_P = 460, - INOUT = 461, - INPUT_P = 462, - INSENSITIVE = 463, - INSERT = 464, - INSTALL = 465, - INSTEAD = 466, - INT_P = 467, - INTEGER = 468, - INTERSECT = 469, - INTERVAL = 470, - INTO = 471, - INVOKER = 472, - IS = 473, - ISNULL = 474, - ISOLATION = 475, - JOIN = 476, - JSON = 477, - KEY = 478, - LABEL = 479, - LANGUAGE = 480, - LARGE_P = 481, - LAST_P = 482, - LATERAL_P = 483, - LEADING = 484, - LEAKPROOF = 485, - LEFT = 486, - LEVEL = 487, - LIKE = 488, - LIMIT = 489, - LISTEN = 490, - LOAD = 491, - LOCAL = 492, - LOCALTIME = 493, - LOCALTIMESTAMP = 494, - LOCATION = 495, - LOCK_P = 496, - LOCKED = 497, - LOGGED = 498, - MACRO = 499, - MAP = 500, - MAPPING = 501, - MATCH = 502, - MATERIALIZED = 503, - MAXVALUE = 504, - METHOD = 505, - MICROSECOND_P = 506, - MICROSECONDS_P = 507, - MILLISECOND_P = 508, - MILLISECONDS_P = 509, - MINUTE_P = 510, - MINUTES_P = 511, - MINVALUE = 512, - MODE = 513, - MONTH_P = 514, - MONTHS_P = 515, - MOVE = 516, - NAME_P = 517, - NAMES = 518, - NATIONAL = 519, - NATURAL = 520, - NCHAR = 521, - NEW = 522, - NEXT = 523, - NO = 524, - NONE = 525, - NOT = 526, - NOTHING = 527, - NOTIFY = 528, - NOTNULL = 529, - NOWAIT = 530, - NULL_P = 531, - NULLIF = 532, - NULLS_P = 533, - NUMERIC = 534, - OBJECT_P = 535, - OF = 536, - OFF = 537, - OFFSET = 538, - OIDS = 539, - OLD = 540, - ON = 541, - ONLY = 542, - OPERATOR = 543, - OPTION = 544, - OPTIONS = 545, - OR = 546, - ORDER = 547, - ORDINALITY = 548, - OUT_P = 549, - OUTER_P = 550, - OVER = 551, - OVERLAPS = 552, - OVERLAY = 553, - OVERRIDING = 554, - OWNED = 555, - OWNER = 556, - PARALLEL = 557, - PARSER = 558, - PARTIAL = 559, - PARTITION = 560, - PASSING = 561, - PASSWORD = 562, - PERCENT = 563, - PLACING = 564, - PLANS = 565, - POLICY = 566, - POSITION = 567, - PRAGMA_P = 568, - PRECEDING = 569, - PRECISION = 570, - PREPARE = 571, - PREPARED = 572, - PRESERVE = 573, - PRIMARY = 574, - PRIOR = 575, - PRIVILEGES = 576, - PROCEDURAL = 577, - PROCEDURE = 578, - PROGRAM = 579, - PUBLICATION = 580, - QUALIFY = 581, - QUOTE = 582, - RANGE = 583, - READ_P = 584, - REAL = 585, - REASSIGN = 586, - RECHECK = 587, - RECURSIVE = 588, - REF = 589, - REFERENCES = 590, - REFERENCING = 591, - REFRESH = 592, - REINDEX = 593, - RELATIVE_P = 594, - RELEASE = 595, - RENAME = 596, - REPEATABLE = 597, - REPLACE = 598, - REPLICA = 599, - RESET = 600, - RESPECT_P = 601, - RESTART = 602, - RESTRICT = 603, - RETURNING = 604, - RETURNS = 605, - REVOKE = 606, - RIGHT = 607, - ROLE = 608, - ROLLBACK = 609, - ROLLUP = 610, - ROW = 611, - ROWS = 612, - RULE = 613, - SAMPLE = 614, - SAVEPOINT = 615, - SCHEMA = 616, - SCHEMAS = 617, - SCROLL = 618, - SEARCH = 619, - SECOND_P = 620, - SECONDS_P = 621, - SECURITY = 622, - SELECT = 623, - SEQUENCE = 624, - SEQUENCES = 625, - SERIALIZABLE = 626, - SERVER = 627, - SESSION = 628, - SESSION_USER = 629, - SET = 630, - SETOF = 631, - SETS = 632, - SHARE = 633, - SHOW = 634, - SIMILAR = 635, - SIMPLE = 636, - SKIP = 637, - SMALLINT = 638, - SNAPSHOT = 639, - SOME = 640, - SQL_P = 641, - STABLE = 642, - STANDALONE_P = 643, - START = 644, - STATEMENT = 645, - STATISTICS = 646, - STDIN = 647, - STDOUT = 648, - STORAGE = 649, - STORED = 650, - STRICT_P = 651, - STRIP_P = 652, - STRUCT = 653, - SUBSCRIPTION = 654, - SUBSTRING = 655, - SUMMARIZE = 656, - SYMMETRIC = 657, - SYSID = 658, - SYSTEM_P = 659, - TABLE = 660, - TABLES = 661, - TABLESAMPLE = 662, - TABLESPACE = 663, - TEMP = 664, - TEMPLATE = 665, - TEMPORARY = 666, - TEXT_P = 667, - THEN = 668, - TIME = 669, - TIMESTAMP = 670, - TO = 671, - TRAILING = 672, - TRANSACTION = 673, - TRANSFORM = 674, - TREAT = 675, - TRIGGER = 676, - TRIM = 677, - TRUE_P = 678, - TRUNCATE = 679, - TRUSTED = 680, - TRY_CAST = 681, - TYPE_P = 682, - TYPES_P = 683, - UNBOUNDED = 684, - UNCOMMITTED = 685, - UNENCRYPTED = 686, - UNION = 687, - UNIQUE = 688, - UNKNOWN = 689, - UNLISTEN = 690, - UNLOGGED = 691, - UNTIL = 692, - UPDATE = 693, - USER = 694, - USING = 695, - VACUUM = 696, - VALID = 697, - VALIDATE = 698, - VALIDATOR = 699, - VALUE_P = 700, - VALUES = 701, - VARCHAR = 702, - VARIADIC = 703, - VARYING = 704, - VERBOSE = 705, - VERSION_P = 706, - VIEW = 707, - VIEWS = 708, - VIRTUAL = 709, - VOLATILE = 710, - WHEN = 711, - WHERE = 712, - WHITESPACE_P = 713, - WINDOW = 714, - WITH = 715, - WITHIN = 716, - WITHOUT = 717, - WORK = 718, - WRAPPER = 719, - WRITE_P = 720, - XML_P = 721, - XMLATTRIBUTES = 722, - XMLCONCAT = 723, - XMLELEMENT = 724, - XMLEXISTS = 725, - XMLFOREST = 726, - XMLNAMESPACES = 727, - XMLPARSE = 728, - XMLPI = 729, - XMLROOT = 730, - XMLSERIALIZE = 731, - XMLTABLE = 732, - YEAR_P = 733, - YEARS_P = 734, - YES_P = 735, - ZONE = 736, - NOT_LA = 737, - NULLS_LA = 738, - WITH_LA = 739, - POSTFIXOP = 740, - UMINUS = 741 + POWER_OF = 270, + LAMBDA_ARROW = 271, + DOUBLE_ARROW = 272, + LESS_EQUALS = 273, + GREATER_EQUALS = 274, + NOT_EQUALS = 275, + ABORT_P = 276, + ABSOLUTE_P = 277, + ACCESS = 278, + ACTION = 279, + ADD_P = 280, + ADMIN = 281, + AFTER = 282, + AGGREGATE = 283, + ALL = 284, + ALSO = 285, + ALTER = 286, + ALWAYS = 287, + ANALYSE = 288, + ANALYZE = 289, + AND = 290, + ANY = 291, + ARRAY = 292, + AS = 293, + ASC_P = 294, + ASSERTION = 295, + ASSIGNMENT = 296, + ASYMMETRIC = 297, + AT = 298, + ATTACH = 299, + ATTRIBUTE = 300, + AUTHORIZATION = 301, + BACKWARD = 302, + BEFORE = 303, + BEGIN_P = 304, + BETWEEN = 305, + BIGINT = 306, + BINARY = 307, + BIT = 308, + BOOLEAN_P = 309, + BOTH = 310, + BY = 311, + CACHE = 312, + CALL_P = 313, + CALLED = 314, + CASCADE = 315, + CASCADED = 316, + CASE = 317, + CAST = 318, + CATALOG_P = 319, + CHAIN = 320, + CHAR_P = 321, + CHARACTER = 322, + CHARACTERISTICS = 323, + CHECK_P = 324, + CHECKPOINT = 325, + CLASS = 326, + CLOSE = 327, + CLUSTER = 328, + COALESCE = 329, + COLLATE = 330, + COLLATION = 331, + COLUMN = 332, + COLUMNS = 333, + COMMENT = 334, + COMMENTS = 335, + COMMIT = 336, + COMMITTED = 337, + COMPRESSION = 338, + CONCURRENTLY = 339, + CONFIGURATION = 340, + CONFLICT = 341, + CONNECTION = 342, + CONSTRAINT = 343, + CONSTRAINTS = 344, + CONTENT_P = 345, + CONTINUE_P = 346, + CONVERSION_P = 347, + COPY = 348, + COST = 349, + CREATE_P = 350, + CROSS = 351, + CSV = 352, + CUBE = 353, + CURRENT_P = 354, + CURRENT_CATALOG = 355, + CURRENT_DATE = 356, + CURRENT_ROLE = 357, + CURRENT_SCHEMA = 358, + CURRENT_TIME = 359, + CURRENT_TIMESTAMP = 360, + CURRENT_USER = 361, + CURSOR = 362, + CYCLE = 363, + DATA_P = 364, + DATABASE = 365, + DAY_P = 366, + DAYS_P = 367, + DEALLOCATE = 368, + DEC = 369, + DECIMAL_P = 370, + DECLARE = 371, + DEFAULT = 372, + DEFAULTS = 373, + DEFERRABLE = 374, + DEFERRED = 375, + DEFINER = 376, + DELETE_P = 377, + DELIMITER = 378, + DELIMITERS = 379, + DEPENDS = 380, + DESC_P = 381, + DESCRIBE = 382, + DETACH = 383, + DICTIONARY = 384, + DISABLE_P = 385, + DISCARD = 386, + DISTINCT = 387, + DO = 388, + DOCUMENT_P = 389, + DOMAIN_P = 390, + DOUBLE_P = 391, + DROP = 392, + EACH = 393, + ELSE = 394, + ENABLE_P = 395, + ENCODING = 396, + ENCRYPTED = 397, + END_P = 398, + ENUM_P = 399, + ESCAPE = 400, + EVENT = 401, + EXCEPT = 402, + EXCLUDE = 403, + EXCLUDING = 404, + EXCLUSIVE = 405, + EXECUTE = 406, + EXISTS = 407, + EXPLAIN = 408, + EXPORT_P = 409, + EXPORT_STATE = 410, + EXTENSION = 411, + EXTERNAL = 412, + EXTRACT = 413, + FALSE_P = 414, + FAMILY = 415, + FETCH = 416, + FILTER = 417, + FIRST_P = 418, + FLOAT_P = 419, + FOLLOWING = 420, + FOR = 421, + FORCE = 422, + FOREIGN = 423, + FORWARD = 424, + FREEZE = 425, + FROM = 426, + FULL = 427, + FUNCTION = 428, + FUNCTIONS = 429, + GENERATED = 430, + GLOB = 431, + GLOBAL = 432, + GRANT = 433, + GRANTED = 434, + GROUP_P = 435, + GROUPING = 436, + GROUPING_ID = 437, + HANDLER = 438, + HAVING = 439, + HEADER_P = 440, + HOLD = 441, + HOUR_P = 442, + HOURS_P = 443, + IDENTITY_P = 444, + IF_P = 445, + IGNORE_P = 446, + ILIKE = 447, + IMMEDIATE = 448, + IMMUTABLE = 449, + IMPLICIT_P = 450, + IMPORT_P = 451, + IN_P = 452, + INCLUDING = 453, + INCREMENT = 454, + INDEX = 455, + INDEXES = 456, + INHERIT = 457, + INHERITS = 458, + INITIALLY = 459, + INLINE_P = 460, + INNER_P = 461, + INOUT = 462, + INPUT_P = 463, + INSENSITIVE = 464, + INSERT = 465, + INSTALL = 466, + INSTEAD = 467, + INT_P = 468, + INTEGER = 469, + INTERSECT = 470, + INTERVAL = 471, + INTO = 472, + INVOKER = 473, + IS = 474, + ISNULL = 475, + ISOLATION = 476, + JOIN = 477, + JSON = 478, + KEY = 479, + LABEL = 480, + LANGUAGE = 481, + LARGE_P = 482, + LAST_P = 483, + LATERAL_P = 484, + LEADING = 485, + LEAKPROOF = 486, + LEFT = 487, + LEVEL = 488, + LIKE = 489, + LIMIT = 490, + LISTEN = 491, + LOAD = 492, + LOCAL = 493, + LOCALTIME = 494, + LOCALTIMESTAMP = 495, + LOCATION = 496, + LOCK_P = 497, + LOCKED = 498, + LOGGED = 499, + MACRO = 500, + MAP = 501, + MAPPING = 502, + MATCH = 503, + MATERIALIZED = 504, + MAXVALUE = 505, + METHOD = 506, + MICROSECOND_P = 507, + MICROSECONDS_P = 508, + MILLISECOND_P = 509, + MILLISECONDS_P = 510, + MINUTE_P = 511, + MINUTES_P = 512, + MINVALUE = 513, + MODE = 514, + MONTH_P = 515, + MONTHS_P = 516, + MOVE = 517, + NAME_P = 518, + NAMES = 519, + NATIONAL = 520, + NATURAL = 521, + NCHAR = 522, + NEW = 523, + NEXT = 524, + NO = 525, + NONE = 526, + NOT = 527, + NOTHING = 528, + NOTIFY = 529, + NOTNULL = 530, + NOWAIT = 531, + NULL_P = 532, + NULLIF = 533, + NULLS_P = 534, + NUMERIC = 535, + OBJECT_P = 536, + OF = 537, + OFF = 538, + OFFSET = 539, + OIDS = 540, + OLD = 541, + ON = 542, + ONLY = 543, + OPERATOR = 544, + OPTION = 545, + OPTIONS = 546, + OR = 547, + ORDER = 548, + ORDINALITY = 549, + OUT_P = 550, + OUTER_P = 551, + OVER = 552, + OVERLAPS = 553, + OVERLAY = 554, + OVERRIDING = 555, + OWNED = 556, + OWNER = 557, + PARALLEL = 558, + PARSER = 559, + PARTIAL = 560, + PARTITION = 561, + PASSING = 562, + PASSWORD = 563, + PERCENT = 564, + PLACING = 565, + PLANS = 566, + POLICY = 567, + POSITION = 568, + PRAGMA_P = 569, + PRECEDING = 570, + PRECISION = 571, + PREPARE = 572, + PREPARED = 573, + PRESERVE = 574, + PRIMARY = 575, + PRIOR = 576, + PRIVILEGES = 577, + PROCEDURAL = 578, + PROCEDURE = 579, + PROGRAM = 580, + PUBLICATION = 581, + QUALIFY = 582, + QUOTE = 583, + RANGE = 584, + READ_P = 585, + REAL = 586, + REASSIGN = 587, + RECHECK = 588, + RECURSIVE = 589, + REF = 590, + REFERENCES = 591, + REFERENCING = 592, + REFRESH = 593, + REINDEX = 594, + RELATIVE_P = 595, + RELEASE = 596, + RENAME = 597, + REPEATABLE = 598, + REPLACE = 599, + REPLICA = 600, + RESET = 601, + RESPECT_P = 602, + RESTART = 603, + RESTRICT = 604, + RETURNING = 605, + RETURNS = 606, + REVOKE = 607, + RIGHT = 608, + ROLE = 609, + ROLLBACK = 610, + ROLLUP = 611, + ROW = 612, + ROWS = 613, + RULE = 614, + SAMPLE = 615, + SAVEPOINT = 616, + SCHEMA = 617, + SCHEMAS = 618, + SCROLL = 619, + SEARCH = 620, + SECOND_P = 621, + SECONDS_P = 622, + SECURITY = 623, + SELECT = 624, + SEQUENCE = 625, + SEQUENCES = 626, + SERIALIZABLE = 627, + SERVER = 628, + SESSION = 629, + SESSION_USER = 630, + SET = 631, + SETOF = 632, + SETS = 633, + SHARE = 634, + SHOW = 635, + SIMILAR = 636, + SIMPLE = 637, + SKIP = 638, + SMALLINT = 639, + SNAPSHOT = 640, + SOME = 641, + SQL_P = 642, + STABLE = 643, + STANDALONE_P = 644, + START = 645, + STATEMENT = 646, + STATISTICS = 647, + STDIN = 648, + STDOUT = 649, + STORAGE = 650, + STORED = 651, + STRICT_P = 652, + STRIP_P = 653, + STRUCT = 654, + SUBSCRIPTION = 655, + SUBSTRING = 656, + SUMMARIZE = 657, + SYMMETRIC = 658, + SYSID = 659, + SYSTEM_P = 660, + TABLE = 661, + TABLES = 662, + TABLESAMPLE = 663, + TABLESPACE = 664, + TEMP = 665, + TEMPLATE = 666, + TEMPORARY = 667, + TEXT_P = 668, + THEN = 669, + TIME = 670, + TIMESTAMP = 671, + TO = 672, + TRAILING = 673, + TRANSACTION = 674, + TRANSFORM = 675, + TREAT = 676, + TRIGGER = 677, + TRIM = 678, + TRUE_P = 679, + TRUNCATE = 680, + TRUSTED = 681, + TRY_CAST = 682, + TYPE_P = 683, + TYPES_P = 684, + UNBOUNDED = 685, + UNCOMMITTED = 686, + UNENCRYPTED = 687, + UNION = 688, + UNIQUE = 689, + UNKNOWN = 690, + UNLISTEN = 691, + UNLOGGED = 692, + UNTIL = 693, + UPDATE = 694, + USER = 695, + USING = 696, + VACUUM = 697, + VALID = 698, + VALIDATE = 699, + VALIDATOR = 700, + VALUE_P = 701, + VALUES = 702, + VARCHAR = 703, + VARIADIC = 704, + VARYING = 705, + VERBOSE = 706, + VERSION_P = 707, + VIEW = 708, + VIEWS = 709, + VIRTUAL = 710, + VOLATILE = 711, + WHEN = 712, + WHERE = 713, + WHITESPACE_P = 714, + WINDOW = 715, + WITH = 716, + WITHIN = 717, + WITHOUT = 718, + WORK = 719, + WRAPPER = 720, + WRITE_P = 721, + XML_P = 722, + XMLATTRIBUTES = 723, + XMLCONCAT = 724, + XMLELEMENT = 725, + XMLEXISTS = 726, + XMLFOREST = 727, + XMLNAMESPACES = 728, + XMLPARSE = 729, + XMLPI = 730, + XMLROOT = 731, + XMLSERIALIZE = 732, + XMLTABLE = 733, + YEAR_P = 734, + YEARS_P = 735, + YES_P = 736, + ZONE = 737, + NOT_LA = 738, + NULLS_LA = 739, + WITH_LA = 740, + POSTFIXOP = 741, + UMINUS = 742 }; #endif /* Tokens. */ @@ -250795,478 +268791,479 @@ PGValue *makeString(const char *str) { #define DOT_DOT 267 #define COLON_EQUALS 268 #define EQUALS_GREATER 269 -#define LAMBDA_ARROW 270 -#define POWER_OF 271 -#define LESS_EQUALS 272 -#define GREATER_EQUALS 273 -#define NOT_EQUALS 274 -#define ABORT_P 275 -#define ABSOLUTE_P 276 -#define ACCESS 277 -#define ACTION 278 -#define ADD_P 279 -#define ADMIN 280 -#define AFTER 281 -#define AGGREGATE 282 -#define ALL 283 -#define ALSO 284 -#define ALTER 285 -#define ALWAYS 286 -#define ANALYSE 287 -#define ANALYZE 288 -#define AND 289 -#define ANY 290 -#define ARRAY 291 -#define AS 292 -#define ASC_P 293 -#define ASSERTION 294 -#define ASSIGNMENT 295 -#define ASYMMETRIC 296 -#define AT 297 -#define ATTACH 298 -#define ATTRIBUTE 299 -#define AUTHORIZATION 300 -#define BACKWARD 301 -#define BEFORE 302 -#define BEGIN_P 303 -#define BETWEEN 304 -#define BIGINT 305 -#define BINARY 306 -#define BIT 307 -#define BOOLEAN_P 308 -#define BOTH 309 -#define BY 310 -#define CACHE 311 -#define CALL_P 312 -#define CALLED 313 -#define CASCADE 314 -#define CASCADED 315 -#define CASE 316 -#define CAST 317 -#define CATALOG_P 318 -#define CHAIN 319 -#define CHAR_P 320 -#define CHARACTER 321 -#define CHARACTERISTICS 322 -#define CHECK_P 323 -#define CHECKPOINT 324 -#define CLASS 325 -#define CLOSE 326 -#define CLUSTER 327 -#define COALESCE 328 -#define COLLATE 329 -#define COLLATION 330 -#define COLUMN 331 -#define COLUMNS 332 -#define COMMENT 333 -#define COMMENTS 334 -#define COMMIT 335 -#define COMMITTED 336 -#define COMPRESSION 337 -#define CONCURRENTLY 338 -#define CONFIGURATION 339 -#define CONFLICT 340 -#define CONNECTION 341 -#define CONSTRAINT 342 -#define CONSTRAINTS 343 -#define CONTENT_P 344 -#define CONTINUE_P 345 -#define CONVERSION_P 346 -#define COPY 347 -#define COST 348 -#define CREATE_P 349 -#define CROSS 350 -#define CSV 351 -#define CUBE 352 -#define CURRENT_P 353 -#define CURRENT_CATALOG 354 -#define CURRENT_DATE 355 -#define CURRENT_ROLE 356 -#define CURRENT_SCHEMA 357 -#define CURRENT_TIME 358 -#define CURRENT_TIMESTAMP 359 -#define CURRENT_USER 360 -#define CURSOR 361 -#define CYCLE 362 -#define DATA_P 363 -#define DATABASE 364 -#define DAY_P 365 -#define DAYS_P 366 -#define DEALLOCATE 367 -#define DEC 368 -#define DECIMAL_P 369 -#define DECLARE 370 -#define DEFAULT 371 -#define DEFAULTS 372 -#define DEFERRABLE 373 -#define DEFERRED 374 -#define DEFINER 375 -#define DELETE_P 376 -#define DELIMITER 377 -#define DELIMITERS 378 -#define DEPENDS 379 -#define DESC_P 380 -#define DESCRIBE 381 -#define DETACH 382 -#define DICTIONARY 383 -#define DISABLE_P 384 -#define DISCARD 385 -#define DISTINCT 386 -#define DO 387 -#define DOCUMENT_P 388 -#define DOMAIN_P 389 -#define DOUBLE_P 390 -#define DROP 391 -#define EACH 392 -#define ELSE 393 -#define ENABLE_P 394 -#define ENCODING 395 -#define ENCRYPTED 396 -#define END_P 397 -#define ENUM_P 398 -#define ESCAPE 399 -#define EVENT 400 -#define EXCEPT 401 -#define EXCLUDE 402 -#define EXCLUDING 403 -#define EXCLUSIVE 404 -#define EXECUTE 405 -#define EXISTS 406 -#define EXPLAIN 407 -#define EXPORT_P 408 -#define EXPORT_STATE 409 -#define EXTENSION 410 -#define EXTERNAL 411 -#define EXTRACT 412 -#define FALSE_P 413 -#define FAMILY 414 -#define FETCH 415 -#define FILTER 416 -#define FIRST_P 417 -#define FLOAT_P 418 -#define FOLLOWING 419 -#define FOR 420 -#define FORCE 421 -#define FOREIGN 422 -#define FORWARD 423 -#define FREEZE 424 -#define FROM 425 -#define FULL 426 -#define FUNCTION 427 -#define FUNCTIONS 428 -#define GENERATED 429 -#define GLOB 430 -#define GLOBAL 431 -#define GRANT 432 -#define GRANTED 433 -#define GROUP_P 434 -#define GROUPING 435 -#define GROUPING_ID 436 -#define HANDLER 437 -#define HAVING 438 -#define HEADER_P 439 -#define HOLD 440 -#define HOUR_P 441 -#define HOURS_P 442 -#define IDENTITY_P 443 -#define IF_P 444 -#define IGNORE_P 445 -#define ILIKE 446 -#define IMMEDIATE 447 -#define IMMUTABLE 448 -#define IMPLICIT_P 449 -#define IMPORT_P 450 -#define IN_P 451 -#define INCLUDING 452 -#define INCREMENT 453 -#define INDEX 454 -#define INDEXES 455 -#define INHERIT 456 -#define INHERITS 457 -#define INITIALLY 458 -#define INLINE_P 459 -#define INNER_P 460 -#define INOUT 461 -#define INPUT_P 462 -#define INSENSITIVE 463 -#define INSERT 464 -#define INSTALL 465 -#define INSTEAD 466 -#define INT_P 467 -#define INTEGER 468 -#define INTERSECT 469 -#define INTERVAL 470 -#define INTO 471 -#define INVOKER 472 -#define IS 473 -#define ISNULL 474 -#define ISOLATION 475 -#define JOIN 476 -#define JSON 477 -#define KEY 478 -#define LABEL 479 -#define LANGUAGE 480 -#define LARGE_P 481 -#define LAST_P 482 -#define LATERAL_P 483 -#define LEADING 484 -#define LEAKPROOF 485 -#define LEFT 486 -#define LEVEL 487 -#define LIKE 488 -#define LIMIT 489 -#define LISTEN 490 -#define LOAD 491 -#define LOCAL 492 -#define LOCALTIME 493 -#define LOCALTIMESTAMP 494 -#define LOCATION 495 -#define LOCK_P 496 -#define LOCKED 497 -#define LOGGED 498 -#define MACRO 499 -#define MAP 500 -#define MAPPING 501 -#define MATCH 502 -#define MATERIALIZED 503 -#define MAXVALUE 504 -#define METHOD 505 -#define MICROSECOND_P 506 -#define MICROSECONDS_P 507 -#define MILLISECOND_P 508 -#define MILLISECONDS_P 509 -#define MINUTE_P 510 -#define MINUTES_P 511 -#define MINVALUE 512 -#define MODE 513 -#define MONTH_P 514 -#define MONTHS_P 515 -#define MOVE 516 -#define NAME_P 517 -#define NAMES 518 -#define NATIONAL 519 -#define NATURAL 520 -#define NCHAR 521 -#define NEW 522 -#define NEXT 523 -#define NO 524 -#define NONE 525 -#define NOT 526 -#define NOTHING 527 -#define NOTIFY 528 -#define NOTNULL 529 -#define NOWAIT 530 -#define NULL_P 531 -#define NULLIF 532 -#define NULLS_P 533 -#define NUMERIC 534 -#define OBJECT_P 535 -#define OF 536 -#define OFF 537 -#define OFFSET 538 -#define OIDS 539 -#define OLD 540 -#define ON 541 -#define ONLY 542 -#define OPERATOR 543 -#define OPTION 544 -#define OPTIONS 545 -#define OR 546 -#define ORDER 547 -#define ORDINALITY 548 -#define OUT_P 549 -#define OUTER_P 550 -#define OVER 551 -#define OVERLAPS 552 -#define OVERLAY 553 -#define OVERRIDING 554 -#define OWNED 555 -#define OWNER 556 -#define PARALLEL 557 -#define PARSER 558 -#define PARTIAL 559 -#define PARTITION 560 -#define PASSING 561 -#define PASSWORD 562 -#define PERCENT 563 -#define PLACING 564 -#define PLANS 565 -#define POLICY 566 -#define POSITION 567 -#define PRAGMA_P 568 -#define PRECEDING 569 -#define PRECISION 570 -#define PREPARE 571 -#define PREPARED 572 -#define PRESERVE 573 -#define PRIMARY 574 -#define PRIOR 575 -#define PRIVILEGES 576 -#define PROCEDURAL 577 -#define PROCEDURE 578 -#define PROGRAM 579 -#define PUBLICATION 580 -#define QUALIFY 581 -#define QUOTE 582 -#define RANGE 583 -#define READ_P 584 -#define REAL 585 -#define REASSIGN 586 -#define RECHECK 587 -#define RECURSIVE 588 -#define REF 589 -#define REFERENCES 590 -#define REFERENCING 591 -#define REFRESH 592 -#define REINDEX 593 -#define RELATIVE_P 594 -#define RELEASE 595 -#define RENAME 596 -#define REPEATABLE 597 -#define REPLACE 598 -#define REPLICA 599 -#define RESET 600 -#define RESPECT_P 601 -#define RESTART 602 -#define RESTRICT 603 -#define RETURNING 604 -#define RETURNS 605 -#define REVOKE 606 -#define RIGHT 607 -#define ROLE 608 -#define ROLLBACK 609 -#define ROLLUP 610 -#define ROW 611 -#define ROWS 612 -#define RULE 613 -#define SAMPLE 614 -#define SAVEPOINT 615 -#define SCHEMA 616 -#define SCHEMAS 617 -#define SCROLL 618 -#define SEARCH 619 -#define SECOND_P 620 -#define SECONDS_P 621 -#define SECURITY 622 -#define SELECT 623 -#define SEQUENCE 624 -#define SEQUENCES 625 -#define SERIALIZABLE 626 -#define SERVER 627 -#define SESSION 628 -#define SESSION_USER 629 -#define SET 630 -#define SETOF 631 -#define SETS 632 -#define SHARE 633 -#define SHOW 634 -#define SIMILAR 635 -#define SIMPLE 636 -#define SKIP 637 -#define SMALLINT 638 -#define SNAPSHOT 639 -#define SOME 640 -#define SQL_P 641 -#define STABLE 642 -#define STANDALONE_P 643 -#define START 644 -#define STATEMENT 645 -#define STATISTICS 646 -#define STDIN 647 -#define STDOUT 648 -#define STORAGE 649 -#define STORED 650 -#define STRICT_P 651 -#define STRIP_P 652 -#define STRUCT 653 -#define SUBSCRIPTION 654 -#define SUBSTRING 655 -#define SUMMARIZE 656 -#define SYMMETRIC 657 -#define SYSID 658 -#define SYSTEM_P 659 -#define TABLE 660 -#define TABLES 661 -#define TABLESAMPLE 662 -#define TABLESPACE 663 -#define TEMP 664 -#define TEMPLATE 665 -#define TEMPORARY 666 -#define TEXT_P 667 -#define THEN 668 -#define TIME 669 -#define TIMESTAMP 670 -#define TO 671 -#define TRAILING 672 -#define TRANSACTION 673 -#define TRANSFORM 674 -#define TREAT 675 -#define TRIGGER 676 -#define TRIM 677 -#define TRUE_P 678 -#define TRUNCATE 679 -#define TRUSTED 680 -#define TRY_CAST 681 -#define TYPE_P 682 -#define TYPES_P 683 -#define UNBOUNDED 684 -#define UNCOMMITTED 685 -#define UNENCRYPTED 686 -#define UNION 687 -#define UNIQUE 688 -#define UNKNOWN 689 -#define UNLISTEN 690 -#define UNLOGGED 691 -#define UNTIL 692 -#define UPDATE 693 -#define USER 694 -#define USING 695 -#define VACUUM 696 -#define VALID 697 -#define VALIDATE 698 -#define VALIDATOR 699 -#define VALUE_P 700 -#define VALUES 701 -#define VARCHAR 702 -#define VARIADIC 703 -#define VARYING 704 -#define VERBOSE 705 -#define VERSION_P 706 -#define VIEW 707 -#define VIEWS 708 -#define VIRTUAL 709 -#define VOLATILE 710 -#define WHEN 711 -#define WHERE 712 -#define WHITESPACE_P 713 -#define WINDOW 714 -#define WITH 715 -#define WITHIN 716 -#define WITHOUT 717 -#define WORK 718 -#define WRAPPER 719 -#define WRITE_P 720 -#define XML_P 721 -#define XMLATTRIBUTES 722 -#define XMLCONCAT 723 -#define XMLELEMENT 724 -#define XMLEXISTS 725 -#define XMLFOREST 726 -#define XMLNAMESPACES 727 -#define XMLPARSE 728 -#define XMLPI 729 -#define XMLROOT 730 -#define XMLSERIALIZE 731 -#define XMLTABLE 732 -#define YEAR_P 733 -#define YEARS_P 734 -#define YES_P 735 -#define ZONE 736 -#define NOT_LA 737 -#define NULLS_LA 738 -#define WITH_LA 739 -#define POSTFIXOP 740 -#define UMINUS 741 +#define POWER_OF 270 +#define LAMBDA_ARROW 271 +#define DOUBLE_ARROW 272 +#define LESS_EQUALS 273 +#define GREATER_EQUALS 274 +#define NOT_EQUALS 275 +#define ABORT_P 276 +#define ABSOLUTE_P 277 +#define ACCESS 278 +#define ACTION 279 +#define ADD_P 280 +#define ADMIN 281 +#define AFTER 282 +#define AGGREGATE 283 +#define ALL 284 +#define ALSO 285 +#define ALTER 286 +#define ALWAYS 287 +#define ANALYSE 288 +#define ANALYZE 289 +#define AND 290 +#define ANY 291 +#define ARRAY 292 +#define AS 293 +#define ASC_P 294 +#define ASSERTION 295 +#define ASSIGNMENT 296 +#define ASYMMETRIC 297 +#define AT 298 +#define ATTACH 299 +#define ATTRIBUTE 300 +#define AUTHORIZATION 301 +#define BACKWARD 302 +#define BEFORE 303 +#define BEGIN_P 304 +#define BETWEEN 305 +#define BIGINT 306 +#define BINARY 307 +#define BIT 308 +#define BOOLEAN_P 309 +#define BOTH 310 +#define BY 311 +#define CACHE 312 +#define CALL_P 313 +#define CALLED 314 +#define CASCADE 315 +#define CASCADED 316 +#define CASE 317 +#define CAST 318 +#define CATALOG_P 319 +#define CHAIN 320 +#define CHAR_P 321 +#define CHARACTER 322 +#define CHARACTERISTICS 323 +#define CHECK_P 324 +#define CHECKPOINT 325 +#define CLASS 326 +#define CLOSE 327 +#define CLUSTER 328 +#define COALESCE 329 +#define COLLATE 330 +#define COLLATION 331 +#define COLUMN 332 +#define COLUMNS 333 +#define COMMENT 334 +#define COMMENTS 335 +#define COMMIT 336 +#define COMMITTED 337 +#define COMPRESSION 338 +#define CONCURRENTLY 339 +#define CONFIGURATION 340 +#define CONFLICT 341 +#define CONNECTION 342 +#define CONSTRAINT 343 +#define CONSTRAINTS 344 +#define CONTENT_P 345 +#define CONTINUE_P 346 +#define CONVERSION_P 347 +#define COPY 348 +#define COST 349 +#define CREATE_P 350 +#define CROSS 351 +#define CSV 352 +#define CUBE 353 +#define CURRENT_P 354 +#define CURRENT_CATALOG 355 +#define CURRENT_DATE 356 +#define CURRENT_ROLE 357 +#define CURRENT_SCHEMA 358 +#define CURRENT_TIME 359 +#define CURRENT_TIMESTAMP 360 +#define CURRENT_USER 361 +#define CURSOR 362 +#define CYCLE 363 +#define DATA_P 364 +#define DATABASE 365 +#define DAY_P 366 +#define DAYS_P 367 +#define DEALLOCATE 368 +#define DEC 369 +#define DECIMAL_P 370 +#define DECLARE 371 +#define DEFAULT 372 +#define DEFAULTS 373 +#define DEFERRABLE 374 +#define DEFERRED 375 +#define DEFINER 376 +#define DELETE_P 377 +#define DELIMITER 378 +#define DELIMITERS 379 +#define DEPENDS 380 +#define DESC_P 381 +#define DESCRIBE 382 +#define DETACH 383 +#define DICTIONARY 384 +#define DISABLE_P 385 +#define DISCARD 386 +#define DISTINCT 387 +#define DO 388 +#define DOCUMENT_P 389 +#define DOMAIN_P 390 +#define DOUBLE_P 391 +#define DROP 392 +#define EACH 393 +#define ELSE 394 +#define ENABLE_P 395 +#define ENCODING 396 +#define ENCRYPTED 397 +#define END_P 398 +#define ENUM_P 399 +#define ESCAPE 400 +#define EVENT 401 +#define EXCEPT 402 +#define EXCLUDE 403 +#define EXCLUDING 404 +#define EXCLUSIVE 405 +#define EXECUTE 406 +#define EXISTS 407 +#define EXPLAIN 408 +#define EXPORT_P 409 +#define EXPORT_STATE 410 +#define EXTENSION 411 +#define EXTERNAL 412 +#define EXTRACT 413 +#define FALSE_P 414 +#define FAMILY 415 +#define FETCH 416 +#define FILTER 417 +#define FIRST_P 418 +#define FLOAT_P 419 +#define FOLLOWING 420 +#define FOR 421 +#define FORCE 422 +#define FOREIGN 423 +#define FORWARD 424 +#define FREEZE 425 +#define FROM 426 +#define FULL 427 +#define FUNCTION 428 +#define FUNCTIONS 429 +#define GENERATED 430 +#define GLOB 431 +#define GLOBAL 432 +#define GRANT 433 +#define GRANTED 434 +#define GROUP_P 435 +#define GROUPING 436 +#define GROUPING_ID 437 +#define HANDLER 438 +#define HAVING 439 +#define HEADER_P 440 +#define HOLD 441 +#define HOUR_P 442 +#define HOURS_P 443 +#define IDENTITY_P 444 +#define IF_P 445 +#define IGNORE_P 446 +#define ILIKE 447 +#define IMMEDIATE 448 +#define IMMUTABLE 449 +#define IMPLICIT_P 450 +#define IMPORT_P 451 +#define IN_P 452 +#define INCLUDING 453 +#define INCREMENT 454 +#define INDEX 455 +#define INDEXES 456 +#define INHERIT 457 +#define INHERITS 458 +#define INITIALLY 459 +#define INLINE_P 460 +#define INNER_P 461 +#define INOUT 462 +#define INPUT_P 463 +#define INSENSITIVE 464 +#define INSERT 465 +#define INSTALL 466 +#define INSTEAD 467 +#define INT_P 468 +#define INTEGER 469 +#define INTERSECT 470 +#define INTERVAL 471 +#define INTO 472 +#define INVOKER 473 +#define IS 474 +#define ISNULL 475 +#define ISOLATION 476 +#define JOIN 477 +#define JSON 478 +#define KEY 479 +#define LABEL 480 +#define LANGUAGE 481 +#define LARGE_P 482 +#define LAST_P 483 +#define LATERAL_P 484 +#define LEADING 485 +#define LEAKPROOF 486 +#define LEFT 487 +#define LEVEL 488 +#define LIKE 489 +#define LIMIT 490 +#define LISTEN 491 +#define LOAD 492 +#define LOCAL 493 +#define LOCALTIME 494 +#define LOCALTIMESTAMP 495 +#define LOCATION 496 +#define LOCK_P 497 +#define LOCKED 498 +#define LOGGED 499 +#define MACRO 500 +#define MAP 501 +#define MAPPING 502 +#define MATCH 503 +#define MATERIALIZED 504 +#define MAXVALUE 505 +#define METHOD 506 +#define MICROSECOND_P 507 +#define MICROSECONDS_P 508 +#define MILLISECOND_P 509 +#define MILLISECONDS_P 510 +#define MINUTE_P 511 +#define MINUTES_P 512 +#define MINVALUE 513 +#define MODE 514 +#define MONTH_P 515 +#define MONTHS_P 516 +#define MOVE 517 +#define NAME_P 518 +#define NAMES 519 +#define NATIONAL 520 +#define NATURAL 521 +#define NCHAR 522 +#define NEW 523 +#define NEXT 524 +#define NO 525 +#define NONE 526 +#define NOT 527 +#define NOTHING 528 +#define NOTIFY 529 +#define NOTNULL 530 +#define NOWAIT 531 +#define NULL_P 532 +#define NULLIF 533 +#define NULLS_P 534 +#define NUMERIC 535 +#define OBJECT_P 536 +#define OF 537 +#define OFF 538 +#define OFFSET 539 +#define OIDS 540 +#define OLD 541 +#define ON 542 +#define ONLY 543 +#define OPERATOR 544 +#define OPTION 545 +#define OPTIONS 546 +#define OR 547 +#define ORDER 548 +#define ORDINALITY 549 +#define OUT_P 550 +#define OUTER_P 551 +#define OVER 552 +#define OVERLAPS 553 +#define OVERLAY 554 +#define OVERRIDING 555 +#define OWNED 556 +#define OWNER 557 +#define PARALLEL 558 +#define PARSER 559 +#define PARTIAL 560 +#define PARTITION 561 +#define PASSING 562 +#define PASSWORD 563 +#define PERCENT 564 +#define PLACING 565 +#define PLANS 566 +#define POLICY 567 +#define POSITION 568 +#define PRAGMA_P 569 +#define PRECEDING 570 +#define PRECISION 571 +#define PREPARE 572 +#define PREPARED 573 +#define PRESERVE 574 +#define PRIMARY 575 +#define PRIOR 576 +#define PRIVILEGES 577 +#define PROCEDURAL 578 +#define PROCEDURE 579 +#define PROGRAM 580 +#define PUBLICATION 581 +#define QUALIFY 582 +#define QUOTE 583 +#define RANGE 584 +#define READ_P 585 +#define REAL 586 +#define REASSIGN 587 +#define RECHECK 588 +#define RECURSIVE 589 +#define REF 590 +#define REFERENCES 591 +#define REFERENCING 592 +#define REFRESH 593 +#define REINDEX 594 +#define RELATIVE_P 595 +#define RELEASE 596 +#define RENAME 597 +#define REPEATABLE 598 +#define REPLACE 599 +#define REPLICA 600 +#define RESET 601 +#define RESPECT_P 602 +#define RESTART 603 +#define RESTRICT 604 +#define RETURNING 605 +#define RETURNS 606 +#define REVOKE 607 +#define RIGHT 608 +#define ROLE 609 +#define ROLLBACK 610 +#define ROLLUP 611 +#define ROW 612 +#define ROWS 613 +#define RULE 614 +#define SAMPLE 615 +#define SAVEPOINT 616 +#define SCHEMA 617 +#define SCHEMAS 618 +#define SCROLL 619 +#define SEARCH 620 +#define SECOND_P 621 +#define SECONDS_P 622 +#define SECURITY 623 +#define SELECT 624 +#define SEQUENCE 625 +#define SEQUENCES 626 +#define SERIALIZABLE 627 +#define SERVER 628 +#define SESSION 629 +#define SESSION_USER 630 +#define SET 631 +#define SETOF 632 +#define SETS 633 +#define SHARE 634 +#define SHOW 635 +#define SIMILAR 636 +#define SIMPLE 637 +#define SKIP 638 +#define SMALLINT 639 +#define SNAPSHOT 640 +#define SOME 641 +#define SQL_P 642 +#define STABLE 643 +#define STANDALONE_P 644 +#define START 645 +#define STATEMENT 646 +#define STATISTICS 647 +#define STDIN 648 +#define STDOUT 649 +#define STORAGE 650 +#define STORED 651 +#define STRICT_P 652 +#define STRIP_P 653 +#define STRUCT 654 +#define SUBSCRIPTION 655 +#define SUBSTRING 656 +#define SUMMARIZE 657 +#define SYMMETRIC 658 +#define SYSID 659 +#define SYSTEM_P 660 +#define TABLE 661 +#define TABLES 662 +#define TABLESAMPLE 663 +#define TABLESPACE 664 +#define TEMP 665 +#define TEMPLATE 666 +#define TEMPORARY 667 +#define TEXT_P 668 +#define THEN 669 +#define TIME 670 +#define TIMESTAMP 671 +#define TO 672 +#define TRAILING 673 +#define TRANSACTION 674 +#define TRANSFORM 675 +#define TREAT 676 +#define TRIGGER 677 +#define TRIM 678 +#define TRUE_P 679 +#define TRUNCATE 680 +#define TRUSTED 681 +#define TRY_CAST 682 +#define TYPE_P 683 +#define TYPES_P 684 +#define UNBOUNDED 685 +#define UNCOMMITTED 686 +#define UNENCRYPTED 687 +#define UNION 688 +#define UNIQUE 689 +#define UNKNOWN 690 +#define UNLISTEN 691 +#define UNLOGGED 692 +#define UNTIL 693 +#define UPDATE 694 +#define USER 695 +#define USING 696 +#define VACUUM 697 +#define VALID 698 +#define VALIDATE 699 +#define VALIDATOR 700 +#define VALUE_P 701 +#define VALUES 702 +#define VARCHAR 703 +#define VARIADIC 704 +#define VARYING 705 +#define VERBOSE 706 +#define VERSION_P 707 +#define VIEW 708 +#define VIEWS 709 +#define VIRTUAL 710 +#define VOLATILE 711 +#define WHEN 712 +#define WHERE 713 +#define WHITESPACE_P 714 +#define WINDOW 715 +#define WITH 716 +#define WITHIN 717 +#define WITHOUT 718 +#define WORK 719 +#define WRAPPER 720 +#define WRITE_P 721 +#define XML_P 722 +#define XMLATTRIBUTES 723 +#define XMLCONCAT 724 +#define XMLELEMENT 725 +#define XMLEXISTS 726 +#define XMLFOREST 727 +#define XMLNAMESPACES 728 +#define XMLPARSE 729 +#define XMLPI 730 +#define XMLROOT 731 +#define XMLSERIALIZE 732 +#define XMLTABLE 733 +#define YEAR_P 734 +#define YEARS_P 735 +#define YES_P 736 +#define ZONE 737 +#define NOT_LA 738 +#define NULLS_LA 739 +#define WITH_LA 740 +#define POSTFIXOP 741 +#define UMINUS 742 @@ -251329,7 +269326,7 @@ PGValue *makeString(const char *str) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -251356,7 +269353,7 @@ PGValue *makeString(const char *str) { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -251494,7 +269491,7 @@ namespace duckdb_libpgquery { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /* A Bison parser, made by GNU Bison 2.3. */ @@ -251550,478 +269547,479 @@ namespace duckdb_libpgquery { DOT_DOT = 267, COLON_EQUALS = 268, EQUALS_GREATER = 269, - LAMBDA_ARROW = 270, - POWER_OF = 271, - LESS_EQUALS = 272, - GREATER_EQUALS = 273, - NOT_EQUALS = 274, - ABORT_P = 275, - ABSOLUTE_P = 276, - ACCESS = 277, - ACTION = 278, - ADD_P = 279, - ADMIN = 280, - AFTER = 281, - AGGREGATE = 282, - ALL = 283, - ALSO = 284, - ALTER = 285, - ALWAYS = 286, - ANALYSE = 287, - ANALYZE = 288, - AND = 289, - ANY = 290, - ARRAY = 291, - AS = 292, - ASC_P = 293, - ASSERTION = 294, - ASSIGNMENT = 295, - ASYMMETRIC = 296, - AT = 297, - ATTACH = 298, - ATTRIBUTE = 299, - AUTHORIZATION = 300, - BACKWARD = 301, - BEFORE = 302, - BEGIN_P = 303, - BETWEEN = 304, - BIGINT = 305, - BINARY = 306, - BIT = 307, - BOOLEAN_P = 308, - BOTH = 309, - BY = 310, - CACHE = 311, - CALL_P = 312, - CALLED = 313, - CASCADE = 314, - CASCADED = 315, - CASE = 316, - CAST = 317, - CATALOG_P = 318, - CHAIN = 319, - CHAR_P = 320, - CHARACTER = 321, - CHARACTERISTICS = 322, - CHECK_P = 323, - CHECKPOINT = 324, - CLASS = 325, - CLOSE = 326, - CLUSTER = 327, - COALESCE = 328, - COLLATE = 329, - COLLATION = 330, - COLUMN = 331, - COLUMNS = 332, - COMMENT = 333, - COMMENTS = 334, - COMMIT = 335, - COMMITTED = 336, - COMPRESSION = 337, - CONCURRENTLY = 338, - CONFIGURATION = 339, - CONFLICT = 340, - CONNECTION = 341, - CONSTRAINT = 342, - CONSTRAINTS = 343, - CONTENT_P = 344, - CONTINUE_P = 345, - CONVERSION_P = 346, - COPY = 347, - COST = 348, - CREATE_P = 349, - CROSS = 350, - CSV = 351, - CUBE = 352, - CURRENT_P = 353, - CURRENT_CATALOG = 354, - CURRENT_DATE = 355, - CURRENT_ROLE = 356, - CURRENT_SCHEMA = 357, - CURRENT_TIME = 358, - CURRENT_TIMESTAMP = 359, - CURRENT_USER = 360, - CURSOR = 361, - CYCLE = 362, - DATA_P = 363, - DATABASE = 364, - DAY_P = 365, - DAYS_P = 366, - DEALLOCATE = 367, - DEC = 368, - DECIMAL_P = 369, - DECLARE = 370, - DEFAULT = 371, - DEFAULTS = 372, - DEFERRABLE = 373, - DEFERRED = 374, - DEFINER = 375, - DELETE_P = 376, - DELIMITER = 377, - DELIMITERS = 378, - DEPENDS = 379, - DESC_P = 380, - DESCRIBE = 381, - DETACH = 382, - DICTIONARY = 383, - DISABLE_P = 384, - DISCARD = 385, - DISTINCT = 386, - DO = 387, - DOCUMENT_P = 388, - DOMAIN_P = 389, - DOUBLE_P = 390, - DROP = 391, - EACH = 392, - ELSE = 393, - ENABLE_P = 394, - ENCODING = 395, - ENCRYPTED = 396, - END_P = 397, - ENUM_P = 398, - ESCAPE = 399, - EVENT = 400, - EXCEPT = 401, - EXCLUDE = 402, - EXCLUDING = 403, - EXCLUSIVE = 404, - EXECUTE = 405, - EXISTS = 406, - EXPLAIN = 407, - EXPORT_P = 408, - EXPORT_STATE = 409, - EXTENSION = 410, - EXTERNAL = 411, - EXTRACT = 412, - FALSE_P = 413, - FAMILY = 414, - FETCH = 415, - FILTER = 416, - FIRST_P = 417, - FLOAT_P = 418, - FOLLOWING = 419, - FOR = 420, - FORCE = 421, - FOREIGN = 422, - FORWARD = 423, - FREEZE = 424, - FROM = 425, - FULL = 426, - FUNCTION = 427, - FUNCTIONS = 428, - GENERATED = 429, - GLOB = 430, - GLOBAL = 431, - GRANT = 432, - GRANTED = 433, - GROUP_P = 434, - GROUPING = 435, - GROUPING_ID = 436, - HANDLER = 437, - HAVING = 438, - HEADER_P = 439, - HOLD = 440, - HOUR_P = 441, - HOURS_P = 442, - IDENTITY_P = 443, - IF_P = 444, - IGNORE_P = 445, - ILIKE = 446, - IMMEDIATE = 447, - IMMUTABLE = 448, - IMPLICIT_P = 449, - IMPORT_P = 450, - IN_P = 451, - INCLUDING = 452, - INCREMENT = 453, - INDEX = 454, - INDEXES = 455, - INHERIT = 456, - INHERITS = 457, - INITIALLY = 458, - INLINE_P = 459, - INNER_P = 460, - INOUT = 461, - INPUT_P = 462, - INSENSITIVE = 463, - INSERT = 464, - INSTALL = 465, - INSTEAD = 466, - INT_P = 467, - INTEGER = 468, - INTERSECT = 469, - INTERVAL = 470, - INTO = 471, - INVOKER = 472, - IS = 473, - ISNULL = 474, - ISOLATION = 475, - JOIN = 476, - JSON = 477, - KEY = 478, - LABEL = 479, - LANGUAGE = 480, - LARGE_P = 481, - LAST_P = 482, - LATERAL_P = 483, - LEADING = 484, - LEAKPROOF = 485, - LEFT = 486, - LEVEL = 487, - LIKE = 488, - LIMIT = 489, - LISTEN = 490, - LOAD = 491, - LOCAL = 492, - LOCALTIME = 493, - LOCALTIMESTAMP = 494, - LOCATION = 495, - LOCK_P = 496, - LOCKED = 497, - LOGGED = 498, - MACRO = 499, - MAP = 500, - MAPPING = 501, - MATCH = 502, - MATERIALIZED = 503, - MAXVALUE = 504, - METHOD = 505, - MICROSECOND_P = 506, - MICROSECONDS_P = 507, - MILLISECOND_P = 508, - MILLISECONDS_P = 509, - MINUTE_P = 510, - MINUTES_P = 511, - MINVALUE = 512, - MODE = 513, - MONTH_P = 514, - MONTHS_P = 515, - MOVE = 516, - NAME_P = 517, - NAMES = 518, - NATIONAL = 519, - NATURAL = 520, - NCHAR = 521, - NEW = 522, - NEXT = 523, - NO = 524, - NONE = 525, - NOT = 526, - NOTHING = 527, - NOTIFY = 528, - NOTNULL = 529, - NOWAIT = 530, - NULL_P = 531, - NULLIF = 532, - NULLS_P = 533, - NUMERIC = 534, - OBJECT_P = 535, - OF = 536, - OFF = 537, - OFFSET = 538, - OIDS = 539, - OLD = 540, - ON = 541, - ONLY = 542, - OPERATOR = 543, - OPTION = 544, - OPTIONS = 545, - OR = 546, - ORDER = 547, - ORDINALITY = 548, - OUT_P = 549, - OUTER_P = 550, - OVER = 551, - OVERLAPS = 552, - OVERLAY = 553, - OVERRIDING = 554, - OWNED = 555, - OWNER = 556, - PARALLEL = 557, - PARSER = 558, - PARTIAL = 559, - PARTITION = 560, - PASSING = 561, - PASSWORD = 562, - PERCENT = 563, - PLACING = 564, - PLANS = 565, - POLICY = 566, - POSITION = 567, - PRAGMA_P = 568, - PRECEDING = 569, - PRECISION = 570, - PREPARE = 571, - PREPARED = 572, - PRESERVE = 573, - PRIMARY = 574, - PRIOR = 575, - PRIVILEGES = 576, - PROCEDURAL = 577, - PROCEDURE = 578, - PROGRAM = 579, - PUBLICATION = 580, - QUALIFY = 581, - QUOTE = 582, - RANGE = 583, - READ_P = 584, - REAL = 585, - REASSIGN = 586, - RECHECK = 587, - RECURSIVE = 588, - REF = 589, - REFERENCES = 590, - REFERENCING = 591, - REFRESH = 592, - REINDEX = 593, - RELATIVE_P = 594, - RELEASE = 595, - RENAME = 596, - REPEATABLE = 597, - REPLACE = 598, - REPLICA = 599, - RESET = 600, - RESPECT_P = 601, - RESTART = 602, - RESTRICT = 603, - RETURNING = 604, - RETURNS = 605, - REVOKE = 606, - RIGHT = 607, - ROLE = 608, - ROLLBACK = 609, - ROLLUP = 610, - ROW = 611, - ROWS = 612, - RULE = 613, - SAMPLE = 614, - SAVEPOINT = 615, - SCHEMA = 616, - SCHEMAS = 617, - SCROLL = 618, - SEARCH = 619, - SECOND_P = 620, - SECONDS_P = 621, - SECURITY = 622, - SELECT = 623, - SEQUENCE = 624, - SEQUENCES = 625, - SERIALIZABLE = 626, - SERVER = 627, - SESSION = 628, - SESSION_USER = 629, - SET = 630, - SETOF = 631, - SETS = 632, - SHARE = 633, - SHOW = 634, - SIMILAR = 635, - SIMPLE = 636, - SKIP = 637, - SMALLINT = 638, - SNAPSHOT = 639, - SOME = 640, - SQL_P = 641, - STABLE = 642, - STANDALONE_P = 643, - START = 644, - STATEMENT = 645, - STATISTICS = 646, - STDIN = 647, - STDOUT = 648, - STORAGE = 649, - STORED = 650, - STRICT_P = 651, - STRIP_P = 652, - STRUCT = 653, - SUBSCRIPTION = 654, - SUBSTRING = 655, - SUMMARIZE = 656, - SYMMETRIC = 657, - SYSID = 658, - SYSTEM_P = 659, - TABLE = 660, - TABLES = 661, - TABLESAMPLE = 662, - TABLESPACE = 663, - TEMP = 664, - TEMPLATE = 665, - TEMPORARY = 666, - TEXT_P = 667, - THEN = 668, - TIME = 669, - TIMESTAMP = 670, - TO = 671, - TRAILING = 672, - TRANSACTION = 673, - TRANSFORM = 674, - TREAT = 675, - TRIGGER = 676, - TRIM = 677, - TRUE_P = 678, - TRUNCATE = 679, - TRUSTED = 680, - TRY_CAST = 681, - TYPE_P = 682, - TYPES_P = 683, - UNBOUNDED = 684, - UNCOMMITTED = 685, - UNENCRYPTED = 686, - UNION = 687, - UNIQUE = 688, - UNKNOWN = 689, - UNLISTEN = 690, - UNLOGGED = 691, - UNTIL = 692, - UPDATE = 693, - USER = 694, - USING = 695, - VACUUM = 696, - VALID = 697, - VALIDATE = 698, - VALIDATOR = 699, - VALUE_P = 700, - VALUES = 701, - VARCHAR = 702, - VARIADIC = 703, - VARYING = 704, - VERBOSE = 705, - VERSION_P = 706, - VIEW = 707, - VIEWS = 708, - VIRTUAL = 709, - VOLATILE = 710, - WHEN = 711, - WHERE = 712, - WHITESPACE_P = 713, - WINDOW = 714, - WITH = 715, - WITHIN = 716, - WITHOUT = 717, - WORK = 718, - WRAPPER = 719, - WRITE_P = 720, - XML_P = 721, - XMLATTRIBUTES = 722, - XMLCONCAT = 723, - XMLELEMENT = 724, - XMLEXISTS = 725, - XMLFOREST = 726, - XMLNAMESPACES = 727, - XMLPARSE = 728, - XMLPI = 729, - XMLROOT = 730, - XMLSERIALIZE = 731, - XMLTABLE = 732, - YEAR_P = 733, - YEARS_P = 734, - YES_P = 735, - ZONE = 736, - NOT_LA = 737, - NULLS_LA = 738, - WITH_LA = 739, - POSTFIXOP = 740, - UMINUS = 741 + POWER_OF = 270, + LAMBDA_ARROW = 271, + DOUBLE_ARROW = 272, + LESS_EQUALS = 273, + GREATER_EQUALS = 274, + NOT_EQUALS = 275, + ABORT_P = 276, + ABSOLUTE_P = 277, + ACCESS = 278, + ACTION = 279, + ADD_P = 280, + ADMIN = 281, + AFTER = 282, + AGGREGATE = 283, + ALL = 284, + ALSO = 285, + ALTER = 286, + ALWAYS = 287, + ANALYSE = 288, + ANALYZE = 289, + AND = 290, + ANY = 291, + ARRAY = 292, + AS = 293, + ASC_P = 294, + ASSERTION = 295, + ASSIGNMENT = 296, + ASYMMETRIC = 297, + AT = 298, + ATTACH = 299, + ATTRIBUTE = 300, + AUTHORIZATION = 301, + BACKWARD = 302, + BEFORE = 303, + BEGIN_P = 304, + BETWEEN = 305, + BIGINT = 306, + BINARY = 307, + BIT = 308, + BOOLEAN_P = 309, + BOTH = 310, + BY = 311, + CACHE = 312, + CALL_P = 313, + CALLED = 314, + CASCADE = 315, + CASCADED = 316, + CASE = 317, + CAST = 318, + CATALOG_P = 319, + CHAIN = 320, + CHAR_P = 321, + CHARACTER = 322, + CHARACTERISTICS = 323, + CHECK_P = 324, + CHECKPOINT = 325, + CLASS = 326, + CLOSE = 327, + CLUSTER = 328, + COALESCE = 329, + COLLATE = 330, + COLLATION = 331, + COLUMN = 332, + COLUMNS = 333, + COMMENT = 334, + COMMENTS = 335, + COMMIT = 336, + COMMITTED = 337, + COMPRESSION = 338, + CONCURRENTLY = 339, + CONFIGURATION = 340, + CONFLICT = 341, + CONNECTION = 342, + CONSTRAINT = 343, + CONSTRAINTS = 344, + CONTENT_P = 345, + CONTINUE_P = 346, + CONVERSION_P = 347, + COPY = 348, + COST = 349, + CREATE_P = 350, + CROSS = 351, + CSV = 352, + CUBE = 353, + CURRENT_P = 354, + CURRENT_CATALOG = 355, + CURRENT_DATE = 356, + CURRENT_ROLE = 357, + CURRENT_SCHEMA = 358, + CURRENT_TIME = 359, + CURRENT_TIMESTAMP = 360, + CURRENT_USER = 361, + CURSOR = 362, + CYCLE = 363, + DATA_P = 364, + DATABASE = 365, + DAY_P = 366, + DAYS_P = 367, + DEALLOCATE = 368, + DEC = 369, + DECIMAL_P = 370, + DECLARE = 371, + DEFAULT = 372, + DEFAULTS = 373, + DEFERRABLE = 374, + DEFERRED = 375, + DEFINER = 376, + DELETE_P = 377, + DELIMITER = 378, + DELIMITERS = 379, + DEPENDS = 380, + DESC_P = 381, + DESCRIBE = 382, + DETACH = 383, + DICTIONARY = 384, + DISABLE_P = 385, + DISCARD = 386, + DISTINCT = 387, + DO = 388, + DOCUMENT_P = 389, + DOMAIN_P = 390, + DOUBLE_P = 391, + DROP = 392, + EACH = 393, + ELSE = 394, + ENABLE_P = 395, + ENCODING = 396, + ENCRYPTED = 397, + END_P = 398, + ENUM_P = 399, + ESCAPE = 400, + EVENT = 401, + EXCEPT = 402, + EXCLUDE = 403, + EXCLUDING = 404, + EXCLUSIVE = 405, + EXECUTE = 406, + EXISTS = 407, + EXPLAIN = 408, + EXPORT_P = 409, + EXPORT_STATE = 410, + EXTENSION = 411, + EXTERNAL = 412, + EXTRACT = 413, + FALSE_P = 414, + FAMILY = 415, + FETCH = 416, + FILTER = 417, + FIRST_P = 418, + FLOAT_P = 419, + FOLLOWING = 420, + FOR = 421, + FORCE = 422, + FOREIGN = 423, + FORWARD = 424, + FREEZE = 425, + FROM = 426, + FULL = 427, + FUNCTION = 428, + FUNCTIONS = 429, + GENERATED = 430, + GLOB = 431, + GLOBAL = 432, + GRANT = 433, + GRANTED = 434, + GROUP_P = 435, + GROUPING = 436, + GROUPING_ID = 437, + HANDLER = 438, + HAVING = 439, + HEADER_P = 440, + HOLD = 441, + HOUR_P = 442, + HOURS_P = 443, + IDENTITY_P = 444, + IF_P = 445, + IGNORE_P = 446, + ILIKE = 447, + IMMEDIATE = 448, + IMMUTABLE = 449, + IMPLICIT_P = 450, + IMPORT_P = 451, + IN_P = 452, + INCLUDING = 453, + INCREMENT = 454, + INDEX = 455, + INDEXES = 456, + INHERIT = 457, + INHERITS = 458, + INITIALLY = 459, + INLINE_P = 460, + INNER_P = 461, + INOUT = 462, + INPUT_P = 463, + INSENSITIVE = 464, + INSERT = 465, + INSTALL = 466, + INSTEAD = 467, + INT_P = 468, + INTEGER = 469, + INTERSECT = 470, + INTERVAL = 471, + INTO = 472, + INVOKER = 473, + IS = 474, + ISNULL = 475, + ISOLATION = 476, + JOIN = 477, + JSON = 478, + KEY = 479, + LABEL = 480, + LANGUAGE = 481, + LARGE_P = 482, + LAST_P = 483, + LATERAL_P = 484, + LEADING = 485, + LEAKPROOF = 486, + LEFT = 487, + LEVEL = 488, + LIKE = 489, + LIMIT = 490, + LISTEN = 491, + LOAD = 492, + LOCAL = 493, + LOCALTIME = 494, + LOCALTIMESTAMP = 495, + LOCATION = 496, + LOCK_P = 497, + LOCKED = 498, + LOGGED = 499, + MACRO = 500, + MAP = 501, + MAPPING = 502, + MATCH = 503, + MATERIALIZED = 504, + MAXVALUE = 505, + METHOD = 506, + MICROSECOND_P = 507, + MICROSECONDS_P = 508, + MILLISECOND_P = 509, + MILLISECONDS_P = 510, + MINUTE_P = 511, + MINUTES_P = 512, + MINVALUE = 513, + MODE = 514, + MONTH_P = 515, + MONTHS_P = 516, + MOVE = 517, + NAME_P = 518, + NAMES = 519, + NATIONAL = 520, + NATURAL = 521, + NCHAR = 522, + NEW = 523, + NEXT = 524, + NO = 525, + NONE = 526, + NOT = 527, + NOTHING = 528, + NOTIFY = 529, + NOTNULL = 530, + NOWAIT = 531, + NULL_P = 532, + NULLIF = 533, + NULLS_P = 534, + NUMERIC = 535, + OBJECT_P = 536, + OF = 537, + OFF = 538, + OFFSET = 539, + OIDS = 540, + OLD = 541, + ON = 542, + ONLY = 543, + OPERATOR = 544, + OPTION = 545, + OPTIONS = 546, + OR = 547, + ORDER = 548, + ORDINALITY = 549, + OUT_P = 550, + OUTER_P = 551, + OVER = 552, + OVERLAPS = 553, + OVERLAY = 554, + OVERRIDING = 555, + OWNED = 556, + OWNER = 557, + PARALLEL = 558, + PARSER = 559, + PARTIAL = 560, + PARTITION = 561, + PASSING = 562, + PASSWORD = 563, + PERCENT = 564, + PLACING = 565, + PLANS = 566, + POLICY = 567, + POSITION = 568, + PRAGMA_P = 569, + PRECEDING = 570, + PRECISION = 571, + PREPARE = 572, + PREPARED = 573, + PRESERVE = 574, + PRIMARY = 575, + PRIOR = 576, + PRIVILEGES = 577, + PROCEDURAL = 578, + PROCEDURE = 579, + PROGRAM = 580, + PUBLICATION = 581, + QUALIFY = 582, + QUOTE = 583, + RANGE = 584, + READ_P = 585, + REAL = 586, + REASSIGN = 587, + RECHECK = 588, + RECURSIVE = 589, + REF = 590, + REFERENCES = 591, + REFERENCING = 592, + REFRESH = 593, + REINDEX = 594, + RELATIVE_P = 595, + RELEASE = 596, + RENAME = 597, + REPEATABLE = 598, + REPLACE = 599, + REPLICA = 600, + RESET = 601, + RESPECT_P = 602, + RESTART = 603, + RESTRICT = 604, + RETURNING = 605, + RETURNS = 606, + REVOKE = 607, + RIGHT = 608, + ROLE = 609, + ROLLBACK = 610, + ROLLUP = 611, + ROW = 612, + ROWS = 613, + RULE = 614, + SAMPLE = 615, + SAVEPOINT = 616, + SCHEMA = 617, + SCHEMAS = 618, + SCROLL = 619, + SEARCH = 620, + SECOND_P = 621, + SECONDS_P = 622, + SECURITY = 623, + SELECT = 624, + SEQUENCE = 625, + SEQUENCES = 626, + SERIALIZABLE = 627, + SERVER = 628, + SESSION = 629, + SESSION_USER = 630, + SET = 631, + SETOF = 632, + SETS = 633, + SHARE = 634, + SHOW = 635, + SIMILAR = 636, + SIMPLE = 637, + SKIP = 638, + SMALLINT = 639, + SNAPSHOT = 640, + SOME = 641, + SQL_P = 642, + STABLE = 643, + STANDALONE_P = 644, + START = 645, + STATEMENT = 646, + STATISTICS = 647, + STDIN = 648, + STDOUT = 649, + STORAGE = 650, + STORED = 651, + STRICT_P = 652, + STRIP_P = 653, + STRUCT = 654, + SUBSCRIPTION = 655, + SUBSTRING = 656, + SUMMARIZE = 657, + SYMMETRIC = 658, + SYSID = 659, + SYSTEM_P = 660, + TABLE = 661, + TABLES = 662, + TABLESAMPLE = 663, + TABLESPACE = 664, + TEMP = 665, + TEMPLATE = 666, + TEMPORARY = 667, + TEXT_P = 668, + THEN = 669, + TIME = 670, + TIMESTAMP = 671, + TO = 672, + TRAILING = 673, + TRANSACTION = 674, + TRANSFORM = 675, + TREAT = 676, + TRIGGER = 677, + TRIM = 678, + TRUE_P = 679, + TRUNCATE = 680, + TRUSTED = 681, + TRY_CAST = 682, + TYPE_P = 683, + TYPES_P = 684, + UNBOUNDED = 685, + UNCOMMITTED = 686, + UNENCRYPTED = 687, + UNION = 688, + UNIQUE = 689, + UNKNOWN = 690, + UNLISTEN = 691, + UNLOGGED = 692, + UNTIL = 693, + UPDATE = 694, + USER = 695, + USING = 696, + VACUUM = 697, + VALID = 698, + VALIDATE = 699, + VALIDATOR = 700, + VALUE_P = 701, + VALUES = 702, + VARCHAR = 703, + VARIADIC = 704, + VARYING = 705, + VERBOSE = 706, + VERSION_P = 707, + VIEW = 708, + VIEWS = 709, + VIRTUAL = 710, + VOLATILE = 711, + WHEN = 712, + WHERE = 713, + WHITESPACE_P = 714, + WINDOW = 715, + WITH = 716, + WITHIN = 717, + WITHOUT = 718, + WORK = 719, + WRAPPER = 720, + WRITE_P = 721, + XML_P = 722, + XMLATTRIBUTES = 723, + XMLCONCAT = 724, + XMLELEMENT = 725, + XMLEXISTS = 726, + XMLFOREST = 727, + XMLNAMESPACES = 728, + XMLPARSE = 729, + XMLPI = 730, + XMLROOT = 731, + XMLSERIALIZE = 732, + XMLTABLE = 733, + YEAR_P = 734, + YEARS_P = 735, + YES_P = 736, + ZONE = 737, + NOT_LA = 738, + NULLS_LA = 739, + WITH_LA = 740, + POSTFIXOP = 741, + UMINUS = 742 }; #endif /* Tokens. */ @@ -252037,478 +270035,479 @@ namespace duckdb_libpgquery { #define DOT_DOT 267 #define COLON_EQUALS 268 #define EQUALS_GREATER 269 -#define LAMBDA_ARROW 270 -#define POWER_OF 271 -#define LESS_EQUALS 272 -#define GREATER_EQUALS 273 -#define NOT_EQUALS 274 -#define ABORT_P 275 -#define ABSOLUTE_P 276 -#define ACCESS 277 -#define ACTION 278 -#define ADD_P 279 -#define ADMIN 280 -#define AFTER 281 -#define AGGREGATE 282 -#define ALL 283 -#define ALSO 284 -#define ALTER 285 -#define ALWAYS 286 -#define ANALYSE 287 -#define ANALYZE 288 -#define AND 289 -#define ANY 290 -#define ARRAY 291 -#define AS 292 -#define ASC_P 293 -#define ASSERTION 294 -#define ASSIGNMENT 295 -#define ASYMMETRIC 296 -#define AT 297 -#define ATTACH 298 -#define ATTRIBUTE 299 -#define AUTHORIZATION 300 -#define BACKWARD 301 -#define BEFORE 302 -#define BEGIN_P 303 -#define BETWEEN 304 -#define BIGINT 305 -#define BINARY 306 -#define BIT 307 -#define BOOLEAN_P 308 -#define BOTH 309 -#define BY 310 -#define CACHE 311 -#define CALL_P 312 -#define CALLED 313 -#define CASCADE 314 -#define CASCADED 315 -#define CASE 316 -#define CAST 317 -#define CATALOG_P 318 -#define CHAIN 319 -#define CHAR_P 320 -#define CHARACTER 321 -#define CHARACTERISTICS 322 -#define CHECK_P 323 -#define CHECKPOINT 324 -#define CLASS 325 -#define CLOSE 326 -#define CLUSTER 327 -#define COALESCE 328 -#define COLLATE 329 -#define COLLATION 330 -#define COLUMN 331 -#define COLUMNS 332 -#define COMMENT 333 -#define COMMENTS 334 -#define COMMIT 335 -#define COMMITTED 336 -#define COMPRESSION 337 -#define CONCURRENTLY 338 -#define CONFIGURATION 339 -#define CONFLICT 340 -#define CONNECTION 341 -#define CONSTRAINT 342 -#define CONSTRAINTS 343 -#define CONTENT_P 344 -#define CONTINUE_P 345 -#define CONVERSION_P 346 -#define COPY 347 -#define COST 348 -#define CREATE_P 349 -#define CROSS 350 -#define CSV 351 -#define CUBE 352 -#define CURRENT_P 353 -#define CURRENT_CATALOG 354 -#define CURRENT_DATE 355 -#define CURRENT_ROLE 356 -#define CURRENT_SCHEMA 357 -#define CURRENT_TIME 358 -#define CURRENT_TIMESTAMP 359 -#define CURRENT_USER 360 -#define CURSOR 361 -#define CYCLE 362 -#define DATA_P 363 -#define DATABASE 364 -#define DAY_P 365 -#define DAYS_P 366 -#define DEALLOCATE 367 -#define DEC 368 -#define DECIMAL_P 369 -#define DECLARE 370 -#define DEFAULT 371 -#define DEFAULTS 372 -#define DEFERRABLE 373 -#define DEFERRED 374 -#define DEFINER 375 -#define DELETE_P 376 -#define DELIMITER 377 -#define DELIMITERS 378 -#define DEPENDS 379 -#define DESC_P 380 -#define DESCRIBE 381 -#define DETACH 382 -#define DICTIONARY 383 -#define DISABLE_P 384 -#define DISCARD 385 -#define DISTINCT 386 -#define DO 387 -#define DOCUMENT_P 388 -#define DOMAIN_P 389 -#define DOUBLE_P 390 -#define DROP 391 -#define EACH 392 -#define ELSE 393 -#define ENABLE_P 394 -#define ENCODING 395 -#define ENCRYPTED 396 -#define END_P 397 -#define ENUM_P 398 -#define ESCAPE 399 -#define EVENT 400 -#define EXCEPT 401 -#define EXCLUDE 402 -#define EXCLUDING 403 -#define EXCLUSIVE 404 -#define EXECUTE 405 -#define EXISTS 406 -#define EXPLAIN 407 -#define EXPORT_P 408 -#define EXPORT_STATE 409 -#define EXTENSION 410 -#define EXTERNAL 411 -#define EXTRACT 412 -#define FALSE_P 413 -#define FAMILY 414 -#define FETCH 415 -#define FILTER 416 -#define FIRST_P 417 -#define FLOAT_P 418 -#define FOLLOWING 419 -#define FOR 420 -#define FORCE 421 -#define FOREIGN 422 -#define FORWARD 423 -#define FREEZE 424 -#define FROM 425 -#define FULL 426 -#define FUNCTION 427 -#define FUNCTIONS 428 -#define GENERATED 429 -#define GLOB 430 -#define GLOBAL 431 -#define GRANT 432 -#define GRANTED 433 -#define GROUP_P 434 -#define GROUPING 435 -#define GROUPING_ID 436 -#define HANDLER 437 -#define HAVING 438 -#define HEADER_P 439 -#define HOLD 440 -#define HOUR_P 441 -#define HOURS_P 442 -#define IDENTITY_P 443 -#define IF_P 444 -#define IGNORE_P 445 -#define ILIKE 446 -#define IMMEDIATE 447 -#define IMMUTABLE 448 -#define IMPLICIT_P 449 -#define IMPORT_P 450 -#define IN_P 451 -#define INCLUDING 452 -#define INCREMENT 453 -#define INDEX 454 -#define INDEXES 455 -#define INHERIT 456 -#define INHERITS 457 -#define INITIALLY 458 -#define INLINE_P 459 -#define INNER_P 460 -#define INOUT 461 -#define INPUT_P 462 -#define INSENSITIVE 463 -#define INSERT 464 -#define INSTALL 465 -#define INSTEAD 466 -#define INT_P 467 -#define INTEGER 468 -#define INTERSECT 469 -#define INTERVAL 470 -#define INTO 471 -#define INVOKER 472 -#define IS 473 -#define ISNULL 474 -#define ISOLATION 475 -#define JOIN 476 -#define JSON 477 -#define KEY 478 -#define LABEL 479 -#define LANGUAGE 480 -#define LARGE_P 481 -#define LAST_P 482 -#define LATERAL_P 483 -#define LEADING 484 -#define LEAKPROOF 485 -#define LEFT 486 -#define LEVEL 487 -#define LIKE 488 -#define LIMIT 489 -#define LISTEN 490 -#define LOAD 491 -#define LOCAL 492 -#define LOCALTIME 493 -#define LOCALTIMESTAMP 494 -#define LOCATION 495 -#define LOCK_P 496 -#define LOCKED 497 -#define LOGGED 498 -#define MACRO 499 -#define MAP 500 -#define MAPPING 501 -#define MATCH 502 -#define MATERIALIZED 503 -#define MAXVALUE 504 -#define METHOD 505 -#define MICROSECOND_P 506 -#define MICROSECONDS_P 507 -#define MILLISECOND_P 508 -#define MILLISECONDS_P 509 -#define MINUTE_P 510 -#define MINUTES_P 511 -#define MINVALUE 512 -#define MODE 513 -#define MONTH_P 514 -#define MONTHS_P 515 -#define MOVE 516 -#define NAME_P 517 -#define NAMES 518 -#define NATIONAL 519 -#define NATURAL 520 -#define NCHAR 521 -#define NEW 522 -#define NEXT 523 -#define NO 524 -#define NONE 525 -#define NOT 526 -#define NOTHING 527 -#define NOTIFY 528 -#define NOTNULL 529 -#define NOWAIT 530 -#define NULL_P 531 -#define NULLIF 532 -#define NULLS_P 533 -#define NUMERIC 534 -#define OBJECT_P 535 -#define OF 536 -#define OFF 537 -#define OFFSET 538 -#define OIDS 539 -#define OLD 540 -#define ON 541 -#define ONLY 542 -#define OPERATOR 543 -#define OPTION 544 -#define OPTIONS 545 -#define OR 546 -#define ORDER 547 -#define ORDINALITY 548 -#define OUT_P 549 -#define OUTER_P 550 -#define OVER 551 -#define OVERLAPS 552 -#define OVERLAY 553 -#define OVERRIDING 554 -#define OWNED 555 -#define OWNER 556 -#define PARALLEL 557 -#define PARSER 558 -#define PARTIAL 559 -#define PARTITION 560 -#define PASSING 561 -#define PASSWORD 562 -#define PERCENT 563 -#define PLACING 564 -#define PLANS 565 -#define POLICY 566 -#define POSITION 567 -#define PRAGMA_P 568 -#define PRECEDING 569 -#define PRECISION 570 -#define PREPARE 571 -#define PREPARED 572 -#define PRESERVE 573 -#define PRIMARY 574 -#define PRIOR 575 -#define PRIVILEGES 576 -#define PROCEDURAL 577 -#define PROCEDURE 578 -#define PROGRAM 579 -#define PUBLICATION 580 -#define QUALIFY 581 -#define QUOTE 582 -#define RANGE 583 -#define READ_P 584 -#define REAL 585 -#define REASSIGN 586 -#define RECHECK 587 -#define RECURSIVE 588 -#define REF 589 -#define REFERENCES 590 -#define REFERENCING 591 -#define REFRESH 592 -#define REINDEX 593 -#define RELATIVE_P 594 -#define RELEASE 595 -#define RENAME 596 -#define REPEATABLE 597 -#define REPLACE 598 -#define REPLICA 599 -#define RESET 600 -#define RESPECT_P 601 -#define RESTART 602 -#define RESTRICT 603 -#define RETURNING 604 -#define RETURNS 605 -#define REVOKE 606 -#define RIGHT 607 -#define ROLE 608 -#define ROLLBACK 609 -#define ROLLUP 610 -#define ROW 611 -#define ROWS 612 -#define RULE 613 -#define SAMPLE 614 -#define SAVEPOINT 615 -#define SCHEMA 616 -#define SCHEMAS 617 -#define SCROLL 618 -#define SEARCH 619 -#define SECOND_P 620 -#define SECONDS_P 621 -#define SECURITY 622 -#define SELECT 623 -#define SEQUENCE 624 -#define SEQUENCES 625 -#define SERIALIZABLE 626 -#define SERVER 627 -#define SESSION 628 -#define SESSION_USER 629 -#define SET 630 -#define SETOF 631 -#define SETS 632 -#define SHARE 633 -#define SHOW 634 -#define SIMILAR 635 -#define SIMPLE 636 -#define SKIP 637 -#define SMALLINT 638 -#define SNAPSHOT 639 -#define SOME 640 -#define SQL_P 641 -#define STABLE 642 -#define STANDALONE_P 643 -#define START 644 -#define STATEMENT 645 -#define STATISTICS 646 -#define STDIN 647 -#define STDOUT 648 -#define STORAGE 649 -#define STORED 650 -#define STRICT_P 651 -#define STRIP_P 652 -#define STRUCT 653 -#define SUBSCRIPTION 654 -#define SUBSTRING 655 -#define SUMMARIZE 656 -#define SYMMETRIC 657 -#define SYSID 658 -#define SYSTEM_P 659 -#define TABLE 660 -#define TABLES 661 -#define TABLESAMPLE 662 -#define TABLESPACE 663 -#define TEMP 664 -#define TEMPLATE 665 -#define TEMPORARY 666 -#define TEXT_P 667 -#define THEN 668 -#define TIME 669 -#define TIMESTAMP 670 -#define TO 671 -#define TRAILING 672 -#define TRANSACTION 673 -#define TRANSFORM 674 -#define TREAT 675 -#define TRIGGER 676 -#define TRIM 677 -#define TRUE_P 678 -#define TRUNCATE 679 -#define TRUSTED 680 -#define TRY_CAST 681 -#define TYPE_P 682 -#define TYPES_P 683 -#define UNBOUNDED 684 -#define UNCOMMITTED 685 -#define UNENCRYPTED 686 -#define UNION 687 -#define UNIQUE 688 -#define UNKNOWN 689 -#define UNLISTEN 690 -#define UNLOGGED 691 -#define UNTIL 692 -#define UPDATE 693 -#define USER 694 -#define USING 695 -#define VACUUM 696 -#define VALID 697 -#define VALIDATE 698 -#define VALIDATOR 699 -#define VALUE_P 700 -#define VALUES 701 -#define VARCHAR 702 -#define VARIADIC 703 -#define VARYING 704 -#define VERBOSE 705 -#define VERSION_P 706 -#define VIEW 707 -#define VIEWS 708 -#define VIRTUAL 709 -#define VOLATILE 710 -#define WHEN 711 -#define WHERE 712 -#define WHITESPACE_P 713 -#define WINDOW 714 -#define WITH 715 -#define WITHIN 716 -#define WITHOUT 717 -#define WORK 718 -#define WRAPPER 719 -#define WRITE_P 720 -#define XML_P 721 -#define XMLATTRIBUTES 722 -#define XMLCONCAT 723 -#define XMLELEMENT 724 -#define XMLEXISTS 725 -#define XMLFOREST 726 -#define XMLNAMESPACES 727 -#define XMLPARSE 728 -#define XMLPI 729 -#define XMLROOT 730 -#define XMLSERIALIZE 731 -#define XMLTABLE 732 -#define YEAR_P 733 -#define YEARS_P 734 -#define YES_P 735 -#define ZONE 736 -#define NOT_LA 737 -#define NULLS_LA 738 -#define WITH_LA 739 -#define POSTFIXOP 740 -#define UMINUS 741 +#define POWER_OF 270 +#define LAMBDA_ARROW 271 +#define DOUBLE_ARROW 272 +#define LESS_EQUALS 273 +#define GREATER_EQUALS 274 +#define NOT_EQUALS 275 +#define ABORT_P 276 +#define ABSOLUTE_P 277 +#define ACCESS 278 +#define ACTION 279 +#define ADD_P 280 +#define ADMIN 281 +#define AFTER 282 +#define AGGREGATE 283 +#define ALL 284 +#define ALSO 285 +#define ALTER 286 +#define ALWAYS 287 +#define ANALYSE 288 +#define ANALYZE 289 +#define AND 290 +#define ANY 291 +#define ARRAY 292 +#define AS 293 +#define ASC_P 294 +#define ASSERTION 295 +#define ASSIGNMENT 296 +#define ASYMMETRIC 297 +#define AT 298 +#define ATTACH 299 +#define ATTRIBUTE 300 +#define AUTHORIZATION 301 +#define BACKWARD 302 +#define BEFORE 303 +#define BEGIN_P 304 +#define BETWEEN 305 +#define BIGINT 306 +#define BINARY 307 +#define BIT 308 +#define BOOLEAN_P 309 +#define BOTH 310 +#define BY 311 +#define CACHE 312 +#define CALL_P 313 +#define CALLED 314 +#define CASCADE 315 +#define CASCADED 316 +#define CASE 317 +#define CAST 318 +#define CATALOG_P 319 +#define CHAIN 320 +#define CHAR_P 321 +#define CHARACTER 322 +#define CHARACTERISTICS 323 +#define CHECK_P 324 +#define CHECKPOINT 325 +#define CLASS 326 +#define CLOSE 327 +#define CLUSTER 328 +#define COALESCE 329 +#define COLLATE 330 +#define COLLATION 331 +#define COLUMN 332 +#define COLUMNS 333 +#define COMMENT 334 +#define COMMENTS 335 +#define COMMIT 336 +#define COMMITTED 337 +#define COMPRESSION 338 +#define CONCURRENTLY 339 +#define CONFIGURATION 340 +#define CONFLICT 341 +#define CONNECTION 342 +#define CONSTRAINT 343 +#define CONSTRAINTS 344 +#define CONTENT_P 345 +#define CONTINUE_P 346 +#define CONVERSION_P 347 +#define COPY 348 +#define COST 349 +#define CREATE_P 350 +#define CROSS 351 +#define CSV 352 +#define CUBE 353 +#define CURRENT_P 354 +#define CURRENT_CATALOG 355 +#define CURRENT_DATE 356 +#define CURRENT_ROLE 357 +#define CURRENT_SCHEMA 358 +#define CURRENT_TIME 359 +#define CURRENT_TIMESTAMP 360 +#define CURRENT_USER 361 +#define CURSOR 362 +#define CYCLE 363 +#define DATA_P 364 +#define DATABASE 365 +#define DAY_P 366 +#define DAYS_P 367 +#define DEALLOCATE 368 +#define DEC 369 +#define DECIMAL_P 370 +#define DECLARE 371 +#define DEFAULT 372 +#define DEFAULTS 373 +#define DEFERRABLE 374 +#define DEFERRED 375 +#define DEFINER 376 +#define DELETE_P 377 +#define DELIMITER 378 +#define DELIMITERS 379 +#define DEPENDS 380 +#define DESC_P 381 +#define DESCRIBE 382 +#define DETACH 383 +#define DICTIONARY 384 +#define DISABLE_P 385 +#define DISCARD 386 +#define DISTINCT 387 +#define DO 388 +#define DOCUMENT_P 389 +#define DOMAIN_P 390 +#define DOUBLE_P 391 +#define DROP 392 +#define EACH 393 +#define ELSE 394 +#define ENABLE_P 395 +#define ENCODING 396 +#define ENCRYPTED 397 +#define END_P 398 +#define ENUM_P 399 +#define ESCAPE 400 +#define EVENT 401 +#define EXCEPT 402 +#define EXCLUDE 403 +#define EXCLUDING 404 +#define EXCLUSIVE 405 +#define EXECUTE 406 +#define EXISTS 407 +#define EXPLAIN 408 +#define EXPORT_P 409 +#define EXPORT_STATE 410 +#define EXTENSION 411 +#define EXTERNAL 412 +#define EXTRACT 413 +#define FALSE_P 414 +#define FAMILY 415 +#define FETCH 416 +#define FILTER 417 +#define FIRST_P 418 +#define FLOAT_P 419 +#define FOLLOWING 420 +#define FOR 421 +#define FORCE 422 +#define FOREIGN 423 +#define FORWARD 424 +#define FREEZE 425 +#define FROM 426 +#define FULL 427 +#define FUNCTION 428 +#define FUNCTIONS 429 +#define GENERATED 430 +#define GLOB 431 +#define GLOBAL 432 +#define GRANT 433 +#define GRANTED 434 +#define GROUP_P 435 +#define GROUPING 436 +#define GROUPING_ID 437 +#define HANDLER 438 +#define HAVING 439 +#define HEADER_P 440 +#define HOLD 441 +#define HOUR_P 442 +#define HOURS_P 443 +#define IDENTITY_P 444 +#define IF_P 445 +#define IGNORE_P 446 +#define ILIKE 447 +#define IMMEDIATE 448 +#define IMMUTABLE 449 +#define IMPLICIT_P 450 +#define IMPORT_P 451 +#define IN_P 452 +#define INCLUDING 453 +#define INCREMENT 454 +#define INDEX 455 +#define INDEXES 456 +#define INHERIT 457 +#define INHERITS 458 +#define INITIALLY 459 +#define INLINE_P 460 +#define INNER_P 461 +#define INOUT 462 +#define INPUT_P 463 +#define INSENSITIVE 464 +#define INSERT 465 +#define INSTALL 466 +#define INSTEAD 467 +#define INT_P 468 +#define INTEGER 469 +#define INTERSECT 470 +#define INTERVAL 471 +#define INTO 472 +#define INVOKER 473 +#define IS 474 +#define ISNULL 475 +#define ISOLATION 476 +#define JOIN 477 +#define JSON 478 +#define KEY 479 +#define LABEL 480 +#define LANGUAGE 481 +#define LARGE_P 482 +#define LAST_P 483 +#define LATERAL_P 484 +#define LEADING 485 +#define LEAKPROOF 486 +#define LEFT 487 +#define LEVEL 488 +#define LIKE 489 +#define LIMIT 490 +#define LISTEN 491 +#define LOAD 492 +#define LOCAL 493 +#define LOCALTIME 494 +#define LOCALTIMESTAMP 495 +#define LOCATION 496 +#define LOCK_P 497 +#define LOCKED 498 +#define LOGGED 499 +#define MACRO 500 +#define MAP 501 +#define MAPPING 502 +#define MATCH 503 +#define MATERIALIZED 504 +#define MAXVALUE 505 +#define METHOD 506 +#define MICROSECOND_P 507 +#define MICROSECONDS_P 508 +#define MILLISECOND_P 509 +#define MILLISECONDS_P 510 +#define MINUTE_P 511 +#define MINUTES_P 512 +#define MINVALUE 513 +#define MODE 514 +#define MONTH_P 515 +#define MONTHS_P 516 +#define MOVE 517 +#define NAME_P 518 +#define NAMES 519 +#define NATIONAL 520 +#define NATURAL 521 +#define NCHAR 522 +#define NEW 523 +#define NEXT 524 +#define NO 525 +#define NONE 526 +#define NOT 527 +#define NOTHING 528 +#define NOTIFY 529 +#define NOTNULL 530 +#define NOWAIT 531 +#define NULL_P 532 +#define NULLIF 533 +#define NULLS_P 534 +#define NUMERIC 535 +#define OBJECT_P 536 +#define OF 537 +#define OFF 538 +#define OFFSET 539 +#define OIDS 540 +#define OLD 541 +#define ON 542 +#define ONLY 543 +#define OPERATOR 544 +#define OPTION 545 +#define OPTIONS 546 +#define OR 547 +#define ORDER 548 +#define ORDINALITY 549 +#define OUT_P 550 +#define OUTER_P 551 +#define OVER 552 +#define OVERLAPS 553 +#define OVERLAY 554 +#define OVERRIDING 555 +#define OWNED 556 +#define OWNER 557 +#define PARALLEL 558 +#define PARSER 559 +#define PARTIAL 560 +#define PARTITION 561 +#define PASSING 562 +#define PASSWORD 563 +#define PERCENT 564 +#define PLACING 565 +#define PLANS 566 +#define POLICY 567 +#define POSITION 568 +#define PRAGMA_P 569 +#define PRECEDING 570 +#define PRECISION 571 +#define PREPARE 572 +#define PREPARED 573 +#define PRESERVE 574 +#define PRIMARY 575 +#define PRIOR 576 +#define PRIVILEGES 577 +#define PROCEDURAL 578 +#define PROCEDURE 579 +#define PROGRAM 580 +#define PUBLICATION 581 +#define QUALIFY 582 +#define QUOTE 583 +#define RANGE 584 +#define READ_P 585 +#define REAL 586 +#define REASSIGN 587 +#define RECHECK 588 +#define RECURSIVE 589 +#define REF 590 +#define REFERENCES 591 +#define REFERENCING 592 +#define REFRESH 593 +#define REINDEX 594 +#define RELATIVE_P 595 +#define RELEASE 596 +#define RENAME 597 +#define REPEATABLE 598 +#define REPLACE 599 +#define REPLICA 600 +#define RESET 601 +#define RESPECT_P 602 +#define RESTART 603 +#define RESTRICT 604 +#define RETURNING 605 +#define RETURNS 606 +#define REVOKE 607 +#define RIGHT 608 +#define ROLE 609 +#define ROLLBACK 610 +#define ROLLUP 611 +#define ROW 612 +#define ROWS 613 +#define RULE 614 +#define SAMPLE 615 +#define SAVEPOINT 616 +#define SCHEMA 617 +#define SCHEMAS 618 +#define SCROLL 619 +#define SEARCH 620 +#define SECOND_P 621 +#define SECONDS_P 622 +#define SECURITY 623 +#define SELECT 624 +#define SEQUENCE 625 +#define SEQUENCES 626 +#define SERIALIZABLE 627 +#define SERVER 628 +#define SESSION 629 +#define SESSION_USER 630 +#define SET 631 +#define SETOF 632 +#define SETS 633 +#define SHARE 634 +#define SHOW 635 +#define SIMILAR 636 +#define SIMPLE 637 +#define SKIP 638 +#define SMALLINT 639 +#define SNAPSHOT 640 +#define SOME 641 +#define SQL_P 642 +#define STABLE 643 +#define STANDALONE_P 644 +#define START 645 +#define STATEMENT 646 +#define STATISTICS 647 +#define STDIN 648 +#define STDOUT 649 +#define STORAGE 650 +#define STORED 651 +#define STRICT_P 652 +#define STRIP_P 653 +#define STRUCT 654 +#define SUBSCRIPTION 655 +#define SUBSTRING 656 +#define SUMMARIZE 657 +#define SYMMETRIC 658 +#define SYSID 659 +#define SYSTEM_P 660 +#define TABLE 661 +#define TABLES 662 +#define TABLESAMPLE 663 +#define TABLESPACE 664 +#define TEMP 665 +#define TEMPLATE 666 +#define TEMPORARY 667 +#define TEXT_P 668 +#define THEN 669 +#define TIME 670 +#define TIMESTAMP 671 +#define TO 672 +#define TRAILING 673 +#define TRANSACTION 674 +#define TRANSFORM 675 +#define TREAT 676 +#define TRIGGER 677 +#define TRIM 678 +#define TRUE_P 679 +#define TRUNCATE 680 +#define TRUSTED 681 +#define TRY_CAST 682 +#define TYPE_P 683 +#define TYPES_P 684 +#define UNBOUNDED 685 +#define UNCOMMITTED 686 +#define UNENCRYPTED 687 +#define UNION 688 +#define UNIQUE 689 +#define UNKNOWN 690 +#define UNLISTEN 691 +#define UNLOGGED 692 +#define UNTIL 693 +#define UPDATE 694 +#define USER 695 +#define USING 696 +#define VACUUM 697 +#define VALID 698 +#define VALIDATE 699 +#define VALIDATOR 700 +#define VALUE_P 701 +#define VALUES 702 +#define VARCHAR 703 +#define VARIADIC 704 +#define VARYING 705 +#define VERBOSE 706 +#define VERSION_P 707 +#define VIEW 708 +#define VIEWS 709 +#define VIRTUAL 710 +#define VOLATILE 711 +#define WHEN 712 +#define WHERE 713 +#define WHITESPACE_P 714 +#define WINDOW 715 +#define WITH 716 +#define WITHIN 717 +#define WITHOUT 718 +#define WORK 719 +#define WRAPPER 720 +#define WRITE_P 721 +#define XML_P 722 +#define XMLATTRIBUTES 723 +#define XMLCONCAT 724 +#define XMLELEMENT 725 +#define XMLEXISTS 726 +#define XMLFOREST 727 +#define XMLNAMESPACES 728 +#define XMLPARSE 729 +#define XMLPI 730 +#define XMLROOT 731 +#define XMLSERIALIZE 732 +#define XMLTABLE 733 +#define YEAR_P 734 +#define YEARS_P 735 +#define YES_P 736 +#define ZONE 737 +#define NOT_LA 738 +#define NULLS_LA 739 +#define WITH_LA 740 +#define POSTFIXOP 741 +#define UMINUS 742 @@ -252561,7 +270560,7 @@ typedef union YYSTYPE PGViewCheckOption viewcheckoption; } /* Line 1529 of yacc.c. */ -#line 1066 "third_party/libpg_query/grammar/grammar_out.hpp" +#line 1068 "third_party/libpg_query/grammar/grammar_out.hpp" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 @@ -252638,7 +270637,7 @@ int base_yyparse(core_yyscan_t yyscanner); // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -252662,7 +270661,7 @@ int base_yyparse(core_yyscan_t yyscanner); // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -252682,7 +270681,7 @@ int base_yyparse(core_yyscan_t yyscanner); // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -252743,7 +270742,7 @@ typedef struct { // LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 // See the end of this file for a list /*------------------------------------------------------------------------- @@ -252970,7 +270969,7 @@ static PGNode *makeIntervalNode(char *str, int location, PGList *typmods); static PGNode *makeIntervalNode(int val, int location, PGList *typmods); static PGNode *makeIntervalNode(PGNode *arg, int location, PGList *typmods); static PGNode *makeSampleSize(PGValue *sample_size, bool is_percentage); -static PGNode *makeSampleOptions(PGNode *sample_size, char *method, int seed, int location); +static PGNode *makeSampleOptions(PGNode *sample_size, char *method, int *seed, int location); static PGNode *makeIntConst(int val, int location); static PGNode *makeFloatConst(char *str, int location); static PGNode *makeBitStringConst(char *str, int location); @@ -253071,7 +271070,7 @@ typedef union YYSTYPE PGViewCheckOption viewcheckoption; } /* Line 193 of yacc.c. */ -#line 1287 "third_party/libpg_query/grammar/grammar_out.cpp" +#line 1289 "third_party/libpg_query/grammar/grammar_out.cpp" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 @@ -253096,7 +271095,7 @@ typedef struct YYLTYPE /* Line 216 of yacc.c. */ -#line 1312 "third_party/libpg_query/grammar/grammar_out.cpp" +#line 1314 "third_party/libpg_query/grammar/grammar_out.cpp" #ifdef short # undef short @@ -253311,22 +271310,22 @@ union yyalloc #endif /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 599 +#define YYFINAL 630 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 55839 +#define YYLAST 56666 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 508 +#define YYNTOKENS 509 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 397 +#define YYNNTS 396 /* YYNRULES -- Number of rules. */ -#define YYNRULES 1850 +#define YYNRULES 1918 /* YYNRULES -- Number of states. */ -#define YYNSTATES 3043 +#define YYNSTATES 3104 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 -#define YYMAXUTOK 741 +#define YYMAXUTOK 742 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) @@ -253337,16 +271336,16 @@ static const yytype_uint16 yytranslate[] = 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 505, 2, 493, 2, 2, - 498, 499, 491, 489, 502, 490, 500, 492, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 507, 501, - 485, 487, 486, 506, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 506, 2, 494, 2, 2, + 499, 500, 492, 490, 503, 491, 501, 493, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 508, 502, + 486, 488, 487, 507, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 496, 2, 497, 494, 2, 2, 2, 2, 2, + 2, 497, 2, 498, 495, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 503, 2, 504, 2, 2, 2, 2, + 2, 2, 2, 504, 2, 505, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -253408,7 +271407,7 @@ static const yytype_uint16 yytranslate[] = 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, - 488, 495 + 485, 489, 496 }; #if YYDEBUG @@ -253432,737 +271431,757 @@ static const yytype_uint16 yyprhs[] = 526, 527, 530, 534, 540, 549, 555, 556, 562, 568, 576, 579, 580, 582, 584, 586, 590, 593, 594, 596, 597, 599, 603, 605, 609, 611, 614, 616, 620, 623, - 632, 638, 640, 641, 643, 647, 650, 655, 661, 667, - 676, 678, 679, 683, 693, 706, 710, 711, 716, 723, - 725, 728, 730, 732, 733, 735, 738, 741, 743, 746, - 749, 751, 754, 758, 761, 764, 767, 770, 774, 778, - 782, 784, 788, 790, 791, 793, 796, 799, 802, 805, - 808, 811, 814, 817, 819, 821, 822, 832, 845, 857, - 858, 861, 863, 865, 867, 869, 871, 873, 877, 878, - 880, 883, 885, 887, 890, 893, 897, 899, 901, 904, - 907, 909, 912, 916, 922, 926, 929, 935, 937, 939, - 941, 942, 948, 956, 962, 965, 969, 971, 973, 976, - 979, 980, 984, 989, 994, 995, 999, 1002, 1003, 1007, - 1009, 1011, 1013, 1015, 1017, 1019, 1021, 1023, 1025, 1027, - 1031, 1035, 1037, 1040, 1043, 1046, 1049, 1052, 1055, 1056, - 1060, 1064, 1068, 1069, 1071, 1074, 1076, 1079, 1082, 1085, - 1088, 1092, 1097, 1099, 1103, 1105, 1107, 1109, 1111, 1115, - 1117, 1120, 1121, 1123, 1126, 1127, 1129, 1133, 1134, 1137, - 1138, 1142, 1146, 1148, 1154, 1158, 1160, 1164, 1166, 1169, - 1171, 1176, 1182, 1188, 1195, 1199, 1207, 1212, 1224, 1226, - 1230, 1233, 1236, 1239, 1240, 1244, 1246, 1248, 1251, 1254, - 1257, 1260, 1262, 1263, 1265, 1268, 1275, 1280, 1287, 1292, - 1299, 1308, 1313, 1320, 1322, 1324, 1326, 1328, 1331, 1333, - 1336, 1338, 1341, 1343, 1345, 1347, 1351, 1355, 1359, 1363, - 1366, 1369, 1371, 1375, 1377, 1379, 1381, 1383, 1387, 1389, - 1391, 1392, 1394, 1396, 1398, 1400, 1404, 1413, 1421, 1423, - 1425, 1428, 1432, 1441, 1453, 1463, 1465, 1467, 1471, 1472, - 1474, 1478, 1480, 1481, 1483, 1484, 1486, 1487, 1489, 1493, - 1495, 1497, 1499, 1503, 1504, 1507, 1510, 1511, 1514, 1515, - 1517, 1518, 1520, 1522, 1524, 1528, 1532, 1534, 1536, 1540, - 1544, 1548, 1552, 1557, 1561, 1564, 1566, 1568, 1570, 1572, - 1574, 1578, 1580, 1582, 1586, 1590, 1592, 1595, 1600, 1605, - 1608, 1612, 1618, 1624, 1626, 1628, 1640, 1652, 1654, 1657, - 1662, 1667, 1672, 1675, 1678, 1682, 1684, 1688, 1695, 1698, - 1699, 1703, 1707, 1712, 1717, 1722, 1727, 1731, 1734, 1736, - 1738, 1739, 1741, 1743, 1744, 1746, 1752, 1754, 1755, 1758, - 1761, 1762, 1764, 1765, 1769, 1775, 1781, 1783, 1787, 1792, - 1796, 1798, 1800, 1801, 1804, 1807, 1808, 1811, 1814, 1816, - 1818, 1820, 1821, 1824, 1829, 1835, 1840, 1843, 1847, 1850, - 1853, 1856, 1859, 1861, 1864, 1868, 1869, 1871, 1872, 1878, - 1880, 1885, 1892, 1895, 1897, 1898, 1903, 1904, 1906, 1908, - 1911, 1914, 1917, 1919, 1921, 1924, 1927, 1929, 1931, 1933, - 1935, 1937, 1939, 1943, 1947, 1951, 1952, 1954, 1958, 1960, - 1963, 1965, 1967, 1969, 1971, 1973, 1976, 1981, 1986, 1992, - 1994, 1996, 1999, 2000, 2003, 2004, 2006, 2010, 2012, 2013, - 2015, 2018, 2022, 2025, 2030, 2033, 2037, 2040, 2041, 2043, - 2046, 2047, 2052, 2058, 2060, 2063, 2066, 2067, 2069, 2073, - 2075, 2078, 2082, 2086, 2090, 2094, 2098, 2100, 2105, 2109, - 2114, 2120, 2125, 2131, 2136, 2142, 2145, 2150, 2152, 2154, - 2155, 2157, 2162, 2168, 2173, 2174, 2177, 2180, 2183, 2185, - 2187, 2188, 2193, 2196, 2198, 2201, 2204, 2209, 2212, 2219, - 2222, 2224, 2228, 2233, 2234, 2237, 2238, 2241, 2242, 2244, - 2248, 2252, 2255, 2256, 2259, 2264, 2266, 2268, 2270, 2271, - 2274, 2278, 2284, 2291, 2294, 2298, 2304, 2310, 2314, 2319, - 2320, 2322, 2324, 2326, 2328, 2330, 2333, 2338, 2340, 2342, - 2344, 2346, 2349, 2353, 2354, 2356, 2358, 2360, 2362, 2364, - 2367, 2370, 2373, 2376, 2379, 2381, 2385, 2386, 2388, 2390, - 2392, 2394, 2400, 2403, 2405, 2407, 2409, 2411, 2416, 2418, - 2421, 2424, 2426, 2430, 2434, 2437, 2439, 2440, 2446, 2449, - 2455, 2458, 2460, 2464, 2468, 2469, 2471, 2473, 2475, 2477, - 2479, 2481, 2483, 2485, 2487, 2489, 2491, 2493, 2495, 2497, - 2499, 2501, 2503, 2505, 2507, 2509, 2511, 2513, 2515, 2517, - 2521, 2525, 2529, 2533, 2537, 2541, 2545, 2546, 2548, 2552, - 2556, 2562, 2565, 2568, 2572, 2576, 2580, 2584, 2588, 2592, - 2596, 2600, 2604, 2608, 2612, 2616, 2620, 2624, 2627, 2630, - 2634, 2638, 2641, 2644, 2648, 2652, 2658, 2663, 2670, 2674, - 2680, 2685, 2692, 2697, 2704, 2710, 2718, 2722, 2725, 2730, - 2734, 2737, 2739, 2743, 2747, 2751, 2755, 2759, 2764, 2768, - 2773, 2777, 2782, 2788, 2795, 2802, 2810, 2817, 2825, 2832, - 2840, 2844, 2849, 2854, 2861, 2863, 2868, 2870, 2874, 2877, - 2880, 2884, 2888, 2892, 2896, 2900, 2904, 2908, 2912, 2916, - 2920, 2924, 2928, 2932, 2936, 2939, 2942, 2948, 2955, 2962, - 2970, 2972, 2974, 2977, 2980, 2983, 2988, 2990, 2993, 2995, - 2998, 3001, 3006, 3010, 3017, 3025, 3035, 3043, 3051, 3056, - 3062, 3064, 3066, 3068, 3074, 3076, 3078, 3083, 3085, 3090, - 3092, 3097, 3099, 3104, 3106, 3108, 3110, 3112, 3114, 3116, - 3123, 3130, 3135, 3140, 3145, 3150, 3157, 3163, 3169, 3175, - 3180, 3187, 3192, 3198, 3199, 3205, 3206, 3208, 3209, 3212, - 3213, 3215, 3219, 3223, 3226, 3229, 3230, 3237, 3239, 3240, - 3244, 3245, 3248, 3251, 3252, 3254, 3259, 3262, 3265, 3268, - 3271, 3274, 3279, 3283, 3285, 3291, 3295, 3297, 3301, 3303, - 3306, 3308, 3310, 3312, 3314, 3316, 3318, 3320, 3322, 3324, - 3326, 3328, 3330, 3332, 3334, 3336, 3338, 3340, 3342, 3344, - 3349, 3351, 3356, 3358, 3363, 3365, 3368, 3370, 3373, 3375, - 3378, 3380, 3384, 3386, 3390, 3392, 3395, 3397, 3398, 3400, - 3404, 3406, 3410, 3414, 3416, 3420, 3424, 3425, 3427, 3429, - 3431, 3433, 3435, 3437, 3439, 3441, 3443, 3445, 3450, 3454, - 3457, 3461, 3462, 3466, 3470, 3473, 3476, 3478, 3479, 3482, - 3485, 3489, 3492, 3494, 3496, 3500, 3506, 3508, 3511, 3516, - 3519, 3520, 3522, 3523, 3525, 3528, 3531, 3535, 3541, 3543, - 3544, 3546, 3549, 3550, 3553, 3555, 3556, 3558, 3559, 3561, - 3565, 3567, 3570, 3574, 3577, 3579, 3583, 3589, 3594, 3597, - 3599, 3600, 3604, 3606, 3610, 3612, 3615, 3620, 3623, 3624, - 3626, 3630, 3632, 3635, 3637, 3641, 3643, 3646, 3648, 3650, - 3652, 3655, 3657, 3659, 3662, 3664, 3666, 3669, 3677, 3680, - 3686, 3690, 3694, 3696, 3698, 3700, 3702, 3704, 3706, 3708, - 3710, 3712, 3714, 3716, 3718, 3720, 3722, 3724, 3726, 3728, - 3730, 3732, 3734, 3737, 3740, 3744, 3748, 3749, 3751, 3753, - 3755, 3757, 3759, 3761, 3763, 3769, 3773, 3774, 3776, 3778, - 3780, 3782, 3787, 3795, 3798, 3799, 3801, 3803, 3805, 3807, - 3821, 3838, 3840, 3843, 3844, 3846, 3847, 3849, 3850, 3853, - 3854, 3856, 3857, 3864, 3873, 3880, 3889, 3896, 3905, 3908, - 3910, 3915, 3919, 3922, 3927, 3931, 3937, 3939, 3940, 3942, - 3944, 3945, 3947, 3949, 3951, 3953, 3955, 3957, 3959, 3961, - 3963, 3965, 3967, 3971, 3973, 3975, 3977, 3979, 3981, 3983, - 3986, 3988, 3990, 3993, 3997, 4001, 4005, 4007, 4011, 4015, - 4018, 4022, 4026, 4030, 4034, 4036, 4038, 4040, 4042, 4046, - 4052, 4054, 4056, 4058, 4060, 4064, 4067, 4070, 4074, 4076, - 4078, 4083, 4089, 4095, 4100, 4107, 4109, 4111, 4113, 4115, - 4117, 4119, 4120, 4122, 4126, 4128, 4129, 4137, 4139, 4142, - 4146, 4149, 4150, 4153, 4154, 4157, 4162, 4165, 4167, 4169, - 4171, 4174, 4178, 4181, 4184, 4187, 4190, 4194, 4199, 4202, - 4204, 4206, 4208, 4210, 4214, 4217, 4227, 4239, 4252, 4267, - 4271, 4276, 4281, 4282, 4290, 4301, 4311, 4314, 4318, 4319, - 4324, 4326, 4328, 4330, 4332, 4334, 4336, 4338, 4340, 4342, - 4344, 4346, 4348, 4350, 4352, 4354, 4356, 4358, 4360, 4362, - 4364, 4366, 4368, 4370, 4372, 4374, 4376, 4378, 4380, 4382, - 4384, 4386, 4388, 4390, 4392, 4394, 4396, 4398, 4400, 4402, - 4404, 4406, 4408, 4410, 4412, 4414, 4416, 4418, 4420, 4422, - 4424, 4426, 4428, 4430, 4432, 4434, 4436, 4438, 4440, 4442, - 4444, 4446, 4448, 4450, 4452, 4454, 4456, 4458, 4460, 4462, - 4464, 4466, 4468, 4470, 4472, 4474, 4476, 4478, 4480, 4482, - 4484, 4486, 4488, 4490, 4492, 4494, 4496, 4498, 4500, 4502, - 4504, 4506, 4508, 4510, 4512, 4514, 4516, 4518, 4520, 4522, - 4524, 4526, 4528, 4530, 4532, 4534, 4536, 4538, 4540, 4542, - 4544, 4546, 4548, 4550, 4552, 4554, 4556, 4558, 4560, 4562, - 4564, 4566, 4568, 4570, 4572, 4574, 4576, 4578, 4580, 4582, - 4584, 4586, 4588, 4590, 4592, 4594, 4596, 4598, 4600, 4602, - 4604, 4606, 4608, 4610, 4612, 4614, 4616, 4618, 4620, 4622, - 4624, 4626, 4628, 4630, 4632, 4634, 4636, 4638, 4640, 4642, - 4644, 4646, 4648, 4650, 4652, 4654, 4656, 4658, 4660, 4662, - 4664, 4666, 4668, 4670, 4672, 4674, 4676, 4678, 4680, 4682, - 4684, 4686, 4688, 4690, 4692, 4694, 4696, 4698, 4700, 4702, - 4704, 4706, 4708, 4710, 4712, 4714, 4716, 4718, 4720, 4722, - 4724, 4726, 4728, 4730, 4732, 4734, 4736, 4738, 4740, 4742, - 4744, 4746, 4748, 4750, 4752, 4754, 4756, 4758, 4760, 4762, - 4764, 4766, 4768, 4770, 4772, 4774, 4776, 4778, 4780, 4782, - 4784, 4786, 4788, 4790, 4792, 4794, 4796, 4798, 4800, 4802, - 4804, 4806, 4808, 4810, 4812, 4814, 4816, 4818, 4820, 4822, - 4824, 4826, 4828, 4830, 4832, 4834, 4836, 4838, 4840, 4842, - 4844, 4846, 4848, 4850, 4852, 4854, 4856, 4858, 4860, 4862, - 4864, 4866, 4868, 4870, 4872, 4874, 4876, 4878, 4880, 4882, - 4884, 4886, 4888, 4890, 4892, 4894, 4896, 4898, 4900, 4902, - 4904, 4906, 4908, 4910, 4912, 4914, 4916, 4918, 4920, 4922, - 4924, 4926, 4928, 4930, 4932, 4934, 4936, 4938, 4940, 4942, - 4944, 4946, 4948, 4950, 4952, 4954, 4956, 4958, 4960, 4962, - 4964, 4966, 4968, 4970, 4972, 4974, 4976, 4978, 4980, 4982, - 4984, 4986, 4988, 4990, 4992, 4994, 4996, 4998, 5000, 5002, - 5004, 5006, 5008, 5010, 5012, 5014, 5016, 5018, 5020, 5022, - 5024, 5026, 5028, 5030, 5032, 5034, 5036, 5038, 5040, 5042, - 5044, 5046, 5048, 5050, 5052, 5054, 5056, 5058, 5060, 5062, - 5064, 5066, 5068, 5070, 5072, 5074, 5076, 5078, 5080, 5082, - 5084, 5086, 5088, 5090, 5092, 5094, 5096, 5098, 5100, 5102, - 5104, 5106, 5108, 5110, 5112, 5114, 5116, 5118, 5120, 5122, - 5124, 5126, 5128, 5130, 5132, 5134, 5136, 5138, 5140, 5142, - 5144, 5146, 5148, 5150, 5152, 5154, 5156, 5158, 5160, 5162, - 5164, 5166, 5168, 5170, 5172, 5174, 5176, 5178, 5180, 5182, - 5184, 5186, 5188, 5190, 5192, 5194, 5196, 5198, 5200, 5202, - 5204, 5206, 5208, 5210, 5212, 5214, 5216, 5218, 5220, 5222, - 5224, 5226, 5228, 5230, 5232, 5234, 5236, 5238, 5240, 5242, - 5244, 5246, 5248, 5250, 5252, 5254, 5256, 5258, 5260, 5262, - 5264, 5266, 5268, 5270, 5272, 5274, 5276, 5278, 5280, 5282, - 5284, 5286, 5288, 5290, 5292, 5294, 5296, 5298, 5300, 5302, - 5304, 5306, 5308, 5310, 5312, 5314, 5316, 5318, 5320, 5322, - 5324, 5326, 5328, 5330, 5332, 5334, 5336, 5338, 5340, 5342, - 5344, 5346, 5348, 5350, 5352, 5354, 5356, 5358, 5360, 5362, - 5364, 5366, 5368, 5370, 5372, 5374, 5376, 5378, 5380, 5382, - 5384, 5386, 5388, 5390, 5392, 5394, 5396, 5398, 5400, 5402, - 5404, 5406, 5408, 5410, 5412, 5414, 5416, 5418, 5420, 5422, - 5424, 5426, 5428, 5430, 5432, 5434, 5436, 5438, 5440, 5442, - 5444, 5446, 5448, 5450, 5452, 5454, 5456, 5458, 5460, 5462, - 5464 + 629, 632, 637, 643, 649, 658, 660, 661, 665, 675, + 688, 692, 693, 698, 705, 707, 710, 712, 714, 715, + 717, 720, 723, 725, 728, 731, 733, 736, 740, 743, + 746, 749, 752, 756, 760, 764, 766, 770, 772, 773, + 775, 778, 781, 784, 787, 790, 793, 796, 799, 801, + 803, 804, 814, 827, 839, 840, 843, 845, 847, 849, + 851, 853, 855, 859, 860, 862, 865, 867, 869, 872, + 875, 879, 881, 883, 886, 889, 891, 894, 898, 904, + 908, 911, 917, 919, 921, 923, 924, 930, 938, 944, + 947, 951, 953, 955, 958, 961, 962, 966, 971, 976, + 977, 981, 984, 985, 989, 991, 993, 995, 997, 999, + 1001, 1003, 1005, 1007, 1009, 1013, 1017, 1019, 1022, 1025, + 1028, 1031, 1034, 1037, 1038, 1042, 1046, 1050, 1051, 1053, + 1056, 1058, 1061, 1064, 1067, 1070, 1074, 1079, 1081, 1085, + 1087, 1089, 1091, 1093, 1097, 1099, 1102, 1103, 1105, 1108, + 1109, 1111, 1115, 1116, 1119, 1120, 1124, 1128, 1130, 1136, + 1140, 1142, 1146, 1148, 1151, 1153, 1158, 1164, 1170, 1177, + 1181, 1189, 1194, 1206, 1208, 1212, 1215, 1218, 1221, 1222, + 1226, 1228, 1230, 1233, 1236, 1239, 1242, 1244, 1245, 1247, + 1250, 1257, 1262, 1269, 1274, 1281, 1290, 1295, 1302, 1304, + 1306, 1308, 1310, 1313, 1315, 1318, 1320, 1323, 1325, 1327, + 1329, 1333, 1337, 1341, 1345, 1348, 1351, 1353, 1357, 1359, + 1361, 1363, 1365, 1369, 1371, 1373, 1374, 1376, 1378, 1380, + 1382, 1386, 1395, 1403, 1405, 1407, 1410, 1414, 1423, 1435, + 1445, 1447, 1449, 1453, 1454, 1456, 1460, 1462, 1463, 1465, + 1466, 1468, 1469, 1471, 1475, 1477, 1479, 1481, 1485, 1486, + 1489, 1492, 1493, 1496, 1497, 1499, 1500, 1502, 1504, 1506, + 1510, 1514, 1516, 1518, 1522, 1526, 1530, 1534, 1539, 1543, + 1546, 1548, 1550, 1552, 1554, 1556, 1560, 1562, 1564, 1568, + 1572, 1574, 1577, 1582, 1587, 1590, 1594, 1600, 1606, 1608, + 1610, 1622, 1634, 1636, 1639, 1645, 1650, 1655, 1660, 1663, + 1666, 1670, 1672, 1676, 1683, 1686, 1687, 1691, 1695, 1700, + 1705, 1710, 1715, 1719, 1722, 1724, 1726, 1727, 1729, 1731, + 1732, 1735, 1737, 1743, 1745, 1746, 1749, 1752, 1753, 1755, + 1756, 1760, 1766, 1772, 1774, 1778, 1783, 1787, 1789, 1791, + 1792, 1795, 1798, 1799, 1802, 1805, 1807, 1809, 1811, 1812, + 1815, 1820, 1826, 1831, 1834, 1838, 1841, 1844, 1847, 1850, + 1852, 1855, 1859, 1860, 1862, 1863, 1869, 1871, 1876, 1883, + 1886, 1888, 1889, 1894, 1895, 1897, 1899, 1902, 1905, 1908, + 1910, 1912, 1915, 1918, 1920, 1922, 1924, 1926, 1928, 1930, + 1934, 1938, 1942, 1943, 1945, 1949, 1951, 1954, 1956, 1958, + 1960, 1962, 1964, 1967, 1972, 1977, 1983, 1985, 1987, 1990, + 1991, 1994, 1995, 1997, 2001, 2003, 2004, 2006, 2009, 2013, + 2016, 2021, 2024, 2028, 2031, 2032, 2034, 2037, 2038, 2043, + 2049, 2051, 2054, 2057, 2058, 2060, 2064, 2066, 2069, 2073, + 2077, 2081, 2085, 2089, 2093, 2095, 2100, 2104, 2109, 2115, + 2120, 2126, 2131, 2137, 2140, 2145, 2147, 2149, 2150, 2152, + 2157, 2163, 2168, 2169, 2172, 2175, 2178, 2180, 2182, 2183, + 2188, 2191, 2193, 2196, 2199, 2204, 2207, 2214, 2217, 2219, + 2223, 2228, 2229, 2232, 2233, 2236, 2237, 2239, 2243, 2247, + 2250, 2251, 2254, 2259, 2261, 2263, 2265, 2266, 2269, 2273, + 2279, 2286, 2289, 2293, 2299, 2305, 2309, 2314, 2315, 2317, + 2319, 2321, 2323, 2325, 2328, 2333, 2335, 2337, 2339, 2341, + 2344, 2348, 2349, 2351, 2353, 2355, 2357, 2359, 2362, 2365, + 2368, 2371, 2374, 2376, 2380, 2381, 2383, 2385, 2387, 2389, + 2395, 2398, 2400, 2402, 2404, 2406, 2411, 2413, 2416, 2419, + 2421, 2425, 2429, 2432, 2434, 2435, 2441, 2444, 2450, 2453, + 2455, 2459, 2463, 2464, 2466, 2468, 2470, 2472, 2474, 2476, + 2478, 2480, 2482, 2484, 2486, 2488, 2490, 2492, 2494, 2496, + 2498, 2500, 2502, 2504, 2506, 2508, 2510, 2512, 2516, 2520, + 2524, 2528, 2532, 2536, 2540, 2541, 2543, 2547, 2551, 2557, + 2560, 2563, 2567, 2571, 2575, 2579, 2583, 2587, 2591, 2595, + 2599, 2603, 2607, 2611, 2615, 2619, 2622, 2625, 2629, 2633, + 2636, 2639, 2643, 2647, 2653, 2658, 2665, 2669, 2675, 2680, + 2687, 2692, 2699, 2705, 2713, 2717, 2720, 2725, 2729, 2732, + 2734, 2738, 2742, 2746, 2750, 2754, 2758, 2763, 2767, 2772, + 2776, 2781, 2787, 2794, 2801, 2809, 2816, 2824, 2831, 2839, + 2843, 2848, 2853, 2860, 2863, 2865, 2870, 2872, 2876, 2879, + 2882, 2886, 2890, 2894, 2898, 2902, 2906, 2910, 2914, 2918, + 2922, 2926, 2930, 2934, 2938, 2941, 2944, 2950, 2957, 2964, + 2972, 2974, 2976, 2979, 2982, 2985, 2990, 2992, 2995, 2997, + 3000, 3003, 3008, 3012, 3019, 3027, 3037, 3045, 3053, 3058, + 3064, 3066, 3068, 3070, 3076, 3078, 3080, 3085, 3087, 3092, + 3094, 3099, 3101, 3106, 3108, 3110, 3112, 3114, 3116, 3118, + 3125, 3132, 3137, 3142, 3147, 3152, 3159, 3165, 3171, 3177, + 3182, 3189, 3194, 3200, 3201, 3207, 3212, 3213, 3215, 3216, + 3219, 3220, 3222, 3226, 3230, 3233, 3236, 3237, 3244, 3246, + 3247, 3251, 3252, 3255, 3258, 3259, 3261, 3266, 3269, 3272, + 3275, 3278, 3281, 3286, 3290, 3292, 3298, 3302, 3304, 3308, + 3310, 3313, 3315, 3317, 3319, 3321, 3323, 3325, 3327, 3329, + 3331, 3333, 3335, 3337, 3339, 3341, 3343, 3345, 3347, 3349, + 3351, 3356, 3358, 3363, 3365, 3370, 3372, 3375, 3377, 3380, + 3382, 3385, 3387, 3391, 3393, 3397, 3399, 3402, 3404, 3405, + 3407, 3411, 3413, 3417, 3421, 3423, 3427, 3431, 3432, 3434, + 3436, 3438, 3440, 3442, 3444, 3446, 3448, 3450, 3452, 3457, + 3461, 3464, 3468, 3469, 3473, 3477, 3480, 3483, 3485, 3486, + 3489, 3492, 3496, 3499, 3501, 3503, 3507, 3513, 3515, 3518, + 3523, 3526, 3527, 3529, 3530, 3532, 3535, 3538, 3542, 3548, + 3550, 3551, 3553, 3556, 3557, 3560, 3562, 3563, 3565, 3566, + 3568, 3572, 3574, 3577, 3581, 3584, 3586, 3590, 3596, 3601, + 3604, 3606, 3607, 3611, 3613, 3617, 3619, 3622, 3627, 3630, + 3631, 3633, 3637, 3639, 3642, 3644, 3648, 3650, 3653, 3655, + 3657, 3659, 3662, 3664, 3666, 3669, 3671, 3673, 3676, 3684, + 3687, 3693, 3697, 3701, 3703, 3705, 3707, 3709, 3711, 3713, + 3715, 3717, 3719, 3721, 3723, 3725, 3727, 3729, 3731, 3733, + 3735, 3737, 3739, 3741, 3744, 3747, 3751, 3755, 3756, 3758, + 3760, 3762, 3764, 3766, 3768, 3770, 3776, 3780, 3781, 3783, + 3785, 3787, 3789, 3794, 3802, 3805, 3806, 3808, 3810, 3812, + 3814, 3828, 3845, 3847, 3850, 3851, 3853, 3854, 3856, 3857, + 3860, 3861, 3863, 3864, 3871, 3880, 3887, 3896, 3903, 3912, + 3915, 3917, 3922, 3926, 3929, 3934, 3938, 3944, 3946, 3947, + 3949, 3951, 3952, 3954, 3956, 3958, 3960, 3962, 3964, 3966, + 3968, 3970, 3972, 3974, 3976, 3978, 3980, 3982, 3984, 3986, + 3988, 3990, 3992, 3994, 3996, 3998, 4000, 4002, 4004, 4006, + 4008, 4010, 4012, 4014, 4016, 4018, 4020, 4022, 4024, 4028, + 4030, 4032, 4034, 4036, 4038, 4040, 4043, 4045, 4047, 4050, + 4054, 4058, 4062, 4064, 4068, 4072, 4075, 4079, 4083, 4087, + 4091, 4093, 4095, 4097, 4099, 4103, 4109, 4111, 4113, 4115, + 4117, 4121, 4124, 4127, 4131, 4133, 4135, 4140, 4146, 4152, + 4157, 4164, 4166, 4168, 4170, 4172, 4174, 4176, 4177, 4179, + 4183, 4185, 4186, 4194, 4196, 4199, 4203, 4206, 4207, 4210, + 4211, 4214, 4219, 4222, 4224, 4226, 4228, 4231, 4235, 4238, + 4241, 4244, 4247, 4251, 4256, 4259, 4261, 4263, 4265, 4267, + 4271, 4274, 4284, 4296, 4309, 4324, 4328, 4333, 4338, 4339, + 4347, 4358, 4368, 4371, 4375, 4376, 4381, 4383, 4385, 4387, + 4389, 4391, 4393, 4395, 4397, 4399, 4401, 4403, 4405, 4407, + 4409, 4411, 4413, 4415, 4417, 4419, 4421, 4423, 4425, 4427, + 4429, 4431, 4433, 4435, 4437, 4439, 4441, 4443, 4445, 4447, + 4449, 4451, 4453, 4455, 4457, 4459, 4461, 4463, 4465, 4467, + 4469, 4471, 4473, 4475, 4477, 4479, 4481, 4483, 4485, 4487, + 4489, 4491, 4493, 4495, 4497, 4499, 4501, 4503, 4505, 4507, + 4509, 4511, 4513, 4515, 4517, 4519, 4521, 4523, 4525, 4527, + 4529, 4531, 4533, 4535, 4537, 4539, 4541, 4543, 4545, 4547, + 4549, 4551, 4553, 4555, 4557, 4559, 4561, 4563, 4565, 4567, + 4569, 4571, 4573, 4575, 4577, 4579, 4581, 4583, 4585, 4587, + 4589, 4591, 4593, 4595, 4597, 4599, 4601, 4603, 4605, 4607, + 4609, 4611, 4613, 4615, 4617, 4619, 4621, 4623, 4625, 4627, + 4629, 4631, 4633, 4635, 4637, 4639, 4641, 4643, 4645, 4647, + 4649, 4651, 4653, 4655, 4657, 4659, 4661, 4663, 4665, 4667, + 4669, 4671, 4673, 4675, 4677, 4679, 4681, 4683, 4685, 4687, + 4689, 4691, 4693, 4695, 4697, 4699, 4701, 4703, 4705, 4707, + 4709, 4711, 4713, 4715, 4717, 4719, 4721, 4723, 4725, 4727, + 4729, 4731, 4733, 4735, 4737, 4739, 4741, 4743, 4745, 4747, + 4749, 4751, 4753, 4755, 4757, 4759, 4761, 4763, 4765, 4767, + 4769, 4771, 4773, 4775, 4777, 4779, 4781, 4783, 4785, 4787, + 4789, 4791, 4793, 4795, 4797, 4799, 4801, 4803, 4805, 4807, + 4809, 4811, 4813, 4815, 4817, 4819, 4821, 4823, 4825, 4827, + 4829, 4831, 4833, 4835, 4837, 4839, 4841, 4843, 4845, 4847, + 4849, 4851, 4853, 4855, 4857, 4859, 4861, 4863, 4865, 4867, + 4869, 4871, 4873, 4875, 4877, 4879, 4881, 4883, 4885, 4887, + 4889, 4891, 4893, 4895, 4897, 4899, 4901, 4903, 4905, 4907, + 4909, 4911, 4913, 4915, 4917, 4919, 4921, 4923, 4925, 4927, + 4929, 4931, 4933, 4935, 4937, 4939, 4941, 4943, 4945, 4947, + 4949, 4951, 4953, 4955, 4957, 4959, 4961, 4963, 4965, 4967, + 4969, 4971, 4973, 4975, 4977, 4979, 4981, 4983, 4985, 4987, + 4989, 4991, 4993, 4995, 4997, 4999, 5001, 5003, 5005, 5007, + 5009, 5011, 5013, 5015, 5017, 5019, 5021, 5023, 5025, 5027, + 5029, 5031, 5033, 5035, 5037, 5039, 5041, 5043, 5045, 5047, + 5049, 5051, 5053, 5055, 5057, 5059, 5061, 5063, 5065, 5067, + 5069, 5071, 5073, 5075, 5077, 5079, 5081, 5083, 5085, 5087, + 5089, 5091, 5093, 5095, 5097, 5099, 5101, 5103, 5105, 5107, + 5109, 5111, 5113, 5115, 5117, 5119, 5121, 5123, 5125, 5127, + 5129, 5131, 5133, 5135, 5137, 5139, 5141, 5143, 5145, 5147, + 5149, 5151, 5153, 5155, 5157, 5159, 5161, 5163, 5165, 5167, + 5169, 5171, 5173, 5175, 5177, 5179, 5181, 5183, 5185, 5187, + 5189, 5191, 5193, 5195, 5197, 5199, 5201, 5203, 5205, 5207, + 5209, 5211, 5213, 5215, 5217, 5219, 5221, 5223, 5225, 5227, + 5229, 5231, 5233, 5235, 5237, 5239, 5241, 5243, 5245, 5247, + 5249, 5251, 5253, 5255, 5257, 5259, 5261, 5263, 5265, 5267, + 5269, 5271, 5273, 5275, 5277, 5279, 5281, 5283, 5285, 5287, + 5289, 5291, 5293, 5295, 5297, 5299, 5301, 5303, 5305, 5307, + 5309, 5311, 5313, 5315, 5317, 5319, 5321, 5323, 5325, 5327, + 5329, 5331, 5333, 5335, 5337, 5339, 5341, 5343, 5345, 5347, + 5349, 5351, 5353, 5355, 5357, 5359, 5361, 5363, 5365, 5367, + 5369, 5371, 5373, 5375, 5377, 5379, 5381, 5383, 5385, 5387, + 5389, 5391, 5393, 5395, 5397, 5399, 5401, 5403, 5405, 5407, + 5409, 5411, 5413, 5415, 5417, 5419, 5421, 5423, 5425, 5427, + 5429, 5431, 5433, 5435, 5437, 5439, 5441, 5443, 5445, 5447, + 5449, 5451, 5453, 5455, 5457, 5459, 5461, 5463, 5465, 5467, + 5469, 5471, 5473, 5475, 5477, 5479, 5481, 5483, 5485, 5487, + 5489, 5491, 5493, 5495, 5497, 5499, 5501, 5503, 5505, 5507, + 5509, 5511, 5513, 5515, 5517, 5519, 5521, 5523, 5525, 5527, + 5529, 5531, 5533, 5535, 5537, 5539, 5541, 5543, 5545, 5547, + 5549, 5551, 5553, 5555, 5557, 5559, 5561, 5563, 5565, 5567, + 5569, 5571, 5573, 5575, 5577, 5579, 5581, 5583, 5585, 5587, + 5589, 5591, 5593, 5595, 5597, 5599, 5601, 5603, 5605 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yytype_int16 yyrhs[] = { - 509, 0, -1, 510, -1, 510, 501, 511, -1, 511, - -1, 853, -1, 553, -1, 512, -1, 885, -1, 892, - -1, 854, -1, 621, -1, 895, -1, 617, -1, 843, - -1, 549, -1, 562, -1, 545, -1, 523, -1, 881, - -1, 610, -1, 551, -1, 857, -1, 855, -1, 856, - -1, 846, -1, 526, -1, 874, -1, 548, -1, 840, - -1, 524, -1, 638, -1, 560, -1, 620, -1, 876, + 510, 0, -1, 511, -1, 511, 502, 512, -1, 512, + -1, 853, -1, 552, -1, 513, -1, 885, -1, 892, + -1, 854, -1, 620, -1, 895, -1, 616, -1, 843, + -1, 548, -1, 561, -1, 546, -1, 524, -1, 881, + -1, 609, -1, 550, -1, 857, -1, 855, -1, 856, + -1, 846, -1, 527, -1, 874, -1, 547, -1, 840, + -1, 525, -1, 637, -1, 559, -1, 619, -1, 876, -1, 886, -1, 868, -1, 889, -1, 893, -1, -1, - 30, 405, 707, 520, -1, 30, 405, 189, 151, 707, - 520, -1, 30, 199, 820, 520, -1, 30, 199, 189, - 151, 820, 520, -1, 30, 369, 820, 520, -1, 30, - 369, 189, 151, 820, 520, -1, 30, 452, 820, 520, - -1, 30, 452, 189, 151, 820, 520, -1, 515, -1, - 513, 515, -1, 375, 116, 750, -1, 136, 116, -1, - 347, -1, 347, 555, 556, -1, 375, 557, -1, 375, - 174, 609, -1, 519, -1, 516, 502, 519, -1, 24, - 589, -1, 24, 189, 271, 151, 589, -1, 24, 76, - 589, -1, 24, 76, 189, 271, 151, 589, -1, 30, - 525, 829, 514, -1, 30, 525, 829, 136, 271, 276, - -1, 30, 525, 829, 375, 271, 276, -1, 30, 525, - 829, 375, 391, 559, -1, 30, 525, 829, 375, 577, - -1, 30, 525, 829, 345, 577, -1, 30, 525, 829, - 375, 394, 829, -1, 30, 525, 829, 24, 174, 609, - 37, 188, 565, -1, 30, 525, 829, 513, -1, 30, - 525, 829, 136, 188, -1, 30, 525, 829, 136, 188, - 189, 151, -1, 136, 525, 189, 151, 829, 614, -1, - 136, 525, 829, 614, -1, 30, 525, 829, 522, 427, - 720, 716, 518, -1, 30, 525, 829, 521, -1, 24, - 579, -1, 30, 87, 823, 563, -1, 443, 87, 823, - -1, 136, 87, 189, 151, 823, 614, -1, 136, 87, - 823, 614, -1, 375, 243, -1, 375, 436, -1, 375, - 577, -1, 345, 577, -1, 521, -1, 440, 750, -1, - -1, 573, -1, 375, 573, -1, 24, 573, -1, 136, - 587, -1, 517, -1, 520, 502, 517, -1, 290, 498, - 516, 499, -1, 375, 108, -1, 375, -1, -1, 112, - 823, -1, 112, 316, 823, -1, 112, 28, -1, 112, - 316, 28, -1, 30, 361, 823, 341, 416, 823, -1, - 30, 405, 707, 341, 416, 823, -1, 30, 405, 189, - 151, 707, 341, 416, 823, -1, 30, 369, 820, 341, - 416, 823, -1, 30, 369, 189, 151, 820, 341, 416, - 823, -1, 30, 452, 820, 341, 416, 823, -1, 30, - 452, 189, 151, 820, 341, 416, 823, -1, 30, 199, - 820, 341, 416, 823, -1, 30, 199, 189, 151, 820, - 341, 416, 823, -1, 30, 405, 707, 341, 525, 823, - 416, 823, -1, 30, 405, 189, 151, 707, 341, 525, - 823, 416, 823, -1, 30, 405, 707, 341, 87, 823, - 416, 823, -1, 30, 405, 189, 151, 707, 341, 87, - 823, 416, 823, -1, 76, -1, -1, 530, 209, 216, - 528, 527, 533, 535, -1, 638, -1, 299, 536, 445, - 638, -1, 498, 540, 499, 638, -1, 498, 540, 499, - 299, 536, 445, 638, -1, 116, 446, -1, 820, -1, - 820, 37, 829, -1, 498, 543, 499, 713, -1, 286, - 87, 823, -1, -1, 643, -1, -1, 829, 807, -1, - 544, 487, 750, -1, 498, 537, 499, 487, 750, -1, - 286, 85, 529, 132, 438, 375, 542, 713, -1, 286, - 85, 529, 132, 272, -1, -1, 829, 538, 539, 657, - 658, -1, 755, 538, 539, 657, 658, -1, 498, 750, - 499, 538, 539, 657, 658, -1, 349, 810, -1, -1, - 439, -1, 404, -1, 544, -1, 537, 502, 544, -1, - 74, 834, -1, -1, 834, -1, -1, 531, -1, 540, - 502, 531, -1, 532, -1, 541, 502, 532, -1, 541, - -1, 541, 502, -1, 534, -1, 543, 502, 534, -1, - 829, 807, -1, 94, 427, 834, 37, 143, 498, 546, - 499, -1, 94, 427, 834, 37, 723, -1, 547, -1, - -1, 828, -1, 547, 502, 828, -1, 313, 829, -1, - 313, 829, 487, 873, -1, 313, 829, 498, 785, 499, - -1, 94, 608, 369, 820, 550, -1, 94, 608, 369, - 189, 271, 151, 820, 550, -1, 554, -1, -1, 150, - 823, 552, -1, 94, 608, 405, 897, 37, 150, 823, - 552, 896, -1, 94, 608, 405, 189, 271, 151, 897, - 37, 150, 823, 552, 896, -1, 498, 783, 499, -1, - -1, 30, 369, 820, 554, -1, 30, 369, 189, 151, - 820, 554, -1, 557, -1, 554, 557, -1, 460, -1, - 484, -1, -1, 4, -1, 489, 4, -1, 490, 4, - -1, 559, -1, 37, 722, -1, 56, 556, -1, 107, - -1, 269, 107, -1, 198, 558, 556, -1, 249, 556, - -1, 257, 556, -1, 269, 249, -1, 269, 257, -1, - 300, 55, 834, -1, 369, 262, 834, -1, 389, 555, - 556, -1, 347, -1, 347, 555, 556, -1, 55, -1, - -1, 827, -1, 489, 827, -1, 490, 827, -1, 20, - 561, -1, 48, 561, -1, 389, 561, -1, 80, 561, - -1, 142, 561, -1, 354, 561, -1, 463, -1, 418, - -1, -1, 94, 608, 405, 820, 498, 595, 499, 584, - 576, -1, 94, 608, 405, 189, 271, 151, 820, 498, - 595, 499, 584, 576, -1, 94, 291, 343, 608, 405, - 820, 498, 595, 499, 584, 576, -1, -1, 563, 588, - -1, 603, -1, 904, -1, 779, -1, 556, -1, 828, - -1, 270, -1, 498, 554, 499, -1, -1, 828, -1, - 269, 23, -1, 348, -1, 59, -1, 375, 276, -1, - 375, 116, -1, 87, 823, 569, -1, 569, -1, 583, - -1, 74, 834, -1, 271, 276, -1, 276, -1, 433, - 594, -1, 319, 223, 594, -1, 68, 498, 750, 499, - 578, -1, 440, 82, 823, -1, 116, 751, -1, 335, - 820, 597, 606, 575, -1, 454, -1, 395, -1, 570, - -1, -1, 174, 609, 37, 188, 565, -1, 174, 609, - 37, 498, 750, 499, 571, -1, 37, 498, 750, 499, - 571, -1, 587, 566, -1, 286, 438, 567, -1, 574, - -1, 599, -1, 574, 599, -1, 599, 574, -1, -1, - 286, 80, 136, -1, 286, 80, 121, 357, -1, 286, - 80, 318, 357, -1, -1, 498, 581, 499, -1, 269, - 201, -1, -1, 87, 823, 604, -1, 604, -1, 79, - -1, 88, -1, 117, -1, 188, -1, 200, -1, 391, - -1, 394, -1, 28, -1, 600, -1, 581, 502, 600, - -1, 440, 199, 591, -1, 118, -1, 271, 118, -1, - 203, 119, -1, 203, 192, -1, 460, 577, -1, 460, - 284, -1, 462, 284, -1, -1, 498, 590, 499, -1, - 586, 197, 580, -1, 586, 148, 580, -1, -1, 838, - -1, 271, 118, -1, 118, -1, 203, 192, -1, 203, - 119, -1, 271, 442, -1, 269, 201, -1, 829, 720, - 598, -1, 829, 719, 572, 598, -1, 593, -1, 590, - 502, 593, -1, 829, -1, 589, -1, 607, -1, 579, - -1, 838, 487, 564, -1, 838, -1, 460, 585, -1, - -1, 605, -1, 605, 502, -1, -1, 829, -1, 498, - 601, 499, -1, -1, 598, 568, -1, -1, 286, 121, - 567, -1, 838, 487, 564, -1, 838, -1, 838, 500, - 838, 487, 564, -1, 838, 500, 838, -1, 596, -1, - 601, 502, 596, -1, 601, -1, 601, 502, -1, 720, - -1, 831, 835, 493, 427, -1, 376, 831, 835, 493, - 427, -1, 68, 498, 750, 499, 563, -1, 433, 498, - 602, 499, 594, 563, -1, 433, 582, 563, -1, 319, - 223, 498, 602, 499, 594, 563, -1, 319, 223, 582, - 563, -1, 167, 223, 498, 602, 499, 335, 820, 597, - 606, 575, 563, -1, 592, -1, 605, 502, 592, -1, - 247, 171, -1, 247, 304, -1, 247, 381, -1, -1, - 233, 820, 586, -1, 411, -1, 409, -1, 237, 411, - -1, 237, 409, -1, 176, 411, -1, 176, 409, -1, - 436, -1, -1, 31, -1, 55, 116, -1, 136, 611, - 189, 151, 613, 614, -1, 136, 611, 613, 614, -1, - 136, 612, 189, 151, 821, 614, -1, 136, 612, 821, - 614, -1, 136, 615, 823, 286, 834, 614, -1, 136, - 615, 189, 151, 823, 286, 834, 614, -1, 136, 427, - 616, 614, -1, 136, 427, 189, 151, 616, 614, -1, - 405, -1, 369, -1, 172, -1, 244, -1, 244, 405, - -1, 452, -1, 248, 452, -1, 199, -1, 167, 405, - -1, 75, -1, 91, -1, 391, -1, 412, 364, 303, - -1, 412, 364, 128, -1, 412, 364, 410, -1, 412, - 364, 84, -1, 22, 250, -1, 145, 421, -1, 155, - -1, 167, 108, 464, -1, 325, -1, 361, -1, 372, - -1, 834, -1, 613, 502, 834, -1, 59, -1, 348, - -1, -1, 311, -1, 358, -1, 421, -1, 720, -1, - 616, 502, 720, -1, 94, 608, 618, 820, 619, 37, - 405, 638, -1, 94, 608, 618, 820, 619, 37, 750, - -1, 172, -1, 244, -1, 498, 499, -1, 498, 785, - 499, -1, 530, 438, 882, 375, 542, 696, 883, 535, - -1, 92, 633, 820, 597, 631, 622, 627, 636, 623, - 555, 628, -1, 92, 498, 842, 499, 416, 627, 636, - 555, 628, -1, 170, -1, 416, -1, 625, 123, 828, - -1, -1, 635, -1, 624, 502, 635, -1, 440, -1, - -1, 37, -1, -1, 324, -1, -1, 632, -1, 498, - 637, 499, -1, 865, -1, 556, -1, 491, -1, 498, - 624, 499, -1, -1, 838, 629, -1, 460, 284, -1, - -1, 632, 634, -1, -1, 51, -1, -1, 51, -1, - 284, -1, 169, -1, 122, 626, 828, -1, 276, 626, - 828, -1, 96, -1, 184, -1, 327, 626, 828, -1, - 144, 626, 828, -1, 166, 327, 601, -1, 166, 327, - 491, -1, 166, 271, 276, 601, -1, 166, 276, 601, - -1, 140, 828, -1, 865, -1, 828, -1, 392, -1, - 393, -1, 630, -1, 637, 502, 630, -1, 640, -1, - 639, -1, 498, 640, 499, -1, 498, 639, 499, -1, - 642, -1, 641, 654, -1, 641, 653, 687, 660, -1, - 641, 653, 659, 688, -1, 643, 641, -1, 643, 641, - 654, -1, 643, 641, 653, 687, 660, -1, 643, 641, - 653, 659, 688, -1, 642, -1, 639, -1, 368, 651, - 809, 646, 696, 713, 676, 685, 760, 686, 664, -1, - 368, 650, 811, 646, 696, 713, 676, 685, 760, 686, - 664, -1, 695, -1, 405, 707, -1, 641, 432, 649, - 641, -1, 641, 214, 649, 641, -1, 641, 146, 649, - 641, -1, 460, 644, -1, 484, 644, -1, 460, 333, - 644, -1, 645, -1, 644, 502, 645, -1, 823, 836, - 37, 498, 842, 499, -1, 216, 647, -1, -1, 411, - 648, 820, -1, 409, 648, 820, -1, 237, 411, 648, - 820, -1, 237, 409, 648, 820, -1, 176, 411, 648, - 820, -1, 176, 409, 648, 820, -1, 436, 648, 820, - -1, 405, 820, -1, 820, -1, 405, -1, -1, 28, - -1, 131, -1, -1, 131, -1, 131, 286, 498, 783, - 499, -1, 28, -1, -1, 190, 278, -1, 346, 278, - -1, -1, 654, -1, -1, 292, 55, 655, -1, 292, - 55, 28, 657, 658, -1, 292, 55, 491, 657, 658, - -1, 656, -1, 655, 502, 656, -1, 750, 440, 779, - 658, -1, 750, 657, 658, -1, 38, -1, 125, -1, - -1, 483, 162, -1, 483, 227, -1, -1, 661, 662, - -1, 662, 661, -1, 661, -1, 662, -1, 659, -1, - -1, 234, 670, -1, 234, 670, 502, 671, -1, 160, - 675, 672, 674, 287, -1, 160, 675, 674, 287, -1, - 283, 671, -1, 283, 672, 674, -1, 4, 493, -1, - 9, 493, -1, 4, 308, -1, 9, 308, -1, 9, - -1, 9, 357, -1, 440, 359, 666, -1, -1, 829, - -1, -1, 665, 498, 663, 499, 669, -1, 663, -1, - 663, 498, 829, 499, -1, 663, 498, 829, 502, 9, - 499, -1, 407, 666, -1, 667, -1, -1, 342, 498, - 9, 499, -1, -1, 750, -1, 28, -1, 750, 493, - -1, 4, 308, -1, 9, 308, -1, 750, -1, 752, - -1, 489, 673, -1, 490, 673, -1, 827, -1, 4, - -1, 356, -1, 357, -1, 162, -1, 268, -1, 179, - 55, 678, -1, 179, 55, 28, -1, 179, 55, 491, - -1, -1, 679, -1, 677, 502, 679, -1, 677, -1, - 677, 502, -1, 750, -1, 680, -1, 682, -1, 681, - -1, 683, -1, 498, 499, -1, 355, 498, 783, 499, - -1, 97, 498, 783, 499, -1, 180, 377, 498, 678, - 499, -1, 180, -1, 181, -1, 183, 750, -1, -1, - 326, 750, -1, -1, 689, -1, 165, 329, 287, -1, - 687, -1, -1, 690, -1, 689, 690, -1, 691, 692, - 693, -1, 165, 438, -1, 165, 269, 223, 438, -1, - 165, 378, -1, 165, 223, 378, -1, 281, 819, -1, - -1, 275, -1, 382, 242, -1, -1, 446, 498, 783, - 499, -1, 694, 502, 498, 783, 499, -1, 694, -1, - 694, 502, -1, 170, 698, -1, -1, 699, -1, 697, - 502, 699, -1, 697, -1, 697, 502, -1, 707, 702, - 668, -1, 708, 703, 668, -1, 228, 708, 703, -1, - 639, 702, 668, -1, 228, 639, 702, -1, 700, -1, - 498, 700, 499, 701, -1, 498, 700, 499, -1, 699, - 95, 221, 699, -1, 699, 704, 221, 699, 706, -1, - 699, 221, 699, 706, -1, 699, 265, 704, 221, 699, - -1, 699, 265, 221, 699, -1, 37, 829, 498, 822, - 499, -1, 37, 830, -1, 829, 498, 822, 499, -1, - 829, -1, 701, -1, -1, 701, -1, 37, 498, 714, - 499, -1, 37, 829, 498, 714, 499, -1, 829, 498, - 714, 499, -1, -1, 171, 705, -1, 231, 705, -1, - 352, 705, -1, 205, -1, 295, -1, -1, 440, 498, - 822, 499, -1, 286, 750, -1, 820, -1, 820, 491, - -1, 287, 820, -1, 287, 498, 820, 499, -1, 755, - 712, -1, 357, 170, 498, 710, 499, 712, -1, 755, - 711, -1, 709, -1, 710, 502, 709, -1, 37, 498, - 714, 499, -1, -1, 484, 293, -1, -1, 457, 750, - -1, -1, 715, -1, 714, 502, 715, -1, 829, 720, - 716, -1, 74, 834, -1, -1, 829, 720, -1, 717, - 502, 829, 720, -1, 356, -1, 398, -1, 720, -1, - -1, 722, 721, -1, 376, 722, 721, -1, 722, 36, - 496, 827, 497, -1, 376, 722, 36, 496, 827, 497, - -1, 722, 36, -1, 376, 722, 36, -1, 718, 498, - 717, 499, 721, -1, 245, 498, 787, 499, 721, -1, - 721, 496, 497, -1, 721, 496, 827, 497, -1, -1, - 724, -1, 726, -1, 728, -1, 732, -1, 738, -1, - 739, 749, -1, 739, 498, 827, 499, -1, 726, -1, - 729, -1, 733, -1, 738, -1, 833, 725, -1, 498, - 783, 499, -1, -1, 212, -1, 213, -1, 383, -1, - 50, -1, 330, -1, 163, 727, -1, 135, 315, -1, - 114, 725, -1, 113, 725, -1, 279, 725, -1, 53, - -1, 498, 827, 499, -1, -1, 730, -1, 731, -1, - 730, -1, 731, -1, 52, 737, 498, 783, 499, -1, - 52, 737, -1, 734, -1, 735, -1, 734, -1, 735, - -1, 736, 498, 827, 499, -1, 736, -1, 66, 737, - -1, 65, 737, -1, 447, -1, 264, 66, 737, -1, - 264, 65, 737, -1, 266, 737, -1, 449, -1, -1, - 415, 498, 827, 499, 740, -1, 415, 740, -1, 414, - 498, 827, 499, 740, -1, 414, 740, -1, 215, -1, - 484, 414, 481, -1, 462, 414, 481, -1, -1, 478, - -1, 479, -1, 259, -1, 260, -1, 110, -1, 111, - -1, 186, -1, 187, -1, 255, -1, 256, -1, 365, - -1, 366, -1, 253, -1, 254, -1, 251, -1, 252, - -1, 741, -1, 742, -1, 743, -1, 744, -1, 745, - -1, 746, -1, 747, -1, 748, -1, 741, 416, 742, - -1, 743, 416, 744, -1, 743, 416, 745, -1, 743, - 416, 746, -1, 744, 416, 745, -1, 744, 416, 746, - -1, 745, 416, 746, -1, -1, 752, -1, 750, 11, - 720, -1, 750, 74, 834, -1, 750, 42, 414, 481, - 750, -1, 489, 750, -1, 490, 750, -1, 750, 489, - 750, -1, 750, 490, 750, -1, 750, 491, 750, -1, - 750, 492, 750, -1, 750, 493, 750, -1, 750, 494, - 750, -1, 750, 16, 750, -1, 750, 485, 750, -1, - 750, 486, 750, -1, 750, 487, 750, -1, 750, 17, - 750, -1, 750, 18, 750, -1, 750, 19, 750, -1, - 750, 778, 750, -1, 778, 750, -1, 750, 778, -1, - 750, 34, 750, -1, 750, 291, 750, -1, 271, 750, - -1, 482, 750, -1, 750, 175, 750, -1, 750, 233, - 750, -1, 750, 233, 750, 144, 750, -1, 750, 482, - 233, 750, -1, 750, 482, 233, 750, 144, 750, -1, - 750, 191, 750, -1, 750, 191, 750, 144, 750, -1, - 750, 482, 191, 750, -1, 750, 482, 191, 750, 144, - 750, -1, 750, 380, 416, 750, -1, 750, 380, 416, - 750, 144, 750, -1, 750, 482, 380, 416, 750, -1, - 750, 482, 380, 416, 750, 144, 750, -1, 750, 218, - 276, -1, 750, 219, -1, 750, 218, 271, 276, -1, - 750, 271, 276, -1, 750, 274, -1, 771, -1, 503, - 774, 504, -1, 496, 784, 497, -1, 750, 15, 750, - -1, 771, 297, 771, -1, 750, 218, 423, -1, 750, - 218, 271, 423, -1, 750, 218, 158, -1, 750, 218, - 271, 158, -1, 750, 218, 434, -1, 750, 218, 271, - 434, -1, 750, 218, 131, 170, 750, -1, 750, 218, - 271, 131, 170, 750, -1, 750, 218, 281, 498, 787, - 499, -1, 750, 218, 271, 281, 498, 787, 499, -1, - 750, 49, 808, 751, 34, 750, -1, 750, 482, 49, - 808, 751, 34, 750, -1, 750, 49, 402, 751, 34, - 750, -1, 750, 482, 49, 402, 751, 34, 750, -1, - 750, 196, 797, -1, 750, 482, 196, 797, -1, 750, - 780, 775, 639, -1, 750, 780, 775, 498, 750, 499, - -1, 116, -1, 36, 496, 784, 497, -1, 752, -1, - 751, 11, 720, -1, 489, 751, -1, 490, 751, -1, - 751, 489, 751, -1, 751, 490, 751, -1, 751, 491, - 751, -1, 751, 492, 751, -1, 751, 493, 751, -1, - 751, 494, 751, -1, 751, 16, 751, -1, 751, 485, - 751, -1, 751, 486, 751, -1, 751, 487, 751, -1, - 751, 17, 751, -1, 751, 18, 751, -1, 751, 19, - 751, -1, 751, 778, 751, -1, 778, 751, -1, 751, - 778, -1, 751, 218, 131, 170, 751, -1, 751, 218, - 271, 131, 170, 751, -1, 751, 218, 281, 498, 787, - 499, -1, 751, 218, 271, 281, 498, 787, 499, -1, - 803, -1, 826, -1, 505, 9, -1, 506, 807, -1, - 10, 807, -1, 498, 750, 499, 807, -1, 798, -1, - 754, 807, -1, 639, -1, 639, 806, -1, 151, 639, - -1, 684, 498, 783, 499, -1, 825, 498, 499, -1, - 825, 498, 785, 653, 652, 499, -1, 825, 498, 448, - 786, 653, 652, 499, -1, 825, 498, 785, 502, 448, - 786, 653, 652, 499, -1, 825, 498, 28, 785, 653, - 652, 499, -1, 825, 498, 131, 785, 653, 652, 499, - -1, 825, 498, 491, 499, -1, 753, 757, 758, 759, - 763, -1, 756, -1, 753, -1, 756, -1, 75, 165, - 498, 750, 499, -1, 100, -1, 103, -1, 103, 498, - 827, 499, -1, 104, -1, 104, 498, 827, 499, -1, - 238, -1, 238, 498, 827, 499, -1, 239, -1, 239, - 498, 827, 499, -1, 101, -1, 105, -1, 374, -1, - 439, -1, 99, -1, 102, -1, 62, 498, 750, 37, - 720, 499, -1, 426, 498, 750, 37, 720, 499, -1, - 157, 498, 788, 499, -1, 298, 498, 790, 499, -1, - 312, 498, 792, 499, -1, 400, 498, 793, 499, -1, - 420, 498, 750, 37, 720, 499, -1, 422, 498, 54, - 796, 499, -1, 422, 498, 229, 796, 499, -1, 422, - 498, 417, 796, 499, -1, 422, 498, 796, 499, -1, - 277, 498, 750, 502, 750, 499, -1, 73, 498, 783, - 499, -1, 461, 179, 498, 654, 499, -1, -1, 161, - 498, 457, 750, 499, -1, -1, 154, -1, -1, 459, - 761, -1, -1, 762, -1, 761, 502, 762, -1, 829, - 37, 764, -1, 296, 764, -1, 296, 829, -1, -1, - 498, 765, 766, 653, 767, 499, -1, 829, -1, -1, - 305, 55, 782, -1, -1, 328, 768, -1, 357, 768, - -1, -1, 769, -1, 49, 769, 34, 769, -1, 429, - 314, -1, 429, 164, -1, 98, 356, -1, 750, 314, - -1, 750, 164, -1, 356, 498, 783, 499, -1, 356, - 498, 499, -1, 770, -1, 498, 782, 502, 750, 499, - -1, 830, 507, 750, -1, 772, -1, 773, 502, 772, - -1, 773, -1, 773, 502, -1, 35, -1, 385, -1, - 28, -1, 8, -1, 777, -1, 489, -1, 490, -1, - 491, -1, 492, -1, 493, -1, 494, -1, 16, -1, - 485, -1, 486, -1, 487, -1, 17, -1, 18, -1, - 19, -1, 8, -1, 288, 498, 781, 499, -1, 776, - -1, 288, 498, 781, 499, -1, 776, -1, 288, 498, - 781, 499, -1, 233, -1, 482, 233, -1, 175, -1, - 482, 175, -1, 191, -1, 482, 191, -1, 776, -1, - 829, 500, 781, -1, 750, -1, 782, 502, 750, -1, - 782, -1, 782, 502, -1, 783, -1, -1, 786, -1, - 785, 502, 786, -1, 750, -1, 837, 13, 750, -1, - 837, 14, 750, -1, 720, -1, 787, 502, 720, -1, - 789, 170, 750, -1, -1, 3, -1, 741, -1, 742, - -1, 743, -1, 744, -1, 745, -1, 746, -1, 747, - -1, 748, -1, 828, -1, 750, 791, 794, 795, -1, - 750, 791, 794, -1, 309, 750, -1, 751, 196, 751, - -1, -1, 750, 794, 795, -1, 750, 795, 794, -1, - 750, 794, -1, 750, 795, -1, 782, -1, -1, 170, - 750, -1, 165, 750, -1, 750, 170, 783, -1, 170, - 783, -1, 783, -1, 639, -1, 498, 783, 499, -1, - 61, 802, 799, 801, 142, -1, 800, -1, 799, 800, - -1, 456, 750, 413, 750, -1, 138, 750, -1, -1, - 750, -1, -1, 829, -1, 829, 806, -1, 500, 824, - -1, 496, 750, 497, -1, 496, 805, 507, 805, 497, - -1, 750, -1, -1, 804, -1, 806, 804, -1, -1, - 807, 804, -1, 41, -1, -1, 811, -1, -1, 812, - -1, 810, 502, 812, -1, 810, -1, 810, 502, -1, - 750, 37, 839, -1, 750, 3, -1, 750, -1, 491, - 814, 818, -1, 829, 500, 491, 814, 818, -1, 147, - 498, 822, 499, -1, 147, 829, -1, 813, -1, -1, - 750, 37, 829, -1, 815, -1, 816, 502, 815, -1, - 816, -1, 816, 502, -1, 343, 498, 817, 499, -1, - 343, 815, -1, -1, 820, -1, 819, 502, 820, -1, - 830, -1, 829, 806, -1, 823, -1, 821, 502, 823, - -1, 821, -1, 821, 502, -1, 829, -1, 838, -1, - 832, -1, 829, 806, -1, 827, -1, 4, -1, 828, - 807, -1, 6, -1, 7, -1, 825, 828, -1, 825, - 498, 785, 653, 652, 499, 828, -1, 723, 828, -1, - 739, 498, 750, 499, 749, -1, 739, 827, 749, -1, - 739, 828, 749, -1, 423, -1, 158, -1, 276, -1, - 9, -1, 5, -1, 3, -1, 898, -1, 899, -1, - 829, -1, 5, -1, 3, -1, 898, -1, 903, -1, - 3, -1, 898, -1, 900, -1, 3, -1, 898, -1, - 901, -1, 829, -1, 829, 835, -1, 500, 824, -1, - 835, 500, 824, -1, 498, 821, 499, -1, -1, 831, - -1, 3, -1, 902, -1, 898, -1, 904, -1, 838, - -1, 5, -1, 316, 823, 841, 37, 842, -1, 498, - 787, 499, -1, -1, 638, -1, 526, -1, 620, -1, - 881, -1, 94, 361, 829, 844, -1, 94, 361, 189, - 271, 151, 829, 844, -1, 844, 845, -1, -1, 562, - -1, 846, -1, 549, -1, 893, -1, 94, 852, 199, - 849, 850, 286, 820, 848, 498, 543, 499, 851, 713, - -1, 94, 852, 199, 849, 189, 271, 151, 591, 286, - 820, 848, 498, 543, 499, 851, 713, -1, 829, -1, - 440, 847, -1, -1, 83, -1, -1, 591, -1, -1, - 460, 577, -1, -1, 433, -1, -1, 30, 405, 707, - 375, 361, 823, -1, 30, 405, 189, 151, 707, 375, - 361, 823, -1, 30, 369, 820, 375, 361, 823, -1, - 30, 369, 189, 151, 820, 375, 361, 823, -1, 30, - 452, 820, 375, 361, 823, -1, 30, 452, 189, 151, - 820, 375, 361, 823, -1, 166, 69, -1, 69, -1, - 153, 109, 828, 628, -1, 195, 109, 828, -1, 152, - 860, -1, 152, 864, 858, 860, -1, 152, 450, 860, - -1, 152, 498, 863, 499, 860, -1, 450, -1, -1, - 865, -1, 556, -1, -1, 638, -1, 526, -1, 620, - -1, 881, -1, 895, -1, 3, -1, 898, -1, 902, - -1, 861, -1, 828, -1, 866, -1, 863, 502, 866, - -1, 33, -1, 32, -1, 423, -1, 158, -1, 286, - -1, 862, -1, 867, 859, -1, 861, -1, 864, -1, - 375, 869, -1, 375, 237, 869, -1, 375, 373, 869, - -1, 375, 176, 869, -1, 870, -1, 891, 170, 98, - -1, 414, 481, 872, -1, 361, 828, -1, 891, 416, - 873, -1, 891, 487, 873, -1, 891, 416, 116, -1, - 891, 487, 116, -1, 865, -1, 556, -1, 828, -1, - 3, -1, 739, 828, 749, -1, 739, 498, 827, 499, - 828, -1, 556, -1, 116, -1, 237, -1, 871, -1, - 873, 502, 871, -1, 236, 875, -1, 210, 875, -1, - 166, 210, 875, -1, 828, -1, 829, -1, 441, 878, - 880, 858, -1, 441, 878, 880, 858, 820, -1, 441, - 878, 880, 858, 885, -1, 441, 498, 879, 499, -1, - 441, 498, 879, 499, 820, 836, -1, 864, -1, 450, - -1, 169, -1, 171, -1, 3, -1, 171, -1, -1, - 877, -1, 879, 502, 877, -1, 169, -1, -1, 530, - 121, 170, 882, 884, 883, 535, -1, 707, -1, 707, - 829, -1, 707, 37, 829, -1, 457, 750, -1, -1, - 440, 698, -1, -1, 864, 858, -1, 864, 858, 820, - 836, -1, 345, 888, -1, 891, -1, 28, -1, 887, - -1, 414, 481, -1, 418, 220, 232, -1, 890, 638, - -1, 401, 638, -1, 401, 891, -1, 890, 891, -1, - 890, 414, 481, -1, 890, 418, 220, 232, -1, 890, - 28, -1, 890, -1, 379, -1, 126, -1, 829, -1, - 891, 500, 829, -1, 57, 753, -1, 94, 608, 452, - 820, 597, 851, 37, 638, 894, -1, 94, 291, 343, - 608, 452, 820, 597, 851, 37, 638, 894, -1, 94, - 608, 333, 452, 820, 498, 601, 499, 851, 37, 638, - 894, -1, 94, 291, 343, 608, 333, 452, 820, 498, - 601, 499, 851, 37, 638, 894, -1, 460, 68, 289, - -1, 460, 60, 68, 289, -1, 460, 237, 68, 289, - -1, -1, 94, 608, 405, 897, 37, 638, 896, -1, - 94, 608, 405, 189, 271, 151, 897, 37, 638, 896, - -1, 94, 291, 343, 608, 405, 897, 37, 638, 896, - -1, 460, 108, -1, 460, 269, 108, -1, -1, 820, - 597, 584, 576, -1, 20, -1, 21, -1, 22, -1, - 23, -1, 24, -1, 25, -1, 26, -1, 27, -1, - 29, -1, 30, -1, 31, -1, 39, -1, 40, -1, - 42, -1, 43, -1, 44, -1, 46, -1, 47, -1, - 48, -1, 55, -1, 56, -1, 57, -1, 58, -1, - 59, -1, 60, -1, 63, -1, 64, -1, 67, -1, - 69, -1, 70, -1, 71, -1, 72, -1, 77, -1, - 78, -1, 79, -1, 80, -1, 81, -1, 82, -1, - 84, -1, 85, -1, 86, -1, 88, -1, 89, -1, - 90, -1, 91, -1, 92, -1, 93, -1, 96, -1, - 97, -1, 98, -1, 106, -1, 107, -1, 108, -1, - 109, -1, 110, -1, 111, -1, 112, -1, 115, -1, - 117, -1, 119, -1, 120, -1, 121, -1, 122, -1, - 123, -1, 124, -1, 126, -1, 127, -1, 128, -1, - 129, -1, 130, -1, 133, -1, 134, -1, 135, -1, - 136, -1, 137, -1, 139, -1, 140, -1, 141, -1, - 143, -1, 144, -1, 145, -1, 147, -1, 148, -1, - 149, -1, 150, -1, 152, -1, 153, -1, 154, -1, - 155, -1, 156, -1, 159, -1, 161, -1, 162, -1, - 164, -1, 166, -1, 168, -1, 172, -1, 173, -1, - 176, -1, 178, -1, 182, -1, 184, -1, 185, -1, - 186, -1, 187, -1, 188, -1, 189, -1, 190, -1, - 192, -1, 193, -1, 194, -1, 195, -1, 197, -1, - 198, -1, 199, -1, 200, -1, 201, -1, 202, -1, - 204, -1, 207, -1, 208, -1, 209, -1, 210, -1, - 211, -1, 217, -1, 220, -1, 222, -1, 223, -1, - 224, -1, 225, -1, 226, -1, 227, -1, 230, -1, - 232, -1, 235, -1, 236, -1, 237, -1, 240, -1, - 241, -1, 242, -1, 243, -1, 244, -1, 246, -1, - 247, -1, 248, -1, 249, -1, 250, -1, 251, -1, - 252, -1, 253, -1, 254, -1, 255, -1, 256, -1, - 257, -1, 258, -1, 259, -1, 260, -1, 261, -1, - 262, -1, 263, -1, 267, -1, 268, -1, 269, -1, - 272, -1, 273, -1, 275, -1, 278, -1, 280, -1, - 281, -1, 282, -1, 284, -1, 285, -1, 288, -1, - 289, -1, 290, -1, 293, -1, 296, -1, 299, -1, - 300, -1, 301, -1, 302, -1, 303, -1, 304, -1, - 305, -1, 306, -1, 307, -1, 308, -1, 310, -1, - 311, -1, 313, -1, 314, -1, 316, -1, 317, -1, - 318, -1, 320, -1, 321, -1, 322, -1, 323, -1, - 324, -1, 325, -1, 327, -1, 328, -1, 329, -1, - 331, -1, 332, -1, 333, -1, 334, -1, 336, -1, - 337, -1, 338, -1, 339, -1, 340, -1, 341, -1, - 342, -1, 343, -1, 344, -1, 345, -1, 346, -1, - 347, -1, 348, -1, 350, -1, 351, -1, 353, -1, - 354, -1, 355, -1, 357, -1, 358, -1, 359, -1, - 360, -1, 361, -1, 362, -1, 363, -1, 364, -1, - 365, -1, 366, -1, 367, -1, 369, -1, 370, -1, - 371, -1, 372, -1, 373, -1, 375, -1, 377, -1, - 378, -1, 379, -1, 381, -1, 382, -1, 384, -1, - 386, -1, 387, -1, 388, -1, 389, -1, 390, -1, - 391, -1, 392, -1, 393, -1, 394, -1, 395, -1, - 396, -1, 397, -1, 399, -1, 401, -1, 403, -1, - 404, -1, 406, -1, 408, -1, 409, -1, 410, -1, - 411, -1, 412, -1, 418, -1, 419, -1, 421, -1, - 424, -1, 425, -1, 427, -1, 428, -1, 429, -1, - 430, -1, 431, -1, 434, -1, 435, -1, 436, -1, - 437, -1, 438, -1, 441, -1, 442, -1, 443, -1, - 444, -1, 445, -1, 449, -1, 451, -1, 452, -1, - 453, -1, 454, -1, 455, -1, 458, -1, 461, -1, - 462, -1, 463, -1, 464, -1, 465, -1, 466, -1, - 478, -1, 479, -1, 480, -1, 481, -1, 49, -1, - 50, -1, 52, -1, 53, -1, 65, -1, 66, -1, - 73, -1, 113, -1, 114, -1, 151, -1, 157, -1, - 163, -1, 174, -1, 180, -1, 181, -1, 206, -1, - 212, -1, 213, -1, 215, -1, 245, -1, 264, -1, - 266, -1, 270, -1, 277, -1, 279, -1, 294, -1, - 298, -1, 312, -1, 315, -1, 330, -1, 356, -1, - 376, -1, 383, -1, 398, -1, 400, -1, 414, -1, - 415, -1, 420, -1, 422, -1, 426, -1, 446, -1, - 447, -1, 467, -1, 468, -1, 469, -1, 470, -1, - 471, -1, 472, -1, 473, -1, 474, -1, 475, -1, - 476, -1, 477, -1, 45, -1, 51, -1, 75, -1, - 83, -1, 95, -1, 102, -1, 169, -1, 171, -1, - 174, -1, 175, -1, 191, -1, 205, -1, 218, -1, - 219, -1, 221, -1, 231, -1, 233, -1, 245, -1, - 265, -1, 274, -1, 295, -1, 297, -1, 352, -1, - 380, -1, 398, -1, 407, -1, 450, -1, 45, -1, - 51, -1, 75, -1, 83, -1, 95, -1, 102, -1, - 169, -1, 171, -1, 175, -1, 191, -1, 205, -1, - 218, -1, 219, -1, 221, -1, 231, -1, 233, -1, - 265, -1, 274, -1, 295, -1, 297, -1, 352, -1, - 380, -1, 407, -1, 426, -1, 450, -1, 49, -1, - 50, -1, 52, -1, 53, -1, 66, -1, 65, -1, - 73, -1, 113, -1, 114, -1, 151, -1, 157, -1, - 163, -1, 174, -1, 180, -1, 181, -1, 206, -1, - 213, -1, 215, -1, 212, -1, 245, -1, 264, -1, - 266, -1, 270, -1, 277, -1, 279, -1, 294, -1, - 298, -1, 312, -1, 315, -1, 330, -1, 356, -1, - 376, -1, 383, -1, 398, -1, 400, -1, 414, -1, - 415, -1, 420, -1, 422, -1, 426, -1, 446, -1, - 447, -1, 467, -1, 468, -1, 469, -1, 470, -1, - 471, -1, 472, -1, 473, -1, 474, -1, 475, -1, - 476, -1, 477, -1, 45, -1, 51, -1, 75, -1, - 83, -1, 95, -1, 102, -1, 169, -1, 171, -1, - 174, -1, 175, -1, 191, -1, 205, -1, 218, -1, - 219, -1, 221, -1, 231, -1, 233, -1, 245, -1, - 265, -1, 274, -1, 295, -1, 297, -1, 352, -1, - 380, -1, 398, -1, 407, -1, 426, -1, 450, -1, - 28, -1, 32, -1, 33, -1, 34, -1, 35, -1, - 36, -1, 37, -1, 38, -1, 41, -1, 54, -1, - 61, -1, 62, -1, 68, -1, 74, -1, 76, -1, - 87, -1, 94, -1, 99, -1, 100, -1, 101, -1, - 103, -1, 104, -1, 105, -1, 116, -1, 118, -1, - 125, -1, 131, -1, 132, -1, 138, -1, 142, -1, - 146, -1, 158, -1, 160, -1, 165, -1, 167, -1, - 170, -1, 177, -1, 179, -1, 183, -1, 196, -1, - 203, -1, 214, -1, 216, -1, 228, -1, 229, -1, - 234, -1, 238, -1, 239, -1, 271, -1, 276, -1, - 283, -1, 286, -1, 287, -1, 291, -1, 292, -1, - 309, -1, 319, -1, 326, -1, 335, -1, 349, -1, - 368, -1, 374, -1, 385, -1, 402, -1, 405, -1, - 413, -1, 416, -1, 417, -1, 423, -1, 432, -1, - 433, -1, 439, -1, 440, -1, 448, -1, 456, -1, - 457, -1, 459, -1, 460, -1 + 31, 406, 707, 521, -1, 31, 406, 190, 152, 707, + 521, -1, 31, 200, 820, 521, -1, 31, 200, 190, + 152, 820, 521, -1, 31, 370, 820, 521, -1, 31, + 370, 190, 152, 820, 521, -1, 31, 453, 820, 521, + -1, 31, 453, 190, 152, 820, 521, -1, 516, -1, + 514, 516, -1, 376, 117, 750, -1, 137, 117, -1, + 348, -1, 348, 554, 555, -1, 376, 556, -1, 376, + 175, 608, -1, 520, -1, 517, 503, 520, -1, 25, + 588, -1, 25, 190, 272, 152, 588, -1, 25, 77, + 588, -1, 25, 77, 190, 272, 152, 588, -1, 31, + 526, 829, 515, -1, 31, 526, 829, 137, 272, 277, + -1, 31, 526, 829, 376, 272, 277, -1, 31, 526, + 829, 376, 392, 558, -1, 31, 526, 829, 376, 576, + -1, 31, 526, 829, 346, 576, -1, 31, 526, 829, + 376, 395, 829, -1, 31, 526, 829, 25, 175, 608, + 38, 189, 564, -1, 31, 526, 829, 514, -1, 31, + 526, 829, 137, 189, -1, 31, 526, 829, 137, 189, + 190, 152, -1, 137, 526, 190, 152, 829, 613, -1, + 137, 526, 829, 613, -1, 31, 526, 829, 523, 428, + 720, 716, 519, -1, 31, 526, 829, 522, -1, 25, + 578, -1, 31, 88, 823, 562, -1, 444, 88, 823, + -1, 137, 88, 190, 152, 823, 613, -1, 137, 88, + 823, 613, -1, 376, 244, -1, 376, 437, -1, 376, + 576, -1, 346, 576, -1, 522, -1, 441, 750, -1, + -1, 572, -1, 376, 572, -1, 25, 572, -1, 137, + 586, -1, 518, -1, 521, 503, 518, -1, 291, 499, + 517, 500, -1, 376, 109, -1, 376, -1, -1, 113, + 823, -1, 113, 317, 823, -1, 113, 29, -1, 113, + 317, 29, -1, 31, 362, 823, 342, 417, 823, -1, + 31, 406, 707, 342, 417, 823, -1, 31, 406, 190, + 152, 707, 342, 417, 823, -1, 31, 370, 820, 342, + 417, 823, -1, 31, 370, 190, 152, 820, 342, 417, + 823, -1, 31, 453, 820, 342, 417, 823, -1, 31, + 453, 190, 152, 820, 342, 417, 823, -1, 31, 200, + 820, 342, 417, 823, -1, 31, 200, 190, 152, 820, + 342, 417, 823, -1, 31, 406, 707, 342, 526, 823, + 417, 823, -1, 31, 406, 190, 152, 707, 342, 526, + 823, 417, 823, -1, 31, 406, 707, 342, 88, 823, + 417, 823, -1, 31, 406, 190, 152, 707, 342, 88, + 823, 417, 823, -1, 77, -1, -1, 531, 210, 217, + 529, 528, 534, 536, -1, 637, -1, 300, 537, 446, + 637, -1, 499, 541, 500, 637, -1, 499, 541, 500, + 300, 537, 446, 637, -1, 117, 447, -1, 820, -1, + 820, 38, 829, -1, 499, 544, 500, 713, -1, 287, + 88, 823, -1, -1, 642, -1, -1, 829, 807, -1, + 545, 488, 750, -1, 499, 538, 500, 488, 750, -1, + 287, 86, 530, 133, 439, 376, 543, 713, -1, 287, + 86, 530, 133, 273, -1, -1, 829, 539, 540, 657, + 658, -1, 755, 539, 540, 657, 658, -1, 499, 750, + 500, 539, 540, 657, 658, -1, 350, 810, -1, -1, + 440, -1, 405, -1, 545, -1, 538, 503, 545, -1, + 75, 834, -1, -1, 834, -1, -1, 532, -1, 541, + 503, 532, -1, 533, -1, 542, 503, 533, -1, 542, + -1, 542, 503, -1, 535, -1, 544, 503, 535, -1, + 829, 807, -1, 95, 428, 834, 38, 720, -1, 314, + 829, -1, 314, 829, 488, 873, -1, 314, 829, 499, + 785, 500, -1, 95, 607, 370, 820, 549, -1, 95, + 607, 370, 190, 272, 152, 820, 549, -1, 553, -1, + -1, 151, 823, 551, -1, 95, 607, 406, 897, 38, + 151, 823, 551, 896, -1, 95, 607, 406, 190, 272, + 152, 897, 38, 151, 823, 551, 896, -1, 499, 783, + 500, -1, -1, 31, 370, 820, 553, -1, 31, 370, + 190, 152, 820, 553, -1, 556, -1, 553, 556, -1, + 461, -1, 485, -1, -1, 4, -1, 490, 4, -1, + 491, 4, -1, 558, -1, 38, 722, -1, 57, 555, + -1, 108, -1, 270, 108, -1, 199, 557, 555, -1, + 250, 555, -1, 258, 555, -1, 270, 250, -1, 270, + 258, -1, 301, 56, 834, -1, 370, 263, 834, -1, + 390, 554, 555, -1, 348, -1, 348, 554, 555, -1, + 56, -1, -1, 827, -1, 490, 827, -1, 491, 827, + -1, 21, 560, -1, 49, 560, -1, 390, 560, -1, + 81, 560, -1, 143, 560, -1, 355, 560, -1, 464, + -1, 419, -1, -1, 95, 607, 406, 820, 499, 594, + 500, 583, 575, -1, 95, 607, 406, 190, 272, 152, + 820, 499, 594, 500, 583, 575, -1, 95, 292, 344, + 607, 406, 820, 499, 594, 500, 583, 575, -1, -1, + 562, 587, -1, 602, -1, 904, -1, 779, -1, 555, + -1, 828, -1, 271, -1, 499, 553, 500, -1, -1, + 828, -1, 270, 24, -1, 349, -1, 60, -1, 376, + 277, -1, 376, 117, -1, 88, 823, 568, -1, 568, + -1, 582, -1, 75, 834, -1, 272, 277, -1, 277, + -1, 434, 593, -1, 320, 224, 593, -1, 69, 499, + 750, 500, 577, -1, 441, 83, 823, -1, 117, 751, + -1, 336, 820, 596, 605, 574, -1, 455, -1, 396, + -1, 569, -1, -1, 175, 608, 38, 189, 564, -1, + 175, 608, 38, 499, 750, 500, 570, -1, 38, 499, + 750, 500, 570, -1, 586, 565, -1, 287, 439, 566, + -1, 573, -1, 598, -1, 573, 598, -1, 598, 573, + -1, -1, 287, 81, 137, -1, 287, 81, 122, 358, + -1, 287, 81, 319, 358, -1, -1, 499, 580, 500, + -1, 270, 202, -1, -1, 88, 823, 603, -1, 603, + -1, 80, -1, 89, -1, 118, -1, 189, -1, 201, + -1, 392, -1, 395, -1, 29, -1, 599, -1, 580, + 503, 599, -1, 441, 200, 590, -1, 119, -1, 272, + 119, -1, 204, 120, -1, 204, 193, -1, 461, 576, + -1, 461, 285, -1, 463, 285, -1, -1, 499, 589, + 500, -1, 585, 198, 579, -1, 585, 149, 579, -1, + -1, 838, -1, 272, 119, -1, 119, -1, 204, 193, + -1, 204, 120, -1, 272, 443, -1, 270, 202, -1, + 829, 720, 597, -1, 829, 719, 571, 597, -1, 592, + -1, 589, 503, 592, -1, 829, -1, 588, -1, 606, + -1, 578, -1, 838, 488, 563, -1, 838, -1, 461, + 584, -1, -1, 604, -1, 604, 503, -1, -1, 829, + -1, 499, 600, 500, -1, -1, 597, 567, -1, -1, + 287, 122, 566, -1, 838, 488, 563, -1, 838, -1, + 838, 501, 838, 488, 563, -1, 838, 501, 838, -1, + 595, -1, 600, 503, 595, -1, 600, -1, 600, 503, + -1, 720, -1, 831, 835, 494, 428, -1, 377, 831, + 835, 494, 428, -1, 69, 499, 750, 500, 562, -1, + 434, 499, 601, 500, 593, 562, -1, 434, 581, 562, + -1, 320, 224, 499, 601, 500, 593, 562, -1, 320, + 224, 581, 562, -1, 168, 224, 499, 601, 500, 336, + 820, 596, 605, 574, 562, -1, 591, -1, 604, 503, + 591, -1, 248, 172, -1, 248, 305, -1, 248, 382, + -1, -1, 234, 820, 585, -1, 412, -1, 410, -1, + 238, 412, -1, 238, 410, -1, 177, 412, -1, 177, + 410, -1, 437, -1, -1, 32, -1, 56, 117, -1, + 137, 610, 190, 152, 612, 613, -1, 137, 610, 612, + 613, -1, 137, 611, 190, 152, 821, 613, -1, 137, + 611, 821, 613, -1, 137, 614, 823, 287, 834, 613, + -1, 137, 614, 190, 152, 823, 287, 834, 613, -1, + 137, 428, 615, 613, -1, 137, 428, 190, 152, 615, + 613, -1, 406, -1, 370, -1, 173, -1, 245, -1, + 245, 406, -1, 453, -1, 249, 453, -1, 200, -1, + 168, 406, -1, 76, -1, 92, -1, 392, -1, 413, + 365, 304, -1, 413, 365, 129, -1, 413, 365, 411, + -1, 413, 365, 85, -1, 23, 251, -1, 146, 422, + -1, 156, -1, 168, 109, 465, -1, 326, -1, 362, + -1, 373, -1, 834, -1, 612, 503, 834, -1, 60, + -1, 349, -1, -1, 312, -1, 359, -1, 422, -1, + 720, -1, 615, 503, 720, -1, 95, 607, 617, 820, + 618, 38, 406, 637, -1, 95, 607, 617, 820, 618, + 38, 750, -1, 173, -1, 245, -1, 499, 500, -1, + 499, 785, 500, -1, 531, 439, 882, 376, 543, 696, + 883, 536, -1, 93, 632, 820, 596, 630, 621, 626, + 635, 622, 554, 627, -1, 93, 499, 637, 500, 417, + 626, 635, 554, 627, -1, 171, -1, 417, -1, 624, + 124, 828, -1, -1, 634, -1, 623, 503, 634, -1, + 441, -1, -1, 38, -1, -1, 325, -1, -1, 631, + -1, 499, 636, 500, -1, 865, -1, 555, -1, 492, + -1, 499, 623, 500, -1, -1, 838, 628, -1, 461, + 285, -1, -1, 631, 633, -1, -1, 52, -1, -1, + 52, -1, 285, -1, 170, -1, 123, 625, 828, -1, + 277, 625, 828, -1, 97, -1, 185, -1, 328, 625, + 828, -1, 145, 625, 828, -1, 167, 328, 600, -1, + 167, 328, 492, -1, 167, 272, 277, 600, -1, 167, + 277, 600, -1, 141, 828, -1, 865, -1, 828, -1, + 393, -1, 394, -1, 629, -1, 636, 503, 629, -1, + 639, -1, 638, -1, 499, 639, 500, -1, 499, 638, + 500, -1, 641, -1, 640, 654, -1, 640, 653, 687, + 660, -1, 640, 653, 659, 688, -1, 642, 640, -1, + 642, 640, 654, -1, 642, 640, 653, 687, 660, -1, + 642, 640, 653, 659, 688, -1, 641, -1, 638, -1, + 369, 651, 809, 645, 696, 713, 676, 685, 760, 686, + 664, -1, 369, 650, 811, 645, 696, 713, 676, 685, + 760, 686, 664, -1, 695, -1, 406, 707, -1, 640, + 433, 648, 649, 640, -1, 640, 433, 648, 640, -1, + 640, 215, 648, 640, -1, 640, 147, 648, 640, -1, + 461, 643, -1, 485, 643, -1, 461, 334, 643, -1, + 644, -1, 643, 503, 644, -1, 823, 836, 38, 499, + 842, 500, -1, 217, 646, -1, -1, 412, 647, 820, + -1, 410, 647, 820, -1, 238, 412, 647, 820, -1, + 238, 410, 647, 820, -1, 177, 412, 647, 820, -1, + 177, 410, 647, 820, -1, 437, 647, 820, -1, 406, + 820, -1, 820, -1, 406, -1, -1, 29, -1, 132, + -1, -1, 56, 263, -1, 132, -1, 132, 287, 499, + 783, 500, -1, 29, -1, -1, 191, 279, -1, 347, + 279, -1, -1, 654, -1, -1, 293, 56, 655, -1, + 293, 56, 29, 657, 658, -1, 293, 56, 492, 657, + 658, -1, 656, -1, 655, 503, 656, -1, 750, 441, + 779, 658, -1, 750, 657, 658, -1, 39, -1, 126, + -1, -1, 484, 163, -1, 484, 228, -1, -1, 661, + 662, -1, 662, 661, -1, 661, -1, 662, -1, 659, + -1, -1, 235, 670, -1, 235, 670, 503, 671, -1, + 161, 675, 672, 674, 288, -1, 161, 675, 674, 288, + -1, 284, 671, -1, 284, 672, 674, -1, 4, 494, + -1, 9, 494, -1, 4, 309, -1, 9, 309, -1, + 9, -1, 9, 358, -1, 441, 360, 666, -1, -1, + 829, -1, -1, 665, 499, 663, 500, 669, -1, 663, + -1, 663, 499, 829, 500, -1, 663, 499, 829, 503, + 9, 500, -1, 408, 666, -1, 667, -1, -1, 343, + 499, 9, 500, -1, -1, 750, -1, 29, -1, 750, + 494, -1, 4, 309, -1, 9, 309, -1, 750, -1, + 752, -1, 490, 673, -1, 491, 673, -1, 827, -1, + 4, -1, 357, -1, 358, -1, 163, -1, 269, -1, + 180, 56, 678, -1, 180, 56, 29, -1, 180, 56, + 492, -1, -1, 679, -1, 677, 503, 679, -1, 677, + -1, 677, 503, -1, 750, -1, 680, -1, 682, -1, + 681, -1, 683, -1, 499, 500, -1, 356, 499, 783, + 500, -1, 98, 499, 783, 500, -1, 181, 378, 499, + 678, 500, -1, 181, -1, 182, -1, 184, 750, -1, + -1, 327, 750, -1, -1, 689, -1, 166, 330, 288, + -1, 687, -1, -1, 690, -1, 689, 690, -1, 691, + 692, 693, -1, 166, 439, -1, 166, 270, 224, 439, + -1, 166, 379, -1, 166, 224, 379, -1, 282, 819, + -1, -1, 276, -1, 383, 243, -1, -1, 447, 499, + 783, 500, -1, 694, 503, 499, 783, 500, -1, 694, + -1, 694, 503, -1, 171, 698, -1, -1, 699, -1, + 697, 503, 699, -1, 697, -1, 697, 503, -1, 707, + 702, 668, -1, 708, 703, 668, -1, 695, 701, 668, + -1, 229, 708, 703, -1, 638, 702, 668, -1, 229, + 638, 702, -1, 700, -1, 499, 700, 500, 701, -1, + 499, 700, 500, -1, 699, 96, 222, 699, -1, 699, + 704, 222, 699, 706, -1, 699, 222, 699, 706, -1, + 699, 266, 704, 222, 699, -1, 699, 266, 222, 699, + -1, 38, 830, 499, 822, 500, -1, 38, 830, -1, + 829, 499, 822, 500, -1, 829, -1, 701, -1, -1, + 701, -1, 38, 499, 714, 500, -1, 38, 830, 499, + 714, 500, -1, 829, 499, 714, 500, -1, -1, 172, + 705, -1, 232, 705, -1, 353, 705, -1, 206, -1, + 296, -1, -1, 441, 499, 822, 500, -1, 287, 750, + -1, 820, -1, 820, 492, -1, 288, 820, -1, 288, + 499, 820, 500, -1, 755, 712, -1, 358, 171, 499, + 710, 500, 712, -1, 755, 711, -1, 709, -1, 710, + 503, 709, -1, 38, 499, 714, 500, -1, -1, 485, + 294, -1, -1, 458, 750, -1, -1, 715, -1, 714, + 503, 715, -1, 830, 720, 716, -1, 75, 834, -1, + -1, 829, 720, -1, 717, 503, 829, 720, -1, 357, + -1, 399, -1, 720, -1, -1, 722, 721, -1, 377, + 722, 721, -1, 722, 37, 497, 827, 498, -1, 377, + 722, 37, 497, 827, 498, -1, 722, 37, -1, 377, + 722, 37, -1, 718, 499, 717, 500, 721, -1, 246, + 499, 787, 500, 721, -1, 721, 497, 498, -1, 721, + 497, 827, 498, -1, -1, 724, -1, 726, -1, 728, + -1, 732, -1, 738, -1, 739, 749, -1, 739, 499, + 827, 500, -1, 726, -1, 729, -1, 733, -1, 738, + -1, 833, 725, -1, 499, 784, 500, -1, -1, 213, + -1, 214, -1, 384, -1, 51, -1, 331, -1, 164, + 727, -1, 136, 316, -1, 115, 725, -1, 114, 725, + -1, 280, 725, -1, 54, -1, 499, 827, 500, -1, + -1, 730, -1, 731, -1, 730, -1, 731, -1, 53, + 737, 499, 783, 500, -1, 53, 737, -1, 734, -1, + 735, -1, 734, -1, 735, -1, 736, 499, 827, 500, + -1, 736, -1, 67, 737, -1, 66, 737, -1, 448, + -1, 265, 67, 737, -1, 265, 66, 737, -1, 267, + 737, -1, 450, -1, -1, 416, 499, 827, 500, 740, + -1, 416, 740, -1, 415, 499, 827, 500, 740, -1, + 415, 740, -1, 216, -1, 485, 415, 482, -1, 463, + 415, 482, -1, -1, 479, -1, 480, -1, 260, -1, + 261, -1, 111, -1, 112, -1, 187, -1, 188, -1, + 256, -1, 257, -1, 366, -1, 367, -1, 254, -1, + 255, -1, 252, -1, 253, -1, 741, -1, 742, -1, + 743, -1, 744, -1, 745, -1, 746, -1, 747, -1, + 748, -1, 741, 417, 742, -1, 743, 417, 744, -1, + 743, 417, 745, -1, 743, 417, 746, -1, 744, 417, + 745, -1, 744, 417, 746, -1, 745, 417, 746, -1, + -1, 752, -1, 750, 11, 720, -1, 750, 75, 834, + -1, 750, 43, 415, 482, 750, -1, 490, 750, -1, + 491, 750, -1, 750, 490, 750, -1, 750, 491, 750, + -1, 750, 492, 750, -1, 750, 493, 750, -1, 750, + 494, 750, -1, 750, 495, 750, -1, 750, 15, 750, + -1, 750, 486, 750, -1, 750, 487, 750, -1, 750, + 488, 750, -1, 750, 18, 750, -1, 750, 19, 750, + -1, 750, 20, 750, -1, 750, 778, 750, -1, 778, + 750, -1, 750, 778, -1, 750, 35, 750, -1, 750, + 292, 750, -1, 272, 750, -1, 483, 750, -1, 750, + 176, 750, -1, 750, 234, 750, -1, 750, 234, 750, + 145, 750, -1, 750, 483, 234, 750, -1, 750, 483, + 234, 750, 145, 750, -1, 750, 192, 750, -1, 750, + 192, 750, 145, 750, -1, 750, 483, 192, 750, -1, + 750, 483, 192, 750, 145, 750, -1, 750, 381, 417, + 750, -1, 750, 381, 417, 750, 145, 750, -1, 750, + 483, 381, 417, 750, -1, 750, 483, 381, 417, 750, + 145, 750, -1, 750, 219, 277, -1, 750, 220, -1, + 750, 219, 272, 277, -1, 750, 272, 277, -1, 750, + 275, -1, 771, -1, 504, 774, 505, -1, 497, 784, + 498, -1, 750, 16, 750, -1, 750, 17, 750, -1, + 771, 298, 771, -1, 750, 219, 424, -1, 750, 219, + 272, 424, -1, 750, 219, 159, -1, 750, 219, 272, + 159, -1, 750, 219, 435, -1, 750, 219, 272, 435, + -1, 750, 219, 132, 171, 750, -1, 750, 219, 272, + 132, 171, 750, -1, 750, 219, 282, 499, 787, 500, + -1, 750, 219, 272, 282, 499, 787, 500, -1, 750, + 50, 808, 751, 35, 750, -1, 750, 483, 50, 808, + 751, 35, 750, -1, 750, 50, 403, 751, 35, 750, + -1, 750, 483, 50, 403, 751, 35, 750, -1, 750, + 197, 797, -1, 750, 483, 197, 797, -1, 750, 780, + 775, 638, -1, 750, 780, 775, 499, 750, 500, -1, + 37, 638, -1, 117, -1, 37, 497, 784, 498, -1, + 752, -1, 751, 11, 720, -1, 490, 751, -1, 491, + 751, -1, 751, 490, 751, -1, 751, 491, 751, -1, + 751, 492, 751, -1, 751, 493, 751, -1, 751, 494, + 751, -1, 751, 495, 751, -1, 751, 15, 751, -1, + 751, 486, 751, -1, 751, 487, 751, -1, 751, 488, + 751, -1, 751, 18, 751, -1, 751, 19, 751, -1, + 751, 20, 751, -1, 751, 778, 751, -1, 778, 751, + -1, 751, 778, -1, 751, 219, 132, 171, 751, -1, + 751, 219, 272, 132, 171, 751, -1, 751, 219, 282, + 499, 787, 500, -1, 751, 219, 272, 282, 499, 787, + 500, -1, 803, -1, 826, -1, 506, 9, -1, 507, + 807, -1, 10, 807, -1, 499, 750, 500, 807, -1, + 798, -1, 754, 807, -1, 638, -1, 638, 806, -1, + 152, 638, -1, 684, 499, 783, 500, -1, 825, 499, + 500, -1, 825, 499, 785, 653, 652, 500, -1, 825, + 499, 449, 786, 653, 652, 500, -1, 825, 499, 785, + 503, 449, 786, 653, 652, 500, -1, 825, 499, 29, + 785, 653, 652, 500, -1, 825, 499, 132, 785, 653, + 652, 500, -1, 825, 499, 492, 500, -1, 753, 757, + 758, 759, 763, -1, 756, -1, 753, -1, 756, -1, + 76, 166, 499, 750, 500, -1, 101, -1, 104, -1, + 104, 499, 827, 500, -1, 105, -1, 105, 499, 827, + 500, -1, 239, -1, 239, 499, 827, 500, -1, 240, + -1, 240, 499, 827, 500, -1, 102, -1, 106, -1, + 375, -1, 440, -1, 100, -1, 103, -1, 63, 499, + 750, 38, 720, 500, -1, 427, 499, 750, 38, 720, + 500, -1, 158, 499, 788, 500, -1, 299, 499, 790, + 500, -1, 313, 499, 792, 500, -1, 401, 499, 793, + 500, -1, 421, 499, 750, 38, 720, 500, -1, 423, + 499, 55, 796, 500, -1, 423, 499, 230, 796, 500, + -1, 423, 499, 418, 796, 500, -1, 423, 499, 796, + 500, -1, 278, 499, 750, 503, 750, 500, -1, 74, + 499, 783, 500, -1, 462, 180, 499, 654, 500, -1, + -1, 162, 499, 458, 750, 500, -1, 162, 499, 750, + 500, -1, -1, 155, -1, -1, 460, 761, -1, -1, + 762, -1, 761, 503, 762, -1, 829, 38, 764, -1, + 297, 764, -1, 297, 829, -1, -1, 499, 765, 766, + 653, 767, 500, -1, 829, -1, -1, 306, 56, 782, + -1, -1, 329, 768, -1, 358, 768, -1, -1, 769, + -1, 50, 769, 35, 769, -1, 430, 315, -1, 430, + 165, -1, 99, 357, -1, 750, 315, -1, 750, 165, + -1, 357, 499, 783, 500, -1, 357, 499, 500, -1, + 770, -1, 499, 782, 503, 750, 500, -1, 830, 508, + 750, -1, 772, -1, 773, 503, 772, -1, 773, -1, + 773, 503, -1, 36, -1, 386, -1, 29, -1, 8, + -1, 777, -1, 490, -1, 491, -1, 492, -1, 493, + -1, 494, -1, 495, -1, 15, -1, 486, -1, 487, + -1, 488, -1, 18, -1, 19, -1, 20, -1, 8, + -1, 289, 499, 781, 500, -1, 776, -1, 289, 499, + 781, 500, -1, 776, -1, 289, 499, 781, 500, -1, + 234, -1, 483, 234, -1, 176, -1, 483, 176, -1, + 192, -1, 483, 192, -1, 776, -1, 829, 501, 781, + -1, 750, -1, 782, 503, 750, -1, 782, -1, 782, + 503, -1, 783, -1, -1, 786, -1, 785, 503, 786, + -1, 750, -1, 837, 13, 750, -1, 837, 14, 750, + -1, 720, -1, 787, 503, 720, -1, 789, 171, 750, + -1, -1, 3, -1, 741, -1, 742, -1, 743, -1, + 744, -1, 745, -1, 746, -1, 747, -1, 748, -1, + 828, -1, 750, 791, 794, 795, -1, 750, 791, 794, + -1, 310, 750, -1, 751, 197, 751, -1, -1, 750, + 794, 795, -1, 750, 795, 794, -1, 750, 794, -1, + 750, 795, -1, 782, -1, -1, 171, 750, -1, 166, + 750, -1, 750, 171, 783, -1, 171, 783, -1, 783, + -1, 638, -1, 499, 783, 500, -1, 62, 802, 799, + 801, 143, -1, 800, -1, 799, 800, -1, 457, 750, + 414, 750, -1, 139, 750, -1, -1, 750, -1, -1, + 829, -1, 829, 806, -1, 501, 824, -1, 497, 750, + 498, -1, 497, 805, 508, 805, 498, -1, 750, -1, + -1, 804, -1, 806, 804, -1, -1, 807, 804, -1, + 42, -1, -1, 811, -1, -1, 812, -1, 810, 503, + 812, -1, 810, -1, 810, 503, -1, 750, 38, 839, + -1, 750, 3, -1, 750, -1, 492, 814, 818, -1, + 829, 501, 492, 814, 818, -1, 148, 499, 822, 500, + -1, 148, 829, -1, 813, -1, -1, 750, 38, 829, + -1, 815, -1, 816, 503, 815, -1, 816, -1, 816, + 503, -1, 344, 499, 817, 500, -1, 344, 815, -1, + -1, 820, -1, 819, 503, 820, -1, 830, -1, 829, + 806, -1, 823, -1, 821, 503, 823, -1, 821, -1, + 821, 503, -1, 830, -1, 838, -1, 832, -1, 829, + 806, -1, 827, -1, 4, -1, 828, 807, -1, 6, + -1, 7, -1, 825, 828, -1, 825, 499, 785, 653, + 652, 500, 828, -1, 723, 828, -1, 739, 499, 750, + 500, 749, -1, 739, 827, 749, -1, 739, 828, 749, + -1, 424, -1, 159, -1, 277, -1, 9, -1, 5, + -1, 3, -1, 898, -1, 899, -1, 829, -1, 5, + -1, 3, -1, 898, -1, 903, -1, 3, -1, 898, + -1, 900, -1, 3, -1, 898, -1, 901, -1, 829, + -1, 829, 835, -1, 501, 824, -1, 835, 501, 824, + -1, 499, 822, 500, -1, -1, 831, -1, 3, -1, + 902, -1, 898, -1, 904, -1, 838, -1, 5, -1, + 317, 823, 841, 38, 842, -1, 499, 787, 500, -1, + -1, 637, -1, 527, -1, 619, -1, 881, -1, 95, + 362, 829, 844, -1, 95, 362, 190, 272, 152, 829, + 844, -1, 844, 845, -1, -1, 561, -1, 846, -1, + 548, -1, 893, -1, 95, 852, 200, 849, 850, 287, + 820, 848, 499, 544, 500, 851, 713, -1, 95, 852, + 200, 849, 190, 272, 152, 590, 287, 820, 848, 499, + 544, 500, 851, 713, -1, 829, -1, 441, 847, -1, + -1, 84, -1, -1, 590, -1, -1, 461, 576, -1, + -1, 434, -1, -1, 31, 406, 707, 376, 362, 823, + -1, 31, 406, 190, 152, 707, 376, 362, 823, -1, + 31, 370, 820, 376, 362, 823, -1, 31, 370, 190, + 152, 820, 376, 362, 823, -1, 31, 453, 820, 376, + 362, 823, -1, 31, 453, 190, 152, 820, 376, 362, + 823, -1, 167, 70, -1, 70, -1, 154, 110, 828, + 627, -1, 196, 110, 828, -1, 153, 860, -1, 153, + 864, 858, 860, -1, 153, 451, 860, -1, 153, 499, + 863, 500, 860, -1, 451, -1, -1, 865, -1, 555, + -1, -1, 853, -1, 552, -1, 513, -1, 892, -1, + 854, -1, 620, -1, 895, -1, 616, -1, 843, -1, + 548, -1, 561, -1, 546, -1, 524, -1, 881, -1, + 609, -1, 550, -1, 846, -1, 527, -1, 874, -1, + 547, -1, 840, -1, 525, -1, 637, -1, 559, -1, + 619, -1, 876, -1, 886, -1, 868, -1, 889, -1, + 893, -1, 3, -1, 898, -1, 902, -1, 861, -1, + 828, -1, 866, -1, 863, 503, 866, -1, 34, -1, + 33, -1, 424, -1, 159, -1, 287, -1, 862, -1, + 867, 859, -1, 861, -1, 864, -1, 376, 869, -1, + 376, 238, 869, -1, 376, 374, 869, -1, 376, 177, + 869, -1, 870, -1, 891, 171, 99, -1, 415, 482, + 872, -1, 362, 828, -1, 891, 417, 873, -1, 891, + 488, 873, -1, 891, 417, 117, -1, 891, 488, 117, + -1, 865, -1, 555, -1, 828, -1, 3, -1, 739, + 828, 749, -1, 739, 499, 827, 500, 828, -1, 555, + -1, 117, -1, 238, -1, 871, -1, 873, 503, 871, + -1, 237, 875, -1, 211, 875, -1, 167, 211, 875, + -1, 828, -1, 829, -1, 442, 878, 880, 858, -1, + 442, 878, 880, 858, 820, -1, 442, 878, 880, 858, + 885, -1, 442, 499, 879, 500, -1, 442, 499, 879, + 500, 820, 836, -1, 864, -1, 451, -1, 170, -1, + 172, -1, 3, -1, 172, -1, -1, 877, -1, 879, + 503, 877, -1, 170, -1, -1, 531, 122, 171, 882, + 884, 883, 536, -1, 707, -1, 707, 829, -1, 707, + 38, 829, -1, 458, 750, -1, -1, 441, 698, -1, + -1, 864, 858, -1, 864, 858, 820, 836, -1, 346, + 888, -1, 891, -1, 29, -1, 887, -1, 415, 482, + -1, 419, 221, 233, -1, 890, 637, -1, 402, 637, + -1, 402, 891, -1, 890, 891, -1, 890, 415, 482, + -1, 890, 419, 221, 233, -1, 890, 29, -1, 890, + -1, 380, -1, 127, -1, 829, -1, 891, 501, 829, + -1, 58, 753, -1, 95, 607, 453, 820, 596, 851, + 38, 637, 894, -1, 95, 292, 344, 607, 453, 820, + 596, 851, 38, 637, 894, -1, 95, 607, 334, 453, + 820, 499, 600, 500, 851, 38, 637, 894, -1, 95, + 292, 344, 607, 334, 453, 820, 499, 600, 500, 851, + 38, 637, 894, -1, 461, 69, 290, -1, 461, 61, + 69, 290, -1, 461, 238, 69, 290, -1, -1, 95, + 607, 406, 897, 38, 637, 896, -1, 95, 607, 406, + 190, 272, 152, 897, 38, 637, 896, -1, 95, 292, + 344, 607, 406, 897, 38, 637, 896, -1, 461, 109, + -1, 461, 270, 109, -1, -1, 820, 596, 583, 575, + -1, 21, -1, 22, -1, 23, -1, 24, -1, 25, + -1, 26, -1, 27, -1, 28, -1, 30, -1, 31, + -1, 32, -1, 40, -1, 41, -1, 43, -1, 44, + -1, 45, -1, 47, -1, 48, -1, 49, -1, 56, + -1, 57, -1, 58, -1, 59, -1, 60, -1, 61, + -1, 64, -1, 65, -1, 68, -1, 70, -1, 71, + -1, 72, -1, 73, -1, 78, -1, 79, -1, 80, + -1, 81, -1, 82, -1, 83, -1, 85, -1, 86, + -1, 87, -1, 89, -1, 90, -1, 91, -1, 92, + -1, 93, -1, 94, -1, 97, -1, 98, -1, 99, + -1, 107, -1, 108, -1, 109, -1, 110, -1, 111, + -1, 112, -1, 113, -1, 116, -1, 118, -1, 120, + -1, 121, -1, 122, -1, 123, -1, 124, -1, 125, + -1, 127, -1, 128, -1, 129, -1, 130, -1, 131, + -1, 134, -1, 135, -1, 136, -1, 137, -1, 138, + -1, 140, -1, 141, -1, 142, -1, 144, -1, 145, + -1, 146, -1, 148, -1, 149, -1, 150, -1, 151, + -1, 153, -1, 154, -1, 155, -1, 156, -1, 157, + -1, 160, -1, 162, -1, 163, -1, 165, -1, 167, + -1, 169, -1, 173, -1, 174, -1, 177, -1, 179, + -1, 183, -1, 185, -1, 186, -1, 187, -1, 188, + -1, 189, -1, 190, -1, 191, -1, 193, -1, 194, + -1, 195, -1, 196, -1, 198, -1, 199, -1, 200, + -1, 201, -1, 202, -1, 203, -1, 205, -1, 208, + -1, 209, -1, 210, -1, 211, -1, 212, -1, 218, + -1, 221, -1, 223, -1, 224, -1, 225, -1, 226, + -1, 227, -1, 228, -1, 231, -1, 233, -1, 236, + -1, 237, -1, 238, -1, 241, -1, 242, -1, 243, + -1, 244, -1, 245, -1, 247, -1, 248, -1, 249, + -1, 250, -1, 251, -1, 252, -1, 253, -1, 254, + -1, 255, -1, 256, -1, 257, -1, 258, -1, 259, + -1, 260, -1, 261, -1, 262, -1, 263, -1, 264, + -1, 268, -1, 269, -1, 270, -1, 273, -1, 274, + -1, 276, -1, 279, -1, 281, -1, 282, -1, 283, + -1, 285, -1, 286, -1, 289, -1, 290, -1, 291, + -1, 294, -1, 297, -1, 300, -1, 301, -1, 302, + -1, 303, -1, 304, -1, 305, -1, 306, -1, 307, + -1, 308, -1, 309, -1, 311, -1, 312, -1, 314, + -1, 315, -1, 317, -1, 318, -1, 319, -1, 321, + -1, 322, -1, 323, -1, 324, -1, 325, -1, 326, + -1, 328, -1, 329, -1, 330, -1, 332, -1, 333, + -1, 334, -1, 335, -1, 337, -1, 338, -1, 339, + -1, 340, -1, 341, -1, 342, -1, 343, -1, 344, + -1, 345, -1, 346, -1, 347, -1, 348, -1, 349, + -1, 351, -1, 352, -1, 354, -1, 355, -1, 356, + -1, 358, -1, 359, -1, 360, -1, 361, -1, 362, + -1, 363, -1, 364, -1, 365, -1, 366, -1, 367, + -1, 368, -1, 370, -1, 371, -1, 372, -1, 373, + -1, 374, -1, 376, -1, 378, -1, 379, -1, 380, + -1, 382, -1, 383, -1, 385, -1, 387, -1, 388, + -1, 389, -1, 390, -1, 391, -1, 392, -1, 393, + -1, 394, -1, 395, -1, 396, -1, 397, -1, 398, + -1, 400, -1, 402, -1, 404, -1, 405, -1, 407, + -1, 409, -1, 410, -1, 411, -1, 412, -1, 413, + -1, 419, -1, 420, -1, 422, -1, 425, -1, 426, + -1, 428, -1, 429, -1, 430, -1, 431, -1, 432, + -1, 435, -1, 436, -1, 437, -1, 438, -1, 439, + -1, 442, -1, 443, -1, 444, -1, 445, -1, 446, + -1, 450, -1, 452, -1, 453, -1, 454, -1, 455, + -1, 456, -1, 459, -1, 462, -1, 463, -1, 464, + -1, 465, -1, 466, -1, 467, -1, 479, -1, 480, + -1, 481, -1, 482, -1, 50, -1, 51, -1, 53, + -1, 54, -1, 66, -1, 67, -1, 74, -1, 114, + -1, 115, -1, 152, -1, 158, -1, 164, -1, 175, + -1, 181, -1, 182, -1, 207, -1, 213, -1, 214, + -1, 216, -1, 246, -1, 265, -1, 267, -1, 271, + -1, 278, -1, 280, -1, 295, -1, 299, -1, 313, + -1, 316, -1, 331, -1, 357, -1, 377, -1, 384, + -1, 399, -1, 401, -1, 415, -1, 416, -1, 421, + -1, 423, -1, 427, -1, 447, -1, 448, -1, 468, + -1, 469, -1, 470, -1, 471, -1, 472, -1, 473, + -1, 474, -1, 475, -1, 476, -1, 477, -1, 478, + -1, 46, -1, 52, -1, 76, -1, 84, -1, 96, + -1, 100, -1, 101, -1, 102, -1, 103, -1, 106, + -1, 170, -1, 172, -1, 175, -1, 176, -1, 192, + -1, 206, -1, 219, -1, 220, -1, 222, -1, 232, + -1, 234, -1, 246, -1, 266, -1, 275, -1, 296, + -1, 298, -1, 353, -1, 375, -1, 381, -1, 399, + -1, 408, -1, 440, -1, 451, -1, 46, -1, 52, + -1, 76, -1, 84, -1, 96, -1, 100, -1, 101, + -1, 102, -1, 103, -1, 106, -1, 170, -1, 172, + -1, 176, -1, 192, -1, 206, -1, 219, -1, 220, + -1, 222, -1, 232, -1, 234, -1, 266, -1, 275, + -1, 296, -1, 298, -1, 353, -1, 375, -1, 381, + -1, 408, -1, 427, -1, 440, -1, 451, -1, 46, + -1, 50, -1, 51, -1, 52, -1, 53, -1, 54, + -1, 67, -1, 66, -1, 74, -1, 76, -1, 84, + -1, 96, -1, 100, -1, 101, -1, 102, -1, 103, + -1, 106, -1, 114, -1, 115, -1, 152, -1, 158, + -1, 164, -1, 170, -1, 172, -1, 175, -1, 176, + -1, 181, -1, 182, -1, 192, -1, 206, -1, 207, + -1, 214, -1, 216, -1, 213, -1, 219, -1, 220, + -1, 222, -1, 232, -1, 234, -1, 246, -1, 265, + -1, 266, -1, 267, -1, 271, -1, 275, -1, 278, + -1, 280, -1, 296, -1, 295, -1, 298, -1, 299, + -1, 313, -1, 316, -1, 331, -1, 353, -1, 357, + -1, 375, -1, 377, -1, 381, -1, 384, -1, 399, + -1, 401, -1, 408, -1, 415, -1, 416, -1, 421, + -1, 423, -1, 427, -1, 440, -1, 447, -1, 448, + -1, 451, -1, 468, -1, 469, -1, 470, -1, 471, + -1, 472, -1, 473, -1, 474, -1, 475, -1, 476, + -1, 477, -1, 478, -1, 46, -1, 52, -1, 76, + -1, 84, -1, 96, -1, 100, -1, 101, -1, 102, + -1, 103, -1, 106, -1, 170, -1, 172, -1, 175, + -1, 176, -1, 192, -1, 206, -1, 219, -1, 220, + -1, 222, -1, 232, -1, 234, -1, 246, -1, 266, + -1, 275, -1, 296, -1, 298, -1, 353, -1, 375, + -1, 381, -1, 399, -1, 408, -1, 427, -1, 440, + -1, 451, -1, 29, -1, 33, -1, 34, -1, 35, + -1, 36, -1, 37, -1, 38, -1, 39, -1, 42, + -1, 55, -1, 62, -1, 63, -1, 69, -1, 75, + -1, 77, -1, 88, -1, 95, -1, 104, -1, 105, + -1, 117, -1, 119, -1, 126, -1, 132, -1, 133, + -1, 139, -1, 143, -1, 147, -1, 159, -1, 161, + -1, 166, -1, 168, -1, 171, -1, 178, -1, 180, + -1, 184, -1, 197, -1, 204, -1, 215, -1, 217, + -1, 229, -1, 230, -1, 235, -1, 239, -1, 240, + -1, 272, -1, 277, -1, 284, -1, 287, -1, 288, + -1, 292, -1, 293, -1, 310, -1, 320, -1, 327, + -1, 336, -1, 350, -1, 369, -1, 386, -1, 403, + -1, 406, -1, 414, -1, 417, -1, 418, -1, 424, + -1, 433, -1, 434, -1, 441, -1, 449, -1, 457, + -1, 458, -1, 460, -1, 461, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const yytype_uint16 yyrline[] = { - 0, 467, 467, 483, 495, 504, 505, 506, 507, 508, - 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, - 519, 520, 521, 522, 523, 524, 525, 526, 527, 528, - 529, 530, 531, 532, 533, 534, 535, 536, 537, 539, + 0, 466, 466, 482, 494, 503, 504, 505, 506, 507, + 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, + 518, 519, 520, 521, 522, 523, 524, 525, 526, 527, + 528, 529, 530, 531, 532, 533, 534, 535, 536, 538, 9, 18, 27, 36, 45, 54, 63, 72, 85, 87, 93, 94, 99, 103, 107, 118, 126, 130, 139, 148, 157, 166, 175, 184, 192, 200, 209, 218, 227, 236, @@ -254175,118 +272194,121 @@ static const yytype_uint16 yyrline[] = 96, 101, 113, 118, 143, 153, 163, 169, 180, 191, 206, 207, 213, 214, 219, 220, 226, 227, 231, 232, 237, 239, 245, 246, 250, 251, 254, 255, 260, 7, - 15, 26, 27, 30, 32, 7, 14, 22, 9, 19, - 32, 33, 7, 14, 31, 51, 52, 9, 17, 29, - 30, 34, 35, 36, 41, 42, 43, 48, 52, 56, - 60, 64, 68, 72, 76, 80, 84, 88, 92, 97, - 101, 105, 112, 113, 117, 118, 119, 2, 9, 15, - 21, 28, 35, 45, 46, 47, 7, 21, 36, 56, - 57, 84, 85, 86, 87, 88, 89, 93, 94, 99, - 104, 105, 106, 107, 108, 113, 120, 121, 122, 139, - 146, 153, 163, 173, 185, 193, 202, 220, 221, 225, - 226, 230, 239, 262, 276, 283, 288, 290, 292, 294, - 297, 300, 301, 302, 303, 308, 312, 313, 318, 325, - 330, 331, 332, 333, 334, 335, 336, 337, 343, 344, - 348, 353, 360, 367, 374, 386, 387, 388, 389, 393, - 398, 399, 400, 405, 410, 411, 412, 413, 414, 415, - 420, 440, 469, 470, 474, 478, 479, 480, 484, 488, - 496, 497, 502, 503, 504, 508, 516, 517, 522, 523, - 527, 532, 536, 540, 545, 553, 554, 558, 559, 563, - 564, 570, 581, 594, 608, 622, 636, 650, 673, 677, - 684, 688, 696, 701, 708, 718, 719, 720, 721, 722, - 729, 736, 737, 742, 743, 9, 19, 29, 39, 49, - 59, 69, 79, 93, 94, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 113, - 114, 115, 116, 117, 118, 119, 124, 125, 130, 131, - 132, 137, 138, 139, 142, 143, 8, 20, 36, 37, - 41, 45, 7, 1, 30, 53, 54, 59, 63, 68, - 72, 80, 81, 85, 86, 91, 92, 96, 97, 102, - 103, 104, 105, 106, 111, 119, 123, 128, 129, 134, - 138, 143, 147, 151, 155, 159, 163, 167, 171, 175, - 179, 183, 187, 191, 195, 203, 209, 210, 211, 216, - 220, 47, 48, 52, 53, 68, 69, 76, 84, 92, - 100, 108, 116, 127, 128, 155, 171, 188, 189, 208, - 212, 216, 233, 240, 247, 257, 258, 261, 273, 284, - 292, 297, 302, 307, 312, 320, 328, 333, 338, 345, - 346, 350, 351, 352, 359, 360, 364, 365, 369, 370, - 371, 375, 376, 380, 381, 391, 404, 405, 408, 417, - 428, 429, 430, 433, 434, 435, 439, 440, 441, 442, - 446, 447, 451, 453, 469, 471, 476, 479, 487, 491, - 495, 499, 503, 507, 514, 519, 526, 527, 531, 535, - 539, 543, 550, 557, 558, 563, 564, 568, 569, 574, - 576, 578, 583, 603, 604, 606, 611, 612, 616, 617, - 620, 621, 646, 647, 652, 657, 661, 662, 666, 667, - 671, 672, 673, 674, 675, 679, 692, 699, 706, 713, - 714, 718, 719, 723, 724, 728, 729, 733, 734, 738, - 739, 743, 754, 755, 756, 757, 761, 762, 767, 768, - 769, 778, 784, 793, 794, 807, 808, 812, 813, 817, - 818, 824, 830, 838, 846, 855, 864, 868, 894, 898, - 911, 925, 940, 952, 968, 974, 979, 985, 992, 993, - 1001, 1005, 1009, 1015, 1022, 1027, 1028, 1029, 1030, 1034, - 1035, 1047, 1048, 1053, 1060, 1067, 1074, 1106, 1117, 1130, - 1135, 1136, 1139, 1140, 1143, 1144, 1149, 1150, 1155, 1159, - 1165, 1186, 1194, 1207, 1210, 1214, 1214, 1217, 1218, 1220, - 1225, 1232, 1237, 1243, 1248, 1254, 1260, 1269, 1271, 1274, - 1278, 1279, 1280, 1281, 1282, 1283, 1288, 1308, 1309, 1310, - 1311, 1322, 1336, 1337, 1343, 1348, 1353, 1358, 1363, 1368, - 1373, 1378, 1384, 1390, 1396, 1403, 1425, 1434, 1438, 1446, - 1450, 1458, 1470, 1491, 1495, 1501, 1505, 1518, 1526, 1536, - 1538, 1540, 1542, 1544, 1546, 1551, 1552, 1559, 1568, 1576, - 1585, 1596, 1604, 1605, 1606, 1610, 1610, 1613, 1613, 1616, - 1616, 1619, 1619, 1622, 1622, 1625, 1625, 1628, 1628, 1631, - 1631, 1634, 1636, 1638, 1640, 1642, 1644, 1646, 1648, 1650, - 1655, 1660, 1666, 1673, 1678, 1684, 1690, 1721, 1723, 1725, - 1733, 1748, 1750, 1752, 1754, 1756, 1758, 1760, 1762, 1764, - 1766, 1768, 1770, 1772, 1774, 1776, 1779, 1781, 1783, 1786, - 1788, 1790, 1792, 1795, 1800, 1805, 1812, 1817, 1824, 1829, - 1836, 1841, 1849, 1857, 1865, 1873, 1891, 1899, 1907, 1915, - 1923, 1931, 1935, 1939, 1943, 1951, 1967, 1975, 1983, 1991, - 1999, 2007, 2015, 2019, 2023, 2027, 2031, 2039, 2047, 2055, - 2063, 2083, 2105, 2116, 2123, 2137, 2153, 2155, 2157, 2159, - 2161, 2163, 2165, 2167, 2169, 2171, 2173, 2175, 2177, 2179, - 2181, 2183, 2185, 2187, 2189, 2191, 2193, 2197, 2201, 2205, - 2219, 2220, 2221, 2228, 2240, 2255, 2267, 2269, 2281, 2292, - 2316, 2327, 2336, 2340, 2347, 2355, 2363, 2374, 2382, 2410, - 2446, 2457, 2458, 2465, 2471, 2475, 2479, 2483, 2487, 2491, - 2495, 2499, 2503, 2507, 2511, 2515, 2519, 2523, 2527, 2531, - 2533, 2535, 2539, 2548, 2553, 2560, 2575, 2582, 2586, 2590, - 2594, 2598, 2612, 2613, 2617, 2618, 2622, 2623, 2630, 2631, - 2635, 2636, 2641, 2649, 2651, 2665, 2668, 2695, 2696, 2699, - 2700, 2711, 2717, 2724, 2733, 2750, 2795, 2803, 2811, 2819, - 2827, 2848, 2849, 2852, 2853, 2857, 2867, 2868, 2872, 2873, - 2877, 2878, 2879, 2882, 2883, 2886, 2887, 2888, 2889, 2890, - 2891, 2892, 2893, 2894, 2895, 2896, 2897, 2898, 2901, 2903, - 2908, 2910, 2915, 2917, 2919, 2921, 2923, 2925, 2927, 2929, - 2943, 2945, 2949, 2953, 2960, 2965, 2972, 2977, 2985, 2989, - 2995, 2999, 3008, 3019, 3020, 3024, 3028, 3035, 3036, 3037, - 3038, 3039, 3040, 3041, 3042, 3043, 3044, 3054, 3058, 3065, - 3072, 3073, 3089, 3093, 3098, 3102, 3117, 3122, 3126, 3129, - 3132, 3133, 3134, 3137, 3144, 3154, 3168, 3169, 3173, 3184, - 3185, 3188, 3189, 3192, 3196, 3203, 3207, 3215, 3226, 3227, - 3231, 3232, 3236, 3237, 3240, 3241, 3251, 3252, 3256, 3257, - 3261, 3262, 3265, 3281, 3289, 3297, 3312, 3330, 3331, 3334, - 3335, 3338, 3342, 3343, 3347, 3348, 3351, 3352, 3353, 3363, - 3364, 3375, 3379, 3406, 3408, 3414, 3415, 3418, 3420, 3430, - 3433, 3444, 3448, 3452, 3464, 3468, 3477, 3484, 3522, 3526, - 3530, 3534, 3538, 3542, 3546, 3552, 3553, 3569, 3570, 3571, - 3574, 3575, 3581, 3582, 3583, 3586, 3587, 3588, 3591, 3592, - 3593, 3596, 3597, 3600, 3602, 3607, 3608, 3611, 3619, 3620, - 3621, 3622, 3625, 3626, 7, 18, 19, 23, 24, 25, - 26, 7, 16, 34, 41, 46, 47, 48, 49, 8, - 33, 62, 66, 67, 72, 73, 78, 79, 83, 84, - 89, 90, 7, 16, 25, 34, 43, 52, 5, 11, - 7, 20, 9, 16, 26, 33, 44, 45, 50, 51, - 52, 57, 58, 59, 60, 61, 65, 66, 67, 72, - 73, 78, 82, 90, 91, 96, 97, 98, 104, 109, - 117, 118, 10, 16, 22, 28, 38, 39, 47, 58, - 70, 78, 86, 93, 103, 105, 111, 115, 119, 134, - 141, 142, 143, 147, 148, 7, 14, 20, 28, 29, - 8, 22, 36, 48, 56, 70, 71, 72, 73, 74, - 87, 88, 93, 94, 98, 99, 7, 21, 25, 32, - 43, 44, 50, 51, 9, 19, 2, 7, 14, 24, - 25, 32, 3, 10, 17, 24, 31, 38, 45, 52, - 61, 61, 63, 64, 6, 8, 21, 34, 52, 74, - 75, 76, 77, 11, 24, 37, 54, 55, 56, 61, + 7, 14, 22, 9, 19, 32, 33, 7, 14, 31, + 51, 52, 9, 17, 29, 30, 34, 35, 36, 41, + 42, 43, 48, 52, 56, 60, 64, 68, 72, 76, + 80, 84, 88, 92, 97, 101, 105, 112, 113, 117, + 118, 119, 2, 9, 15, 21, 28, 35, 45, 46, + 47, 7, 21, 36, 56, 57, 84, 85, 86, 87, + 88, 89, 93, 94, 99, 104, 105, 106, 107, 108, + 113, 120, 121, 122, 139, 146, 153, 163, 173, 185, + 193, 202, 220, 221, 225, 226, 230, 239, 262, 276, + 283, 288, 290, 292, 294, 297, 300, 301, 302, 303, + 308, 312, 313, 318, 325, 330, 331, 332, 333, 334, + 335, 336, 337, 343, 344, 348, 353, 360, 367, 374, + 386, 387, 388, 389, 393, 398, 399, 400, 405, 410, + 411, 412, 413, 414, 415, 420, 440, 469, 470, 474, + 478, 479, 480, 484, 488, 496, 497, 502, 503, 504, + 508, 516, 517, 522, 523, 527, 532, 536, 540, 545, + 553, 554, 558, 559, 563, 564, 570, 581, 594, 608, + 622, 636, 650, 673, 677, 684, 688, 696, 701, 708, + 718, 719, 720, 721, 722, 729, 736, 737, 742, 743, + 9, 19, 29, 39, 49, 59, 69, 79, 93, 94, + 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 113, 114, 115, 116, 117, 118, + 119, 124, 125, 130, 131, 132, 137, 138, 139, 142, + 143, 8, 20, 36, 37, 41, 45, 7, 1, 30, + 53, 54, 59, 63, 68, 72, 80, 81, 85, 86, + 91, 92, 96, 97, 102, 103, 104, 105, 106, 111, + 119, 123, 128, 129, 134, 138, 143, 147, 151, 155, + 159, 163, 167, 171, 175, 179, 183, 187, 191, 195, + 203, 209, 210, 211, 216, 220, 47, 48, 52, 53, + 68, 69, 76, 84, 92, 100, 108, 116, 127, 128, + 155, 171, 188, 189, 208, 212, 216, 220, 237, 244, + 251, 261, 262, 265, 277, 288, 296, 301, 306, 311, + 316, 324, 332, 337, 342, 349, 350, 354, 355, 356, + 360, 367, 368, 372, 373, 377, 378, 379, 383, 384, + 388, 389, 399, 412, 413, 416, 425, 436, 437, 438, + 441, 442, 443, 447, 448, 449, 450, 454, 455, 459, + 461, 477, 479, 484, 487, 495, 499, 503, 507, 511, + 515, 522, 527, 534, 535, 539, 544, 548, 552, 560, + 567, 568, 573, 574, 578, 579, 584, 586, 588, 593, + 613, 614, 616, 621, 622, 626, 627, 630, 631, 656, + 657, 662, 667, 671, 672, 676, 677, 681, 682, 683, + 684, 685, 689, 702, 709, 716, 723, 724, 728, 729, + 733, 734, 738, 739, 743, 744, 748, 749, 753, 764, + 765, 766, 767, 771, 772, 777, 778, 779, 788, 794, + 803, 804, 817, 818, 822, 823, 827, 828, 834, 840, + 848, 857, 865, 874, 883, 887, 913, 917, 930, 944, + 959, 971, 987, 993, 998, 1004, 1011, 1012, 1020, 1024, + 1028, 1034, 1041, 1046, 1047, 1048, 1049, 1053, 1054, 1066, + 1067, 1072, 1079, 1086, 1093, 1125, 1136, 1149, 1154, 1155, + 1158, 1159, 1162, 1163, 1168, 1169, 1174, 1178, 1184, 1205, + 1213, 1226, 1229, 1233, 1233, 1236, 1237, 1239, 1244, 1251, + 1256, 1262, 1267, 1273, 1279, 1288, 1290, 1293, 1297, 1298, + 1299, 1300, 1301, 1302, 1307, 1327, 1328, 1329, 1330, 1341, + 1355, 1356, 1362, 1367, 1372, 1377, 1382, 1387, 1392, 1397, + 1403, 1409, 1415, 1422, 1444, 1453, 1457, 1465, 1469, 1477, + 1489, 1510, 1514, 1520, 1524, 1537, 1545, 1555, 1557, 1559, + 1561, 1563, 1565, 1570, 1571, 1578, 1587, 1595, 1604, 1615, + 1623, 1624, 1625, 1629, 1629, 1632, 1632, 1635, 1635, 1638, + 1638, 1641, 1641, 1644, 1644, 1647, 1647, 1650, 1650, 1653, + 1655, 1657, 1659, 1661, 1663, 1665, 1667, 1669, 1674, 1679, + 1685, 1692, 1697, 1703, 1709, 1740, 1742, 1744, 1752, 1767, + 1769, 1771, 1773, 1775, 1777, 1779, 1781, 1783, 1785, 1787, + 1789, 1791, 1793, 1795, 1798, 1800, 1802, 1805, 1807, 1809, + 1811, 1813, 1818, 1823, 1830, 1835, 1842, 1847, 1854, 1859, + 1867, 1875, 1883, 1891, 1909, 1917, 1925, 1933, 1941, 1949, + 1953, 1957, 1961, 1969, 1973, 1989, 1997, 2005, 2013, 2021, + 2029, 2037, 2041, 2045, 2049, 2053, 2061, 2069, 2077, 2085, + 2105, 2127, 2138, 2145, 2156, 2170, 2186, 2188, 2190, 2192, + 2194, 2196, 2198, 2200, 2202, 2204, 2206, 2208, 2210, 2212, + 2214, 2216, 2218, 2220, 2222, 2224, 2226, 2230, 2234, 2238, + 2252, 2253, 2254, 2261, 2273, 2288, 2300, 2302, 2314, 2325, + 2349, 2360, 2369, 2373, 2380, 2388, 2396, 2407, 2415, 2443, + 2479, 2490, 2491, 2498, 2504, 2508, 2512, 2516, 2520, 2524, + 2528, 2532, 2536, 2540, 2544, 2548, 2552, 2556, 2560, 2564, + 2566, 2568, 2572, 2581, 2586, 2593, 2608, 2615, 2619, 2623, + 2627, 2631, 2645, 2646, 2650, 2651, 2652, 2656, 2657, 2664, + 2665, 2669, 2670, 2675, 2683, 2685, 2699, 2702, 2729, 2730, + 2733, 2734, 2745, 2751, 2758, 2767, 2784, 2829, 2837, 2845, + 2853, 2861, 2882, 2883, 2886, 2887, 2891, 2901, 2902, 2906, + 2907, 2911, 2912, 2913, 2916, 2917, 2920, 2921, 2922, 2923, + 2924, 2925, 2926, 2927, 2928, 2929, 2930, 2931, 2932, 2935, + 2937, 2942, 2944, 2949, 2951, 2953, 2955, 2957, 2959, 2961, + 2963, 2977, 2979, 2983, 2987, 2994, 2999, 3006, 3011, 3019, + 3023, 3029, 3033, 3042, 3053, 3054, 3058, 3062, 3069, 3070, + 3071, 3072, 3073, 3074, 3075, 3076, 3077, 3078, 3088, 3092, + 3099, 3106, 3107, 3123, 3127, 3132, 3136, 3151, 3156, 3160, + 3163, 3166, 3167, 3168, 3171, 3178, 3188, 3202, 3203, 3207, + 3218, 3219, 3222, 3223, 3226, 3230, 3237, 3241, 3249, 3260, + 3261, 3265, 3266, 3270, 3271, 3274, 3275, 3285, 3286, 3290, + 3291, 3295, 3296, 3299, 3315, 3323, 3331, 3346, 3364, 3365, + 3368, 3369, 3372, 3376, 3377, 3381, 3382, 3385, 3386, 3387, + 3397, 3398, 3409, 3413, 3440, 3442, 3448, 3449, 3452, 3454, + 3464, 3467, 3478, 3482, 3486, 3498, 3502, 3511, 3518, 3556, + 3560, 3564, 3568, 3572, 3576, 3580, 3586, 3587, 3603, 3604, + 3605, 3608, 3609, 3615, 3616, 3617, 3620, 3621, 3622, 3625, + 3626, 3627, 3630, 3631, 3634, 3636, 3641, 3642, 3645, 3653, + 3654, 3655, 3656, 3659, 3660, 7, 18, 19, 23, 24, + 25, 26, 7, 16, 34, 41, 46, 47, 48, 49, + 8, 33, 62, 66, 67, 72, 73, 78, 79, 83, + 84, 89, 90, 7, 16, 25, 34, 43, 52, 5, + 11, 7, 20, 9, 16, 26, 33, 44, 45, 50, + 51, 52, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, + 85, 86, 90, 91, 92, 97, 98, 103, 107, 115, + 116, 121, 122, 123, 129, 134, 142, 143, 10, 16, + 22, 28, 38, 39, 47, 58, 70, 78, 86, 93, + 103, 105, 111, 115, 119, 134, 141, 142, 143, 147, + 148, 7, 14, 20, 28, 29, 8, 22, 36, 48, + 56, 70, 71, 72, 73, 74, 87, 88, 93, 94, + 98, 99, 7, 21, 25, 32, 43, 44, 50, 51, + 9, 19, 2, 7, 14, 24, 25, 32, 3, 10, + 17, 24, 31, 38, 45, 52, 61, 61, 63, 64, + 6, 8, 21, 34, 52, 74, 75, 76, 77, 11, + 24, 37, 54, 55, 56, 61, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, @@ -254317,34 +272339,37 @@ static const yytype_uint16 yyrline[] = 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 74, 74, 74, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, + 75, 75, 75, 75, 75, 75, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, 76, - 76, 76, 76, 76, 76, 76, 76, 77, 77, 77, + 76, 76, 76, 76, 76, 76, 76, 76, 76, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, - 78, 78, 78, 78, 78, 79, 79, 79, 79, 79, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, + 78, 78, 78, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 80, 80, 80, 80, 80, 80, 80, + 79, 79, 79, 79, 79, 79, 79, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, - 80 + 80, 80, 80, 80, 80, 80, 80, 80, 80 }; #endif @@ -254355,31 +272380,31 @@ static const char *const yytname[] = { "$end", "error", "$undefined", "IDENT", "FCONST", "SCONST", "BCONST", "XCONST", "Op", "ICONST", "PARAM", "TYPECAST", "DOT_DOT", "COLON_EQUALS", - "EQUALS_GREATER", "LAMBDA_ARROW", "POWER_OF", "LESS_EQUALS", - "GREATER_EQUALS", "NOT_EQUALS", "ABORT_P", "ABSOLUTE_P", "ACCESS", - "ACTION", "ADD_P", "ADMIN", "AFTER", "AGGREGATE", "ALL", "ALSO", "ALTER", - "ALWAYS", "ANALYSE", "ANALYZE", "AND", "ANY", "ARRAY", "AS", "ASC_P", - "ASSERTION", "ASSIGNMENT", "ASYMMETRIC", "AT", "ATTACH", "ATTRIBUTE", - "AUTHORIZATION", "BACKWARD", "BEFORE", "BEGIN_P", "BETWEEN", "BIGINT", - "BINARY", "BIT", "BOOLEAN_P", "BOTH", "BY", "CACHE", "CALL_P", "CALLED", - "CASCADE", "CASCADED", "CASE", "CAST", "CATALOG_P", "CHAIN", "CHAR_P", - "CHARACTER", "CHARACTERISTICS", "CHECK_P", "CHECKPOINT", "CLASS", - "CLOSE", "CLUSTER", "COALESCE", "COLLATE", "COLLATION", "COLUMN", - "COLUMNS", "COMMENT", "COMMENTS", "COMMIT", "COMMITTED", "COMPRESSION", - "CONCURRENTLY", "CONFIGURATION", "CONFLICT", "CONNECTION", "CONSTRAINT", - "CONSTRAINTS", "CONTENT_P", "CONTINUE_P", "CONVERSION_P", "COPY", "COST", - "CREATE_P", "CROSS", "CSV", "CUBE", "CURRENT_P", "CURRENT_CATALOG", - "CURRENT_DATE", "CURRENT_ROLE", "CURRENT_SCHEMA", "CURRENT_TIME", - "CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", "CYCLE", "DATA_P", - "DATABASE", "DAY_P", "DAYS_P", "DEALLOCATE", "DEC", "DECIMAL_P", - "DECLARE", "DEFAULT", "DEFAULTS", "DEFERRABLE", "DEFERRED", "DEFINER", - "DELETE_P", "DELIMITER", "DELIMITERS", "DEPENDS", "DESC_P", "DESCRIBE", - "DETACH", "DICTIONARY", "DISABLE_P", "DISCARD", "DISTINCT", "DO", - "DOCUMENT_P", "DOMAIN_P", "DOUBLE_P", "DROP", "EACH", "ELSE", "ENABLE_P", - "ENCODING", "ENCRYPTED", "END_P", "ENUM_P", "ESCAPE", "EVENT", "EXCEPT", - "EXCLUDE", "EXCLUDING", "EXCLUSIVE", "EXECUTE", "EXISTS", "EXPLAIN", - "EXPORT_P", "EXPORT_STATE", "EXTENSION", "EXTERNAL", "EXTRACT", - "FALSE_P", "FAMILY", "FETCH", "FILTER", "FIRST_P", "FLOAT_P", + "EQUALS_GREATER", "POWER_OF", "LAMBDA_ARROW", "DOUBLE_ARROW", + "LESS_EQUALS", "GREATER_EQUALS", "NOT_EQUALS", "ABORT_P", "ABSOLUTE_P", + "ACCESS", "ACTION", "ADD_P", "ADMIN", "AFTER", "AGGREGATE", "ALL", + "ALSO", "ALTER", "ALWAYS", "ANALYSE", "ANALYZE", "AND", "ANY", "ARRAY", + "AS", "ASC_P", "ASSERTION", "ASSIGNMENT", "ASYMMETRIC", "AT", "ATTACH", + "ATTRIBUTE", "AUTHORIZATION", "BACKWARD", "BEFORE", "BEGIN_P", "BETWEEN", + "BIGINT", "BINARY", "BIT", "BOOLEAN_P", "BOTH", "BY", "CACHE", "CALL_P", + "CALLED", "CASCADE", "CASCADED", "CASE", "CAST", "CATALOG_P", "CHAIN", + "CHAR_P", "CHARACTER", "CHARACTERISTICS", "CHECK_P", "CHECKPOINT", + "CLASS", "CLOSE", "CLUSTER", "COALESCE", "COLLATE", "COLLATION", + "COLUMN", "COLUMNS", "COMMENT", "COMMENTS", "COMMIT", "COMMITTED", + "COMPRESSION", "CONCURRENTLY", "CONFIGURATION", "CONFLICT", "CONNECTION", + "CONSTRAINT", "CONSTRAINTS", "CONTENT_P", "CONTINUE_P", "CONVERSION_P", + "COPY", "COST", "CREATE_P", "CROSS", "CSV", "CUBE", "CURRENT_P", + "CURRENT_CATALOG", "CURRENT_DATE", "CURRENT_ROLE", "CURRENT_SCHEMA", + "CURRENT_TIME", "CURRENT_TIMESTAMP", "CURRENT_USER", "CURSOR", "CYCLE", + "DATA_P", "DATABASE", "DAY_P", "DAYS_P", "DEALLOCATE", "DEC", + "DECIMAL_P", "DECLARE", "DEFAULT", "DEFAULTS", "DEFERRABLE", "DEFERRED", + "DEFINER", "DELETE_P", "DELIMITER", "DELIMITERS", "DEPENDS", "DESC_P", + "DESCRIBE", "DETACH", "DICTIONARY", "DISABLE_P", "DISCARD", "DISTINCT", + "DO", "DOCUMENT_P", "DOMAIN_P", "DOUBLE_P", "DROP", "EACH", "ELSE", + "ENABLE_P", "ENCODING", "ENCRYPTED", "END_P", "ENUM_P", "ESCAPE", + "EVENT", "EXCEPT", "EXCLUDE", "EXCLUDING", "EXCLUSIVE", "EXECUTE", + "EXISTS", "EXPLAIN", "EXPORT_P", "EXPORT_STATE", "EXTENSION", "EXTERNAL", + "EXTRACT", "FALSE_P", "FAMILY", "FETCH", "FILTER", "FIRST_P", "FLOAT_P", "FOLLOWING", "FOR", "FORCE", "FOREIGN", "FORWARD", "FREEZE", "FROM", "FULL", "FUNCTION", "FUNCTIONS", "GENERATED", "GLOB", "GLOBAL", "GRANT", "GRANTED", "GROUP_P", "GROUPING", "GROUPING_ID", "HANDLER", "HAVING", @@ -254444,39 +272469,39 @@ static const char *const yytname[] = "returning_clause", "override_kind", "set_target_list", "opt_collate", "opt_class", "insert_column_list", "set_clause_list", "set_clause_list_opt_comma", "index_params", "set_target", - "CreateTypeStmt", "opt_enum_val_list", "enum_val_list", "PragmaStmt", - "CreateSeqStmt", "OptSeqOptList", "ExecuteStmt", "execute_param_clause", - "AlterSeqStmt", "SeqOptList", "opt_with", "NumericOnly", "SeqOptElem", - "opt_by", "SignedIconst", "TransactionStmt", "opt_transaction", - "CreateStmt", "ConstraintAttributeSpec", "def_arg", - "OptParenthesizedSeqOptList", "generic_option_arg", "key_action", - "ColConstraint", "ColConstraintElem", "GeneratedColumnType", - "opt_GeneratedColumnType", "GeneratedConstraintElem", - "generic_option_elem", "key_update", "key_actions", "OnCommitOption", - "reloptions", "opt_no_inherit", "TableConstraint", "TableLikeOption", - "reloption_list", "ExistingIndex", "ConstraintAttr", "OptWith", - "definition", "TableLikeOptionList", "generic_option_name", - "ConstraintAttributeElem", "columnDef", "def_list", "index_name", - "TableElement", "def_elem", "opt_definition", "OptTableElementList", - "columnElem", "opt_column_list", "ColQualList", "key_delete", - "reloption_elem", "columnList", "columnList_opt_comma", "func_type", - "ConstraintElem", "TableElementList", "key_match", "TableLikeClause", - "OptTemp", "generated_when", "DropStmt", "drop_type_any_name", - "drop_type_name", "any_name_list", "opt_drop_behavior", - "drop_type_name_on_any_name", "type_name_list", "CreateFunctionStmt", - "macro_alias", "param_list", "UpdateStmt", "CopyStmt", "copy_from", - "copy_delimiter", "copy_generic_opt_arg_list", "opt_using", "opt_as", - "opt_program", "copy_options", "copy_generic_opt_arg", - "copy_generic_opt_elem", "opt_oids", "copy_opt_list", "opt_binary", - "copy_opt_item", "copy_generic_opt_arg_list_item", "copy_file_name", + "CreateTypeStmt", "PragmaStmt", "CreateSeqStmt", "OptSeqOptList", + "ExecuteStmt", "execute_param_clause", "AlterSeqStmt", "SeqOptList", + "opt_with", "NumericOnly", "SeqOptElem", "opt_by", "SignedIconst", + "TransactionStmt", "opt_transaction", "CreateStmt", + "ConstraintAttributeSpec", "def_arg", "OptParenthesizedSeqOptList", + "generic_option_arg", "key_action", "ColConstraint", "ColConstraintElem", + "GeneratedColumnType", "opt_GeneratedColumnType", + "GeneratedConstraintElem", "generic_option_elem", "key_update", + "key_actions", "OnCommitOption", "reloptions", "opt_no_inherit", + "TableConstraint", "TableLikeOption", "reloption_list", "ExistingIndex", + "ConstraintAttr", "OptWith", "definition", "TableLikeOptionList", + "generic_option_name", "ConstraintAttributeElem", "columnDef", + "def_list", "index_name", "TableElement", "def_elem", "opt_definition", + "OptTableElementList", "columnElem", "opt_column_list", "ColQualList", + "key_delete", "reloption_elem", "columnList", "columnList_opt_comma", + "func_type", "ConstraintElem", "TableElementList", "key_match", + "TableLikeClause", "OptTemp", "generated_when", "DropStmt", + "drop_type_any_name", "drop_type_name", "any_name_list", + "opt_drop_behavior", "drop_type_name_on_any_name", "type_name_list", + "CreateFunctionStmt", "macro_alias", "param_list", "UpdateStmt", + "CopyStmt", "copy_from", "copy_delimiter", "copy_generic_opt_arg_list", + "opt_using", "opt_as", "opt_program", "copy_options", + "copy_generic_opt_arg", "copy_generic_opt_elem", "opt_oids", + "copy_opt_list", "opt_binary", "copy_opt_item", + "copy_generic_opt_arg_list_item", "copy_file_name", "copy_generic_opt_list", "SelectStmt", "select_with_parens", "select_no_parens", "select_clause", "simple_select", "with_clause", "cte_list", "common_table_expr", "into_clause", "OptTempTableName", - "opt_table", "all_or_distinct", "distinct_clause", "opt_all_clause", - "opt_ignore_nulls", "opt_sort_clause", "sort_clause", "sortby_list", - "sortby", "opt_asc_desc", "opt_nulls_order", "select_limit", - "opt_select_limit", "limit_clause", "offset_clause", "sample_count", - "sample_clause", "opt_sample_func", "tablesample_entry", + "opt_table", "all_or_distinct", "by_name", "distinct_clause", + "opt_all_clause", "opt_ignore_nulls", "opt_sort_clause", "sort_clause", + "sortby_list", "sortby", "opt_asc_desc", "opt_nulls_order", + "select_limit", "opt_select_limit", "limit_clause", "offset_clause", + "sample_count", "sample_clause", "opt_sample_func", "tablesample_entry", "tablesample_clause", "opt_tablesample_clause", "opt_repeatable_clause", "select_limit_value", "select_offset_value", "select_fetch_first_value", "I_or_F_const", "row_or_rows", "first_or_next", "group_clause", @@ -254599,92 +272624,92 @@ static const yytype_uint16 yytoknum[] = 705, 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 718, 719, 720, 721, 722, 723, 724, 725, 726, 727, 728, 729, 730, 731, 732, 733, 734, - 735, 736, 737, 738, 739, 60, 62, 61, 740, 43, - 45, 42, 47, 37, 94, 741, 91, 93, 40, 41, - 46, 59, 44, 123, 125, 35, 63, 58 + 735, 736, 737, 738, 739, 740, 60, 62, 61, 741, + 43, 45, 42, 47, 37, 94, 742, 91, 93, 40, + 41, 46, 59, 44, 123, 125, 35, 63, 58 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const yytype_uint16 yyr1[] = { - 0, 508, 509, 510, 510, 511, 511, 511, 511, 511, - 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, - 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, - 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, - 512, 512, 512, 512, 512, 512, 512, 512, 513, 513, - 514, 514, 515, 515, 515, 515, 516, 516, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 517, 517, 517, - 517, 517, 517, 517, 517, 517, 517, 518, 518, 519, - 519, 519, 519, 520, 520, 521, 522, 522, 522, 523, - 523, 523, 523, 524, 524, 524, 524, 524, 524, 524, - 524, 524, 524, 524, 524, 524, 525, 525, 526, 527, - 527, 527, 527, 527, 528, 528, 529, 529, 529, 530, - 530, 531, 532, 532, 533, 533, 533, 534, 534, 534, - 535, 535, 536, 536, 537, 537, 538, 538, 539, 539, - 540, 540, 541, 541, 542, 542, 543, 543, 544, 545, - 545, 546, 546, 547, 547, 548, 548, 548, 549, 549, - 550, 550, 551, 551, 551, 552, 552, 553, 553, 554, - 554, 555, 555, 555, 556, 556, 556, 556, 557, 557, - 557, 557, 557, 557, 557, 557, 557, 557, 557, 557, - 557, 557, 558, 558, 559, 559, 559, 560, 560, 560, - 560, 560, 560, 561, 561, 561, 562, 562, 562, 563, - 563, 564, 564, 564, 564, 564, 564, 565, 565, 566, - 567, 567, 567, 567, 567, 568, 568, 568, 568, 569, - 569, 569, 569, 569, 569, 569, 569, 570, 570, 571, - 571, 572, 572, 572, 573, 574, 575, 575, 575, 575, - 575, 576, 576, 576, 576, 577, 578, 578, 579, 579, - 580, 580, 580, 580, 580, 580, 580, 580, 581, 581, - 582, 583, 583, 583, 583, 584, 584, 584, 584, 585, - 586, 586, 586, 587, 588, 588, 588, 588, 588, 588, - 589, 589, 590, 590, 591, 592, 592, 592, 593, 593, - 594, 594, 595, 595, 595, 596, 597, 597, 598, 598, - 599, 600, 600, 600, 600, 601, 601, 602, 602, 603, - 603, 603, 604, 604, 604, 604, 604, 604, 605, 605, - 606, 606, 606, 606, 607, 608, 608, 608, 608, 608, - 608, 608, 608, 609, 609, 610, 610, 610, 610, 610, - 610, 610, 610, 611, 611, 611, 611, 611, 611, 611, - 611, 611, 611, 611, 611, 611, 611, 611, 611, 612, - 612, 612, 612, 612, 612, 612, 613, 613, 614, 614, - 614, 615, 615, 615, 616, 616, 617, 617, 618, 618, - 619, 619, 620, 621, 621, 622, 622, 623, 623, 624, - 624, 625, 625, 626, 626, 627, 627, 628, 628, 629, - 629, 629, 629, 629, 630, 631, 631, 632, 632, 633, - 633, 634, 634, 634, 634, 634, 634, 634, 634, 634, - 634, 634, 634, 634, 634, 635, 636, 636, 636, 637, - 637, 638, 638, 639, 639, 640, 640, 640, 640, 640, - 640, 640, 640, 641, 641, 642, 642, 642, 642, 642, - 642, 642, 643, 643, 643, 644, 644, 645, 646, 646, - 647, 647, 647, 647, 647, 647, 647, 647, 647, 648, - 648, 649, 649, 649, 650, 650, 651, 651, 652, 652, - 652, 653, 653, 654, 654, 654, 655, 655, 656, 656, - 657, 657, 657, 658, 658, 658, 659, 659, 659, 659, - 660, 660, 661, 661, 661, 661, 662, 662, 663, 663, - 663, 663, 663, 663, 664, 664, 665, 665, 666, 666, - 666, 666, 667, 668, 668, 669, 669, 670, 670, 670, - 670, 670, 671, 672, 672, 672, 673, 673, 674, 674, - 675, 675, 676, 676, 676, 676, 677, 677, 678, 678, - 679, 679, 679, 679, 679, 680, 681, 682, 683, 684, - 684, 685, 685, 686, 686, 687, 687, 688, 688, 689, - 689, 690, 691, 691, 691, 691, 692, 692, 693, 693, - 693, 694, 694, 695, 695, 696, 696, 697, 697, 698, - 698, 699, 699, 699, 699, 699, 699, 699, 700, 700, - 700, 700, 700, 700, 701, 701, 701, 701, 702, 702, - 703, 703, 703, 703, 703, 704, 704, 704, 704, 705, - 705, 706, 706, 707, 707, 707, 707, 708, 708, 709, - 710, 710, 711, 711, 712, 712, 713, 713, 714, 714, - 715, 716, 716, 717, 717, 718, 718, 719, 719, 720, - 720, 720, 720, 720, 720, 720, 720, 721, 721, 721, - 722, 722, 722, 722, 722, 722, 722, 723, 723, 723, - 723, 724, 725, 725, 726, 726, 726, 726, 726, 726, - 726, 726, 726, 726, 726, 727, 727, 728, 728, 729, - 729, 730, 731, 732, 732, 733, 733, 734, 735, 736, - 736, 736, 736, 736, 736, 737, 737, 738, 738, 738, - 738, 739, 740, 740, 740, 741, 741, 742, 742, 743, - 743, 744, 744, 745, 745, 746, 746, 747, 747, 748, - 748, 749, 749, 749, 749, 749, 749, 749, 749, 749, - 749, 749, 749, 749, 749, 749, 749, 750, 750, 750, + 0, 509, 510, 511, 511, 512, 512, 512, 512, 512, + 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, + 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, + 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, + 513, 513, 513, 513, 513, 513, 513, 513, 514, 514, + 515, 515, 516, 516, 516, 516, 517, 517, 518, 518, + 518, 518, 518, 518, 518, 518, 518, 518, 518, 518, + 518, 518, 518, 518, 518, 518, 518, 518, 518, 518, + 518, 518, 518, 518, 518, 518, 518, 519, 519, 520, + 520, 520, 520, 521, 521, 522, 523, 523, 523, 524, + 524, 524, 524, 525, 525, 525, 525, 525, 525, 525, + 525, 525, 525, 525, 525, 525, 526, 526, 527, 528, + 528, 528, 528, 528, 529, 529, 530, 530, 530, 531, + 531, 532, 533, 533, 534, 534, 534, 535, 535, 535, + 536, 536, 537, 537, 538, 538, 539, 539, 540, 540, + 541, 541, 542, 542, 543, 543, 544, 544, 545, 546, + 547, 547, 547, 548, 548, 549, 549, 550, 550, 550, + 551, 551, 552, 552, 553, 553, 554, 554, 554, 555, + 555, 555, 555, 556, 556, 556, 556, 556, 556, 556, + 556, 556, 556, 556, 556, 556, 556, 557, 557, 558, + 558, 558, 559, 559, 559, 559, 559, 559, 560, 560, + 560, 561, 561, 561, 562, 562, 563, 563, 563, 563, + 563, 563, 564, 564, 565, 566, 566, 566, 566, 566, + 567, 567, 567, 567, 568, 568, 568, 568, 568, 568, + 568, 568, 569, 569, 570, 570, 571, 571, 571, 572, + 573, 574, 574, 574, 574, 574, 575, 575, 575, 575, + 576, 577, 577, 578, 578, 579, 579, 579, 579, 579, + 579, 579, 579, 580, 580, 581, 582, 582, 582, 582, + 583, 583, 583, 583, 584, 585, 585, 585, 586, 587, + 587, 587, 587, 587, 587, 588, 588, 589, 589, 590, + 591, 591, 591, 592, 592, 593, 593, 594, 594, 594, + 595, 596, 596, 597, 597, 598, 599, 599, 599, 599, + 600, 600, 601, 601, 602, 602, 602, 603, 603, 603, + 603, 603, 603, 604, 604, 605, 605, 605, 605, 606, + 607, 607, 607, 607, 607, 607, 607, 607, 608, 608, + 609, 609, 609, 609, 609, 609, 609, 609, 610, 610, + 610, 610, 610, 610, 610, 610, 610, 610, 610, 610, + 610, 610, 610, 610, 611, 611, 611, 611, 611, 611, + 611, 612, 612, 613, 613, 613, 614, 614, 614, 615, + 615, 616, 616, 617, 617, 618, 618, 619, 620, 620, + 621, 621, 622, 622, 623, 623, 624, 624, 625, 625, + 626, 626, 627, 627, 628, 628, 628, 628, 628, 629, + 630, 630, 631, 631, 632, 632, 633, 633, 633, 633, + 633, 633, 633, 633, 633, 633, 633, 633, 633, 633, + 634, 635, 635, 635, 636, 636, 637, 637, 638, 638, + 639, 639, 639, 639, 639, 639, 639, 639, 640, 640, + 641, 641, 641, 641, 641, 641, 641, 641, 642, 642, + 642, 643, 643, 644, 645, 645, 646, 646, 646, 646, + 646, 646, 646, 646, 646, 647, 647, 648, 648, 648, + 649, 650, 650, 651, 651, 652, 652, 652, 653, 653, + 654, 654, 654, 655, 655, 656, 656, 657, 657, 657, + 658, 658, 658, 659, 659, 659, 659, 660, 660, 661, + 661, 661, 661, 662, 662, 663, 663, 663, 663, 663, + 663, 664, 664, 665, 665, 666, 666, 666, 666, 667, + 668, 668, 669, 669, 670, 670, 670, 670, 670, 671, + 672, 672, 672, 673, 673, 674, 674, 675, 675, 676, + 676, 676, 676, 677, 677, 678, 678, 679, 679, 679, + 679, 679, 680, 681, 682, 683, 684, 684, 685, 685, + 686, 686, 687, 687, 688, 688, 689, 689, 690, 691, + 691, 691, 691, 692, 692, 693, 693, 693, 694, 694, + 695, 695, 696, 696, 697, 697, 698, 698, 699, 699, + 699, 699, 699, 699, 699, 699, 700, 700, 700, 700, + 700, 700, 701, 701, 701, 701, 702, 702, 703, 703, + 703, 703, 703, 704, 704, 704, 704, 705, 705, 706, + 706, 707, 707, 707, 707, 708, 708, 709, 710, 710, + 711, 711, 712, 712, 713, 713, 714, 714, 715, 716, + 716, 717, 717, 718, 718, 719, 719, 720, 720, 720, + 720, 720, 720, 720, 720, 721, 721, 721, 722, 722, + 722, 722, 722, 722, 722, 723, 723, 723, 723, 724, + 725, 725, 726, 726, 726, 726, 726, 726, 726, 726, + 726, 726, 726, 727, 727, 728, 728, 729, 729, 730, + 731, 732, 732, 733, 733, 734, 735, 736, 736, 736, + 736, 736, 736, 737, 737, 738, 738, 738, 738, 739, + 740, 740, 740, 741, 741, 742, 742, 743, 743, 744, + 744, 745, 745, 746, 746, 747, 747, 748, 748, 749, + 749, 749, 749, 749, 749, 749, 749, 749, 749, 749, + 749, 749, 749, 749, 749, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, 750, @@ -254699,43 +272724,46 @@ static const yytype_uint16 yyr1[] = 754, 755, 755, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, 756, - 756, 756, 757, 757, 758, 758, 759, 759, 760, 760, - 761, 761, 762, 763, 763, 763, 764, 765, 765, 766, - 766, 767, 767, 767, 768, 768, 769, 769, 769, 769, - 769, 770, 770, 771, 771, 772, 773, 773, 774, 774, - 775, 775, 775, 776, 776, 777, 777, 777, 777, 777, - 777, 777, 777, 777, 777, 777, 777, 777, 778, 778, - 779, 779, 780, 780, 780, 780, 780, 780, 780, 780, - 781, 781, 782, 782, 783, 783, 784, 784, 785, 785, - 786, 786, 786, 787, 787, 788, 788, 789, 789, 789, - 789, 789, 789, 789, 789, 789, 789, 790, 790, 791, - 792, 792, 793, 793, 793, 793, 793, 793, 794, 795, - 796, 796, 796, 797, 797, 798, 799, 799, 800, 801, - 801, 802, 802, 803, 803, 804, 804, 804, 805, 805, - 806, 806, 807, 807, 808, 808, 809, 809, 810, 810, - 811, 811, 812, 812, 812, 812, 812, 813, 813, 814, - 814, 815, 816, 816, 817, 817, 818, 818, 818, 819, - 819, 820, 820, 821, 821, 822, 822, 823, 824, 825, - 825, 826, 826, 826, 826, 826, 826, 826, 826, 826, - 826, 826, 826, 826, 826, 827, 828, 829, 829, 829, - 830, 830, 831, 831, 831, 832, 832, 832, 833, 833, - 833, 834, 834, 835, 835, 836, 836, 837, 838, 838, - 838, 838, 839, 839, 840, 841, 841, 842, 842, 842, - 842, 843, 843, 844, 844, 845, 845, 845, 845, 846, - 846, 847, 848, 848, 849, 849, 850, 850, 851, 851, - 852, 852, 853, 853, 853, 853, 853, 853, 854, 854, - 855, 856, 857, 857, 857, 857, 858, 858, 859, 859, - 859, 860, 860, 860, 860, 860, 861, 861, 861, 862, - 862, 863, 863, 864, 864, 865, 865, 865, 865, 866, - 867, 867, 868, 868, 868, 868, 869, 869, 869, 869, - 870, 870, 870, 870, 871, 871, 872, 872, 872, 872, - 872, 872, 872, 873, 873, 874, 874, 874, 875, 875, - 876, 876, 876, 876, 876, 877, 877, 877, 877, 877, - 878, 878, 879, 879, 880, 880, 881, 882, 882, 882, - 883, 883, 884, 884, 885, 885, 886, 887, 887, 888, - 888, 888, 889, 889, 889, 889, 889, 889, 889, 889, - 890, 890, 891, 891, 892, 893, 893, 893, 893, 894, - 894, 894, 894, 895, 895, 895, 896, 896, 896, 897, + 756, 756, 757, 757, 758, 758, 758, 759, 759, 760, + 760, 761, 761, 762, 763, 763, 763, 764, 765, 765, + 766, 766, 767, 767, 767, 768, 768, 769, 769, 769, + 769, 769, 770, 770, 771, 771, 772, 773, 773, 774, + 774, 775, 775, 775, 776, 776, 777, 777, 777, 777, + 777, 777, 777, 777, 777, 777, 777, 777, 777, 778, + 778, 779, 779, 780, 780, 780, 780, 780, 780, 780, + 780, 781, 781, 782, 782, 783, 783, 784, 784, 785, + 785, 786, 786, 786, 787, 787, 788, 788, 789, 789, + 789, 789, 789, 789, 789, 789, 789, 789, 790, 790, + 791, 792, 792, 793, 793, 793, 793, 793, 793, 794, + 795, 796, 796, 796, 797, 797, 798, 799, 799, 800, + 801, 801, 802, 802, 803, 803, 804, 804, 804, 805, + 805, 806, 806, 807, 807, 808, 808, 809, 809, 810, + 810, 811, 811, 812, 812, 812, 812, 812, 813, 813, + 814, 814, 815, 816, 816, 817, 817, 818, 818, 818, + 819, 819, 820, 820, 821, 821, 822, 822, 823, 824, + 825, 825, 826, 826, 826, 826, 826, 826, 826, 826, + 826, 826, 826, 826, 826, 826, 827, 828, 829, 829, + 829, 830, 830, 831, 831, 831, 832, 832, 832, 833, + 833, 833, 834, 834, 835, 835, 836, 836, 837, 838, + 838, 838, 838, 839, 839, 840, 841, 841, 842, 842, + 842, 842, 843, 843, 844, 844, 845, 845, 845, 845, + 846, 846, 847, 848, 848, 849, 849, 850, 850, 851, + 851, 852, 852, 853, 853, 853, 853, 853, 853, 854, + 854, 855, 856, 857, 857, 857, 857, 858, 858, 859, + 859, 859, 860, 860, 860, 860, 860, 860, 860, 860, + 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, + 860, 860, 860, 860, 860, 860, 860, 860, 860, 860, + 860, 860, 861, 861, 861, 862, 862, 863, 863, 864, + 864, 865, 865, 865, 865, 866, 867, 867, 868, 868, + 868, 868, 869, 869, 869, 869, 870, 870, 870, 870, + 871, 871, 872, 872, 872, 872, 872, 872, 872, 873, + 873, 874, 874, 874, 875, 875, 876, 876, 876, 876, + 876, 877, 877, 877, 877, 877, 878, 878, 879, 879, + 880, 880, 881, 882, 882, 882, 883, 883, 884, 884, + 885, 885, 886, 887, 887, 888, 888, 888, 889, 889, + 889, 889, 889, 889, 889, 889, 890, 890, 891, 891, + 892, 893, 893, 893, 893, 894, 894, 894, 894, 895, + 895, 895, 896, 896, 896, 897, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, @@ -254766,34 +272794,37 @@ static const yytype_uint16 yyr1[] = 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, 898, - 898, 898, 898, 898, 898, 898, 898, 899, 899, 899, - 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, + 898, 898, 898, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, 899, + 899, 899, 899, 899, 899, 899, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, 900, - 900, 900, 900, 900, 900, 900, 900, 901, 901, 901, + 900, 900, 900, 900, 900, 900, 900, 900, 900, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, - 901, 901, 902, 902, 902, 902, 902, 902, 902, 902, + 901, 901, 901, 901, 901, 901, 901, 901, 901, 901, + 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, + 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, 902, - 902, 902, 902, 902, 902, 903, 903, 903, 903, 903, + 902, 902, 902, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, 903, - 903, 903, 903, 904, 904, 904, 904, 904, 904, 904, + 903, 903, 903, 903, 903, 903, 903, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, - 904, 904, 904, 904, 904, 904, 904, 904, 904, 904, - 904 + 904, 904, 904, 904, 904, 904, 904, 904, 904 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -254814,75 +272845,75 @@ static const yytype_uint8 yyr2[] = 4, 4, 7, 2, 1, 3, 4, 3, 0, 1, 0, 2, 3, 5, 8, 5, 0, 5, 5, 7, 2, 0, 1, 1, 1, 3, 2, 0, 1, 0, - 1, 3, 1, 3, 1, 2, 1, 3, 2, 8, - 5, 1, 0, 1, 3, 2, 4, 5, 5, 8, - 1, 0, 3, 9, 12, 3, 0, 4, 6, 1, - 2, 1, 1, 0, 1, 2, 2, 1, 2, 2, - 1, 2, 3, 2, 2, 2, 2, 3, 3, 3, - 1, 3, 1, 0, 1, 2, 2, 2, 2, 2, - 2, 2, 2, 1, 1, 0, 9, 12, 11, 0, - 2, 1, 1, 1, 1, 1, 1, 3, 0, 1, - 2, 1, 1, 2, 2, 3, 1, 1, 2, 2, - 1, 2, 3, 5, 3, 2, 5, 1, 1, 1, - 0, 5, 7, 5, 2, 3, 1, 1, 2, 2, - 0, 3, 4, 4, 0, 3, 2, 0, 3, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, - 3, 1, 2, 2, 2, 2, 2, 2, 0, 3, - 3, 3, 0, 1, 2, 1, 2, 2, 2, 2, - 3, 4, 1, 3, 1, 1, 1, 1, 3, 1, - 2, 0, 1, 2, 0, 1, 3, 0, 2, 0, - 3, 3, 1, 5, 3, 1, 3, 1, 2, 1, - 4, 5, 5, 6, 3, 7, 4, 11, 1, 3, - 2, 2, 2, 0, 3, 1, 1, 2, 2, 2, - 2, 1, 0, 1, 2, 6, 4, 6, 4, 6, - 8, 4, 6, 1, 1, 1, 1, 2, 1, 2, - 1, 2, 1, 1, 1, 3, 3, 3, 3, 2, - 2, 1, 3, 1, 1, 1, 1, 3, 1, 1, - 0, 1, 1, 1, 1, 3, 8, 7, 1, 1, - 2, 3, 8, 11, 9, 1, 1, 3, 0, 1, - 3, 1, 0, 1, 0, 1, 0, 1, 3, 1, - 1, 1, 3, 0, 2, 2, 0, 2, 0, 1, - 0, 1, 1, 1, 3, 3, 1, 1, 3, 3, - 3, 3, 4, 3, 2, 1, 1, 1, 1, 1, - 3, 1, 1, 3, 3, 1, 2, 4, 4, 2, - 3, 5, 5, 1, 1, 11, 11, 1, 2, 4, - 4, 4, 2, 2, 3, 1, 3, 6, 2, 0, - 3, 3, 4, 4, 4, 4, 3, 2, 1, 1, - 0, 1, 1, 0, 1, 5, 1, 0, 2, 2, - 0, 1, 0, 3, 5, 5, 1, 3, 4, 3, - 1, 1, 0, 2, 2, 0, 2, 2, 1, 1, - 1, 0, 2, 4, 5, 4, 2, 3, 2, 2, - 2, 2, 1, 2, 3, 0, 1, 0, 5, 1, - 4, 6, 2, 1, 0, 4, 0, 1, 1, 2, - 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, - 1, 1, 3, 3, 3, 0, 1, 3, 1, 2, - 1, 1, 1, 1, 1, 2, 4, 4, 5, 1, - 1, 2, 0, 2, 0, 1, 3, 1, 0, 1, - 2, 3, 2, 4, 2, 3, 2, 0, 1, 2, - 0, 4, 5, 1, 2, 2, 0, 1, 3, 1, - 2, 3, 3, 3, 3, 3, 1, 4, 3, 4, - 5, 4, 5, 4, 5, 2, 4, 1, 1, 0, - 1, 4, 5, 4, 0, 2, 2, 2, 1, 1, - 0, 4, 2, 1, 2, 2, 4, 2, 6, 2, - 1, 3, 4, 0, 2, 0, 2, 0, 1, 3, - 3, 2, 0, 2, 4, 1, 1, 1, 0, 2, - 3, 5, 6, 2, 3, 5, 5, 3, 4, 0, - 1, 1, 1, 1, 1, 2, 4, 1, 1, 1, - 1, 2, 3, 0, 1, 1, 1, 1, 1, 2, - 2, 2, 2, 2, 1, 3, 0, 1, 1, 1, - 1, 5, 2, 1, 1, 1, 1, 4, 1, 2, - 2, 1, 3, 3, 2, 1, 0, 5, 2, 5, - 2, 1, 3, 3, 0, 1, 1, 1, 1, 1, + 1, 3, 1, 3, 1, 2, 1, 3, 2, 5, + 2, 4, 5, 5, 8, 1, 0, 3, 9, 12, + 3, 0, 4, 6, 1, 2, 1, 1, 0, 1, + 2, 2, 1, 2, 2, 1, 2, 3, 2, 2, + 2, 2, 3, 3, 3, 1, 3, 1, 0, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, + 0, 9, 12, 11, 0, 2, 1, 1, 1, 1, + 1, 1, 3, 0, 1, 2, 1, 1, 2, 2, + 3, 1, 1, 2, 2, 1, 2, 3, 5, 3, + 2, 5, 1, 1, 1, 0, 5, 7, 5, 2, + 3, 1, 1, 2, 2, 0, 3, 4, 4, 0, + 3, 2, 0, 3, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 3, 3, 1, 2, 2, 2, + 2, 2, 2, 0, 3, 3, 3, 0, 1, 2, + 1, 2, 2, 2, 2, 3, 4, 1, 3, 1, + 1, 1, 1, 3, 1, 2, 0, 1, 2, 0, + 1, 3, 0, 2, 0, 3, 3, 1, 5, 3, + 1, 3, 1, 2, 1, 4, 5, 5, 6, 3, + 7, 4, 11, 1, 3, 2, 2, 2, 0, 3, + 1, 1, 2, 2, 2, 2, 1, 0, 1, 2, + 6, 4, 6, 4, 6, 8, 4, 6, 1, 1, + 1, 1, 2, 1, 2, 1, 2, 1, 1, 1, + 3, 3, 3, 3, 2, 2, 1, 3, 1, 1, + 1, 1, 3, 1, 1, 0, 1, 1, 1, 1, + 3, 8, 7, 1, 1, 2, 3, 8, 11, 9, + 1, 1, 3, 0, 1, 3, 1, 0, 1, 0, + 1, 0, 1, 3, 1, 1, 1, 3, 0, 2, + 2, 0, 2, 0, 1, 0, 1, 1, 1, 3, + 3, 1, 1, 3, 3, 3, 3, 4, 3, 2, + 1, 1, 1, 1, 1, 3, 1, 1, 3, 3, + 1, 2, 4, 4, 2, 3, 5, 5, 1, 1, + 11, 11, 1, 2, 5, 4, 4, 4, 2, 2, + 3, 1, 3, 6, 2, 0, 3, 3, 4, 4, + 4, 4, 3, 2, 1, 1, 0, 1, 1, 0, + 2, 1, 5, 1, 0, 2, 2, 0, 1, 0, + 3, 5, 5, 1, 3, 4, 3, 1, 1, 0, + 2, 2, 0, 2, 2, 1, 1, 1, 0, 2, + 4, 5, 4, 2, 3, 2, 2, 2, 2, 1, + 2, 3, 0, 1, 0, 5, 1, 4, 6, 2, + 1, 0, 4, 0, 1, 1, 2, 2, 2, 1, + 1, 2, 2, 1, 1, 1, 1, 1, 1, 3, + 3, 3, 0, 1, 3, 1, 2, 1, 1, 1, + 1, 1, 2, 4, 4, 5, 1, 1, 2, 0, + 2, 0, 1, 3, 1, 0, 1, 2, 3, 2, + 4, 2, 3, 2, 0, 1, 2, 0, 4, 5, + 1, 2, 2, 0, 1, 3, 1, 2, 3, 3, + 3, 3, 3, 3, 1, 4, 3, 4, 5, 4, + 5, 4, 5, 2, 4, 1, 1, 0, 1, 4, + 5, 4, 0, 2, 2, 2, 1, 1, 0, 4, + 2, 1, 2, 2, 4, 2, 6, 2, 1, 3, + 4, 0, 2, 0, 2, 0, 1, 3, 3, 2, + 0, 2, 4, 1, 1, 1, 0, 2, 3, 5, + 6, 2, 3, 5, 5, 3, 4, 0, 1, 1, + 1, 1, 1, 2, 4, 1, 1, 1, 1, 2, + 3, 0, 1, 1, 1, 1, 1, 2, 2, 2, + 2, 2, 1, 3, 0, 1, 1, 1, 1, 5, + 2, 1, 1, 1, 1, 4, 1, 2, 2, 1, + 3, 3, 2, 1, 0, 5, 2, 5, 2, 1, + 3, 3, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, - 3, 3, 3, 3, 3, 3, 0, 1, 3, 3, - 5, 2, 2, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, - 3, 2, 2, 3, 3, 5, 4, 6, 3, 5, - 4, 6, 4, 6, 5, 7, 3, 2, 4, 3, - 2, 1, 3, 3, 3, 3, 3, 4, 3, 4, - 3, 4, 5, 6, 6, 7, 6, 7, 6, 7, - 3, 4, 4, 6, 1, 4, 1, 3, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, + 3, 3, 3, 3, 0, 1, 3, 3, 5, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 2, 2, 3, 3, 2, + 2, 3, 3, 5, 4, 6, 3, 5, 4, 6, + 4, 6, 5, 7, 3, 2, 4, 3, 2, 1, + 3, 3, 3, 3, 3, 3, 4, 3, 4, 3, + 4, 5, 6, 6, 7, 6, 7, 6, 7, 3, + 4, 4, 6, 2, 1, 4, 1, 3, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 5, 6, 6, 7, 1, 1, 2, 2, 2, 4, 1, 2, 1, 2, @@ -254890,43 +272921,47 @@ static const yytype_uint8 yyr2[] = 1, 1, 1, 5, 1, 1, 4, 1, 4, 1, 4, 1, 4, 1, 1, 1, 1, 1, 1, 6, 6, 4, 4, 4, 4, 6, 5, 5, 5, 4, - 6, 4, 5, 0, 5, 0, 1, 0, 2, 0, - 1, 3, 3, 2, 2, 0, 6, 1, 0, 3, - 0, 2, 2, 0, 1, 4, 2, 2, 2, 2, - 2, 4, 3, 1, 5, 3, 1, 3, 1, 2, + 6, 4, 5, 0, 5, 4, 0, 1, 0, 2, + 0, 1, 3, 3, 2, 2, 0, 6, 1, 0, + 3, 0, 2, 2, 0, 1, 4, 2, 2, 2, + 2, 2, 4, 3, 1, 5, 3, 1, 3, 1, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 4, 1, 4, 1, 4, 1, 2, 1, 2, 1, + 2, 1, 3, 1, 3, 1, 2, 1, 0, 1, + 3, 1, 3, 3, 1, 3, 3, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 4, 3, + 2, 3, 0, 3, 3, 2, 2, 1, 0, 2, + 2, 3, 2, 1, 1, 3, 5, 1, 2, 4, + 2, 0, 1, 0, 1, 2, 2, 3, 5, 1, + 0, 1, 2, 0, 2, 1, 0, 1, 0, 1, + 3, 1, 2, 3, 2, 1, 3, 5, 4, 2, + 1, 0, 3, 1, 3, 1, 2, 4, 2, 0, + 1, 3, 1, 2, 1, 3, 1, 2, 1, 1, + 1, 2, 1, 1, 2, 1, 1, 2, 7, 2, + 5, 3, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 3, 3, 0, 1, 1, + 1, 1, 1, 1, 1, 5, 3, 0, 1, 1, + 1, 1, 4, 7, 2, 0, 1, 1, 1, 1, + 13, 16, 1, 2, 0, 1, 0, 1, 0, 2, + 0, 1, 0, 6, 8, 6, 8, 6, 8, 2, + 1, 4, 3, 2, 4, 3, 5, 1, 0, 1, + 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, - 1, 4, 1, 4, 1, 2, 1, 2, 1, 2, - 1, 3, 1, 3, 1, 2, 1, 0, 1, 3, - 1, 3, 3, 1, 3, 3, 0, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 4, 3, 2, - 3, 0, 3, 3, 2, 2, 1, 0, 2, 2, - 3, 2, 1, 1, 3, 5, 1, 2, 4, 2, - 0, 1, 0, 1, 2, 2, 3, 5, 1, 0, - 1, 2, 0, 2, 1, 0, 1, 0, 1, 3, - 1, 2, 3, 2, 1, 3, 5, 4, 2, 1, - 0, 3, 1, 3, 1, 2, 4, 2, 0, 1, - 3, 1, 2, 1, 3, 1, 2, 1, 1, 1, - 2, 1, 1, 2, 1, 1, 2, 7, 2, 5, - 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, + 1, 1, 1, 1, 1, 2, 1, 1, 2, 3, + 3, 3, 1, 3, 3, 2, 3, 3, 3, 3, + 1, 1, 1, 1, 3, 5, 1, 1, 1, 1, + 3, 2, 2, 3, 1, 1, 4, 5, 5, 4, + 6, 1, 1, 1, 1, 1, 1, 0, 1, 3, + 1, 0, 7, 1, 2, 3, 2, 0, 2, 0, + 2, 4, 2, 1, 1, 1, 2, 3, 2, 2, + 2, 2, 3, 4, 2, 1, 1, 1, 1, 3, + 2, 9, 11, 12, 14, 3, 4, 4, 0, 7, + 10, 9, 2, 3, 0, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 3, 3, 0, 1, 1, 1, - 1, 1, 1, 1, 5, 3, 0, 1, 1, 1, - 1, 4, 7, 2, 0, 1, 1, 1, 1, 13, - 16, 1, 2, 0, 1, 0, 1, 0, 2, 0, - 1, 0, 6, 8, 6, 8, 6, 8, 2, 1, - 4, 3, 2, 4, 3, 5, 1, 0, 1, 1, - 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 3, 1, 1, 1, 1, 1, 1, 2, - 1, 1, 2, 3, 3, 3, 1, 3, 3, 2, - 3, 3, 3, 3, 1, 1, 1, 1, 3, 5, - 1, 1, 1, 1, 3, 2, 2, 3, 1, 1, - 4, 5, 5, 4, 6, 1, 1, 1, 1, 1, - 1, 0, 1, 3, 1, 0, 7, 1, 2, 3, - 2, 0, 2, 0, 2, 4, 2, 1, 1, 1, - 2, 3, 2, 2, 2, 2, 3, 4, 2, 1, - 1, 1, 1, 3, 2, 9, 11, 12, 14, 3, - 4, 4, 0, 7, 10, 9, 2, 3, 0, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -254984,7 +273019,9 @@ static const yytype_uint8 yyr2[] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -254992,3350 +273029,3588 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint16 yydefact[] = { - 130, 215, 0, 1184, 1183, 215, 0, 1159, 215, 430, - 352, 0, 1261, 0, 215, 0, 130, 0, 0, 0, - 0, 0, 0, 0, 0, 215, 497, 0, 1260, 215, - 0, 0, 1231, 0, 0, 0, 0, 0, 2, 4, + 130, 210, 0, 1210, 1209, 210, 0, 1160, 210, 425, + 347, 0, 1287, 0, 210, 0, 130, 0, 0, 0, + 0, 0, 0, 0, 0, 210, 494, 0, 1286, 210, + 0, 0, 1257, 0, 0, 0, 0, 0, 2, 4, 7, 18, 30, 26, 0, 17, 28, 15, 21, 6, - 32, 16, 20, 13, 33, 11, 31, 464, 451, 502, - 463, 129, 603, 467, 29, 14, 25, 5, 10, 23, - 24, 22, 1167, 36, 27, 34, 19, 8, 35, 37, - 1259, 9, 38, 12, 214, 213, 207, 0, 0, 0, - 0, 0, 208, 1097, 1280, 1281, 1282, 1283, 1284, 1285, - 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 1295, - 1640, 1296, 1297, 1298, 1587, 1588, 1641, 1589, 1590, 1299, - 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1591, 1592, 1307, - 1308, 1309, 1310, 1311, 1593, 1642, 1312, 1313, 1314, 1315, - 1316, 1317, 1643, 1318, 1319, 1320, 1321, 1322, 1323, 1324, - 1325, 1326, 1644, 1327, 1328, 1329, 1645, 1330, 1331, 1332, - 1333, 1334, 1335, 1336, 1594, 1595, 1337, 1338, 1339, 1340, - 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349, 1350, - 1351, 1352, 1353, 1354, 1355, 1356, 1357, 1358, 1359, 1360, - 1361, 1362, 1363, 1364, 1596, 1365, 1366, 1367, 1368, 1369, - 1597, 1370, 1371, 1372, 1598, 1373, 1374, 1375, 1646, 1647, - 1376, 1377, 1599, 1649, 1378, 1379, 1600, 1601, 1380, 1381, - 1382, 1383, 1384, 1385, 1386, 1387, 1650, 1388, 1389, 1390, - 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1651, 1602, - 1399, 1400, 1401, 1402, 1403, 1603, 1604, 1605, 1404, 1652, - 1653, 1405, 1654, 1406, 1407, 1408, 1409, 1410, 1411, 1412, - 1655, 1413, 1656, 1414, 1415, 1416, 1417, 1418, 1419, 1420, - 1421, 1606, 1422, 1423, 1424, 1425, 1426, 1427, 1428, 1429, - 1430, 1431, 1432, 1433, 1434, 1435, 1436, 1437, 1438, 1439, - 1607, 1658, 1608, 1440, 1441, 1442, 1609, 1443, 1444, 1659, - 1445, 1610, 1446, 1611, 1447, 1448, 1449, 1450, 1451, 1452, - 1453, 1454, 1455, 1612, 1660, 1456, 1661, 1613, 1457, 1458, - 1459, 1460, 1461, 1462, 1463, 1464, 1465, 1466, 1467, 1468, - 1614, 1469, 1470, 1615, 1471, 1472, 1473, 1474, 1475, 1476, - 1477, 1478, 1479, 1480, 1481, 1482, 1616, 1483, 1484, 1485, - 1486, 1487, 1488, 1489, 1490, 1491, 1492, 1493, 1494, 1495, - 1496, 1497, 1498, 1499, 1500, 1501, 1662, 1502, 1503, 1504, - 1617, 1505, 1506, 1507, 1508, 1509, 1510, 1511, 1512, 1513, - 1514, 1515, 1516, 1517, 1518, 1519, 1520, 1521, 1618, 1522, - 1523, 1524, 1663, 1525, 1526, 1619, 1527, 1528, 1529, 1530, - 1531, 1532, 1533, 1534, 1535, 1536, 1537, 1538, 1539, 1620, - 1540, 1621, 1541, 1542, 1543, 1544, 1665, 1545, 1546, 1547, - 1548, 1549, 1622, 1623, 1550, 1551, 1624, 1552, 1625, 1553, - 1554, 1626, 1555, 1556, 1557, 1558, 1559, 1560, 1561, 1562, - 1563, 1564, 1565, 1566, 1567, 1568, 1569, 1627, 1628, 1570, - 1666, 1571, 1572, 1573, 1574, 1575, 1576, 1577, 1578, 1579, - 1580, 1581, 1582, 1629, 1630, 1631, 1632, 1633, 1634, 1635, - 1636, 1637, 1638, 1639, 1583, 1584, 1585, 1586, 1264, 0, - 0, 1079, 1098, 1099, 1107, 210, 429, 130, 0, 0, - 0, 0, 0, 346, 345, 0, 1150, 351, 0, 0, - 1097, 101, 1599, 1606, 1471, 1620, 99, 1077, 1098, 0, - 372, 373, 0, 381, 0, 365, 370, 366, 0, 391, - 383, 392, 384, 364, 385, 374, 363, 0, 393, 0, - 368, 0, 0, 0, 211, 176, 352, 130, 0, 1172, - 1173, 1171, 1162, 1167, 1174, 1175, 0, 1158, 0, 0, - 1096, 1218, 1219, 1216, 1215, 165, 1126, 1248, 1622, 1550, - 1262, 1249, 1246, 1247, 212, 496, 494, 0, 1047, 1378, - 1416, 1509, 1520, 1622, 1192, 1196, 0, 209, 1627, 1253, - 0, 1254, 1101, 0, 468, 643, 1100, 1071, 1230, 0, - 1235, 0, 1485, 472, 475, 1116, 473, 464, 0, 1, - 130, 0, 0, 0, 493, 493, 0, 493, 0, 456, - 464, 459, 463, 604, 1166, 1244, 1258, 1622, 1550, 1252, - 1255, 1386, 0, 0, 1386, 0, 1386, 0, 1386, 0, - 0, 1039, 0, 1040, 1080, 1128, 1129, 1127, 0, 1130, - 317, 350, 349, 348, 347, 352, 1386, 1134, 1111, 0, - 398, 399, 0, 0, 0, 0, 0, 1145, 102, 100, - 379, 380, 0, 371, 367, 369, 0, 1108, 1667, 697, - 1668, 726, 704, 726, 726, 1669, 1670, 1671, 1672, 693, - 693, 1352, 706, 1673, 1674, 1675, 1386, 1676, 1677, 694, - 695, 731, 1678, 1679, 1680, 1681, 1682, 0, 0, 1683, - 726, 1684, 693, 1685, 1686, 698, 1687, 665, 0, 1688, - 696, 666, 1689, 734, 734, 1690, 721, 1691, 390, 0, - 394, 679, 680, 681, 682, 707, 708, 683, 713, 714, - 718, 684, 766, 693, 1109, 1110, 1386, 390, 386, 1386, - 390, 1073, 1386, 0, 0, 172, 0, 0, 1164, 1176, - 1692, 1693, 1694, 1695, 1697, 1696, 1698, 1699, 1700, 1701, - 1702, 1703, 1704, 1705, 1706, 1707, 1710, 1708, 1709, 1711, - 1712, 1713, 1714, 1715, 1716, 1717, 1718, 1719, 1720, 1721, - 1722, 1723, 1724, 1725, 1726, 1727, 1728, 1729, 1730, 1731, - 1732, 1733, 1734, 1735, 1736, 1737, 1738, 1739, 1740, 1741, - 1742, 1743, 1744, 1190, 0, 1191, 1181, 1170, 1177, 1178, - 130, 428, 1217, 1161, 0, 0, 0, 0, 1250, 0, - 0, 0, 1082, 1084, 1085, 968, 1095, 1042, 0, 1588, - 1589, 1590, 1032, 0, 1591, 1592, 1593, 1642, 897, 884, - 893, 898, 885, 887, 894, 1594, 1595, 834, 1596, 1597, - 1093, 1598, 1600, 1601, 1603, 1604, 1605, 889, 891, 1607, - 1608, 0, 1094, 1610, 1611, 1452, 1613, 1614, 1616, 1617, - 895, 1619, 1621, 1622, 1623, 1624, 1625, 1092, 1626, 896, - 1628, 0, 0, 0, 1060, 987, 0, 0, 0, 1042, - 868, 0, 0, 687, 688, 709, 710, 689, 715, 716, - 690, 0, 1054, 767, 913, 1042, 880, 943, 811, 0, - 866, 860, 1050, 479, 1048, 0, 861, 1081, 1042, 1033, - 479, 1046, 1195, 1193, 1199, 1194, 0, 0, 0, 0, - 0, 645, 644, 1072, 1229, 1227, 1228, 1226, 1225, 1232, - 0, 1234, 1167, 982, 984, 0, 1033, 474, 0, 0, - 0, 454, 453, 3, 0, 0, 1237, 0, 491, 492, - 0, 0, 0, 0, 0, 0, 0, 0, 588, 518, - 519, 521, 585, 589, 597, 0, 460, 0, 1116, 1256, - 0, 0, 0, 117, 117, 0, 0, 0, 0, 0, - 93, 42, 86, 0, 0, 0, 0, 190, 203, 0, - 0, 0, 0, 0, 200, 0, 0, 183, 44, 177, - 179, 0, 117, 0, 40, 0, 0, 0, 46, 1097, - 0, 1640, 1641, 1642, 1643, 1644, 898, 0, 1646, 1647, - 1599, 1649, 1650, 1651, 1652, 1653, 1654, 1655, 1656, 1606, - 1658, 1659, 1660, 1661, 1662, 1663, 1620, 1665, 1626, 0, - 1666, 0, 872, 990, 502, 988, 1117, 0, 1098, 1104, - 1038, 0, 1118, 1773, 1774, 1775, 1776, 1777, 1778, 1779, - 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, 1789, - 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, 1799, - 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809, - 1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, - 1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829, - 1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839, - 1840, 1841, 1842, 1843, 1844, 1845, 1732, 1846, 1847, 1848, - 1849, 1850, 1035, 1078, 1120, 1119, 1121, 1041, 0, 0, - 426, 0, 0, 1131, 0, 1112, 0, 0, 1386, 171, - 1386, 317, 0, 317, 0, 1144, 1147, 382, 378, 376, - 375, 377, 725, 712, 720, 719, 0, 702, 701, 700, - 0, 699, 0, 0, 726, 726, 724, 703, 679, 0, - 0, 0, 730, 0, 728, 388, 389, 0, 361, 0, - 673, 669, 0, 739, 740, 741, 742, 749, 750, 747, - 748, 743, 744, 737, 738, 745, 746, 735, 736, 0, - 751, 752, 753, 754, 755, 756, 757, 758, 685, 691, - 0, 0, 356, 0, 0, 358, 0, 0, 0, 352, - 0, 130, 0, 184, 1186, 1187, 1185, 0, 0, 1169, - 187, 204, 1180, 1189, 1179, 1188, 1168, 1163, 0, 1160, - 417, 1205, 1204, 1213, 166, 0, 993, 0, 130, 1251, - 1263, 0, 864, 987, 1031, 0, 0, 0, 0, 0, - 0, 870, 996, 0, 0, 791, 0, 0, 0, 1011, - 0, 1017, 0, 0, 0, 792, 771, 772, 0, 1059, - 1068, 986, 0, 868, 982, 0, 946, 948, 0, 1100, - 0, 862, 863, 869, 0, 1088, 0, 766, 766, 1053, - 968, 0, 0, 961, 965, 966, 967, 0, 0, 0, - 1045, 0, 976, 978, 0, 0, 807, 974, 0, 810, - 0, 0, 0, 0, 962, 963, 964, 955, 956, 957, - 958, 959, 960, 972, 954, 788, 0, 0, 915, 867, - 0, 787, 1051, 0, 606, 0, 1086, 1083, 0, 1034, - 606, 1207, 1211, 1212, 1210, 0, 1206, 1198, 1197, 1202, - 1200, 1203, 1201, 0, 1223, 0, 1220, 985, 601, 476, - 0, 0, 1243, 0, 124, 0, 1238, 0, 471, 470, - 512, 512, 503, 506, 512, 469, 560, 561, 0, 0, - 0, 0, 594, 592, 1082, 1095, 548, 522, 547, 0, - 0, 526, 0, 552, 767, 587, 458, 516, 517, 520, - 457, 0, 590, 0, 600, 588, 521, 0, 1245, 1257, - 0, 0, 0, 0, 0, 1386, 0, 0, 77, 58, - 269, 668, 116, 0, 0, 0, 0, 0, 0, 0, - 85, 82, 83, 84, 0, 0, 0, 0, 188, 189, - 202, 0, 193, 194, 191, 195, 196, 0, 0, 181, - 182, 0, 0, 0, 0, 180, 0, 0, 0, 0, - 0, 0, 0, 0, 502, 502, 502, 878, 0, 500, - 501, 0, 0, 1036, 1039, 416, 325, 0, 315, 0, - 0, 0, 0, 0, 0, 352, 1137, 1135, 1133, 1136, - 1138, 1113, 0, 0, 0, 160, 0, 0, 168, 170, - 0, 314, 288, 0, 1149, 0, 0, 1386, 1146, 304, - 0, 0, 0, 0, 390, 0, 723, 722, 674, 670, - 0, 0, 0, 0, 395, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 390, 387, 390, 1074, 0, - 390, 175, 0, 1386, 317, 0, 1165, 1182, 185, 205, - 186, 206, 449, 0, 423, 431, 436, 414, 0, 414, - 0, 433, 437, 414, 432, 414, 427, 0, 167, 0, - 1125, 0, 1124, 0, 1043, 0, 0, 1030, 1026, 0, - 0, 0, 0, 0, 997, 998, 999, 1000, 1001, 1002, - 1003, 1004, 1005, 0, 0, 1006, 0, 0, 0, 953, - 961, 965, 966, 967, 962, 963, 964, 955, 956, 957, - 958, 959, 960, 980, 0, 0, 0, 0, 0, 0, - 0, 0, 836, 0, 0, 942, 0, 982, 1016, 0, - 0, 0, 0, 0, 0, 982, 1022, 0, 0, 0, - 1058, 0, 1055, 813, 1042, 0, 949, 812, 0, 0, - 0, 1090, 1091, 768, 814, 779, 783, 784, 785, 789, - 1123, 1122, 1052, 0, 1044, 0, 0, 769, 793, 798, - 0, 1023, 830, 0, 818, 0, 806, 0, 816, 820, - 794, 809, 0, 790, 0, 1045, 977, 979, 0, 975, - 0, 780, 781, 782, 773, 774, 775, 776, 777, 778, - 786, 952, 950, 951, 0, 0, 0, 917, 0, 0, - 815, 1049, 1378, 1416, 0, 490, 490, 490, 478, 488, - 0, 657, 502, 1060, 657, 0, 766, 646, 1116, 1233, - 1221, 1222, 983, 1115, 130, 0, 1241, 0, 0, 0, - 136, 119, 0, 1239, 0, 152, 154, 606, 0, 1042, - 510, 511, 515, 515, 0, 0, 515, 1617, 1505, 0, - 0, 0, 0, 553, 595, 0, 586, 550, 551, 0, - 549, 1082, 554, 1081, 555, 558, 559, 527, 596, 1069, - 598, 0, 591, 462, 461, 602, 0, 43, 0, 1386, - 60, 0, 0, 0, 0, 0, 0, 219, 0, 319, - 219, 98, 1386, 390, 1386, 390, 1284, 1353, 1521, 0, - 56, 89, 0, 293, 110, 0, 278, 322, 79, 94, - 103, 0, 0, 45, 178, 192, 197, 106, 201, 198, - 1154, 199, 117, 0, 41, 0, 104, 0, 1152, 0, - 0, 47, 108, 1156, 500, 500, 500, 0, 989, 0, - 0, 0, 991, 992, 1038, 0, 415, 0, 316, 0, - 425, 405, 406, 416, 0, 317, 0, 317, 1134, 0, - 0, 1114, 162, 0, 0, 0, 0, 307, 305, 338, - 0, 312, 306, 315, 0, 0, 264, 0, 1278, 0, - 0, 400, 0, 0, 0, 0, 0, 692, 705, 362, - 679, 0, 733, 732, 734, 734, 679, 0, 663, 0, - 677, 0, 717, 686, 759, 760, 761, 762, 763, 764, - 765, 355, 357, 0, 359, 0, 0, 0, 418, 0, - 421, 0, 420, 424, 419, 413, 0, 444, 0, 0, - 0, 0, 0, 0, 1214, 994, 495, 835, 0, 0, - 1027, 0, 0, 911, 0, 886, 888, 901, 0, 890, - 892, 0, 969, 0, 0, 0, 902, 838, 839, 0, + 32, 16, 20, 13, 33, 11, 31, 459, 446, 499, + 458, 129, 600, 462, 29, 14, 25, 5, 10, 23, + 24, 22, 1168, 36, 27, 34, 19, 8, 35, 37, + 1285, 9, 38, 12, 209, 208, 202, 0, 0, 0, + 0, 0, 203, 1098, 1306, 1307, 1308, 1309, 1310, 1311, + 1312, 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1321, + 1666, 1322, 1323, 1324, 1613, 1614, 1667, 1615, 1616, 1325, + 1326, 1327, 1328, 1329, 1330, 1331, 1332, 1617, 1618, 1333, + 1334, 1335, 1336, 1337, 1619, 1668, 1338, 1339, 1340, 1341, + 1342, 1343, 1669, 1344, 1345, 1346, 1347, 1348, 1349, 1350, + 1351, 1352, 1670, 1353, 1354, 1355, 1671, 1672, 1673, 1674, + 1675, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1620, 1621, + 1363, 1364, 1365, 1366, 1367, 1368, 1369, 1370, 1371, 1372, + 1373, 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, + 1383, 1384, 1385, 1386, 1387, 1388, 1389, 1390, 1622, 1391, + 1392, 1393, 1394, 1395, 1623, 1396, 1397, 1398, 1624, 1399, + 1400, 1401, 1676, 1677, 1402, 1403, 1625, 1679, 1404, 1405, + 1626, 1627, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1413, + 1680, 1414, 1415, 1416, 1417, 1418, 1419, 1420, 1421, 1422, + 1423, 1424, 1681, 1628, 1425, 1426, 1427, 1428, 1429, 1629, + 1630, 1631, 1430, 1682, 1683, 1431, 1684, 1432, 1433, 1434, + 1435, 1436, 1437, 1438, 1685, 1439, 1686, 1440, 1441, 1442, + 1443, 1444, 1445, 1446, 1447, 1632, 1448, 1449, 1450, 1451, + 1452, 1453, 1454, 1455, 1456, 1457, 1458, 1459, 1460, 1461, + 1462, 1463, 1464, 1465, 1633, 1688, 1634, 1466, 1467, 1468, + 1635, 1469, 1470, 1689, 1471, 1636, 1472, 1637, 1473, 1474, + 1475, 1476, 1477, 1478, 1479, 1480, 1481, 1638, 1690, 1482, + 1691, 1639, 1483, 1484, 1485, 1486, 1487, 1488, 1489, 1490, + 1491, 1492, 1493, 1494, 1640, 1495, 1496, 1641, 1497, 1498, + 1499, 1500, 1501, 1502, 1503, 1504, 1505, 1506, 1507, 1508, + 1642, 1509, 1510, 1511, 1512, 1513, 1514, 1515, 1516, 1517, + 1518, 1519, 1520, 1521, 1522, 1523, 1524, 1525, 1526, 1527, + 1692, 1528, 1529, 1530, 1643, 1531, 1532, 1533, 1534, 1535, + 1536, 1537, 1538, 1539, 1540, 1541, 1542, 1543, 1544, 1545, + 1546, 1693, 1547, 1644, 1548, 1549, 1550, 1694, 1551, 1552, + 1645, 1553, 1554, 1555, 1556, 1557, 1558, 1559, 1560, 1561, + 1562, 1563, 1564, 1565, 1646, 1566, 1647, 1567, 1568, 1569, + 1570, 1696, 1571, 1572, 1573, 1574, 1575, 1648, 1649, 1576, + 1577, 1650, 1578, 1651, 1579, 1580, 1652, 1581, 1582, 1583, + 1584, 1585, 1586, 1587, 1588, 1589, 1590, 1697, 1591, 1592, + 1593, 1594, 1595, 1653, 1654, 1596, 1698, 1597, 1598, 1599, + 1600, 1601, 1602, 1603, 1604, 1605, 1606, 1607, 1608, 1655, + 1656, 1657, 1658, 1659, 1660, 1661, 1662, 1663, 1664, 1665, + 1609, 1610, 1611, 1612, 1290, 0, 0, 1080, 1099, 1100, + 1108, 205, 424, 0, 0, 0, 0, 0, 0, 341, + 340, 0, 1151, 346, 0, 0, 1098, 1102, 101, 1625, + 1632, 1497, 1646, 99, 1101, 1078, 1099, 0, 367, 368, + 0, 376, 0, 360, 365, 361, 0, 386, 378, 387, + 379, 359, 380, 369, 358, 0, 388, 0, 363, 0, + 0, 0, 206, 171, 130, 0, 1174, 1184, 1193, 1189, + 1183, 1191, 1181, 1187, 1173, 1195, 1182, 1186, 1179, 1196, + 1177, 1194, 1192, 1180, 1188, 1172, 1176, 1163, 1168, 1199, + 1190, 1197, 1185, 1198, 1200, 1175, 1201, 1178, 0, 1159, + 0, 0, 1097, 1244, 1245, 1242, 1241, 160, 1127, 1274, + 1648, 1576, 1288, 1275, 1272, 1273, 207, 493, 491, 0, + 1048, 1404, 1442, 1535, 1546, 1648, 1218, 1222, 0, 204, + 1653, 1279, 0, 1280, 0, 463, 641, 1101, 1072, 1256, + 0, 1261, 0, 1511, 468, 471, 1117, 469, 459, 0, + 1, 130, 0, 0, 0, 489, 489, 0, 489, 0, + 451, 459, 454, 458, 601, 1167, 1270, 1284, 1648, 1576, + 1278, 1281, 1412, 0, 0, 1412, 0, 1412, 0, 1412, + 0, 0, 1040, 0, 1041, 1081, 0, 312, 345, 344, + 343, 342, 347, 1412, 1135, 1112, 0, 393, 394, 0, + 0, 0, 0, 0, 1146, 102, 100, 374, 375, 0, + 366, 362, 364, 0, 1109, 1699, 695, 1700, 724, 702, + 724, 724, 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, + 691, 691, 1378, 704, 1709, 1710, 1711, 1412, 1712, 1713, + 692, 693, 729, 1714, 1715, 1716, 1717, 1718, 0, 0, + 1719, 724, 1720, 691, 1721, 1722, 696, 1723, 663, 1724, + 0, 1725, 694, 664, 1726, 732, 732, 1727, 1728, 719, + 1729, 385, 0, 389, 677, 678, 679, 680, 705, 706, + 681, 711, 712, 716, 682, 764, 691, 1110, 1111, 1412, + 385, 381, 1412, 385, 1074, 1412, 0, 0, 167, 1165, + 1202, 1730, 1731, 1732, 1733, 1734, 1735, 1737, 1736, 1738, + 1739, 1740, 1741, 1742, 1743, 1744, 1745, 1746, 1747, 1748, + 1749, 1750, 1751, 1752, 1753, 1754, 1755, 1756, 1757, 1758, + 1759, 1760, 1763, 1761, 1762, 1764, 1765, 1766, 1767, 1768, + 1769, 1770, 1771, 1772, 1773, 1774, 1775, 1776, 1778, 1777, + 1779, 1780, 1781, 1782, 1783, 1784, 1785, 1786, 1787, 1788, + 1789, 1790, 1791, 1792, 1793, 1794, 1795, 1796, 1797, 1798, + 1799, 1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, + 1809, 1810, 1811, 1812, 1216, 0, 1217, 1207, 1171, 1203, + 1204, 130, 423, 1243, 1162, 0, 0, 0, 0, 1276, + 0, 0, 0, 1083, 1085, 1086, 969, 1096, 1043, 0, + 1614, 1615, 1616, 1033, 0, 1617, 1618, 1619, 1668, 897, + 884, 893, 898, 885, 887, 894, 1620, 1621, 834, 1622, + 1623, 1094, 1624, 1626, 1627, 1629, 1630, 1631, 889, 891, + 1633, 1634, 0, 1095, 1636, 1637, 1478, 1639, 1640, 1642, + 1643, 895, 1645, 1647, 1648, 1649, 1650, 1651, 1093, 1652, + 896, 1654, 0, 0, 0, 1061, 988, 0, 0, 0, + 1043, 868, 0, 0, 685, 686, 707, 708, 687, 713, + 714, 688, 0, 1055, 765, 913, 1043, 880, 944, 809, + 0, 866, 860, 1051, 475, 1049, 0, 861, 1082, 1043, + 1034, 475, 1047, 1221, 1219, 1225, 1220, 0, 0, 0, + 0, 0, 643, 642, 1073, 1255, 1253, 1254, 1252, 1251, + 1258, 0, 1260, 1168, 983, 985, 0, 1034, 470, 0, + 0, 0, 449, 448, 3, 0, 0, 1263, 0, 487, + 488, 0, 0, 0, 0, 0, 0, 0, 0, 585, + 515, 516, 518, 582, 586, 594, 0, 455, 0, 1117, + 1282, 0, 0, 0, 117, 117, 0, 0, 0, 0, + 0, 93, 42, 86, 0, 0, 0, 0, 185, 198, + 0, 0, 0, 0, 0, 195, 0, 0, 178, 44, + 172, 174, 0, 117, 0, 40, 0, 0, 0, 46, + 1098, 0, 1666, 1667, 1668, 1669, 1670, 897, 884, 893, + 898, 894, 0, 1676, 1677, 1625, 1679, 1680, 1681, 1682, + 1683, 1684, 1685, 1686, 1632, 1688, 1689, 1690, 1691, 1692, + 895, 1694, 1646, 1696, 1652, 896, 0, 1698, 0, 872, + 991, 499, 989, 1118, 0, 1099, 1105, 1039, 0, 1119, + 1847, 1848, 1849, 1850, 1851, 1852, 1853, 1854, 1855, 1856, + 1857, 1858, 1859, 1860, 1861, 1862, 1863, 1864, 1865, 1866, + 1867, 1868, 1869, 1870, 1871, 1872, 1873, 1874, 1875, 1876, + 1877, 1878, 1879, 1880, 1881, 1882, 1883, 1884, 1885, 1886, + 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1895, 1896, + 1897, 1898, 1899, 1900, 1901, 1902, 1903, 1904, 1905, 1906, + 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1799, 1914, 1915, + 1916, 1917, 1918, 1036, 1079, 1121, 1120, 1122, 1042, 0, + 0, 421, 0, 0, 1132, 0, 1113, 0, 0, 1412, + 166, 1412, 312, 0, 312, 0, 1145, 1148, 377, 373, + 371, 370, 372, 723, 710, 718, 717, 988, 700, 699, + 698, 0, 697, 0, 0, 724, 724, 722, 701, 677, + 0, 0, 0, 728, 0, 726, 383, 384, 0, 356, + 0, 671, 667, 0, 737, 738, 739, 740, 747, 748, + 745, 746, 741, 742, 735, 736, 743, 744, 733, 734, + 0, 749, 750, 751, 752, 753, 754, 755, 756, 683, + 689, 0, 0, 351, 0, 0, 353, 0, 0, 0, + 130, 0, 179, 1212, 1213, 1211, 0, 0, 1170, 182, + 199, 1206, 1215, 1205, 1214, 1169, 1164, 0, 1161, 412, + 1231, 1230, 1239, 161, 0, 994, 0, 130, 1277, 1289, + 0, 864, 988, 833, 1032, 0, 0, 0, 0, 0, + 0, 870, 997, 0, 0, 789, 0, 0, 0, 1012, + 0, 1018, 0, 0, 0, 790, 769, 770, 0, 1060, + 1069, 987, 0, 868, 983, 0, 947, 949, 0, 0, + 862, 863, 869, 0, 1089, 0, 764, 764, 1054, 969, + 0, 962, 0, 0, 966, 967, 968, 0, 0, 0, + 1046, 0, 977, 979, 0, 0, 805, 975, 0, 808, + 0, 0, 0, 0, 963, 964, 965, 956, 957, 958, + 959, 960, 961, 973, 955, 786, 0, 0, 916, 867, + 0, 785, 1052, 0, 603, 0, 1087, 1084, 0, 1035, + 603, 1233, 1237, 1238, 1236, 0, 1232, 1224, 1223, 1228, + 1226, 1229, 1227, 0, 1249, 0, 1246, 986, 598, 472, + 1076, 0, 0, 1269, 0, 124, 0, 1264, 0, 467, + 466, 509, 509, 500, 503, 509, 0, 465, 0, 557, + 558, 0, 0, 0, 0, 591, 589, 1083, 1096, 545, + 519, 544, 0, 0, 523, 0, 549, 765, 584, 453, + 513, 514, 517, 452, 0, 587, 0, 597, 585, 518, + 0, 1271, 1283, 0, 0, 0, 0, 0, 1412, 0, + 0, 77, 58, 264, 666, 116, 0, 0, 0, 0, + 0, 0, 0, 85, 82, 83, 84, 0, 0, 0, + 0, 183, 184, 197, 0, 188, 189, 186, 190, 191, + 0, 0, 176, 177, 0, 0, 0, 0, 175, 0, + 0, 0, 0, 0, 0, 0, 0, 499, 499, 499, + 878, 0, 497, 498, 0, 0, 1037, 1040, 411, 320, + 0, 310, 0, 0, 0, 0, 0, 0, 347, 1138, + 1136, 1134, 1137, 1139, 1114, 0, 159, 0, 0, 163, + 165, 0, 309, 283, 0, 1150, 0, 0, 1412, 1147, + 299, 0, 0, 0, 0, 385, 0, 721, 720, 672, + 668, 0, 0, 0, 0, 390, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 385, 382, 385, 1075, + 0, 385, 170, 1166, 1208, 180, 200, 181, 201, 444, + 0, 418, 426, 431, 409, 0, 409, 0, 428, 432, + 409, 427, 409, 422, 0, 162, 0, 1126, 0, 1129, + 1130, 1128, 1125, 1131, 0, 1044, 0, 0, 1031, 1027, + 0, 0, 0, 0, 0, 998, 999, 1000, 1001, 1002, + 1003, 1004, 1005, 1006, 0, 0, 1007, 0, 0, 0, + 954, 962, 966, 967, 968, 963, 964, 965, 956, 957, + 958, 959, 960, 961, 981, 0, 0, 0, 0, 0, + 0, 0, 0, 836, 0, 0, 943, 0, 983, 1017, + 0, 0, 0, 0, 0, 0, 983, 1023, 0, 0, + 0, 1059, 0, 1056, 811, 1043, 0, 950, 810, 0, + 0, 0, 1091, 1092, 766, 777, 812, 813, 781, 782, + 783, 787, 1124, 1123, 1053, 0, 1045, 0, 0, 767, + 791, 796, 0, 1024, 829, 0, 817, 0, 804, 0, + 815, 819, 792, 807, 0, 788, 0, 1046, 978, 980, + 0, 976, 0, 778, 779, 780, 771, 772, 773, 774, + 775, 776, 784, 953, 951, 952, 0, 0, 0, 918, + 0, 0, 814, 1050, 1404, 1442, 0, 486, 486, 486, + 474, 484, 0, 655, 499, 1061, 655, 0, 764, 644, + 1117, 1259, 1247, 1248, 984, 1077, 1116, 130, 0, 1267, + 0, 0, 0, 136, 119, 0, 1265, 0, 152, 154, + 603, 0, 1043, 507, 508, 512, 512, 0, 0, 512, + 490, 464, 1643, 1531, 0, 0, 0, 0, 550, 592, + 0, 583, 547, 548, 0, 546, 1083, 551, 1082, 552, + 555, 556, 524, 593, 1070, 595, 0, 588, 457, 456, + 599, 0, 43, 0, 1412, 60, 0, 0, 0, 0, + 0, 0, 214, 0, 314, 214, 98, 1412, 385, 1412, + 385, 1310, 1379, 1547, 0, 56, 89, 0, 288, 110, + 0, 273, 317, 79, 94, 103, 0, 0, 45, 173, + 187, 192, 106, 196, 193, 1155, 194, 117, 0, 41, + 0, 104, 0, 1153, 0, 0, 47, 108, 1157, 497, + 497, 497, 0, 990, 0, 0, 0, 992, 993, 1039, + 0, 410, 0, 311, 0, 420, 400, 401, 411, 0, + 312, 0, 312, 1135, 0, 0, 1115, 0, 0, 0, + 0, 302, 300, 333, 0, 307, 301, 310, 0, 0, + 259, 0, 1304, 0, 0, 395, 0, 0, 0, 0, + 0, 690, 703, 357, 677, 0, 731, 730, 732, 732, + 677, 0, 661, 0, 675, 0, 715, 684, 757, 758, + 759, 760, 761, 762, 763, 350, 352, 0, 354, 413, + 0, 416, 0, 415, 419, 414, 408, 0, 439, 0, + 0, 0, 0, 0, 0, 1240, 995, 492, 835, 0, + 0, 1028, 0, 0, 911, 0, 886, 888, 901, 0, + 890, 892, 0, 970, 0, 0, 0, 902, 838, 839, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 855, 854, 903, - 941, 0, 0, 1014, 1015, 0, 904, 0, 0, 1021, - 0, 0, 0, 909, 0, 1075, 0, 0, 0, 1067, - 865, 983, 947, 945, 871, 766, 0, 0, 0, 0, - 0, 0, 0, 819, 808, 0, 817, 821, 0, 0, - 0, 802, 0, 0, 800, 831, 796, 0, 0, 832, - 0, 0, 916, 925, 490, 490, 490, 490, 487, 489, - 0, 0, 0, 0, 1505, 0, 629, 609, 605, 607, - 616, 629, 634, 881, 655, 882, 1100, 0, 565, 500, - 1068, 565, 0, 1208, 1224, 0, 1242, 0, 141, 123, - 143, 142, 0, 150, 0, 1042, 0, 141, 125, 0, - 144, 155, 1241, 0, 158, 0, 504, 505, 507, 0, - 970, 515, 509, 557, 556, 0, 525, 593, 523, 0, - 599, 0, 0, 0, 268, 0, 0, 0, 219, 0, - 327, 0, 334, 0, 0, 319, 300, 78, 0, 0, - 0, 52, 97, 70, 62, 48, 76, 0, 0, 81, - 0, 74, 91, 92, 90, 95, 0, 254, 229, 265, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 502, 498, 499, 873, - 1037, 447, 448, 183, 446, 326, 0, 0, 314, 0, - 1149, 1132, 352, 0, 0, 161, 163, 0, 171, 317, - 0, 292, 288, 313, 286, 285, 287, 0, 1279, 176, - 0, 1273, 1148, 0, 401, 0, 397, 0, 1143, 711, - 676, 0, 729, 727, 675, 0, 671, 678, 390, 0, - 450, 0, 409, 445, 434, 439, 0, 443, 441, 440, - 435, 438, 0, 1029, 1025, 0, 883, 995, 0, 981, - 1009, 1008, 837, 846, 850, 851, 852, 1010, 0, 0, - 0, 847, 848, 849, 840, 841, 842, 843, 844, 845, - 853, 1019, 1018, 1012, 1013, 0, 906, 907, 908, 1020, - 0, 1076, 1057, 982, 1062, 1064, 0, 0, 944, 1089, - 770, 0, 0, 799, 1024, 822, 0, 0, 0, 795, - 969, 0, 0, 0, 0, 0, 804, 0, 0, 0, - 0, 879, 0, 0, 0, 0, 481, 480, 486, 629, - 634, 0, 464, 0, 616, 0, 628, 544, 627, 610, - 0, 640, 638, 0, 640, 0, 640, 0, 544, 0, - 630, 544, 627, 0, 647, 1072, 656, 0, 582, 0, - 1056, 582, 0, 477, 1240, 0, 1236, 0, 0, 0, - 131, 128, 118, 0, 0, 153, 141, 132, 513, 514, - 0, 508, 524, 1070, 111, 219, 0, 0, 59, 0, - 336, 280, 328, 311, 295, 0, 0, 0, 220, 0, - 353, 0, 0, 301, 0, 0, 0, 0, 281, 0, - 0, 240, 0, 0, 311, 0, 318, 236, 237, 0, - 51, 71, 0, 67, 0, 96, 0, 0, 0, 0, - 0, 54, 66, 0, 49, 0, 390, 390, 57, 279, - 1108, 1667, 1668, 1669, 1670, 1671, 1672, 1673, 1674, 1753, - 1675, 1676, 1677, 1678, 1679, 1680, 1681, 1682, 1762, 1683, - 226, 1684, 1452, 1685, 1686, 1687, 0, 1688, 666, 1689, - 1690, 1691, 955, 956, 224, 321, 221, 329, 223, 225, - 0, 1109, 222, 324, 107, 1155, 0, 105, 0, 1153, - 114, 112, 109, 1157, 876, 877, 874, 500, 428, 408, - 0, 0, 1278, 0, 0, 1386, 0, 159, 0, 1149, - 169, 314, 0, 344, 264, 339, 0, 1278, 1276, 0, - 1272, 396, 0, 0, 0, 672, 664, 360, 0, 422, - 0, 442, 1028, 899, 910, 1007, 0, 0, 0, 0, - 905, 900, 1065, 1066, 1061, 828, 826, 823, 0, 824, - 803, 0, 0, 801, 797, 0, 833, 912, 0, 928, - 923, 924, 485, 484, 483, 482, 615, 613, 0, 618, - 1100, 625, 537, 543, 614, 0, 608, 0, 639, 635, - 0, 636, 0, 0, 637, 0, 611, 0, 1100, 612, - 0, 654, 0, 0, 919, 873, 919, 1209, 140, 120, - 0, 121, 151, 0, 0, 0, 0, 145, 402, 0, - 332, 61, 0, 311, 0, 219, 297, 296, 299, 294, - 298, 0, 354, 0, 0, 238, 0, 245, 283, 284, - 282, 239, 311, 317, 241, 0, 0, 0, 63, 53, - 50, 55, 64, 0, 0, 65, 68, 662, 80, 73, - 1762, 1769, 0, 0, 0, 0, 0, 0, 404, 411, - 183, 0, 0, 288, 1275, 0, 0, 0, 314, 164, - 0, 0, 0, 1278, 0, 0, 216, 0, 261, 0, - 173, 1277, 0, 1265, 0, 1141, 1142, 0, 0, 410, - 856, 0, 0, 0, 1063, 825, 829, 827, 805, 914, - 930, 927, 650, 0, 653, 617, 0, 0, 532, 539, - 0, 542, 536, 0, 619, 0, 0, 621, 623, 0, - 0, 0, 658, 0, 0, 0, 1077, 563, 1328, 1600, - 1504, 564, 0, 568, 562, 566, 571, 573, 572, 574, - 570, 581, 0, 584, 1087, 584, 0, 0, 0, 0, - 156, 0, 147, 147, 0, 133, 971, 0, 219, 0, - 310, 333, 250, 228, 0, 0, 0, 235, 242, 343, - 244, 0, 72, 0, 88, 0, 0, 323, 115, 113, - 875, 428, 0, 1149, 264, 1272, 0, 0, 0, 288, - 176, 1274, 277, 270, 271, 272, 273, 274, 275, 276, - 291, 290, 262, 263, 0, 0, 0, 1143, 0, 857, - 0, 858, 0, 502, 655, 0, 0, 649, 0, 530, - 528, 531, 533, 529, 0, 0, 626, 642, 0, 622, - 620, 631, 0, 662, 0, 633, 0, 0, 0, 575, - 569, 918, 920, 0, 0, 535, 535, 0, 127, 0, - 657, 0, 0, 149, 149, 135, 0, 317, 335, 0, - 302, 309, 248, 247, 249, 253, 0, 251, 0, 267, - 0, 260, 228, 661, 0, 75, 0, 330, 403, 407, - 0, 218, 1266, 314, 0, 1272, 264, 1278, 0, 1269, - 0, 0, 1149, 859, 0, 933, 648, 651, 0, 624, - 0, 0, 0, 659, 660, 632, 0, 0, 0, 567, - 0, 0, 583, 0, 466, 465, 122, 147, 126, 157, - 146, 512, 148, 512, 0, 343, 289, 0, 0, 0, - 250, 0, 243, 340, 341, 342, 0, 256, 246, 257, - 69, 87, 331, 0, 314, 1267, 217, 174, 1270, 1271, - 0, 657, 929, 0, 0, 0, 0, 540, 0, 546, - 641, 577, 0, 576, 921, 922, 537, 149, 515, 515, - 657, 260, 303, 308, 227, 252, 266, 0, 0, 0, - 258, 0, 259, 1272, 0, 1139, 1587, 1329, 1557, 0, - 931, 934, 932, 926, 652, 0, 0, 538, 578, 534, - 512, 138, 137, 134, 219, 232, 0, 231, 0, 320, - 255, 1268, 1149, 0, 938, 937, 936, 940, 939, 541, - 0, 515, 337, 230, 234, 233, 657, 0, 0, 139, - 1140, 935, 545 + 0, 0, 0, 0, 0, 0, 0, 0, 855, 854, + 903, 942, 0, 0, 1015, 1016, 0, 904, 0, 0, + 1022, 0, 0, 0, 909, 0, 0, 0, 0, 1068, + 865, 984, 948, 946, 871, 764, 0, 0, 0, 0, + 0, 0, 0, 818, 806, 0, 816, 820, 0, 0, + 0, 800, 0, 0, 798, 830, 794, 0, 0, 831, + 0, 0, 917, 926, 486, 486, 486, 486, 483, 485, + 0, 0, 0, 0, 1531, 0, 627, 0, 606, 602, + 604, 614, 627, 632, 881, 653, 882, 1101, 0, 562, + 497, 1069, 562, 0, 1234, 1250, 0, 1268, 0, 141, + 123, 143, 142, 0, 150, 0, 1043, 0, 141, 125, + 0, 144, 155, 1267, 0, 158, 0, 501, 502, 504, + 0, 971, 512, 506, 554, 553, 0, 522, 590, 520, + 0, 596, 0, 0, 0, 263, 0, 0, 0, 214, + 0, 322, 0, 329, 0, 0, 314, 295, 78, 0, + 0, 0, 52, 97, 70, 62, 48, 76, 0, 0, + 81, 0, 74, 91, 92, 90, 95, 0, 249, 224, + 260, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 499, 495, 496, + 873, 1038, 442, 443, 178, 441, 321, 0, 0, 309, + 0, 1150, 1133, 347, 0, 0, 166, 312, 0, 287, + 283, 308, 281, 280, 282, 0, 1305, 171, 0, 1299, + 1149, 0, 396, 0, 392, 0, 1144, 709, 674, 0, + 727, 725, 673, 0, 669, 676, 385, 445, 0, 404, + 440, 429, 434, 0, 438, 436, 435, 430, 433, 0, + 1030, 1026, 0, 883, 996, 0, 982, 1010, 1009, 837, + 846, 850, 851, 852, 1011, 0, 0, 0, 847, 848, + 849, 840, 841, 842, 843, 844, 845, 853, 1020, 1019, + 1013, 1014, 0, 906, 907, 908, 1021, 0, 1058, 983, + 1063, 1065, 0, 0, 945, 1090, 768, 0, 0, 797, + 1025, 821, 0, 0, 0, 793, 970, 0, 0, 0, + 0, 0, 802, 0, 0, 0, 0, 0, 879, 0, + 0, 0, 0, 477, 476, 482, 627, 632, 0, 459, + 462, 0, 614, 0, 626, 541, 625, 541, 607, 0, + 638, 636, 0, 638, 0, 638, 0, 541, 0, 628, + 541, 625, 0, 645, 1073, 654, 0, 579, 0, 1057, + 579, 0, 473, 1266, 0, 1262, 0, 0, 0, 131, + 128, 118, 0, 0, 153, 141, 132, 510, 511, 0, + 505, 521, 1071, 111, 214, 0, 0, 59, 0, 331, + 275, 323, 306, 290, 0, 0, 0, 215, 0, 348, + 0, 0, 296, 0, 0, 0, 0, 276, 0, 0, + 235, 0, 0, 306, 0, 313, 231, 232, 0, 51, + 71, 0, 67, 0, 96, 0, 0, 0, 0, 0, + 54, 66, 0, 49, 0, 385, 385, 57, 274, 1109, + 1699, 1700, 1701, 1702, 1703, 1704, 1705, 1706, 1707, 1708, + 1709, 1710, 1825, 1711, 1712, 1713, 1714, 1715, 1716, 1717, + 1718, 1834, 1719, 221, 1720, 1478, 1721, 1722, 1723, 1724, + 0, 1725, 664, 1726, 1727, 1728, 1729, 956, 957, 219, + 316, 216, 324, 218, 220, 0, 1110, 217, 319, 107, + 1156, 0, 105, 0, 1154, 114, 112, 109, 1158, 876, + 877, 874, 497, 423, 403, 0, 0, 1304, 0, 0, + 1412, 0, 1150, 164, 309, 0, 339, 259, 334, 0, + 1304, 1302, 0, 1298, 391, 0, 0, 0, 670, 662, + 355, 417, 0, 437, 1029, 899, 910, 1008, 0, 0, + 0, 0, 905, 900, 1066, 1067, 1062, 827, 825, 822, + 0, 823, 801, 0, 0, 799, 795, 0, 832, 912, + 0, 915, 929, 924, 925, 481, 480, 479, 478, 613, + 611, 0, 616, 623, 534, 540, 612, 0, 610, 605, + 0, 637, 633, 0, 634, 0, 0, 635, 0, 608, + 0, 623, 609, 0, 652, 0, 0, 920, 873, 920, + 1235, 140, 120, 0, 121, 151, 0, 0, 0, 0, + 145, 397, 0, 327, 61, 0, 306, 0, 214, 292, + 291, 294, 289, 293, 0, 349, 0, 0, 233, 0, + 240, 278, 279, 277, 234, 306, 312, 236, 0, 0, + 0, 63, 53, 50, 55, 64, 0, 0, 65, 68, + 660, 80, 73, 1834, 1842, 0, 0, 0, 0, 0, + 0, 399, 406, 178, 0, 0, 283, 1301, 0, 0, + 0, 309, 0, 0, 0, 1304, 0, 0, 211, 0, + 256, 0, 168, 1303, 0, 1291, 0, 1142, 1143, 0, + 405, 856, 0, 0, 0, 1064, 824, 828, 826, 803, + 914, 931, 928, 648, 0, 651, 615, 0, 0, 529, + 536, 0, 539, 533, 0, 617, 0, 0, 619, 621, + 0, 0, 0, 656, 0, 0, 0, 1078, 560, 1354, + 1626, 1530, 561, 0, 565, 559, 563, 568, 570, 569, + 571, 567, 578, 0, 581, 1088, 581, 0, 0, 0, + 0, 156, 0, 147, 147, 0, 133, 972, 0, 214, + 0, 305, 328, 245, 223, 0, 0, 0, 230, 237, + 338, 239, 0, 72, 0, 88, 0, 0, 318, 115, + 113, 875, 423, 0, 1150, 259, 1298, 0, 0, 0, + 283, 171, 1300, 272, 265, 266, 267, 268, 269, 270, + 271, 286, 285, 257, 258, 0, 0, 0, 1144, 0, + 857, 0, 858, 0, 499, 653, 0, 0, 647, 0, + 527, 525, 528, 530, 526, 0, 0, 624, 640, 0, + 620, 618, 629, 0, 660, 0, 631, 0, 0, 0, + 572, 566, 919, 921, 0, 0, 532, 532, 0, 127, + 0, 655, 0, 0, 149, 149, 135, 0, 312, 330, + 0, 297, 304, 243, 242, 244, 248, 0, 246, 0, + 262, 0, 255, 223, 659, 0, 75, 0, 325, 398, + 402, 0, 213, 1292, 309, 0, 1298, 259, 1304, 0, + 1295, 0, 0, 1150, 859, 0, 934, 646, 649, 0, + 622, 0, 0, 0, 657, 658, 630, 0, 0, 0, + 564, 0, 0, 580, 0, 461, 460, 122, 147, 126, + 157, 146, 509, 148, 509, 0, 338, 284, 0, 0, + 0, 245, 0, 238, 335, 336, 337, 0, 251, 241, + 252, 69, 87, 326, 0, 309, 1293, 212, 169, 1296, + 1297, 0, 655, 930, 0, 0, 0, 0, 537, 0, + 543, 639, 574, 0, 573, 922, 923, 534, 149, 512, + 512, 655, 255, 298, 303, 222, 247, 261, 0, 0, + 0, 253, 0, 254, 1298, 0, 1140, 1613, 1355, 1583, + 0, 932, 935, 933, 927, 650, 0, 0, 535, 575, + 531, 509, 138, 137, 134, 214, 227, 0, 226, 0, + 315, 250, 1294, 1150, 0, 939, 938, 937, 941, 940, + 538, 0, 512, 332, 225, 229, 228, 655, 0, 0, + 139, 1141, 936, 542 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 37, 38, 39, 40, 2163, 2164, 2165, 1839, 990, - 2885, 1840, 991, 992, 2167, 41, 42, 1454, 539, 1770, - 1393, 2615, 44, 2113, 1775, 2117, 2760, 2376, 2112, 2119, - 2863, 2931, 2114, 1776, 1777, 2761, 1778, 45, 2214, 2215, - 46, 47, 1528, 48, 745, 49, 1529, 1481, 1261, 1010, - 1471, 1250, 50, 86, 51, 2152, 2485, 2877, 2177, 3019, - 2426, 2427, 2874, 2875, 2155, 1841, 2947, 2948, 2228, 1463, - 2942, 1907, 2810, 1845, 1827, 2428, 1916, 2770, 2523, 1842, - 2408, 1908, 2869, 1538, 1909, 2870, 2625, 1910, 1506, 1532, - 2156, 2949, 1846, 1507, 2151, 2486, 1450, 1911, 2881, 1912, - 498, 2412, 52, 531, 532, 737, 1198, 533, 718, 53, - 656, 1536, 540, 55, 1893, 2670, 2251, 2671, 1966, 1887, - 1259, 1963, 1582, 1510, 1260, 488, 1596, 2252, 2203, 1583, - 541, 890, 58, 59, 60, 580, 593, 594, 1364, 1748, - 2080, 960, 567, 568, 1881, 608, 1500, 1402, 1403, 1782, - 2126, 1429, 1430, 969, 970, 2719, 2924, 2720, 2721, 2583, - 2584, 3007, 1417, 1421, 1422, 1802, 1792, 1408, 2368, 2743, - 2744, 2745, 2746, 2747, 2748, 2749, 891, 2604, 2855, 1425, - 1426, 972, 973, 974, 1434, 1812, 62, 63, 1751, 2087, - 2088, 2089, 2090, 2346, 2347, 2361, 2357, 2589, 2727, 2091, - 2092, 2712, 2713, 2827, 2364, 2098, 2731, 2732, 2784, 1555, - 719, 1828, 1266, 1201, 721, 892, 722, 1177, 893, 1181, - 724, 894, 895, 896, 727, 897, 898, 899, 730, 1173, - 900, 901, 1192, 1220, 1221, 1222, 1223, 1224, 1225, 1226, - 1227, 1228, 943, 1651, 903, 904, 905, 2094, 906, 1358, - 1737, 2073, 2753, 2851, 2852, 2331, 2570, 2710, 2823, 2965, - 3000, 3001, 907, 908, 1306, 1307, 1308, 1734, 1353, 1354, - 909, 2488, 1356, 1644, 944, 1666, 1302, 1054, 1055, 1267, - 1623, 1624, 1647, 1995, 1654, 1659, 2023, 2024, 1667, 1702, - 910, 1607, 1608, 1981, 1275, 911, 633, 1061, 634, 1272, - 1696, 920, 912, 913, 914, 1299, 1300, 2039, 2305, 2306, - 1672, 1808, 585, 2035, 2723, 741, 1142, 915, 916, 917, - 918, 946, 587, 1056, 481, 733, 2932, 1155, 950, 1057, - 1843, 1692, 64, 817, 638, 65, 1153, 1518, 66, 2696, - 2534, 1166, 1540, 1920, 499, 67, 68, 69, 70, 71, - 615, 1253, 542, 1254, 1255, 804, 72, 1262, 806, 807, - 73, 574, 575, 1263, 1377, 1264, 74, 553, 75, 939, - 590, 940, 942, 544, 957, 2108, 1766, 77, 78, 561, - 562, 79, 80, 576, 81, 82, 2693, 545, 2231, 1896, - 508, 483, 484, 735, 1145, 1059, 1146 + -1, 37, 38, 39, 546, 2224, 2225, 2226, 1904, 1051, + 2946, 1905, 1052, 1053, 2228, 547, 548, 1517, 549, 1833, + 1454, 2678, 44, 2174, 1838, 2178, 2821, 2435, 2173, 2180, + 2924, 2992, 2175, 1839, 1840, 2822, 1841, 550, 551, 552, + 1589, 553, 778, 554, 1590, 1544, 1320, 1071, 1534, 1309, + 555, 86, 556, 2213, 2550, 2938, 2238, 3080, 2485, 2486, + 2935, 2936, 2216, 1906, 3008, 3009, 2286, 1526, 3003, 1971, + 2871, 1910, 1892, 2487, 1980, 2831, 2586, 1907, 2467, 1972, + 2930, 1599, 1973, 2931, 2688, 1974, 1569, 1593, 2217, 3010, + 1911, 1570, 2212, 2551, 1513, 1975, 2942, 1976, 504, 2471, + 557, 539, 540, 770, 1259, 541, 751, 558, 683, 1597, + 559, 560, 1958, 2733, 2308, 2734, 2027, 1952, 1318, 2024, + 1639, 1573, 1319, 494, 1653, 2309, 2264, 1640, 561, 951, + 58, 59, 60, 612, 624, 625, 1424, 1810, 2140, 1021, + 1468, 599, 600, 1946, 639, 1563, 1463, 1464, 1845, 2187, + 1492, 1493, 1030, 1031, 2780, 2985, 2781, 2782, 2645, 2646, + 3068, 1480, 1484, 1485, 1867, 1857, 1471, 2427, 2804, 2805, + 2806, 2807, 2808, 2809, 2810, 952, 2667, 2916, 1488, 1489, + 1033, 1034, 1035, 1497, 1877, 62, 63, 1813, 2148, 2149, + 2150, 2151, 2404, 2405, 2420, 2416, 2652, 2788, 2152, 2153, + 2773, 2774, 2888, 2423, 2159, 2792, 2793, 2845, 1616, 752, + 1893, 1325, 1262, 754, 953, 755, 1238, 954, 1242, 757, + 955, 956, 957, 760, 958, 959, 960, 763, 1234, 961, + 962, 1253, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, + 1289, 1004, 1712, 964, 965, 966, 2155, 967, 1418, 1799, + 2133, 2814, 2912, 2913, 2388, 2633, 2771, 2884, 3026, 3061, + 3062, 968, 969, 1366, 1367, 1368, 1796, 1413, 1414, 970, + 2553, 1416, 1705, 1005, 1727, 1362, 1121, 1122, 1326, 1684, + 1685, 1708, 2056, 1715, 1720, 2084, 2085, 1728, 1764, 971, + 1668, 1669, 2042, 1335, 972, 664, 1128, 665, 1331, 1758, + 981, 973, 974, 975, 1359, 1360, 2099, 2361, 2362, 1733, + 1873, 616, 1450, 2784, 774, 1203, 976, 977, 978, 979, + 1007, 618, 1123, 487, 766, 2993, 1216, 1011, 1124, 1908, + 1754, 562, 878, 1662, 563, 1214, 1581, 564, 2758, 2597, + 1227, 1601, 1984, 505, 565, 566, 69, 70, 71, 646, + 1312, 567, 1313, 1314, 865, 72, 1321, 867, 868, 569, + 606, 607, 1322, 1437, 1323, 570, 585, 571, 1000, 621, + 1001, 1003, 572, 1018, 2169, 1829, 77, 573, 593, 594, + 574, 80, 608, 575, 576, 2755, 577, 2289, 1223, 516, + 489, 490, 768, 1206, 1126, 1207 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -2671 +#define YYPACT_NINF -2716 static const int yypact[] = { - 4951, -127, 780, -2671, -2671, -127, 35300, -2671, -127, 57, - 1274, 40090, -2671, 4366, -127, 46796, 436, 221, 182, 239, - 40569, 40569, 46796, 46796, 41048, -127, 260, 47275, -2671, -127, - 24334, 37695, -9, -156, 47754, 46796, 995, 365, -72, -2671, - -2671, -2671, -2671, -2671, 80, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, 91, -2671, 185, - 121, 437, -36, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -15, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - 23855, -2671, -2671, -2671, -2671, -2671, -2671, 41527, 46796, 42006, - 38174, 42485, -2671, 123, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, 134, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, 153, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, 160, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -20, - 361, -2671, 161, -2671, -2671, -2671, -2671, 995, 42964, 505, - 581, 190, 48233, -2671, -2671, 46796, -2671, -2671, 480, 351, - -2671, -2671, -2671, -2671, 43443, -2671, -2671, -2671, -2671, 390, - -2671, -2671, 257, -2671, 71, -2671, -2671, 293, 271, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, 376, -2671, 53966, - -2671, 48712, 49191, 49670, -2671, 278, 544, 906, 23376, -2671, - -2671, -2671, -2671, -15, -2671, -2671, 817, -2671, 40569, 817, - -2671, -2671, -2671, -2671, -2671, 267, 353, -2671, 383, 653, - -2671, -2671, -2671, 446, -2671, -2671, 666, 10450, 10450, 50149, - 50149, 817, 50149, 478, -2671, -2671, 258, -2671, -156, -2671, - 437, 446, -2671, 24814, -2671, 493, 361, -2671, -2671, 94, - 837, 13978, 46796, 497, -2671, 518, 497, 524, 530, -2671, - 4951, 881, 839, 37695, 284, 284, 1021, 284, 619, 1068, - -2671, 1412, -2671, 587, -2671, 42964, -2671, 628, 912, -2671, - 446, 1020, 230, 854, 1060, 3460, 1065, 718, 1070, 894, - 6922, 13978, 33863, -2671, 361, -2671, -2671, -2671, 730, -2671, - 736, -2671, -2671, -2671, -2671, 602, 992, -2671, 743, 1264, - -2671, -2671, 855, 43922, 44401, 42964, 42964, 1242, -2671, -2671, - -2671, -2671, 870, -2671, -2671, -2671, 553, -2671, -2671, -2671, - -2671, 901, -2671, 901, 901, -2671, -2671, -2671, -2671, 857, - 857, 1050, 869, -2671, -2671, -2671, 1218, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, 880, 900, -2671, - 901, -2671, 857, -2671, -2671, -2671, -2671, -2671, 55358, -2671, - -2671, -2671, -2671, 514, 519, -2671, -2671, -2671, 55, 898, - -2671, 1362, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - 907, -2671, 875, 857, -2671, -2671, 1259, 61, -2671, 1271, - 70, -2671, 1280, 1130, 13978, -2671, 1094, 1037, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -156, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, 434, -2671, -2671, 31438, -2671, -2671, - 906, 950, -2671, -2671, 31438, 14482, 54430, 1420, -2671, 1244, - 46796, 986, -2671, -2671, -2671, -2671, -2671, -2671, 998, 1477, - 100, 1492, 13978, 1012, 100, 100, 1017, 1337, -2671, -2671, - -2671, 165, 1022, 1026, -2671, 166, 166, -2671, 1028, 1030, - -2671, 169, 1043, 1059, 1559, 1561, 151, 1072, 1081, 900, - 100, 13978, -2671, 1083, 166, 1085, 1090, 1101, 1580, 1115, - -2671, 1587, 1126, 96, 98, 1131, 1134, -2671, 1136, -2671, - 170, 13978, 13978, 13978, 1493, 13978, 7930, 42964, 1632, -2671, - 361, 1150, 817, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, 152, 5528, -2671, 1190, -2671, -2671, -2671, 1352, 13978, - -2671, -2671, 1148, 1436, -2671, 171, -2671, -2671, -2671, 539, - 1436, -2671, -2671, -2671, -2671, -2671, 187, 1556, 30480, 30959, - 42964, -2671, -2671, 361, -2671, -2671, -2671, -2671, -2671, -2671, - 476, -2671, -15, 32681, 1158, 1162, 361, 497, 46796, 46796, - 1625, -2671, -2671, -2671, 37695, 42964, 50628, 1288, -2671, -2671, - 437, 437, 9442, 437, 119, 33, 10954, 14986, 1499, 1383, - 149, 632, 1506, -2671, 1389, 619, 1068, 13978, 518, -2671, - 1444, 42964, 35779, 830, 882, 1179, 1263, 1180, 292, 1600, - -2671, 1186, -2671, 1277, 42964, 55358, 113, -2671, 1642, 113, - 113, 603, 1645, 1286, 222, 1443, -11, 352, 1186, 1345, - -2671, 37695, 237, 129, 1186, 42964, 1290, 546, 1186, 97, - 14482, 1051, 1107, 272, 1146, 1152, 99, 14482, 1174, 1189, - 102, 1300, 1310, 1315, 1371, 1433, 1456, 1495, 1500, 130, - 1505, 1518, 1524, 1532, 1534, 1549, 135, 1560, 138, 14482, - 1584, 1210, -2671, 32681, -70, -2671, -2671, 1590, 141, -2671, - 29044, 1205, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, 1299, 46796, - 1258, 416, 1568, 1628, 33863, 1224, 28817, 42964, 1454, 1345, - 1455, 1229, 1695, 736, 1237, -2671, 51107, -2671, -2671, -2671, - -2671, -2671, -2671, 1239, -2671, -2671, 13978, -2671, -2671, -2671, - 1729, -2671, 54430, 54430, 901, 901, -2671, -2671, 1703, 1328, - 1329, 1729, -2671, 1729, -2671, -2671, -2671, 54430, -2671, 46796, - 1253, 1260, 1729, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, 1729, - 1330, -2671, 1332, 1342, 1347, -2671, -2671, -2671, -2671, -2671, - 46796, 46796, -2671, 46796, 46796, -2671, 46796, 46796, 1267, 602, - 44880, 906, 38653, -2671, -2671, -2671, -2671, 821, 825, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, 33863, -2671, - 1762, -2671, -2671, -2671, 1266, 590, -2671, 623, 995, -2671, - -2671, 13978, 361, 13978, 32681, 1313, 13978, 13978, 1272, 1729, - 1729, -2671, 815, 1729, 1729, 5813, 13978, 27693, 13978, 18514, - 11458, 13978, 13978, 8434, 13978, 5813, 1760, 1760, 25772, -2671, - 1429, -2671, 1278, 872, 6154, 1282, -2671, 1283, 1275, -2671, - 1279, -2671, 361, 361, 13978, -2671, 13978, 2141, 2141, -2671, - 188, 54430, 13978, 13978, 13978, 13978, 13978, 13978, 33384, 1376, - 143, 46796, 13978, 13978, 1293, 985, -2671, 13978, 1516, -2671, - 1298, 13978, 1385, 198, 13978, 13978, 13978, 13978, 13978, 13978, - 13978, 13978, 13978, -2671, -2671, 20012, 189, 1626, 1643, 361, - -110, 281, 10450, 39132, 1636, 6922, -2671, 361, 29522, 93, - 1636, -2671, -2671, -2671, -2671, 173, -2671, -2671, -2671, -2671, - 1266, -2671, 1266, 1308, 42964, 94, 37216, 13978, -2671, -2671, - 680, 1317, 1368, 746, 1774, 46796, -2671, 26251, 1602, -2671, - 245, 245, 1320, -2671, 31914, 1602, -2671, -2671, 19004, 1445, - 1603, 1538, -2671, -2671, 1520, 1521, -2671, 1331, 32909, 15490, - 15490, -2671, 1250, 32681, 1252, -2671, -2671, -2671, -2671, -2671, - -2671, 27, -2671, 42964, -1, 1499, 632, 1336, -2671, -2671, - 914, 1338, 51586, 46796, 1614, 1567, 1616, -139, -2671, -2671, - -2671, 54430, -2671, 46796, 46796, 52065, 52544, 34342, 46796, 33863, - -2671, -2671, -2671, -2671, 46796, 758, 46796, 6477, -2671, -2671, - -2671, 113, -2671, -2671, -2671, -2671, -2671, 46796, 46796, -2671, - -2671, 113, 46796, 46796, 113, -2671, 917, 46796, 46796, 46796, - 46796, 1087, 46796, 46796, -43, -43, 1550, -2671, 11962, 68, - -2671, 13978, 13978, -2671, 13978, 1517, -2671, 687, -2671, 1564, - 92, 1393, 42964, 42964, 46796, 1391, -2671, -2671, -2671, -2671, - -2671, -2671, 33863, 1050, 1353, -2671, 1354, 1698, -2671, 1345, - 1699, 36258, 545, 965, 1395, 12466, 1816, 1586, -2671, -2671, - 1573, 13978, 1361, 1363, 55, 694, -2671, -2671, 1365, 1260, - 1386, 1388, 1367, 1373, -2671, 698, 54430, 1729, 86, 1374, - 1375, 1351, 1188, 547, 1251, 61, -2671, 70, -2671, 1578, - 150, -2671, 1465, 1604, 736, 1839, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, 716, 22897, -2671, -2671, 1840, 817, 1840, - 58, -2671, -2671, 1840, -2671, 1840, -2671, 31438, -2671, 14482, - -2671, 54430, -2671, 1379, -2671, 1382, 13978, 35, -2671, 31975, - 1394, 13978, 1397, 1399, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, 1400, 1715, -2671, 1401, 1404, 5295, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, 1405, 1392, 32065, 1406, 18514, 18514, - 7930, 1872, -2671, 18514, 1409, -2671, 1410, 31927, 1408, 1414, - 32295, 12970, 13978, 12970, 12970, 32349, -2671, 1415, 32488, 46796, - -2671, 15994, -2671, -2671, -2671, 13978, 42964, -2671, 13978, 1416, - 6378, -2671, -2671, -2671, 281, 856, 4927, 4927, 4927, 5813, - -2671, -2671, -2671, 1413, -2671, 18514, 18514, -2671, 28362, 3960, - 7930, -2671, -2671, 1748, -2671, 739, -2671, 1421, -2671, -2671, - 4659, -2671, 27693, 32716, 13978, 162, -2671, 13978, 1293, 13978, - 1504, 4927, 4927, 4927, 195, 195, 203, 203, 203, 856, - 281, -2671, -2671, -2671, 1424, 1426, 1428, 1773, 1115, 13978, - -2671, -2671, 649, 685, 42964, 2888, 3130, 3255, -2671, -2671, - 21460, 1472, -70, 1493, 1472, 1729, 2141, -2671, 518, -2671, - -2671, -2671, 32681, -2671, 995, 21460, 1473, 1486, -79, 24334, - 1647, -2671, 46796, -2671, 46796, -2671, 1432, 1636, 1449, -2671, - -2671, -2671, 1458, 1458, 13978, 1712, 1458, 1650, 1651, 1000, - 1000, 1250, 1655, -2671, -2671, 1507, -2671, -2671, -2671, 13978, - 8938, 1262, -2671, 1265, -2671, -2671, -2671, -2671, 1442, -2671, - -2671, 1705, -2671, -2671, -2671, -2671, 1536, 1186, 13978, 1685, - -2671, 120, 1459, 1807, -129, 1761, 46796, -2671, 300, 654, - -2671, 358, 1808, 150, 1810, 150, 33863, 33863, 33863, 749, - -2671, -2671, 817, -2671, -2671, 773, -2671, -183, -2671, -2671, - -2671, 1547, 589, 1186, 1345, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, 240, 711, 1186, 1548, -2671, 1552, -2671, 1553, - 721, 1186, -2671, -2671, 68, 68, 68, 14482, -2671, 1687, - 1692, 1475, 32681, 32681, 32681, 1474, -2671, 136, -2671, 46796, - -2671, -2671, -2671, 1517, 42964, 1479, 1935, 736, -2671, 1635, - 411, -2671, 817, 46796, 42964, 42964, 42964, -2671, -2671, -2671, - 1476, 1478, -2671, 53023, -50, 1697, 1693, 46796, 1523, 1180, - 1947, -2671, 796, 13474, 1835, 42964, 1488, -2671, -2671, -2671, - -2671, 1729, -2671, -2671, 85, 85, -2671, 46796, -2671, 1494, - -2671, 1515, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, 46796, -2671, 42964, 1838, 995, -2671, 33863, - -2671, 36737, -2671, -2671, -2671, -2671, 817, -2671, 817, 1714, - 46796, 30001, 817, 817, -2671, -2671, -2671, -2671, 32573, 13978, - -2671, 1850, 54430, -2671, 28180, -2671, -2671, -2671, 13978, -2671, - -2671, 13978, -2671, 27693, 13978, 1831, -2671, 2006, 2006, 6154, - 54430, 18514, 18514, 18514, 18514, 18514, 191, 1085, 18514, 18514, - 18514, 18514, 18514, 18514, 18514, 18514, 18514, 19508, 304, -2671, - -2671, 13978, 13978, 1853, 1831, 13978, -2671, 54430, 1525, -2671, - 1526, 1530, 13978, -2671, 54430, 1533, 1535, 7930, 32627, -2671, - 361, 28209, -2671, 32681, -2671, 2141, 13978, 1932, 2502, 13978, - 1540, 13978, 1852, -2671, -2671, 1522, -2671, -2671, 54430, 13978, - 1542, 4677, 18514, 18514, 6169, -2671, 6317, 13978, 7930, -2671, - 1550, 1575, -2671, 1741, 1637, 1637, 1637, 1637, -2671, -2671, - 42964, 42964, 42964, 21939, 1874, 20980, 45359, 1545, -2671, 826, - -2671, 45359, 45838, -2671, 1565, -2671, 361, 13978, 1869, 68, - 1429, 1869, 1551, -2671, -2671, 1566, -2671, 13978, 1702, -2671, - -2671, -2671, 1610, -2671, 797, -2671, 1973, 1702, -2671, 798, - -2671, 26251, 1473, 13978, 361, 148, -2671, -2671, -2671, 1562, - -2671, 1458, -2671, -2671, -2671, 1772, -2671, -2671, -2671, 42964, - -2671, 46796, 28244, 1913, -2671, 46796, 46796, 46796, -2671, 46796, - 1570, 1571, 621, 1569, 701, -2671, 1349, 621, 1895, 156, - 1180, 222, 5078, 354, -2671, -2671, -2671, 1649, 46796, -2671, - 46796, -2671, -2671, -2671, -2671, -2671, 34342, -2671, -2671, -2671, - 33863, 27213, 33863, 46796, 46796, 46796, 46796, 46796, 46796, 46796, - 46796, 46796, 46796, 1583, 1588, 1589, 1550, -2671, -2671, -2671, - -2671, -2671, -2671, 352, -2671, -2671, 136, 1576, 36258, 995, - 1395, 1628, 602, 46317, 1593, 1581, -2671, 804, 1345, 1595, - 2057, -2671, 545, 36258, -2671, -2671, -2671, 2015, -2671, 278, - 131, -2671, -2671, 995, -2671, 995, 32681, 46796, 1656, -2671, - 1260, 1605, -2671, -2671, 1260, 54430, -2671, -2671, 150, 42964, - -2671, 810, -2671, -2671, -2671, -2671, 46796, 1597, -2671, 1597, - -2671, -2671, 13978, 32681, -2671, 1598, -2671, 32681, 28273, -2671, - 32681, 1853, -2671, 2006, 2587, 2587, 2587, 3241, 1930, 142, - 1607, 2587, 2587, 2587, 202, 202, 178, 178, 178, 2006, - 304, 32681, 32681, -2671, -2671, 1612, -2671, -2671, -2671, -2671, - 1615, 46796, -2671, 5665, -2671, 1613, 1617, 46796, -2671, -2671, - 279, 13978, 13978, 28362, -2671, 6304, 13978, 54430, 859, 28362, - 233, 13978, 2664, 2741, 13978, 13978, 6398, 28312, 1619, 13978, - 26730, -2671, 42964, 42964, 42964, 42964, -2671, -2671, -2671, 45359, - 45838, 1608, 20500, 826, 1620, 42964, -2671, 1713, 1624, 21460, - 1903, 1830, -2671, 21460, 1830, 688, 1830, 1905, 1713, 25293, - -2671, 1713, 1631, 1837, -2671, 556, 32681, 2076, 1950, 1639, - -2671, 1950, 817, -2671, 32681, 10450, -2671, 995, 1441, 46796, - 361, -38, -2671, 1648, 46796, -2671, 1702, 32681, -2671, -2671, - 27693, -2671, -2671, -2671, -2671, -2671, 46796, 1640, -2671, 1644, - 621, -2671, 46796, 1676, -2671, 157, 1940, 46, -2671, 13978, - -2671, 2028, 2108, 1349, 1653, 46796, 46796, 18514, -2671, 227, - 125, -2671, 1923, 42964, 1676, 2065, -2671, -2671, -2671, 701, - -2671, 1959, 1873, -2671, 113, -2671, 13978, 701, 1876, 87, - 46796, -2671, -2671, 1327, -2671, 54430, 150, 150, -2671, -2671, - 1654, 1657, 1659, 1661, 1662, 1663, 1664, 1665, 1666, -2671, - 1667, 1668, 1669, 1671, 1672, 1673, 1677, 1678, 880, 1679, - -2671, 1682, 1562, 1683, 1688, 1689, 54894, 1690, 1691, 1694, - 1696, 1707, 821, 825, -2671, -2671, -2671, -2671, -2671, -2671, - 743, 1708, -2671, 1700, -2671, -2671, 1737, -2671, 1739, -2671, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, 68, 950, 77, - 46796, 1710, 1523, 2119, 422, 1921, 1719, -2671, 817, 1395, - -2671, 36258, 1155, 264, 1693, -2671, 146, 1523, -2671, 2085, - 1735, -2671, 1924, 46796, 1723, -2671, -2671, -2671, 2175, -2671, - 36737, 1597, 32681, -2671, -2671, -2671, 18514, 2043, 1725, 54430, - -2671, -2671, 13978, -2671, -2671, 28362, 28362, 6304, 877, -2671, - 28362, 13978, 13978, 28362, 28362, 13978, -2671, -2671, 28557, 53487, - -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, 34821, 45359, - 1726, -2671, 39611, -2671, -2671, 46796, 826, 21460, -2671, -2671, - 1235, -2671, 21460, 2005, -2671, 21460, -2671, 46796, 1731, -2671, - 46796, -2671, 9946, 13978, 1768, 817, 1768, -2671, 1733, -2671, - -79, -2671, -2671, 2144, 22418, 2096, 13978, -2671, -2671, 1734, - 621, -2671, 1901, 1676, 1742, -2671, -2671, -2671, -2671, -2671, - -2671, 28641, -2671, 41, 13978, -2671, 765, 3241, -2671, -2671, - -2671, -2671, 1676, 736, -2671, 46796, 2200, 2090, -2671, -2671, - 32681, -2671, -2671, 1729, 1729, -2671, -2671, 2168, -2671, -2671, - -2671, -2671, 743, 111, 27213, 46796, 46796, 1744, -2671, -2671, - 352, 2121, 890, 545, -2671, 995, 42964, 2094, 36258, -2671, - 2209, 1749, 46796, 1523, 176, 176, -2671, 1890, -2671, 1892, - -2671, -2671, 238, -2671, 42964, -2671, -2671, 22418, 995, -2671, - 3535, 18514, 54430, 895, -2671, -2671, 28362, 28362, 28362, -2671, - 1952, -2671, -2671, 910, 2223, -2671, 46796, -67, -73, 1767, - 1769, -2671, -2671, 1770, -2671, 13978, 1775, -2671, -2671, 21460, - 1235, 919, -2671, 54430, 46796, 925, 54430, -2671, 1776, -120, - 1777, -2671, 7426, 1766, -2671, -2671, -2671, -2671, -2671, -2671, - 32681, 32681, 46796, 1946, -2671, 1946, 10450, 1832, 46796, 13978, - -2671, 927, 2202, 26, -28, 32681, -2671, 42964, -2671, 33863, - -2671, 621, -96, 1781, 13978, 28705, 2004, -2671, -2671, 2034, - -2671, 2095, -2671, 46796, 1845, 145, 1859, -2671, -2671, -2671, - -2671, 950, 817, 1395, 1693, 1735, 1789, 42964, 995, 545, - 278, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, -2671, - -2671, -2671, -2671, -2671, 2222, 2002, 2224, 1656, 962, 3535, - 972, -2671, 2238, 1550, 1565, 34821, 1796, -2671, 1797, -2671, - -2671, -2671, -2671, -2671, 46796, 1015, -2671, 32681, 46796, -2671, - -2671, -2671, 46796, 2168, 978, -2671, 13978, 1803, 13978, -2671, - 16498, 1793, -2671, 2266, 13978, 1864, 1864, 995, -2671, 28766, - 1472, 22418, 46796, 46796, 46796, -2671, 1933, 736, 621, 984, - -2671, 1820, -2671, -2671, -2671, -2671, 1345, -2671, 28891, 2040, - 82, 2030, 1781, -2671, 13978, -2671, 1893, -2671, -2671, -2671, - 2280, -2671, -2671, 36258, 1823, 1735, 1693, 1523, 2035, -2671, - 2036, 1833, 1395, -2671, 13978, 4, -2671, -2671, 46796, -2671, - 988, 1836, 1841, -2671, -2671, -2671, 1842, 16498, 1843, -2671, - 46796, 1834, 32681, 1970, -2671, -2671, -2671, 2202, -2671, -2671, - -2671, 245, -2671, 245, 26251, 2034, -2671, 33863, 27213, 1138, - -96, 2129, -2671, -2671, -2671, -2671, 89, 2048, -2671, 2050, - -2671, 32681, -2671, 995, 36258, -2671, -2671, -2671, -2671, -2671, - 22418, 1472, 1408, 17002, 17002, 1847, 989, -2671, 2328, 1996, - -2671, -2671, 1849, -2671, -2671, -2671, 39611, 46796, 1458, 1458, - 1472, 2030, -2671, -2671, -2671, -2671, -2671, 377, 377, 2218, - -2671, 1906, -2671, 1735, 1004, -2671, 18010, 1993, 207, 31962, - -2671, -2671, -2671, -2671, -2671, 1851, 1854, -2671, -2671, -2671, - 245, -2671, -2671, -2671, -2671, -2671, 2330, -2671, 154, -2671, - -2671, -2671, 1395, 2317, -2671, -2671, -2671, -2671, -2671, -2671, - 2345, 1458, 621, -2671, -2671, -2671, 1472, 17506, 1856, -2671, - -2671, -2671, -2671 + 5188, 365, 709, -2716, -2716, 365, 37059, -2716, 365, 57, + 1454, 39444, -2716, 5625, 365, 42324, 56166, 240, 246, 260, + 42804, 42804, 50454, 42324, 43284, 365, 293, 50934, -2716, 365, + 25146, 39924, 59, -143, 43764, 42324, 912, 397, -78, -2716, + -2716, -2716, -2716, -2716, 114, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, 113, -2716, 93, + 122, 1020, -73, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, 51, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + 24666, -2716, -2716, -2716, -2716, -2716, -2716, 44244, 42324, 44724, + 40404, 45204, -2716, 144, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, 152, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, 171, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, 180, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -15, 592, -2716, 186, -2716, + -2716, -2716, -2716, 912, 42324, 764, 783, 162, 51414, -2716, + -2716, 50454, -2716, -2716, 1037, 386, -2716, -2716, -2716, -2716, + -2716, 40884, -2716, -2716, -2716, -2716, -2716, 376, -2716, -2716, + 226, -2716, 159, -2716, -2716, 300, 243, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, 410, -2716, 45684, -2716, 51894, + 46149, 46629, -2716, 326, 56167, 23226, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, 51, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, 786, -2716, + 42804, 786, -2716, -2716, -2716, -2716, -2716, -117, 369, -2716, + 408, 661, -2716, -2716, -2716, 395, -2716, -2716, 615, 10728, + 10728, 52374, 52374, 786, 52374, 441, -2716, -2716, 689, -2716, + -143, -2716, 1020, 395, 25627, -2716, 453, 592, -2716, -2716, + 137, 785, 14768, 42324, 469, -2716, 489, 469, 516, 525, + -2716, 5188, 860, 821, 39924, 297, 297, 988, 297, 1175, + 1307, -2716, 799, -2716, 568, -2716, 42324, -2716, 600, 873, + -2716, 395, 961, 756, 779, 984, 5407, 1004, 850, 1030, + 908, 7193, 14768, 34659, -2716, 592, 687, 608, -2716, -2716, + -2716, -2716, 668, 925, -2716, 712, 1206, -2716, -2716, 796, + 47109, 47589, 42324, 42324, 1171, -2716, -2716, -2716, -2716, 808, + -2716, -2716, -2716, 158, -2716, -2716, -2716, -2716, 841, -2716, + 841, 841, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + 780, 780, 992, 815, -2716, -2716, -2716, 1167, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, 828, 1139, + -2716, 841, -2716, 780, -2716, -2716, -2716, -2716, -2716, -2716, + 55239, -2716, -2716, -2716, -2716, 513, 557, -2716, -2716, -2716, + -2716, 65, 835, -2716, 1316, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, 865, -2716, 5037, 780, -2716, -2716, 1232, + 72, -2716, 1238, 73, -2716, 1256, 1130, 14768, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -143, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, 432, -2716, -2716, 32167, -2716, + -2716, 56167, 936, -2716, -2716, 32167, 15273, 48069, 1401, -2716, + 1227, 50454, 965, -2716, -2716, -2716, -2716, -2716, -2716, 602, + 1486, 121, 1490, 14768, 1010, 121, 121, 1014, 1345, 187, + 200, 209, 213, 1016, 1027, 214, 225, 225, -2716, 1029, + 1034, -2716, 237, 1042, 1047, 1547, 1558, 146, 1066, 1078, + 1139, 121, 14768, -2716, 1081, 225, 1086, 1093, 1102, 1600, + 1109, 267, 1605, 1126, 132, 181, 1128, 1137, -2716, 1141, + 275, 277, 14768, 14768, 14768, 1499, 14768, 8203, 42324, 1629, + -2716, 592, 1150, 786, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, 169, 5838, -2716, 1189, -2716, -2716, -2716, 1355, + 14768, -2716, -2716, 1154, 1445, -2716, 278, -2716, -2716, -2716, + 611, 1445, -2716, -2716, -2716, -2716, -2716, 295, 1566, 31207, + 31687, 42324, -2716, -2716, 592, -2716, -2716, -2716, -2716, -2716, + -2716, 536, -2716, 51, 33554, 1168, 1180, 592, 469, 42324, + 42324, 1653, -2716, -2716, -2716, 39924, 42324, 52854, 1322, -2716, + -2716, 1020, 1020, 9718, 71, 256, 898, 11233, 15778, 1536, + 1422, 265, 183, 1545, -2716, 1433, 1175, 1307, 14768, 489, + -2716, 1494, 42324, 37539, 616, 721, 1237, 1327, 1246, 14, + 1662, -2716, 1259, -2716, 1342, 42324, 55239, 292, -2716, 1709, + 292, 292, 720, 1713, 1354, 336, 1509, 562, -83, 1259, + 2234, -2716, 39924, 147, 653, 1259, 42324, 1359, 667, 1259, + 148, 15273, 1060, 1216, 339, 1248, 1283, 151, 155, 168, + 170, 175, 15273, 1399, 1543, 182, 1556, 1570, 1574, 1581, + 1585, 1590, 1604, 1610, 189, 1616, 1619, 1630, 1642, 1646, + 196, 1655, 199, 1664, 129, 202, 15273, 1671, 1277, -2716, + 33554, -23, -2716, -2716, 1676, 215, -2716, 29769, 1270, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, 1364, + 50454, 1323, -22, 1633, 1692, 34659, 1289, 48069, 42324, 1521, + 2234, 1522, 1298, 1760, 608, 1302, -2716, 53334, -2716, -2716, + -2716, -2716, -2716, -2716, 1310, -2716, -2716, 14768, -2716, -2716, + -2716, 1804, -2716, 48069, 48069, 841, 841, -2716, -2716, 1780, + 1403, 1411, 1804, -2716, 1804, -2716, -2716, -2716, 48069, -2716, + 50454, 1330, 1333, 1804, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + 1804, 1414, -2716, 1415, 1416, 1417, -2716, -2716, -2716, -2716, + -2716, 50454, 50454, -2716, 42324, 42324, -2716, 42324, 50454, 1337, + 56167, 36579, -2716, -2716, -2716, -2716, 683, 882, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, 34659, -2716, 1452, + -2716, -2716, -2716, 1335, 680, -2716, 775, 912, -2716, -2716, + 14768, 592, 14768, -2716, 33554, 1379, 14768, 14768, 1340, 1804, + 1804, -2716, 4979, 1804, 1804, 33630, 14768, 28510, 14768, 19313, + 11738, 14768, 14768, 8708, 14768, 33630, 1829, 1829, 26587, -2716, + 1498, -2716, 1346, 1267, 6350, 1343, -2716, 1344, 1348, 1353, + -2716, 592, 592, 14768, -2716, 14768, 5439, 5439, -2716, 205, + 48069, 14768, 14768, 14768, 14768, 14768, 14768, 14768, 34179, 1428, + 195, 50454, 14768, 14768, 1349, 926, -2716, 14768, 1573, -2716, + 1352, 14768, 1435, 919, 14768, 14768, 14768, 14768, 14768, 14768, + 14768, 14768, 14768, -2716, -2716, 20814, 233, 1682, 1701, 592, + -79, 364, 10728, 41364, 1694, 7193, -2716, 592, 30247, 107, + 1694, -2716, -2716, -2716, -2716, 279, -2716, -2716, -2716, -2716, + 1335, -2716, 1335, 1368, 42324, 137, 38499, 14768, -2716, -2716, + 1369, 1371, 1375, 1438, 703, 1837, 50454, -2716, 27067, 1661, + -2716, 290, 290, 1378, -2716, 32644, 1620, 1661, 1020, -2716, + -2716, 19804, 1505, 1663, 1597, -2716, -2716, 1577, 1580, -2716, + 1389, 33617, 16283, 16283, -2716, 1336, 33554, 1338, -2716, -2716, + -2716, -2716, -2716, -2716, 698, -2716, 42324, 44, 1536, 183, + 1393, -2716, -2716, 1012, 1400, 53814, 42324, 1677, 1628, 1678, + -95, -2716, -2716, -2716, 48069, -2716, 42324, 50454, 48534, 54294, + 35139, 42324, 34659, -2716, -2716, -2716, -2716, 42324, 266, 42324, + 29692, -2716, -2716, -2716, 292, -2716, -2716, -2716, -2716, -2716, + 50454, 42324, -2716, -2716, 292, 50454, 42324, 292, -2716, 1202, + 42324, 42324, 42324, 42324, 1469, 42324, 42324, -14, -14, 1611, + -2716, 12243, 143, -2716, 14768, 14768, -2716, 14768, 1578, -2716, + 801, -2716, 1621, 86, 1456, 42324, 42324, 50454, 75, -2716, + -2716, -2716, -2716, -2716, -2716, 34659, -2716, 1406, 1755, -2716, + 2234, 1758, 38019, 684, 682, 1450, 12748, 1874, 1643, -2716, + -2716, 1631, 14768, 1423, 1431, 65, 806, -2716, -2716, 1419, + 1333, 1453, 1455, 1439, 1440, -2716, 810, 48069, 1804, 105, + 1441, 1443, 1449, 607, 154, 1347, 72, -2716, 73, -2716, + 1645, 191, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + 812, 22266, -2716, -2716, 1879, 786, 1879, 690, -2716, -2716, + 1879, -2716, 1879, -2716, 32167, -2716, 15273, -2716, 48069, -2716, + -2716, -2716, -2716, -2716, 1444, -2716, 1436, 14768, 67, -2716, + 32706, 1447, 14768, 1448, 1451, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, 1457, 1767, -2716, 1459, 1461, 5594, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, 1462, 1463, 32742, 1465, 19313, + 19313, 8203, 3206, -2716, 19313, 1467, -2716, 1468, 32657, 1446, + 1470, 32787, 13253, 14768, 13253, 13253, 33196, -2716, 1472, 33275, + 42324, -2716, 16788, -2716, -2716, -2716, 14768, 42324, -2716, 14768, + 1473, 6415, -2716, -2716, -2716, 647, 5236, 364, 2488, 2488, + 2488, 33630, -2716, -2716, -2716, 1471, -2716, 19313, 19313, -2716, + 3680, 2440, 8203, -2716, -2716, 1781, -2716, 751, -2716, 1475, + -2716, -2716, 4135, -2716, 28510, 3589, 14768, 206, -2716, 14768, + 1349, 14768, 1537, 2488, 2488, 2488, 455, 455, 210, 210, + 210, 647, 364, -2716, -2716, -2716, 1477, 1478, 1479, 1800, + 1109, 14768, -2716, -2716, 830, 958, 42324, 3115, 3185, 3659, + -2716, -2716, 22746, 1526, -23, 1499, 1526, 1804, 5439, -2716, + 489, -2716, -2716, -2716, 33554, 42324, -2716, 912, 22746, 1527, + 1532, -41, 25146, 1693, -2716, 50454, -2716, 50454, -2716, 1480, + 1694, 1500, -2716, -2716, -2716, 1507, 1507, 14768, 1434, 1507, + -2716, 1661, 1704, 1705, 977, 977, 1336, 1706, -2716, -2716, + 1550, -2716, -2716, -2716, 14768, 9213, 1363, -2716, 1367, -2716, + -2716, -2716, -2716, 1492, -2716, -2716, 1753, -2716, -2716, -2716, + -2716, 1582, 1259, 14768, 1725, -2716, 163, 1501, 1846, 82, + 1802, 50454, -2716, 283, 285, -2716, 778, 1851, 191, 1852, + 191, 34659, 34659, 34659, 820, -2716, -2716, 786, -2716, -2716, + 829, -2716, 343, -2716, -2716, -2716, 1588, 722, 1259, 2234, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, 156, 735, 1259, + 1593, -2716, 1594, -2716, 1595, 852, 1259, -2716, -2716, 143, + 143, 143, 15273, -2716, 1728, 1734, 1515, 33554, 33554, 33554, + 1519, -2716, 142, -2716, 50454, -2716, -2716, -2716, 1578, 42324, + 1520, 1980, 608, -2716, 1680, 837, -2716, 50454, 42324, 42324, + 42324, -2716, -2716, -2716, 1528, 1517, -2716, 38979, -26, 1736, + 1739, 42324, 1569, 1246, 1989, -2716, 862, 13758, 1880, 42324, + 1531, -2716, -2716, -2716, -2716, 1804, -2716, -2716, -108, -108, + -2716, 50454, -2716, 1535, -2716, 1538, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, -2716, -2716, 50454, -2716, -2716, + 34659, -2716, 36099, -2716, -2716, -2716, -2716, 786, -2716, 786, + 1761, 50454, 30727, 786, 786, -2716, -2716, -2716, -2716, 33304, + 14768, -2716, 1892, 48069, -2716, 6598, -2716, -2716, -2716, 14768, + -2716, -2716, 14768, -2716, 28510, 14768, 1868, -2716, 2029, 2029, + 6350, 48069, 19313, 19313, 19313, 19313, 19313, 550, 1086, 19313, + 19313, 19313, 19313, 19313, 19313, 19313, 19313, 19313, 20309, 347, + -2716, -2716, 14768, 14768, 1875, 1868, 14768, -2716, 48069, 1544, + -2716, 1548, 1551, 14768, -2716, 48069, 1552, 8203, 33383, -2716, + 592, 6680, -2716, 33554, -2716, 5439, 14768, 3489, 4548, 14768, + 1553, 14768, 1876, -2716, -2716, 1555, -2716, -2716, 48069, 14768, + 1562, 4203, 19313, 19313, 4447, -2716, 4663, 14768, 8203, -2716, + 1611, 14263, -2716, 1776, 1668, 1668, 1668, 1668, -2716, -2716, + 42324, 42324, 42324, 23706, 1904, 21783, 49014, 49014, 1576, -2716, + 1516, -2716, 49014, 49494, -2716, 1598, -2716, 592, 14768, 1905, + 143, 1498, 1905, 1584, -2716, -2716, 1592, -2716, 14768, 1744, + -2716, -2716, -2716, 1649, -2716, 863, -2716, 2010, 1744, -2716, + 921, -2716, 27067, 1527, 14768, 592, 173, -2716, -2716, -2716, + 1599, -2716, 1507, -2716, -2716, -2716, 1809, -2716, -2716, -2716, + 42324, -2716, 42324, 28998, 1947, -2716, 50454, 50454, 50454, -2716, + 50454, 1601, 1602, 642, 1609, 651, -2716, 1686, 642, 1926, + 160, 1246, 336, 2502, 17, -2716, -2716, -2716, 1681, 42324, + -2716, 50454, -2716, -2716, -2716, -2716, -2716, 35139, -2716, -2716, + -2716, 34659, 28029, 34659, 42324, 42324, 42324, 42324, 42324, 42324, + 42324, 42324, 42324, 42324, 1614, 1615, 1618, 1611, -2716, -2716, + -2716, -2716, -2716, -2716, -83, -2716, -2716, 142, 1612, 38019, + 912, 1450, 1692, 668, 49974, 927, 2234, 1627, 2072, -2716, + 684, 38019, -2716, -2716, -2716, 2038, -2716, 326, 208, -2716, + -2716, 912, -2716, 912, 33554, 50454, 1687, -2716, 1333, 1632, + -2716, -2716, 1333, 48069, -2716, -2716, 191, -2716, 931, -2716, + -2716, -2716, -2716, 50454, 1626, -2716, 1626, -2716, -2716, 14768, + 33554, -2716, 1634, -2716, 33554, 29027, -2716, 33554, 1875, -2716, + 2029, 1044, 1044, 1044, 3234, 1960, 179, 1636, 1044, 1044, + 1044, 357, 357, 135, 135, 135, 2029, 347, 33554, 33554, + -2716, -2716, 1644, -2716, -2716, -2716, -2716, 1647, -2716, 6167, + -2716, 1639, 1648, 50454, -2716, -2716, 622, 14768, 14768, 3680, + -2716, 33704, 14768, 48069, 947, 3680, 235, 14768, 4699, 4875, + 14768, 14768, 4782, 29063, 1651, 14768, 29092, 27547, -2716, 42324, + 42324, 42324, 42324, -2716, -2716, -2716, 49014, 49494, 1637, 21303, + 49014, 1516, 1654, 42324, -2716, 1735, 1650, 1735, 22746, 1911, + 1859, -2716, 22746, 1859, 1019, 1859, 1934, 1735, 26107, -2716, + 1735, 1660, 1867, -2716, 569, 33554, 2108, 1982, 1669, -2716, + 1982, 786, -2716, 33554, 10728, -2716, 912, 1115, 50454, 592, + -11, -2716, 1685, 50454, -2716, 1744, 33554, -2716, -2716, 28510, + -2716, -2716, -2716, -2716, -2716, 50454, 1670, -2716, 1674, 642, + -2716, 50454, 1707, -2716, 212, 1973, 229, -2716, 14768, -2716, + 2059, 2139, 1686, 1683, 50454, 42324, 19313, -2716, 366, 176, + -2716, 1955, 42324, 1707, 2097, -2716, -2716, -2716, 651, -2716, + 1991, 1906, -2716, 292, -2716, 14768, 651, 1907, 110, 50454, + -2716, -2716, 2306, -2716, 48069, 191, 191, -2716, -2716, 1688, + 1689, 1695, 1696, 1697, 1698, 1699, 1700, 1702, 1703, 1708, + 1710, 1711, -2716, 1715, 1716, 1717, 1718, 1719, 1720, 1722, + 1724, 828, 1726, -2716, 1727, 1599, 1729, 1732, 1733, 1737, + 54774, 1738, 1740, 1741, 1742, 1743, 1746, 683, 882, -2716, + -2716, -2716, -2716, -2716, -2716, 712, 1749, -2716, 1752, -2716, + -2716, 1769, -2716, 1771, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, 143, 936, 125, 50454, 1714, 1569, 2156, 555, + 1923, 1730, 1450, -2716, 38019, 754, 194, 1739, -2716, 188, + 1569, -2716, 2098, 1745, -2716, 1921, 50454, 1759, -2716, -2716, + -2716, -2716, 36099, 1626, 33554, -2716, -2716, -2716, 19313, 2039, + 1763, 48069, -2716, -2716, 14768, -2716, -2716, 3680, 3680, 33704, + 955, -2716, 3680, 14768, 14768, 3680, 3680, 14768, -2716, -2716, + 29190, -2716, 55704, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, 35619, 49014, 1766, 41844, -2716, -2716, 42324, -2716, 1516, + 22746, -2716, -2716, 1525, -2716, 22746, 2023, -2716, 22746, -2716, + 42324, 1768, -2716, 42324, -2716, 10223, 14768, 1799, 786, 1799, + -2716, 1757, -2716, -41, -2716, -2716, 2180, 24186, 2136, 14768, + -2716, -2716, 1770, 642, -2716, 1935, 1707, 1775, -2716, -2716, + -2716, -2716, -2716, -2716, 29420, -2716, 49, 14768, -2716, 858, + 3234, -2716, -2716, -2716, -2716, 1707, 608, -2716, 42324, 2250, + 2137, -2716, -2716, 33554, -2716, -2716, 1804, 1804, -2716, -2716, + 2215, -2716, -2716, -2716, -2716, 712, 383, 28029, 42324, 42324, + 1792, -2716, -2716, -83, 2169, 966, 684, -2716, 912, 42324, + 2142, 38019, 2257, 1803, 42324, 1569, 930, 930, -2716, 1948, + -2716, 1949, -2716, -2716, 258, -2716, 42324, -2716, -2716, 24186, + -2716, 4592, 19313, 48069, 971, -2716, -2716, 3680, 3680, 3680, + -2716, 1999, -2716, -2716, 972, 2272, -2716, 42324, -19, -20, + 1812, 1813, -2716, -2716, 1814, -2716, 14768, 1817, -2716, -2716, + 22746, 1525, 978, -2716, 48069, 42324, 989, 48069, -2716, 1818, + -43, 1820, -2716, 7698, 1819, -2716, -2716, -2716, -2716, -2716, + -2716, 33554, 33554, 50454, 1994, -2716, 1994, 10728, 1877, 42324, + 14768, -2716, 996, 2249, 88, 20, 33554, -2716, 42324, -2716, + 34659, -2716, 642, -59, 1828, 14768, 29524, 2051, -2716, -2716, + 2081, -2716, 2141, -2716, 50454, 1890, 462, 1908, -2716, -2716, + -2716, -2716, 936, 786, 1450, 1739, 1745, 1838, 42324, 912, + 684, 326, -2716, -2716, -2716, -2716, -2716, -2716, -2716, -2716, + -2716, -2716, -2716, -2716, -2716, 2269, 2049, 2277, 1687, 1003, + 4592, 1007, -2716, 2285, 1611, 1598, 35619, 1848, -2716, 1849, + -2716, -2716, -2716, -2716, -2716, 50454, 981, -2716, 33554, 42324, + -2716, -2716, -2716, 42324, 2215, 1017, -2716, 14768, 1853, 14768, + -2716, 17293, 1845, -2716, 2312, 14768, 1912, 1912, 912, -2716, + 29586, 1526, 24186, 50454, 50454, 50454, -2716, 1978, 608, 642, + 1022, -2716, 1869, -2716, -2716, -2716, -2716, 2234, -2716, 29651, + 2085, 217, 2069, 1828, -2716, 14768, -2716, 1930, -2716, -2716, + -2716, 2321, -2716, -2716, 38019, 1865, 1745, 1739, 1569, 2075, + -2716, 2078, 1870, 1450, -2716, 14768, 485, -2716, -2716, 42324, + -2716, 1024, 1872, 1873, -2716, -2716, -2716, 1878, 17293, 1881, + -2716, 50454, 1884, 33554, 2016, -2716, -2716, -2716, 2249, -2716, + -2716, -2716, 290, -2716, 290, 27067, 2081, -2716, 34659, 28029, + 2050, -59, 2175, -2716, -2716, -2716, -2716, 184, 2099, -2716, + 2100, -2716, 33554, -2716, 912, 38019, -2716, -2716, -2716, -2716, + -2716, 24186, 1526, 1446, 17798, 17798, 1885, 1040, -2716, 2375, + 2046, -2716, -2716, 1891, -2716, -2716, -2716, 41844, 50454, 1507, + 1507, 1526, 2069, -2716, -2716, -2716, -2716, -2716, 185, 185, + 2268, -2716, 1953, -2716, 1745, 1050, -2716, 18808, 2036, 263, + 32693, -2716, -2716, -2716, -2716, -2716, 1894, 1896, -2716, -2716, + -2716, 290, -2716, -2716, -2716, -2716, -2716, 2372, -2716, 216, + -2716, -2716, -2716, 1450, 2362, -2716, -2716, -2716, -2716, -2716, + -2716, 2390, 1507, 642, -2716, -2716, -2716, 1526, 18303, 1900, + -2716, -2716, -2716, -2716 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -2671, -2671, -2671, 1771, -2671, -2671, -2671, 197, -2671, 902, - -2671, 194, -495, 541, -2671, -2671, -2671, -931, 10, -2671, - -2671, -2671, -2671, -5, 255, -2671, -482, -1887, -232, -2671, - -2521, -2598, -2671, -2671, -553, -2459, -1692, -2671, -2671, -2671, - -2671, -1123, 172, -2671, -2159, -2671, -622, -989, -801, -1004, - -2671, -51, -2671, 1217, -1114, -1794, -2436, -493, -2671, -589, - -2671, -231, -2671, -536, -2671, -734, -543, -574, -2401, -952, - -2671, 1427, -277, -2671, 586, -2671, -2142, -2671, -2671, 575, - -2671, -963, -2671, -1874, 192, -523, -1908, -2147, -1803, -629, - 265, -534, 247, -1750, -1001, -2671, 607, -2671, -506, -2671, - -521, -1670, -2671, -2671, -2671, 1201, -666, -2671, 1256, -2671, - -2671, -2671, 13, -2671, -2671, -2671, -2671, -2671, -567, 557, - -2311, -2671, 473, -2671, -2671, -2671, -2671, -89, 246, -2671, - 79, 147, -14, -21, -12, 9, 52, 1510, 1539, -2671, - -1313, 642, -2671, -2671, -1791, -607, -57, -2671, 669, -1372, - -1741, -466, 1018, 1491, 1496, -373, -393, -2671, -512, -2671, - -1312, -2671, -2671, 667, 1061, -1248, -1272, -2671, 366, -2671, - -449, -379, -2671, -2671, -2671, -2671, -2671, 101, -282, -427, - 1039, -2671, 1503, -2671, -2671, -2671, -2671, -2671, -1239, -2671, - 712, -2008, 391, -1993, -1858, 140, 126, -1204, -252, 16, - 399, -342, -2671, -2671, -340, -1704, -2395, -357, -356, -2671, - -2671, -2671, -478, -1119, -700, 1333, -2671, 853, -483, -2671, - -2671, -2671, 2106, 2289, -2671, -2671, 2331, 2336, -2671, -555, - 2377, -522, -681, 1204, -1075, 1206, -1095, -1070, -1080, 1208, - 1209, -1245, 2881, -1559, 432, 38, -2671, -2445, -1687, -2671, - -2671, -2671, -114, -2671, -423, -2671, -428, -2671, -2671, -2671, - -465, -2670, -2671, 1141, 822, -2671, -2671, -2671, -1271, -2671, - 3964, 717, -2671, -1637, -874, -564, 1230, -749, -993, -1163, - -2671, -2671, -2671, -2671, -2671, -2671, -1681, -1764, -524, 787, - -2671, -2671, 904, -2671, -2671, -2671, -582, 1005, -562, -851, - 793, -2671, 137, 1948, -1336, -2671, 761, -1944, -2671, -2671, - 415, -2671, 2286, -464, -1621, 620, -986, 49, -2671, 3059, - 298, 1730, -870, -2124, -2671, -2671, -494, -2254, -918, -2671, - -611, -2671, -2671, -2671, -1176, -2671, 624, -2671, -1112, -2671, - -300, -2671, -2671, -2151, -2671, -2671, -2671, -2671, -2671, -2671, - -405, -2671, -475, -474, -2671, -2671, 18, -793, 1281, -2671, - -2671, 511, -2671, 929, -2671, 702, -2671, 67, -2671, 1142, - -2671, -2671, -2671, 23, 1574, 407, -2671, 1144, -2671, -2671, - -2671, -2671, -2671, 913, -2671, -1110, -2555, 65, -2345, -626, - -6, -2671, -2671, -2671, -507, -2671, -2123 + -2716, -2716, -2716, 1773, 69, -2716, -2716, 192, -2716, 884, + -2716, 178, -596, 514, -2716, 78, 80, -1002, 29, -2716, + -2716, -2716, -2716, -25, 239, -2716, -505, -1928, -254, -2716, + -2509, -2586, -2716, -2716, -570, -2505, -1752, 84, 89, 4, + 150, 90, -2188, 92, -650, -1052, -794, -1058, -2716, -71, + 97, 1432, 5, -1858, -2480, -512, -2716, -620, -2716, -267, + -2716, -567, -2716, -518, -575, -606, -2390, -1001, -2716, 1394, + -309, -2716, 554, -2716, -2182, -2716, -2716, 537, -2716, -1023, + -2716, -1841, 166, -549, -2195, -2199, -1851, -664, 236, -555, + 218, -1832, -812, -2716, 570, -2716, -539, -2716, -647, -1794, + 100, -2716, -2716, 1169, -752, -2716, 1215, 102, -2716, -2716, + 30, 104, -2716, -2716, -2716, -2716, -641, 503, -2268, -2716, + 443, -2716, -2716, -2716, -2716, -138, 198, -2716, 8, 118, + -4, -30, 2, 28, 61, 1458, 1485, -2716, -889, 787, + -2716, -2716, -2716, -1846, -629, -52, -2716, 621, -1426, -1804, + -487, 970, 1460, 1464, -425, -443, -2716, -562, -2716, -1522, + -2716, -2716, 612, 1006, -1293, -1318, -2716, 316, -2716, -498, + -432, -2716, -2716, -2716, -2716, -2716, 52, -330, -473, 990, + -2716, 1476, -2716, -2716, -2716, -2716, -1737, -1285, -2716, 665, + -2021, 352, -2037, -1897, 103, 87, -928, -289, 15, 367, + -375, -2716, -2716, -373, -1748, -2389, -390, -388, -2716, -2716, + -2716, -514, -1192, -726, -2716, -2716, 572, -454, -2716, -2716, + -2716, 743, 765, -2716, -2716, 1229, 2218, -2716, -593, 2310, + -479, -712, 1172, -1077, 1176, -1086, -947, -1096, 1177, 1179, + -1304, 3395, -1628, -806, -5, -2716, -1805, -1601, -2716, -2716, + -2716, -152, -2716, -459, -2716, -458, -2716, -2716, -2716, -502, + -2715, -2716, 1105, 790, -2716, -2716, -2716, -1298, -2716, 4175, + 681, -2716, -1697, -936, -605, -919, -800, -1064, -1218, -2716, + -2716, -2716, -2716, -2716, -2716, -1168, -1824, -729, 748, -2716, + -2716, 864, -2716, -2716, -2716, -614, 969, -590, -900, 760, + -2716, 108, 1939, -1381, -2716, 726, -1996, -2716, -2716, 382, + -2716, 2135, -475, -991, 2407, -1038, 42, -2716, 3770, 138, + 1652, 1785, -2181, -2716, -2716, -499, -2261, -986, -2716, -628, + -2716, 106, -2716, 717, 111, 583, -2716, 9, -2716, -331, + -2716, -2716, -2216, -2716, 115, 117, -2716, -2716, -2716, -424, + -2716, -490, -489, -2716, -2716, 6, -853, 1247, -2716, 120, + 400, -2716, 895, -2716, 745, 123, 66, 128, 1106, -2716, + -2716, -2716, 33, 1542, 370, -2716, 1112, 131, -2716, -2716, + 136, -2716, 793, 139, 10, -2583, 141, -2351, -1454, -6, + -2716, -2716, -2716, -521, -2716, -2175 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -1773 +#define YYTABLE_NINF -1847 static const yytype_int16 yytable[] = { - 482, 649, 609, 1009, 975, 1485, 1249, 732, 1188, 61, - 43, 1150, 1305, 54, 1256, 747, 1643, 1310, 1484, 1449, - 1545, 1143, 598, 76, 933, 61, 1741, 945, 1162, 1783, - 1516, 809, 1786, 1194, 543, 1460, 2157, 738, 1312, 1517, - 611, 1519, 2127, 1520, 478, 2132, 723, 584, 2036, 612, - 2101, 720, 1147, 1456, 1359, 479, 1496, 2490, 2492, 2513, - 1438, 2511, 748, 2095, 803, 83, 1265, 1367, 740, 1549, - 2527, 1232, 1681, 1682, 1235, 2060, 2150, 2343, 2095, 56, - 2524, 1489, 2120, 2193, 2194, 2195, 2205, 596, 554, 1997, - 1998, -452, 1602, 2304, 2018, 826, 826, 934, -1080, 2360, - 2862, -734, -1105, -734, -1645, -726, 627, -1648, 486, 579, - -1102, -1102, -1750, -1750, 1195, -1753, -1753, 1243, 1174, 1175, - 1195, -455, 826, 2686, 1151, 1374, 3, 4, -1105, 1195, - 1008, 1754, 1014, 2714, 1018, -1657, 2047, 2048, 810, -1648, - -1664, 550, 968, -1762, -1762, 1186, -1106, 57, -1769, -1769, - 1807, -1771, -1771, 2217, -1103, -1103, -731, 550, -1657, 619, - -731, 826, 588, 57, 2629, -1664, -1106, 2674, 1521, 2762, - -1645, -693, 1804, 1979, -706, -721, 550, 57, 550, 662, - 1238, 971, 2690, 597, 1694, -452, 732, 1618, 1441, 2000, - 1371, 1243, 550, 1194, 2001, 1469, 826, 2668, 1472, 1473, - -412, 601, 1620, 1694, 2802, 2735, 1321, 1616, 610, 1195, - 2987, 1323, 1619, 2000, 1321, -455, -953, 1731, 2001, 1323, - 2257, 2259, 606, -953, 1732, 723, -183, 57, 2787, 2773, - 2382, -183, 1461, 2358, 2224, 2831, 2663, 1329, 2818, 2528, - 2892, 2829, 2864, 2640, 2865, 1329, 1738, 1715, 2613, 606, - 1409, 547, 2762, 2943, 982, 2803, 1409, 2847, 1879, 2293, - 983, -973, 1891, 935, 2804, 936, 2933, 2687, -973, 1331, - 3034, 1494, 2430, 2547, 1810, 2401, 2626, 1331, 1495, 1174, - 1175, 1406, 2688, 1780, 2832, -1747, -1747, 1444, 565, 602, - 1321, 84, 1321, 2805, 732, 1468, 1410, 1323, 2814, 2872, - 809, 1825, 1410, 1372, 2181, 1186, 2815, 809, 2369, 964, - 2388, 1825, 958, 1452, 2271, 2000, 1452, 2182, 551, 551, - 2001, 1301, 2278, 1329, 1487, 2110, 3023, 2185, 1313, 1969, - 546, 604, 2963, 723, 1970, 1257, 85, 2153, 2801, 2844, - 2955, 2586, 591, 2294, 2431, 2590, 2638, 2360, 549, 2627, - 1483, 1147, 2662, 1331, 2400, 1331, 2269, 1369, 2873, 1826, - 2111, 2964, 1411, 2532, 2806, 599, 984, 3041, 2680, 2147, - 1781, 3025, 1461, 1716, 2681, 2389, 2807, -452, -579, 3010, - 2714, 1811, 2158, 966, 1369, 1971, 2944, 1407, 1739, 1717, - 2391, 566, 548, 2891, 1718, 2150, 2095, 2150, 2095, 605, - 2529, 2641, 691, 1196, 1375, 1412, 2977, -455, 2785, 1196, - 2866, 1412, 2684, 1437, 1880, 959, 2762, 1658, 1196, 2639, - 2833, 809, 809, 2548, 1373, 1462, 2830, 2432, 927, 600, - 3035, 1719, 1498, 2081, 2082, 614, 3015, 1278, 3021, 1446, - -452, 1643, 2273, 2274, 2275, 2276, 2277, 1499, 1459, 2281, - 2282, 2283, 2284, 2285, 2286, 2287, 2288, 2289, 2290, 1599, - 2614, 2685, 2279, 2945, 2689, 1413, 613, 1945, 3, 4, - -455, 1413, 2280, 732, 2154, 2816, 663, 606, 630, 1820, - 2888, 2576, 1947, 1949, 1950, 1390, 1944, 1459, 2630, 589, - 1490, 1606, 1946, 1948, 2159, 2956, 61, 635, 1196, 2618, - 636, 2994, 2983, 2322, 2323, 1878, 2541, 2545, 1892, 1435, - 639, 2103, 723, 2966, 2130, 2762, 2644, 2669, 603, 2135, - 985, 3026, 631, 734, 598, 1485, 632, 2988, 2201, 2202, - 536, 2794, 808, 645, 1534, 1461, 1901, 1386, 2122, 2774, - 2490, 2492, 1804, 1143, 937, 1695, 61, 1189, 1436, 1172, - 657, -452, 2957, 1447, 976, 487, 805, 1197, 1189, 611, - 1189, 482, 482, 1231, 2062, 1462, 637, 2808, 612, 1190, - 2809, 986, 1234, -953, 1733, 987, 2653, 2654, 1720, 2724, - 1190, -455, 1190, 1940, 2728, 482, 2715, 2730, 2105, 631, - -452, -1080, -452, 632, 1191, -1105, 1193, -1645, -726, 2205, - -1648, 2620, 1247, 1248, 2786, 988, 1878, 938, 2704, 61, - 43, 1522, 1542, 54, 1575, 812, 1752, 607, -973, 956, - -455, -1105, -455, 76, 1058, 482, 1144, 1459, -1657, 1546, - 1547, 506, -1648, -1664, 57, 535, 1294, 1168, 2886, -1106, - 660, 2897, 2890, 556, 947, 1522, 3016, 1584, 985, -731, - 1316, -1657, 650, 1488, 595, 595, 2186, 2896, -1664, -1106, - 732, 732, 2095, -1645, 1176, 83, 2095, 1180, -721, 1365, - 1855, 1755, 2016, 989, 928, 732, 1247, 1248, 661, 56, - 1858, 1169, 1479, 1861, 57, 597, 1349, 1350, 1351, 1352, - 1604, -667, 2617, 2013, 2014, 2015, 2016, 1352, 664, 723, - 723, 2161, 734, 2160, 720, 2161, 1480, 1603, 623, 1301, - 1474, -183, -183, 1610, 723, 2768, 2667, 1691, 1572, 1554, - 489, 2839, 1643, 665, 651, 3017, 1656, 610, 1462, 2443, - 1604, 1147, 2410, 2162, 2778, 809, 738, 1566, 482, 2404, - 666, 1313, 982, 1570, 652, 929, 2511, 57, 983, 1511, - 1679, 2961, 3018, 2619, 814, 1511, 2411, 1143, 820, 2646, - 2672, 2332, 2333, 2334, 2335, 815, 1576, 2651, 803, 1567, - 1347, 1348, 1349, 1350, 1351, 1352, 744, 1604, 489, 964, - 653, 490, 982, 1962, 965, 1604, 1922, 1147, 983, 1461, - 1459, 1964, 964, 2011, 2012, 2013, 2014, 2015, 2016, 732, - 2309, 808, 1211, 1212, 26, 26, 1310, 2681, 808, 1058, - 734, 2240, 1479, 652, 2490, 2492, 2213, 2244, 1614, 61, - 550, 1512, 550, 2040, 2405, 1578, 482, 2676, -667, 1580, - 826, 2771, 1461, 2414, 826, 746, 1480, 1697, 723, 490, - 2104, 31, 31, 1683, 811, 1854, 551, 813, 1847, 653, - 1485, 816, 1475, 966, 984, 482, 1170, 631, 2637, 2351, - 1476, 632, 1767, 655, 818, 1305, 966, 1321, 1513, 924, - 2052, 3036, 598, 819, 1513, 482, 482, 482, 1929, 482, - 482, 2417, 33, 33, 2196, 654, 537, 1874, 1875, 1876, - 2406, 2095, 2407, 2352, 984, 2318, 34, 2053, 1329, 1951, - 2095, 1952, 967, 482, 1954, 2095, 1452, 1493, 2095, 2592, - 2130, 1143, 1215, 1216, 641, 967, 642, 1453, 982, 2354, - 35, 2350, 808, 808, 983, 1203, 1204, 2095, 2124, 732, - 1331, 2187, 655, 1241, 538, 36, 1242, 563, 982, 1398, - 1399, 982, 1405, 581, 983, 1817, 820, 983, 612, 612, - 2184, 612, 821, 493, 1461, 494, 482, 57, 1452, 926, - 482, 482, 2225, 1171, 1461, 1184, 1185, 2232, 723, 1455, - 956, 482, 1853, 1829, 2868, 1384, 1189, 1926, 1385, 87, - 497, 1189, 1462, 1856, 932, 1203, 1204, 2700, 1859, 734, - 643, 1864, 644, 620, 1900, 1281, 1871, 2351, 1190, 948, - 536, 1205, 1206, 1190, 2133, 1914, 941, 1915, 985, 826, - 2095, 493, 1191, 494, 1058, 2054, 949, 1193, -464, 2717, - 2055, 1058, 1968, 951, 2718, 1462, 1972, 1486, 1973, 952, - 984, 2352, -464, 1303, 732, 631, 2776, -464, 497, 1368, - 2356, 2421, 2095, 1058, 1459, 1768, 2596, 2353, 985, 2599, - 984, 954, 631, 984, -1080, 955, 632, 2354, 2074, 1012, - 2075, 1205, 1206, 987, -1745, -1745, 1207, 1208, 1209, 1210, - 1211, 1212, 2188, 723, 1213, 1214, 962, 809, 1938, 732, - 922, 923, 2192, 925, 2422, 977, -464, 1459, 1516, 1598, - 809, 2355, 1599, 1013, 2076, 2828, 2077, 1517, 2029, 1519, - 2423, 1520, 2172, 987, 2174, 1252, -464, 610, 610, 979, - 610, 982, 1252, 2828, 26, 1917, 1703, 983, 723, 1643, - -1746, -1746, 1600, 1975, 659, 1601, 1207, 1208, 1209, 1210, - 1211, 1212, 980, 988, 1213, 1214, 2050, 2028, 2095, 2030, - 2031, 88, 2819, 1704, 2397, 2099, 2399, 1462, 1144, 89, - 2591, 31, 2594, 743, 2558, -464, 2928, 1462, 2441, -1748, - -1748, 989, 2056, 1305, -464, -1749, -1749, 2169, 2253, 2171, - 482, 981, 2434, 2057, 2095, 995, 734, 734, 2356, 1763, - 1215, 1216, 1234, 2398, 985, 90, 1888, -1751, -1751, 1889, - 1315, 734, 33, 1930, 996, 993, 1601, 1936, 2424, 1318, - 1937, 989, -1752, -1752, 985, 2425, 34, 985, 2433, 1459, - 2442, 994, 595, 1366, 2508, 1958, 1011, 2912, 1959, 1459, - 3032, 1015, 92, 984, 1376, 485, 1252, 1252, -501, 1148, - 35, 534, 91, -501, 1149, 1016, 808, 3011, 3012, 987, - 1215, 1216, 564, 1154, 1769, 997, 577, 961, 2175, 963, - 61, 2176, 1144, 2242, 2243, 1816, 1705, 2995, 1862, 987, - 805, 1706, 987, 1152, 2380, 482, 1707, 482, 2210, 1017, - 482, 482, 2179, 2095, 26, 2180, 3013, 61, 635, 2220, - 482, 636, 482, 482, 482, 482, 482, 482, 482, 988, - 3039, 639, 1863, 1217, 1218, 2234, 2378, 2383, 1599, 2379, - 2384, 1156, -501, 2519, -464, 2682, 1889, 1157, 482, 2539, - 482, 31, 2540, -1754, -1754, 734, 482, 482, 482, 482, - 482, 482, 1144, -1755, -1755, 1165, 482, 482, -1756, -1756, - 2350, 482, 3040, 26, 1167, 482, 998, 989, 482, 482, - 482, 482, 482, 482, 482, 482, 482, 637, 1584, 482, - 1172, -501, 33, 1217, 1218, 1176, 482, 989, 2559, 1058, - 989, 1601, 1144, 26, 995, 1179, 34, 1180, 631, 1182, - 31, 951, 632, 1219, 1205, 1206, 2705, 985, 1183, 1601, - 2484, 482, 995, 996, -1757, -1757, 2703, 999, 57, 2793, - 35, 732, 1889, 2130, 2821, 1000, 1199, 1601, 1200, 1424, - 31, 996, 482, 938, 36, 1202, 2351, 1001, 1708, 2824, - 1230, 33, 2825, 482, 482, 57, 1237, 2414, 2841, 1709, - 1741, 2842, 1233, 2415, 2845, 34, 2860, 2842, 1869, 2861, - 723, 1236, 987, 2621, 997, 1829, 2416, 1239, 1002, 2441, - 2352, 33, 1240, 1211, 1212, 734, -1758, -1758, 1258, 35, - 489, 1144, 997, 1144, 809, 34, 2353, 1268, 1604, 2248, - 732, 2902, 1870, 36, 2861, 2417, 2354, 2418, 2299, -1759, - -1759, 2903, 1771, -1151, 1601, 2581, 1269, 2915, 732, 35, - 2842, 1701, -697, 2936, 1271, 1004, 2937, 2967, 3004, 2581, - 2968, 2842, 1058, 36, 1273, 482, 482, -704, 482, 723, - 2355, 2437, 1278, 3022, 2265, 732, 2861, 1005, -1760, -1760, - 1276, 490, 732, -1761, -1761, 1277, 1144, 723, -1763, -1763, - 1279, 2725, 2272, 26, 1280, 998, 36, 1007, 1282, 1058, - 989, -1764, -1764, 1178, 2365, 482, 732, -1765, -1765, 2820, - 57, -579, 1604, 998, 723, -1766, -1766, -1767, -1767, 2295, - 734, 723, 2419, 1215, 1216, 1187, 2300, -580, 604, 2978, - 31, 2979, -1768, -1768, -694, 491, -695, 489, 595, 1847, - 1283, 2493, -502, -1770, -1770, 723, 999, -502, 808, 1284, - 1625, 1286, 2537, 1287, 1000, -698, 1229, 2356, 1288, 2507, - -1151, 808, -696, 1058, 999, 734, 1001, -1772, -1772, 1289, - 482, 33, 1000, 1501, 1502, 482, 1805, 1806, -553, -553, - 1213, 1214, 1918, 1290, 1001, 34, 1215, 1216, -557, -557, - 2420, -556, -556, 2538, 1291, 2421, 605, 1002, 490, 1292, - 1380, 1382, 1293, 2649, 1294, 492, 598, 2984, 3031, 35, - 1298, 1311, 482, 482, 482, 1002, -502, 482, 1314, 1360, - 1362, 1357, 1363, 36, 1378, 482, 482, 482, 482, 732, - 1387, 1388, 1391, 1397, 965, 482, 967, 2130, 2422, 482, - 1433, 1431, 482, 1756, 1004, 2726, 1439, 1457, 1459, 1458, - 57, 2791, 1899, 493, 2423, 494, 598, 1464, 1465, 482, - 482, 2514, 1004, 1466, 482, -502, 1005, 1470, 723, 1178, - 1477, 495, 1478, 2487, 606, 1482, 1492, 496, 482, 1497, - 497, 482, 1504, 482, 1005, 1505, 1007, 1187, 1509, 1514, - 1629, 1652, 1515, 732, 1522, 1527, 1530, 1531, 1630, 1631, - 1632, 1633, 1533, 482, 1007, 1535, 480, 1541, 826, 1548, - 2610, 507, 1550, 1551, 482, 507, 1561, 2253, 1562, 1557, - 552, 552, 555, 507, 560, 598, 1558, 560, 1563, 482, - 560, 586, 723, 1564, 507, 507, 1571, 2536, 1597, 1606, - 1611, 1321, 1671, 61, 635, 1673, 1188, 636, 482, 1677, - 2658, 2659, 2424, 1147, 1675, 1676, 1678, 639, 2093, 2425, - 1693, 1700, 1711, 482, 482, 732, 1712, 1303, 1604, 479, - 493, 1714, 494, 2093, 1736, 1735, 1750, 1757, 1765, 26, - 560, 1772, 482, 1585, 479, 1764, 605, 586, 507, 586, - 586, 586, 1784, 1794, 496, 1796, 1795, 497, 1797, 1798, - 1144, 1144, 1144, 1799, 723, 1815, 1818, 1822, 1823, 1824, - 1793, 1886, 606, 637, 607, 1894, 31, 1303, 1890, 1904, - 1905, 1902, 1903, 1923, 1568, 1919, 1569, 1924, 1586, 1925, - 1927, 1931, 1928, 2484, 1953, 1701, 1934, 1932, 1305, 1933, - 1955, 1058, 1935, 1942, 1943, 1956, 1957, 1965, 1976, 1977, - 825, 2069, 1252, 2000, 1587, 1988, 1967, 33, 2001, 2002, - 2003, 2004, 1993, 1983, 2046, 1252, 1985, 2086, 1986, 1987, - 1989, 34, 1588, 1990, 1992, 1996, 1589, 734, 2019, 2020, - 2025, 57, 2086, 2026, 2033, 2044, 597, 482, 2051, 2058, - 2067, 2635, 2068, 732, 2070, 35, 2071, 2072, 1590, 2097, - 2107, 1591, 2109, 2116, 2121, 1485, 2123, -558, -559, 36, - 825, 2125, 2136, 2000, 2139, 2137, 1592, 2140, 2001, 2002, - 2003, 2004, 2141, 1144, 732, 808, 2143, 2145, 2146, 2168, - 2149, 2170, 723, 2183, 2189, 2197, 2311, 2657, 2190, 2191, - 2198, 2200, 2209, 482, 2199, 2222, 734, 2208, 2212, 2227, - 2223, 2226, 482, 2230, 2233, 482, 2237, 2239, 482, 2249, - 2256, 2246, 2264, 723, 734, 482, 482, 482, 482, 482, - 2129, 2022, 482, 482, 482, 482, 482, 482, 482, 482, - 482, 482, 2247, 2328, 2779, 482, 482, 2000, 2021, 482, - 2317, 734, 2316, 598, 2296, 2297, 482, 732, 734, 2298, - 2962, 482, 2329, 809, 2302, 2301, 1918, 2330, 1593, 2314, - 482, 2320, 2079, 482, 2341, 482, 1594, 2349, 2367, 2363, - 2372, 2375, 734, 482, 598, 2377, 482, 482, 2381, 2392, - 2390, 482, 482, 1821, 2396, 2373, 723, 2409, 2005, 2429, - 2403, 598, 2402, 1830, 2510, 1833, 2445, 482, 1844, 482, - 1652, 1652, 2504, 2518, 1848, 1652, 1850, 2505, 2506, 1595, - 2006, 482, 2517, 2521, 2522, 2526, 2533, 2543, 1857, 1889, - 2546, 482, 2535, 1860, 57, 2549, 2578, 1865, 1866, 1867, - 1868, 2550, 1872, 1873, 2551, 2552, 2553, 482, 2567, 2579, - 2582, 2093, 2585, 2093, 2587, 2588, 2595, 1652, 1652, 2600, - 2601, 2602, 479, 2603, 479, 2616, 2624, 2484, 2605, 2622, - 2178, 2628, 732, 2623, 2632, 2633, 2642, 2645, 2647, 2648, - 2006, 2634, 2652, 2665, -1102, 2666, 2675, -1745, 2871, -1746, - 2007, -1747, -1748, -1749, -1750, -1751, -1752, -1754, -1755, -1756, - 1144, -1757, -1758, -1759, 1144, 2491, 1144, -1760, -1761, -1763, - 732, 723, -1764, -1765, 1303, 2204, 2487, 2664, -1766, -1767, - -1768, -1769, 2677, 2691, -1770, 2692, -1771, 1634, 1635, 1636, - 2216, 1637, 1638, 1639, 1640, 1641, 1642, -1772, -1103, 2673, - 2694, 732, 2698, 2701, 732, 1303, 2905, 2678, 586, 723, - 2007, 2697, 647, 2702, 2716, 648, 2729, 2752, 2764, 2734, - 2339, 2758, 2342, 2766, 507, 2756, 2767, 2781, 2935, 734, - 2769, 2782, 2783, 2790, 2792, 2797, 2798, 2812, 2799, 2813, - 723, 1203, 1204, 723, 2939, 2843, 482, 2822, 2843, 1252, - 2826, 648, 507, 507, 2254, 2834, 2255, 2835, 2850, 2836, - 2260, 2261, 2854, 2838, 2846, 2848, 2862, 2857, 552, 2876, - 2641, 2880, 2916, 2882, 2918, 2884, 2887, 2893, 2512, 2883, - 2898, 2899, 2900, 2904, 2908, 2920, 2909, 919, 919, 560, - 560, 2917, 560, 2921, 2923, 482, 482, 2938, 2934, 2941, - 482, 734, 2530, 586, 2531, 482, 2946, 2953, 482, 482, - 2952, 2954, 507, 482, 2958, 2959, 2871, 1205, 1206, 2976, - 2986, 2960, 2569, 586, 2989, 2969, 2991, 3005, 3006, 2987, - 2970, 2971, 2973, 482, 2988, 586, 3003, 482, 3008, 3024, - 3029, 3037, 3030, 3033, 3038, 3042, 57, 2008, 2009, 2010, - 2444, 2011, 2012, 2013, 2014, 2015, 2016, 1849, 2930, 482, - 2448, 953, 2166, 622, 2612, 625, 2385, 629, 2757, 2929, - 57, 2980, 57, 586, 586, 586, 586, 2093, 2655, 2950, - 2520, 2093, 1207, 1208, 1209, 1210, 1211, 1212, 479, 3020, - 1213, 1214, 479, 482, 2985, 2777, 2992, 3014, 2811, 1448, - 2148, 482, 2173, 2990, 2982, 2525, 732, 2008, 2009, 2010, - 2413, 2011, 2012, 2013, 2014, 2015, 2016, 2449, 2144, 2981, - 482, 1565, 2250, 1652, 1652, 1652, 1652, 1652, 1544, 734, - 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, 1652, - 2206, 2699, 2509, 2128, 1814, 723, 2609, 2611, 1389, 1370, - 2487, 1428, 2911, 2925, 3009, 1427, 2138, 2371, 2972, 1791, - 2491, 2919, 2606, 2856, 1813, 1432, 2344, 2106, 2840, 2489, - 2577, 2593, 2340, 2907, 2906, 2913, 1615, 2914, 1617, 1525, - 1621, 1622, 2755, 2975, 1652, 1652, 2086, 2974, 2042, 3002, - 2086, 1740, 2131, 1605, 2204, 2065, 1215, 1216, 2063, 1885, - 825, 1980, 2608, 2000, 2100, 2370, 921, 2901, 2001, 2002, - 2003, 2004, 2211, 1577, 57, 57, 1974, 1759, 1392, 2386, - 1761, 0, 0, 0, 808, 0, 2312, 2229, 0, 0, - 482, 0, 0, 734, 0, 0, 482, 0, 0, 0, - 1270, 0, 0, 0, 0, 482, 482, 0, 0, 482, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 482, 0, 0, 0, 0, 0, 0, 0, - 0, 482, 0, 0, 0, 0, 482, 0, 0, 482, - 0, 0, 0, 0, 0, 825, 482, 482, 2000, 0, - 0, 2683, 0, 2001, -1773, -1773, -1773, 0, 482, 0, - 482, 0, 0, 0, 0, 0, 2093, 1309, 0, 1217, - 1218, 0, 0, 0, 0, 2093, 0, 479, 482, 0, - 2093, 0, 0, 2093, 0, 725, 479, 0, 0, 0, - 0, 479, 0, 0, 479, 0, 0, 0, 0, 0, - 0, 0, 2093, 0, 0, 0, 0, 0, 2491, 0, - 586, 0, 0, 479, 0, 0, 0, 0, 0, 57, - 2607, 0, 825, 0, 0, 2000, 0, 0, 507, 507, - 2001, 2002, 2003, 2004, 586, 586, 1396, 0, 0, 0, - 0, 482, 0, 0, 0, 482, 734, 0, 2561, 0, + 488, 484, 676, 1211, 47, 51, 1070, 640, 56, 66, + 82, 1365, 1548, 1036, 1249, 1315, 1547, 1006, 1293, 1451, + 1512, 1296, 568, 753, 870, 1212, 1606, 994, 61, 43, + 54, 642, 629, 76, 1255, 1204, 1846, 2218, 611, 1849, + 771, 1803, 2188, 1519, 61, 2193, 615, 1523, 485, 1704, + 1371, 1208, 1559, 1501, 779, 2578, 864, 1610, 765, 2211, + 1069, 2555, 1075, 643, 1079, 773, 1419, 2557, 2162, 40, + 2576, 1552, 1742, 1743, 1308, 2147, 1324, 2120, 41, 1427, + 42, 2058, 2059, 756, 45, 2181, 2079, 586, 650, 46, + 48, 2147, 49, 2254, 2255, 2256, 627, 50, 2587, 2590, + 52, 2360, 53, 2266, 55, 658, 64, 1235, 1236, 492, + 2407, 65, -1081, -447, 887, 67, 2419, 68, 57, 887, + 73, 1961, -450, 74, 2401, 1256, -724, 1466, 75, 2107, + 2108, 78, 1256, 1256, 57, 2275, 79, -732, 1247, 81, + 995, 83, -1844, -1844, 871, 1816, 2061, 582, 57, -1106, + 2062, -729, 1029, -1106, 628, -729, -1671, -1678, 583, 583, + -1672, -1103, -1103, 2923, -1818, -1818, 1032, 1872, -1819, -1819, + 3, 4, 1299, -1673, 582, -1674, -1687, 1584, 887, 641, + -1675, -1820, -1820, -1821, -1821, -1695, -732, -1678, -1822, -1822, + 1869, -1107, -1671, 1434, -1687, -1825, -1825, 2748, 57, 2314, + 2316, -1693, -1834, -1834, -1695, -1672, 2040, -1697, -447, -1840, + -1840, 2156, -1842, -1842, -1673, -1845, -1845, -450, -1674, -1675, + -1107, 1380, 1487, 1255, 1515, 1381, 2737, 2156, -1104, -1104, + -691, 619, 1504, 1515, -954, 1550, 632, 1756, 2834, 2752, + 635, -954, -704, 1229, 2246, 3076, 1681, 2848, 1756, -407, + 2441, 1256, 495, 1389, 2879, 2417, 1679, 1956, 1524, 2282, + 2350, 765, 1793, 1532, -974, 1677, 1535, 1536, 689, 1794, + 637, -974, -1693, 2953, 2796, -1152, 2676, 2489, 1800, 637, + -1697, 1557, -719, 582, 582, 1391, 756, 1230, 2707, 2892, + 2890, 1043, 1558, 2926, 2726, 2703, 1302, 1044, 1431, 1302, + 582, 887, 1235, 1236, 887, 2731, 3048, 996, 636, 997, + 2749, 2609, 1574, 496, 2428, 2925, 579, 2591, 1603, 2875, + 1875, 2214, 597, -665, 633, 2750, 1019, 2876, 1247, 1843, + 1531, 1507, 2689, 3095, 1944, 2908, 2447, 2933, 2893, 2994, + -178, 1361, 3084, 2746, 1025, -178, 1890, 870, 2692, 2490, + 578, 2459, -1815, -1815, 870, 1250, 622, 2326, 2061, 2725, + 2419, 1372, 2062, 2407, 2171, 2222, 2742, 1964, 2061, 2460, + 581, 875, 2062, 3016, 2211, 1380, 2211, 1251, 1542, 1381, + 1208, 1316, 876, 3102, 1575, 2743, 637, 2649, 2450, 3004, + 1429, 2653, 2747, 2502, 2862, 1680, 2934, 630, 765, 2172, + -447, 2448, 1543, 1045, 1891, 2690, 2905, 1389, 2400, -450, + 1272, 1273, 1432, 1666, 1257, 1719, 1844, 1429, 1027, 1469, + 1801, 1257, 1257, 756, 631, 598, 1025, 1876, 3086, 1020, + 644, 1576, 2491, 1500, 2330, 2331, 2332, 2333, 2334, 1391, + 26, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345, 2346, + 2347, 1525, 3071, 2704, 2595, 3077, -576, 580, 2215, 2927, + -665, 2610, 1231, -447, 2846, 2952, 1380, 1028, 870, 870, + 1381, 3082, -450, 1522, 2894, 2891, 1704, 31, 2592, 3038, + 1561, 2603, 1885, 1509, 661, 499, 2701, 500, 2677, 1656, + 1945, 2829, 1562, 3096, 2378, 2379, 2877, 1943, 1389, 2639, + 1027, 666, 645, 1957, 2607, 1338, 672, 2751, 1435, 502, + 2839, 722, 503, 1522, 2164, 2278, 3055, 2681, 33, 3044, + 1276, 1277, 3005, 1890, 1667, 1470, 638, 2011, 2013, 2014, + 1391, 767, 1548, 1433, 3078, 2262, 2263, 2009, 2196, 869, + 1257, 629, 2156, 1713, 2156, 2008, 2555, 1966, 2835, 1498, + 2191, 866, 2557, 634, 2855, 2183, 493, 1046, 620, 2702, + 1595, 3079, 1869, 1499, 1551, 690, 2732, 3017, 1258, 1232, + 36, 1233, 61, 2247, -447, 1292, 1295, 765, 3087, 1446, + 3027, 2208, 642, -450, 2949, 662, 684, 1204, 998, 663, + 1037, -954, 1943, 488, 488, 1250, 2683, 1510, 1757, 3006, + 2716, 2717, 756, 2004, 662, 2776, -1081, 3018, 663, 2122, + 2266, 57, 1048, -447, 643, -447, 488, 1251, 2765, 1795, + -724, -974, -450, 3049, -450, 1814, 999, 687, 1354, 2785, + 2077, 1252, 1361, 1380, 2789, 47, 51, 2791, 2951, 56, + 66, 82, 1049, -1106, 1250, -729, 873, -1106, 688, 1017, + -1671, -1678, 1607, 1608, -1672, 1125, 488, 1205, 1380, 61, + 43, 54, 57, 628, 76, 1858, 1251, -1673, 1375, -1674, + -1687, 2147, 2693, 2958, -1675, 2147, 2010, 2012, 2957, -1695, + 1254, -1678, 2335, 2469, 1008, -1107, -1671, 1635, -1687, 1641, + 1389, 2680, 887, 1515, 2709, -1693, 692, 1391, -1695, -1672, + 40, -1697, 2714, 1586, 1516, 1412, 691, 2470, -1673, 41, + 1050, 42, -1674, -1675, -1107, 45, 872, 1665, 583, 874, + 46, 48, 1391, 49, 1237, 1664, 2730, 1361, 50, 753, + 641, 52, 1671, 53, 767, 55, 1241, 64, 765, 2096, + 1920, 985, 65, 2735, 1615, 1717, 67, 3022, 68, 57, + 1923, 73, 2682, 1926, 74, 2576, 1704, 1665, 1208, 75, + 1753, 2463, 78, 756, 765, 765, -1693, 79, 1740, 2900, + 81, 488, 83, 1372, -1697, 693, -719, 1425, 1817, 765, + 870, 1043, 1306, 1307, 84, 1306, 1307, 1044, 2025, 756, + 756, 582, 771, 1627, 1266, 1267, 1986, 1542, 1515, 1631, + 1204, 2365, 2298, 2219, 756, 1665, 1524, 2156, 2302, 1518, + 1633, 2156, 864, 1665, 3024, 1208, 2743, 595, 2555, 1628, + 1830, 1543, 2336, 613, 2557, 777, -178, -178, 1537, 85, + 2832, 2242, 2337, 1981, 2165, 2100, 2775, 2072, 2073, 2074, + 2075, 2076, 2077, 3025, 2243, 495, 2464, 2023, 2700, 2074, + 2075, 2076, 2077, 1993, 1407, 1408, 1409, 1410, 1411, 1412, + 988, 1548, 869, 1272, 1273, 1365, 1744, 3097, 877, 869, + 1125, 767, 2823, 651, 2015, 1043, 2016, 2847, 2257, 2018, + 1919, 1044, 880, 2112, 1585, 2648, 1637, 488, 2328, 1574, + 879, 887, 1759, 1045, 1912, 2659, 881, 1524, 2662, 61, + 2374, 765, 882, 1713, 1713, 2744, 496, 1882, 1713, 87, + 2113, 1524, 2465, 2147, 2466, 2220, 488, 2351, 2147, 2141, + 2142, 2147, 1472, 987, 1546, 2248, 756, 2473, 1939, 1940, + 1941, 1965, 1300, 1043, 1918, 1301, 488, 488, 488, 1044, + 488, 488, 2185, 629, 2191, 993, 635, 1409, 1410, 1411, + 1412, 1713, 1713, 1929, 2823, 1002, 2947, 1204, 1936, 2863, + -499, 2739, 2030, 1585, 488, -499, 1524, 2031, 1473, 1777, + 1538, 2929, 1009, 1276, 1277, 2476, 1250, 2283, 1539, 1524, + 2761, 2194, 2290, 869, 869, 2778, 887, 1045, 1010, 57, + 2779, 1459, 1460, 2089, 1467, 2091, 2092, 1990, 1251, 1525, + 1894, 983, 984, 1831, 986, 2029, 1311, 1333, 1576, 2033, + 2864, 2034, 1252, 1311, 636, 1553, 1012, 488, 2032, 2865, + 1250, 488, 488, 643, 643, 1013, 643, 1341, 2114, 1556, + 1017, 1015, 488, 2115, -499, 765, 1444, 1043, 1016, 1445, + 2156, 1921, 1251, 1044, 1023, 1045, 1924, 1046, 2866, 2156, + 767, 26, 886, 2147, 2156, 2061, 1254, 2156, 1765, 2062, + 756, 1522, -1847, -1847, -1847, 1363, 662, 1038, -1081, 1046, + 663, 88, 26, -1813, -1813, 1125, 2156, 1475, 499, 89, + 500, 2775, 1040, -499, 2245, 1766, 1125, 1549, 31, 662, + 1525, 1374, 637, 663, 1041, 1778, 1524, 2249, 1047, 1332, + 1377, 36, 1048, 2002, 1525, 503, 989, 1210, 662, 31, + 1125, 1779, 1428, 1042, 1426, 90, 1780, 2823, 2090, 2867, + 870, 1054, 1472, 26, 2221, 1436, 2222, 1311, 1311, 33, + 2837, 2868, 1049, 870, 2880, 2480, 1055, 1476, 765, 641, + 641, 1046, 641, 34, 2036, 1978, 2230, 1979, 2232, 1045, + 33, 1704, 1522, 1781, 2223, 2620, 1072, 2110, 2156, 1525, + 31, 1365, 91, 756, 34, 2500, 1522, 35, 1473, 2310, + 2493, 679, 1525, 2989, 668, 2116, 669, 990, 2481, 765, + 1655, 36, 1076, 1656, 2457, 2160, 2117, 1209, 35, 2156, + 881, 2410, 1073, 670, 2482, 671, 1048, 1213, 1767, 1046, + 1050, 33, 1832, 1768, 756, 1245, 1246, 680, 1769, 1205, + 677, 767, 2573, 1215, 2253, 34, 2823, 3093, 1579, 1580, + 2492, 1522, 2501, 1582, 1583, 2411, 1074, 1043, 1474, -1814, + -1814, 488, 638, 1044, 1522, 3072, 3073, 767, 767, 35, + 2134, 2655, 2135, 2274, 1217, 2389, 2390, 2391, 2392, 1218, + 1077, 2413, 767, 36, 1048, 1226, 1713, 1713, 1713, 1713, + 1713, -1816, -1816, 1713, 1713, 1713, 1713, 1713, 1713, 1713, + 1713, 1713, 1713, 1228, 3056, 1657, 2439, 1475, 1658, 1237, + 758, 26, 678, 1239, 1078, 2156, 2300, 2301, 3100, 1525, + 682, 1233, 2483, 3074, 1050, 869, -1817, -1817, 2271, 2484, + 1782, 1953, 759, 1046, 1954, 1248, 1994, 866, 1240, 1658, + 2000, 1205, 2019, 2001, 1241, 2020, 1713, 1713, 31, 1243, + 2236, 2156, 2869, 2237, 488, 2870, 488, 1244, 61, 2240, + 488, 488, 2241, 2068, 1260, 1661, 1025, 1476, 1290, 1045, + 488, 1026, 488, 488, 488, 488, 488, 488, 488, 3101, + 1770, 1522, 1050, 1261, 1881, 61, 1659, 1660, 1048, 33, + 1663, 1771, 2292, 2437, 1263, 1656, 2438, 488, 2136, 488, + 2137, 679, 2415, 34, 767, 488, 488, 488, 488, 488, + 488, 488, 1205, 2233, 1291, 2235, 488, 488, 1049, 26, + 1294, 488, 1641, 2764, 2456, 488, 2458, 35, 488, 488, + 488, 488, 488, 488, 488, 488, 488, 680, 1297, 488, + 1027, 36, -1823, -1823, -459, 2673, 488, 1298, 57, 1125, + 2156, 2442, 1205, 1022, 2443, 1024, 31, 2582, -459, 2191, + 1954, 2601, 2684, -459, 2602, 1317, 1803, 92, 1851, 1327, + 491, 488, 1690, 681, 2500, 57, 542, 2621, 2549, 1691, + 1658, 999, 1692, 1693, 1694, 2766, 1050, 596, 1658, 1028, + 1328, 609, 1834, 1894, 1330, 488, 2854, 33, -498, 1954, + 643, 2882, 2885, -498, 1658, 2886, 488, 488, 2902, 1239, + 1686, 2903, -459, 758, 26, 2654, 1665, 2657, 2356, 2906, + 682, -695, 2903, 1046, 1043, -702, 2921, 1248, 765, 2922, + 1044, 870, -459, 2963, 1642, 759, 2922, 2964, 767, 1336, + 1658, 1338, 1763, 1337, 1205, 1339, 1205, 2976, 2306, 36, + 2903, 31, 2997, 756, 3028, 2998, 1340, 3029, 36, 2322, + -1847, -1847, -1847, 1342, 2072, 2073, 2074, 2075, 2076, 2077, + 3065, -576, -498, 2903, 1927, 2881, -577, 2329, 1048, 1643, + 3083, -459, -692, 2922, 2600, 1125, -1824, -1824, 488, 488, + -459, 488, 33, -693, 765, 1343, 3039, 2424, 3040, -1826, + -1826, 1665, 57, 1818, 2352, 1644, 34, 1344, 1928, 1205, + 1346, 2357, 765, -1827, -1827, 1347, 641, -1828, -1828, 756, + 1125, -498, 1348, 1645, -1829, -1829, 488, 1646, -1830, -1830, + 35, 1349, 1982, -1831, -1831, -696, 1045, 756, 1350, 765, + -694, 767, 2409, 1912, 36, 2558, 765, -1832, -1832, 1647, + 758, 2409, 1648, -1833, -1833, 1351, 2579, 1352, 2572, -1835, + -1835, 495, -1836, -1836, 756, 869, 1353, 1649, 1370, 765, + 1354, 756, 759, -1837, -1837, 3092, 1050, 1358, 869, 1373, + 1125, 1417, 767, 1420, -1152, -1838, -1838, 1422, 486, -1839, + -1839, 488, 1423, 514, 756, 1438, 488, 514, -1841, -1841, + 1713, 1447, 584, 584, 587, 514, 592, -1843, -1843, 592, + 1448, 2852, 592, 617, -1846, -1846, 514, 514, 2410, 1564, + 1565, 1452, 496, 1870, 1871, -550, -550, 2410, 1458, 2712, + -459, 2191, 1026, 488, 488, 488, 1028, 629, 488, 1274, + 1275, 1494, 57, 1276, 1277, 1496, 488, 488, 488, 488, + -554, -554, 2411, 2190, -553, -553, 488, 1502, 2552, 1650, + 488, 2411, 592, 488, 1440, 1442, 1520, 1651, 2412, 617, + 514, 617, 617, 617, 1521, 1522, 497, 2412, 2413, 2310, + 1527, 488, 488, 2721, 2722, 2473, 488, 2413, 629, 1529, + 1046, 2474, 1528, 765, 662, 1533, 761, 1012, 663, 1540, + 488, 1541, 1545, 488, 2475, 488, 1555, 1560, 1567, 1311, + 1652, 1568, 2414, 2028, 1572, 1577, 2889, 1578, 756, 2599, + 1585, 2414, 1311, 1588, 1591, 488, 515, 1592, 1594, 758, + 515, 1596, 1713, 2476, 2889, 2477, 488, 2154, 515, 1602, + 1208, 1934, 2786, 887, 1249, 1048, 498, 1609, 1611, 515, + 515, 759, 488, 2154, 765, 1665, 1612, 1618, 629, 1363, + 1619, 1622, 1623, 1624, 1625, 1661, 1667, 1632, 1654, 1672, + 1380, 488, 1732, 1755, 1734, 1935, 1736, 1737, 1762, 756, + 1773, 1774, 1776, 1738, 485, 61, 1659, 1660, 488, 488, + 1663, 1739, 1797, 1798, 499, 1812, 500, 1365, 1819, 2415, + 485, 1826, 1825, 515, 1827, 1835, 636, 488, 2415, 1828, + 1363, 1847, 501, 1850, 1859, 1861, 1862, 1860, 502, 1863, + 2478, 503, 1864, 1880, 765, 1205, 1205, 1205, 1763, 1883, + 1888, 1887, 1889, 1951, 637, 1967, 1955, 1968, 2973, 1959, + 1969, 1983, 1987, 1050, 2129, 1988, 1995, 2026, 1989, 756, + 1695, 1696, 1697, 1991, 1698, 1699, 1700, 1701, 1702, 1703, + 2146, 1992, 2017, 2549, 2038, 1996, 1125, 1997, 2049, 1998, + 1999, 2006, 1548, 2007, 2037, 57, 2146, 2044, 2046, 2086, + 628, 2047, 2111, 2106, 2127, 2132, 1713, 2048, 2479, 2050, + 758, 2051, 2053, 2480, 2054, 2057, 2787, 2080, 2081, 761, + 2087, 767, 2094, 2104, 2118, 2698, 2128, 2130, 2131, 2170, + 2177, 488, 759, 2182, 2158, 2168, 758, 758, 2184, 2198, + 2720, 2186, -555, -556, 2197, 2200, 2201, 2204, 2207, 2202, + 2206, 758, 2210, 2229, 2231, 2244, 2481, 2258, 759, 759, + 2250, 2251, 2252, 2259, 1205, 2260, 869, 2261, 2270, 2269, + 2281, 2284, 2482, 759, 2273, 765, 2285, 2291, 2280, 3023, + 2288, 2297, 2295, 2304, 488, 2321, 2305, 767, 2313, 2083, + 2061, 2082, 2840, 488, 2353, 2239, 488, 2372, 2354, 488, + 756, 2355, 2358, 2370, 2373, 767, 488, 488, 488, 488, + 488, 765, 2376, 488, 488, 488, 488, 488, 488, 488, + 488, 488, 488, 2387, 2139, 2398, 488, 488, 2384, 2408, + 488, 870, 767, 2422, 2431, 2426, 756, 488, 1056, 767, + 2265, 488, 2432, 629, 2434, 2436, 2440, 2451, 2449, 2455, + 488, 2488, 2462, 488, 2461, 488, 761, 1057, 2468, 2504, + 2585, 2575, 767, 488, 2569, 2570, 488, 488, 2571, 2589, + 2483, 488, 488, 758, 629, 488, 2584, 2484, 2596, 1954, + 2598, 2608, 765, 2650, 2605, 2611, 2641, 488, 2154, 488, + 2154, 629, 2614, 2644, 2612, 759, 617, 2613, 2615, 2647, + 674, 2629, 488, 675, 2642, 2651, 2658, 756, 1058, 2663, + 1311, 2664, 488, 514, 2665, 2311, 2666, 2312, 2687, 2668, + 2685, 2317, 2318, 2679, 2686, 2691, 2695, 2696, 488, 2705, + 2708, 2710, 2697, 2711, 2715, 485, 2728, 485, 2729, -1103, + -1813, 675, 514, 514, 2738, 2740, -1814, -1815, -1816, -1817, + -1818, -1819, 2932, -1820, -1821, 2549, 2754, 2753, 2756, -1822, + 2762, -1823, -1824, 2552, 2736, 1363, -1826, -1827, -1828, -1829, + -1830, -1831, 653, -1832, 656, -1833, 660, -1835, -1836, 2741, + -1837, 1205, 584, -1838, -1839, 1205, 2556, 1205, -1840, -1841, + 2727, -1842, -1843, -1844, -1845, 2790, 1363, -1846, 765, 1059, + -1104, 980, 980, 592, 592, 2966, 592, 758, 2759, 2813, + 2817, 2396, 2763, 2399, 2996, 2777, 617, 2795, 2819, 2825, + 2827, 2828, 1056, 756, 2830, 514, 1579, 1580, 2577, 759, + 2904, 1582, 1583, 2904, 765, 761, 617, 3000, 2842, 2843, + 2844, 1057, 2851, 2853, 2858, 2859, 515, 767, 617, 2593, + 1060, 2594, 2977, 2860, 2979, 2883, 2873, 2874, 1061, 756, + 2887, 2895, 2896, 488, 2897, 765, 2899, 2907, 765, 2909, + 1062, 2915, 2911, 2918, 2923, 515, 515, 2937, 2704, 2941, + 2943, 2945, 617, 617, 617, 617, 2948, 2954, 2959, 2960, + 756, 2965, 1058, 756, 1056, 2944, 2961, 2969, 2981, 2970, + 2982, 1063, 2978, 2984, 2995, 3002, 3007, 2999, 3013, 3014, + 758, 488, 488, 1057, 3015, 3019, 488, 767, 3020, 3021, + 2932, 488, 3030, 3031, 488, 488, 3037, 3047, 3032, 488, + 2554, 3034, 759, 2632, 3066, 3064, 3050, 3052, 57, 3067, + 3048, 3069, 3049, 3085, 3090, 3091, 3094, 3098, 1065, 3099, + 3103, 758, 488, 2154, 1014, 2265, 488, 2154, 515, 57, + 2227, 57, 1914, 2675, 1058, 2507, 2503, 2990, 513, 2818, + 1066, 2444, 543, 759, 2991, 3041, 2583, 2718, 488, 3081, + 588, 3011, 2838, 1059, 3046, 3053, 3075, 1511, 2872, 2234, + 1068, 626, 626, 2209, 2672, 2674, 761, 2588, 1379, 3043, + 485, 1380, 2472, 3051, 485, 1381, 2205, 3042, 1605, 2508, + 1626, 2267, 488, 2307, 2760, 2574, 1430, 1449, 2189, 1879, + 488, 2972, 761, 761, 2986, 3070, 2199, 1856, 2430, 2980, + 3033, 2496, 2669, 1389, 1060, 2552, 2917, 761, 1878, 488, + -1847, 1491, 1061, 2167, 1490, 654, 1379, 2402, 767, 1380, + 2640, 2656, 2901, 1381, 1062, 1059, -1847, -1847, -1847, 1495, + 2397, 2968, 2967, 2974, 1676, 1391, 2975, 2816, 1678, 1682, + 765, 1683, 3035, 3063, 3036, 1802, 2146, 2102, 2125, 2192, + 2146, 1389, 2041, 1329, 2556, 1063, 1950, 2123, 1390, 982, + 1056, 2161, 2671, 2429, 2166, 756, 2272, 2962, 1634, 2035, + 3045, 1821, 0, 2445, 57, 57, 1060, 1453, 1823, 1057, + 0, 0, 0, 1391, 1061, 0, 0, 0, 0, 2670, + 0, 0, 0, 0, 0, 0, 1062, 0, 0, 0, + 0, 0, 1065, 0, 0, 2109, 0, 0, 0, 0, + 0, 0, 0, 2745, 0, 0, 869, 0, 0, 0, + 514, 0, 488, 0, 1066, 767, 0, 1063, 488, 761, + 1058, 2494, 0, 0, 0, 0, -1847, 488, 488, 2495, + 0, 488, 0, 0, 1068, 0, 0, 0, 0, 667, + 0, 0, -1847, 0, 0, 488, 2154, -1847, 0, 0, + 0, 0, 0, 617, 488, 2154, 0, 0, 0, 488, + 2154, 0, 488, 2154, 1065, 0, 0, 0, 0, 488, + 488, 514, 514, 0, 1392, 0, 0, 617, 617, 1457, + 0, 488, 2154, 488, -1847, 0, 1066, 2496, 0, 0, + 1393, 0, 0, 485, 0, 1394, 0, 0, 0, 0, + 0, 488, 485, 0, 617, 1514, 1068, 485, 0, 0, + 485, 1059, 0, 57, 0, 0, 0, 617, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 485, + 758, 2556, 1397, 0, 617, 0, 0, 0, 617, 1400, + 0, 0, 0, 1369, 0, 0, 0, 0, 0, 0, + 1311, 0, 759, 761, 0, 0, 2856, 0, 0, 992, + 0, 0, 1060, 488, 2154, 762, 488, 767, 0, 0, + 1061, 0, 0, 0, 0, 0, 0, 0, 2146, 0, + 0, 0, 1062, 2146, 2497, 0, 2146, 1400, 0, 0, + 488, 1039, 0, 0, 488, 2154, 758, 0, 767, 0, + 0, 767, 0, 0, 515, 515, 0, 488, 0, 629, + 0, 485, 0, 1063, 758, 0, 2815, 0, 759, 0, + 0, 488, 0, 0, 488, 1220, 1222, 1224, 1225, 0, + 0, -1847, 0, 0, 1205, 0, 759, 0, 0, 488, + 0, 758, 485, 0, 0, 0, 0, 0, 758, 0, + 0, 0, 0, 0, 0, 0, 761, 764, 0, 0, + 1065, 0, 0, 759, 0, 0, 57, 0, 0, 0, + 759, 758, 1571, 0, 0, 2554, 0, 2956, 0, 1402, + 617, 0, 1066, 0, 0, 0, 0, 0, 0, 1600, + 488, 2154, 0, 759, 0, 0, 0, 761, 0, 0, + 0, 0, 1068, 0, 2498, 0, 0, 2499, 0, 0, + 0, 488, 0, 488, 0, 488, 0, 0, 2146, 488, + 0, 0, 1617, 0, 0, 0, 488, 2154, 686, 0, + 0, 1363, 0, -1847, 0, 0, 2987, 0, 485, 0, + 1407, 1408, 1409, 1410, 1411, 1412, 0, 0, 0, 488, + 0, 0, 0, 675, 675, 0, 514, 514, 776, 514, + 675, 0, 0, 0, 0, 0, 0, 0, 762, 488, + 0, 0, 0, 0, 485, 0, 0, 0, 0, 0, + 0, 1403, 488, 0, -1847, -1847, -1847, 57, 1407, 1408, + 1409, 1410, 1411, 1412, 0, 758, 0, 0, 0, 0, + 0, 2950, 1205, 2556, 0, 0, 0, 0, 0, 1706, + 0, 1522, 0, 0, 0, 0, 0, 759, 0, 0, + 1731, 0, 0, 0, 0, 488, 2154, 0, 488, 488, + 0, 0, 3054, 0, 0, 0, 0, 0, 0, 0, + 626, 0, 0, 0, 0, 0, 57, 0, 0, 0, + 0, 0, 0, 675, 0, 0, 758, 0, 0, 0, + 764, 488, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 485, 0, 0, 0, 0, 759, 0, + 0, 0, 0, 0, 980, 617, 0, 0, 0, 515, + 515, 0, 515, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 488, 0, 0, 762, 617, 0, 617, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1836, 0, + 1842, 0, 0, 0, 0, -1572, 758, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1443, 0, 0, 0, + 0, 0, 57, 0, 0, 0, 0, 2554, 759, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 617, 0, + 0, 1455, 0, 0, 0, 0, 0, 1514, 514, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 514, 1896, + 514, 1900, 0, 514, 0, 0, 0, 1503, 0, 514, + 0, 514, 0, 0, 0, -1574, 0, 764, 0, 0, + 1530, 0, 675, 514, 0, 0, 0, 675, 514, 0, + 0, 0, 514, 514, 514, 514, 761, 514, 514, 0, + -1572, 1554, 0, 0, 886, 0, 0, 2061, 0, 0, + 0, 2062, 0, 0, 2063, 2064, 2065, 617, 617, 1963, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 586, 1451, 0, 0, 0, 0, 0, 0, 482, - 2006, 0, 0, 482, 586, 0, 0, 734, 598, 0, - 734, 0, 0, 0, 2086, 2093, 482, 0, 0, 2086, - 0, 586, 2086, 0, 0, 586, 479, 0, 0, 825, - 482, 0, 2000, 482, 2795, 0, 0, 2001, 2002, 2003, - 2004, 2394, 0, 1144, 0, 0, 0, 2093, 482, 0, - 0, 0, 0, 0, 640, 2562, 0, 2683, 479, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2446, 0, - 2007, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2494, 2495, 2496, 2497, 2498, 2499, 2500, - 2501, 2502, 2503, 0, 725, 0, 2679, 0, 726, 482, - 0, 0, 57, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1252, 0, - 482, 0, 482, 0, 482, 57, 0, 0, 482, 1652, - 0, 0, 0, 0, 0, 482, 0, 0, 0, 0, - 728, 0, 0, 2093, 0, 729, 0, 0, 0, 931, - 0, 0, 0, 0, 479, 2007, 2086, 2895, 482, 1508, - 0, 0, 2006, 0, 0, 0, 0, 586, -1546, 1303, - 0, 0, 0, 0, 0, 0, 1539, 0, 482, 2093, - 0, 978, 0, 2754, 0, 0, 731, 0, 0, 0, - 479, 482, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1568, 725, 0, 0, 0, 0, 0, 0, 1556, - 0, 1144, 2491, 0, 0, 0, 2926, 0, 0, 1159, - 1161, 1163, 1164, 0, 0, 57, 0, 0, 0, 0, - 0, 0, 2007, 0, 482, 0, 0, 482, 482, 2006, - 648, 648, 2489, 507, 507, 0, 507, 648, 0, 0, - 586, 0, 0, 0, 0, 0, 0, 0, 1652, 0, - 0, 0, -1546, 0, 0, 0, 0, 2008, 2009, 2010, - 482, 2011, 2012, 2013, 2014, 2015, 2016, 726, 2093, 0, - 0, 0, 0, 0, 57, 0, 0, 0, 0, 479, - 0, 0, 0, 0, 0, 0, 0, 1645, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1670, 2007, - 0, 482, 2993, 0, -1546, 0, 2636, 0, 0, 728, - 0, 0, 0, 0, 729, 0, 0, 0, -1546, 0, - 0, 0, 0, -1546, 0, 0, 0, 0, -1546, 0, - 0, 648, 0, 0, 0, 0, 0, -1546, 0, 0, - 0, -1546, -1773, -1773, -1773, 0, 2011, 2012, 2013, 2014, - 2015, 2016, 0, 0, 0, 731, 0, 0, 0, 0, - 2889, 0, 919, 586, 0, 0, 0, 0, 0, 0, - 57, 725, -1546, 0, 0, 726, 0, 0, 0, 0, - 0, 0, 0, 0, 586, 0, 586, 0, 0, 0, - 0, 0, -1546, 0, 0, 1773, 0, 1779, 0, 0, - -1548, 0, 0, 1652, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 728, 0, 2008, - 2009, 2010, 729, 2011, 2012, 2013, 2014, 2015, 2016, 0, - 0, 0, 0, 586, 0, 0, 0, 0, 0, 0, - 0, -1546, 1451, 507, -1546, 0, 0, 0, 0, 0, - -1546, 0, 0, 507, 1831, 507, 1835, 0, 507, 0, - 0, 0, 0, 731, 507, 0, 507, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 648, 507, 0, - 0, 0, 648, 507, -1546, 0, 1383, 507, 507, 507, - 507, 0, 507, 507, -1548, 0, 2008, 2009, 2010, 0, - 2011, 2012, 2013, 2014, 2015, 2016, 2489, -1546, 0, 0, - 0, 1394, 586, 586, 1898, 0, 0, 0, 0, 825, - 0, 0, 2000, 0, 0, -1562, 0, 2001, 2002, 2003, - 2004, 1913, 0, 0, 0, 2780, 0, 1440, 0, 0, - 0, 0, 0, 0, 0, 0, -1548, 0, 0, 0, - 1467, 0, 0, 0, 726, 2788, 2789, 0, 725, 725, - -1548, 0, 0, 2079, 0, -1548, 0, 0, 0, 0, - -1548, 1491, 2800, 725, 0, 0, 0, 0, 0, -1548, - 0, 0, 0, -1548, 0, 0, 0, 0, 0, 0, - -1546, 0, 0, 0, 0, 0, 728, 0, -1546, 0, - 0, 729, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -1548, -1546, 0, -1546, -1546, -1562, + 0, 0, 886, 0, 1977, 2061, 0, 758, 0, 2062, + 0, 0, 2063, 2064, 2065, 0, 0, 0, 0, 0, + 0, 0, -1572, 0, 0, 0, 0, 0, 0, 759, + 0, 0, 761, 0, 762, 0, -1572, 0, 0, 0, + -1574, -1572, 0, 758, 0, 0, -1572, 0, 0, 0, + 761, 515, 0, 0, 0, -1572, 0, 0, 0, -1572, + 0, 515, 0, 515, 0, 759, 515, 0, 0, 0, + 0, 0, 515, 0, 515, 0, 0, 761, 0, 0, + 0, 0, 0, 0, 761, 0, 515, 0, 0, 0, + -1572, 515, -1574, 0, 0, 515, 515, 515, 515, 0, + 515, 515, 0, 0, 0, 0, -1574, 761, 0, 0, + -1572, -1574, 0, 1587, 758, 0, -1574, 0, 0, 0, + 0, 0, 0, 0, 0, -1574, 764, 0, 0, -1574, + 0, 0, 0, 0, 0, 0, 759, 0, 0, 0, + 0, 0, 514, 0, 0, 0, 0, 0, 0, 514, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -1572, + -1574, 0, -1572, 2066, 0, 0, 0, 0, -1572, 0, + 0, 0, 0, 0, 0, 0, 626, 0, 0, 0, + -1574, 0, 0, 0, 0, 2067, 1706, 0, 0, 0, + 0, 0, 0, 0, 0, 762, 0, 0, 0, 0, + 0, 0, -1572, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2067, 0, 0, 0, 0, 617, 0, + 0, 762, 762, 0, 2157, -1572, 0, 0, 0, -1574, + 758, 761, -1574, 0, 0, 0, 762, 514, -1574, 0, + 2157, 0, 0, 0, 2176, 0, 0, 2179, 0, 1842, + 0, 0, 759, 0, 0, 2068, 0, 886, 0, 0, + 2061, 0, 0, 0, 2062, 0, 758, 2063, 2064, 2065, + 0, 0, -1574, 0, 0, 515, 0, 0, 0, 0, + 0, 2139, 1369, 2068, 2367, 0, 0, 764, 759, 0, + 0, 0, 761, 0, 0, -1574, 0, 758, 0, 0, + 758, 0, 0, 1571, 0, 0, 0, 0, -1572, 0, + 0, 0, 0, 764, 764, 0, -1572, 0, 1811, 759, + 0, 0, 759, 0, 0, 0, 0, 0, 764, 0, + 0, 0, 0, -1572, 0, -1572, -1572, 0, 0, 1820, + 0, 1822, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 2139, 0, 0, 0, 0, 0, 1379, 762, 0, + 1380, 0, 761, 0, 1381, 0, 1571, 1384, 1385, 1386, + 515, 617, -1572, 0, 0, -1572, -1572, -1572, -1574, 1571, + 617, 617, 617, 0, 1387, 0, -1574, 0, 0, 0, + 0, 1874, 1389, 514, 0, 0, 0, 0, 0, 1390, + 0, 617, 0, -1574, 0, -1574, -1574, 0, 0, 0, + 0, 0, 0, 2303, 0, 0, 0, 0, 0, -1588, + 0, 0, 0, 0, 1391, 0, 0, 0, 0, 675, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -1548, 0, 0, 0, 0, 0, - 0, 0, 731, 0, 0, 0, 0, 0, 2858, 0, - 0, 0, 0, 0, -1546, 0, 0, -1546, -1546, -1546, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 507, - 0, -1562, 0, 0, 0, 0, 1309, 0, 0, 0, - 0, 0, 0, -1548, 0, -1562, -1548, 0, 0, 0, - -1562, 0, -1548, 0, 0, -1562, 0, 725, 0, 0, - 0, 0, 0, 0, -1562, 0, 0, 0, -1562, 0, - 0, 0, 1645, 1526, 0, 0, 0, 0, 902, 902, - 0, 0, 0, 0, 0, 0, -1548, 0, 0, 2006, - 0, 0, 0, 0, 0, 0, 0, 0, 0, -1562, - 0, 726, 726, 0, 586, 0, 0, 0, 0, -1548, - 2096, 0, 0, 0, 982, 0, 726, 0, 0, -1562, - 983, 0, 0, 0, 0, 2096, 0, 995, 0, 2115, - 0, 0, 2118, 0, 1779, 0, 0, 0, 0, 0, - 0, 1053, 1060, 728, 728, 0, 996, 0, 729, 729, - 0, 0, 0, 0, 0, 0, 1574, 0, 728, 2007, - 0, 0, 0, 729, 0, 2079, 0, 0, -1562, 0, - 0, -1562, 0, 825, 0, 0, 2000, -1562, 0, 0, - 0, 2001, 2002, 2003, 2004, 0, 1508, 725, 0, 731, - 731, 0, -1548, 0, 0, 0, 0, 997, 0, 0, - -1548, 0, 0, 0, 731, 0, 0, 0, 0, 0, - 0, -1562, 0, 0, 0, 0, 0, -1548, 0, -1548, - -1548, 0, 0, 0, 0, 0, 984, 0, 0, 0, - 0, 0, 0, 0, -1562, 0, 0, 0, 0, 0, - 726, 0, 0, 0, 0, 0, 0, 0, 0, 1508, - 0, 0, 0, 0, 586, 0, -1548, 0, 0, -1548, - -1548, -1548, 0, 1508, 586, 586, 586, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 507, 0, 1749, - 0, 0, 728, 0, 0, 586, 0, 729, 998, 0, - 2079, 0, 725, 0, 0, 0, 0, 2245, 0, 0, - 1758, 0, 1760, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 648, 0, 586, 0, -1562, 0, 0, - 0, 0, 0, 0, 0, -1562, 1053, 0, 731, 0, - 1508, 1508, 0, 0, 0, 0, 0, 725, 0, 999, - 0, 0, -1562, 1274, -1562, -1562, 0, 1000, 0, 1809, - 0, 0, 0, 1645, 0, 0, 2008, 2009, 2010, 1001, - 2011, 2012, 2013, 2014, 2015, 2016, 0, 0, 0, 0, - 726, 0, 1285, 0, 0, 0, 0, 0, 0, 0, - 985, -1562, 0, -1773, -1562, -1562, -1562, 0, 0, 0, - 1002, 0, 1295, 1296, 1297, 0, 0, 1304, 0, 0, + 0, 0, -1574, 1571, 1571, -1574, -1574, -1574, 1379, 0, + 764, 1380, 2069, 2070, 2071, 1381, 2072, 2073, 2074, 2075, + 2076, 2077, 1629, 0, 1630, 0, 1706, 0, 2067, 0, + 1960, 1962, 0, 0, 0, 0, 0, 0, 0, 0, + 2069, 2070, 2071, 1389, 2072, 2073, 2074, 2075, 2076, 2077, + -1847, 0, 762, 761, 0, 0, 0, 0, 0, 0, + 0, 0, 758, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -1588, 1391, 0, 0, 0, 0, + 0, 0, 0, 0, 759, 1392, 515, 0, 0, 761, + 0, 0, 0, 0, 0, 0, 0, 0, 2068, 0, + 0, 1393, 0, 0, 0, 0, 1394, 0, 0, 0, + 0, 0, 617, 617, 617, 486, 0, 2157, 2406, 2406, + 0, 0, 0, 0, 2406, 2421, -1588, 0, 1395, 1396, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 728, 0, 0, 0, 0, 729, 0, 0, - 1361, 0, 0, 0, 0, 0, 0, 0, 1895, 1897, - 0, 1003, 0, 0, 0, 987, 0, 1004, 0, 0, - 586, 586, 586, 480, 0, 2096, 2348, 0, 0, 0, - 0, 2348, 2362, 2007, 0, 0, 0, 0, 731, 1005, - 0, 0, 0, 0, 0, 1006, 0, 0, 0, 0, - 0, 0, 0, 1404, 0, 726, 0, 1418, 1423, 1007, - 0, 1779, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1251, 0, 0, 586, - 0, 507, 0, 1251, 0, 1508, 1451, 1508, 0, 1539, - 0, 0, 0, 0, 0, 0, 0, 728, 0, 0, - 726, 0, 729, 0, 0, 0, 0, 0, 507, 0, - 2447, 1053, 0, 989, 0, 0, 0, 0, 1053, 0, - 0, 0, 0, 507, 507, 507, 507, 507, 507, 507, - 507, 507, 507, 0, 0, 0, 0, 0, 0, 0, - 1053, 0, 728, 731, 0, 0, 0, 729, 1913, 0, - 0, 0, 0, 586, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1451, 0, 0, 0, 0, 0, 0, - 1317, 0, 0, 0, 0, 0, 0, 1539, 1320, 0, - 0, 1321, 0, 0, 0, 0, 1323, 0, 731, 586, - 0, 0, 0, 0, 0, 1251, 1508, 1251, 1251, 0, + -1588, 0, 0, 1397, 764, -1588, 0, 0, 0, 0, + -1588, 0, 0, 0, 1842, 762, 0, 0, 0, -1588, + 761, 0, 0, -1588, 0, 0, 0, 0, 0, 0, + 0, 0, 617, 0, 514, 0, -1847, 0, 1571, 1514, + 1571, 1398, 1600, 0, 1399, 0, 0, 0, 0, 0, + 0, 0, -1847, 0, -1588, 0, 762, -1847, 1400, 0, + 0, 514, 0, 2506, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -1588, 0, 514, 514, 514, 514, + 514, 514, 514, 514, 514, 514, 0, 0, 0, 0, + 0, 0, 0, 1886, -1847, 0, 0, 0, 0, 0, + 0, 1977, 0, 1895, 0, 1898, 617, 764, 1909, 0, + 0, 0, 0, 1514, 1913, 0, 1915, 0, 0, 0, + 0, 2138, 0, -1588, 0, 0, -1588, 1600, 1922, 0, + 0, 0, -1588, 1925, 0, 0, 761, 1930, 1931, 1932, + 1933, 0, 1937, 1938, 0, 1571, 0, 0, 764, 1400, + 1402, 0, 0, 0, 0, 2069, 2070, 2071, 0, 2072, + 2073, 2074, 2075, 2076, 2077, 0, -1588, 515, 0, 0, + 0, 0, 761, 0, 963, 963, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -1588, + 0, 0, 0, 0, 515, 2616, 0, 0, 0, 0, + 0, 0, 0, 761, 0, 0, 761, 0, 0, 515, + 515, 515, 515, 515, 515, 515, 515, 515, 515, 2634, + 0, 617, 617, 617, 617, 0, 0, 0, 2406, 2421, + 0, 2406, 2406, 0, 0, 514, 1120, 1127, 0, 0, + 2157, -1847, 0, 0, 2157, 2139, 0, 0, 0, 0, + 514, 0, 1403, 0, 0, 1404, 1405, 1406, 0, 1407, + 1408, 1409, 1410, 1411, 1412, 0, 980, 0, 0, 0, + 2176, 0, -1588, 0, 2268, 1842, 0, 0, 0, 0, + -1588, 1706, 0, 2276, 2277, 2279, 0, 1514, 0, 0, + 0, 0, 0, 1571, 0, 0, 0, -1588, 0, -1588, + -1588, 0, 0, 0, 2296, 0, 675, 514, 0, 0, + 0, 0, 0, 0, 617, 0, 0, 0, 0, 0, + 0, 0, 0, 1379, 0, 0, 1380, 0, 0, 0, + 1381, 2719, 0, 0, 0, 0, -1588, 0, 0, -1588, + -1588, -1588, 0, -1847, 0, 0, 0, 0, 0, 0, + 1407, 1408, 1409, 1410, 1411, 1412, 0, 0, 1389, 0, + 0, 0, 0, 0, 0, -1847, 0, 0, 2643, 0, + 0, 0, 0, 0, 0, 762, 0, 0, 0, 0, + 0, 0, 0, 2661, 0, 0, 0, 0, 0, 0, + 1391, 1379, 0, 0, 1380, 0, 0, 0, 1381, 0, + 0, 0, 0, 0, 0, 0, 0, 1571, 761, 0, + 0, 0, 1629, 0, 0, 0, 1977, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1389, 0, 2757, 0, + 0, 0, 0, -1847, 0, 0, 0, 0, 0, 0, + 515, 762, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1120, 0, 0, 0, 2393, 2394, 2395, 1391, 762, + 2119, 0, 0, 0, 2772, 0, 0, 764, 1334, 0, + 0, 0, 0, 486, 2406, 0, 2783, 0, 0, 514, + 0, 0, 2157, 0, 0, 0, 762, 2157, 0, 0, + 2157, -1847, 514, 762, 0, 514, 0, 1345, 0, 0, + 0, 0, 0, 0, 0, 0, 0, -1847, 0, 2824, + 0, 0, -1847, 0, 0, 2452, 762, 1355, 1356, 1357, + 0, 0, 1364, 0, 0, 0, 0, 0, 2377, 0, + 0, 0, 0, 764, 0, 0, 0, 0, 0, 0, + 514, 0, 0, 0, 0, 1421, 0, 0, 0, -1847, + 0, 764, 0, 0, 0, 0, 0, 0, 0, -1847, + 514, 514, 0, 0, 0, 0, 0, 0, 2287, 0, + 0, 617, 0, 1514, 0, -1847, 514, 0, 764, 0, + -1847, 0, 0, 0, 0, 764, 0, 0, 617, 2581, + 0, 2824, 0, 0, 0, 0, 0, 0, 1465, 0, + 0, 0, 1481, 1486, 1400, 0, 0, 0, 764, 514, + 0, 0, 515, 0, 0, 0, 0, -1847, 0, 0, + 0, 0, 2157, 0, 0, 2794, 0, 514, 2797, 0, + 0, 0, 0, 0, 0, 1379, 0, 0, 1380, 0, + 762, 0, 1381, 0, 0, 2914, 0, 0, 0, 980, + 0, 514, 0, 0, 0, 0, 1120, 0, 0, 0, + 617, 0, 0, 0, 0, 0, 0, 1120, 0, 0, + 1389, 0, 1400, 515, 0, 0, 675, -1847, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1329, 0, 0, 0, 0, 0, 0, -1773, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 725, - 2008, 2009, 2010, 0, 2011, 2012, 2013, 2014, 2015, 2016, - 2078, 507, 0, 0, 1331, 0, 0, 2554, 0, 0, + 617, 1120, 0, 515, 515, 0, -1847, 0, 0, 0, + 0, 762, 1391, 0, 2635, 2636, 2637, 2638, 0, 515, + 0, 0, 0, 0, 0, 0, 0, 0, 486, 0, + 0, 0, 0, 0, 0, 0, 0, 2971, 0, 0, + 0, 514, 764, 0, 0, 514, 886, 0, 0, 2061, + 0, 0, 515, 2062, 0, 0, 2063, 2064, 2065, 0, + 0, 0, 0, 0, 2824, 675, 675, 675, 0, 0, + 2797, 0, 0, 2368, -1847, 0, 0, 0, 0, 0, + 0, 762, 2380, 0, 0, 0, 0, 0, 0, 0, + 886, 0, 0, 2061, 515, 0, 1514, 2062, 0, 2453, + 2063, 2064, 2065, 764, 0, 0, 0, 2706, -1847, 0, + 0, 514, 0, -1847, 0, 1407, 1408, 1409, 1410, 1411, + 1412, 0, 0, 2914, 0, 0, 2505, 0, 1310, -1847, + 0, 0, 0, 0, -1847, 1310, 0, 1842, 0, 0, + 0, 2559, 2560, 2561, 2562, 2563, 2564, 2565, 2566, 2567, + 2568, 0, 0, 0, 0, 0, 0, 1514, 0, 0, + 0, 1379, 0, 2824, 1380, 0, 0, 0, 1381, 0, + 0, -1847, 0, 764, 515, 0, -1847, 0, 2794, 2783, + 675, 0, 0, 1407, 1408, 1409, 1410, 1411, 1412, 0, + 0, 0, 0, 0, 0, 0, 1389, 886, 0, 0, + 2061, 0, 0, -1847, 2062, 0, 0, 2063, 2064, 2065, + 0, 0, 762, 0, 0, 0, 0, 0, 0, 0, + 0, 1670, 1376, 0, 2623, 0, 1400, 0, 1391, 0, + 0, 1689, 0, 1707, 0, 0, 1718, 1721, 1726, 1729, + 0, 0, 0, 0, 2794, 0, 0, 1310, 762, 1310, + 1310, 0, 0, 0, 0, 0, 0, 2067, 0, 0, + 1741, 0, 0, 0, 0, 0, 1745, 1746, 1747, 1748, + 1749, 1750, 1751, 0, 0, 0, 0, 1760, 1761, 0, + 1379, 0, 1772, 1380, 0, 0, 1775, 1381, 0, 1783, + 1784, 1785, 1786, 1787, 1788, 1789, 1790, 1791, 2381, 0, + 1792, -1847, 0, 0, 764, 0, 0, 963, 0, 0, + 1120, 0, 0, 0, 0, 1389, 0, 1310, -1847, 762, + 1310, 1310, -1847, 0, 0, 0, 0, 2068, 0, -1847, + 0, 0, 1824, 0, 0, 0, 0, 0, 0, 0, + 764, 0, 0, 0, 0, -1847, 0, 1391, 0, 0, + -1847, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2857, 0, 0, 1356, 1357, 0, + 0, 2068, 2699, 886, 0, 0, 2061, 0, 0, 0, + 2062, 2878, 0, 2063, 2064, 2065, 0, -1847, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1251, 0, 0, 1251, 1251, - 2571, 0, 586, 586, 586, 586, 0, 0, 0, 2348, - 2362, 0, 2348, 0, 0, 2580, 0, 0, 0, 2096, - 0, 0, 0, 2096, 0, 0, 0, 0, 725, 2598, + 2624, 0, 0, 0, 0, 0, 0, 0, 2067, 0, + 0, 764, 0, 0, 0, 0, 0, 2627, 0, 0, + -1847, 0, 0, 0, 0, 0, 0, 1407, 1408, 1409, + 1410, 1411, 1412, 0, 0, 762, 0, 0, 0, 0, + 0, 0, 1400, 0, 0, 0, 1120, 0, -1847, 1947, + 1948, 0, 1949, 2928, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, -1847, 0, 0, 0, 0, -1847, + 0, 762, 1675, 0, 582, 0, 0, 0, 2068, 0, + 0, 1120, 0, 2955, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2049, 919, 725, 0, 0, 2115, - 0, 0, 0, 0, 1779, 0, 0, 0, 0, 0, - 1645, 0, 0, 0, 0, 0, 1451, 0, 0, 0, - 0, 0, 1508, 725, 0, -1773, 0, 0, 0, 0, - 725, 0, 0, 0, 0, 648, 507, 0, 0, 0, - 0, -1773, 0, 586, 0, 0, -1773, 1609, 0, 0, - 0, 0, 0, 0, 725, 0, 0, 1628, 0, 1646, - 2656, 0, 1657, 1660, 1665, 1668, 0, 0, 0, 0, - 2207, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2218, 2219, 2221, -1773, 0, 0, 0, 1680, 0, 0, - 0, 0, 726, 1684, 1685, 1686, 1687, 1688, 1689, 0, - 0, 2238, 0, 1698, 1699, 0, 0, 0, 1710, 0, - 0, 0, 1713, 0, 0, 1721, 1722, 1723, 1724, 1725, - 1726, 1727, 1728, 1729, 0, 0, 1730, 0, 0, 1543, - 1508, 1574, 0, 902, 728, 0, 1053, 0, 1340, 729, - 1552, 1913, 1553, 0, 0, 0, 0, 0, 0, 0, - 0, 1559, 0, 2695, 0, 0, 0, 0, 1762, 0, - 0, 726, 0, 0, 0, 0, 0, 0, 1560, 0, - 0, 0, 0, 0, 0, 0, 0, 725, 0, 726, - 731, 0, 0, 0, 0, 0, 0, 0, 0, 2711, - 1296, 1297, 0, 0, 0, 0, 1579, 1581, 480, 2348, - 0, 0, 2722, 728, 0, 507, 726, 2096, 729, 0, - 0, 0, 2096, 726, 0, 2096, 0, 2733, 0, 0, - 2736, 728, 0, 0, 0, 0, 729, 0, 1612, 1613, - -1773, 0, 1626, 1627, 2763, 0, 0, 726, 0, 0, - 0, 725, 0, 0, 0, 0, 0, 0, 728, 731, - 0, 0, 0, 729, 0, 728, 2336, 2337, 2338, 0, - 729, 0, 0, 0, 0, 507, 0, 731, 0, 1053, - 0, 0, 1882, 1883, 0, 1884, 0, 0, 509, 728, - 0, 0, 0, 0, 729, 507, 507, 0, 0, 0, - 0, 0, 0, 0, 731, 0, 586, 0, 1451, 0, - 0, 731, 507, 0, 0, 0, 1053, 0, 0, 0, - 0, 0, 0, 725, 586, 2393, 0, 2763, 0, 0, - 0, 0, 0, 0, 0, 731, 0, 0, 0, 0, - 0, 510, -1773, 0, 0, 0, 507, 0, 0, 1347, - 1348, 1349, 1350, 1351, 1352, 0, 0, 511, 0, 2096, - 0, 0, 0, 0, 2736, 0, 0, 0, 0, 0, - 726, 0, 0, 0, 0, 0, 0, 0, 1803, 1803, - 1053, 0, 2853, 0, 0, 0, 919, 1978, 507, 0, - 0, 0, 1984, 0, 0, 0, 0, 586, 0, 2516, + 0, 1604, 762, 0, 0, 762, -1847, 0, 0, 0, + 0, 0, 1613, 0, 1614, 0, 0, 0, 0, 0, + 0, 0, 0, 1620, 2069, 2070, 2071, 764, 2072, 2073, + 2074, 2075, 2076, 2077, -1847, 0, 0, 0, 0, 0, + 1621, 1120, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2039, 0, 0, 0, 0, 2045, 0, 0, + 0, 1400, 0, 764, 0, 0, 1636, 1638, 2069, 2070, + 2071, 0, 2072, 2073, 2074, 2075, 2076, 2077, 0, 0, + 1264, 1265, 0, 0, 2067, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 764, 0, 2060, 764, 0, 1673, + 1674, 0, 0, 1687, 1688, 2841, 0, 1726, 0, 1726, + 1726, 0, 0, 0, 0, 0, 0, 2098, 0, 0, + 0, 2101, 0, 0, 2103, 2849, 2850, 0, 1415, 0, + 0, 0, 0, 0, 0, 0, -1847, 0, 1264, 1265, + 0, 2861, 0, 1407, 1408, 1409, 1410, 1411, 1412, 0, + 0, 0, 0, -1847, 2068, 0, 1266, 1267, 0, 0, + 0, 2121, 0, 0, 2124, 0, 2126, 0, 0, 1415, + 0, 0, 0, 0, 0, 2069, 2070, 2071, -39, 2072, + 2073, 2074, 2075, 2076, 2077, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 762, 0, 2, + 0, 3, 4, 0, 1266, 1267, 2919, 0, 0, 0, + 0, 1268, 1269, 1270, 1271, 1272, 1273, 5, 0, 1274, + 1275, 0, 1465, 0, 1379, 0, 6, 1380, 0, 0, + 0, 1381, 1868, 1868, 1384, 1385, 1386, 0, 7, 1486, + 1790, 0, 0, 0, 0, -1847, 0, 0, 0, 8, + 0, 1387, 1407, 1408, 1409, 1410, 1411, 1412, 2203, 1389, + 0, 9, 0, 10, 0, 0, 1390, 0, 0, 1268, + 1269, 1270, 1271, 1272, 1273, 1415, 0, 1274, 1275, 0, + 0, 11, 1415, 0, 1310, 0, 0, 0, 0, 764, + 0, 1391, 0, 0, 1310, 12, 0, 1310, 0, 0, + 0, 0, 0, 0, 0, 13, 0, 0, 0, 0, + 0, 14, 0, 0, 0, 0, 0, 1120, 0, 15, + 0, 16, 17, 0, 0, 1276, 1277, 0, 0, 0, + 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, + 0, 2069, 2070, 2071, 0, 2072, 2073, 2074, 2075, 2076, + 2077, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2294, 0, 19, 0, 0, 0, 2003, 2005, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, + 0, 0, 0, 1276, 1277, 0, 0, 0, 0, 0, + 0, 1310, 1392, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1310, 21, 0, 0, 1393, 0, + 0, 0, 1043, 1394, 0, 2320, 0, 0, 1044, 0, + 0, 0, 0, 0, 2324, 1056, 0, 2325, 0, 0, + 2327, 0, 0, 0, 0, 1395, 1396, 0, 1278, 1279, + 0, 0, 0, 0, 1057, 0, 0, 0, 0, 0, + 1397, 0, 0, 0, 0, 0, 0, 2348, 2349, 0, + 0, 1824, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2359, 0, 0, 0, 0, 0, 0, 0, + 0, 2366, 22, 0, 2369, 23, 2371, 0, 1398, 1415, + 0, 1399, 0, 0, 2375, 1058, 1278, 1279, 0, 0, + 1415, 0, 2382, 2383, 1714, 1400, 2386, 0, 1401, 0, + 1415, 1415, 1415, 0, 24, 0, 1280, 0, 0, 1415, + 0, 0, 0, 25, 1045, 0, 0, 0, 0, 0, + 1264, 1265, 0, 2425, 0, 0, 0, 26, 0, 0, + 0, 0, 0, 2433, 27, 0, 0, 0, 28, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 29, 2446, + 0, 0, 0, 0, 0, 0, 0, 2163, 0, 0, + 30, 0, 0, 0, 31, 0, 1415, 0, 0, 0, + 0, 0, 1379, 0, 0, 1380, 1059, 0, 0, 1381, + 1382, 1383, 1384, 1385, 1386, 0, 0, 1402, 0, 0, + 0, 0, 0, 0, 2195, 2195, 1266, 1267, 0, 1387, + 32, 0, 0, 0, 0, 33, 0, 1389, 0, 0, + 1415, 0, 0, 0, 1390, 0, 0, 0, 517, 34, + 0, 0, 0, 0, 0, 0, 1415, 1060, 0, 0, + 0, 1415, 0, 0, 0, 1061, 0, 0, 0, 1391, + 0, 0, 0, 35, 0, 0, 0, 1062, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 36, 0, 0, + -39, 1268, 1269, 1270, 1271, 1272, 1273, 0, 1046, 1274, + 1275, 518, 0, 0, 0, 0, 0, 0, 1063, 0, + 0, 0, 0, 0, 2604, 0, 0, 519, 0, 1403, + 0, 0, 1404, 1405, 1406, 0, 1407, 1408, 1409, 1410, + 1411, 1412, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1064, + 0, 0, 0, 1048, 0, 1065, 0, 0, 0, 0, + 0, 0, 2617, 2618, 0, 2299, 0, 2619, 0, 0, + 1392, 520, 2622, 0, 0, 2625, 2626, 1066, 0, 0, + 2630, 521, 0, 1067, 0, 0, 1393, 0, 0, 0, + 0, 1394, 0, 522, 0, 0, 0, 1068, 523, 0, + 0, 0, 0, 0, 0, 1276, 1277, 0, 0, 0, + 0, 0, 0, 1395, 1396, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 524, 0, 0, 1397, 963, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 512, 728, 648, 0, 0, 0, 729, 0, 0, - 0, 513, 0, 0, 0, 0, 0, 586, 0, 0, - 1251, 1999, 0, 514, 726, 1574, 0, 0, 515, 0, - 1251, 0, 1665, 1251, 1665, 1665, 0, 0, 0, 0, - 0, 725, 2038, 0, 0, 480, 2041, 0, 731, 2043, - 0, 0, 0, 0, 2910, 516, 0, 0, 507, 0, - 0, 0, 2733, 0, 0, 0, 728, 0, 0, 0, - 0, 729, 725, 0, 0, 0, 0, 0, 0, 0, - 0, 2763, 648, 648, 648, 2061, 0, 0, 2064, 0, - 2066, 0, 0, 0, 0, 0, 726, 0, 0, 0, - 517, 0, 0, 0, 518, 0, 1939, 1941, 2572, 2573, - 2574, 2575, 731, 1451, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2733, 0, - 0, 0, 0, 1251, 0, 0, 0, 0, 728, 0, - 2853, 0, 0, 729, 0, 725, 1251, 0, 0, 0, - 0, 0, 0, 0, 1779, 1404, 0, 1320, 0, 0, - 1321, 0, 0, 0, 0, 1323, 0, 519, 0, 0, - 1423, 1728, 0, 0, 1451, 1320, 0, 0, 1321, 0, - 2763, 520, 0, 1323, 731, 0, 0, 0, 0, 2142, - 0, 1329, 0, 0, 0, 0, 2722, 648, -1773, 2643, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1329, - 0, 0, 0, 0, 521, 0, -1773, 522, 0, 0, - 0, 0, 0, 1331, 726, 523, 0, 0, 524, 0, + 0, 1378, 0, 0, 0, 1415, 1379, 0, 0, 1380, + 0, 1050, 0, 1381, 1382, 1383, 1384, 1385, 1386, 0, + 0, 0, 0, 2694, 1415, 0, 1398, 0, 0, 1399, + 525, 0, 0, 1387, 526, 0, 1388, 0, 0, 0, + 0, 1389, 1415, 1400, 1714, 1714, 1401, 2078, 1390, 1714, + 2713, 0, 0, 1415, 0, 0, 1415, 0, 0, 0, + 0, 1415, 0, 0, 1415, 0, 0, 0, 0, 0, + 0, 0, 0, 1391, 0, 0, 1415, 0, 1278, 1279, + 1415, 1415, 1415, 1415, 1415, 1415, 1415, 0, 0, 0, + 0, 0, 1714, 1714, 0, 1415, 1415, 527, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1415, 0, 0, + 1415, 528, 0, 0, 0, 0, 0, 0, 1415, 1415, + 1415, 1415, 1415, 1415, 1415, 1415, 1415, 1415, 0, 0, + 0, 0, 0, 0, 0, 1402, 0, 0, 0, 0, + 0, 0, 0, 0, 529, 0, 0, 530, 0, 0, + 0, 0, 0, 0, 0, 531, 0, 0, 532, 1415, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 2098, + 0, 0, 1310, 0, 1392, 0, 0, 533, 2767, 2768, + 0, 0, 2769, 0, 0, 0, 0, 0, 0, 0, + 1393, 534, 0, 0, 0, 1394, 0, 0, 535, 0, + 0, 0, 0, 0, 0, 0, 0, 536, 0, 0, + 0, 0, 0, 537, 0, 0, 0, 1395, 1396, 0, + 2811, 2812, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1397, 0, 2826, 0, 0, 1403, 538, 0, + 1404, 1405, 1406, 0, 1407, 1408, 1409, 1410, 1411, 1412, + 0, 0, 2836, 0, 0, 0, 0, 2052, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1331, 0, 0, 0, 0, 0, 525, 1053, 0, - 0, 0, 0, 0, 0, 726, 0, 0, 0, 0, - 725, 526, 0, 0, 0, 0, 728, 0, 527, 0, - 0, 729, 0, 0, 0, 0, 0, 528, 0, 0, - 0, 0, 0, 529, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2059, 2236, 0, 0, 728, 725, 0, - 0, 0, 729, 0, 2102, 0, 0, 0, 530, 0, - 0, 2321, 731, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, -1773, 0, 0, 0, 726, 725, - 0, 0, 725, 0, 0, 0, 0, 0, 2134, 2134, - -1773, 0, -1773, 731, 0, -1773, 0, 0, 0, 0, - 2263, 0, 0, 0, 0, 0, 1355, 0, -1773, 2267, - 0, 0, 2268, -1773, 0, 2270, 0, 0, 0, 0, - 728, 0, 0, 0, 0, 729, 0, 0, 0, 0, - 0, 0, -1773, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 2291, 2292, 0, 0, 1762, 1355, 0, 0, - -1773, 0, 0, 0, 0, 0, 0, 0, 2303, 0, - 0, 0, 0, 0, 0, 0, 731, 2310, 0, 0, - 2313, 0, 2315, 0, 0, 1320, 0, 0, 1321, 0, - 2319, 0, 0, 1323, -1773, -1773, -1773, 1340, 2326, 2327, - 0, -39, 0, 726, 0, 0, 0, 0, 0, 0, - 0, 0, 2796, 0, 0, 1340, 0, 0, 0, 1329, - 0, 1, 0, 0, 0, 0, 1330, 0, 2366, 0, - 2817, 2, 0, 3, 4, 0, 0, 0, 2374, 0, - 2241, 726, 0, 0, 0, 728, 0, 0, 0, 5, - 729, 1331, 0, 0, 2387, 0, 0, 0, 6, 0, - 0, 0, 0, 0, 0, 0, 0, 1355, 0, 0, - 7, 0, 726, 0, 1355, 726, 0, 0, 0, 0, - 0, 8, 0, 728, 0, 0, 0, 0, 729, -1773, - 0, 731, 0, 9, 725, 10, 0, 0, 0, 0, - 0, 0, 0, 2867, 0, 0, 0, -1773, 0, 0, - 0, 0, 0, 11, 728, 0, 0, 728, 0, 729, - 0, 0, 729, 0, 0, 0, 0, 12, 0, 731, - 0, 0, 0, 2894, 0, 0, 0, 13, 0, 0, - 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, - 0, 15, 1332, 16, 17, 0, 0, 0, 0, 0, - 731, 0, 0, 731, 0, 995, 0, 18, 1333, 0, - 0, 0, 0, 1334, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 996, 0, 0, 0, 0, 0, - 0, -1773, 0, 2542, 0, 0, 19, 0, 1347, 1348, - 1349, 1350, 1351, 1352, 0, 0, 0, 0, 0, -1773, - 1337, 20, 0, 0, 0, 0, 1347, 1348, 1349, 1350, - 1351, 1352, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 997, 2435, 21, 0, 0, - 0, 0, 2555, 2556, 2436, 0, 0, 2557, 0, 0, - 0, 0, 2560, 0, 0, 2563, 2564, 0, 0, 0, - 2568, 0, 0, 0, 0, 1340, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 726, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1355, 0, - 1251, 0, 0, 0, 0, 0, 0, 0, 0, 1355, - 0, 0, 2437, 1653, 0, 0, 902, 0, 0, 1355, - 1355, 1355, 0, 0, 22, 0, 0, 23, 1355, 728, - 0, 0, 0, 0, 729, 0, 998, 0, 0, 0, + 1398, 0, 0, 1399, 0, 0, 0, 0, 0, 0, + 0, 0, 1415, 1415, 1415, 0, 0, 1400, 0, 0, + 1401, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 2631, 0, 0, 0, 0, 0, 24, 0, 0, 0, - 0, 0, 0, 1320, 0, 25, 1321, 1342, 0, 0, - 1322, 1323, 1324, 1325, 1326, 731, 0, 2650, 0, 26, - 0, 0, 0, 0, 0, 1355, 27, 999, 0, 1327, - 28, 0, 0, 0, 0, 1000, 0, 1329, 0, 0, - 29, 0, 0, 0, 1330, 0, 0, 1001, 0, 2438, - 0, 0, 30, 0, 0, 0, 31, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1355, 1331, - 0, 0, 0, 0, 0, 0, 0, 0, 1002, 0, - 0, 0, 1355, 0, 0, 0, 0, 1355, 0, 0, - 0, 0, 32, 0, 0, 0, 0, 33, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1343, - 0, 34, -1773, -1773, -1773, 0, 1347, 1348, 1349, 1350, - 1351, 1352, 0, 0, 0, 1004, 0, 0, 0, 0, - 0, 0, 0, 2038, 0, 35, 0, 0, 0, 0, - 0, 0, 2706, 2707, 0, 0, 2708, 1005, 0, 36, - 0, 0, -39, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1007, 0, 2439, - 1332, 0, 2440, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 2750, 2751, 0, 1333, 0, 0, 0, - 0, 1334, 0, 1251, 0, 0, 0, 2765, 1251, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1335, 1336, 2775, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1337, 0, - 0, 1319, 0, 0, 0, 0, 1320, 0, 0, 1321, - 0, 1579, 1581, 1322, 1323, 1324, 1325, 1326, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1327, 0, 0, 1328, 1338, 0, 0, 1339, - 1329, 0, 0, 1355, 0, 0, 1459, 1330, 0, 0, - 0, 0, 0, 1340, 0, 0, 1341, 0, 0, 0, - 0, 0, 1355, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1331, 0, 0, 0, 2837, 0, 0, 0, - 1355, 0, 1653, 1653, 0, 2017, 0, 1653, 0, 0, - 0, 1355, 0, 1304, 1355, 0, 0, 0, 0, 1355, - 0, 0, 1355, 0, 0, 0, 0, 902, 0, 0, - 2859, 0, 0, 0, 1355, 0, 0, 0, 1355, 1355, - 1355, 1355, 1355, 1355, 0, 2878, 0, 0, 0, 1653, - 1653, 0, 1355, 1355, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1320, 1355, 1342, 1321, 1355, 0, 0, - 1322, 1323, 1324, 1325, 1326, 1355, 1355, 1355, 1355, 1355, - 1355, 1355, 1355, 1355, 1355, 0, 0, 0, 0, 1327, - 0, 0, 2307, 1332, 0, 0, 0, 1329, 0, 0, - 0, 0, 1579, 1581, 1330, 0, 0, 0, 0, 1333, - 0, 0, 0, 1251, 1334, 0, 1355, 0, 0, 0, - 0, 2750, 0, 0, 0, 2922, 0, 0, 0, 1331, - 0, 0, 0, 0, 0, 0, 1335, 1336, 0, 0, + 0, 0, 0, 0, 0, 1379, 0, 0, 1380, 0, + 0, 2898, 1381, 1382, 1383, 1384, 1385, 1386, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1364, 0, + 0, 0, 1387, 0, 0, 2363, 0, 0, 0, 0, + 1389, 0, 963, 0, 1415, 2920, 0, 1390, 0, 1402, + 1415, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2939, 0, 0, 2078, 2078, 1415, 0, 1714, 1714, 1714, + 1714, 1714, 1391, 0, 1714, 1714, 1714, 1714, 1714, 1714, + 1714, 1714, 1714, 1714, 2078, 0, 0, 0, 0, 0, + 0, 0, 0, 1310, 0, 0, 0, 0, 1310, 0, + 0, 0, 0, 1415, 0, 0, 1415, 0, 1415, 0, + 0, 0, 2078, 2078, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1415, 1714, 1714, 1415, + 0, 1415, 0, 0, 0, 0, 2811, 0, 0, 0, + 2983, 0, 0, 0, 0, 0, 0, 1636, 1638, 0, + 0, 1403, 0, 0, 1404, 1405, 1406, 0, 1407, 1408, + 1409, 1410, 1411, 1412, 0, 0, 0, 0, 0, 0, + 3012, 0, 0, 1392, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1379, 1393, + 0, 1380, 0, 0, 1394, 1381, 1382, 1383, 1384, 1385, + 1386, 0, 0, 2811, 0, 0, 0, 0, 1415, 0, + 0, 0, 0, 0, 0, 1387, 1395, 1396, 0, 0, + 0, 0, 0, 1389, 0, 0, 0, 0, 0, 0, + 1390, 1397, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3060, + 3060, 0, 0, 1379, 0, 1391, 1380, 0, 0, 0, + 1381, 1382, 1383, 1384, 1385, 1386, 0, 0, 0, 1398, + 0, 0, 1399, 0, 0, 0, 0, 0, 0, 0, + 1387, 0, 3060, 0, 0, 0, 1400, 0, 1389, 1401, + 0, 0, 0, 0, 0, 1390, 0, 0, 0, 1415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1337, 0, 0, 0, 2951, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1343, 0, 0, - 1344, 1345, 1346, 0, 1347, 1348, 1349, 1350, 1351, 1352, - 0, 0, 0, 0, 0, 0, 0, 1991, 2750, 1338, - 0, 0, 1339, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1340, 0, 0, 1341, - 0, 1320, 0, 0, 1321, 0, 0, 0, 0, 1323, - 1324, 1325, 1326, 0, 0, 0, 0, 0, 0, 0, - 1332, 0, 0, 0, 2999, 2999, 1355, 1355, 1355, 0, - 0, 0, 0, 0, 0, 1329, 1333, 0, 0, 0, - 0, 1334, 1330, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 2999, 0, 0, - 0, 0, 0, 1335, 1336, 0, 0, 1331, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1337, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1342, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2999, 0, + 0, 0, 0, 0, 0, 0, 1636, 1638, 0, 0, + 1391, 0, 0, 3060, 0, 1415, 0, 1310, 0, 1415, + 1415, 0, 1415, 0, 0, 2078, 2078, 2078, 2078, 2078, + 0, 0, 0, 2078, 2078, 2078, 2078, 2078, 2078, 2078, + 2078, 2078, 2078, 1415, 1415, 0, 1392, 0, 0, 0, + 0, 0, 0, 0, 1415, 0, 0, 0, 0, 0, + 0, 1415, 1393, 0, 1415, 0, 1415, 1394, 1402, 0, + 1415, 0, 0, 2078, 2078, 0, 0, 1415, 1415, 0, + 0, 1415, 0, 0, 0, 0, 0, 0, 0, 1395, + 1396, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1397, 0, 0, 0, 0, 0, + 0, 1392, 0, 0, 0, 0, 0, 0, 0, 0, + 1415, 0, 0, 0, 0, 0, 1379, 1393, 1415, 1380, + 0, 0, 1394, 1381, 1382, 1383, 1384, 1385, 1386, 0, + 0, 1415, 1398, 0, 0, 1399, 0, 0, 0, 0, + 0, 0, 0, 1387, 1395, 1396, 0, 0, 0, 1400, + 0, 1389, 1401, 0, 0, 0, 0, 0, 1390, 1397, + 1403, 1714, 0, 1404, 1405, 1406, 0, 1407, 1408, 1409, + 1410, 1411, 1412, 0, 0, 0, 0, 1735, 0, 0, + 0, 0, 0, 1391, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1398, 1379, 0, + 1399, 1380, 0, 0, 0, 1381, 1382, 1383, 1384, 1385, + 1386, 0, 0, 0, 1400, 0, 0, 1401, 0, 0, + 0, 0, 0, 0, 0, 1387, 0, 0, 0, 0, + 0, 0, 0, 1389, 0, 0, 0, 0, 0, 0, + 1390, 1402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1338, 0, 0, 1339, - 0, 0, 1355, 0, 0, 0, 0, 0, 1355, 0, - 0, 0, 0, 1340, 0, 0, 1341, 0, 0, 0, - 0, 2017, 2017, 1355, 0, 1653, 1653, 1653, 1653, 1653, - 0, 0, 1653, 1653, 1653, 1653, 1653, 1653, 1653, 1653, - 1653, 1653, 2017, 0, 0, 0, 0, 0, 1332, 0, - 0, 0, 0, 0, 0, 0, 0, 1251, 0, 0, - 0, 0, 1355, 0, 1333, 1355, 0, 1355, 0, 1334, - 1343, 2017, 2017, 1344, 1345, 1346, 0, 1347, 1348, 1349, - 1350, 1351, 1352, 0, 0, 1355, 1653, 1653, 1355, 0, - 1355, 1335, 1336, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1342, 1337, 0, 0, 0, + 0, 0, 0, 0, 0, 1391, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1310, + 0, 0, 0, 0, 1392, 0, 0, 0, 0, 1415, + 0, 0, 0, 1714, 0, 0, 0, 0, 0, 0, + 1393, 0, 1415, 1415, 1415, 1394, 1402, 1415, 0, 0, + 1415, 1415, 0, 0, 0, 1415, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1395, 1396, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1397, 1403, 0, 0, 1404, 1405, 1406, 0, + 1407, 1408, 1409, 1410, 1411, 1412, 0, 0, 0, 0, + 1735, 0, 0, 0, 0, 0, 1392, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1415, + 1398, 0, 1393, 1399, 0, 2078, 0, 1394, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1400, 1415, 0, + 1401, 0, 0, 0, 0, 0, 0, 0, 1403, 1395, + 1396, 1404, 1405, 1406, 0, 1407, 1408, 1409, 1410, 1411, + 1412, 0, 0, 0, 1397, 2105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2078, 1714, 0, 0, + 0, 0, 1415, 1415, 1415, 0, 0, 0, 0, 0, + 0, 0, 1398, 0, 0, 1399, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1400, + 0, 0, 1401, 0, 0, 0, 0, 0, 0, 1402, + 0, 0, 0, 0, 0, 0, 1415, 1415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1338, 0, 0, 1339, 0, 0, + 0, 1415, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1340, 0, 0, 0, 0, 1355, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 2078, 0, 0, 0, 0, + 0, 1402, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1415, 0, 0, 0, 0, 0, 0, + 0, 1403, 0, 0, 1404, 1405, 1406, 0, 1407, 1408, + 1409, 1410, 1411, 1412, 0, 1415, 0, 0, 2323, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1343, 0, 0, - 1344, 1345, 1346, 0, 1347, 1348, 1349, 1350, 1351, 1352, - 0, 0, 1320, 0, 1674, 1321, 0, 0, 0, 1322, - 1323, 1324, 1325, 1326, 0, 0, 0, 1320, 0, 0, - 1321, 0, 0, 0, 0, 1323, 0, 0, 1327, 0, - 0, 0, 0, 1342, 0, 0, 1329, 0, 0, 0, - 1355, 0, 0, 1330, 0, 0, 0, 0, 0, 0, - 0, 1329, 0, 0, 0, 0, 0, 0, -1773, 0, - 0, 0, 0, 0, 0, 0, 0, 1355, 1331, 0, - 0, 1355, 1355, 0, 1355, 0, 0, 2017, 2017, 2017, - 2017, 2017, 0, 1331, 0, 2017, 2017, 2017, 2017, 2017, - 2017, 2017, 2017, 2017, 2017, 1355, 1355, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1355, 0, 0, - 0, 0, 0, 0, 1355, 0, 0, 1355, 0, 1355, - 0, 0, 0, 1355, 0, 0, 2017, 2017, 0, 0, - 1355, 1355, 0, 0, 0, 1343, 0, 0, 1344, 1345, - 1346, 0, 1347, 1348, 1349, 1350, 1351, 1352, 0, 0, - 0, 0, 1320, 2324, 0, 1321, 0, 0, 0, 0, - 1323, 1324, 1325, 1326, 0, 1320, 0, 0, 1321, 1332, - 1355, 0, 0, 1323, 0, 0, 0, 0, 1355, 0, - 0, 0, 0, 0, -1773, 1333, 1329, 0, 0, 0, - 1334, 1355, 0, 1330, 0, 0, 0, 0, 0, 1329, - -1773, 0, 0, 0, 0, -1773, -1773, 0, 0, 0, - 0, 0, 1335, 1336, 0, 0, 0, 0, 1331, 0, - 0, 1653, 0, 0, 0, 0, 1320, 1337, 0, 1321, - 0, 1331, 0, 1322, 1323, 1324, 1325, 1326, 0, 0, - 0, 0, -1773, 0, 0, 0, 1320, 0, 0, 1321, - 0, 0, 1327, 0, 1323, 0, 0, 0, 0, 0, - 1329, 0, 0, 0, 0, 1338, 0, 1330, 1339, 0, + 0, 0, 0, 0, 1415, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1329, 0, 1340, 0, 0, 1341, 0, -1773, 0, 0, - 0, 0, 1331, 0, 0, 0, 0, 1340, 0, 0, - 0, 2325, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1331, 0, 0, 0, 0, 0, 0, 1332, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, -1773, 0, 0, 1333, 0, 0, 0, 0, - 1334, 982, 0, 0, 0, 0, 1355, 983, -1773, 0, - 1653, 0, 0, -1773, 995, 0, 0, 0, 0, 1355, - 1355, 1355, -1773, -1773, 1355, 0, 0, 1355, 1355, 0, - 0, 0, 1355, 996, 1342, 0, 0, 1337, 0, 0, - 0, 0, 2565, 0, 0, 0, 0, 0, 0, -1773, - -1773, 0, 0, 1332, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1333, - 0, 0, 0, -1773, 1334, 0, 0, 0, -1773, 0, - 0, 0, 0, 0, 997, 0, 0, 0, 0, -1773, - 0, 0, 1340, 0, -1773, 1355, 1335, 1336, 0, 0, - 0, 2017, 0, 0, 0, 1340, 0, 0, 0, 0, - 0, 1337, 0, 984, 1355, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -1773, 0, 0, 0, 0, 1343, 0, 0, 1344, - 1345, 1346, 0, 1347, 1348, 1349, 1350, 1351, 1352, 1338, - 0, -1773, 1339, 1674, 0, 0, 0, 0, 1347, 1348, - 1349, 1350, 1351, 1352, 2017, 1653, 1340, 0, 0, 1341, - 1355, 1355, 1355, 0, 0, 998, 0, 0, 0, 0, - 0, 0, 0, 0, 1342, 0, 1340, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -1773, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1355, 1355, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 999, 0, 0, 1355, - 0, 0, 0, 0, 1000, 0, 0, 0, 0, 1355, - 0, 0, 0, 0, 0, 0, 1001, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1342, 0, - 0, 0, 0, 0, 0, 0, 0, 985, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1002, -1773, 0, - 0, 0, 0, 2017, 0, 0, 1343, 0, 0, 1344, - 1345, 1346, 0, 1347, 1348, 1349, 1350, 1351, 1352, -1773, - 0, 1355, 0, 0, 0, 0, 1347, 1348, 1349, 1350, - 1351, 1352, 0, 0, 0, 0, 0, 0, 1851, 0, - 0, 0, 987, 1355, 1004, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1355, 0, 0, 0, 1005, 0, 0, 0, - 0, 0, 1852, 0, 0, 0, 0, 0, 0, 0, - 1343, 0, 0, 1344, 1345, 1346, 1007, 1347, 1348, 1349, - 1350, 1351, 1352, 0, 0, 0, 0, 2045, 0, 0, - -1773, 0, 0, 0, 0, 0, 1355, 1347, 1348, 1349, - 1350, 1351, 1352, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1355, 0, 0, 0, 0, - 989, 0, 0, 0, 0, 1019, 822, 550, 823, 824, - 825, 826, 827, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, - 1020, 102, 103, 104, 0, 0, 0, 0, 828, 0, - 0, 105, 106, 1355, 107, 108, 109, 1021, 111, 112, - 113, 114, 829, 1022, 830, 831, 0, 119, 120, 121, - 122, 123, 124, 832, 833, 125, 126, 834, 835, 129, - 0, 130, 131, 132, 133, 836, 0, 1023, 0, 136, - 137, 138, 139, 140, 141, 1024, 143, 144, 145, 0, - 146, 147, 148, 149, 150, 151, 0, 1025, 153, 154, - 155, 838, 839, 840, 1026, 842, 843, 844, 157, 158, - 159, 160, 161, 162, 163, 845, 846, 166, 847, 167, - 0, 168, 169, 170, 171, 172, 173, 0, 174, 175, - 176, 177, 178, 1027, 0, 179, 180, 681, 182, 183, - 0, 184, 185, 186, 0, 187, 188, 189, 0, 190, - 191, 192, 193, 848, 195, 196, 197, 198, 199, 849, - 850, 201, 0, 202, 203, 851, 205, 0, 206, 0, - 207, 1028, 0, 1029, 210, 211, 1030, 1031, 214, 0, - 215, 0, 852, 853, 218, 0, 219, 220, 221, 222, - 223, 224, 225, 1032, 227, 228, 229, 230, 0, 231, - 232, 233, 234, 235, 236, 0, 237, 1033, 239, 240, - 241, 242, 243, 244, 854, 855, 0, 856, 0, 248, - 1034, 1035, 251, 1036, 253, 254, 255, 256, 257, 258, - 0, 0, 259, 1037, 261, 1038, 0, 263, 264, 265, - 857, 858, 266, 267, 268, 269, 270, 1039, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 859, 1040, 860, 293, - 294, 295, 296, 861, 297, 298, 1041, 300, 862, 863, - 302, 864, 304, 305, 306, 0, 307, 308, 0, 0, - 865, 310, 311, 0, 0, 312, 313, 1042, 315, 1043, - 866, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 0, 328, 329, 867, 331, 332, 333, 334, 335, - 336, 0, 337, 338, 339, 340, 341, 342, 0, 343, - 344, 345, 868, 347, 348, 349, 350, 0, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 0, 364, 365, 1044, 367, 368, 369, 869, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 0, 382, 383, 384, 385, 386, 870, 387, 388, 389, - 390, 391, 1045, 393, 394, 871, 396, 0, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 1046, 410, 872, 412, 0, 413, 414, 0, 415, 1047, - 417, 418, 419, 420, 421, 0, 873, 874, 0, 0, - 424, 425, 875, 427, 876, 877, 429, 430, 1048, 432, - 433, 434, 435, 436, 0, 0, 437, 438, 439, 440, - 441, 879, 0, 442, 443, 444, 445, 446, 447, 880, - 1049, 449, 1050, 451, 452, 453, 454, 455, 0, 0, - 456, 0, 0, 457, 458, 459, 460, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 881, 0, 0, 0, 0, 0, - 0, 882, 883, 1051, 0, 0, 0, 0, 885, 0, - 886, 1052, 0, 0, 0, 887, 0, 888, 889, 93, - 822, 550, 823, 824, 825, 826, 827, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, - 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, - 0, 0, 828, 0, 0, 105, 106, 0, 107, 108, - 109, 110, 111, 112, 113, 114, 829, 116, 830, 831, - 0, 119, 120, 121, 122, 123, 124, 832, 833, 125, - 126, 834, 835, 129, 0, 130, 131, 132, 133, 836, - 0, 837, 0, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, - 0, 152, 153, 154, 155, 838, 839, 840, 841, 842, - 843, 844, 157, 158, 159, 160, 161, 162, 163, 845, - 846, 166, 847, 167, 0, 168, 169, 170, 171, 172, - 173, 0, 174, 175, 176, 177, 178, 0, 0, 179, - 180, 681, 182, 183, 0, 184, 185, 186, 0, 187, - 188, 189, 0, 190, 191, 192, 193, 848, 195, 196, - 197, 198, 199, 849, 850, 201, 0, 202, 203, 851, - 205, 0, 206, 0, 207, 208, 0, 209, 210, 211, - 212, 213, 214, 0, 215, 0, 852, 853, 218, 0, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 0, 231, 232, 233, 234, 235, 236, 0, - 237, 238, 239, 240, 241, 242, 243, 244, 854, 855, - 0, 856, 0, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 0, 0, 259, 260, 261, 262, - 0, 263, 264, 265, 857, 858, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 859, 291, 860, 293, 294, 295, 296, 861, 297, 298, - 299, 300, 862, 863, 302, 864, 304, 305, 306, 0, - 307, 308, 0, 0, 865, 310, 311, 0, 0, 312, - 313, 314, 315, 316, 866, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 0, 328, 329, 867, 331, - 332, 333, 334, 335, 336, 0, 337, 338, 339, 340, - 341, 342, 0, 343, 344, 345, 868, 347, 348, 349, - 350, 0, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 0, 364, 365, 366, 367, - 368, 369, 869, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 26, 382, 383, 384, 385, 386, - 870, 387, 388, 389, 390, 391, 392, 393, 394, 871, - 396, 0, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 872, 412, 0, 413, - 414, 31, 415, 416, 417, 418, 419, 420, 421, 0, - 873, 874, 0, 0, 424, 425, 875, 427, 876, 877, - 429, 430, 878, 432, 433, 434, 435, 436, 0, 0, - 437, 438, 439, 440, 441, 879, 0, 442, 443, 444, - 445, 446, 578, 880, 0, 449, 450, 451, 452, 453, - 454, 455, 0, 0, 456, 0, 34, 457, 458, 459, - 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 881, 0, - 35, 0, 0, 0, 0, 882, 883, 0, 0, 0, - 0, 0, 885, 0, 886, 2849, 0, 0, 0, 887, - 0, 888, 889, 93, 822, 550, 823, 824, 825, 826, - 827, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, - 103, 104, 0, 0, 0, 0, 828, 0, 0, 105, - 106, 0, 107, 108, 109, 110, 111, 112, 113, 114, - 829, 116, 830, 831, 0, 119, 120, 121, 122, 123, - 124, 832, 833, 125, 126, 834, 835, 129, 0, 130, - 131, 132, 133, 836, 0, 837, 0, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, 152, 153, 154, 155, 838, - 839, 840, 841, 842, 843, 844, 157, 158, 159, 160, - 161, 162, 163, 845, 846, 166, 847, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 681, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 848, 195, 196, 197, 198, 199, 849, 850, 201, - 0, 202, 203, 851, 205, 0, 206, 0, 207, 208, - 0, 209, 210, 211, 212, 213, 214, 0, 215, 0, - 852, 853, 218, 0, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 238, 239, 240, 241, 242, - 243, 244, 854, 855, 0, 856, 0, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 0, 0, - 259, 260, 261, 262, 0, 263, 264, 265, 857, 858, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 0, 0, 0, 0, 0, 0, 0, 0, 1415, 0, + 0, 0, 0, 1403, 0, 0, 1404, 1405, 1406, 0, + 1407, 1408, 1409, 1410, 1411, 1412, 0, 0, 0, 0, + 2364, 0, 0, 0, 0, 0, 0, 1415, 0, 0, + 0, 0, 0, 0, 0, 0, 1080, 883, 582, 884, + 885, 886, 887, 888, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, + 100, 101, 1081, 102, 103, 104, 0, 0, 0, 0, + 889, 0, 0, 105, 106, 1415, 107, 108, 109, 1082, + 111, 112, 113, 114, 890, 1083, 891, 892, 0, 119, + 120, 121, 122, 123, 124, 893, 894, 125, 126, 895, + 896, 129, 0, 130, 131, 132, 133, 897, 0, 1084, + 0, 136, 137, 138, 139, 140, 141, 1085, 143, 144, + 145, 0, 146, 147, 148, 149, 150, 151, 0, 1086, + 153, 154, 155, 1087, 1088, 1089, 1090, 903, 904, 1091, + 161, 162, 163, 164, 165, 166, 167, 906, 907, 170, + 908, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 1092, 0, 183, 184, 712, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 909, 199, 200, 201, 202, + 203, 910, 911, 205, 0, 206, 207, 912, 209, 0, + 210, 0, 211, 1093, 0, 1094, 214, 215, 1095, 1096, + 218, 0, 219, 0, 913, 914, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 1097, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 1098, + 243, 244, 245, 246, 247, 248, 915, 916, 0, 917, + 0, 252, 1099, 1100, 255, 1101, 257, 258, 259, 260, + 261, 262, 0, 0, 263, 1102, 265, 1103, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 1104, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 859, 291, 860, 293, 294, 295, - 296, 861, 297, 298, 299, 300, 862, 863, 302, 864, - 304, 305, 306, 0, 307, 308, 0, 0, 865, 310, - 311, 0, 0, 312, 313, 314, 315, 316, 866, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 867, 331, 332, 333, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 868, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 366, 367, 368, 369, 869, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 26, 382, - 383, 384, 385, 386, 870, 387, 388, 389, 390, 391, - 392, 393, 394, 871, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 872, 412, 0, 413, 414, 31, 415, 416, 417, 418, - 419, 420, 421, 0, 873, 874, 0, 0, 424, 425, - 875, 427, 876, 877, 429, 430, 878, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 879, - 0, 442, 443, 444, 445, 446, 578, 880, 0, 449, - 450, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 34, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 881, 0, 35, 0, 0, 0, 0, 882, - 883, 0, 0, 0, 0, 0, 885, 0, 886, 0, - 0, 0, 0, 887, 0, 888, 889, 93, 822, 550, - 823, 824, 825, 826, 827, 0, 0, 0, 0, 0, + 286, 287, 288, 289, 290, 291, 292, 293, 920, 1105, + 921, 297, 298, 299, 300, 922, 301, 302, 1106, 304, + 923, 924, 306, 925, 308, 309, 310, 0, 311, 312, + 0, 0, 926, 314, 315, 0, 0, 316, 317, 1107, + 319, 1108, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 929, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 1109, 371, 372, 373, + 930, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 0, 386, 387, 388, 389, 390, 1110, 392, + 393, 394, 395, 396, 1111, 398, 399, 932, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 1112, 415, 933, 417, 0, 418, 419, 0, + 420, 1113, 422, 423, 424, 425, 426, 0, 934, 935, + 0, 0, 429, 430, 936, 432, 937, 938, 434, 435, + 1114, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 1115, 0, 448, 449, 450, 451, 452, + 453, 941, 1116, 455, 1117, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 483, 942, 0, 0, 0, + 0, 0, 0, 943, 944, 1118, 0, 0, 0, 0, + 946, 0, 947, 1119, 0, 0, 0, 948, 0, 949, + 950, 93, 883, 582, 884, 885, 886, 887, 888, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, + 104, 0, 0, 0, 0, 889, 0, 0, 105, 106, + 0, 107, 108, 109, 110, 111, 112, 113, 114, 890, + 116, 891, 892, 0, 119, 120, 121, 122, 123, 124, + 893, 894, 125, 126, 895, 896, 129, 0, 130, 131, + 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, + 149, 150, 151, 0, 152, 153, 154, 155, 899, 900, + 901, 902, 903, 904, 905, 161, 162, 163, 164, 165, + 166, 167, 906, 907, 170, 908, 171, 0, 172, 173, + 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, + 0, 0, 183, 184, 712, 186, 187, 0, 188, 189, + 190, 0, 191, 192, 193, 0, 194, 195, 196, 197, + 909, 199, 200, 201, 202, 203, 910, 911, 205, 0, + 206, 207, 912, 209, 0, 210, 0, 211, 212, 0, + 213, 214, 215, 216, 217, 218, 0, 219, 0, 913, + 914, 222, 0, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 0, 235, 236, 237, 238, + 239, 240, 0, 241, 242, 243, 244, 245, 246, 247, + 248, 915, 916, 0, 917, 0, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 0, 0, 263, + 264, 265, 266, 0, 267, 268, 269, 918, 919, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 920, 295, 921, 297, 298, 299, 300, + 922, 301, 302, 303, 304, 923, 924, 306, 925, 308, + 309, 310, 0, 311, 312, 0, 0, 926, 314, 315, + 0, 0, 316, 317, 318, 319, 320, 927, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 0, 332, + 333, 928, 335, 336, 337, 338, 339, 340, 0, 341, + 342, 343, 344, 345, 346, 0, 347, 348, 349, 929, + 351, 352, 353, 354, 0, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 0, 368, + 369, 370, 371, 372, 373, 930, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 26, 386, 387, + 388, 389, 390, 931, 392, 393, 394, 395, 396, 397, + 398, 399, 932, 401, 0, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 933, + 417, 0, 418, 419, 31, 420, 421, 422, 423, 424, + 425, 426, 0, 934, 935, 0, 0, 429, 430, 936, + 432, 937, 938, 434, 435, 939, 437, 438, 439, 440, + 441, 0, 0, 442, 443, 444, 445, 446, 940, 0, + 448, 449, 450, 451, 452, 610, 941, 0, 455, 456, + 457, 458, 459, 460, 461, 0, 0, 462, 0, 34, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 483, 942, 0, 35, 0, 0, 0, 0, 943, 944, + 0, 0, 0, 0, 0, 946, 0, 947, 2910, 0, + 0, 0, 948, 0, 949, 950, 93, 883, 582, 884, + 885, 886, 887, 888, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, - 828, 0, 0, 105, 106, 0, 107, 108, 109, 110, - 111, 112, 113, 114, 829, 116, 830, 831, 1661, 119, - 120, 121, 122, 123, 124, 832, 833, 125, 126, 834, - 835, 129, 0, 130, 131, 132, 133, 836, 0, 837, + 889, 0, 0, 105, 106, 0, 107, 108, 109, 110, + 111, 112, 113, 114, 890, 116, 891, 892, 0, 119, + 120, 121, 122, 123, 124, 893, 894, 125, 126, 895, + 896, 129, 0, 130, 131, 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 152, - 153, 154, 155, 838, 839, 840, 841, 842, 843, 844, - 157, 158, 159, 160, 161, 162, 163, 845, 846, 166, - 847, 167, 0, 168, 169, 170, 171, 172, 173, 0, - 174, 175, 176, 177, 178, 0, 0, 179, 180, 681, - 182, 183, 0, 184, 185, 186, 0, 187, 188, 189, - 0, 190, 191, 192, 193, 848, 195, 196, 197, 198, - 199, 849, 850, 201, 0, 202, 203, 851, 205, 0, - 206, 0, 207, 208, 1662, 209, 210, 211, 212, 213, - 214, 0, 215, 0, 852, 853, 218, 0, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 0, 231, 232, 233, 234, 235, 236, 0, 237, 238, - 239, 240, 241, 242, 243, 244, 854, 855, 0, 856, - 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 0, 1663, 259, 260, 261, 262, 0, 263, - 264, 265, 857, 858, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 859, 291, - 860, 293, 294, 295, 296, 861, 297, 298, 299, 300, - 862, 863, 302, 864, 304, 305, 306, 0, 307, 308, - 0, 0, 865, 310, 311, 0, 0, 312, 313, 314, - 315, 316, 866, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 0, 328, 329, 867, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 339, 340, 341, 342, - 0, 343, 344, 345, 868, 347, 348, 349, 350, 0, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 0, 364, 365, 366, 367, 368, 369, - 869, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 0, 382, 383, 384, 385, 386, 870, 387, - 388, 389, 390, 391, 392, 393, 394, 871, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 872, 412, 0, 413, 414, 0, - 415, 416, 417, 418, 419, 420, 421, 0, 873, 874, - 0, 1664, 424, 425, 875, 427, 876, 877, 429, 430, - 878, 432, 433, 434, 435, 436, 0, 0, 437, 438, - 439, 440, 441, 879, 0, 442, 443, 444, 445, 446, - 447, 880, 0, 449, 450, 451, 452, 453, 454, 455, - 0, 0, 456, 0, 0, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 881, 0, 0, 0, - 0, 0, 0, 882, 883, 0, 0, 0, 0, 0, - 885, 0, 886, 0, 0, 0, 0, 887, 0, 888, - 889, 93, 822, 550, 823, 824, 825, 826, 827, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, - 96, 97, 98, 99, 100, 101, -959, 102, 103, 104, - 0, 0, 0, -959, 828, 0, 0, 105, 106, 0, - 107, 108, 109, 110, 111, 112, 113, 114, 829, 116, - 830, 831, 0, 119, 120, 121, 122, 123, 124, 832, - 833, 125, 126, 834, 835, 129, 0, 130, 131, 132, - 133, 836, 0, 837, 0, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, - 150, 151, 0, 152, 153, 154, 155, 838, 839, 840, - 841, 842, 843, 844, 157, 158, 159, 160, 161, 162, - 163, 845, 846, 166, 847, 167, 0, 168, 169, 170, - 171, 172, 173, 0, 174, 175, 176, 177, 178, 0, - 0, 179, 180, 681, 182, 183, 0, 184, 185, 186, - 0, 187, 188, 189, 0, 190, 191, 192, 193, 848, - 195, 196, 197, 198, 199, 849, 850, 201, 0, 202, - 203, 851, 205, 0, 206, 0, 207, 208, 0, 209, - 210, 211, 212, 213, 214, 0, 215, 0, 852, 853, - 218, 0, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 0, 231, 232, 233, 234, 235, - 236, 0, 237, 238, 239, 240, 241, 242, 243, 244, - 854, 855, 0, 856, 0, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 0, 0, 259, 260, - 261, 262, 0, 263, 264, 265, 857, 858, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 859, 291, 860, 293, 294, 295, 296, 861, - 297, 298, 299, 300, 862, 863, 302, 864, 304, 305, - 306, 0, 307, 308, 0, 0, 865, 310, 311, 0, - 0, 312, 313, 314, 315, 316, 866, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 0, 328, 329, - 867, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 339, 340, 341, 342, 0, 343, 344, 345, 868, 347, - 348, 349, 350, 0, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 0, 364, 365, - 366, 367, 368, 369, 869, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 0, 382, 383, 384, - 385, 386, 870, 387, 388, 389, 390, 391, 392, 393, - 394, 871, 396, -959, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 872, 412, - 0, 413, 414, 0, 415, 416, 417, 418, 419, 420, - 421, 0, 873, 874, 0, 0, 424, 425, 875, 427, - 876, 877, 429, 430, 878, 432, 433, 434, 435, 436, - 0, 0, 437, 438, 439, 440, 441, 879, 0, 442, - 443, 444, 445, 446, 447, 880, 0, 449, 450, 451, - 452, 453, 454, 455, 0, 0, 456, 0, 0, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, + 153, 154, 155, 899, 900, 901, 902, 903, 904, 905, + 161, 162, 163, 164, 165, 166, 167, 906, 907, 170, + 908, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 712, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 909, 199, 200, 201, 202, + 203, 910, 911, 205, 0, 206, 207, 912, 209, 0, + 210, 0, 211, 212, 0, 213, 214, 215, 216, 217, + 218, 0, 219, 0, 913, 914, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 242, + 243, 244, 245, 246, 247, 248, 915, 916, 0, 917, + 0, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 0, 0, 263, 264, 265, 266, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 920, 295, + 921, 297, 298, 299, 300, 922, 301, 302, 303, 304, + 923, 924, 306, 925, 308, 309, 310, 0, 311, 312, + 0, 0, 926, 314, 315, 0, 0, 316, 317, 318, + 319, 320, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 929, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 370, 371, 372, 373, + 930, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 26, 386, 387, 388, 389, 390, 931, 392, + 393, 394, 395, 396, 397, 398, 399, 932, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 933, 417, 0, 418, 419, 31, + 420, 421, 422, 423, 424, 425, 426, 0, 934, 935, + 0, 0, 429, 430, 936, 432, 937, 938, 434, 435, + 939, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 940, 0, 448, 449, 450, 451, 452, + 610, 941, 0, 455, 456, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 34, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 881, 0, 0, 0, 0, 0, 0, 882, 883, 0, - 0, 0, 0, 0, 885, 0, 886, 0, 0, 0, - 0, 887, 0, 888, 889, 93, 822, 550, 823, 824, - 825, 826, 827, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, - 1400, 102, 103, 104, 0, 0, 0, 0, 828, 0, - 0, 105, 106, 0, 107, 108, 109, 110, 111, 112, - 113, 114, 829, 116, 830, 831, 0, 119, 120, 121, - 122, 123, 124, 832, 833, 125, 126, 834, 835, 129, - 0, 130, 131, 132, 133, 836, 0, 837, 0, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, - 146, 147, 148, 149, 150, 151, 0, 152, 153, 154, - 155, 838, 839, 840, 841, 842, 843, 844, 157, 158, - 159, 160, 161, 162, 163, 845, 846, 166, 847, 167, - 0, 168, 169, 170, 171, 172, 173, 0, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 681, 182, 183, - 0, 184, 185, 186, 0, 187, 188, 189, 0, 190, - 191, 192, 193, 848, 195, 196, 197, 198, 199, 849, - 850, 201, 0, 202, 203, 851, 205, 0, 206, 0, - 207, 208, 0, 209, 210, 211, 212, 213, 214, 0, - 215, 0, 852, 853, 218, 0, 219, 220, 221, 222, - 223, 224, 225, 226, 227, 228, 229, 230, 0, 231, - 232, 233, 234, 235, 236, 0, 237, 238, 239, 240, - 241, 242, 243, 244, 854, 855, 0, 856, 0, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 0, 0, 259, 260, 261, 262, 0, 263, 264, 265, - 857, 858, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 859, 291, 860, 293, - 294, 295, 296, 861, 297, 298, 299, 300, 862, 863, - 302, 864, 304, 305, 306, 0, 307, 308, 0, 0, - 865, 310, 311, 0, 0, 312, 313, 314, 315, 316, - 866, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 0, 328, 329, 867, 331, 332, 333, 334, 335, - 336, 0, 337, 338, 339, 340, 341, 342, 0, 343, - 344, 345, 868, 347, 348, 349, 350, 0, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 0, 364, 365, 366, 367, 368, 369, 869, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 0, 382, 383, 384, 385, 386, 870, 387, 388, 389, - 390, 391, 392, 393, 394, 871, 396, 0, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 872, 412, 0, 413, 414, 0, 415, 416, - 417, 418, 419, 420, 421, 0, 873, 874, 0, 0, - 424, 425, 875, 427, 876, 877, 429, 430, 878, 432, - 433, 434, 435, 436, 0, 0, 437, 438, 439, 440, - 441, 879, 0, 442, 443, 444, 445, 446, 447, 880, - 0, 449, 450, 451, 452, 453, 454, 455, 0, 0, - 456, 0, 0, 457, 458, 459, 460, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 881, 0, 0, 0, 0, 0, - 0, 882, 883, 1401, 0, 0, 0, 0, 885, 0, - 886, 0, 0, 0, 0, 887, 0, 888, 889, 93, - 822, 550, 823, 824, 825, 826, 827, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, - 98, 99, 100, 101, 2737, 102, 103, 104, 0, 0, - 0, 0, 828, 0, 0, 105, 106, 0, 107, 108, - 109, 110, 111, 112, 113, 114, 829, 116, 830, 831, - 0, 119, 120, 121, 122, 123, 124, 832, 833, 125, - 126, 834, 835, 129, 0, 130, 131, 132, 133, 836, - 0, 837, 0, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, - 0, 152, 153, 2738, 155, 838, 839, 840, 841, 842, - 843, 844, 157, 158, 159, 160, 161, 162, 163, 845, - 846, 166, 847, 167, 0, 168, 169, 170, 171, 172, - 173, 0, 174, 175, 176, 177, 178, 0, 0, 179, - 180, 681, 182, 183, 0, 184, 185, 186, 0, 187, - 188, 189, 0, 190, 191, 192, 193, 848, 195, 196, - 197, 198, 199, 849, 850, 201, 0, 202, 203, 851, - 205, 0, 206, 0, 207, 208, 0, 209, 210, 211, - 212, 213, 214, 0, 215, 0, 2739, 853, 218, 0, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 0, 231, 232, 233, 234, 235, 236, 0, - 237, 238, 239, 240, 241, 242, 243, 244, 854, 855, - 0, 856, 0, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 0, 0, 259, 260, 261, 262, - 0, 263, 264, 265, 857, 858, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 859, 291, 860, 293, 294, 295, 296, 861, 297, 298, - 299, 300, 862, 863, 302, 864, 304, 305, 306, 0, - 307, 308, 0, 0, 865, 310, 311, 0, 0, 312, - 313, 314, 315, 316, 866, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 0, 328, 329, 867, 331, - 332, 333, 334, 335, 336, 0, 337, 338, 339, 340, - 341, 342, 0, 343, 344, 345, 868, 347, 348, 349, - 350, 0, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 0, 364, 365, 366, 367, - 368, 2740, 869, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 0, 382, 383, 384, 385, 386, - 870, 387, 388, 389, 390, 391, 392, 393, 394, 871, - 396, 0, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 872, 412, 0, 413, - 414, 0, 415, 416, 417, 418, 419, 420, 421, 0, - 873, 874, 0, 0, 424, 425, 875, 427, 876, 877, - 429, 430, 878, 432, 433, 434, 435, 436, 0, 0, - 437, 438, 439, 440, 441, 879, 0, 442, 443, 444, - 445, 446, 447, 880, 0, 449, 450, 451, 452, 453, - 454, 455, 0, 0, 456, 0, 0, 457, 458, 459, - 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 881, 0, - 0, 0, 0, 0, 0, 882, 883, 2741, 0, 0, - 0, 0, 885, 0, 2742, 0, 0, 0, 0, 887, - 0, 888, 889, 93, 822, 550, 823, 824, 825, 826, - 827, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, - 103, 104, 0, 0, 0, 0, 828, 0, 0, 105, - 106, 0, 107, 108, 109, 110, 111, 112, 113, 114, - 829, 116, 830, 831, 0, 119, 120, 121, 122, 123, - 124, 832, 833, 125, 126, 834, 835, 129, 0, 130, - 131, 132, 133, 836, 0, 837, 0, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, 152, 153, 154, 155, 838, - 839, 840, 841, 842, 843, 844, 157, 158, 159, 160, - 161, 162, 163, 845, 846, 166, 847, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 681, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 848, 195, 196, 197, 198, 199, 849, 850, 201, - 0, 202, 203, 851, 205, 0, 206, 0, 207, 208, - 0, 209, 210, 211, 212, 213, 214, 0, 215, 0, - 852, 853, 218, 0, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 238, 239, 240, 241, 242, - 243, 244, 854, 855, 0, 856, 0, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 0, 0, - 259, 260, 261, 262, 0, 263, 264, 265, 857, 858, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 478, 479, 480, 481, 482, 483, 942, 0, 35, 0, + 0, 0, 0, 943, 944, 0, 0, 0, 0, 0, + 946, 0, 947, 0, 0, 0, 0, 948, 0, 949, + 950, 93, 883, 582, 884, 885, 886, 887, 888, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, + 104, 0, 0, 0, 0, 889, 0, 0, 105, 106, + 0, 107, 108, 109, 110, 111, 112, 113, 114, 890, + 116, 891, 892, 1722, 119, 120, 121, 122, 123, 124, + 893, 894, 125, 126, 895, 896, 129, 0, 130, 131, + 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, + 149, 150, 151, 0, 152, 153, 154, 155, 899, 900, + 901, 902, 903, 904, 905, 161, 162, 163, 164, 165, + 166, 167, 906, 907, 170, 908, 171, 0, 172, 173, + 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, + 0, 0, 183, 184, 712, 186, 187, 0, 188, 189, + 190, 0, 191, 192, 193, 0, 194, 195, 196, 197, + 909, 199, 200, 201, 202, 203, 910, 911, 205, 0, + 206, 207, 912, 209, 0, 210, 0, 211, 212, 1723, + 213, 214, 215, 216, 217, 218, 0, 219, 0, 913, + 914, 222, 0, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 0, 235, 236, 237, 238, + 239, 240, 0, 241, 242, 243, 244, 245, 246, 247, + 248, 915, 916, 0, 917, 0, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 0, 1724, 263, + 264, 265, 266, 0, 267, 268, 269, 918, 919, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 920, 295, 921, 297, 298, 299, 300, + 922, 301, 302, 303, 304, 923, 924, 306, 925, 308, + 309, 310, 0, 311, 312, 0, 0, 926, 314, 315, + 0, 0, 316, 317, 318, 319, 320, 927, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 0, 332, + 333, 928, 335, 336, 337, 338, 339, 340, 0, 341, + 342, 343, 344, 345, 346, 0, 347, 348, 349, 929, + 351, 352, 353, 354, 0, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 0, 368, + 369, 370, 371, 372, 373, 930, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 0, 386, 387, + 388, 389, 390, 931, 392, 393, 394, 395, 396, 397, + 398, 399, 932, 401, 0, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 933, + 417, 0, 418, 419, 0, 420, 421, 422, 423, 424, + 425, 426, 0, 934, 935, 0, 1725, 429, 430, 936, + 432, 937, 938, 434, 435, 939, 437, 438, 439, 440, + 441, 0, 0, 442, 443, 444, 445, 446, 940, 0, + 448, 449, 450, 451, 452, 453, 941, 0, 455, 456, + 457, 458, 459, 460, 461, 0, 0, 462, 0, 0, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 483, 942, 0, 0, 0, 0, 0, 0, 943, 944, + 0, 0, 0, 0, 0, 946, 0, 947, 0, 0, + 0, 0, 948, 0, 949, 950, 93, 883, 582, 884, + 885, 886, 887, 888, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, + 100, 101, -960, 102, 103, 104, 0, 0, 0, -960, + 889, 0, 0, 105, 106, 0, 107, 108, 109, 110, + 111, 112, 113, 114, 890, 116, 891, 892, 0, 119, + 120, 121, 122, 123, 124, 893, 894, 125, 126, 895, + 896, 129, 0, 130, 131, 132, 133, 897, 0, 898, + 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 0, 146, 147, 148, 149, 150, 151, 0, 152, + 153, 154, 155, 899, 900, 901, 902, 903, 904, 905, + 161, 162, 163, 164, 165, 166, 167, 906, 907, 170, + 908, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 712, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 909, 199, 200, 201, 202, + 203, 910, 911, 205, 0, 206, 207, 912, 209, 0, + 210, 0, 211, 212, 0, 213, 214, 215, 216, 217, + 218, 0, 219, 0, 913, 914, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 242, + 243, 244, 245, 246, 247, 248, 915, 916, 0, 917, + 0, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 0, 0, 263, 264, 265, 266, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 859, 291, 860, 293, 294, 295, - 296, 861, 297, 298, 299, 300, 862, 863, 302, 864, - 304, 305, 306, 0, 307, 308, 0, 0, 865, 310, - 311, 0, 0, 312, 313, 314, 315, 316, 866, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 867, 331, 332, 333, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 868, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 366, 367, 368, 369, 869, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 0, 382, - 383, 384, 385, 386, 870, 387, 388, 389, 390, 391, - 392, 393, 394, 871, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 872, 412, 0, 413, 414, 0, 415, 416, 417, 418, - 419, 420, 421, 0, 873, 874, 0, 0, 424, 425, - 875, 427, 876, 877, 429, 430, 878, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 879, - 0, 442, 443, 444, 445, 446, 447, 880, 0, 449, - 450, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 0, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 881, 0, 0, 0, 0, 0, 0, 882, - 883, 884, 0, 0, 0, 0, 885, 0, 886, 0, - 0, 0, 0, 887, 0, 888, 889, 93, 1414, 550, - 823, 824, 825, 1415, 827, 0, 0, 0, 0, 0, + 286, 287, 288, 289, 290, 291, 292, 293, 920, 295, + 921, 297, 298, 299, 300, 922, 301, 302, 303, 304, + 923, 924, 306, 925, 308, 309, 310, 0, 311, 312, + 0, 0, 926, 314, 315, 0, 0, 316, 317, 318, + 319, 320, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 929, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 370, 371, 372, 373, + 930, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 0, 386, 387, 388, 389, 390, 931, 392, + 393, 394, 395, 396, 397, 398, 399, 932, 401, -960, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 933, 417, 0, 418, 419, 0, + 420, 421, 422, 423, 424, 425, 426, 0, 934, 935, + 0, 0, 429, 430, 936, 432, 937, 938, 434, 435, + 939, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 940, 0, 448, 449, 450, 451, 452, + 453, 941, 0, 455, 456, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 483, 942, 0, 0, 0, + 0, 0, 0, 943, 944, 0, 0, 0, 0, 0, + 946, 0, 947, 0, 0, 0, 0, 948, 0, 949, + 950, 93, 883, 582, 884, 885, 886, 887, 888, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 95, 96, 97, 98, 99, 100, 101, 1461, 102, 103, + 104, 0, 0, 0, 0, 889, 0, 0, 105, 106, + 0, 107, 108, 109, 110, 111, 112, 113, 114, 890, + 116, 891, 892, 0, 119, 120, 121, 122, 123, 124, + 893, 894, 125, 126, 895, 896, 129, 0, 130, 131, + 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, + 149, 150, 151, 0, 152, 153, 154, 155, 899, 900, + 901, 902, 903, 904, 905, 161, 162, 163, 164, 165, + 166, 167, 906, 907, 170, 908, 171, 0, 172, 173, + 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, + 0, 0, 183, 184, 712, 186, 187, 0, 188, 189, + 190, 0, 191, 192, 193, 0, 194, 195, 196, 197, + 909, 199, 200, 201, 202, 203, 910, 911, 205, 0, + 206, 207, 912, 209, 0, 210, 0, 211, 212, 0, + 213, 214, 215, 216, 217, 218, 0, 219, 0, 913, + 914, 222, 0, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 0, 235, 236, 237, 238, + 239, 240, 0, 241, 242, 243, 244, 245, 246, 247, + 248, 915, 916, 0, 917, 0, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 0, 0, 263, + 264, 265, 266, 0, 267, 268, 269, 918, 919, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 920, 295, 921, 297, 298, 299, 300, + 922, 301, 302, 303, 304, 923, 924, 306, 925, 308, + 309, 310, 0, 311, 312, 0, 0, 926, 314, 315, + 0, 0, 316, 317, 318, 319, 320, 927, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 0, 332, + 333, 928, 335, 336, 337, 338, 339, 340, 0, 341, + 342, 343, 344, 345, 346, 0, 347, 348, 349, 929, + 351, 352, 353, 354, 0, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 0, 368, + 369, 370, 371, 372, 373, 930, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 0, 386, 387, + 388, 389, 390, 931, 392, 393, 394, 395, 396, 397, + 398, 399, 932, 401, 0, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 933, + 417, 0, 418, 419, 0, 420, 421, 422, 423, 424, + 425, 426, 0, 934, 935, 0, 0, 429, 430, 936, + 432, 937, 938, 434, 435, 939, 437, 438, 439, 440, + 441, 0, 0, 442, 443, 444, 445, 446, 940, 0, + 448, 449, 450, 451, 452, 453, 941, 0, 455, 456, + 457, 458, 459, 460, 461, 0, 0, 462, 0, 0, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 483, 942, 0, 0, 0, 0, 0, 0, 943, 944, + 1462, 0, 0, 0, 0, 946, 0, 947, 0, 0, + 0, 0, 948, 0, 949, 950, 93, 883, 582, 884, + 885, 886, 887, 888, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, - 100, 101, 1416, 102, 103, 104, 0, 0, 0, 0, - 828, 0, 0, 105, 106, 0, 107, 108, 109, 110, - 111, 112, 113, 114, 829, 116, 830, 831, 0, 119, - 120, 121, 122, 123, 124, 832, 833, 125, 126, 834, - 835, 129, 0, 130, 131, 132, 133, 836, 0, 837, + 100, 101, 2798, 102, 103, 104, 0, 0, 0, 0, + 889, 0, 0, 105, 106, 0, 107, 108, 109, 110, + 111, 112, 113, 114, 890, 116, 891, 892, 0, 119, + 120, 121, 122, 123, 124, 893, 894, 125, 126, 895, + 896, 129, 0, 130, 131, 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 152, - 153, 154, 155, 838, 839, 840, 841, 842, 843, 844, - 157, 158, 159, 160, 161, 162, 163, 845, 846, 166, - 847, 167, 0, 168, 169, 170, 171, 172, 173, 0, - 174, 175, 176, 177, 178, 0, 0, 179, 180, 681, - 182, 183, 0, 184, 185, 186, 0, 187, 188, 189, - 0, 190, 191, 192, 193, 848, 195, 196, 197, 198, - 199, 849, 850, 201, 0, 202, 203, 851, 205, 0, - 206, 0, 207, 208, 0, 209, 210, 211, 212, 213, - 214, 0, 215, 0, 852, 853, 218, 0, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 0, 231, 232, 233, 234, 235, 236, 0, 237, 238, - 239, 240, 241, 242, 243, 244, 854, 855, 0, 856, - 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 0, 0, 259, 260, 261, 262, 0, 263, - 264, 265, 857, 858, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 859, 291, - 860, 293, 294, 295, 296, 861, 297, 298, 299, 300, - 862, 863, 302, 864, 304, 305, 306, 0, 307, 308, - 0, 0, 865, 310, 311, 0, 0, 312, 313, 314, - 315, 316, 866, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 0, 328, 329, 867, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 339, 340, 341, 342, - 0, 343, 344, 345, 868, 347, 348, 349, 350, 0, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 0, 364, 365, 366, 367, 368, 369, - 869, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 0, 382, 383, 384, 385, 386, 870, 387, - 388, 389, 390, 391, 392, 393, 394, 871, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 872, 412, 0, 413, 414, 0, - 415, 416, 417, 418, 419, 420, 421, 0, 873, 874, - 0, 0, 424, 425, 875, 427, 876, 877, 429, 430, - 878, 432, 433, 434, 435, 436, 0, 0, 437, 438, - 439, 440, 441, 879, 0, 442, 443, 444, 445, 446, - 447, 880, 0, 449, 450, 451, 452, 453, 454, 455, - 0, 0, 456, 0, 0, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 881, 0, 0, 0, - 0, 0, 0, 882, 883, 0, 0, 0, 0, 0, - 885, 0, 886, 0, 0, 0, 0, 887, 0, 888, - 889, 93, 822, 550, 823, 824, 825, 826, 827, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, - 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, - 0, 0, 0, 0, 828, 0, 0, 105, 106, 0, - 107, 108, 109, 110, 111, 112, 113, 114, 829, 116, - 830, 831, 0, 119, 120, 121, 122, 123, 124, 832, - 833, 125, 126, 834, 835, 129, 0, 130, 131, 132, - 133, 836, 0, 837, 0, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, - 150, 151, 0, 152, 153, 154, 155, 838, 839, 840, - 841, 842, 843, 844, 157, 158, 159, 160, 161, 162, - 163, 845, 846, 166, 847, 167, 0, 168, 169, 170, - 171, 172, 173, 0, 174, 175, 176, 177, 178, 0, - 0, 179, 180, 681, 182, 183, 0, 184, 185, 186, - 0, 187, 188, 189, 0, 190, 191, 192, 193, 848, - 195, 196, 197, 198, 199, 849, 850, 201, 0, 202, - 203, 851, 205, 0, 206, 0, 207, 208, 0, 209, - 210, 211, 212, 213, 214, 0, 215, 0, 852, 853, - 218, 0, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 0, 231, 232, 233, 234, 235, - 236, 0, 237, 238, 239, 240, 241, 242, 243, 244, - 854, 855, 0, 856, 0, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 0, 0, 259, 260, - 261, 262, 0, 263, 264, 265, 857, 858, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 859, 291, 860, 293, 294, 295, 296, 861, - 297, 298, 299, 300, 862, 863, 302, 864, 304, 305, - 306, 0, 307, 308, 0, 0, 865, 310, 311, 0, - 0, 312, 313, 314, 315, 316, 866, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 0, 328, 329, - 867, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 339, 340, 341, 342, 0, 343, 344, 345, 868, 347, - 348, 349, 350, 0, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 0, 364, 365, - 366, 367, 368, 369, 869, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 0, 382, 383, 384, - 385, 386, 870, 387, 388, 389, 390, 391, 392, 393, - 394, 871, 396, 0, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 872, 412, - 0, 413, 414, 0, 415, 416, 417, 418, 419, 420, - 421, 0, 873, 874, 0, 0, 424, 425, 875, 427, - 876, 877, 429, 430, 878, 432, 433, 434, 435, 436, - 0, 0, 437, 438, 439, 440, 441, 879, 0, 442, - 443, 444, 445, 446, 447, 880, 0, 449, 450, 451, - 452, 453, 454, 455, 0, 0, 456, 0, 0, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, + 153, 2799, 155, 899, 900, 901, 902, 903, 904, 905, + 161, 162, 163, 164, 165, 166, 167, 906, 907, 170, + 908, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 712, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 909, 199, 200, 201, 202, + 203, 910, 911, 205, 0, 206, 207, 912, 209, 0, + 210, 0, 211, 212, 0, 213, 214, 215, 216, 217, + 218, 0, 219, 0, 2800, 914, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 242, + 243, 244, 245, 246, 247, 248, 915, 916, 0, 917, + 0, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 0, 0, 263, 264, 265, 266, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 920, 295, + 921, 297, 298, 299, 300, 922, 301, 302, 303, 304, + 923, 924, 306, 925, 308, 309, 310, 0, 311, 312, + 0, 0, 926, 314, 315, 0, 0, 316, 317, 318, + 319, 320, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 929, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 370, 371, 372, 2801, + 930, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 0, 386, 387, 388, 389, 390, 931, 392, + 393, 394, 395, 396, 397, 398, 399, 932, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 933, 417, 0, 418, 419, 0, + 420, 421, 422, 423, 424, 425, 426, 0, 934, 935, + 0, 0, 429, 430, 936, 432, 937, 938, 434, 435, + 939, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 940, 0, 448, 449, 450, 451, 452, + 453, 941, 0, 455, 456, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 881, 0, 0, 0, 0, 0, 0, 882, 883, 0, - 0, 0, 0, 0, 885, 0, 886, 1655, 0, 0, - 0, 887, 0, 888, 889, 1019, 822, 550, 823, 824, - 825, 826, 827, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, - 0, 102, 103, 104, 0, 0, 0, 0, 828, 0, - 0, 105, 106, 0, 107, 108, 109, 1021, 111, 112, - 113, 114, 829, 1022, 830, 831, 0, 119, 120, 121, - 122, 123, 124, 832, 833, 125, 126, 834, 835, 129, - 0, 130, 131, 132, 133, 836, 0, 1023, 0, 136, - 137, 138, 139, 140, 141, 1024, 143, 144, 145, 0, - 146, 147, 148, 149, 150, 151, 0, 1025, 153, 154, - 155, 838, 839, 840, 1026, 842, 843, 844, 157, 158, - 159, 160, 161, 162, 163, 845, 846, 166, 847, 167, - 0, 168, 169, 170, 171, 172, 173, 0, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 681, 182, 183, - 0, 184, 185, 186, 0, 187, 188, 189, 0, 190, - 191, 192, 193, 848, 195, 196, 197, 198, 199, 849, - 850, 201, 0, 202, 203, 851, 205, 0, 206, 0, - 207, 1028, 0, 1029, 210, 211, 1030, 1031, 214, 0, - 215, 0, 852, 853, 218, 0, 219, 220, 221, 222, - 223, 224, 225, 1032, 227, 228, 229, 230, 0, 231, - 232, 233, 234, 235, 236, 0, 237, 1033, 239, 240, - 241, 242, 243, 244, 854, 855, 0, 856, 0, 248, - 1034, 1035, 251, 1036, 253, 254, 255, 256, 257, 258, - 0, 0, 259, 1037, 261, 1038, 0, 263, 264, 265, - 857, 858, 266, 267, 268, 269, 270, 1039, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 859, 1040, 860, 293, - 294, 295, 296, 861, 297, 298, 1041, 300, 862, 863, - 302, 864, 304, 305, 306, 0, 307, 308, 0, 0, - 865, 310, 311, 0, 0, 312, 313, 1042, 315, 1043, - 866, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 0, 328, 329, 867, 331, 332, 333, 334, 335, - 336, 0, 337, 338, 339, 340, 341, 342, 0, 343, - 344, 345, 868, 347, 348, 349, 350, 0, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 0, 364, 365, 1044, 367, 368, 369, 869, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 0, 382, 383, 384, 385, 386, 870, 387, 388, 389, - 390, 391, 1045, 393, 394, 871, 396, 0, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 1046, 410, 872, 412, 0, 413, 414, 0, 415, 1047, - 417, 418, 419, 420, 421, 0, 873, 874, 0, 0, - 424, 425, 875, 427, 876, 877, 429, 430, 1048, 432, - 433, 434, 435, 436, 0, 0, 437, 438, 439, 440, - 441, 879, 0, 442, 443, 444, 445, 446, 447, 880, - 1877, 449, 1050, 451, 452, 453, 454, 455, 0, 0, - 456, 0, 0, 457, 458, 459, 460, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 881, 0, 0, 0, 0, 0, - 0, 882, 883, 0, 0, 0, 0, 0, 885, 0, - 886, 0, 0, 0, 0, 887, 0, 888, 889, 1019, - 822, 550, 823, 824, 825, 826, 827, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, - 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, - 0, 0, 828, 0, 0, 105, 106, 0, 107, 108, - 109, 1021, 111, 112, 113, 114, 829, 1022, 830, 831, - 0, 119, 120, 121, 122, 123, 124, 832, 833, 125, - 126, 834, 835, 129, 0, 130, 131, 132, 133, 836, - 0, 1023, 0, 136, 137, 138, 139, 140, 141, 1024, - 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, - 0, 1025, 153, 154, 155, 838, 839, 840, 1026, 842, - 843, 844, 157, 158, 159, 160, 161, 162, 163, 845, - 846, 166, 847, 167, 0, 168, 169, 170, 171, 172, - 173, 0, 174, 175, 176, 177, 178, 0, 0, 179, - 180, 681, 182, 183, 0, 184, 185, 186, 0, 187, - 188, 189, 0, 190, 191, 192, 193, 848, 195, 196, - 197, 198, 199, 849, 850, 201, 0, 202, 203, 851, - 205, 0, 206, 0, 207, 1028, 0, 1029, 210, 211, - 1030, 1031, 214, 0, 215, 0, 852, 853, 218, 0, - 219, 220, 221, 222, 223, 224, 225, 1032, 227, 228, - 229, 230, 0, 231, 232, 233, 234, 235, 236, 0, - 237, 1033, 239, 240, 241, 242, 243, 244, 854, 855, - 0, 856, 0, 248, 1034, 1035, 251, 1036, 253, 254, - 255, 256, 257, 258, 0, 0, 259, 1037, 261, 1038, - 0, 263, 264, 265, 857, 858, 266, 267, 268, 269, - 270, 1039, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 859, 1040, 860, 293, 294, 295, 296, 861, 297, 298, - 1041, 300, 862, 863, 302, 864, 304, 305, 306, 0, - 307, 308, 0, 0, 865, 310, 311, 0, 0, 312, - 313, 1042, 315, 1043, 866, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 0, 328, 329, 867, 331, - 332, 333, 334, 335, 336, 0, 337, 338, 339, 340, - 341, 342, 0, 343, 344, 345, 868, 347, 348, 349, - 350, 0, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 0, 364, 365, 1044, 367, - 368, 369, 869, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 0, 382, 383, 384, 385, 386, - 870, 387, 388, 389, 390, 391, 1045, 393, 394, 871, - 396, 0, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 1046, 410, 872, 412, 0, 413, - 414, 0, 415, 1047, 417, 418, 419, 420, 421, 0, - 873, 874, 0, 0, 424, 425, 875, 427, 876, 877, - 429, 430, 1048, 432, 433, 434, 435, 436, 0, 0, - 437, 438, 439, 440, 441, 879, 0, 442, 443, 444, - 445, 446, 447, 880, 0, 449, 1050, 451, 452, 453, - 454, 455, 0, 0, 456, 0, 0, 457, 458, 459, - 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 881, 0, - 0, 0, 0, 0, 0, 882, 883, 0, 0, 0, - 0, 0, 885, 0, 886, 1921, 0, 0, 0, 887, - 0, 888, 889, 93, 822, 550, 823, 824, 825, 826, - 827, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, - 103, 104, 0, 0, 0, 0, 828, 0, 0, 105, - 106, 0, 107, 108, 109, 110, 111, 112, 113, 114, - 829, 116, 830, 831, 0, 119, 120, 121, 122, 123, - 124, 832, 833, 125, 126, 834, 835, 129, 0, 130, - 131, 132, 133, 836, 0, 837, 0, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, 152, 153, 154, 155, 838, - 839, 840, 841, 842, 843, 844, 157, 158, 159, 160, - 161, 162, 163, 845, 846, 166, 847, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 681, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 848, 195, 196, 197, 198, 199, 849, 850, 201, - 0, 202, 203, 851, 205, 0, 206, 0, 207, 208, - 1662, 209, 210, 211, 212, 213, 214, 0, 215, 0, - 852, 853, 218, 0, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 238, 239, 240, 241, 242, - 243, 244, 854, 855, 0, 856, 0, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 0, 0, - 259, 260, 261, 262, 0, 263, 264, 265, 857, 858, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 478, 479, 480, 481, 482, 483, 942, 0, 0, 0, + 0, 0, 0, 943, 944, 2802, 0, 0, 0, 0, + 946, 0, 2803, 0, 0, 0, 0, 948, 0, 949, + 950, 93, 883, 582, 884, 885, 886, 887, 888, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, + 104, 0, 0, 0, 0, 889, 0, 0, 105, 106, + 0, 107, 108, 109, 110, 111, 112, 113, 114, 890, + 116, 891, 892, 0, 119, 120, 121, 122, 123, 124, + 893, 894, 125, 126, 895, 896, 129, 0, 130, 131, + 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, + 149, 150, 151, 0, 152, 153, 154, 155, 899, 900, + 901, 902, 903, 904, 905, 161, 162, 163, 164, 165, + 166, 167, 906, 907, 170, 908, 171, 0, 172, 173, + 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, + 0, 0, 183, 184, 712, 186, 187, 0, 188, 189, + 190, 0, 191, 192, 193, 0, 194, 195, 196, 197, + 909, 199, 200, 201, 202, 203, 910, 911, 205, 0, + 206, 207, 912, 209, 0, 210, 0, 211, 212, 0, + 213, 214, 215, 216, 217, 218, 0, 219, 0, 913, + 914, 222, 0, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 0, 235, 236, 237, 238, + 239, 240, 0, 241, 242, 243, 244, 245, 246, 247, + 248, 915, 916, 0, 917, 0, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 0, 0, 263, + 264, 265, 266, 0, 267, 268, 269, 918, 919, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 920, 295, 921, 297, 298, 299, 300, + 922, 301, 302, 303, 304, 923, 924, 306, 925, 308, + 309, 310, 0, 311, 312, 0, 0, 926, 314, 315, + 0, 0, 316, 317, 318, 319, 320, 927, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 0, 332, + 333, 928, 335, 336, 337, 338, 339, 340, 0, 341, + 342, 343, 344, 345, 346, 0, 347, 348, 349, 929, + 351, 352, 353, 354, 0, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 0, 368, + 369, 370, 371, 372, 373, 930, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 0, 386, 387, + 388, 389, 390, 931, 392, 393, 394, 395, 396, 397, + 398, 399, 932, 401, 0, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 933, + 417, 0, 418, 419, 0, 420, 421, 422, 423, 424, + 425, 426, 0, 934, 935, 0, 0, 429, 430, 936, + 432, 937, 938, 434, 435, 939, 437, 438, 439, 440, + 441, 0, 0, 442, 443, 444, 445, 446, 940, 0, + 448, 449, 450, 451, 452, 453, 941, 0, 455, 456, + 457, 458, 459, 460, 461, 0, 0, 462, 0, 0, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 483, 942, 0, 0, 0, 0, 0, 0, 943, 944, + 945, 0, 0, 0, 0, 946, 0, 947, 0, 0, + 0, 0, 948, 0, 949, 950, 93, 1477, 582, 884, + 885, 886, 1478, 888, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, + 100, 101, 1479, 102, 103, 104, 0, 0, 0, 0, + 889, 0, 0, 105, 106, 0, 107, 108, 109, 110, + 111, 112, 113, 114, 890, 116, 891, 892, 0, 119, + 120, 121, 122, 123, 124, 893, 894, 125, 126, 895, + 896, 129, 0, 130, 131, 132, 133, 897, 0, 898, + 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 0, 146, 147, 148, 149, 150, 151, 0, 152, + 153, 154, 155, 899, 900, 901, 902, 903, 904, 905, + 161, 162, 163, 164, 165, 166, 167, 906, 907, 170, + 908, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 712, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 909, 199, 200, 201, 202, + 203, 910, 911, 205, 0, 206, 207, 912, 209, 0, + 210, 0, 211, 212, 0, 213, 214, 215, 216, 217, + 218, 0, 219, 0, 913, 914, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 242, + 243, 244, 245, 246, 247, 248, 915, 916, 0, 917, + 0, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 0, 0, 263, 264, 265, 266, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 859, 291, 860, 293, 294, 295, - 296, 861, 297, 298, 299, 300, 862, 863, 302, 864, - 304, 305, 306, 0, 307, 308, 0, 0, 865, 310, - 311, 0, 0, 312, 313, 314, 315, 316, 866, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 867, 331, 332, 333, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 868, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 366, 367, 368, 369, 869, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 0, 382, - 383, 384, 385, 386, 870, 387, 388, 389, 390, 391, - 392, 393, 394, 871, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 872, 412, 0, 413, 414, 0, 415, 416, 417, 418, - 419, 420, 421, 0, 873, 874, 0, 0, 424, 425, - 875, 427, 876, 877, 429, 430, 878, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 879, - 0, 442, 443, 444, 445, 446, 447, 880, 0, 449, - 450, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 0, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 881, 0, 0, 0, 0, 0, 0, 882, - 883, 0, 0, 0, 0, 0, 885, 0, 886, 0, - 0, 0, 0, 887, 0, 888, 889, 93, 822, 550, - 823, 824, 825, 826, 827, 0, 0, 0, 0, 0, + 286, 287, 288, 289, 290, 291, 292, 293, 920, 295, + 921, 297, 298, 299, 300, 922, 301, 302, 303, 304, + 923, 924, 306, 925, 308, 309, 310, 0, 311, 312, + 0, 0, 926, 314, 315, 0, 0, 316, 317, 318, + 319, 320, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 929, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 370, 371, 372, 373, + 930, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 0, 386, 387, 388, 389, 390, 931, 392, + 393, 394, 395, 396, 397, 398, 399, 932, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 933, 417, 0, 418, 419, 0, + 420, 421, 422, 423, 424, 425, 426, 0, 934, 935, + 0, 0, 429, 430, 936, 432, 937, 938, 434, 435, + 939, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 940, 0, 448, 449, 450, 451, 452, + 453, 941, 0, 455, 456, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 483, 942, 0, 0, 0, + 0, 0, 0, 943, 944, 0, 0, 0, 0, 0, + 946, 0, 947, 0, 0, 0, 0, 948, 0, 949, + 950, 93, 883, 582, 884, 885, 886, 887, 888, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, + 104, 0, 0, 0, 0, 889, 0, 0, 105, 106, + 0, 107, 108, 109, 110, 111, 112, 113, 114, 890, + 116, 891, 892, 0, 119, 120, 121, 122, 123, 124, + 893, 894, 125, 126, 895, 896, 129, 0, 130, 131, + 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, + 149, 150, 151, 0, 152, 153, 154, 155, 899, 900, + 901, 902, 903, 904, 905, 161, 162, 163, 164, 165, + 166, 167, 906, 907, 170, 908, 171, 0, 172, 173, + 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, + 0, 0, 183, 184, 712, 186, 187, 0, 188, 189, + 190, 0, 191, 192, 193, 0, 194, 195, 196, 197, + 909, 199, 200, 201, 202, 203, 910, 911, 205, 0, + 206, 207, 912, 209, 0, 210, 0, 211, 212, 0, + 213, 214, 215, 216, 217, 218, 0, 219, 0, 913, + 914, 222, 0, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 0, 235, 236, 237, 238, + 239, 240, 0, 241, 242, 243, 244, 245, 246, 247, + 248, 915, 916, 0, 917, 0, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 0, 0, 263, + 264, 265, 266, 0, 267, 268, 269, 918, 919, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 920, 295, 921, 297, 298, 299, 300, + 922, 301, 302, 303, 304, 923, 924, 306, 925, 308, + 309, 310, 0, 311, 312, 0, 0, 926, 314, 315, + 0, 0, 316, 317, 318, 319, 320, 927, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 0, 332, + 333, 928, 335, 336, 337, 338, 339, 340, 0, 341, + 342, 343, 344, 345, 346, 0, 347, 348, 349, 929, + 351, 352, 353, 354, 0, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 0, 368, + 369, 370, 371, 372, 373, 930, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 0, 386, 387, + 388, 389, 390, 931, 392, 393, 394, 395, 396, 397, + 398, 399, 932, 401, 0, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 933, + 417, 0, 418, 419, 0, 420, 421, 422, 423, 424, + 425, 426, 0, 934, 935, 0, 0, 429, 430, 936, + 432, 937, 938, 434, 435, 939, 437, 438, 439, 440, + 441, 0, 0, 442, 443, 444, 445, 446, 940, 0, + 448, 449, 450, 451, 452, 453, 941, 0, 455, 456, + 457, 458, 459, 460, 461, 0, 0, 462, 0, 0, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 483, 942, 0, 0, 0, 0, 0, 0, 943, 944, + 0, 0, 0, 0, 0, 946, 0, 947, 1716, 0, + 0, 0, 948, 0, 949, 950, 1080, 883, 582, 884, + 885, 886, 887, 888, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, + 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, + 889, 0, 0, 105, 106, 0, 107, 108, 109, 1082, + 111, 112, 113, 114, 890, 1083, 891, 892, 0, 119, + 120, 121, 122, 123, 124, 893, 894, 125, 126, 895, + 896, 129, 0, 130, 131, 132, 133, 897, 0, 1084, + 0, 136, 137, 138, 139, 140, 141, 1085, 143, 144, + 145, 0, 146, 147, 148, 149, 150, 151, 0, 1086, + 153, 154, 155, 1087, 1088, 1089, 1090, 903, 904, 1091, + 161, 162, 163, 164, 165, 166, 167, 906, 907, 170, + 908, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 712, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 909, 199, 200, 201, 202, + 203, 910, 911, 205, 0, 206, 207, 912, 209, 0, + 210, 0, 211, 1093, 0, 1094, 214, 215, 1095, 1096, + 218, 0, 219, 0, 913, 914, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 1097, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 1098, + 243, 244, 245, 246, 247, 248, 915, 916, 0, 917, + 0, 252, 1099, 1100, 255, 1101, 257, 258, 259, 260, + 261, 262, 0, 0, 263, 1102, 265, 1103, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 1104, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 920, 1105, + 921, 297, 298, 299, 300, 922, 301, 302, 1106, 304, + 923, 924, 306, 925, 308, 309, 310, 0, 311, 312, + 0, 0, 926, 314, 315, 0, 0, 316, 317, 1107, + 319, 1108, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 929, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 1109, 371, 372, 373, + 930, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 0, 386, 387, 388, 389, 390, 1110, 392, + 393, 394, 395, 396, 1111, 398, 399, 932, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 1112, 415, 933, 417, 0, 418, 419, 0, + 420, 1113, 422, 423, 424, 425, 426, 0, 934, 935, + 0, 0, 429, 430, 936, 432, 937, 938, 434, 435, + 1114, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 1115, 0, 448, 449, 450, 451, 452, + 453, 941, 1942, 455, 1117, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 483, 942, 0, 0, 0, + 0, 0, 0, 943, 944, 0, 0, 0, 0, 0, + 946, 0, 947, 0, 0, 0, 0, 948, 0, 949, + 950, 1080, 883, 582, 884, 885, 886, 887, 888, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, + 104, 0, 0, 0, 0, 889, 0, 0, 105, 106, + 0, 107, 108, 109, 1082, 111, 112, 113, 114, 890, + 1083, 891, 892, 0, 119, 120, 121, 122, 123, 124, + 893, 894, 125, 126, 895, 896, 129, 0, 130, 131, + 132, 133, 897, 0, 1084, 0, 136, 137, 138, 139, + 140, 141, 1085, 143, 144, 145, 0, 146, 147, 148, + 149, 150, 151, 0, 1086, 153, 154, 155, 1087, 1088, + 1089, 1090, 903, 904, 1091, 161, 162, 163, 164, 165, + 166, 167, 906, 907, 170, 908, 171, 0, 172, 173, + 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, + 0, 0, 183, 184, 712, 186, 187, 0, 188, 189, + 190, 0, 191, 192, 193, 0, 194, 195, 196, 197, + 909, 199, 200, 201, 202, 203, 910, 911, 205, 0, + 206, 207, 912, 209, 0, 210, 0, 211, 1093, 0, + 1094, 214, 215, 1095, 1096, 218, 0, 219, 0, 913, + 914, 222, 0, 223, 224, 225, 226, 227, 228, 229, + 1097, 231, 232, 233, 234, 0, 235, 236, 237, 238, + 239, 240, 0, 241, 1098, 243, 244, 245, 246, 247, + 248, 915, 916, 0, 917, 0, 252, 1099, 1100, 255, + 1101, 257, 258, 259, 260, 261, 262, 0, 0, 263, + 1102, 265, 1103, 0, 267, 268, 269, 918, 919, 270, + 271, 272, 273, 274, 1104, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 920, 1105, 921, 297, 298, 299, 300, + 922, 301, 302, 1106, 304, 923, 924, 306, 925, 308, + 309, 310, 0, 311, 312, 0, 0, 926, 314, 315, + 0, 0, 316, 317, 1107, 319, 1108, 927, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 0, 332, + 333, 928, 335, 336, 337, 338, 339, 340, 0, 341, + 342, 343, 344, 345, 346, 0, 347, 348, 349, 929, + 351, 352, 353, 354, 0, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 0, 368, + 369, 1109, 371, 372, 373, 930, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 0, 386, 387, + 388, 389, 390, 1110, 392, 393, 394, 395, 396, 1111, + 398, 399, 932, 401, 0, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 1112, 415, 933, + 417, 0, 418, 419, 0, 420, 1113, 422, 423, 424, + 425, 426, 0, 934, 935, 0, 0, 429, 430, 936, + 432, 937, 938, 434, 435, 1114, 437, 438, 439, 440, + 441, 0, 0, 442, 443, 444, 445, 446, 1115, 0, + 448, 449, 450, 451, 452, 453, 941, 0, 455, 1117, + 457, 458, 459, 460, 461, 0, 0, 462, 0, 0, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 483, 942, 0, 0, 0, 0, 0, 0, 943, 944, + 0, 0, 0, 0, 0, 946, 0, 947, 1985, 0, + 0, 0, 948, 0, 949, 950, 93, 883, 582, 884, + 885, 886, 887, 888, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, - 828, 0, 0, 105, 106, 0, 107, 108, 109, 110, - 111, 112, 113, 114, 829, 116, 830, 831, 0, 119, - 120, 121, 122, 123, 124, 832, 833, 125, 126, 834, - 835, 129, 0, 130, 131, 132, 133, 836, 0, 837, + 889, 0, 0, 105, 106, 0, 107, 108, 109, 110, + 111, 112, 113, 114, 890, 116, 891, 892, 0, 119, + 120, 121, 122, 123, 124, 893, 894, 125, 126, 895, + 896, 129, 0, 130, 131, 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 152, - 153, 154, 155, 838, 839, 840, 841, 842, 843, 844, - 157, 158, 159, 160, 161, 162, 163, 845, 846, 166, - 847, 167, 0, 168, 169, 170, 171, 172, 173, 0, - 174, 175, 176, 177, 178, 0, 0, 179, 180, 681, - 182, 183, 0, 184, 185, 186, 0, 187, 188, 189, - 0, 190, 191, 192, 193, 848, 195, 196, 197, 198, - 199, 849, 850, 201, 0, 202, 203, 851, 205, 0, - 206, 0, 207, 208, 0, 209, 210, 211, 212, 213, - 214, 0, 215, 0, 852, 853, 218, 0, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 0, 231, 232, 233, 234, 235, 236, 0, 237, 238, - 239, 240, 241, 242, 243, 244, 854, 855, 0, 856, - 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 0, 0, 259, 260, 261, 262, 0, 263, - 264, 265, 857, 858, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 859, 291, - 860, 293, 294, 295, 296, 861, 297, 298, 299, 300, - 862, 863, 302, 864, 304, 305, 306, 0, 307, 308, - 0, 0, 865, 310, 311, 0, 0, 312, 313, 314, - 315, 316, 866, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 0, 328, 329, 867, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 339, 340, 341, 342, - 0, 343, 344, 345, 868, 347, 348, 349, 350, 0, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 0, 364, 365, 366, 367, 368, 369, - 869, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 0, 382, 383, 384, 385, 386, 870, 387, - 388, 389, 390, 391, 392, 393, 394, 871, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 872, 412, 0, 413, 414, 2235, - 415, 416, 417, 418, 419, 420, 421, 0, 873, 874, - 0, 0, 424, 425, 875, 427, 876, 877, 429, 430, - 878, 432, 433, 434, 435, 436, 0, 0, 437, 438, - 439, 440, 441, 879, 0, 442, 443, 444, 445, 446, - 447, 880, 0, 449, 450, 451, 452, 453, 454, 455, - 0, 0, 456, 0, 0, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 881, 0, 0, 0, - 0, 0, 0, 882, 883, 0, 0, 0, 0, 0, - 885, 0, 886, 0, 0, 0, 0, 887, 0, 888, - 889, 93, 822, 550, 823, 824, 825, 826, 827, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, - 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, - 0, 0, 0, 0, 828, 0, 0, 105, 106, 0, - 107, 108, 109, 110, 111, 112, 113, 114, 829, 116, - 830, 831, 0, 119, 120, 121, 122, 123, 124, 832, - 833, 125, 126, 834, 835, 129, 0, 130, 131, 132, - 133, 836, 0, 837, 0, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, - 150, 151, 0, 152, 153, 154, 155, 838, 839, 840, - 841, 842, 843, 844, 157, 158, 159, 160, 161, 162, - 163, 845, 846, 166, 847, 167, 0, 168, 169, 170, - 171, 172, 173, 0, 174, 175, 176, 177, 178, 0, - 0, 179, 180, 681, 182, 183, 0, 184, 185, 186, - 0, 187, 188, 189, 0, 190, 191, 192, 193, 848, - 195, 196, 197, 198, 199, 849, 850, 201, 0, 202, - 203, 851, 205, 0, 206, 0, 207, 208, 0, 209, - 210, 211, 212, 213, 214, 0, 215, 0, 852, 853, - 218, 0, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 0, 231, 232, 233, 234, 235, - 236, 0, 237, 238, 239, 240, 241, 242, 243, 244, - 854, 855, 0, 856, 0, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 0, 0, 259, 260, - 261, 262, 0, 263, 264, 265, 857, 858, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 859, 291, 860, 293, 294, 295, 296, 861, - 297, 298, 299, 300, 862, 863, 302, 864, 304, 305, - 306, 0, 307, 308, 0, 0, 865, 310, 311, 0, - 0, 312, 313, 314, 315, 316, 866, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 0, 328, 329, - 867, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 339, 340, 341, 342, 0, 343, 344, 345, 868, 347, - 348, 349, 350, 0, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 0, 364, 365, - 366, 367, 368, 369, 869, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 0, 382, 383, 384, - 385, 386, 870, 387, 388, 389, 390, 391, 392, 393, - 394, 871, 396, 0, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 872, 412, - 0, 413, 414, 0, 415, 416, 417, 418, 419, 420, - 421, 0, 873, 874, 0, 0, 424, 425, 875, 427, - 876, 877, 429, 430, 878, 432, 433, 434, 435, 436, - 0, 0, 437, 438, 439, 440, 441, 879, 0, 442, - 443, 444, 445, 446, 447, 880, 0, 449, 450, 451, - 452, 453, 454, 455, 0, 0, 456, 0, 0, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 881, 0, 0, 0, 0, 0, 0, 882, 883, 0, - 0, 0, 0, 0, 885, 0, 886, 0, 0, 0, - 0, 887, 0, 888, 889, 1019, 822, 550, 823, 824, - 825, 826, 827, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, - 0, 102, 103, 104, 0, 0, 0, 0, 828, 0, - 0, 105, 106, 0, 107, 108, 109, 1021, 111, 112, - 113, 114, 829, 1022, 830, 831, 0, 119, 120, 121, - 122, 123, 124, 832, 833, 125, 126, 834, 835, 129, - 0, 130, 131, 132, 133, 836, 0, 1023, 0, 136, - 137, 138, 139, 140, 141, 1024, 143, 144, 145, 0, - 146, 147, 148, 149, 150, 151, 0, 1025, 153, 154, - 155, 838, 839, 840, 1026, 842, 843, 844, 157, 158, - 159, 160, 161, 162, 163, 845, 846, 166, 847, 167, - 0, 168, 169, 170, 171, 172, 173, 0, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 681, 182, 183, - 0, 184, 185, 186, 0, 187, 188, 189, 0, 190, - 191, 192, 193, 848, 195, 196, 197, 198, 199, 849, - 850, 201, 0, 202, 203, 851, 205, 0, 206, 0, - 207, 1028, 0, 1029, 210, 211, 1030, 1031, 214, 0, - 215, 0, 852, 853, 218, 0, 219, 220, 221, 222, - 223, 224, 225, 1032, 227, 228, 229, 230, 0, 231, - 232, 233, 234, 235, 236, 0, 237, 1033, 239, 240, - 241, 242, 243, 244, 854, 855, 0, 856, 0, 248, - 1034, 1035, 251, 1036, 253, 254, 255, 256, 257, 258, - 0, 0, 259, 1037, 261, 1038, 0, 263, 264, 265, - 857, 858, 266, 267, 268, 269, 270, 1039, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 859, 1040, 860, 293, - 294, 295, 296, 861, 297, 298, 1041, 300, 862, 863, - 302, 864, 304, 305, 306, 0, 307, 308, 0, 0, - 865, 310, 311, 0, 0, 312, 313, 1042, 315, 1043, - 866, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 0, 328, 329, 867, 331, 332, 333, 334, 335, - 336, 0, 337, 338, 339, 340, 341, 342, 0, 343, - 344, 345, 868, 347, 348, 349, 350, 0, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 0, 364, 365, 1044, 367, 368, 369, 869, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 0, 382, 383, 384, 385, 386, 870, 387, 388, 389, - 390, 391, 1045, 393, 394, 871, 396, 0, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 1046, 410, 872, 412, 0, 413, 414, 0, 415, 1047, - 417, 418, 419, 420, 421, 0, 873, 874, 0, 0, - 424, 425, 875, 427, 876, 877, 429, 430, 1048, 432, - 433, 434, 435, 436, 0, 0, 437, 438, 439, 440, - 441, 879, 0, 442, 443, 444, 445, 446, 447, 880, - 0, 449, 1050, 451, 452, 453, 454, 455, 0, 0, - 456, 0, 0, 457, 458, 459, 460, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 881, 0, 0, 0, 0, 0, - 0, 882, 883, 0, 0, 0, 0, 0, 885, 0, - 886, 0, 0, 0, 0, 887, 0, 888, 889, 93, - 822, 550, 823, 824, 825, 826, 827, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, - 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, - 0, 0, 828, 0, 0, 105, 106, 0, 107, 108, - 109, 110, 111, 112, 113, 114, 829, 116, 830, 831, - 0, 119, 120, 121, 122, 123, 124, 832, 833, 125, - 126, 834, 835, 129, 0, 130, 131, 132, 133, 836, - 0, 837, 0, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, - 0, 152, 153, 154, 155, 838, 839, 840, 841, 842, - 843, 844, 157, 158, 159, 160, 161, 162, 163, 845, - 846, 166, 847, 167, 0, 168, 169, 170, 171, 172, - 173, 0, 174, 175, 176, 177, 178, 0, 0, 179, - 180, 681, 182, 183, 0, 184, 185, 186, 0, 187, - 188, 189, 0, 190, 191, 192, 193, 848, 195, 196, - 197, 198, 199, 849, 850, 201, 0, 202, 203, 851, - 205, 0, 206, 0, 207, 208, 0, 209, 210, 211, - 212, 213, 214, 0, 215, 0, 852, 853, 218, 0, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 0, 231, 232, 233, 234, 235, 236, 0, - 237, 238, 239, 240, 241, 242, 243, 244, 854, 855, - 0, 856, 0, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 0, 0, 259, 260, 261, 262, - 0, 263, 264, 265, 857, 858, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 859, 291, 860, 293, 294, 295, 296, 861, 297, 298, - 299, 300, 862, 863, 302, 864, 304, 305, 306, 0, - 307, 308, 0, 0, 865, 310, 311, 0, 0, 312, - 313, 314, 315, 316, 866, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 0, 328, 329, 867, 331, - 332, 333, 334, 335, 336, 0, 337, 338, 339, 340, - 341, 342, 0, 343, 344, 345, 868, 347, 348, 349, - 350, 0, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 0, 364, 365, 366, 367, - 368, 369, 869, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 0, 382, 383, 384, 385, 386, - 870, 387, 388, 389, 390, 391, 392, 393, 394, 871, - 396, 0, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 872, 412, 0, 413, - 414, 0, 415, 416, 417, 418, 419, 420, 421, 0, - 873, 874, 0, 0, 424, 425, 875, 427, 876, 877, - 429, 430, 878, 432, 433, 434, 435, 436, 0, 0, - 437, 438, 439, 440, 441, 879, 0, 442, 443, 444, - 445, 446, 447, 880, 0, 449, 450, 451, 452, 453, - 454, 455, 0, 0, 456, 0, 0, 457, 458, 459, - 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 881, 0, - 0, 0, 0, 0, 0, 1419, 1420, 0, 0, 0, - 0, 0, 885, 0, 886, 0, 0, 0, 0, 887, - 0, 888, 889, 93, 1801, 550, 823, 824, 825, 826, - 827, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, - 103, 104, 0, 0, 0, 0, 828, 0, 0, 105, - 106, 0, 107, 108, 109, 110, 111, 112, 113, 114, - 829, 116, 830, 831, 0, 119, 120, 121, 122, 123, - 124, 832, 833, 125, 126, 834, 835, 129, 0, 130, - 131, 132, 133, 836, 0, 837, 0, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, 152, 153, 154, 155, 838, - 839, 840, 841, 842, 843, 844, 157, 158, 159, 160, - 161, 162, 163, 845, 846, 166, 847, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 681, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 848, 195, 196, 197, 198, 199, 849, 850, 201, - 0, 202, 203, 851, 205, 0, 206, 0, 207, 208, - 0, 209, 210, 211, 212, 213, 214, 0, 215, 0, - 852, 853, 218, 0, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 238, 239, 240, 241, 242, - 243, 244, 854, 855, 0, 856, 0, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 0, 0, - 259, 260, 261, 262, 0, 263, 264, 265, 857, 858, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 153, 154, 155, 899, 900, 901, 902, 903, 904, 905, + 161, 162, 163, 164, 165, 166, 167, 906, 907, 170, + 908, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 712, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 909, 199, 200, 201, 202, + 203, 910, 911, 205, 0, 206, 207, 912, 209, 0, + 210, 0, 211, 212, 1723, 213, 214, 215, 216, 217, + 218, 0, 219, 0, 913, 914, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 242, + 243, 244, 245, 246, 247, 248, 915, 916, 0, 917, + 0, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 0, 0, 263, 264, 265, 266, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 859, 291, 860, 293, 294, 295, - 296, 861, 297, 298, 299, 300, 862, 863, 302, 864, - 304, 305, 306, 0, 307, 308, 0, 0, 865, 310, - 311, 0, 0, 312, 313, 314, 315, 316, 866, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 867, 331, 332, 333, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 868, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 366, 367, 368, 369, 869, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 0, 382, - 383, 384, 385, 386, 870, 387, 388, 389, 390, 391, - 392, 393, 394, 871, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 872, 412, 0, 413, 414, 0, 415, 416, 417, 418, - 419, 420, 421, 0, 873, 874, 0, 0, 424, 425, - 875, 427, 876, 877, 429, 430, 878, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 879, - 0, 442, 443, 444, 445, 446, 447, 880, 0, 449, - 450, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 0, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 881, 0, 0, 0, 0, 0, 0, 882, - 883, 0, 0, 0, 0, 0, 885, 0, 886, 0, - 0, 0, 0, 887, 0, 888, 889, 93, 822, 550, - 823, 824, 825, 826, 827, 0, 0, 0, 0, 0, + 286, 287, 288, 289, 290, 291, 292, 293, 920, 295, + 921, 297, 298, 299, 300, 922, 301, 302, 303, 304, + 923, 924, 306, 925, 308, 309, 310, 0, 311, 312, + 0, 0, 926, 314, 315, 0, 0, 316, 317, 318, + 319, 320, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 929, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 370, 371, 372, 373, + 930, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 0, 386, 387, 388, 389, 390, 931, 392, + 393, 394, 395, 396, 397, 398, 399, 932, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 933, 417, 0, 418, 419, 0, + 420, 421, 422, 423, 424, 425, 426, 0, 934, 935, + 0, 0, 429, 430, 936, 432, 937, 938, 434, 435, + 939, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 940, 0, 448, 449, 450, 451, 452, + 453, 941, 0, 455, 456, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 483, 942, 0, 0, 0, + 0, 0, 0, 943, 944, 0, 0, 0, 0, 0, + 946, 0, 947, 0, 0, 0, 0, 948, 0, 949, + 950, 93, 883, 582, 884, 885, 886, 887, 888, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, + 104, 0, 0, 0, 0, 889, 0, 0, 105, 106, + 0, 107, 108, 109, 110, 111, 112, 113, 114, 890, + 116, 891, 892, 0, 119, 120, 121, 122, 123, 124, + 893, 894, 125, 126, 895, 896, 129, 0, 130, 131, + 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, + 149, 150, 151, 0, 152, 153, 154, 155, 899, 900, + 901, 902, 903, 904, 905, 161, 162, 163, 164, 165, + 166, 167, 906, 907, 170, 908, 171, 0, 172, 173, + 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, + 0, 0, 183, 184, 712, 186, 187, 0, 188, 189, + 190, 0, 191, 192, 193, 0, 194, 195, 196, 197, + 909, 199, 200, 201, 202, 203, 910, 911, 205, 0, + 206, 207, 912, 209, 0, 210, 0, 211, 212, 0, + 213, 214, 215, 216, 217, 218, 0, 219, 0, 913, + 914, 222, 0, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 0, 235, 236, 237, 238, + 239, 240, 0, 241, 242, 243, 244, 245, 246, 247, + 248, 915, 916, 0, 917, 0, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 0, 0, 263, + 264, 265, 266, 0, 267, 268, 269, 918, 919, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 920, 295, 921, 297, 298, 299, 300, + 922, 301, 302, 303, 304, 923, 924, 306, 925, 308, + 309, 310, 0, 311, 312, 0, 0, 926, 314, 315, + 0, 0, 316, 317, 318, 319, 320, 927, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 0, 332, + 333, 928, 335, 336, 337, 338, 339, 340, 0, 341, + 342, 343, 344, 345, 346, 0, 347, 348, 349, 929, + 351, 352, 353, 354, 0, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 0, 368, + 369, 370, 371, 372, 373, 930, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 0, 386, 387, + 388, 389, 390, 931, 392, 393, 394, 395, 396, 397, + 398, 399, 932, 401, 0, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 933, + 417, 0, 418, 419, 2293, 420, 421, 422, 423, 424, + 425, 426, 0, 934, 935, 0, 0, 429, 430, 936, + 432, 937, 938, 434, 435, 939, 437, 438, 439, 440, + 441, 0, 0, 442, 443, 444, 445, 446, 940, 0, + 448, 449, 450, 451, 452, 453, 941, 0, 455, 456, + 457, 458, 459, 460, 461, 0, 0, 462, 0, 0, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 483, 942, 0, 0, 0, 0, 0, 0, 943, 944, + 0, 0, 0, 0, 0, 946, 0, 947, 0, 0, + 0, 0, 948, 0, 949, 950, 93, 883, 582, 884, + 885, 886, 887, 888, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, - 828, 0, 0, 105, 106, 0, 107, 108, 109, 110, - 111, 112, 113, 114, 829, 116, 830, 831, 0, 119, - 120, 121, 122, 123, 124, 832, 833, 125, 126, 834, - 835, 129, 0, 130, 131, 132, 133, 836, 0, 837, + 889, 0, 0, 105, 106, 0, 107, 108, 109, 110, + 111, 112, 113, 114, 890, 116, 891, 892, 0, 119, + 120, 121, 122, 123, 124, 893, 894, 125, 126, 895, + 896, 129, 0, 130, 131, 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 152, - 153, 154, 155, 838, 839, 840, 841, 842, 843, 844, - 157, 158, 159, 160, 161, 162, 163, 845, 846, 166, - 847, 167, 0, 168, 169, 170, 171, 172, 173, 0, - 174, 175, 176, 177, 178, 0, 0, 179, 180, 681, - 182, 183, 0, 184, 185, 186, 0, 187, 188, 189, - 0, 190, 191, 192, 193, 848, 195, 196, 197, 198, - 199, 849, 850, 201, 0, 202, 203, 851, 205, 0, - 206, 0, 207, 208, 0, 209, 210, 211, 212, 213, - 214, 0, 215, 0, 852, 853, 218, 0, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 0, 231, 232, 233, 234, 235, 236, 0, 237, 238, - 239, 240, 241, 242, 243, 244, 854, 855, 0, 856, - 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 0, 0, 259, 260, 261, 262, 0, 263, - 264, 265, 857, 858, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 859, 291, - 860, 293, 294, 295, 296, 861, 297, 298, 299, 300, - 862, 863, 302, 864, 304, 305, 306, 0, 307, 308, - 0, 0, 865, 310, 311, 0, 0, 312, 313, 314, - 315, 316, 866, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 0, 328, 329, 867, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 339, 340, 341, 342, - 0, 343, 344, 345, 868, 347, 348, 349, 350, 0, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 0, 364, 365, 366, 367, 368, 369, - 869, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 0, 382, 383, 384, 385, 386, 870, 387, - 388, 389, 390, 391, 392, 393, 394, 871, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 872, 412, 0, 413, 414, 0, - 415, 416, 417, 418, 419, 420, 421, 0, 873, 874, - 0, 0, 424, 425, 875, 427, 876, 877, 429, 430, - 878, 432, 433, 434, 435, 436, 0, 0, 437, 438, - 439, 440, 441, 879, 0, 442, 443, 444, 445, 446, - 447, 880, 0, 449, 450, 451, 452, 453, 454, 455, - 0, 0, 456, 0, 0, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 881, 0, 0, 0, - 0, 0, 0, 882, 883, 0, 0, 0, 0, 0, - 885, 0, 2037, 0, 0, 0, 0, 887, 0, 888, - 889, 93, 822, 550, 823, 824, 825, 826, 827, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, - 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, - 0, 0, 0, 0, 828, 0, 0, 105, 106, 0, - 107, 108, 109, 110, 111, 112, 113, 114, 829, 116, - 830, 831, 0, 119, 120, 121, 122, 123, 124, 832, - 833, 125, 126, 834, 835, 129, 0, 130, 131, 132, - 133, 836, 0, 837, 0, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, - 150, 151, 0, 152, 153, 2738, 155, 838, 839, 840, - 841, 842, 843, 844, 157, 158, 159, 160, 161, 162, - 163, 845, 846, 166, 847, 167, 0, 168, 169, 170, - 171, 172, 173, 0, 174, 175, 176, 177, 178, 0, - 0, 179, 180, 681, 182, 183, 0, 184, 185, 186, - 0, 187, 188, 189, 0, 190, 191, 192, 193, 848, - 195, 196, 197, 198, 199, 849, 850, 201, 0, 202, - 203, 851, 205, 0, 206, 0, 207, 208, 0, 209, - 210, 211, 212, 213, 214, 0, 215, 0, 2739, 853, - 218, 0, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 0, 231, 232, 233, 234, 235, - 236, 0, 237, 238, 239, 240, 241, 242, 243, 244, - 854, 855, 0, 856, 0, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 0, 0, 259, 260, - 261, 262, 0, 263, 264, 265, 857, 858, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 859, 291, 860, 293, 294, 295, 296, 861, - 297, 298, 299, 300, 862, 863, 302, 864, 304, 305, - 306, 0, 307, 308, 0, 0, 865, 310, 311, 0, - 0, 312, 313, 314, 315, 316, 866, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 0, 328, 329, - 867, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 339, 340, 341, 342, 0, 343, 344, 345, 868, 347, - 348, 349, 350, 0, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 0, 364, 365, - 366, 367, 368, 2740, 869, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 0, 382, 383, 384, - 385, 386, 870, 387, 388, 389, 390, 391, 392, 393, - 394, 871, 396, 0, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 872, 412, - 0, 413, 414, 0, 415, 416, 417, 418, 419, 420, - 421, 0, 873, 874, 0, 0, 424, 425, 875, 427, - 876, 877, 429, 430, 878, 432, 433, 434, 435, 436, - 0, 0, 437, 438, 439, 440, 441, 879, 0, 442, - 443, 444, 445, 446, 447, 880, 0, 449, 450, 451, - 452, 453, 454, 455, 0, 0, 456, 0, 0, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, + 153, 154, 155, 899, 900, 901, 902, 903, 904, 905, + 161, 162, 163, 164, 165, 166, 167, 906, 907, 170, + 908, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 712, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 909, 199, 200, 201, 202, + 203, 910, 911, 205, 0, 206, 207, 912, 209, 0, + 210, 0, 211, 212, 0, 213, 214, 215, 216, 217, + 218, 0, 219, 0, 913, 914, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 242, + 243, 244, 245, 246, 247, 248, 915, 916, 0, 917, + 0, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 0, 0, 263, 264, 265, 266, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 920, 295, + 921, 297, 298, 299, 300, 922, 301, 302, 303, 304, + 923, 924, 306, 925, 308, 309, 310, 0, 311, 312, + 0, 0, 926, 314, 315, 0, 0, 316, 317, 318, + 319, 320, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 929, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 370, 371, 372, 373, + 930, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 0, 386, 387, 388, 389, 390, 931, 392, + 393, 394, 395, 396, 397, 398, 399, 932, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 933, 417, 0, 418, 419, 0, + 420, 421, 422, 423, 424, 425, 426, 0, 934, 935, + 0, 0, 429, 430, 936, 432, 937, 938, 434, 435, + 939, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 940, 0, 448, 449, 450, 451, 452, + 453, 941, 0, 455, 456, 457, 458, 459, 460, 461, + 0, 2385, 462, 0, 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 881, 0, 0, 0, 0, 0, 0, 882, 883, 0, - 0, 0, 0, 0, 885, 0, 2742, 0, 0, 0, - 0, 887, 0, 888, 889, 93, 822, 550, 823, 824, - 825, 826, 827, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, - 0, 102, 103, 104, 0, 0, 0, 0, 828, 0, - 0, 105, 106, 0, 107, 108, 109, 110, 111, 112, - 113, 2996, 829, 116, 830, 831, 0, 119, 120, 121, - 122, 123, 124, 832, 833, 125, 126, 834, 835, 129, - 0, 130, 131, 132, 133, 836, 0, 837, 0, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, - 146, 147, 148, 149, 150, 151, 0, 152, 153, 154, - 2997, 838, 839, 840, 841, 842, 843, 844, 157, 158, - 159, 160, 161, 162, 163, 845, 846, 166, 847, 167, - 0, 168, 169, 170, 171, 172, 173, 0, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 681, 182, 183, - 0, 184, 185, 186, 0, 187, 188, 189, 0, 190, - 191, 192, 193, 848, 195, 196, 197, 198, 199, 849, - 850, 201, 0, 202, 203, 851, 205, 0, 206, 0, - 207, 208, 0, 209, 210, 211, 212, 213, 214, 0, - 215, 0, 852, 853, 218, 0, 219, 220, 221, 222, - 223, 224, 225, 226, 227, 228, 229, 230, 0, 231, - 232, 233, 234, 235, 236, 0, 237, 238, 239, 240, - 241, 242, 243, 244, 854, 855, 0, 856, 0, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 0, 0, 259, 260, 261, 262, 0, 263, 264, 265, - 857, 858, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 859, 291, 860, 293, - 294, 295, 296, 861, 297, 298, 299, 300, 862, 863, - 302, 864, 304, 305, 306, 0, 307, 308, 0, 0, - 865, 310, 311, 0, 0, 312, 313, 314, 315, 316, - 866, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 0, 328, 329, 867, 331, 332, 333, 334, 335, - 336, 0, 337, 338, 339, 340, 341, 342, 0, 343, - 344, 345, 868, 347, 348, 349, 350, 0, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 0, 364, 365, 366, 367, 368, 369, 869, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 0, 382, 383, 384, 385, 386, 870, 387, 388, 389, - 390, 391, 392, 393, 394, 871, 396, 0, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 872, 412, 0, 413, 414, 0, 415, 416, - 417, 418, 419, 420, 421, 0, 873, 874, 0, 0, - 424, 425, 875, 427, 876, 877, 429, 430, 878, 432, - 433, 2998, 435, 436, 0, 0, 437, 438, 439, 440, - 441, 879, 0, 442, 443, 444, 445, 446, 447, 880, - 0, 449, 450, 451, 452, 453, 454, 455, 0, 0, - 456, 0, 0, 457, 458, 459, 460, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 881, 0, 0, 0, 0, 0, - 0, 882, 883, 0, 0, 0, 0, 0, 885, 0, - 886, 0, 0, 0, 0, 887, 0, 888, 889, 93, - 822, 550, 823, 824, 825, 826, 827, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, - 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, - 0, 0, 828, 0, 0, 105, 106, 0, 107, 108, - 109, 110, 111, 112, 113, 114, 829, 116, 830, 831, - 0, 119, 120, 121, 122, 123, 124, 832, 833, 125, - 126, 834, 835, 129, 0, 130, 131, 132, 133, 836, - 0, 837, 0, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, - 0, 152, 153, 154, 2997, 838, 839, 840, 841, 842, - 843, 844, 157, 158, 159, 160, 161, 162, 163, 845, - 846, 166, 847, 167, 0, 168, 169, 170, 171, 172, - 173, 0, 174, 175, 176, 177, 178, 0, 0, 179, - 180, 681, 182, 183, 0, 184, 185, 186, 0, 187, - 188, 189, 0, 190, 191, 192, 193, 848, 195, 196, - 197, 198, 199, 849, 850, 201, 0, 202, 203, 851, - 205, 0, 206, 0, 207, 208, 0, 209, 210, 211, - 212, 213, 214, 0, 215, 0, 852, 853, 218, 0, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, - 229, 230, 0, 231, 232, 233, 234, 235, 236, 0, - 237, 238, 239, 240, 241, 242, 243, 244, 854, 855, - 0, 856, 0, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 0, 0, 259, 260, 261, 262, - 0, 263, 264, 265, 857, 858, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 859, 291, 860, 293, 294, 295, 296, 861, 297, 298, - 299, 300, 862, 863, 302, 864, 304, 305, 306, 0, - 307, 308, 0, 0, 865, 310, 311, 0, 0, 312, - 313, 314, 315, 316, 866, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 0, 328, 329, 867, 331, - 332, 333, 334, 335, 336, 0, 337, 338, 339, 340, - 341, 342, 0, 343, 344, 345, 868, 347, 348, 349, - 350, 0, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 0, 364, 365, 366, 367, - 368, 369, 869, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 0, 382, 383, 384, 385, 386, - 870, 387, 388, 389, 390, 391, 392, 393, 394, 871, - 396, 0, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 409, 410, 872, 412, 0, 413, - 414, 0, 415, 416, 417, 418, 419, 420, 421, 0, - 873, 874, 0, 0, 424, 425, 875, 427, 876, 877, - 429, 430, 878, 432, 433, 2998, 435, 436, 0, 0, - 437, 438, 439, 440, 441, 879, 0, 442, 443, 444, - 445, 446, 447, 880, 0, 449, 450, 451, 452, 453, - 454, 455, 0, 0, 456, 0, 0, 457, 458, 459, - 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 881, 0, - 0, 0, 0, 0, 0, 882, 883, 0, 0, 0, - 0, 0, 885, 0, 886, 0, 0, 0, 0, 887, - 0, 888, 889, 93, 822, 550, 823, 824, 825, 826, - 827, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, - 103, 104, 0, 0, 0, 0, 828, 0, 0, 105, - 106, 0, 107, 108, 109, 110, 111, 112, 113, -1773, - 829, 116, 830, 831, 0, 119, 120, 121, 122, 123, - 124, 832, 833, 125, 126, 834, 835, 129, 0, 130, - 131, 132, 133, 836, 0, 837, 0, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, 152, 153, 154, 2997, 838, - 839, 840, 841, 842, 843, 844, 157, 158, 159, 160, - 161, 162, 163, 845, 846, 166, 847, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 681, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 848, 195, 196, 197, 198, 199, 849, 850, 201, - 0, 202, 203, 851, 205, 0, 206, 0, 207, 208, - 0, 209, 210, 211, 212, -1773, 214, 0, 215, 0, - 852, 853, 218, 0, 219, 220, 221, 222, 223, 224, - 225, -1773, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 238, 239, 240, 241, 242, - 243, 244, 854, 855, 0, 856, 0, 248, 0, 0, - 251, 252, 253, 254, 255, 256, 257, 258, 0, 0, - 259, 260, 261, -1773, 0, 263, 264, 265, 857, 858, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 478, 479, 480, 481, 482, 483, 942, 0, 0, 0, + 0, 0, 0, 943, 944, 0, 0, 0, 0, 0, + 946, 0, 947, 0, 0, 0, 0, 948, 0, 949, + 950, 93, 883, 582, 884, 885, 886, 887, 888, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, + 104, 0, 0, 0, 0, 889, 0, 0, 105, 106, + 0, 107, 108, 109, 110, 111, 112, 113, 114, 890, + 116, 891, 892, 0, 119, 120, 121, 122, 123, 124, + 893, 894, 125, 126, 895, 896, 129, 0, 130, 131, + 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, + 149, 150, 151, 0, 152, 153, 154, 155, 899, 900, + 901, 902, 903, 904, 905, 161, 162, 163, 164, 165, + 166, 167, 906, 907, 170, 908, 171, 0, 172, 173, + 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, + 0, 0, 183, 184, 712, 186, 187, 0, 188, 189, + 190, 0, 191, 192, 193, 0, 194, 195, 196, 197, + 909, 199, 200, 201, 202, 203, 910, 911, 205, 0, + 206, 207, 912, 209, 0, 210, 0, 211, 212, 0, + 213, 214, 215, 216, 217, 218, 0, 219, 0, 913, + 914, 222, 0, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 0, 235, 236, 237, 238, + 239, 240, 0, 241, 242, 243, 244, 245, 246, 247, + 248, 915, 916, 0, 917, 0, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 0, 0, 263, + 264, 265, 266, 0, 267, 268, 269, 918, 919, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 920, 295, 921, 297, 298, 299, 300, + 922, 301, 302, 303, 304, 923, 924, 306, 925, 308, + 309, 310, 0, 311, 312, 0, 0, 926, 314, 315, + 0, 0, 316, 317, 318, 319, 320, 927, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 0, 332, + 333, 928, 335, 336, 337, 338, 339, 340, 0, 341, + 342, 343, 344, 345, 346, 0, 347, 348, 349, 929, + 351, 352, 353, 354, 0, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 0, 368, + 369, 370, 371, 372, 373, 930, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 0, 386, 387, + 388, 389, 390, 931, 392, 393, 394, 395, 396, 397, + 398, 399, 932, 401, 0, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 933, + 417, 0, 418, 419, 0, 420, 421, 422, 423, 424, + 425, 426, 0, 934, 935, 0, 0, 429, 430, 936, + 432, 937, 938, 434, 435, 939, 437, 438, 439, 440, + 441, 0, 0, 442, 443, 444, 445, 446, 940, 0, + 448, 449, 450, 451, 452, 453, 941, 0, 455, 456, + 457, 458, 459, 460, 461, 0, 0, 462, 0, 0, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 483, 942, 0, 0, 0, 0, 0, 0, 943, 944, + 0, 0, 0, 0, 0, 946, 0, 947, 0, 0, + 0, 0, 948, 0, 949, 950, 1080, 883, 582, 884, + 885, 886, 887, 888, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, + 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, + 889, 0, 0, 105, 106, 0, 107, 108, 109, 1082, + 111, 112, 113, 114, 890, 1083, 891, 892, 0, 119, + 120, 121, 122, 123, 124, 893, 894, 125, 126, 895, + 896, 129, 0, 130, 131, 132, 133, 897, 0, 1084, + 0, 136, 137, 138, 139, 140, 141, 1085, 143, 144, + 145, 0, 146, 147, 148, 149, 150, 151, 0, 1086, + 153, 154, 155, 1087, 1088, 1089, 1090, 903, 904, 1091, + 161, 162, 163, 164, 165, 166, 167, 906, 907, 170, + 908, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 712, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 909, 199, 200, 201, 202, + 203, 910, 911, 205, 0, 206, 207, 912, 209, 0, + 210, 0, 211, 1093, 0, 1094, 214, 215, 1095, 1096, + 218, 0, 219, 0, 913, 914, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 1097, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 1098, + 243, 244, 245, 246, 247, 248, 915, 916, 0, 917, + 0, 252, 1099, 1100, 255, 1101, 257, 258, 259, 260, + 261, 262, 0, 0, 263, 1102, 265, 1103, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 1104, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 859, 291, 860, 293, 294, 295, - 296, 0, 297, 298, 0, 300, 862, 863, 302, 864, - 304, 305, 306, 0, 307, 308, 0, 0, 865, 310, - 311, 0, 0, 312, 313, 314, 315, 316, 866, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 867, 331, 332, 333, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 868, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 366, 367, 368, 369, 869, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 0, 382, - 383, 384, 385, 386, 870, 387, 388, 389, 390, 391, - -1773, 393, 394, 871, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 872, 412, 0, 413, 414, 0, 415, 416, 417, 418, - 419, 420, 421, 0, 873, 874, 0, 0, 424, 425, - 875, 427, 876, 877, 429, 430, 878, 432, 433, 2998, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 879, - 0, 442, 443, 444, 445, 446, 447, 880, 0, 449, - 450, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 0, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, -1773, 0, 0, 0, 0, 0, 0, 882, - 883, 0, 0, 0, 0, 0, 885, 0, 886, 0, - 0, 0, 0, 887, 0, 888, 889, 93, 822, 550, - 823, 824, 825, 826, 827, 0, 0, 0, 0, 0, + 286, 287, 288, 289, 290, 291, 292, 293, 920, 1105, + 921, 297, 298, 299, 300, 922, 301, 302, 1106, 304, + 923, 924, 306, 925, 308, 309, 310, 0, 311, 312, + 0, 0, 926, 314, 315, 0, 0, 316, 317, 1107, + 319, 1108, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 929, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 1109, 371, 372, 373, + 930, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 0, 386, 387, 388, 389, 390, 1110, 392, + 393, 394, 395, 396, 1111, 398, 399, 932, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 1112, 415, 933, 417, 0, 418, 419, 0, + 420, 1113, 422, 423, 424, 425, 426, 0, 934, 935, + 0, 0, 429, 430, 936, 432, 937, 938, 434, 435, + 1114, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 1115, 0, 448, 449, 450, 451, 452, + 453, 941, 0, 455, 1117, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 483, 942, 0, 0, 0, + 0, 0, 0, 943, 944, 0, 0, 0, 0, 0, + 946, 0, 947, 0, 0, 0, 0, 948, 0, 949, + 950, 93, 883, 582, 884, 885, 886, 887, 888, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, + 104, 0, 0, 0, 0, 889, 0, 0, 105, 106, + 0, 107, 108, 109, 110, 111, 112, 113, 114, 890, + 116, 891, 892, 0, 119, 120, 121, 122, 123, 124, + 893, 894, 125, 126, 895, 896, 129, 0, 130, 131, + 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, + 149, 150, 151, 0, 152, 153, 154, 155, 899, 900, + 901, 902, 903, 904, 905, 161, 162, 163, 164, 165, + 166, 167, 906, 907, 170, 908, 171, 0, 172, 173, + 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, + 0, 0, 183, 184, 712, 186, 187, 0, 188, 189, + 190, 0, 191, 192, 193, 0, 194, 195, 196, 197, + 909, 199, 200, 201, 202, 203, 910, 911, 205, 0, + 206, 207, 912, 209, 0, 210, 0, 211, 212, 0, + 213, 214, 215, 216, 217, 218, 0, 219, 0, 913, + 914, 222, 0, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 0, 235, 236, 237, 238, + 239, 240, 0, 241, 242, 243, 244, 245, 246, 247, + 248, 915, 916, 0, 917, 0, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 0, 0, 263, + 264, 265, 266, 0, 267, 268, 269, 918, 919, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 920, 295, 921, 297, 298, 299, 300, + 922, 301, 302, 303, 304, 923, 924, 306, 925, 308, + 309, 310, 0, 311, 312, 0, 0, 926, 314, 315, + 0, 0, 316, 317, 318, 319, 320, 927, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 0, 332, + 333, 928, 335, 336, 337, 338, 339, 340, 0, 341, + 342, 343, 344, 345, 346, 0, 347, 348, 349, 929, + 351, 352, 353, 354, 0, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 0, 368, + 369, 370, 371, 372, 373, 930, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 0, 386, 387, + 388, 389, 390, 931, 392, 393, 394, 395, 396, 397, + 398, 399, 932, 401, 0, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 933, + 417, 0, 418, 419, 0, 420, 421, 422, 423, 424, + 425, 426, 0, 934, 935, 0, 0, 429, 430, 936, + 432, 937, 938, 434, 435, 939, 437, 438, 439, 440, + 441, 0, 0, 442, 443, 444, 445, 446, 940, 0, + 448, 449, 450, 451, 452, 453, 941, 0, 455, 456, + 457, 458, 459, 460, 461, 0, 0, 462, 0, 0, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 483, 942, 0, 0, 0, 0, 0, 0, 1482, 1483, + 0, 0, 0, 0, 0, 946, 0, 947, 0, 0, + 0, 0, 948, 0, 949, 950, 93, 1866, 582, 884, + 885, 886, 887, 888, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, - 0, 0, 0, 105, 106, 0, 107, 108, 109, 110, - 111, 112, 113, 114, 829, 116, 830, 831, 0, 119, - 120, 121, 122, 123, 124, 832, 833, 125, 126, 834, - 835, 129, 0, 130, 131, 132, 133, 836, 0, 837, + 889, 0, 0, 105, 106, 0, 107, 108, 109, 110, + 111, 112, 113, 114, 890, 116, 891, 892, 0, 119, + 120, 121, 122, 123, 124, 893, 894, 125, 126, 895, + 896, 129, 0, 130, 131, 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 152, - 153, 154, 155, 838, 839, 840, 841, 842, 843, 844, - 157, 158, 159, 160, 161, 162, 163, 845, 846, 166, - 0, 167, 0, 168, 169, 170, 171, 172, 173, 0, - 174, 175, 176, 177, 178, 0, 0, 179, 180, 681, - 182, 183, 0, 184, 185, 186, 0, 187, 188, 189, - 0, 190, 191, 192, 193, 848, 195, 196, 197, 198, - 199, 849, 850, 201, 0, 202, 203, 851, 205, 0, - 206, 0, 207, 208, 0, 209, 210, 211, 212, 213, - 214, 0, 215, 0, 852, 853, 218, 0, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 0, 231, 232, 233, 234, 235, 236, 0, 237, 238, - 239, 240, 241, 242, 243, 244, 854, 855, 0, 856, - 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 0, 0, 259, 260, 261, 262, 0, 263, - 264, 265, 857, 858, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 859, 291, - 860, 293, 294, 295, 296, 0, 297, 298, 299, 300, - 862, 863, 302, 864, 304, 305, 306, 0, 307, 308, - 0, 0, 865, 310, 311, 0, 0, 312, 313, 314, - 315, 316, 866, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 0, 328, 329, 867, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 339, 340, 341, 342, - 0, 343, 344, 345, 868, 347, 348, 349, 350, 0, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 0, 364, 365, 366, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 0, 382, 383, 384, 385, 386, 870, 387, - 388, 389, 390, 391, 392, 393, 394, 871, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 872, 412, 0, 413, 414, 0, - 415, 416, 417, 418, 419, 420, 421, 0, 873, 874, - 0, 0, 424, 425, 875, 427, 876, 877, 429, 430, - 878, 432, 433, 434, 435, 436, 0, 0, 437, 438, - 439, 440, 441, 879, 0, 442, 443, 444, 445, 446, - 447, 880, 0, 449, 450, 451, 452, 453, 454, 455, - 0, 0, 456, 0, 0, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 0, 0, 0, 0, - 0, 0, 0, 1648, 1649, 0, 0, 93, 822, 550, - 823, 824, 1650, 826, 827, 0, 0, 0, 0, 888, - 889, 0, 0, 0, 94, 95, 96, 97, 98, 99, + 153, 154, 155, 899, 900, 901, 902, 903, 904, 905, + 161, 162, 163, 164, 165, 166, 167, 906, 907, 170, + 908, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 712, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 909, 199, 200, 201, 202, + 203, 910, 911, 205, 0, 206, 207, 912, 209, 0, + 210, 0, 211, 212, 0, 213, 214, 215, 216, 217, + 218, 0, 219, 0, 913, 914, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 242, + 243, 244, 245, 246, 247, 248, 915, 916, 0, 917, + 0, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 0, 0, 263, 264, 265, 266, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 920, 295, + 921, 297, 298, 299, 300, 922, 301, 302, 303, 304, + 923, 924, 306, 925, 308, 309, 310, 0, 311, 312, + 0, 0, 926, 314, 315, 0, 0, 316, 317, 318, + 319, 320, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 929, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 370, 371, 372, 373, + 930, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 0, 386, 387, 388, 389, 390, 931, 392, + 393, 394, 395, 396, 397, 398, 399, 932, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 933, 417, 0, 418, 419, 0, + 420, 421, 422, 423, 424, 425, 426, 0, 934, 935, + 0, 0, 429, 430, 936, 432, 937, 938, 434, 435, + 939, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 940, 0, 448, 449, 450, 451, 452, + 453, 941, 0, 455, 456, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 483, 942, 0, 0, 0, + 0, 0, 0, 943, 944, 0, 0, 0, 0, 0, + 946, 0, 947, 0, 0, 0, 0, 948, 0, 949, + 950, 93, 883, 582, 884, 885, 886, 887, 888, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, + 104, 0, 0, 0, 0, 889, 0, 0, 105, 106, + 0, 107, 108, 109, 110, 111, 112, 113, 114, 890, + 116, 891, 892, 0, 119, 120, 121, 122, 123, 124, + 893, 894, 125, 126, 895, 896, 129, 0, 130, 131, + 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, + 149, 150, 151, 0, 152, 153, 154, 155, 899, 900, + 901, 902, 903, 904, 905, 161, 162, 163, 164, 165, + 166, 167, 906, 907, 170, 908, 171, 0, 172, 173, + 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, + 0, 0, 183, 184, 712, 186, 187, 0, 188, 189, + 190, 0, 191, 192, 193, 0, 194, 195, 196, 197, + 909, 199, 200, 201, 202, 203, 910, 911, 205, 0, + 206, 207, 912, 209, 0, 210, 0, 211, 212, 0, + 213, 214, 215, 216, 217, 218, 0, 219, 0, 913, + 914, 222, 0, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 0, 235, 236, 237, 238, + 239, 240, 0, 241, 242, 243, 244, 245, 246, 247, + 248, 915, 916, 0, 917, 0, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 0, 0, 263, + 264, 265, 266, 0, 267, 268, 269, 918, 919, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 920, 295, 921, 297, 298, 299, 300, + 922, 301, 302, 303, 304, 923, 924, 306, 925, 308, + 309, 310, 0, 311, 312, 0, 0, 926, 314, 315, + 0, 0, 316, 317, 318, 319, 320, 927, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 0, 332, + 333, 928, 335, 336, 337, 338, 339, 340, 0, 341, + 342, 343, 344, 345, 346, 0, 347, 348, 349, 929, + 351, 352, 353, 354, 0, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 0, 368, + 369, 370, 371, 372, 373, 930, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 0, 386, 387, + 388, 389, 390, 931, 392, 393, 394, 395, 396, 397, + 398, 399, 932, 401, 0, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 933, + 417, 0, 418, 419, 0, 420, 421, 422, 423, 424, + 425, 426, 0, 934, 935, 0, 0, 429, 430, 936, + 432, 937, 938, 434, 435, 939, 437, 438, 439, 440, + 441, 0, 0, 442, 443, 444, 445, 446, 940, 0, + 448, 449, 450, 451, 452, 453, 941, 0, 455, 456, + 457, 458, 459, 460, 461, 0, 0, 462, 0, 0, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 483, 942, 0, 0, 0, 0, 0, 0, 943, 944, + 0, 0, 0, 0, 0, 946, 0, 2097, 0, 0, + 0, 0, 948, 0, 949, 950, 93, 883, 582, 884, + 885, 886, 887, 888, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, - 0, 0, 0, 105, 106, 0, 107, 108, 109, 110, - 111, 112, 113, 114, 829, 116, 830, 831, 0, 119, - 120, 121, 122, 123, 124, 832, 833, 125, 126, 834, - 835, 129, 0, 130, 131, 132, 133, 836, 0, 837, + 889, 0, 0, 105, 106, 0, 107, 108, 109, 110, + 111, 112, 113, 114, 890, 116, 891, 892, 0, 119, + 120, 121, 122, 123, 124, 893, 894, 125, 126, 895, + 896, 129, 0, 130, 131, 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 152, - 153, 154, 155, 838, 839, 840, 841, 842, 843, 844, - 157, 158, 159, 160, 161, 162, 163, 845, 846, 166, - 0, 167, 0, 168, 169, 170, 171, 172, 173, 0, - 174, 175, 176, 177, 178, 0, 0, 179, 180, 681, - 182, 183, 0, 184, 185, 186, 0, 187, 188, 189, - 0, 190, 191, 192, 193, 848, 195, 196, 197, 198, - 199, 849, 850, 201, 0, 202, 203, 851, 205, 0, - 206, 0, 207, 208, 0, 209, 210, 211, 212, 213, - 214, 0, 215, 0, 852, 853, 218, 0, 219, 220, - 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, - 0, 231, 232, 233, 234, 235, 236, 0, 237, 238, - 239, 240, 241, 242, 243, 244, 854, 855, 0, 856, - 0, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 0, 0, 259, 260, 261, 262, 0, 263, - 264, 265, 857, 858, 266, 267, 268, 269, 270, 271, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 859, 291, - 860, 293, 294, 295, 296, 0, 297, 298, 299, 300, - 862, 863, 302, 864, 304, 305, 306, 0, 307, 308, - 0, 0, 309, 310, 311, 0, 0, 312, 313, 314, - 315, 316, 866, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 0, 328, 329, 867, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 339, 340, 341, 342, - 0, 343, 344, 345, 868, 347, 348, 349, 350, 0, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 0, 364, 365, 366, 367, 368, 369, - 1787, 1788, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 0, 382, 383, 384, 385, 386, 870, 387, - 388, 389, 390, 391, 392, 393, 394, 871, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 872, 412, 0, 413, 414, 0, - 415, 416, 417, 418, 419, 420, 421, 0, 873, 874, - 0, 0, 424, 425, 875, 427, 876, 877, 429, 430, - 878, 432, 433, 434, 435, 436, 0, 0, 437, 438, - 439, 440, 441, 879, 0, 442, 443, 444, 445, 446, - 447, 880, 0, 449, 450, 451, 452, 453, 454, 455, - 0, 0, 456, 0, 0, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 0, 0, 0, 0, - 0, 0, 0, 1789, 1790, 0, 0, 0, 0, 0, - 0, 0, 1650, 0, 0, 0, 0, 0, 0, 888, - 889, 93, 822, 550, 823, 824, 825, 826, 827, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, - 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, - 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, - 107, 108, 109, 110, 111, 112, 113, 114, 829, 116, - 830, 831, 0, 119, 120, 121, 122, 123, 124, 832, - 833, 125, 126, 834, 835, 129, 0, 130, 131, 132, - 133, 836, 0, 837, 0, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, - 150, 151, 0, 152, 153, 154, 155, 838, 839, 840, - 841, 842, 843, 844, 157, 158, 159, 160, 161, 162, - 163, 845, 846, 166, 0, 167, 0, 168, 169, 170, - 171, 172, 173, 0, 174, 175, 176, 177, 178, 0, - 0, 179, 180, 681, 182, 183, 0, 184, 185, 186, - 0, 187, 188, 189, 0, 190, 191, 192, 193, 848, - 195, 196, 197, 198, 199, 849, 850, 201, 0, 202, - 203, 851, 205, 0, 206, 0, 207, 208, 0, 209, - 210, 211, 212, 213, 214, 0, 215, 0, 852, 853, - 218, 0, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 0, 231, 232, 233, 234, 235, - 236, 0, 237, 238, 239, 240, 241, 242, 243, 244, - 854, 855, 0, 856, 0, 248, 0, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 0, 0, 259, 260, - 261, 262, 0, 263, 264, 265, 857, 858, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 859, 291, 860, 293, 294, 295, 296, 0, - 297, 298, 299, 300, 862, 863, 302, 864, 304, 305, - 306, 0, 307, 308, 0, 0, 865, 310, 311, 0, - 0, 312, 313, 314, 315, 316, 866, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 0, 328, 329, - 867, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 339, 340, 341, 342, 0, 343, 344, 345, 868, 347, - 348, 349, 350, 0, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 0, 364, 365, - 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 0, 382, 383, 384, - 385, 386, 870, 387, 388, 389, 390, 391, 392, 393, - 394, 871, 396, 0, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 872, 412, - 0, 413, 414, 0, 415, 416, 417, 418, 419, 420, - 421, 0, 873, 874, 0, 0, 424, 425, 875, 427, - 876, 877, 429, 430, 878, 432, 433, 434, 435, 436, - 0, 0, 437, 438, 439, 440, 441, 879, 0, 442, - 443, 444, 445, 446, 447, 880, 0, 449, 450, 451, - 452, 453, 454, 455, 0, 0, 456, 0, 0, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, + 153, 2799, 155, 899, 900, 901, 902, 903, 904, 905, + 161, 162, 163, 164, 165, 166, 167, 906, 907, 170, + 908, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 712, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 909, 199, 200, 201, 202, + 203, 910, 911, 205, 0, 206, 207, 912, 209, 0, + 210, 0, 211, 212, 0, 213, 214, 215, 216, 217, + 218, 0, 219, 0, 2800, 914, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 242, + 243, 244, 245, 246, 247, 248, 915, 916, 0, 917, + 0, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 0, 0, 263, 264, 265, 266, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 920, 295, + 921, 297, 298, 299, 300, 922, 301, 302, 303, 304, + 923, 924, 306, 925, 308, 309, 310, 0, 311, 312, + 0, 0, 926, 314, 315, 0, 0, 316, 317, 318, + 319, 320, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 929, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 370, 371, 372, 2801, + 930, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 0, 386, 387, 388, 389, 390, 931, 392, + 393, 394, 395, 396, 397, 398, 399, 932, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 933, 417, 0, 418, 419, 0, + 420, 421, 422, 423, 424, 425, 426, 0, 934, 935, + 0, 0, 429, 430, 936, 432, 937, 938, 434, 435, + 939, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 940, 0, 448, 449, 450, 451, 452, + 453, 941, 0, 455, 456, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 0, 0, 0, 0, 0, 0, 0, 1648, 1649, 0, - 0, 0, 0, 0, 0, 0, 1650, 0, 0, 0, - 0, 0, 0, 888, 889, 93, 822, 550, 823, 824, - 825, 826, 827, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, - 0, 102, 103, 104, 0, 0, 0, 0, 828, 0, - 0, 105, 106, 0, 107, 108, 109, 110, 111, 112, - 113, 0, 829, 116, 830, 831, 0, 119, 120, 121, - 122, 123, 124, 832, 833, 125, 126, 834, 835, 129, - 0, 130, 131, 132, 133, 836, 0, 837, 0, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, - 146, 147, 148, 149, 150, 151, 0, 152, 153, 154, - 155, 838, 839, 840, 841, 842, 843, 844, 157, 158, - 159, 160, 161, 162, 163, 845, 846, 166, 847, 167, - 0, 168, 169, 170, 171, 172, 173, 0, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 681, 182, 183, - 0, 184, 185, 186, 0, 187, 0, 189, 0, 190, - 191, 192, 193, 848, 195, 196, 197, 198, 199, 849, - 850, 201, 0, 202, 203, 851, 205, 0, 206, 0, - 207, 208, 0, 209, 210, 211, 212, 0, 214, 0, - 215, 0, 852, 853, 218, 0, 219, 220, 221, 222, - 223, 224, 225, 0, 227, 228, 229, 230, 0, 231, - 232, 233, 234, 235, 236, 0, 237, 238, 239, 240, - 241, 242, 243, 244, 854, 855, 0, 856, 0, 248, - 0, 0, 251, 252, 253, 254, 255, 256, 257, 258, - 0, 0, 259, 260, 261, 0, 0, 263, 264, 265, - 857, 858, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 859, 291, 860, 293, - 294, 295, 296, 0, 297, 298, 0, 300, 862, 863, - 302, 864, 304, 305, 306, 0, 307, 308, 0, 0, - 865, 310, 311, 0, 0, 312, 313, 314, 315, 316, - 866, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 0, 328, 329, 867, 331, 332, 333, 334, 335, - 336, 0, 337, 338, 339, 340, 341, 342, 0, 343, - 344, 345, 868, 347, 348, 349, 350, 0, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 0, 364, 365, 366, 367, 368, 369, 869, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 0, 382, 383, 384, 385, 386, 870, 387, 388, 389, - 390, 391, 0, 393, 394, 871, 396, 0, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 872, 412, 0, 413, 414, 0, 415, 416, - 417, 418, 419, 420, 421, 0, 873, 874, 0, 0, - 424, 425, 875, 427, 876, 877, 429, 430, 878, 432, - 433, 434, 435, 436, 0, 0, 437, 438, 439, 440, - 441, 879, 0, 442, 443, 444, 445, 446, 447, 880, - 0, 449, 450, 451, 452, 453, 454, 455, 0, 0, - 456, 0, 0, 457, 458, 459, 460, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 0, 0, 0, 0, 0, 0, - 0, 882, 883, 500, 0, 0, 0, 0, 885, 0, - 886, 0, 0, 0, 0, 887, 0, 888, 889, 0, - 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, - 103, 104, 0, 0, 0, 0, 0, 2345, 0, 105, - 106, 0, 107, 108, 109, 0, 111, 112, 113, 114, - 115, 0, 117, 118, 0, 119, 120, 121, 122, 123, - 124, 0, 0, 125, 126, 127, 128, 129, 0, 130, - 131, 132, 133, 134, 0, 0, 0, 136, 137, 138, - 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, -629, 153, 154, 155, 0, - 0, 0, 0, 0, 0, 0, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 0, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 181, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 0, 201, - 0, 202, 203, 204, 205, 0, 206, 0, 207, 0, - 0, -629, 210, 211, 502, 0, 214, 0, 215, 0, - 216, 217, 218, 0, 219, 220, 221, 222, 223, 224, - 225, 0, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, -629, 239, 240, 241, 242, - 243, 244, 245, 246, 0, 247, 0, 248, 0, 0, - 251, -629, 253, 254, 255, 256, 257, 258, 0, 0, - 259, -629, 261, 0, 0, 263, 264, 265, 0, 0, - 266, 267, 268, 269, 270, 503, 272, 273, 274, 275, + 478, 479, 480, 481, 482, 483, 942, 0, 0, 0, + 0, 0, 0, 943, 944, 0, 0, 0, 0, 0, + 946, 0, 2803, 0, 0, 0, 0, 948, 0, 949, + 950, 93, 883, 582, 884, 885, 886, 887, 888, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, + 104, 0, 0, 0, 0, 889, 0, 0, 105, 106, + 0, 107, 108, 109, 110, 111, 112, 113, 3057, 890, + 116, 891, 892, 0, 119, 120, 121, 122, 123, 124, + 893, 894, 125, 126, 895, 896, 129, 0, 130, 131, + 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, + 149, 150, 151, 0, 152, 153, 154, 3058, 899, 900, + 901, 902, 903, 904, 905, 161, 162, 163, 164, 165, + 166, 167, 906, 907, 170, 908, 171, 0, 172, 173, + 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, + 0, 0, 183, 184, 712, 186, 187, 0, 188, 189, + 190, 0, 191, 192, 193, 0, 194, 195, 196, 197, + 909, 199, 200, 201, 202, 203, 910, 911, 205, 0, + 206, 207, 912, 209, 0, 210, 0, 211, 212, 0, + 213, 214, 215, 216, 217, 218, 0, 219, 0, 913, + 914, 222, 0, 223, 224, 225, 226, 227, 228, 229, + 230, 231, 232, 233, 234, 0, 235, 236, 237, 238, + 239, 240, 0, 241, 242, 243, 244, 245, 246, 247, + 248, 915, 916, 0, 917, 0, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 0, 0, 263, + 264, 265, 266, 0, 267, 268, 269, 918, 919, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 920, 295, 921, 297, 298, 299, 300, + 922, 301, 302, 303, 304, 923, 924, 306, 925, 308, + 309, 310, 0, 311, 312, 0, 0, 926, 314, 315, + 0, 0, 316, 317, 318, 319, 320, 927, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 0, 332, + 333, 928, 335, 336, 337, 338, 339, 340, 0, 341, + 342, 343, 344, 345, 346, 0, 347, 348, 349, 929, + 351, 352, 353, 354, 0, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 0, 368, + 369, 370, 371, 372, 373, 930, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 0, 386, 387, + 388, 389, 390, 931, 392, 393, 394, 395, 396, 397, + 398, 399, 932, 401, 0, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 933, + 417, 0, 418, 419, 0, 420, 421, 422, 423, 424, + 425, 426, 0, 934, 935, 0, 0, 429, 430, 936, + 432, 937, 938, 434, 435, 939, 437, 438, 3059, 440, + 441, 0, 0, 442, 443, 444, 445, 446, 940, 0, + 448, 449, 450, 451, 452, 453, 941, 0, 455, 456, + 457, 458, 459, 460, 461, 0, 0, 462, 0, 0, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 483, 942, 0, 0, 0, 0, 0, 0, 943, 944, + 0, 0, 0, 0, 0, 946, 0, 947, 0, 0, + 0, 0, 948, 0, 949, 950, 93, 883, 582, 884, + 885, 886, 887, 888, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, + 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, + 889, 0, 0, 105, 106, 0, 107, 108, 109, 110, + 111, 112, 113, 114, 890, 116, 891, 892, 0, 119, + 120, 121, 122, 123, 124, 893, 894, 125, 126, 895, + 896, 129, 0, 130, 131, 132, 133, 897, 0, 898, + 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 0, 146, 147, 148, 149, 150, 151, 0, 152, + 153, 154, 3058, 899, 900, 901, 902, 903, 904, 905, + 161, 162, 163, 164, 165, 166, 167, 906, 907, 170, + 908, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 712, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 909, 199, 200, 201, 202, + 203, 910, 911, 205, 0, 206, 207, 912, 209, 0, + 210, 0, 211, 212, 0, 213, 214, 215, 216, 217, + 218, 0, 219, 0, 913, 914, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 242, + 243, 244, 245, 246, 247, 248, 915, 916, 0, 917, + 0, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 0, 0, 263, 264, 265, 266, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, -629, 292, 293, 294, 295, - 296, 0, 297, 298, 0, 300, 0, 301, 302, 303, - 304, 305, 306, 0, 307, 308, 0, 0, 309, 310, - 311, 0, 0, 312, 313, 0, 315, 0, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 330, 331, 332, 333, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 346, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, -629, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 0, 382, - 383, 384, 385, 386, 0, 387, 388, 389, 390, 391, - 0, 393, 394, 395, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 505, 410, - 411, 412, 0, 413, 414, 0, 415, -629, 417, 418, - 419, 420, 421, 0, 422, 423, 0, 0, 424, 425, - 426, 427, 428, 0, 429, 430, 431, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 0, - 0, 442, 443, 444, 445, 446, 447, 448, 0, 449, - 0, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 0, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 0, 93, 0, 582, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 951, - 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, - 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, - 106, 0, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 0, 119, 120, 121, 122, 123, - 124, 0, 833, 125, 126, 127, 128, 129, 0, 130, - 131, 132, 133, 836, 0, 837, 0, 136, 137, 138, - 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, 152, 153, 154, 155, 838, - 839, 840, 841, 842, 843, 844, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 0, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 181, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 849, 0, 201, - 0, 202, 203, 204, 205, 0, 206, 0, 207, 208, - 0, 209, 210, 211, 212, 213, 214, 0, 215, 0, - 216, 217, 218, 0, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 0, 247, 0, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 2083, 0, - 259, 260, 261, 262, 0, 263, 264, 265, 857, 858, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 286, 287, 288, 289, 290, 291, 292, 293, 920, 295, + 921, 297, 298, 299, 300, 922, 301, 302, 303, 304, + 923, 924, 306, 925, 308, 309, 310, 0, 311, 312, + 0, 0, 926, 314, 315, 0, 0, 316, 317, 318, + 319, 320, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 929, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 370, 371, 372, 373, + 930, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 0, 386, 387, 388, 389, 390, 931, 392, + 393, 394, 395, 396, 397, 398, 399, 932, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 933, 417, 0, 418, 419, 0, + 420, 421, 422, 423, 424, 425, 426, 0, 934, 935, + 0, 0, 429, 430, 936, 432, 937, 938, 434, 435, + 939, 437, 438, 3059, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 940, 0, 448, 449, 450, 451, 452, + 453, 941, 0, 455, 456, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 483, 942, 0, 0, 0, + 0, 0, 0, 943, 944, 0, 0, 0, 0, 0, + 946, 0, 947, 0, 0, 0, 0, 948, 0, 949, + 950, 93, 883, 582, 884, 885, 886, 887, 888, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, + 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, + 104, 0, 0, 0, 0, 889, 0, 0, 105, 106, + 0, 107, 108, 109, 110, 111, 112, 113, -1847, 890, + 116, 891, 892, 0, 119, 120, 121, 122, 123, 124, + 893, 894, 125, 126, 895, 896, 129, 0, 130, 131, + 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, + 149, 150, 151, 0, 152, 153, 154, 3058, 899, 900, + 901, 902, 903, 904, 905, 161, 162, 163, 164, 165, + 166, 167, 906, 907, 170, 908, 171, 0, 172, 173, + 174, 175, 176, 177, 0, 178, 179, 180, 181, 182, + 0, 0, 183, 184, 712, 186, 187, 0, 188, 189, + 190, 0, 191, 192, 193, 0, 194, 195, 196, 197, + 909, 199, 200, 201, 202, 203, 910, 911, 205, 0, + 206, 207, 912, 209, 0, 210, 0, 211, 212, 0, + 213, 214, 215, 216, -1847, 218, 0, 219, 0, 913, + 914, 222, 0, 223, 224, 225, 226, 227, 228, 229, + -1847, 231, 232, 233, 234, 0, 235, 236, 237, 238, + 239, 240, 0, 241, 242, 243, 244, 245, 246, 247, + 248, 915, 916, 0, 917, 0, 252, 0, 0, 255, + 256, 257, 258, 259, 260, 261, 262, 0, 0, 263, + 264, 265, -1847, 0, 267, 268, 269, 918, 919, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 920, 295, 921, 297, 298, 299, 300, + 0, 301, 302, 0, 304, 923, 924, 306, 925, 308, + 309, 310, 0, 311, 312, 0, 0, 926, 314, 315, + 0, 0, 316, 317, 318, 319, 320, 927, 322, 323, + 324, 325, 326, 327, 328, 329, 330, 331, 0, 332, + 333, 928, 335, 336, 337, 338, 339, 340, 0, 341, + 342, 343, 344, 345, 346, 0, 347, 348, 349, 929, + 351, 352, 353, 354, 0, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 0, 368, + 369, 370, 371, 372, 373, 930, 375, 376, 377, 378, + 379, 380, 381, 382, 383, 384, 385, 0, 386, 387, + 388, 389, 390, 931, 392, 393, 394, 395, 396, -1847, + 398, 399, 932, 401, 0, 402, 403, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, 414, 415, 933, + 417, 0, 418, 419, 0, 420, 421, 422, 423, 424, + 425, 426, 0, 934, 935, 0, 0, 429, 430, 936, + 432, 937, 938, 434, 435, 939, 437, 438, 3059, 440, + 441, 0, 0, 442, 443, 444, 445, 446, 940, 0, + 448, 449, 450, 451, 452, 453, 941, 0, 455, 456, + 457, 458, 459, 460, 461, 0, 0, 462, 0, 0, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 483, -1847, 0, 0, 0, 0, 0, 0, 943, 944, + 0, 0, 0, 0, 0, 946, 0, 947, 0, 0, + 0, 0, 948, 0, 949, 950, 93, 883, 582, 884, + 885, 886, 887, 888, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, + 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, + 0, 0, 0, 105, 106, 0, 107, 108, 109, 110, + 111, 112, 113, 114, 890, 116, 891, 892, 0, 119, + 120, 121, 122, 123, 124, 893, 894, 125, 126, 895, + 896, 129, 0, 130, 131, 132, 133, 897, 0, 898, + 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 0, 146, 147, 148, 149, 150, 151, 0, 152, + 153, 154, 155, 899, 900, 901, 902, 903, 904, 905, + 161, 162, 163, 164, 165, 166, 167, 906, 907, 170, + 0, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 712, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 909, 199, 200, 201, 202, + 203, 910, 911, 205, 0, 206, 207, 912, 209, 0, + 210, 0, 211, 212, 0, 213, 214, 215, 216, 217, + 218, 0, 219, 0, 913, 914, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 242, + 243, 244, 245, 246, 247, 248, 915, 916, 0, 917, + 0, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 0, 0, 263, 264, 265, 266, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 0, 297, 298, 299, 300, 0, 863, 302, 303, - 304, 305, 306, 0, 307, 308, 0, 583, 309, 310, - 311, 0, 0, 312, 313, 314, 315, 316, 866, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 867, 331, 332, 333, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 346, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 366, 367, 368, 369, 370, 2084, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 26, 382, - 383, 384, 385, 386, 870, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 872, 412, 0, 413, 414, 31, 415, 416, 417, 418, - 419, 420, 421, 0, 422, 423, 0, 0, 424, 425, - 875, 427, 876, 0, 429, 430, 878, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 879, - 0, 442, 443, 444, 445, 446, 578, 448, 0, 449, - 450, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 34, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 0, 93, 35, 582, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2085, 0, + 286, 287, 288, 289, 290, 291, 292, 293, 920, 295, + 921, 297, 298, 299, 300, 0, 301, 302, 303, 304, + 923, 924, 306, 925, 308, 309, 310, 0, 311, 312, + 0, 0, 926, 314, 315, 0, 0, 316, 317, 318, + 319, 320, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 929, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 0, 386, 387, 388, 389, 390, 931, 392, + 393, 394, 395, 396, 397, 398, 399, 932, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 933, 417, 0, 418, 419, 0, + 420, 421, 422, 423, 424, 425, 426, 0, 934, 935, + 0, 0, 429, 430, 936, 432, 937, 938, 434, 435, + 939, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 940, 0, 448, 449, 450, 451, 452, + 453, 941, 0, 455, 456, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 483, 0, 0, 0, 0, + 0, 0, 0, 1709, 1710, 0, 0, 93, 883, 582, + 884, 885, 1711, 887, 888, 0, 0, 0, 0, 949, + 950, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 110, 111, 112, 113, 114, 890, 116, 891, 892, 0, + 119, 120, 121, 122, 123, 124, 893, 894, 125, 126, + 895, 896, 129, 0, 130, 131, 132, 133, 897, 0, + 898, 0, 136, 137, 138, 139, 140, 141, 142, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 152, 153, 154, 155, 899, 900, 901, 902, 903, 904, + 905, 161, 162, 163, 164, 165, 166, 167, 906, 907, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 712, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 909, 199, 200, 201, + 202, 203, 910, 911, 205, 0, 206, 207, 912, 209, + 0, 210, 0, 211, 212, 0, 213, 214, 215, 216, + 217, 218, 0, 219, 0, 913, 914, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 242, 243, 244, 245, 246, 247, 248, 915, 916, 0, + 917, 0, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 264, 265, 266, 0, + 267, 268, 269, 918, 919, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 920, + 295, 921, 297, 298, 299, 300, 0, 301, 302, 303, + 304, 923, 924, 306, 925, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 318, 319, 320, 927, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 928, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 929, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 370, 371, 372, + 373, 1852, 1853, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 931, + 392, 393, 394, 395, 396, 397, 398, 399, 932, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 933, 417, 0, 418, 419, + 0, 420, 421, 422, 423, 424, 425, 426, 0, 934, + 935, 0, 0, 429, 430, 936, 432, 937, 938, 434, + 435, 939, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 940, 0, 448, 449, 450, 451, + 452, 453, 941, 0, 455, 456, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 0, 0, 0, + 0, 0, 0, 0, 1854, 1855, 0, 0, 0, 0, + 0, 0, 0, 1711, 0, 0, 0, 0, 0, 0, + 949, 950, 93, 883, 582, 884, 885, 886, 887, 888, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, 110, 111, 112, 113, 114, - 115, 116, 117, 118, 0, 119, 120, 121, 122, 123, - 124, 0, 833, 125, 126, 127, 128, 129, 0, 130, - 131, 132, 133, 836, 0, 837, 0, 136, 137, 138, + 890, 116, 891, 892, 0, 119, 120, 121, 122, 123, + 124, 893, 894, 125, 126, 895, 896, 129, 0, 130, + 131, 132, 133, 897, 0, 898, 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, 152, 153, 154, 155, 838, - 839, 840, 841, 842, 843, 844, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 0, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 181, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 849, 0, 201, - 0, 202, 203, 204, 205, 0, 206, 0, 207, 208, - 0, 209, 210, 211, 212, 213, 214, 0, 215, 0, - 216, 217, 218, 0, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 0, 247, 0, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 2083, 0, - 259, 260, 261, 262, 0, 263, 264, 265, 857, 858, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 0, 297, 298, 299, 300, 0, 863, 302, 303, - 304, 305, 306, 0, 307, 308, 0, 583, 309, 310, - 311, 0, 0, 312, 313, 314, 315, 316, 866, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 867, 331, 332, 333, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 346, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 366, 367, 368, 369, 370, 2084, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 0, 382, - 383, 384, 385, 386, 870, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 872, 412, 0, 413, 414, 0, 415, 416, 417, 418, - 419, 420, 421, 0, 422, 423, 0, 0, 424, 425, - 875, 427, 876, 0, 429, 430, 878, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 879, - 0, 442, 443, 444, 445, 446, 447, 448, 0, 449, - 450, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 0, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 93, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 2085, 94, - 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, - 104, 0, 0, 0, 0, 0, 0, 0, 105, 106, - 0, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 0, 119, 120, 121, 122, 123, 124, - 0, 833, 125, 126, 127, 128, 129, 0, 130, 131, - 132, 133, 836, 0, 837, 0, 136, 137, 138, 139, - 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, - 149, 150, 151, 0, 152, 153, 154, 155, 838, 839, - 840, 841, 842, 843, 844, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 0, 167, 0, 168, 169, - 170, 171, 172, 173, 0, 174, 175, 176, 177, 178, - 0, 0, 179, 180, 181, 182, 183, 0, 184, 185, - 186, 0, 187, 188, 189, 0, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 849, 0, 201, 0, - 202, 203, 204, 205, 0, 206, 0, 207, 208, 0, - 209, 210, 211, 212, 213, 214, 0, 215, 0, 216, - 217, 218, 0, 219, 220, 221, 222, 223, 224, 225, - 226, 227, 228, 229, 230, 0, 231, 232, 233, 234, - 235, 236, 0, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 0, 247, 0, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 0, 0, 259, - 260, 261, 262, 0, 263, 264, 265, 857, 858, 266, - 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, - 0, 297, 298, 299, 300, 0, 863, 302, 303, 304, - 305, 306, 0, 307, 308, 0, 0, 309, 310, 311, - 0, 0, 312, 313, 314, 315, 316, 866, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, 0, 328, - 329, 867, 331, 332, 333, 334, 335, 336, 0, 337, - 338, 339, 340, 341, 342, 0, 343, 344, 345, 346, - 347, 348, 349, 350, 0, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 0, 364, - 365, 366, 367, 368, 369, 370, 2084, 372, 373, 374, - 375, 376, 377, 378, 379, 380, 381, 0, 382, 383, - 384, 385, 386, 870, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 0, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 872, - 412, 0, 413, 414, 0, 415, 416, 417, 418, 419, - 420, 421, 0, 422, 423, 0, 0, 424, 425, 875, - 427, 876, 0, 429, 430, 878, 432, 433, 434, 435, - 436, 0, 0, 437, 438, 439, 440, 441, 879, 0, - 442, 443, 444, 445, 446, 447, 448, 0, 449, 450, - 451, 452, 453, 454, 455, 0, 0, 456, 0, 0, - 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, - 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, - 477, 93, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 36, 94, 95, - 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, - 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 0, 119, 120, 121, 122, 123, 124, 0, - 833, 125, 126, 127, 128, 129, 0, 130, 131, 132, - 133, 836, 0, 837, 0, 136, 137, 138, 139, 140, - 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, - 150, 151, 0, 152, 153, 154, 155, 838, 839, 840, - 841, 842, 843, 844, 157, 158, 159, 160, 161, 162, - 163, 164, 165, 166, 0, 167, 0, 168, 169, 170, - 171, 172, 173, 0, 174, 175, 176, 177, 178, 0, - 0, 179, 180, 181, 182, 183, 0, 184, 185, 186, - 0, 187, 188, 189, 0, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 849, 0, 201, 0, 202, - 203, 204, 205, 0, 206, 0, 207, 208, 0, 209, - 210, 211, 212, 213, 214, 0, 215, 0, 216, 217, - 218, 0, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 0, 231, 232, 233, 234, 235, - 236, 0, 237, 238, 239, 240, 241, 242, 243, 244, - 245, 246, 0, 247, 0, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 0, 0, 259, 260, - 261, 262, 0, 263, 264, 265, 857, 858, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, 295, 296, 0, - 297, 298, 299, 300, 0, 863, 302, 303, 304, 305, - 306, 0, 307, 308, 0, 0, 309, 310, 311, 0, - 0, 312, 313, 314, 315, 316, 866, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 0, 328, 329, - 867, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 339, 340, 341, 342, 0, 343, 344, 345, 346, 347, - 348, 349, 350, 0, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 0, 364, 365, - 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 0, 382, 383, 384, - 385, 386, 870, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 0, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 872, 412, - 0, 413, 414, 0, 415, 416, 417, 418, 419, 420, - 421, 0, 422, 423, 0, 0, 424, 425, 875, 427, - 876, 0, 429, 430, 878, 432, 433, 434, 435, 436, - 0, 0, 437, 438, 439, 440, 441, 879, 0, 442, - 443, 444, 445, 446, 447, 448, 0, 449, 450, 451, - 452, 453, 454, 455, 0, 0, 456, 0, 0, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 749, 1243, 550, 0, 0, 0, 826, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2759, 94, 95, 96, - 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, - 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, - 108, 109, 0, 111, 112, 113, 750, 751, 0, 752, - 753, 0, 119, 120, 121, 122, 123, 124, 0, 0, - 125, 126, 754, 755, 129, 0, 130, 131, 132, 133, - 756, 0, 0, 0, 136, 137, 138, 139, 140, 141, - 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, - 151, 0, 0, 153, 154, 155, 0, 0, 0, 0, - 0, 0, 0, 157, 158, 159, 160, 161, 162, 163, - 757, 758, 166, 0, 167, 0, 168, 169, 170, 171, - 172, 173, 0, 174, 175, 176, 177, 178, 0, 0, - 179, 180, 181, 182, 183, 0, 184, 185, 186, 0, - 187, 188, 189, 0, 190, 191, 192, 193, 759, 195, - 196, 197, 198, 199, 760, 1244, 201, 0, 202, 203, - 761, 205, 0, 206, 0, 207, 0, 0, 0, 210, - 211, 762, 0, 214, 0, 215, 0, 763, 764, 218, - 0, 219, 220, 221, 222, 223, 224, 225, 0, 227, - 228, 229, 230, 0, 231, 232, 233, 234, 235, 236, - 0, 237, 0, 765, 240, 241, 242, 243, 244, 766, - 767, 0, 768, 0, 248, 0, 0, 251, 0, 253, - 254, 255, 256, 257, 258, 0, 0, 259, 0, 261, - 0, 0, 263, 264, 265, 0, 0, 266, 267, 268, - 269, 270, 769, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 770, 0, 771, 293, 294, 295, 772, 0, 297, - 298, 0, 300, 0, 773, 302, 774, 304, 305, 306, - 0, 307, 308, 1245, 0, 309, 310, 311, 0, 0, - 312, 775, 0, 315, 0, 776, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, 0, 328, 329, 777, - 331, 332, 778, 334, 335, 336, 0, 337, 338, 339, - 340, 341, 342, 0, 343, 344, 345, 779, 347, 348, - 349, 350, 0, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 0, 364, 365, 0, - 367, 368, 369, 780, 371, 372, 373, 374, 375, 376, - 377, 378, 379, 380, 381, 0, 382, 383, 384, 385, - 386, 0, 387, 781, 389, 390, 391, 0, 393, 394, - 782, 396, 0, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 783, 410, 784, 412, 0, - 413, 414, 0, 415, 0, 417, 418, 419, 420, 421, - 0, 785, 786, 0, 0, 424, 425, 787, 427, 788, - 1246, 429, 430, 789, 432, 433, 434, 435, 436, 0, - 0, 437, 438, 439, 440, 441, 0, 0, 442, 443, - 444, 445, 446, 1136, 791, 0, 449, 0, 451, 452, - 453, 454, 455, 0, 0, 456, 0, 0, 457, 458, - 459, 460, 461, 462, 792, 793, 794, 795, 796, 797, - 798, 799, 800, 801, 802, 474, 475, 476, 477, 749, - 0, 0, 0, 0, 0, 0, 1247, 1248, 1960, 0, - 0, 0, 0, 0, 0, 1961, 94, 95, 96, 97, - 98, 99, 100, 101, 0, 102, 103, 104, 3, 4, - 0, 0, 0, 0, 0, 105, 106, 0, 107, 108, - 109, 0, 111, 112, 113, 750, 751, 0, 752, 753, - 0, 119, 120, 121, 122, 123, 124, 0, 0, 125, - 126, 754, 755, 129, 0, 130, 131, 132, 133, 756, - 0, 0, 0, 136, 137, 138, 139, 140, 141, 0, - 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, - 0, 0, 153, 154, 155, 0, 0, 0, 0, 0, - 0, 0, 157, 158, 159, 160, 161, 162, 163, 757, - 758, 166, 0, 167, 0, 168, 169, 170, 171, 172, - 173, 0, 174, 175, 176, 177, 178, 0, 0, 179, - 180, 181, 182, 183, 0, 184, 185, 186, 0, 187, - 188, 189, 0, 190, 191, 192, 193, 759, 195, 196, - 197, 198, 199, 760, 0, 201, 0, 202, 203, 761, - 205, 0, 206, 0, 207, 0, 0, 0, 210, 211, - 762, 0, 214, 0, 215, 0, 763, 764, 218, 0, - 219, 220, 221, 222, 223, 224, 225, 0, 227, 228, - 229, 230, 0, 231, 232, 233, 234, 235, 236, 0, - 237, 0, 765, 240, 241, 242, 243, 244, 766, 767, - 0, 768, 0, 248, 0, 0, 251, 0, 253, 254, - 255, 256, 257, 258, 0, 0, 259, 0, 261, 0, - 0, 263, 264, 265, 0, 0, 266, 267, 268, 269, - 270, 769, 272, 273, 274, 275, 276, 277, 278, 279, + 148, 149, 150, 151, 0, 152, 153, 154, 155, 899, + 900, 901, 902, 903, 904, 905, 161, 162, 163, 164, + 165, 166, 167, 906, 907, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 712, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 909, 199, 200, 201, 202, 203, 910, 911, 205, + 0, 206, 207, 912, 209, 0, 210, 0, 211, 212, + 0, 213, 214, 215, 216, 217, 218, 0, 219, 0, + 913, 914, 222, 0, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 242, 243, 244, 245, 246, + 247, 248, 915, 916, 0, 917, 0, 252, 0, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 264, 265, 266, 0, 267, 268, 269, 918, 919, + 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 770, 0, 771, 293, 294, 295, 772, 0, 297, 298, - 0, 300, 0, 773, 302, 774, 304, 305, 306, 0, - 307, 308, 0, 0, 309, 310, 311, 0, 0, 312, - 775, 0, 315, 0, 776, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 0, 328, 329, 777, 331, - 332, 778, 334, 335, 336, 0, 337, 338, 339, 340, - 341, 342, 0, 343, 344, 345, 779, 347, 348, 349, - 350, 0, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 0, 364, 365, 0, 367, - 368, 369, 780, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 26, 382, 383, 384, 385, 386, - 0, 387, 781, 389, 390, 391, 0, 393, 394, 782, - 396, 0, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 783, 410, 784, 412, 0, 413, - 414, 31, 415, 0, 417, 418, 419, 420, 421, 0, - 785, 786, 0, 0, 424, 425, 787, 427, 788, 0, - 429, 430, 789, 432, 433, 434, 435, 436, 0, 0, - 437, 438, 439, 440, 441, 0, 0, 442, 443, 444, - 445, 446, 790, 791, 0, 449, 0, 451, 452, 453, - 454, 455, 0, 0, 456, 0, 34, 457, 458, 459, - 460, 461, 462, 792, 793, 794, 795, 796, 797, 798, - 799, 800, 801, 802, 474, 475, 476, 477, 500, 0, - 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 36, 94, 95, 96, 97, 98, - 99, 100, 101, 616, 102, 103, 104, 0, 0, 0, - 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, - 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, - 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, - 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, - 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 290, 291, 292, 293, 920, 295, 921, 297, 298, 299, + 300, 0, 301, 302, 303, 304, 923, 924, 306, 925, + 308, 309, 310, 0, 311, 312, 0, 0, 926, 314, + 315, 0, 0, 316, 317, 318, 319, 320, 927, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 928, 335, 336, 337, 338, 339, 340, 0, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 929, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 931, 392, 393, 394, 395, 396, + 397, 398, 399, 932, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, + 933, 417, 0, 418, 419, 0, 420, 421, 422, 423, + 424, 425, 426, 0, 934, 935, 0, 0, 429, 430, + 936, 432, 937, 938, 434, 435, 939, 437, 438, 439, + 440, 441, 0, 0, 442, 443, 444, 445, 446, 940, + 0, 448, 449, 450, 451, 452, 453, 941, 0, 455, + 456, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, 0, 0, 0, 0, 0, 0, 0, 1709, + 1710, 0, 0, 0, 0, 0, 0, 0, 1711, 0, + 0, 0, 0, 0, 0, 949, 950, 93, 883, 582, + 884, 885, 886, 887, 888, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 889, 0, 0, 105, 106, 0, 107, 108, 109, + 110, 111, 112, 113, 0, 890, 116, 891, 892, 0, + 119, 120, 121, 122, 123, 124, 893, 894, 125, 126, + 895, 896, 129, 0, 130, 131, 132, 133, 897, 0, + 898, 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, - 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, - 0, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 0, 167, 0, 168, 169, 170, 171, 172, 173, - 0, 174, 175, 176, 177, 178, 0, 0, 179, 180, - 181, 182, 183, 0, 184, 185, 186, 0, 187, 188, - 189, 0, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 0, 201, 0, 202, 203, 204, 205, - 0, 206, 0, 207, 0, 0, 0, 210, 211, 502, - 0, 214, 0, 215, 0, 216, 217, 218, 0, 219, - 220, 221, 222, 223, 224, 225, 0, 227, 228, 229, - 230, 0, 231, 232, 233, 234, 235, 236, 0, 237, - 0, 239, 240, 241, 242, 243, 244, 245, 246, 0, - 247, 0, 248, 0, 0, 251, 0, 253, 254, 255, - 256, 257, 258, 0, 0, 259, 0, 261, 0, 0, - 263, 264, 265, 0, 0, 266, 267, 268, 269, 270, - 503, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 0, 292, 293, 294, 295, 296, 0, 297, 298, 0, - 300, 0, 301, 302, 303, 304, 305, 306, 0, 307, - 308, 0, 0, 309, 310, 311, 0, 0, 312, 313, - 0, 315, 0, 317, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, 0, 328, 329, 330, 331, 332, - 333, 334, 335, 336, 0, 337, 338, 339, 340, 341, - 342, 0, 343, 344, 345, 346, 347, 348, 349, 350, - 0, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 0, 364, 365, 0, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - 379, 380, 381, 26, 382, 383, 384, 385, 386, 0, - 387, 388, 389, 390, 391, 0, 393, 394, 395, 396, - 0, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 505, 410, 411, 412, 0, 413, 414, - 31, 415, 0, 417, 418, 419, 420, 421, 0, 617, - 423, 0, 0, 618, 425, 426, 427, 428, 0, 429, - 430, 431, 432, 433, 434, 435, 436, 0, 0, 437, - 438, 439, 440, 441, 0, 0, 442, 443, 444, 445, - 446, 578, 448, 0, 449, 0, 451, 452, 453, 454, - 455, 0, 0, 456, 0, 34, 457, 458, 459, 460, - 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, - 471, 472, 473, 474, 475, 476, 477, 500, 0, 35, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 36, 94, 95, 96, 97, 98, 99, + 152, 153, 154, 155, 899, 900, 901, 902, 903, 904, + 905, 161, 162, 163, 164, 165, 166, 167, 906, 907, + 170, 908, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 712, 186, 187, 0, 188, 189, 190, 0, 191, 0, + 193, 0, 194, 195, 196, 197, 909, 199, 200, 201, + 202, 203, 910, 911, 205, 0, 206, 207, 912, 209, + 0, 210, 0, 211, 212, 0, 213, 214, 215, 216, + 0, 218, 0, 219, 0, 913, 914, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 242, 243, 244, 245, 246, 247, 248, 915, 916, 0, + 917, 0, 252, 0, 0, 255, 256, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 264, 265, 0, 0, + 267, 268, 269, 918, 919, 270, 271, 272, 273, 274, + 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 920, + 295, 921, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 923, 924, 306, 925, 308, 309, 310, 0, 311, + 312, 0, 0, 926, 314, 315, 0, 0, 316, 317, + 318, 319, 320, 927, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 928, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 929, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 370, 371, 372, + 373, 930, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 931, + 392, 393, 394, 395, 396, 0, 398, 399, 932, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 933, 417, 0, 418, 419, + 0, 420, 421, 422, 423, 424, 425, 426, 0, 934, + 935, 0, 0, 429, 430, 936, 432, 937, 938, 434, + 435, 939, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 940, 0, 448, 449, 450, 451, + 452, 453, 941, 0, 455, 456, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 0, 0, 0, + 0, 0, 0, 0, 943, 944, 506, 0, 0, 0, + 0, 946, 0, 947, 0, 0, 0, 0, 948, 0, + 949, 950, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, - 0, 0, 0, 105, 106, 0, 107, 108, 109, 0, + 0, 2403, 0, 105, 106, 0, 107, 108, 109, 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, 144, - 145, 0, 146, 147, 148, 149, 150, 151, 0, 0, + 145, 0, 146, 147, 148, 149, 150, 151, 0, -627, 153, 154, 155, 0, 0, 0, 0, 0, 0, 0, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 0, 167, 0, 168, 169, 170, 171, 172, 173, 0, - 174, 175, 176, 177, 178, 0, 0, 179, 180, 181, - 182, 183, 0, 184, 185, 186, 0, 187, 188, 189, - 0, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 0, 201, 0, 202, 203, 204, 205, 0, - 206, 0, 207, 0, 0, 0, 210, 211, 502, 0, - 214, 0, 215, 0, 216, 217, 218, 0, 219, 220, - 221, 222, 223, 224, 225, 0, 227, 228, 229, 230, - 0, 231, 232, 233, 234, 235, 236, 0, 237, 0, - 239, 240, 241, 242, 243, 244, 245, 246, 0, 247, - 0, 248, 0, 0, 251, 0, 253, 254, 255, 256, - 257, 258, 0, 0, 259, 0, 261, 0, 0, 263, - 264, 265, 0, 0, 266, 267, 268, 269, 270, 503, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 0, - 292, 293, 294, 295, 296, 0, 297, 298, 0, 300, - 0, 301, 302, 303, 304, 305, 306, 0, 307, 308, - 0, 0, 309, 310, 311, 0, 0, 312, 313, 0, - 315, 0, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 0, 328, 329, 330, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 339, 340, 341, 342, - 0, 343, 344, 345, 346, 347, 348, 349, 350, 0, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 0, 364, 365, 0, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 26, 382, 383, 384, 385, 386, 0, 387, - 388, 389, 390, 391, 0, 393, 394, 395, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 505, 410, 411, 412, 0, 413, 414, 31, - 415, 0, 417, 418, 419, 420, 421, 0, 422, 423, - 0, 0, 424, 425, 426, 427, 428, 0, 429, 430, - 431, 432, 433, 434, 435, 436, 0, 0, 437, 438, - 439, 440, 441, 0, 0, 442, 443, 444, 445, 446, - 578, 448, 0, 449, 0, 451, 452, 453, 454, 455, - 0, 0, 456, 0, 34, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 0, 500, 35, 582, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 0, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 185, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 198, 199, 200, 201, 202, + 203, 204, 0, 205, 0, 206, 207, 208, 209, 0, + 210, 0, 211, 0, 0, -627, 214, 215, 509, 0, + 218, 0, 219, 0, 220, 221, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 0, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, -627, + 243, 244, 245, 246, 247, 248, 249, 250, 0, 251, + 0, 252, 0, 0, 255, -627, 257, 258, 259, 260, + 261, 262, 0, 0, 263, -627, 265, 0, 0, 267, + 268, 269, 0, 0, 270, 271, 272, 273, 274, 510, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 294, -627, + 296, 297, 298, 299, 300, 0, 301, 302, 0, 304, + 0, 305, 306, 307, 308, 309, 310, 0, 311, 312, + 0, 0, 313, 314, 315, 0, 0, 316, 317, 0, + 319, 0, 321, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 334, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 350, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, -627, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 0, 386, 387, 388, 389, 390, 0, 392, + 393, 394, 395, 396, 0, 398, 399, 400, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 512, 415, 416, 417, 0, 418, 419, 0, + 420, -627, 422, 423, 424, 425, 426, 0, 427, 428, + 0, 0, 429, 430, 431, 432, 433, 0, 434, 435, + 436, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 0, 0, 448, 449, 450, 451, 452, + 453, 454, 0, 455, 0, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 483, 93, 0, 507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 36, 0, 94, 95, 96, 97, 98, 99, + 0, 0, 0, 1012, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, - 0, 0, 0, 105, 106, 0, 107, 108, 109, 0, - 111, 112, 113, 114, 115, 0, 117, 118, 0, 119, - 120, 121, 122, 123, 124, 0, 0, 125, 126, 127, - 128, 129, 0, 130, 131, 132, 133, 134, 0, 0, - 0, 136, 137, 138, 139, 140, 141, 0, 143, 144, - 145, 0, 146, 147, 148, 149, 150, 151, 0, 0, - 153, 154, 155, 0, 0, 0, 0, 0, 0, 0, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 0, 167, 0, 168, 169, 170, 171, 172, 173, 0, - 174, 175, 176, 177, 178, 0, 0, 179, 180, 181, - 182, 183, 0, 184, 185, 186, 0, 187, 188, 189, - 0, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 0, 201, 0, 202, 203, 204, 205, 0, - 206, 0, 207, 0, 0, 0, 210, 211, 502, 0, - 214, 0, 215, 0, 216, 217, 218, 0, 219, 220, - 221, 222, 223, 224, 225, 0, 227, 228, 229, 230, - 0, 231, 232, 233, 234, 235, 236, 0, 237, 0, - 239, 240, 241, 242, 243, 244, 245, 246, 0, 247, - 0, 248, 0, 0, 251, 0, 253, 254, 255, 256, - 257, 258, 0, 0, 259, 0, 261, 0, 0, 263, - 264, 265, 0, 0, 266, 267, 268, 269, 270, 503, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 0, - 292, 293, 294, 295, 296, 0, 297, 298, 0, 300, - 0, 301, 302, 303, 304, 305, 306, 0, 307, 308, - 0, 0, 309, 310, 311, 0, 0, 312, 313, 0, - 315, 0, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 0, 328, 329, 330, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 339, 340, 341, 342, - 0, 343, 344, 345, 346, 347, 348, 349, 350, 0, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 0, 364, 365, 0, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 0, 382, 383, 384, 385, 386, 0, 387, - 388, 389, 390, 391, 0, 393, 394, 395, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 505, 410, 411, 412, 0, 413, 414, 0, - 415, 0, 417, 418, 419, 420, 421, 0, 422, 423, - 0, 0, 424, 425, 426, 427, 428, 0, 429, 430, - 431, 432, 433, 434, 435, 436, 0, 0, 437, 438, - 439, 440, 441, 0, 0, 442, 443, 444, 445, 446, - 447, 448, 0, 449, 0, 451, 452, 453, 454, 455, - 0, 0, 456, 0, 0, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 500, 0, 582, 0, + 0, 0, 0, 105, 106, 0, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 0, 119, + 120, 121, 122, 123, 124, 0, 894, 125, 126, 127, + 128, 129, 0, 130, 131, 132, 133, 897, 0, 898, + 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, + 145, 0, 146, 147, 148, 149, 150, 151, 0, 152, + 153, 154, 155, 899, 900, 901, 902, 903, 904, 905, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 0, 171, 0, 172, 173, 174, 175, 176, 177, 0, + 178, 179, 180, 181, 182, 0, 0, 183, 184, 185, + 186, 187, 0, 188, 189, 190, 0, 191, 192, 193, + 0, 194, 195, 196, 197, 198, 199, 200, 201, 202, + 203, 910, 0, 205, 0, 206, 207, 208, 209, 0, + 210, 0, 211, 212, 0, 213, 214, 215, 216, 217, + 218, 0, 219, 0, 220, 221, 222, 0, 223, 224, + 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, + 0, 235, 236, 237, 238, 239, 240, 0, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 0, 251, + 0, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 2143, 0, 263, 264, 265, 266, 0, 267, + 268, 269, 918, 919, 270, 271, 272, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, + 296, 297, 298, 299, 300, 0, 301, 302, 303, 304, + 0, 924, 306, 307, 308, 309, 310, 0, 311, 312, + 0, 614, 313, 314, 315, 0, 0, 316, 317, 318, + 319, 320, 927, 322, 323, 324, 325, 326, 327, 328, + 329, 330, 331, 0, 332, 333, 928, 335, 336, 337, + 338, 339, 340, 0, 341, 342, 343, 344, 345, 346, + 0, 347, 348, 349, 350, 351, 352, 353, 354, 0, + 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, + 365, 366, 367, 0, 368, 369, 370, 371, 372, 373, + 374, 2144, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 26, 386, 387, 388, 389, 390, 931, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 0, + 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, 414, 415, 933, 417, 0, 418, 419, 31, + 420, 421, 422, 423, 424, 425, 426, 0, 427, 428, + 0, 0, 429, 430, 936, 432, 937, 0, 434, 435, + 939, 437, 438, 439, 440, 441, 0, 0, 442, 443, + 444, 445, 446, 940, 0, 448, 449, 450, 451, 452, + 610, 454, 0, 455, 456, 457, 458, 459, 460, 461, + 0, 0, 462, 0, 34, 463, 464, 465, 466, 467, + 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, + 478, 479, 480, 481, 482, 483, 0, 0, 35, 780, + 1302, 582, 0, 0, 0, 887, 0, 0, 0, 0, + 0, 0, 2145, 0, 0, 0, 0, 94, 95, 96, + 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, + 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, + 108, 109, 781, 111, 112, 113, 782, 783, 784, 785, + 786, 0, 119, 120, 121, 122, 123, 124, 0, 0, + 125, 126, 787, 788, 129, 0, 130, 131, 132, 133, + 789, 0, 790, 0, 136, 137, 138, 139, 140, 141, + 791, 143, 144, 145, 0, 146, 147, 148, 149, 150, + 151, 0, 792, 153, 154, 155, 793, 794, 795, 796, + 0, 0, 797, 161, 162, 163, 164, 165, 166, 167, + 798, 799, 170, 0, 171, 0, 172, 173, 174, 175, + 176, 177, 0, 178, 179, 180, 181, 182, 0, 0, + 183, 184, 185, 186, 187, 0, 188, 189, 190, 0, + 191, 192, 193, 0, 194, 195, 196, 197, 800, 199, + 200, 201, 202, 203, 801, 1303, 205, 0, 206, 207, + 802, 209, 0, 210, 0, 211, 803, 0, 804, 214, + 215, 805, 806, 218, 0, 219, 0, 807, 808, 222, + 0, 223, 224, 225, 226, 227, 228, 229, 809, 231, + 232, 233, 234, 0, 235, 236, 237, 238, 239, 240, + 0, 241, 810, 811, 244, 245, 246, 247, 248, 812, + 813, 0, 814, 0, 252, 815, 816, 255, 817, 257, + 258, 259, 260, 261, 262, 0, 0, 263, 818, 265, + 819, 0, 267, 268, 269, 0, 0, 270, 271, 272, + 273, 274, 820, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 821, 822, 823, 297, 298, 299, 824, 0, 301, + 302, 825, 304, 0, 826, 306, 827, 308, 309, 310, + 0, 311, 312, 1304, 0, 313, 314, 315, 0, 0, + 316, 828, 829, 319, 830, 831, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 0, 332, 333, 832, + 335, 336, 833, 338, 339, 340, 0, 341, 342, 343, + 344, 345, 346, 0, 347, 348, 349, 834, 351, 352, + 353, 354, 0, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 0, 368, 369, 835, + 371, 372, 373, 836, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, 0, 386, 387, 388, 389, + 390, 837, 392, 838, 394, 395, 396, 839, 398, 399, + 840, 401, 0, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 841, 415, 842, 417, 0, + 418, 419, 0, 420, 843, 422, 423, 424, 425, 426, + 0, 844, 845, 0, 0, 429, 430, 846, 432, 847, + 1305, 434, 435, 848, 437, 438, 439, 440, 441, 0, + 0, 442, 443, 444, 445, 446, 849, 0, 448, 449, + 450, 451, 452, 1197, 851, 0, 455, 852, 457, 458, + 459, 460, 461, 0, 0, 462, 0, 0, 463, 464, + 465, 466, 467, 468, 853, 854, 855, 856, 857, 858, + 859, 860, 861, 862, 863, 480, 481, 482, 483, 93, + 0, 507, 0, 0, 0, 0, 1306, 1307, 2021, 0, + 0, 0, 0, 0, 0, 2022, 0, 94, 95, 96, + 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, + 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 0, 119, 120, 121, 122, 123, 124, 0, 894, + 125, 126, 127, 128, 129, 0, 130, 131, 132, 133, + 897, 0, 898, 0, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 0, 146, 147, 148, 149, 150, + 151, 0, 152, 153, 154, 155, 899, 900, 901, 902, + 903, 904, 905, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 0, 171, 0, 172, 173, 174, 175, + 176, 177, 0, 178, 179, 180, 181, 182, 0, 0, + 183, 184, 185, 186, 187, 0, 188, 189, 190, 0, + 191, 192, 193, 0, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 910, 0, 205, 0, 206, 207, + 208, 209, 0, 210, 0, 211, 212, 0, 213, 214, + 215, 216, 217, 218, 0, 219, 0, 220, 221, 222, + 0, 223, 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 0, 235, 236, 237, 238, 239, 240, + 0, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 0, 251, 0, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 2143, 0, 263, 264, 265, + 266, 0, 267, 268, 269, 918, 919, 270, 271, 272, + 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 295, 296, 297, 298, 299, 300, 0, 301, + 302, 303, 304, 0, 924, 306, 307, 308, 309, 310, + 0, 311, 312, 0, 614, 313, 314, 315, 0, 0, + 316, 317, 318, 319, 320, 927, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 0, 332, 333, 928, + 335, 336, 337, 338, 339, 340, 0, 341, 342, 343, + 344, 345, 346, 0, 347, 348, 349, 350, 351, 352, + 353, 354, 0, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 0, 368, 369, 370, + 371, 372, 373, 374, 2144, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, 0, 386, 387, 388, 389, + 390, 931, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 401, 0, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 933, 417, 0, + 418, 419, 0, 420, 421, 422, 423, 424, 425, 426, + 0, 427, 428, 0, 0, 429, 430, 936, 432, 937, + 0, 434, 435, 939, 437, 438, 439, 440, 441, 0, + 0, 442, 443, 444, 445, 446, 940, 0, 448, 449, + 450, 451, 452, 610, 454, 0, 455, 456, 457, 458, + 459, 460, 461, 0, 0, 462, 0, 0, 463, 464, + 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, + 475, 476, 477, 478, 479, 480, 481, 482, 483, 780, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 930, 94, 95, 96, 97, 98, 99, 100, - 101, 0, 102, 103, 104, 0, 0, 0, 0, 0, - 0, 0, 105, 106, 0, 107, 108, 109, 0, 111, - 112, 113, 114, 115, 0, 117, 118, 0, 119, 120, - 121, 122, 123, 124, 0, 0, 125, 126, 127, 128, - 129, 0, 130, 131, 132, 133, 134, 0, 0, 0, - 136, 137, 138, 139, 140, 141, 0, 143, 144, 145, - 0, 146, 147, 148, 149, 150, 151, 0, 0, 153, - 154, 155, 0, 0, 0, 0, 0, 0, 0, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 0, - 167, 0, 168, 169, 170, 171, 172, 173, 0, 174, - 175, 176, 177, 178, 0, 0, 179, 180, 181, 182, - 183, 0, 184, 185, 186, 0, 187, 188, 189, 0, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 0, 201, 0, 202, 203, 204, 205, 0, 206, - 0, 207, 0, 0, 0, 210, 211, 502, 0, 214, - 0, 215, 0, 216, 217, 218, 0, 219, 220, 221, - 222, 223, 224, 225, 0, 227, 228, 229, 230, 0, - 231, 232, 233, 234, 235, 236, 0, 237, 0, 239, - 240, 241, 242, 243, 244, 245, 246, 0, 247, 0, - 248, 0, 0, 251, 0, 253, 254, 255, 256, 257, - 258, 0, 0, 259, 0, 261, 0, 0, 263, 264, - 265, 0, 0, 266, 267, 268, 269, 270, 503, 272, + 0, 0, 0, 0, 0, 2145, 0, 94, 95, 96, + 97, 98, 99, 100, 101, 0, 102, 103, 104, 3, + 4, 0, 0, 0, 0, 0, 105, 106, 0, 107, + 108, 109, 781, 111, 112, 113, 782, 783, 784, 785, + 786, 0, 119, 120, 121, 122, 123, 124, 0, 0, + 125, 126, 787, 788, 129, 0, 130, 131, 132, 133, + 789, 0, 790, 0, 136, 137, 138, 139, 140, 141, + 791, 143, 144, 145, 0, 146, 147, 148, 149, 150, + 151, 0, 792, 153, 154, 155, 793, 794, 795, 796, + 0, 0, 797, 161, 162, 163, 164, 165, 166, 167, + 798, 799, 170, 0, 171, 0, 172, 173, 174, 175, + 176, 177, 0, 178, 179, 180, 181, 182, 0, 0, + 183, 184, 185, 186, 187, 0, 188, 189, 190, 0, + 191, 192, 193, 0, 194, 195, 196, 197, 800, 199, + 200, 201, 202, 203, 801, 0, 205, 0, 206, 207, + 802, 209, 0, 210, 0, 211, 803, 0, 804, 214, + 215, 805, 806, 218, 0, 219, 0, 807, 808, 222, + 0, 223, 224, 225, 226, 227, 228, 229, 809, 231, + 232, 233, 234, 0, 235, 236, 237, 238, 239, 240, + 0, 241, 810, 811, 244, 245, 246, 247, 248, 812, + 813, 0, 814, 0, 252, 815, 816, 255, 817, 257, + 258, 259, 260, 261, 262, 0, 0, 263, 818, 265, + 819, 0, 267, 268, 269, 0, 0, 270, 271, 272, + 273, 274, 820, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 821, 822, 823, 297, 298, 299, 824, 0, 301, + 302, 825, 304, 0, 826, 306, 827, 308, 309, 310, + 0, 311, 312, 0, 0, 313, 314, 315, 0, 0, + 316, 828, 829, 319, 830, 831, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 0, 332, 333, 832, + 335, 336, 833, 338, 339, 340, 0, 341, 342, 343, + 344, 345, 346, 0, 347, 348, 349, 834, 351, 352, + 353, 354, 0, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 0, 368, 369, 835, + 371, 372, 373, 836, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, 26, 386, 387, 388, 389, + 390, 837, 392, 838, 394, 395, 396, 839, 398, 399, + 840, 401, 0, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 841, 415, 842, 417, 0, + 418, 419, 31, 420, 843, 422, 423, 424, 425, 426, + 0, 844, 845, 0, 0, 429, 430, 846, 432, 847, + 0, 434, 435, 848, 437, 438, 439, 440, 441, 0, + 0, 442, 443, 444, 445, 446, 849, 0, 448, 449, + 450, 451, 452, 850, 851, 0, 455, 852, 457, 458, + 459, 460, 461, 0, 0, 462, 0, 34, 463, 464, + 465, 466, 467, 468, 853, 854, 855, 856, 857, 858, + 859, 860, 861, 862, 863, 480, 481, 482, 483, 93, + 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 36, 0, 94, 95, 96, + 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, + 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 0, 119, 120, 121, 122, 123, 124, 0, 894, + 125, 126, 127, 128, 129, 0, 130, 131, 132, 133, + 897, 0, 898, 0, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 0, 146, 147, 148, 149, 150, + 151, 0, 152, 153, 154, 155, 899, 900, 901, 902, + 903, 904, 905, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 0, 171, 0, 172, 173, 174, 175, + 176, 177, 0, 178, 179, 180, 181, 182, 0, 0, + 183, 184, 185, 186, 187, 0, 188, 189, 190, 0, + 191, 192, 193, 0, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 910, 0, 205, 0, 206, 207, + 208, 209, 0, 210, 0, 211, 212, 0, 213, 214, + 215, 216, 217, 218, 0, 219, 0, 220, 221, 222, + 0, 223, 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 0, 235, 236, 237, 238, 239, 240, + 0, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 0, 251, 0, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 0, 0, 263, 264, 265, + 266, 0, 267, 268, 269, 918, 919, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 290, 0, 292, - 293, 294, 295, 296, 0, 297, 298, 0, 300, 0, - 301, 302, 303, 304, 305, 306, 0, 307, 308, 0, - 0, 309, 310, 311, 0, 0, 312, 313, 0, 315, - 0, 317, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 0, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 339, 340, 341, 342, 0, - 343, 344, 345, 346, 347, 348, 349, 350, 0, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 0, 364, 365, 0, 367, 368, 369, 370, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 295, 296, 297, 298, 299, 300, 0, 301, + 302, 303, 304, 0, 924, 306, 307, 308, 309, 310, + 0, 311, 312, 0, 0, 313, 314, 315, 0, 0, + 316, 317, 318, 319, 320, 927, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 0, 332, 333, 928, + 335, 336, 337, 338, 339, 340, 0, 341, 342, 343, + 344, 345, 346, 0, 347, 348, 349, 350, 351, 352, + 353, 354, 0, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 0, 368, 369, 370, + 371, 372, 373, 374, 2144, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, 0, 386, 387, 388, 389, + 390, 931, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 401, 0, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 933, 417, 0, + 418, 419, 0, 420, 421, 422, 423, 424, 425, 426, + 0, 427, 428, 0, 0, 429, 430, 936, 432, 937, + 0, 434, 435, 939, 437, 438, 439, 440, 441, 0, + 0, 442, 443, 444, 445, 446, 940, 0, 448, 449, + 450, 451, 452, 453, 454, 0, 455, 456, 457, 458, + 459, 460, 461, 0, 0, 462, 0, 0, 463, 464, + 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, + 475, 476, 477, 478, 479, 480, 481, 482, 483, 93, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 36, 0, 94, 95, 96, + 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, + 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, + 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, + 118, 0, 119, 120, 121, 122, 123, 124, 0, 894, + 125, 126, 127, 128, 129, 0, 130, 131, 132, 133, + 897, 0, 898, 0, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 0, 146, 147, 148, 149, 150, + 151, 0, 152, 153, 154, 155, 899, 900, 901, 902, + 903, 904, 905, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 0, 171, 0, 172, 173, 174, 175, + 176, 177, 0, 178, 179, 180, 181, 182, 0, 0, + 183, 184, 185, 186, 187, 0, 188, 189, 190, 0, + 191, 192, 193, 0, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 910, 0, 205, 0, 206, 207, + 208, 209, 0, 210, 0, 211, 212, 0, 213, 214, + 215, 216, 217, 218, 0, 219, 0, 220, 221, 222, + 0, 223, 224, 225, 226, 227, 228, 229, 230, 231, + 232, 233, 234, 0, 235, 236, 237, 238, 239, 240, + 0, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 0, 251, 0, 252, 253, 254, 255, 256, 257, + 258, 259, 260, 261, 262, 0, 0, 263, 264, 265, + 266, 0, 267, 268, 269, 918, 919, 270, 271, 272, + 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 295, 296, 297, 298, 299, 300, 0, 301, + 302, 303, 304, 0, 924, 306, 307, 308, 309, 310, + 0, 311, 312, 0, 0, 313, 314, 315, 0, 0, + 316, 317, 318, 319, 320, 927, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 0, 332, 333, 928, + 335, 336, 337, 338, 339, 340, 0, 341, 342, 343, + 344, 345, 346, 0, 347, 348, 349, 350, 351, 352, + 353, 354, 0, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 0, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, - 381, 0, 382, 383, 384, 385, 386, 0, 387, 388, - 389, 390, 391, 0, 393, 394, 395, 396, 0, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 505, 410, 411, 412, 0, 413, 414, 0, 415, - 0, 417, 418, 419, 420, 421, 0, 422, 423, 0, - 0, 424, 425, 426, 427, 428, 0, 429, 430, 431, - 432, 433, 434, 435, 436, 0, 0, 437, 438, 439, - 440, 441, 0, 0, 442, 443, 444, 445, 446, 447, - 448, 0, 449, 0, 451, 452, 453, 454, 455, 0, - 0, 456, 0, 0, 457, 458, 459, 460, 461, 462, - 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, - 473, 474, 475, 476, 477, 500, 0, 0, 0, 0, + 381, 382, 383, 384, 385, 0, 386, 387, 388, 389, + 390, 931, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 401, 0, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 414, 415, 933, 417, 0, + 418, 419, 0, 420, 421, 422, 423, 424, 425, 426, + 0, 427, 428, 0, 0, 429, 430, 936, 432, 937, + 0, 434, 435, 939, 437, 438, 439, 440, 441, 0, + 0, 442, 443, 444, 445, 446, 940, 0, 448, 449, + 450, 451, 452, 453, 454, 0, 455, 456, 457, 458, + 459, 460, 461, 0, 0, 462, 0, 0, 463, 464, + 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, + 475, 476, 477, 478, 479, 480, 481, 482, 483, 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 2597, 94, 95, 96, 97, 98, 99, 100, 101, - 0, 102, 103, 104, 0, 0, 0, 0, 0, 0, - 0, 105, 106, 0, 107, 108, 109, 0, 111, 112, - 113, 114, 115, 0, 117, 118, 0, 119, 120, 121, - 122, 123, 124, 0, 0, 125, 126, 127, 128, 129, - 0, 130, 131, 132, 133, 134, 0, 0, 0, 136, - 137, 138, 139, 140, 141, 0, 143, 144, 145, 0, - 146, 147, 148, 149, 150, 151, 0, 0, 153, 154, - 155, 0, 0, 0, 0, 0, 0, 0, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 0, 167, - 0, 168, 169, 170, 171, 172, 173, 0, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 181, 182, 183, - 0, 184, 185, 186, 0, 187, 188, 189, 0, 190, - 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 0, 201, 0, 202, 203, 204, 205, 0, 206, 0, - 207, 0, 0, 0, 210, 211, 502, 0, 214, 0, - 215, 0, 216, 217, 218, 0, 219, 220, 221, 222, - 223, 224, 225, 0, 227, 228, 229, 230, 0, 231, - 232, 233, 234, 235, 236, 0, 237, 0, 239, 240, - 241, 242, 243, 244, 245, 246, 0, 247, 0, 248, - 0, 0, 251, 0, 253, 254, 255, 256, 257, 258, - 0, 0, 259, 0, 261, 0, 0, 263, 264, 265, - 0, 0, 266, 267, 268, 269, 270, 503, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 0, 292, 293, - 294, 295, 296, 0, 297, 298, 0, 300, 0, 301, - 302, 303, 304, 305, 306, 0, 307, 308, 0, 0, - 309, 310, 311, 0, 0, 312, 313, 0, 315, 0, - 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 0, 328, 329, 330, 331, 332, 333, 334, 335, - 336, 0, 337, 338, 339, 340, 341, 342, 0, 343, - 344, 345, 346, 347, 348, 349, 350, 0, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 0, 364, 365, 0, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 0, 382, 383, 384, 385, 386, 0, 387, 388, 389, - 390, 391, 0, 393, 394, 395, 396, 0, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 505, 410, 411, 412, 0, 413, 414, 0, 415, 0, - 417, 418, 419, 420, 421, 0, 422, 423, 0, 0, - 424, 425, 426, 427, 428, 0, 429, 430, 431, 432, - 433, 434, 435, 436, 0, 0, 437, 438, 439, 440, - 441, 0, 0, 442, 443, 444, 445, 446, 447, 448, - 0, 449, 0, 451, 452, 453, 454, 455, 0, 0, - 456, 0, 0, 457, 458, 459, 460, 461, 462, 463, + 0, 0, 0, 0, 0, 2820, 0, 94, 95, 96, + 97, 98, 99, 100, 101, 647, 102, 103, 104, 0, + 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, + 108, 109, 0, 111, 112, 113, 114, 115, 0, 117, + 118, 0, 119, 120, 121, 122, 123, 124, 0, 0, + 125, 126, 127, 128, 129, 0, 130, 131, 132, 133, + 134, 0, 0, 0, 136, 137, 138, 139, 140, 141, + 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, + 151, 0, 0, 153, 154, 155, 0, 0, 0, 0, + 0, 0, 0, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 0, 171, 0, 172, 173, 174, 175, + 176, 177, 0, 178, 179, 180, 181, 182, 0, 0, + 183, 184, 185, 186, 187, 0, 188, 189, 190, 0, + 191, 192, 193, 0, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 0, 205, 0, 206, 207, + 208, 209, 0, 210, 0, 211, 0, 0, 0, 214, + 215, 509, 0, 218, 0, 219, 0, 220, 221, 222, + 0, 223, 224, 225, 226, 227, 228, 229, 0, 231, + 232, 233, 234, 0, 235, 236, 237, 238, 239, 240, + 0, 241, 0, 243, 244, 245, 246, 247, 248, 249, + 250, 0, 251, 0, 252, 0, 0, 255, 0, 257, + 258, 259, 260, 261, 262, 0, 0, 263, 0, 265, + 0, 0, 267, 268, 269, 0, 0, 270, 271, 272, + 273, 274, 510, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 0, 296, 297, 298, 299, 300, 0, 301, + 302, 0, 304, 0, 305, 306, 307, 308, 309, 310, + 0, 311, 312, 0, 0, 313, 314, 315, 0, 0, + 316, 317, 0, 319, 0, 321, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 0, 332, 333, 334, + 335, 336, 337, 338, 339, 340, 0, 341, 342, 343, + 344, 345, 346, 0, 347, 348, 349, 350, 351, 352, + 353, 354, 0, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 0, 368, 369, 0, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, 26, 386, 387, 388, 389, + 390, 0, 392, 393, 394, 395, 396, 0, 398, 399, + 400, 401, 0, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 512, 415, 416, 417, 0, + 418, 419, 31, 420, 0, 422, 423, 424, 425, 426, + 0, 648, 428, 0, 0, 649, 430, 431, 432, 433, + 0, 434, 435, 436, 437, 438, 439, 440, 441, 0, + 0, 442, 443, 444, 445, 446, 0, 0, 448, 449, + 450, 451, 452, 610, 454, 0, 455, 0, 457, 458, + 459, 460, 461, 0, 0, 462, 0, 34, 463, 464, + 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, + 475, 476, 477, 478, 479, 480, 481, 482, 483, 506, + 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 36, 0, 94, 95, 96, + 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, + 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, + 108, 109, 0, 111, 112, 113, 114, 115, 0, 117, + 118, 0, 119, 120, 121, 122, 123, 124, 0, 0, + 125, 126, 127, 128, 129, 0, 130, 131, 132, 133, + 134, 0, 0, 0, 136, 137, 138, 139, 140, 141, + 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, + 151, 0, 0, 153, 154, 155, 0, 0, 0, 0, + 0, 0, 0, 161, 162, 163, 164, 165, 166, 167, + 168, 169, 170, 0, 171, 0, 172, 173, 174, 175, + 176, 177, 0, 178, 179, 180, 181, 182, 0, 0, + 183, 184, 185, 186, 187, 0, 188, 189, 190, 0, + 191, 192, 193, 0, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 0, 205, 0, 206, 207, + 208, 209, 0, 210, 0, 211, 0, 0, 0, 214, + 215, 509, 0, 218, 0, 219, 0, 220, 221, 222, + 0, 223, 224, 225, 226, 227, 228, 229, 0, 231, + 232, 233, 234, 0, 235, 236, 237, 238, 239, 240, + 0, 241, 0, 243, 244, 245, 246, 247, 248, 249, + 250, 0, 251, 0, 252, 0, 0, 255, 0, 257, + 258, 259, 260, 261, 262, 0, 0, 263, 0, 265, + 0, 0, 267, 268, 269, 0, 0, 270, 271, 272, + 273, 274, 510, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 0, 296, 297, 298, 299, 300, 0, 301, + 302, 0, 304, 0, 305, 306, 307, 308, 309, 310, + 0, 311, 312, 0, 0, 313, 314, 315, 0, 0, + 316, 317, 0, 319, 0, 321, 322, 323, 324, 325, + 326, 327, 328, 329, 330, 331, 0, 332, 333, 334, + 335, 336, 337, 338, 339, 340, 0, 341, 342, 343, + 344, 345, 346, 0, 347, 348, 349, 350, 351, 352, + 353, 354, 0, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 0, 368, 369, 0, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, 26, 386, 387, 388, 389, + 390, 0, 392, 393, 394, 395, 396, 0, 398, 399, + 400, 401, 0, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, 512, 415, 416, 417, 0, + 418, 419, 31, 420, 0, 422, 423, 424, 425, 426, + 0, 427, 428, 0, 0, 429, 430, 431, 432, 433, + 0, 434, 435, 436, 437, 438, 439, 440, 441, 0, + 0, 442, 443, 444, 445, 446, 0, 0, 448, 449, + 450, 451, 452, 610, 454, 0, 455, 0, 457, 458, + 459, 460, 461, 0, 0, 462, 0, 34, 463, 464, + 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, + 475, 476, 477, 478, 479, 480, 481, 482, 483, 0, + 506, 35, 507, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 36, 0, 0, 94, 95, + 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, + 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, + 107, 108, 109, 0, 111, 112, 113, 114, 115, 0, + 117, 118, 0, 119, 120, 121, 122, 123, 124, 0, + 0, 125, 126, 127, 128, 129, 0, 130, 131, 132, + 133, 134, 0, 0, 0, 136, 137, 138, 139, 140, + 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, + 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, + 0, 0, 0, 0, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 0, 171, 0, 172, 173, 174, + 175, 176, 177, 0, 178, 179, 180, 181, 182, 0, + 0, 183, 184, 185, 186, 187, 0, 188, 189, 190, + 0, 191, 192, 193, 0, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 0, 205, 0, 206, + 207, 208, 209, 0, 210, 0, 211, 0, 0, 0, + 214, 215, 509, 0, 218, 0, 219, 0, 220, 221, + 222, 0, 223, 224, 225, 226, 227, 228, 229, 0, + 231, 232, 233, 234, 0, 235, 236, 237, 238, 239, + 240, 0, 241, 0, 243, 244, 245, 246, 247, 248, + 249, 250, 0, 251, 0, 252, 0, 0, 255, 0, + 257, 258, 259, 260, 261, 262, 0, 0, 263, 0, + 265, 0, 0, 267, 268, 269, 0, 0, 270, 271, + 272, 273, 274, 510, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 0, 296, 297, 298, 299, 300, 0, + 301, 302, 0, 304, 0, 305, 306, 307, 308, 309, + 310, 0, 311, 312, 0, 0, 313, 314, 315, 0, + 0, 316, 317, 0, 319, 0, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 0, 332, 333, + 334, 335, 336, 337, 338, 339, 340, 0, 341, 342, + 343, 344, 345, 346, 0, 347, 348, 349, 350, 351, + 352, 353, 354, 0, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 0, 368, 369, + 0, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, 382, 383, 384, 385, 0, 386, 387, 388, + 389, 390, 0, 392, 393, 394, 395, 396, 0, 398, + 399, 400, 401, 0, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 512, 415, 416, 417, + 0, 418, 419, 0, 420, 0, 422, 423, 424, 425, + 426, 0, 427, 428, 0, 0, 429, 430, 431, 432, + 433, 0, 434, 435, 436, 437, 438, 439, 440, 441, + 0, 0, 442, 443, 444, 445, 446, 0, 0, 448, + 449, 450, 451, 452, 453, 454, 0, 455, 0, 457, + 458, 459, 460, 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 500, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1669, 94, 95, 96, 97, 98, 99, 100, 101, 0, + 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, + 506, 0, 507, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 991, 0, 94, 95, + 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, + 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, + 107, 108, 109, 0, 111, 112, 113, 114, 115, 0, + 117, 118, 0, 119, 120, 121, 122, 123, 124, 0, + 0, 125, 126, 127, 128, 129, 0, 130, 131, 132, + 133, 134, 0, 0, 0, 136, 137, 138, 139, 140, + 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, + 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, + 0, 0, 0, 0, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 0, 171, 0, 172, 173, 174, + 175, 176, 177, 0, 178, 179, 180, 181, 182, 0, + 0, 183, 184, 185, 186, 187, 0, 188, 189, 190, + 0, 191, 192, 193, 0, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 0, 205, 0, 206, + 207, 208, 209, 0, 210, 0, 211, 0, 0, 0, + 214, 215, 509, 0, 218, 0, 219, 0, 220, 221, + 222, 0, 223, 224, 225, 226, 227, 228, 229, 0, + 231, 232, 233, 234, 0, 235, 236, 237, 238, 239, + 240, 0, 241, 0, 243, 244, 245, 246, 247, 248, + 249, 250, 0, 251, 0, 252, 0, 0, 255, 0, + 257, 258, 259, 260, 261, 262, 0, 0, 263, 0, + 265, 0, 0, 267, 268, 269, 0, 0, 270, 271, + 272, 273, 274, 510, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 0, 296, 297, 298, 299, 300, 0, + 301, 302, 0, 304, 0, 305, 306, 307, 308, 309, + 310, 0, 311, 312, 0, 0, 313, 314, 315, 0, + 0, 316, 317, 0, 319, 0, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 0, 332, 333, + 334, 335, 336, 337, 338, 339, 340, 0, 341, 342, + 343, 344, 345, 346, 0, 347, 348, 349, 350, 351, + 352, 353, 354, 0, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 0, 368, 369, + 0, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, 382, 383, 384, 385, 0, 386, 387, 388, + 389, 390, 0, 392, 393, 394, 395, 396, 0, 398, + 399, 400, 401, 0, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 512, 415, 416, 417, + 0, 418, 419, 0, 420, 0, 422, 423, 424, 425, + 426, 0, 427, 428, 0, 0, 429, 430, 431, 432, + 433, 0, 434, 435, 436, 437, 438, 439, 440, 441, + 0, 0, 442, 443, 444, 445, 446, 0, 0, 448, + 449, 450, 451, 452, 453, 454, 0, 455, 0, 457, + 458, 459, 460, 461, 0, 0, 462, 0, 0, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, + 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2660, 0, 94, 95, + 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, + 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, + 107, 108, 109, 0, 111, 112, 113, 114, 115, 0, + 117, 118, 0, 119, 120, 121, 122, 123, 124, 0, + 0, 125, 126, 127, 128, 129, 0, 130, 131, 132, + 133, 134, 0, 0, 0, 136, 137, 138, 139, 140, + 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, + 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, + 0, 0, 0, 0, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 0, 171, 0, 172, 173, 174, + 175, 176, 177, 0, 178, 179, 180, 181, 182, 0, + 0, 183, 184, 185, 186, 187, 0, 188, 189, 190, + 0, 191, 192, 193, 0, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 0, 205, 0, 206, + 207, 208, 209, 0, 210, 0, 211, 0, 0, 0, + 214, 215, 509, 0, 218, 0, 219, 0, 220, 221, + 222, 0, 223, 224, 225, 226, 227, 228, 229, 0, + 231, 232, 233, 234, 0, 235, 236, 237, 238, 239, + 240, 0, 241, 0, 243, 244, 245, 246, 247, 248, + 249, 250, 0, 251, 0, 252, 0, 0, 255, 0, + 257, 258, 259, 260, 261, 262, 0, 0, 263, 0, + 265, 0, 0, 267, 268, 269, 0, 0, 270, 271, + 272, 273, 274, 510, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 0, 296, 297, 298, 299, 300, 0, + 301, 302, 0, 304, 0, 305, 306, 307, 308, 309, + 310, 0, 311, 312, 0, 0, 313, 314, 315, 0, + 0, 316, 317, 0, 319, 0, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 0, 332, 333, + 334, 335, 336, 337, 338, 339, 340, 0, 341, 342, + 343, 344, 345, 346, 0, 347, 348, 349, 350, 351, + 352, 353, 354, 0, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 0, 368, 369, + 0, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, 382, 383, 384, 385, 0, 386, 387, 388, + 389, 390, 0, 392, 393, 394, 395, 396, 0, 398, + 399, 400, 401, 0, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 512, 415, 416, 417, + 0, 418, 419, 0, 420, 0, 422, 423, 424, 425, + 426, 0, 427, 428, 0, 0, 429, 430, 431, 432, + 433, 0, 434, 435, 436, 437, 438, 439, 440, 441, + 0, 0, 442, 443, 444, 445, 446, 0, 0, 448, + 449, 450, 451, 452, 453, 454, 0, 455, 0, 457, + 458, 459, 460, 461, 0, 0, 462, 0, 0, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, + 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1730, 0, 94, 95, + 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, + 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, + 107, 108, 109, 0, 111, 112, 113, 114, 115, 0, + 117, 118, 0, 119, 120, 121, 122, 123, 124, 0, + 0, 125, 126, 127, 128, 129, 0, 130, 131, 132, + 133, 134, 0, 0, 0, 136, 137, 138, 139, 140, + 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, + 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, + 0, 0, 0, 0, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 0, 171, 0, 172, 173, 174, + 175, 176, 177, 0, 178, 179, 180, 181, 182, 0, + 0, 183, 184, 185, 186, 187, 0, 188, 189, 190, + 0, 191, 192, 193, 0, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 0, 205, 0, 206, + 207, 208, 209, 0, 210, 0, 211, 0, 0, 0, + 214, 215, 509, 0, 218, 0, 219, 0, 220, 221, + 222, 0, 223, 224, 225, 226, 227, 228, 229, 0, + 231, 232, 233, 234, 0, 235, 236, 237, 238, 239, + 240, 0, 241, 0, 243, 244, 245, 246, 247, 248, + 249, 250, 0, 251, 0, 252, 0, 0, 255, 0, + 257, 258, 259, 260, 261, 262, 0, 0, 263, 0, + 265, 0, 0, 267, 268, 269, 0, 0, 270, 271, + 272, 273, 274, 510, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 0, 296, 297, 298, 299, 300, 0, + 301, 302, 0, 304, 0, 305, 306, 307, 308, 309, + 310, 0, 311, 312, 0, 0, 313, 314, 315, 0, + 0, 316, 317, 0, 319, 0, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 0, 332, 333, + 334, 335, 336, 337, 338, 339, 340, 0, 341, 342, + 343, 344, 345, 346, 0, 347, 348, 349, 350, 351, + 352, 353, 354, 0, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 0, 368, 369, + 0, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, 382, 383, 384, 385, 0, 386, 387, 388, + 389, 390, 0, 392, 393, 394, 395, 396, 0, 398, + 399, 400, 401, 0, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 512, 415, 416, 417, + 0, 418, 419, 0, 420, 0, 422, 423, 424, 425, + 426, 0, 427, 428, 0, 0, 429, 430, 431, 432, + 433, 0, 434, 435, 436, 437, 438, 439, 440, 441, + 0, 0, 442, 443, 444, 445, 446, 0, 0, 448, + 449, 450, 451, 452, 453, 454, 0, 455, 0, 457, + 458, 459, 460, 461, 0, 0, 462, 0, 0, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, + 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1837, 0, 94, 95, + 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, + 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, + 107, 108, 109, 0, 111, 112, 113, 114, 115, 0, + 117, 118, 0, 119, 120, 121, 122, 123, 124, 0, + 0, 125, 126, 127, 128, 129, 0, 130, 131, 132, + 133, 134, 0, 0, 0, 136, 137, 138, 139, 140, + 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, + 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, + 0, 0, 0, 0, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 0, 171, 0, 172, 173, 174, + 175, 176, 177, 0, 178, 179, 180, 181, 182, 0, + 0, 183, 184, 185, 186, 187, 0, 188, 189, 190, + 0, 191, 192, 193, 0, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 0, 205, 0, 206, + 207, 208, 209, 0, 210, 0, 211, 0, 0, 0, + 214, 215, 509, 0, 218, 0, 219, 0, 220, 221, + 222, 0, 223, 224, 225, 226, 227, 228, 229, 0, + 231, 232, 233, 234, 0, 235, 236, 237, 238, 239, + 240, 0, 241, 0, 243, 244, 245, 246, 247, 248, + 249, 250, 0, 251, 0, 252, 0, 0, 255, 0, + 257, 258, 259, 260, 261, 262, 0, 0, 263, 0, + 265, 0, 0, 267, 268, 269, 0, 0, 270, 271, + 272, 273, 274, 510, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 0, 296, 297, 298, 299, 300, 0, + 301, 302, 0, 304, 0, 305, 306, 307, 308, 309, + 310, 0, 311, 312, 0, 0, 313, 314, 315, 0, + 0, 316, 317, 0, 319, 0, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 0, 332, 333, + 334, 335, 336, 337, 338, 339, 340, 0, 341, 342, + 343, 344, 345, 346, 0, 347, 348, 349, 350, 351, + 352, 353, 354, 0, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 0, 368, 369, + 0, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, 382, 383, 384, 385, 0, 386, 387, 388, + 389, 390, 0, 392, 393, 394, 395, 396, 0, 398, + 399, 400, 401, 0, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 512, 415, 416, 417, + 0, 418, 419, 0, 420, 0, 422, 423, 424, 425, + 426, 0, 427, 428, 0, 0, 429, 430, 431, 432, + 433, 0, 434, 435, 436, 437, 438, 439, 440, 441, + 0, 0, 442, 443, 444, 445, 446, 0, 0, 448, + 449, 450, 451, 452, 453, 454, 0, 455, 0, 457, + 458, 459, 460, 461, 0, 0, 462, 0, 0, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, + 0, 0, 2509, 1302, 582, 0, 0, 1690, 887, 0, + 0, 0, 0, 0, 1691, 0, 2632, 1692, 1693, 1694, + 94, 95, 96, 97, 98, 99, 100, 101, 1130, 102, + 103, 104, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 105, + 106, 1138, 107, 108, 109, 2510, 111, 112, 113, 0, + 696, 2511, 698, 699, 1139, 119, 120, 121, 122, 123, + 124, 1140, 1141, 125, 126, 700, 701, 129, 1142, 130, + 131, 132, 133, 0, 1143, 2512, 1144, 136, 137, 138, + 139, 140, 141, 2513, 143, 144, 145, 1145, 146, 147, + 148, 149, 150, 151, 1146, 2514, 153, 154, 155, 2515, + 2516, 2517, 2518, 1147, 1148, 2519, 161, 162, 163, 164, + 165, 166, 167, 710, 711, 170, 1149, 171, 1150, 172, + 173, 174, 175, 176, 177, 1151, 178, 179, 180, 181, + 182, 1152, 1153, 183, 184, 712, 186, 187, 1154, 188, + 189, 190, 1155, 191, 192, 193, 1156, 194, 195, 196, + 197, 0, 199, 200, 201, 202, 203, 0, 1157, 205, + 1158, 206, 207, 713, 209, 1159, 210, 1160, 211, 2520, + 1161, 2521, 214, 215, 2522, 2523, 218, 1162, 219, 1163, + 0, 0, 222, 1164, 223, 224, 225, 226, 227, 228, + 229, 2524, 231, 232, 233, 234, 1165, 235, 236, 237, + 238, 239, 240, 1166, 241, 2525, 0, 244, 245, 246, + 247, 248, 720, 721, 1167, 722, 1168, 252, 2526, 2527, + 255, 2528, 257, 258, 259, 260, 261, 262, 1169, 1170, + 263, 2529, 265, 2530, 1171, 267, 268, 269, 1172, 1173, + 270, 271, 272, 273, 274, 2531, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 729, 2532, 731, 297, 298, 299, + 2533, 1174, 301, 302, 2534, 304, 1175, 0, 306, 733, + 308, 309, 310, 1176, 311, 312, 1177, 1178, 2535, 314, + 315, 1179, 1180, 316, 0, 2536, 319, 2537, 0, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 1181, + 332, 333, 0, 335, 336, 0, 338, 339, 340, 1182, + 341, 342, 343, 344, 345, 346, 1183, 347, 348, 349, + 736, 351, 352, 353, 354, 1184, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 1185, + 368, 369, 2538, 371, 372, 373, 738, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 1186, 386, + 387, 388, 389, 390, 2539, 392, 2540, 394, 395, 396, + 2541, 398, 399, 742, 401, 1187, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 2542, 415, + 0, 417, 1188, 418, 419, 1189, 420, 2543, 422, 423, + 424, 425, 426, 1190, 745, 746, 1191, 1192, 429, 430, + 0, 432, 0, 1193, 434, 435, 2544, 437, 438, 439, + 440, 441, 1194, 1195, 442, 443, 444, 445, 446, 2545, + 1196, 448, 449, 450, 451, 452, 0, 749, 1198, 455, + 2546, 457, 458, 459, 460, 461, 1199, 1200, 462, 1201, + 1202, 463, 464, 465, 466, 467, 468, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 480, 481, + 482, 483, 0, 506, 0, 1695, 1696, 1697, 1690, 2547, + 2548, 1700, 1701, 1702, 1703, 1691, 0, 0, 1692, 1693, + 1694, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, 119, 120, 121, 122, @@ -258343,902 +276618,852 @@ static const yytype_int16 yytable[] = 130, 131, 132, 133, 134, 0, 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 0, 153, 154, 155, - 0, 0, 0, 0, 0, 0, 0, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 0, 167, 0, - 168, 169, 170, 171, 172, 173, 0, 174, 175, 176, - 177, 178, 0, 0, 179, 180, 181, 182, 183, 0, - 184, 185, 186, 0, 187, 188, 189, 0, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 0, - 201, 0, 202, 203, 204, 205, 0, 206, 0, 207, - 0, 0, 0, 210, 211, 502, 0, 214, 0, 215, - 0, 216, 217, 218, 0, 219, 220, 221, 222, 223, - 224, 225, 0, 227, 228, 229, 230, 0, 231, 232, - 233, 234, 235, 236, 0, 237, 0, 239, 240, 241, - 242, 243, 244, 245, 246, 0, 247, 0, 248, 0, - 0, 251, 0, 253, 254, 255, 256, 257, 258, 0, - 0, 259, 0, 261, 0, 0, 263, 264, 265, 0, - 0, 266, 267, 268, 269, 270, 503, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 0, 292, 293, 294, - 295, 296, 0, 297, 298, 0, 300, 0, 301, 302, - 303, 304, 305, 306, 0, 307, 308, 0, 0, 309, - 310, 311, 0, 0, 312, 313, 0, 315, 0, 317, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 0, 328, 329, 330, 331, 332, 333, 334, 335, 336, - 0, 337, 338, 339, 340, 341, 342, 0, 343, 344, - 345, 346, 347, 348, 349, 350, 0, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 0, 364, 365, 0, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, 379, 380, 381, 0, - 382, 383, 384, 385, 386, 0, 387, 388, 389, 390, - 391, 0, 393, 394, 395, 396, 0, 397, 398, 399, - 400, 401, 402, 403, 404, 405, 406, 407, 408, 505, - 410, 411, 412, 0, 413, 414, 0, 415, 0, 417, - 418, 419, 420, 421, 0, 422, 423, 0, 0, 424, - 425, 426, 427, 428, 0, 429, 430, 431, 432, 433, - 434, 435, 436, 0, 0, 437, 438, 439, 440, 441, - 0, 0, 442, 443, 444, 445, 446, 447, 448, 0, - 449, 0, 451, 452, 453, 454, 455, 0, 0, 456, - 0, 0, 457, 458, 459, 460, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 500, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1774, - 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, - 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, - 106, 0, 107, 108, 109, 0, 111, 112, 113, 114, - 115, 0, 117, 118, 0, 119, 120, 121, 122, 123, - 124, 0, 0, 125, 126, 127, 128, 129, 0, 130, - 131, 132, 133, 134, 0, 0, 0, 136, 137, 138, - 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, - 0, 0, 0, 0, 0, 0, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 0, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 181, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 0, 201, - 0, 202, 203, 204, 205, 0, 206, 0, 207, 0, - 0, 0, 210, 211, 502, 0, 214, 0, 215, 0, - 216, 217, 218, 0, 219, 220, 221, 222, 223, 224, - 225, 0, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 0, 239, 240, 241, 242, - 243, 244, 245, 246, 0, 247, 0, 248, 0, 0, - 251, 0, 253, 254, 255, 256, 257, 258, 0, 0, - 259, 0, 261, 0, 0, 263, 264, 265, 0, 0, - 266, 267, 268, 269, 270, 503, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 0, 292, 293, 294, 295, - 296, 0, 297, 298, 0, 300, 0, 301, 302, 303, - 304, 305, 306, 0, 307, 308, 0, 0, 309, 310, - 311, 0, 0, 312, 313, 0, 315, 0, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 330, 331, 332, 333, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 346, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 0, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 0, 382, - 383, 384, 385, 386, 0, 387, 388, 389, 390, 391, - 0, 393, 394, 395, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 505, 410, - 411, 412, 0, 413, 414, 0, 415, 0, 417, 418, - 419, 420, 421, 0, 422, 423, 0, 0, 424, 425, - 426, 427, 428, 0, 429, 430, 431, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 0, - 0, 442, 443, 444, 445, 446, 447, 448, 0, 449, - 0, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 0, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 0, 0, 0, 0, 2450, 1243, 550, 0, - 0, 1629, 826, 0, 0, 0, 0, 0, 2569, 1630, - 1631, 1632, 1633, 94, 95, 96, 97, 98, 99, 100, - 101, 1063, 102, 103, 104, 1064, 1065, 1066, 1067, 1068, - 1069, 1070, 105, 106, 1071, 107, 108, 109, 2451, 111, - 112, 113, 0, 669, 2452, 671, 672, 1072, 119, 120, - 121, 122, 123, 124, 1073, 1074, 125, 126, 673, 674, - 129, 1075, 130, 131, 132, 133, 0, 1076, 2453, 1077, - 136, 137, 138, 139, 140, 141, 2454, 143, 144, 145, - 1078, 146, 147, 148, 149, 150, 151, 1079, 2455, 153, - 154, 155, 1080, 1081, 1082, 2456, 1083, 1084, 1085, 157, - 158, 159, 160, 161, 162, 163, 679, 680, 166, 1086, - 167, 1087, 168, 169, 170, 171, 172, 173, 1088, 174, - 175, 176, 177, 178, 1089, 1090, 179, 180, 681, 182, - 183, 1091, 184, 185, 186, 1092, 187, 188, 189, 1093, - 190, 191, 192, 193, 0, 195, 196, 197, 198, 199, - 0, 1094, 201, 1095, 202, 203, 682, 205, 1096, 206, - 1097, 207, 2457, 1098, 2458, 210, 211, 2459, 2460, 214, - 1099, 215, 1100, 0, 0, 218, 1101, 219, 220, 221, - 222, 223, 224, 225, 2461, 227, 228, 229, 230, 1102, - 231, 232, 233, 234, 235, 236, 1103, 237, 2462, 0, - 240, 241, 242, 243, 244, 689, 690, 1104, 691, 1105, - 248, 2463, 2464, 251, 2465, 253, 254, 255, 256, 257, - 258, 1106, 1107, 259, 2466, 261, 2467, 1108, 263, 264, - 265, 1109, 1110, 266, 267, 268, 269, 270, 2468, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 698, 2469, 700, - 293, 294, 295, 2470, 1111, 297, 298, 2471, 300, 1112, - 0, 302, 702, 304, 305, 306, 1113, 307, 308, 1114, - 1115, 2472, 310, 311, 1116, 1117, 312, 0, 2473, 315, - 2474, 0, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 1118, 328, 329, 0, 331, 332, 0, 334, - 335, 336, 1119, 337, 338, 339, 340, 341, 342, 1120, - 343, 344, 345, 705, 347, 348, 349, 350, 1121, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 1122, 364, 365, 2475, 367, 368, 369, 707, - 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, - 381, 1123, 382, 383, 384, 385, 386, 1124, 387, 2476, - 389, 390, 391, 2477, 393, 394, 710, 396, 1125, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 2478, 410, 0, 412, 1126, 413, 414, 1127, 415, - 2479, 417, 418, 419, 420, 421, 1128, 713, 714, 1129, - 1130, 424, 425, 0, 427, 0, 1131, 429, 430, 2480, - 432, 433, 434, 435, 436, 1132, 1133, 437, 438, 439, - 440, 441, 1134, 1135, 442, 443, 444, 445, 446, 0, - 716, 1137, 449, 2481, 451, 452, 453, 454, 455, 1138, - 1139, 456, 1140, 1141, 457, 458, 459, 460, 461, 462, + 0, 0, 0, 0, 0, 0, 0, 161, 162, 163, + 164, 165, 166, 167, 168, 169, 170, 0, 171, 0, + 172, 173, 174, 175, 176, 177, 0, 178, 179, 180, + 181, 182, 0, 0, 183, 184, 185, 186, 187, 0, + 188, 189, 190, 0, 191, 192, 193, 0, 194, 195, + 196, 197, 198, 199, 200, 201, 202, 203, 204, 0, + 205, 0, 206, 207, 208, 209, 0, 210, 0, 211, + 0, 0, 0, 214, 215, 509, 0, 218, 0, 219, + 0, 220, 221, 222, 0, 223, 224, 225, 226, 227, + 228, 229, 0, 231, 232, 233, 234, 0, 235, 236, + 237, 238, 239, 240, 0, 241, 0, 243, 244, 245, + 246, 247, 248, 249, 250, 0, 251, 0, 252, 0, + 0, 255, 0, 257, 258, 259, 260, 261, 262, 0, + 0, 263, 0, 265, 0, 0, 267, 268, 269, 0, + 0, 270, 271, 272, 273, 274, 510, 276, 277, 278, + 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, + 289, 290, 291, 292, 293, 294, 0, 296, 297, 298, + 299, 300, 0, 301, 302, 0, 304, 0, 305, 306, + 307, 308, 309, 310, 0, 311, 312, 0, 0, 313, + 314, 315, 0, 0, 316, 317, 0, 319, 0, 321, + 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, + 0, 332, 333, 334, 335, 336, 337, 338, 339, 340, + 0, 341, 342, 343, 344, 345, 346, 0, 347, 348, + 349, 350, 351, 352, 353, 354, 0, 355, 356, 357, + 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, + 0, 368, 369, 0, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, 0, + 386, 387, 388, 389, 390, 0, 392, 393, 394, 395, + 396, 0, 398, 399, 400, 401, 0, 402, 403, 404, + 405, 406, 407, 408, 409, 410, 411, 412, 413, 512, + 415, 416, 417, 0, 418, 419, 0, 420, 0, 422, + 423, 424, 425, 426, 0, 427, 428, 0, 0, 429, + 430, 431, 432, 433, 0, 434, 435, 436, 437, 438, + 439, 440, 441, 0, 0, 442, 443, 444, 445, 446, + 0, 0, 448, 449, 450, 451, 452, 453, 454, 0, + 455, 0, 457, 458, 459, 460, 461, 0, 0, 462, + 0, 0, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 483, 0, 0, 0, 1695, 1696, 1697, 0, + 1698, 1699, 1700, 1701, 1702, 1703, 1379, 0, 0, 1380, + 0, 0, 0, 1381, 1382, 1383, 1384, 1385, 1386, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 474, 475, 476, 477, 0, 500, 0, 1634, 1635, - 1636, 1629, 2482, 2483, 1639, 1640, 1641, 1642, 0, 1630, - 1631, 1632, 1633, 94, 95, 96, 97, 98, 99, 100, - 101, 0, 102, 103, 104, 0, 0, 0, 0, 0, - 0, 0, 105, 106, 0, 107, 108, 109, 0, 111, - 112, 113, 114, 115, 0, 117, 118, 0, 119, 120, - 121, 122, 123, 124, 0, 0, 125, 126, 127, 128, - 129, 0, 130, 131, 132, 133, 134, 0, 0, 0, - 136, 137, 138, 139, 140, 141, 0, 143, 144, 145, - 0, 146, 147, 148, 149, 150, 151, 0, 0, 153, - 154, 155, 0, 0, 0, 0, 0, 0, 0, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 0, - 167, 0, 168, 169, 170, 171, 172, 173, 0, 174, - 175, 176, 177, 178, 0, 0, 179, 180, 181, 182, - 183, 0, 184, 185, 186, 0, 187, 188, 189, 0, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 0, 201, 0, 202, 203, 204, 205, 0, 206, - 0, 207, 0, 0, 0, 210, 211, 502, 0, 214, - 0, 215, 0, 216, 217, 218, 0, 219, 220, 221, - 222, 223, 224, 225, 0, 227, 228, 229, 230, 0, - 231, 232, 233, 234, 235, 236, 0, 237, 0, 239, - 240, 241, 242, 243, 244, 245, 246, 0, 247, 0, - 248, 0, 0, 251, 0, 253, 254, 255, 256, 257, - 258, 0, 0, 259, 0, 261, 0, 0, 263, 264, - 265, 0, 0, 266, 267, 268, 269, 270, 503, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 290, 0, 292, - 293, 294, 295, 296, 0, 297, 298, 0, 300, 0, - 301, 302, 303, 304, 305, 306, 0, 307, 308, 0, - 0, 309, 310, 311, 0, 0, 312, 313, 0, 315, - 0, 317, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 0, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 339, 340, 341, 342, 0, - 343, 344, 345, 346, 347, 348, 349, 350, 0, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 0, 364, 365, 0, 367, 368, 369, 370, - 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, - 381, 0, 382, 383, 384, 385, 386, 0, 387, 388, - 389, 390, 391, 0, 393, 394, 395, 396, 0, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 505, 410, 411, 412, 0, 413, 414, 0, 415, - 0, 417, 418, 419, 420, 421, 0, 422, 423, 0, - 0, 424, 425, 426, 427, 428, 0, 429, 430, 431, - 432, 433, 434, 435, 436, 0, 0, 437, 438, 439, - 440, 441, 0, 0, 442, 443, 444, 445, 446, 447, - 448, 0, 449, 0, 451, 452, 453, 454, 455, 0, - 0, 456, 0, 0, 457, 458, 459, 460, 461, 462, - 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, - 473, 474, 475, 476, 477, 0, 0, 0, 1634, 1635, - 1636, 0, 1637, 1638, 1639, 1640, 1641, 1642, 1320, 0, - 0, 1321, 0, 0, 0, 1322, 1323, 1324, 1325, 1326, + 0, 0, 0, 1387, 0, 1379, 0, 0, 1380, 0, + 0, 1389, 1381, 1382, 1383, 1384, 1385, 1386, 1390, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1327, 0, 0, 1320, 0, 0, - 1321, 0, 1329, 0, 1322, 1323, 1324, 1325, 1326, 1330, + 0, 0, 1387, 0, 0, 0, 0, 0, 0, 0, + 1389, 1379, 0, 1391, 1380, 0, 0, 1390, 1381, 1382, + 1383, 1384, 1385, 1386, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1387, 0, + 1379, 0, 1391, 1380, 0, 0, 1389, 1381, 1382, 1383, + 1384, 1385, 1386, 1390, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1387, 0, 0, + 0, 0, 0, 0, 0, 1389, 0, 0, 1391, 0, + 0, 0, 1390, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1327, 0, 0, 0, 0, 0, 0, - 0, 1329, 1320, 0, 1331, 1321, 0, 0, 1330, 1322, - 1323, 1324, 1325, 1326, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1327, 0, - 0, 1320, 0, 1331, 1321, 0, 1329, 0, 1322, 1323, - 1324, 1325, 1326, 1330, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1327, 0, 0, - 0, 0, 0, 0, 0, 1329, 0, 0, 1331, 0, - 1320, 0, 1330, 1321, 0, 0, 0, 1322, 1323, 1324, - 1325, 1326, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1327, 1331, 0, 0, - 0, 0, 0, 0, 1329, 1332, 0, 0, 0, 0, - 0, 1330, 0, 0, 0, 0, 0, 0, 0, 0, - 1320, 1333, 0, 1321, 0, 0, 1334, 0, 1323, 0, - 0, 0, 0, 0, 1332, 0, 1331, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1335, 1336, - 1333, 0, 0, 0, 1329, 1334, 0, 0, 0, 0, - 0, -1773, 0, 1337, 0, 0, 0, 0, 0, 1332, - 0, 0, 0, 0, 0, 0, 0, 1335, 1336, 0, - 0, 0, 0, 0, 0, 1333, 1331, 0, 0, 0, - 1334, 0, 1337, 0, 0, 0, 0, 0, 1332, 0, - 0, 1338, 0, 0, 1339, 0, 0, 0, 0, 0, - 0, 0, 1335, 1336, 1333, 0, 0, 0, 1340, 1334, - 0, 1341, 0, 0, 0, 0, 0, 1337, 0, 0, - 1338, 0, 0, 1339, 0, 0, 0, 1332, 0, 0, - 0, 1335, 1336, 0, 0, 0, 0, 1340, 0, 0, - 1341, 0, 0, 1333, 0, 0, 1337, 0, 1334, 0, - 0, 0, 0, 0, 0, 1338, 0, 0, 1339, 0, + 0, 0, 0, 0, 0, 0, 0, 1391, 0, 0, + 0, 0, 0, 0, 1392, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1335, 1336, 1340, 0, 0, 1341, 0, -1773, 0, 0, - 0, 0, 0, 0, 1338, 1337, 0, 1339, 0, 0, - 0, 0, 0, -1773, 0, 0, 0, 0, -1773, 0, - 1342, 1340, 0, 0, 1341, 1320, 0, 0, 1321, 0, - 0, 0, 1322, 1323, 1324, 1325, 1326, 0, 0, 0, - 0, 0, 0, 1338, 0, 0, 1339, 0, 0, 1342, - 0, 1327, 0, 0, 0, -1773, 0, 0, 0, 1329, - 1340, 0, 0, 1341, 0, 0, 1330, 0, 0, 0, + 1393, 0, 0, 0, 0, 1394, 0, 0, 1379, 0, + 0, 1380, 0, 1392, 0, 1381, 1382, 1383, 1384, 1385, + 1386, 0, 0, 0, 0, 0, 0, 1395, 1396, 1393, + 0, 0, 0, 0, 1394, 1387, 0, 0, 0, 0, + 0, 0, 1397, 1389, 0, 0, 0, 0, 0, 1392, + 1390, 0, 0, 0, 0, 0, 1395, 1396, 0, 0, + 0, 0, 0, 0, 0, 1393, 0, 0, 0, 0, + 1394, 1397, 0, 0, 0, 1391, 0, 0, 1392, 0, + 1398, 0, 0, 1399, 0, 0, 0, 0, 0, 0, + 0, 0, 1395, 1396, 1393, 0, 0, 1400, 0, 1394, + 1401, 0, 0, 0, 0, 0, 0, 1397, 0, 1398, + 0, 0, 1399, 0, 0, 0, 0, 0, 0, 0, + 0, 1395, 1396, 0, 0, 0, 1400, 0, 0, 1401, + 0, 0, 0, 0, 0, 0, 1397, 0, 0, 0, + 0, 0, 0, 0, 0, 1398, 0, 0, 1399, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1342, 0, 0, 0, 0, 0, - 0, 1331, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1320, - 1340, 0, 1321, 1342, 0, 0, 1322, 1323, 1324, 1325, - 1326, 0, 1343, 0, 0, 1344, 1345, 1346, 0, 1347, - 1348, 1349, 1350, 1351, 1352, 1327, 0, 0, 0, 2266, - 0, 0, 0, 1329, 0, 0, 0, 0, 0, 0, - 1330, 1343, 1342, 0, 1344, 1345, 1346, 0, 1347, 1348, - 1349, 1350, 1351, 1352, 0, 0, 0, 0, 2308, 0, - 0, 0, 0, 1320, 0, 1331, 1321, 0, 0, 0, - 1322, 1323, 1324, 1325, 1326, 0, 1343, 0, 0, 1344, - 1345, 1346, 1332, 1347, 1348, 1349, 1350, 1351, 1352, 1327, - 0, 0, -1773, 2395, 0, 0, 0, 1329, 1333, 0, - 0, 0, 0, 1334, 1330, 1343, 0, 0, 1344, 1345, - 1346, 0, 1347, 1348, 1349, 1350, 1351, 1352, 0, 0, - 0, 0, 2544, 0, 1320, 1335, 1336, 1321, 0, 1331, - 0, 1322, 1323, 1324, 1325, 1326, 0, 0, 0, 0, - 1337, 0, 0, 0, 1343, 0, 0, 1344, 1345, 1346, - 1327, 1347, 1348, 1349, 1350, 1351, 1352, 0, 1329, 0, - 0, 2566, 0, 0, 0, 1330, 1332, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1338, 0, - 0, 1339, 1333, 0, 0, 0, 0, 1334, 0, 0, - 1331, 0, 0, 0, -1773, 1340, 0, 0, 1341, 0, - 0, 1347, 1348, 1349, 1350, 1351, 1352, 0, 0, 1335, - 1336, 0, 0, 0, 0, 0, 0, 669, 0, 671, - 672, 0, 0, 0, 1337, 0, 0, 0, 0, 0, - 1332, 0, 673, 674, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1333, 0, 0, 1320, - 0, 1334, 1321, 0, 0, 0, 1322, 1323, 1324, 1325, - 1326, 0, 1338, 0, 0, 1339, 0, 0, 0, 0, - 0, 0, 0, 1335, 1336, 1327, 0, 0, 0, 1340, - 679, 680, 1341, 1329, 0, 0, 0, 1342, 1337, 0, - 1330, 1332, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1523, 0, 0, 0, 0, 1333, 0, 0, - 1524, 0, 1334, 0, 0, 1331, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1338, 0, 0, 1339, - 682, 0, 0, 0, 1335, 1336, 0, 0, 0, 0, - 0, 0, 0, 1340, 0, 0, 1341, 0, 0, 1337, + 0, 0, 1400, 0, 0, 1401, 0, 0, 0, 0, + 0, 0, 0, 0, 1398, 0, 1392, 1399, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1402, + 0, 1400, 1393, 0, 1401, 0, 0, 1394, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1402, 1395, + 1396, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1397, 0, 0, 0, 1379, 0, + 0, 1380, 0, 0, 0, 1381, 1382, 1383, 1384, 1385, + 1386, 0, 0, 0, 1402, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1387, 0, 0, 0, 0, + 0, 0, 1398, 1389, 0, 1399, 0, 0, 0, 0, + 1390, 0, 0, 1402, 0, 0, 0, 0, 0, 1400, + 0, 1403, 1401, 0, 1404, 1405, 1406, 0, 1407, 1408, + 1409, 1410, 1411, 1412, 0, 1391, 0, 0, 2454, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1342, 0, 0, 0, 0, 0, 0, 0, 689, - 690, 0, 0, 0, 0, 0, 0, 1338, 0, 1343, - 1339, 0, 1344, 1345, 1346, 0, 1347, 1348, 1349, 1350, - 1351, 1352, 1320, 0, 1340, 1321, 2709, 1341, 0, 1322, - 1323, 1324, 1325, 1326, 0, 0, 1332, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1327, 0, - 0, 698, 1333, 700, 0, 1342, 1329, 1334, 0, 0, - 0, 0, 0, 1330, 0, 0, 702, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1335, - 1336, 0, 0, 0, 0, 0, 0, 0, 1331, 0, - 0, 0, 0, 1343, 1337, 0, 1344, 1345, 1346, 0, - 1347, 1348, 1349, 1350, 1351, 1352, 0, 0, 0, 0, - 2772, 0, 0, 0, 0, 0, 1342, 705, 0, 0, + 1403, 0, 0, 1404, 1405, 1406, 0, 1407, 1408, 1409, + 1410, 1411, 1412, 0, 0, 0, 0, 2606, 0, 0, + 0, 0, 1379, 0, 0, 1380, 0, 0, 0, 1381, + 1382, 1383, 1384, 1385, 1386, 0, 1403, 0, 0, 1404, + 1405, 1406, 0, 1407, 1408, 1409, 1410, 1411, 1412, 1387, + 0, 0, 0, 2628, 0, 0, 0, 1389, 0, 0, + 0, 1402, 0, 0, 1390, 1403, 0, 0, 1404, 1405, + 1406, 0, 1407, 1408, 1409, 1410, 1411, 1412, 0, 0, + 0, 0, 2631, 0, 1379, 0, 1392, 1380, 0, 1391, + 0, 1381, 1382, 1383, 1384, 1385, 1386, 0, 0, 0, + 0, 0, 1393, 0, 0, 0, 0, 1394, 0, 0, + 0, 1387, 0, 0, 0, 0, 0, 0, 0, 1389, + 0, 0, 0, 0, 0, 0, 1390, 0, 0, 1395, + 1396, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1397, 0, 0, 0, 0, 1379, + 0, 1391, 1380, 0, 0, 0, 1381, 1382, 1383, 1384, + 1385, 1386, 0, 1403, 0, 0, 1404, 1405, 1406, 0, + 1407, 1408, 1409, 1410, 1411, 1412, 1387, 0, 0, 0, + 2770, 0, 1398, 0, 1389, 1399, 0, 0, 0, 0, + 1392, 1390, 0, 0, 0, 0, 0, 0, 0, 1400, + 0, 0, 1401, 0, 0, 0, 1393, 1043, 0, 0, + 0, 1394, 0, 1044, 0, 0, 1391, 0, 0, 0, + 1056, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1395, 1396, 0, 0, 0, 0, 1057, + 0, 0, 0, 0, 0, 0, 0, 0, 1397, 0, + 0, 0, 1392, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1379, 1393, 0, + 1380, 0, 0, 1394, 1381, 1382, 1383, 1384, 1385, 1386, + 0, 0, 0, 0, 0, 0, 1398, 0, 0, 1399, + 1058, 1402, 0, 0, 1387, 1395, 1396, 0, 0, 0, + 0, 0, 1389, 1400, 0, 0, 1401, 0, 0, 1390, + 1397, 0, 0, 0, 0, 0, 0, 1392, 0, 1045, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1338, 0, 0, 1339, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1340, - 0, 0, 1341, 0, 0, 0, 0, 1343, 0, 0, - 1344, 1345, 1346, 0, 1347, 1348, 1349, 1350, 1351, 1352, - 710, 0, 0, 0, 2879, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1332, + 0, 0, 0, 1393, 1391, 0, 0, 0, 1394, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1398, 0, + 0, 1399, 0, 0, 0, 0, 0, 0, 0, 0, + 1395, 1396, 0, 0, 0, 1400, 0, 0, 1401, 0, + 0, 0, 0, 0, 0, 1397, 0, 0, 0, 0, + 0, 1059, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1403, 0, 1402, 1404, 1405, 1406, 0, + 1407, 1408, 1409, 1410, 1411, 1412, 0, 0, 0, 0, + 2833, 0, 0, 1398, 0, 0, 1399, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 713, 714, 0, 0, 1333, 0, 0, 0, 0, - 1334, 0, 0, 0, 0, 0, 0, 0, 1343, 0, - 0, 1344, 1345, 1346, 0, 1347, 1348, 1349, 1350, 1351, - 1352, 0, 1335, 1336, 716, 2927, 0, 0, 0, 0, - 0, 1342, 0, 0, 0, 0, 0, 1337, 0, 0, + 1400, 0, 1060, 1401, 0, 1392, 0, 0, 0, 0, + 1061, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1393, 1062, 0, 0, 0, 1394, 1402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1046, 0, 0, 0, 0, 1395, 1396, + 0, 0, 0, 1063, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1397, 0, 0, 0, 1403, 0, 0, + 1404, 1405, 1406, 0, 1407, 1408, 1409, 1410, 1411, 1412, + 0, 0, 0, 0, 2940, 0, 0, 0, 0, 0, + 0, 0, 1402, 0, 1916, 0, 0, 0, 1048, 0, + 1065, 1398, 0, 0, 1399, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1400, 0, + 0, 1401, 1066, 0, 0, 0, 0, 0, 1917, 1403, + 0, 0, 1404, 1405, 1406, 0, 1407, 1408, 1409, 1410, + 1411, 1412, 1068, 0, 0, 0, 2988, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1338, 0, 0, 1339, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1340, 0, 0, 1341, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1403, 0, 1050, 1404, 1405, 1406, + 0, 1407, 1408, 1409, 1410, 1411, 1412, 0, 0, 0, + 1402, 3001, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1343, 0, 0, 1344, 1345, 1346, 0, - 1347, 1348, 1349, 1350, 1351, 1352, 0, 0, 0, 0, - 2940, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1342, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1062, 1343, 0, 0, 1344, - 1345, 1346, 0, 1347, 1348, 1349, 1350, 1351, 1352, 0, - 0, 1503, 94, 95, 96, 97, 98, 99, 100, 101, - 1063, 102, 103, 104, 1064, 1065, 1066, 1067, 1068, 1069, - 1070, 105, 106, 1071, 107, 108, 109, 0, 111, 112, - 113, 750, 751, 0, 752, 753, 1072, 119, 120, 121, - 122, 123, 124, 1073, 1074, 125, 126, 754, 755, 129, - 1075, 130, 131, 132, 133, 756, 1076, 0, 1077, 136, - 137, 138, 139, 140, 141, 0, 143, 144, 145, 1078, - 146, 147, 148, 149, 150, 151, 1079, 0, 153, 154, - 155, 1080, 1081, 1082, 0, 1083, 1084, 1085, 157, 158, - 159, 160, 161, 162, 163, 757, 758, 166, 1086, 167, - 1087, 168, 169, 170, 171, 172, 173, 1088, 174, 175, - 176, 177, 178, 1089, 1090, 179, 180, 181, 182, 183, - 1091, 184, 185, 186, 1092, 187, 188, 189, 1093, 190, - 191, 192, 193, 759, 195, 196, 197, 198, 199, 760, - 1094, 201, 1095, 202, 203, 761, 205, 1096, 206, 1097, - 207, 0, 1098, 0, 210, 211, 762, 0, 214, 1099, - 215, 1100, 763, 764, 218, 1101, 219, 220, 221, 222, - 223, 224, 225, 0, 227, 228, 229, 230, 1102, 231, - 232, 233, 234, 235, 236, 1103, 237, 0, 765, 240, - 241, 242, 243, 244, 766, 767, 1104, 768, 1105, 248, - 0, 0, 251, 0, 253, 254, 255, 256, 257, 258, - 1106, 1107, 259, 0, 261, 0, 1108, 263, 264, 265, - 1109, 1110, 266, 267, 268, 269, 270, 769, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 770, 0, 771, 293, - 294, 295, 772, 1111, 297, 298, 0, 300, 1112, 773, - 302, 774, 304, 305, 306, 1113, 307, 308, 1114, 1115, - 309, 310, 311, 1116, 1117, 312, 775, 0, 315, 0, - 776, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 1118, 328, 329, 777, 331, 332, 778, 334, 335, - 336, 1119, 337, 338, 339, 340, 341, 342, 1120, 343, - 344, 345, 779, 347, 348, 349, 350, 1121, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 1122, 364, 365, 0, 367, 368, 369, 780, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 1123, 382, 383, 384, 385, 386, 1124, 387, 781, 389, - 390, 391, 0, 393, 394, 782, 396, 1125, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 783, 410, 784, 412, 1126, 413, 414, 1127, 415, 0, - 417, 418, 419, 420, 421, 1128, 785, 786, 1129, 1130, - 424, 425, 787, 427, 788, 1131, 429, 430, 789, 432, - 433, 434, 435, 436, 1132, 1133, 437, 438, 439, 440, - 441, 1134, 1135, 442, 443, 444, 445, 446, 1136, 791, - 1137, 449, 0, 451, 452, 453, 454, 455, 1138, 1139, - 456, 1140, 1141, 457, 458, 459, 460, 461, 462, 792, - 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, - 474, 475, 476, 477, 500, 0, 0, 0, 0, 0, - 0, 0, 0, 1753, 0, 0, 0, 0, 0, 0, - 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, - 102, 103, 104, 0, 0, 0, 0, 0, 0, 0, - 105, 106, 0, 107, 108, 109, 0, 111, 112, 113, - 114, 115, 0, 117, 118, 0, 119, 120, 121, 122, - 123, 124, 0, 0, 125, 126, 127, 128, 129, 0, - 130, 131, 132, 133, 134, 0, 0, 0, 136, 137, - 138, 139, 140, 141, 0, 143, 144, 145, 0, 146, - 147, 148, 149, 150, 151, 0, 0, 153, 154, 155, - 0, 0, 0, 0, 0, 0, 0, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 0, 167, 0, - 168, 169, 170, 171, 172, 173, 0, 174, 175, 176, - 177, 178, 0, 0, 179, 180, 181, 182, 183, 0, - 184, 185, 186, 0, 187, 188, 189, 0, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 0, - 201, 0, 202, 203, 204, 205, 0, 206, 0, 207, - 0, 0, 0, 210, 211, 502, 0, 214, 0, 215, - 0, 216, 217, 218, 0, 219, 220, 221, 222, 223, - 224, 225, 0, 227, 228, 229, 230, 0, 231, 232, - 233, 234, 235, 236, 0, 237, 0, 239, 240, 241, - 242, 243, 244, 245, 246, 0, 247, 0, 248, 0, - 0, 251, 0, 253, 254, 255, 256, 257, 258, 0, - 0, 259, 0, 261, 0, 0, 263, 264, 265, 0, - 0, 266, 267, 268, 269, 270, 503, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 0, 292, 293, 294, - 295, 296, 0, 297, 298, 0, 300, 0, 301, 302, - 303, 304, 305, 306, 0, 307, 308, 0, 0, 309, - 310, 311, 0, 0, 312, 313, 0, 315, 0, 317, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 0, 328, 329, 330, 331, 332, 333, 334, 335, 336, - 0, 337, 338, 339, 340, 341, 342, 0, 343, 344, - 345, 346, 347, 348, 349, 350, 0, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 0, 364, 365, 0, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, 379, 380, 381, 0, - 382, 383, 384, 385, 386, 0, 387, 388, 389, 390, - 391, 0, 393, 394, 395, 396, 0, 397, 398, 399, - 400, 401, 402, 403, 404, 405, 406, 407, 408, 505, - 410, 411, 412, 0, 413, 414, 0, 415, 0, 417, - 418, 419, 420, 421, 0, 422, 423, 0, 0, 424, - 425, 426, 427, 428, 0, 429, 430, 431, 432, 433, - 434, 435, 436, 0, 0, 437, 438, 439, 440, 441, - 0, 0, 442, 443, 444, 445, 446, 447, 448, 0, - 449, 0, 451, 452, 453, 454, 455, 0, 0, 456, - 0, 0, 457, 458, 459, 460, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 749, 1243, 550, 0, 0, 0, 826, - 0, 0, 2258, 0, 0, 0, 0, 0, 0, 0, - 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, - 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, - 106, 0, 107, 108, 109, 0, 111, 112, 113, 750, - 751, 0, 752, 753, 0, 119, 120, 121, 122, 123, - 124, 0, 0, 125, 126, 754, 755, 129, 0, 130, - 131, 132, 133, 756, 0, 0, 0, 136, 137, 138, - 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, - 0, 0, 0, 0, 0, 0, 157, 158, 159, 160, - 161, 162, 163, 757, 758, 166, 1379, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 181, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 759, 195, 196, 197, 198, 199, 760, 1244, 201, - 0, 202, 203, 761, 205, 0, 206, 0, 207, 0, - 0, 0, 210, 211, 762, 0, 214, 0, 215, 0, - 763, 764, 218, 0, 219, 220, 221, 222, 223, 224, - 225, 0, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 0, 765, 240, 241, 242, - 243, 244, 766, 767, 0, 768, 0, 248, 0, 0, - 251, 0, 253, 254, 255, 256, 257, 258, 0, 0, - 259, 0, 261, 0, 0, 263, 264, 265, 0, 0, - 266, 267, 268, 269, 270, 769, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 770, 0, 771, 293, 294, 295, - 772, 0, 297, 298, 0, 300, 0, 773, 302, 774, - 304, 305, 306, 0, 307, 308, 1245, 0, 309, 310, - 311, 0, 0, 312, 775, 0, 315, 0, 776, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 777, 331, 332, 778, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 779, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 0, 367, 368, 369, 780, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 0, 382, - 383, 384, 385, 386, 0, 387, 781, 389, 390, 391, - 0, 393, 394, 782, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 783, 410, - 784, 412, 0, 413, 414, 0, 415, 0, 417, 418, - 419, 420, 421, 0, 785, 786, 0, 0, 424, 425, - 787, 427, 788, 1246, 429, 430, 789, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 0, - 0, 442, 443, 444, 445, 446, 1136, 791, 0, 449, - 0, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 0, 457, 458, 459, 460, 461, 462, 792, 793, 794, - 795, 796, 797, 798, 799, 800, 801, 802, 474, 475, - 476, 477, 749, 1243, 550, 0, 0, 0, 826, 1247, - 1248, 0, 0, 0, 0, 0, 0, 0, 0, 94, - 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, - 104, 0, 0, 0, 0, 0, 0, 0, 105, 106, - 0, 107, 108, 109, 0, 111, 112, 113, 750, 751, - 0, 752, 753, 0, 119, 120, 121, 122, 123, 124, - 0, 0, 125, 126, 754, 755, 129, 0, 130, 131, - 132, 133, 756, 0, 0, 0, 136, 137, 138, 139, - 140, 141, 0, 143, 144, 145, 0, 146, 147, 148, - 149, 150, 151, 0, 0, 153, 154, 155, 0, 0, - 0, 0, 0, 0, 0, 157, 158, 159, 160, 161, - 162, 163, 757, 758, 166, 1381, 167, 0, 168, 169, - 170, 171, 172, 173, 0, 174, 175, 176, 177, 178, - 0, 0, 179, 180, 181, 182, 183, 0, 184, 185, - 186, 0, 187, 188, 189, 0, 190, 191, 192, 193, - 759, 195, 196, 197, 198, 199, 760, 1244, 201, 0, - 202, 203, 761, 205, 0, 206, 0, 207, 0, 0, - 0, 210, 211, 762, 0, 214, 0, 215, 0, 763, - 764, 218, 0, 219, 220, 221, 222, 223, 224, 225, - 0, 227, 228, 229, 230, 0, 231, 232, 233, 234, - 235, 236, 0, 237, 0, 765, 240, 241, 242, 243, - 244, 766, 767, 0, 768, 0, 248, 0, 0, 251, - 0, 253, 254, 255, 256, 257, 258, 0, 0, 259, - 0, 261, 0, 0, 263, 264, 265, 0, 0, 266, - 267, 268, 269, 270, 769, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 770, 0, 771, 293, 294, 295, 772, - 0, 297, 298, 0, 300, 0, 773, 302, 774, 304, - 305, 306, 0, 307, 308, 1245, 0, 309, 310, 311, - 0, 0, 312, 775, 0, 315, 0, 776, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, 0, 328, - 329, 777, 331, 332, 778, 334, 335, 336, 0, 337, - 338, 339, 340, 341, 342, 0, 343, 344, 345, 779, - 347, 348, 349, 350, 0, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 0, 364, - 365, 0, 367, 368, 369, 780, 371, 372, 373, 374, - 375, 376, 377, 378, 379, 380, 381, 0, 382, 383, - 384, 385, 386, 0, 387, 781, 389, 390, 391, 0, - 393, 394, 782, 396, 0, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 783, 410, 784, - 412, 0, 413, 414, 0, 415, 0, 417, 418, 419, - 420, 421, 0, 785, 786, 0, 0, 424, 425, 787, - 427, 788, 1246, 429, 430, 789, 432, 433, 434, 435, - 436, 0, 0, 437, 438, 439, 440, 441, 0, 0, - 442, 443, 444, 445, 446, 1136, 791, 0, 449, 0, - 451, 452, 453, 454, 455, 0, 0, 456, 0, 0, - 457, 458, 459, 460, 461, 462, 792, 793, 794, 795, - 796, 797, 798, 799, 800, 801, 802, 474, 475, 476, - 477, 749, 1243, 550, 0, 0, 0, 826, 1247, 1248, + 1129, 0, 1403, 0, 0, 1404, 1405, 1406, 0, 1407, + 1408, 1409, 1410, 1411, 1412, 0, 0, 1566, 94, 95, + 96, 97, 98, 99, 100, 101, 1130, 102, 103, 104, + 1131, 1132, 1133, 1134, 1135, 1136, 1137, 105, 106, 1138, + 107, 108, 109, 781, 111, 112, 113, 782, 783, 784, + 785, 786, 1139, 119, 120, 121, 122, 123, 124, 1140, + 1141, 125, 126, 787, 788, 129, 1142, 130, 131, 132, + 133, 789, 1143, 790, 1144, 136, 137, 138, 139, 140, + 141, 791, 143, 144, 145, 1145, 146, 147, 148, 149, + 150, 151, 1146, 792, 153, 154, 155, 793, 794, 795, + 796, 1147, 1148, 797, 161, 162, 163, 164, 165, 166, + 167, 798, 799, 170, 1149, 171, 1150, 172, 173, 174, + 175, 176, 177, 1151, 178, 179, 180, 181, 182, 1152, + 1153, 183, 184, 185, 186, 187, 1154, 188, 189, 190, + 1155, 191, 192, 193, 1156, 194, 195, 196, 197, 800, + 199, 200, 201, 202, 203, 801, 1157, 205, 1158, 206, + 207, 802, 209, 1159, 210, 1160, 211, 803, 1161, 804, + 214, 215, 805, 806, 218, 1162, 219, 1163, 807, 808, + 222, 1164, 223, 224, 225, 226, 227, 228, 229, 809, + 231, 232, 233, 234, 1165, 235, 236, 237, 238, 239, + 240, 1166, 241, 810, 811, 244, 245, 246, 247, 248, + 812, 813, 1167, 814, 1168, 252, 815, 816, 255, 817, + 257, 258, 259, 260, 261, 262, 1169, 1170, 263, 818, + 265, 819, 1171, 267, 268, 269, 1172, 1173, 270, 271, + 272, 273, 274, 820, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 821, 822, 823, 297, 298, 299, 824, 1174, + 301, 302, 825, 304, 1175, 826, 306, 827, 308, 309, + 310, 1176, 311, 312, 1177, 1178, 313, 314, 315, 1179, + 1180, 316, 828, 829, 319, 830, 831, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 1181, 332, 333, + 832, 335, 336, 833, 338, 339, 340, 1182, 341, 342, + 343, 344, 345, 346, 1183, 347, 348, 349, 834, 351, + 352, 353, 354, 1184, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 1185, 368, 369, + 835, 371, 372, 373, 836, 375, 376, 377, 378, 379, + 380, 381, 382, 383, 384, 385, 1186, 386, 387, 388, + 389, 390, 837, 392, 838, 394, 395, 396, 839, 398, + 399, 840, 401, 1187, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 841, 415, 842, 417, + 1188, 418, 419, 1189, 420, 843, 422, 423, 424, 425, + 426, 1190, 844, 845, 1191, 1192, 429, 430, 846, 432, + 847, 1193, 434, 435, 848, 437, 438, 439, 440, 441, + 1194, 1195, 442, 443, 444, 445, 446, 849, 1196, 448, + 449, 450, 451, 452, 1197, 851, 1198, 455, 852, 457, + 458, 459, 460, 461, 1199, 1200, 462, 1201, 1202, 463, + 464, 465, 466, 467, 468, 853, 854, 855, 856, 857, + 858, 859, 860, 861, 862, 863, 480, 481, 482, 483, + 506, 0, 0, 0, 0, 0, 0, 0, 0, 1815, 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, - 107, 108, 109, 0, 111, 112, 113, 750, 751, 0, - 752, 753, 0, 119, 120, 121, 122, 123, 124, 0, - 0, 125, 126, 754, 755, 129, 0, 130, 131, 132, - 133, 756, 0, 0, 0, 136, 137, 138, 139, 140, + 107, 108, 109, 0, 111, 112, 113, 114, 115, 0, + 117, 118, 0, 119, 120, 121, 122, 123, 124, 0, + 0, 125, 126, 127, 128, 129, 0, 130, 131, 132, + 133, 134, 0, 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, - 0, 0, 0, 0, 157, 158, 159, 160, 161, 162, - 163, 757, 758, 166, 0, 167, 0, 168, 169, 170, - 171, 172, 173, 0, 174, 175, 176, 177, 178, 0, - 0, 179, 180, 181, 182, 183, 0, 184, 185, 186, - 0, 187, 188, 189, 0, 190, 191, 192, 193, 759, - 195, 196, 197, 198, 199, 760, 1244, 201, 0, 202, - 203, 761, 205, 0, 206, 0, 207, 0, 0, 0, - 210, 211, 762, 0, 214, 0, 215, 0, 763, 764, - 218, 0, 219, 220, 221, 222, 223, 224, 225, 0, - 227, 228, 229, 230, 0, 231, 232, 233, 234, 235, - 236, 0, 237, 0, 765, 240, 241, 242, 243, 244, - 766, 767, 0, 768, 0, 248, 0, 0, 251, 0, - 253, 254, 255, 256, 257, 258, 0, 0, 259, 0, - 261, 0, 0, 263, 264, 265, 0, 0, 266, 267, - 268, 269, 270, 769, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 770, 0, 771, 293, 294, 295, 772, 0, - 297, 298, 0, 300, 0, 773, 302, 774, 304, 305, - 306, 0, 307, 308, 1245, 0, 309, 310, 311, 0, - 0, 312, 775, 0, 315, 0, 776, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 0, 328, 329, - 777, 331, 332, 778, 334, 335, 336, 0, 337, 338, - 339, 340, 341, 342, 0, 343, 344, 345, 779, 347, - 348, 349, 350, 0, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 0, 364, 365, - 0, 367, 368, 369, 780, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 0, 382, 383, 384, - 385, 386, 0, 387, 781, 389, 390, 391, 0, 393, - 394, 782, 396, 0, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 783, 410, 784, 412, - 0, 413, 414, 0, 415, 0, 417, 418, 419, 420, - 421, 0, 785, 786, 0, 0, 424, 425, 787, 427, - 788, 1246, 429, 430, 789, 432, 433, 434, 435, 436, - 0, 0, 437, 438, 439, 440, 441, 0, 0, 442, - 443, 444, 445, 446, 1136, 791, 0, 449, 0, 451, - 452, 453, 454, 455, 0, 0, 456, 0, 0, 457, - 458, 459, 460, 461, 462, 792, 793, 794, 795, 796, - 797, 798, 799, 800, 801, 802, 474, 475, 476, 477, - 0, 0, 1320, 0, 0, 1321, 0, 1247, 1248, 1322, - 1323, 1324, 1325, 1326, 0, 1320, 0, 0, 1321, 0, - 0, 0, 1322, 1323, 1324, 1325, 1326, 0, 1327, 0, - 0, 0, 1780, 0, 0, 0, 1329, 0, 0, 0, - 0, 1327, 0, 1330, 0, 0, 0, 0, 0, 1329, - 1320, 0, 0, 1321, 0, 0, 1330, 1322, 1323, 1324, - 1325, 1326, 0, 1320, 0, 0, 1321, 0, 1331, 0, - 1322, 1323, 1324, 1325, 1326, 0, 1327, 0, 0, 0, - 0, 1331, 0, 0, 1329, 0, 0, 0, 0, 1327, - 0, 1330, 1982, 0, 0, 0, 0, 1329, 0, 0, - 0, 0, 0, 0, 1330, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1331, 0, 0, 1781, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1331, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1320, 0, 0, 1321, 0, 0, 0, - 1322, 1323, 1324, 1325, 1326, 0, 0, 0, 0, 1332, - 0, 0, 2021, 0, 0, 0, 0, 2022, 0, 1327, - 0, 0, 1332, 0, 0, 1333, 0, 1329, 0, 0, - 1334, 0, 0, 0, 1330, 0, 0, 0, 1333, 0, - 0, 0, 0, 1334, 0, 0, 3027, 0, 0, 0, - 0, 0, 1335, 1336, 0, 0, 0, 1332, 0, 1331, - 0, 0, 0, 0, 0, 1335, 1336, 1337, 0, 0, - 1332, 0, 0, 1333, 0, 0, 0, 0, 1334, 0, - 1337, 0, 0, 0, 0, 0, 1333, 0, 0, 0, - 0, 1334, 0, 0, 0, 0, 0, 0, 0, 0, - 1335, 1336, 0, 0, 0, 1338, 0, 0, 1339, 0, - 0, 0, 0, 1335, 1336, 1337, 0, 0, 1338, 0, - 0, 1339, 1340, 0, 0, 1341, 0, 0, 1337, 0, - 0, 0, 0, 0, 0, 1340, 0, 0, 1341, 0, + 0, 0, 0, 0, 161, 162, 163, 164, 165, 166, + 167, 168, 169, 170, 0, 171, 0, 172, 173, 174, + 175, 176, 177, 0, 178, 179, 180, 181, 182, 0, + 0, 183, 184, 185, 186, 187, 0, 188, 189, 190, + 0, 191, 192, 193, 0, 194, 195, 196, 197, 198, + 199, 200, 201, 202, 203, 204, 0, 205, 0, 206, + 207, 208, 209, 0, 210, 0, 211, 0, 0, 0, + 214, 215, 509, 0, 218, 0, 219, 0, 220, 221, + 222, 0, 223, 224, 225, 226, 227, 228, 229, 0, + 231, 232, 233, 234, 0, 235, 236, 237, 238, 239, + 240, 0, 241, 0, 243, 244, 245, 246, 247, 248, + 249, 250, 0, 251, 0, 252, 0, 0, 255, 0, + 257, 258, 259, 260, 261, 262, 0, 0, 263, 0, + 265, 0, 0, 267, 268, 269, 0, 0, 270, 271, + 272, 273, 274, 510, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 294, 0, 296, 297, 298, 299, 300, 0, + 301, 302, 0, 304, 0, 305, 306, 307, 308, 309, + 310, 0, 311, 312, 0, 0, 313, 314, 315, 0, + 0, 316, 317, 0, 319, 0, 321, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 0, 332, 333, + 334, 335, 336, 337, 338, 339, 340, 0, 341, 342, + 343, 344, 345, 346, 0, 347, 348, 349, 350, 351, + 352, 353, 354, 0, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 0, 368, 369, + 0, 371, 372, 373, 374, 375, 376, 377, 378, 379, + 380, 381, 382, 383, 384, 385, 0, 386, 387, 388, + 389, 390, 0, 392, 393, 394, 395, 396, 0, 398, + 399, 400, 401, 0, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 512, 415, 416, 417, + 0, 418, 419, 0, 420, 0, 422, 423, 424, 425, + 426, 0, 427, 428, 0, 0, 429, 430, 431, 432, + 433, 0, 434, 435, 436, 437, 438, 439, 440, 441, + 0, 0, 442, 443, 444, 445, 446, 0, 0, 448, + 449, 450, 451, 452, 453, 454, 0, 455, 0, 457, + 458, 459, 460, 461, 0, 0, 462, 0, 0, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, 482, 483, + 780, 1302, 582, 0, 0, 0, 887, 0, 0, 2315, + 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, + 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, + 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, + 107, 108, 109, 781, 111, 112, 113, 782, 783, 784, + 785, 786, 0, 119, 120, 121, 122, 123, 124, 0, + 0, 125, 126, 787, 788, 129, 0, 130, 131, 132, + 133, 789, 0, 790, 0, 136, 137, 138, 139, 140, + 141, 791, 143, 144, 145, 0, 146, 147, 148, 149, + 150, 151, 0, 792, 153, 154, 155, 793, 794, 795, + 796, 0, 0, 797, 161, 162, 163, 164, 165, 166, + 167, 798, 799, 170, 1439, 171, 0, 172, 173, 174, + 175, 176, 177, 0, 178, 179, 180, 181, 182, 0, + 0, 183, 184, 185, 186, 187, 0, 188, 189, 190, + 0, 191, 192, 193, 0, 194, 195, 196, 197, 800, + 199, 200, 201, 202, 203, 801, 1303, 205, 0, 206, + 207, 802, 209, 0, 210, 0, 211, 803, 0, 804, + 214, 215, 805, 806, 218, 0, 219, 0, 807, 808, + 222, 0, 223, 224, 225, 226, 227, 228, 229, 809, + 231, 232, 233, 234, 0, 235, 236, 237, 238, 239, + 240, 0, 241, 810, 811, 244, 245, 246, 247, 248, + 812, 813, 0, 814, 0, 252, 815, 816, 255, 817, + 257, 258, 259, 260, 261, 262, 0, 0, 263, 818, + 265, 819, 0, 267, 268, 269, 0, 0, 270, 271, + 272, 273, 274, 820, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 821, 822, 823, 297, 298, 299, 824, 0, + 301, 302, 825, 304, 0, 826, 306, 827, 308, 309, + 310, 0, 311, 312, 1304, 0, 313, 314, 315, 0, + 0, 316, 828, 829, 319, 830, 831, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 0, 332, 333, + 832, 335, 336, 833, 338, 339, 340, 0, 341, 342, + 343, 344, 345, 346, 0, 347, 348, 349, 834, 351, + 352, 353, 354, 0, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 0, 368, 369, + 835, 371, 372, 373, 836, 375, 376, 377, 378, 379, + 380, 381, 382, 383, 384, 385, 0, 386, 387, 388, + 389, 390, 837, 392, 838, 394, 395, 396, 839, 398, + 399, 840, 401, 0, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 841, 415, 842, 417, + 0, 418, 419, 0, 420, 843, 422, 423, 424, 425, + 426, 0, 844, 845, 0, 0, 429, 430, 846, 432, + 847, 1305, 434, 435, 848, 437, 438, 439, 440, 441, + 0, 0, 442, 443, 444, 445, 446, 849, 0, 448, + 449, 450, 451, 452, 1197, 851, 0, 455, 852, 457, + 458, 459, 460, 461, 0, 0, 462, 0, 0, 463, + 464, 465, 466, 467, 468, 853, 854, 855, 856, 857, + 858, 859, 860, 861, 862, 863, 480, 481, 482, 483, + 780, 1302, 582, 0, 0, 0, 887, 1306, 1307, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, + 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, + 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, + 107, 108, 109, 781, 111, 112, 113, 782, 783, 784, + 785, 786, 0, 119, 120, 121, 122, 123, 124, 0, + 0, 125, 126, 787, 788, 129, 0, 130, 131, 132, + 133, 789, 0, 790, 0, 136, 137, 138, 139, 140, + 141, 791, 143, 144, 145, 0, 146, 147, 148, 149, + 150, 151, 0, 792, 153, 154, 155, 793, 794, 795, + 796, 0, 0, 797, 161, 162, 163, 164, 165, 166, + 167, 798, 799, 170, 1441, 171, 0, 172, 173, 174, + 175, 176, 177, 0, 178, 179, 180, 181, 182, 0, + 0, 183, 184, 185, 186, 187, 0, 188, 189, 190, + 0, 191, 192, 193, 0, 194, 195, 196, 197, 800, + 199, 200, 201, 202, 203, 801, 1303, 205, 0, 206, + 207, 802, 209, 0, 210, 0, 211, 803, 0, 804, + 214, 215, 805, 806, 218, 0, 219, 0, 807, 808, + 222, 0, 223, 224, 225, 226, 227, 228, 229, 809, + 231, 232, 233, 234, 0, 235, 236, 237, 238, 239, + 240, 0, 241, 810, 811, 244, 245, 246, 247, 248, + 812, 813, 0, 814, 0, 252, 815, 816, 255, 817, + 257, 258, 259, 260, 261, 262, 0, 0, 263, 818, + 265, 819, 0, 267, 268, 269, 0, 0, 270, 271, + 272, 273, 274, 820, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 821, 822, 823, 297, 298, 299, 824, 0, + 301, 302, 825, 304, 0, 826, 306, 827, 308, 309, + 310, 0, 311, 312, 1304, 0, 313, 314, 315, 0, + 0, 316, 828, 829, 319, 830, 831, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 0, 332, 333, + 832, 335, 336, 833, 338, 339, 340, 0, 341, 342, + 343, 344, 345, 346, 0, 347, 348, 349, 834, 351, + 352, 353, 354, 0, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 0, 368, 369, + 835, 371, 372, 373, 836, 375, 376, 377, 378, 379, + 380, 381, 382, 383, 384, 385, 0, 386, 387, 388, + 389, 390, 837, 392, 838, 394, 395, 396, 839, 398, + 399, 840, 401, 0, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 841, 415, 842, 417, + 0, 418, 419, 0, 420, 843, 422, 423, 424, 425, + 426, 0, 844, 845, 0, 0, 429, 430, 846, 432, + 847, 1305, 434, 435, 848, 437, 438, 439, 440, 441, + 0, 0, 442, 443, 444, 445, 446, 849, 0, 448, + 449, 450, 451, 452, 1197, 851, 0, 455, 852, 457, + 458, 459, 460, 461, 0, 0, 462, 0, 0, 463, + 464, 465, 466, 467, 468, 853, 854, 855, 856, 857, + 858, 859, 860, 861, 862, 863, 480, 481, 482, 483, + 780, 1302, 582, 0, 0, 0, 887, 1306, 1307, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, + 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, + 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, + 107, 108, 109, 781, 111, 112, 113, 782, 783, 784, + 785, 786, 0, 119, 120, 121, 122, 123, 124, 0, + 0, 125, 126, 787, 788, 129, 0, 130, 131, 132, + 133, 789, 0, 790, 0, 136, 137, 138, 139, 140, + 141, 791, 143, 144, 145, 0, 146, 147, 148, 149, + 150, 151, 0, 792, 153, 154, 155, 793, 794, 795, + 796, 0, 0, 797, 161, 162, 163, 164, 165, 166, + 167, 798, 799, 170, 0, 171, 0, 172, 173, 174, + 175, 176, 177, 0, 178, 179, 180, 181, 182, 0, + 0, 183, 184, 185, 186, 187, 0, 188, 189, 190, + 0, 191, 192, 193, 0, 194, 195, 196, 197, 800, + 199, 200, 201, 202, 203, 801, 1303, 205, 0, 206, + 207, 802, 209, 0, 210, 0, 211, 803, 0, 804, + 214, 215, 805, 806, 218, 0, 219, 0, 807, 808, + 222, 0, 223, 224, 225, 226, 227, 228, 229, 809, + 231, 232, 233, 234, 0, 235, 236, 237, 238, 239, + 240, 0, 241, 810, 811, 244, 245, 246, 247, 248, + 812, 813, 0, 814, 0, 252, 815, 816, 255, 817, + 257, 258, 259, 260, 261, 262, 0, 0, 263, 818, + 265, 819, 0, 267, 268, 269, 0, 0, 270, 271, + 272, 273, 274, 820, 276, 277, 278, 279, 280, 281, + 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, + 292, 293, 821, 822, 823, 297, 298, 299, 824, 0, + 301, 302, 825, 304, 0, 826, 306, 827, 308, 309, + 310, 0, 311, 312, 1304, 0, 313, 314, 315, 0, + 0, 316, 828, 829, 319, 830, 831, 322, 323, 324, + 325, 326, 327, 328, 329, 330, 331, 0, 332, 333, + 832, 335, 336, 833, 338, 339, 340, 0, 341, 342, + 343, 344, 345, 346, 0, 347, 348, 349, 834, 351, + 352, 353, 354, 0, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 0, 368, 369, + 835, 371, 372, 373, 836, 375, 376, 377, 378, 379, + 380, 381, 382, 383, 384, 385, 0, 386, 387, 388, + 389, 390, 837, 392, 838, 394, 395, 396, 839, 398, + 399, 840, 401, 0, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 412, 413, 841, 415, 842, 417, + 0, 418, 419, 0, 420, 843, 422, 423, 424, 425, + 426, 0, 844, 845, 0, 0, 429, 430, 846, 432, + 847, 1305, 434, 435, 848, 437, 438, 439, 440, 441, + 0, 0, 442, 443, 444, 445, 446, 849, 0, 448, + 449, 450, 451, 452, 1197, 851, 0, 455, 852, 457, + 458, 459, 460, 461, 0, 0, 462, 0, 0, 463, + 464, 465, 466, 467, 468, 853, 854, 855, 856, 857, + 858, 859, 860, 861, 862, 863, 480, 481, 482, 483, + 0, 0, 1379, 0, 0, 1380, 0, 1306, 1307, 1381, + 1382, 1383, 1384, 1385, 1386, 1379, 0, 0, 1380, 0, + 0, 0, 1381, 1382, 1383, 1384, 1385, 1386, 0, 1387, + 0, 0, 0, 1843, 0, 0, 0, 1389, 0, 0, + 0, 0, 1387, 0, 1390, 0, 0, 0, 0, 0, + 1389, 1379, 0, 0, 1380, 0, 0, 1390, 1381, 1382, + 1383, 1384, 1385, 1386, 1379, 0, 0, 1380, 0, 1391, + 0, 1381, 1382, 1383, 1384, 1385, 1386, 0, 1387, 0, + 0, 0, 1391, 0, 0, 0, 1389, 0, 0, 0, + 0, 1387, 0, 1390, 2043, 0, 0, 0, 0, 1389, + 1379, 0, 0, 1380, 0, 0, 1390, 1381, 1382, 1383, + 1384, 1385, 1386, 0, 0, 0, 0, 0, 1391, 0, + 1844, 0, 0, 0, 0, 0, 0, 1387, 0, 0, + 0, 1391, 0, 0, 0, 1389, 0, 0, 0, 0, + 0, 0, 1390, 0, 0, 1379, 0, 0, 1380, 0, + 0, 0, 1381, 1382, 1383, 1384, 1385, 1386, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1391, 0, 0, + 1392, 0, 1387, 2082, 0, 2088, 0, 0, 2083, 0, + 1389, 0, 0, 1392, 0, 0, 1393, 1390, 0, 0, + 0, 1394, 0, 0, 0, 0, 0, 0, 0, 1393, + 0, 0, 0, 0, 1394, 0, 0, 0, 3088, 0, + 0, 0, 1391, 1395, 1396, 0, 0, 0, 0, 1392, + 0, 0, 0, 0, 0, 0, 1395, 1396, 1397, 0, + 0, 0, 1392, 0, 0, 1393, 0, 0, 0, 0, + 1394, 1397, 0, 0, 0, 0, 0, 0, 1393, 0, + 0, 0, 0, 1394, 0, 0, 0, 0, 0, 0, + 0, 0, 1395, 1396, 0, 0, 1398, 0, 1392, 1399, + 0, 0, 0, 0, 0, 1395, 1396, 1397, 0, 1398, + 0, 0, 1399, 1400, 1393, 0, 1401, 0, 0, 1394, + 1397, 0, 0, 0, 0, 0, 1400, 0, 0, 1401, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1338, 0, 0, 1339, 0, 0, 0, - 1332, 0, 0, 0, 0, 0, 1338, 0, 0, 1339, - 1340, 0, 0, 1341, 0, 0, 1333, 0, 0, 0, - 0, 1334, 0, 1340, 0, 0, 1341, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3028, 0, 0, 0, - 0, 0, 0, 1335, 1336, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1342, 0, 0, 0, 1337, 0, - 0, 0, 0, 1320, 0, 0, 1321, 1342, 0, 0, - 1322, 1323, 1324, 1325, 1326, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1327, - 0, 0, 2027, 0, 0, 0, 1338, 1329, 0, 1339, - 0, 0, 1342, 0, 1330, 0, 0, 0, 0, 0, - 0, 0, 0, 1340, 1785, 1342, 1341, 1320, 0, 0, - 1321, 0, 0, 0, 1322, 1323, 1324, 1325, 1326, 1331, - 0, 0, 0, 0, 1994, 0, 0, 0, 0, 0, - 0, 0, 0, 1327, 0, 0, 0, 0, 0, 0, - 0, 1329, 0, 0, 0, 0, 1343, 0, 1330, 1344, - 1345, 1346, 0, 1347, 1348, 1349, 1350, 1351, 1352, 1343, - 0, 0, 1344, 1345, 1346, 0, 1347, 1348, 1349, 1350, - 1351, 1352, 0, 1331, 0, 0, 0, 0, 0, 0, + 0, 1395, 1396, 1392, 0, 1398, 0, 0, 1399, 0, + 0, 0, 0, 0, 0, 0, 1397, 0, 1398, 1393, + 0, 1399, 1400, 0, 1394, 1401, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1400, 0, 0, 1401, 0, + 0, 0, 0, 0, 0, 0, 1395, 1396, 3089, 0, + 0, 0, 0, 0, 1398, 0, 0, 1399, 0, 0, + 0, 1397, 0, 0, 0, 1402, 0, 0, 0, 0, + 0, 1400, 0, 0, 1401, 0, 0, 0, 1402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1343, 1342, 0, 1344, 1345, 1346, - 0, 1347, 1348, 1349, 1350, 1351, 1352, 1343, 0, 0, - 1344, 1345, 1346, 0, 1347, 1348, 1349, 1350, 1351, 1352, - 1332, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1333, 0, 0, 0, - 0, 1334, 0, 0, 0, 0, 1320, 0, 0, 1321, - 0, 0, 0, 1322, 1323, 1324, 1325, 1326, 0, 0, - 0, 0, 0, 1335, 1336, 0, 0, 0, 0, 2032, - 0, 0, 1327, 0, 1332, 2034, 0, 0, 1337, 0, - 1329, 0, 0, 0, 0, 0, 0, 1330, 0, 0, - 1333, 0, 0, 0, 0, 1334, 0, 1343, 0, 0, - 1344, 1345, 1346, 0, 1347, 1348, 1349, 1350, 1351, 1352, - 0, 0, 1331, 0, 0, 0, 1338, 1335, 1336, 1339, + 0, 0, 2055, 0, 0, 0, 0, 0, 0, 1398, + 0, 0, 1399, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1402, 0, 1400, 0, 0, 1401, + 0, 0, 0, 0, 0, 1848, 0, 1402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1320, 1337, 1340, 1321, 0, 1341, 0, 1322, 1323, - 1324, 1325, 1326, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1327, 0, 0, - 0, 0, 0, 0, 0, 1329, 0, 0, 0, 0, - 1338, 0, 1330, 1339, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1320, 0, 1340, 1321, 0, - 1341, 0, 1322, 1323, 1324, 1325, 1326, 1331, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1327, 0, 1332, 2307, 0, 0, 0, 0, 1329, - 0, 0, 0, 0, 0, 1342, 1330, 0, 0, 1333, - 0, 0, 0, 0, 1334, 0, 0, 0, 0, 1320, - 0, 0, 1321, 0, 0, 0, 1322, 1323, 1324, 1325, - 1326, 1331, 0, 0, 0, 0, 1335, 1336, 0, 0, - 0, 0, 0, 0, 0, 1327, 0, 0, 0, 0, - 0, 1337, 0, 1329, 1320, 0, 0, 1321, 0, 1342, - 1330, 0, 1323, 1324, 1325, 1326, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1332, 0, - 1327, 0, 0, 0, 0, 1331, 0, 0, 1329, 1338, - 0, 0, 1339, 0, 1333, 1330, 0, 0, 0, 1334, - 0, 0, 0, 0, 0, 0, 1340, 1343, 0, 1341, - 1344, 1345, 1346, 0, 1347, 1348, 1349, 1350, 1351, 1352, - 1331, 1335, 1336, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1332, 0, 0, 0, 1337, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1333, 0, - 0, 0, 0, 1334, 0, 0, 0, 0, 0, 0, - 0, 1343, 0, 0, 1344, 1345, 1346, 0, 1347, 1348, - 1349, 1350, 1351, 1352, 1338, 1335, 1336, 1339, 0, 0, - 0, 0, 0, 0, 0, 0, 1332, 0, 0, 0, - 1337, 1340, 0, 0, 1341, 0, 0, 0, 1342, 0, - 0, 0, 1333, 0, 0, 0, 0, 1334, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1332, 0, 0, 0, 0, 0, 0, 1338, 1335, - 1336, 1339, 0, 0, 0, 0, 0, 1333, 0, 0, - 0, 0, 1334, 0, 1337, 1340, 0, 1320, 1341, 0, - 1321, 0, 0, 0, 1322, 1323, 1324, 1325, 1326, 0, - 0, 0, 0, 0, 1335, 1336, 0, 0, 0, 0, - 0, 0, 0, 1327, 0, 0, 0, 0, 0, 1337, - 0, 1329, 1338, 1342, 0, 1339, 0, 0, 1330, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1340, - 1343, 0, 1341, 1344, 1345, 1346, 0, 1347, 1348, 1349, - 1350, 1351, 1352, 1331, 0, 0, 2262, 1338, 0, 0, - 1339, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1340, 0, 0, 1342, 0, 0, + 0, 0, 0, 1402, 0, 0, 0, 1403, 0, 0, + 1404, 1405, 1406, 0, 1407, 1408, 1409, 1410, 1411, 1412, + 1403, 0, 0, 1404, 1405, 1406, 0, 1407, 1408, 1409, + 1410, 1411, 1412, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1402, 0, + 0, 0, 0, 0, 0, 0, 1403, 0, 0, 1404, + 1405, 1406, 0, 1407, 1408, 1409, 1410, 1411, 1412, 1403, + 0, 0, 1404, 1405, 1406, 0, 1407, 1408, 1409, 1410, + 1411, 1412, 0, 0, 1379, 0, 0, 1380, 0, 0, + 0, 1381, 1382, 1383, 1384, 1385, 1386, 0, 0, 0, + 0, 0, 0, 0, 0, 1403, 0, 0, 1404, 1405, + 1406, 1387, 1407, 1408, 1409, 1410, 1411, 1412, 0, 1389, + 0, 0, 0, 0, 0, 0, 1390, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1403, 1391, 0, 1404, 1405, 1406, 0, 1407, 1408, 1409, + 1410, 1411, 1412, 1379, 0, 0, 1380, 0, 0, 0, + 1381, 1382, 1383, 1384, 1385, 1386, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1387, 0, 1379, 2095, 0, 1380, 0, 0, 1389, 1381, + 1382, 1383, 1384, 1385, 1386, 1390, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1387, + 0, 0, 0, 0, 0, 0, 0, 1389, 0, 0, + 1391, 0, 0, 0, 1390, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 2093, 0, 0, + 0, 0, 1392, 0, 0, 0, 0, 0, 0, 1391, + 0, 0, 0, 0, 0, 0, 0, 0, 1393, 0, + 0, 1379, 0, 1394, 1380, 0, 0, 0, 1381, 1382, + 1383, 1384, 1385, 1386, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1395, 1396, 0, 1387, 0, + 0, 2363, 0, 0, 0, 0, 1389, 0, 0, 0, + 1397, 0, 0, 1390, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1343, 0, 0, 1344, 1345, - 1346, 1342, 1347, 1348, 1349, 1350, 1351, 1352, 0, 0, + 0, 1392, 0, 0, 0, 0, 0, 0, 1391, 0, + 0, 0, 0, 0, 0, 0, 0, 1393, 1398, 0, + 0, 1399, 1394, 0, 0, 0, 0, 0, 0, 0, + 1392, 0, 0, 0, 0, 1400, 0, 0, 1401, 0, + 0, 0, 0, 0, 1395, 1396, 1393, 0, 0, 0, + 0, 1394, 0, 0, 0, 0, 0, 0, 0, 1397, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1332, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1342, 0, 0, 0, - 1333, 0, 0, 0, 0, 1334, 0, 0, 0, 1343, - 0, 0, 1344, 1345, 1346, 0, 1347, 1348, 1349, 1350, - 1351, 1352, 0, 0, 0, 0, 0, 1335, 1336, 0, + 0, 0, 0, 1395, 1396, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1397, 0, + 0, 0, 0, 0, 0, 0, 0, 1398, 0, 0, + 1399, 0, 0, 0, 0, 0, 0, 0, 0, 1392, + 0, 0, 1379, 0, 1400, 1380, 0, 1401, 0, 1381, + 1382, 1383, 1384, 1385, 1386, 1393, 1398, 1402, 0, 1399, + 1394, 0, 0, 0, 0, 0, 0, 0, 0, 1387, + 0, 0, 0, 1400, 0, 0, 1401, 1389, 0, 0, + 0, 0, 1395, 1396, 1390, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1397, 0, 0, + 0, 0, 0, 0, 0, 1379, 0, 0, 1380, 1391, + 0, 0, 1381, 1382, 1383, 1384, 1385, 1386, 1379, 0, + 0, 1380, 0, 0, 0, 1381, 0, 0, 1384, 1385, + 1386, 0, 1387, 0, 0, 1398, 1402, 0, 1399, 0, + 1389, 0, 0, 0, 0, 0, 0, 1390, 0, 0, + 0, 0, 1400, 1389, 0, 1401, 0, 0, 0, 1403, + 1390, 0, 1404, 1405, 1406, 1402, 1407, 1408, 1409, 1410, + 1411, 1412, 1391, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1391, 0, 0, 0, 0, + 0, 0, 1379, 0, 0, 1380, 0, 0, 2319, 1381, + 0, 0, 1384, 1385, 1386, 0, 0, 0, 0, 0, + 1392, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1393, 1389, 0, 0, + 0, 1394, 0, 0, 1390, 0, 0, 0, 1403, 0, + 0, 1404, 1405, 1406, 1402, 1407, 1408, 1409, 1410, 1411, + 1412, 0, 0, 1395, 1396, 0, 0, 0, 0, 1391, + 0, 0, 0, 0, 0, 0, 0, 1403, 1397, 0, + 1404, 1405, 1406, 1392, 1407, 1408, 1409, 1410, 1411, 1412, + 0, 0, 0, 0, 0, 0, 1392, 0, 0, 1393, + 0, 0, 0, 0, 1394, 0, 0, 0, 0, 0, + 0, 0, 1393, 0, 0, 0, 1398, 1394, 0, 1399, + 0, 0, 0, 0, 0, 0, 1395, 1396, 0, 0, + 0, 0, 0, 1400, 0, 0, 1401, 0, 0, 1395, + 1396, 1397, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1397, 0, 1403, 0, 0, 1404, + 1405, 1406, 0, 1407, 1408, 1409, 1410, 1411, 1412, 0, + 1392, 0, 0, 0, 0, 0, 0, 0, 0, 1398, + 0, 0, 1399, 0, 0, 0, 1393, 0, 0, 0, + 0, 1394, 1398, 0, 0, 1399, 1400, 0, 0, 1401, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1400, + 0, 0, 0, -1847, -1847, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1402, 0, 0, 1397, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1337, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1343, 0, 0, 1344, 1345, 1346, 0, - 1347, 1348, 1349, 1350, 1351, 1352, 0, 0, 0, 0, - 1338, 0, 0, 1339, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1340, 1343, 0, - 1341, 1344, 1345, 1346, 0, 1347, 1348, 1349, 1350, 1351, - 1352, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, -1847, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1400, 0, 0, 0, 0, 1402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1403, 0, 0, + 1404, 1405, 1406, 0, 1407, 1408, 1409, 1410, 1411, 1412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1342, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1402, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1403, 0, 0, 1404, 1405, 1406, 0, 1407, 1408, 1409, + 1410, 1865, 1412, 1403, 0, 0, 1404, 1405, 1406, 0, + 1407, 1408, 1409, 1410, 1411, 1412, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1129, 0, 1752, 0, 0, 1403, 0, 0, + 1404, 1405, 1406, 0, 1407, 1408, 1409, 1410, 1411, 1412, + 94, 95, 96, 97, 98, 99, 100, 101, 1130, 102, + 103, 104, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 105, + 106, 1138, 107, 108, 109, 781, 111, 112, 113, 782, + 783, 784, 785, 786, 1139, 119, 120, 121, 122, 123, + 124, 1140, 1141, 125, 126, 787, 788, 129, 1142, 130, + 131, 132, 133, 789, 1143, 790, 1144, 136, 137, 138, + 139, 140, 141, 791, 143, 144, 145, 1145, 146, 147, + 148, 149, 150, 151, 1146, 792, 153, 154, 155, 793, + 794, 795, 796, 1147, 1148, 797, 161, 162, 163, 164, + 165, 166, 167, 798, 799, 170, 1149, 171, 1150, 172, + 173, 174, 175, 176, 177, 1151, 178, 179, 180, 181, + 182, 1152, 1153, 183, 184, 185, 186, 187, 1154, 188, + 189, 190, 1155, 191, 192, 193, 1156, 194, 195, 196, + 197, 800, 199, 200, 201, 202, 203, 801, 1157, 205, + 1158, 206, 207, 802, 209, 1159, 210, 1160, 211, 803, + 1161, 804, 214, 215, 805, 806, 218, 1162, 219, 1163, + 807, 808, 222, 1164, 223, 224, 225, 226, 227, 228, + 229, 809, 231, 232, 233, 234, 1165, 235, 236, 237, + 238, 239, 240, 1166, 241, 810, 811, 244, 245, 246, + 247, 248, 812, 813, 1167, 814, 1168, 252, 815, 816, + 255, 817, 257, 258, 259, 260, 261, 262, 1169, 1170, + 263, 818, 265, 819, 1171, 267, 268, 269, 1172, 1173, + 270, 271, 272, 273, 274, 820, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 821, 822, 823, 297, 298, 299, + 824, 1174, 301, 302, 825, 304, 1175, 826, 306, 827, + 308, 309, 310, 1176, 311, 312, 1177, 1178, 313, 314, + 315, 1179, 1180, 316, 828, 829, 319, 830, 831, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 1181, + 332, 333, 832, 335, 336, 833, 338, 339, 340, 1182, + 341, 342, 343, 344, 345, 346, 1183, 347, 348, 349, + 834, 351, 352, 353, 354, 1184, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 1185, + 368, 369, 835, 371, 372, 373, 836, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 1186, 386, + 387, 388, 389, 390, 837, 392, 838, 394, 395, 396, + 839, 398, 399, 840, 401, 1187, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 841, 415, + 842, 417, 1188, 418, 419, 1189, 420, 843, 422, 423, + 424, 425, 426, 1190, 844, 845, 1191, 1192, 429, 430, + 846, 432, 847, 1193, 434, 435, 848, 437, 438, 439, + 440, 441, 1194, 1195, 442, 443, 444, 445, 446, 849, + 1196, 448, 449, 450, 451, 452, 1197, 851, 1198, 455, + 852, 457, 458, 459, 460, 461, 1199, 1200, 462, 1201, + 1202, 463, 464, 465, 466, 467, 468, 853, 854, 855, + 856, 857, 858, 859, 860, 861, 862, 863, 480, 481, + 482, 483, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 94, 95, 96, 97, 98, 99, 100, 101, 1130, 102, + 103, 104, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 105, + 106, 1138, 107, 108, 109, 781, 111, 112, 113, 782, + 783, 784, 785, 786, 1139, 119, 120, 121, 122, 123, + 124, 1140, 1141, 125, 126, 787, 788, 129, 1142, 130, + 131, 132, 133, 789, 1143, 790, 1144, 136, 137, 138, + 139, 140, 141, 791, 143, 144, 145, 1145, 146, 147, + 148, 149, 150, 151, 1146, 792, 153, 154, 155, 793, + 794, 795, 796, 1147, 1148, 797, 161, 162, 163, 164, + 165, 166, 167, 798, 799, 170, 1149, 171, 1150, 172, + 173, 174, 175, 176, 177, 1151, 178, 179, 180, 181, + 182, 1152, 1153, 183, 184, 185, 186, 187, 1154, 188, + 189, 190, 1155, 191, 192, 193, 1156, 194, 195, 196, + 197, 800, 199, 200, 201, 202, 203, 801, 1157, 205, + 1158, 206, 207, 802, 209, 1159, 210, 1160, 211, 803, + 1161, 804, 214, 215, 805, 806, 218, 1162, 219, 1163, + 807, 808, 222, 1164, 223, 224, 225, 226, 227, 228, + 229, 809, 231, 232, 233, 234, 1165, 235, 236, 237, + 238, 239, 240, 1166, 241, 810, 811, 244, 245, 246, + 247, 248, 812, 813, 1167, 814, 1168, 252, 815, 816, + 255, 817, 257, 258, 259, 260, 261, 262, 1169, 1170, + 263, 818, 265, 819, 1171, 267, 268, 269, 1172, 1173, + 270, 271, 272, 273, 274, 820, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 821, 822, 823, 297, 298, 299, + 824, 1174, 301, 302, 825, 304, 1175, 826, 306, 827, + 308, 309, 310, 1176, 311, 312, 1177, 1178, 313, 314, + 315, 1179, 1180, 316, 828, 829, 319, 830, 831, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 1181, + 332, 333, 832, 335, 336, 833, 338, 339, 340, 1182, + 341, 342, 343, 344, 345, 346, 1183, 347, 348, 349, + 834, 351, 352, 353, 354, 1184, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 1185, + 368, 369, 835, 371, 372, 373, 836, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 1186, 386, + 387, 388, 389, 390, 837, 392, 838, 394, 395, 396, + 839, 398, 399, 840, 401, 1187, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 841, 415, + 842, 417, 1188, 418, 419, 1189, 420, 843, 422, 423, + 424, 425, 426, 1190, 844, 845, 1191, 1192, 429, 430, + 846, 432, 847, 1193, 434, 435, 848, 437, 438, 439, + 440, 441, 1194, 1195, 442, 443, 444, 445, 446, 849, + 1196, 448, 449, 450, 451, 452, 1197, 851, 1198, 455, + 852, 457, 458, 459, 460, 461, 1199, 1200, 462, 1201, + 1202, 463, 464, 465, 466, 467, 468, 853, 854, 855, + 856, 857, 858, 859, 860, 861, 862, 863, 480, 481, + 482, 483, 1129, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1062, 0, 1690, - 0, 1343, 0, 0, 1344, 1345, 1346, 0, 1347, 1348, - 1349, 1350, 1800, 1352, 94, 95, 96, 97, 98, 99, - 100, 101, 1063, 102, 103, 104, 1064, 1065, 1066, 1067, - 1068, 1069, 1070, 105, 106, 1071, 107, 108, 109, 0, - 111, 112, 113, 750, 751, 0, 752, 753, 1072, 119, - 120, 121, 122, 123, 124, 1073, 1074, 125, 126, 754, - 755, 129, 1075, 130, 131, 132, 133, 756, 1076, 0, - 1077, 136, 137, 138, 139, 140, 141, 0, 143, 144, - 145, 1078, 146, 147, 148, 149, 150, 151, 1079, 0, - 153, 154, 155, 1080, 1081, 1082, 0, 1083, 1084, 1085, - 157, 158, 159, 160, 161, 162, 163, 757, 758, 166, - 1086, 167, 1087, 168, 169, 170, 171, 172, 173, 1088, - 174, 175, 176, 177, 178, 1089, 1090, 179, 180, 181, - 182, 183, 1091, 184, 185, 186, 1092, 187, 188, 189, - 1093, 190, 191, 192, 193, 759, 195, 196, 197, 198, - 199, 760, 1094, 201, 1095, 202, 203, 761, 205, 1096, - 206, 1097, 207, 0, 1098, 0, 210, 211, 762, 0, - 214, 1099, 215, 1100, 763, 764, 218, 1101, 219, 220, - 221, 222, 223, 224, 225, 0, 227, 228, 229, 230, - 1102, 231, 232, 233, 234, 235, 236, 1103, 237, 0, - 765, 240, 241, 242, 243, 244, 766, 767, 1104, 768, - 1105, 248, 0, 0, 251, 0, 253, 254, 255, 256, - 257, 258, 1106, 1107, 259, 0, 261, 0, 1108, 263, - 264, 265, 1109, 1110, 266, 267, 268, 269, 270, 769, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 770, 0, - 771, 293, 294, 295, 772, 1111, 297, 298, 0, 300, - 1112, 773, 302, 774, 304, 305, 306, 1113, 307, 308, - 1114, 1115, 309, 310, 311, 1116, 1117, 312, 775, 0, - 315, 0, 776, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 1118, 328, 329, 777, 331, 332, 778, - 334, 335, 336, 1119, 337, 338, 339, 340, 341, 342, - 1120, 343, 344, 345, 779, 347, 348, 349, 350, 1121, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 1122, 364, 365, 0, 367, 368, 369, - 780, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 1123, 382, 383, 384, 385, 386, 1124, 387, - 781, 389, 390, 391, 0, 393, 394, 782, 396, 1125, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 783, 410, 784, 412, 1126, 413, 414, 1127, - 415, 0, 417, 418, 419, 420, 421, 1128, 785, 786, - 1129, 1130, 424, 425, 787, 427, 788, 1131, 429, 430, - 789, 432, 433, 434, 435, 436, 1132, 1133, 437, 438, - 439, 440, 441, 1134, 1135, 442, 443, 444, 445, 446, - 1136, 791, 1137, 449, 0, 451, 452, 453, 454, 455, - 1138, 1139, 456, 1140, 1141, 457, 458, 459, 460, 461, - 462, 792, 793, 794, 795, 796, 797, 798, 799, 800, - 801, 802, 474, 475, 476, 477, 1062, 0, 0, 0, + 94, 95, 96, 97, 1901, 99, 100, 101, 1130, 102, + 103, 104, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 105, + 106, 1138, 107, 108, 109, 781, 111, 112, 113, 782, + 783, 784, 785, 786, 1139, 119, 120, 121, 122, 123, + 124, 1140, 1141, 125, 126, 787, 788, 129, 1142, 130, + 131, 132, 133, 789, 1143, 790, 1144, 136, 137, 138, + 139, 140, 141, 791, 143, 144, 145, 1145, 146, 147, + 148, 149, 150, 151, 1146, 792, 153, 154, 155, 793, + 794, 795, 796, 1147, 1148, 797, 161, 162, 163, 164, + 165, 166, 167, 798, 799, 170, 1149, 171, 1150, 172, + 173, 174, 175, 176, 177, 1151, 178, 179, 180, 181, + 182, 1152, 1153, 183, 184, 185, 1902, 187, 1154, 188, + 189, 190, 1155, 191, 192, 193, 1156, 194, 195, 196, + 197, 800, 199, 200, 201, 202, 203, 801, 1157, 205, + 1158, 206, 207, 802, 209, 1159, 210, 1160, 211, 803, + 1161, 804, 214, 215, 805, 806, 218, 1162, 219, 1163, + 807, 808, 222, 1164, 223, 224, 225, 226, 227, 228, + 229, 809, 231, 232, 233, 234, 1165, 235, 236, 237, + 238, 239, 240, 1166, 241, 810, 811, 244, 245, 246, + 247, 248, 812, 813, 1167, 814, 1168, 252, 815, 816, + 255, 817, 257, 258, 259, 260, 261, 262, 1169, 1170, + 263, 818, 265, 819, 1171, 267, 268, 269, 1172, 1173, + 270, 271, 272, 273, 274, 820, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 821, 822, 823, 297, 298, 299, + 824, 1174, 301, 302, 825, 304, 1175, 826, 306, 827, + 308, 309, 310, 1176, 311, 312, 1177, 1178, 313, 314, + 315, 1179, 1180, 316, 828, 829, 319, 830, 831, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 1181, + 332, 333, 832, 335, 336, 833, 338, 339, 340, 1182, + 341, 342, 343, 344, 345, 346, 1183, 347, 348, 349, + 834, 351, 352, 353, 354, 1184, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 1185, + 368, 369, 835, 371, 372, 373, 836, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 1186, 386, + 387, 388, 389, 390, 837, 1903, 838, 394, 395, 396, + 839, 398, 399, 840, 401, 1187, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 841, 415, + 842, 417, 1188, 418, 419, 1189, 420, 843, 422, 423, + 424, 425, 426, 1190, 844, 845, 1191, 1192, 429, 430, + 846, 432, 847, 1193, 434, 435, 848, 437, 438, 439, + 440, 441, 1194, 1195, 442, 443, 444, 445, 446, 849, + 1196, 448, 449, 450, 451, 452, 1197, 851, 1198, 455, + 852, 457, 458, 459, 460, 461, 1199, 1200, 462, 1201, + 1202, 463, 464, 465, 466, 467, 468, 853, 854, 855, + 856, 857, 858, 859, 860, 861, 862, 863, 480, 481, + 482, 483, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, - 101, 1063, 102, 103, 104, 1064, 1065, 1066, 1067, 1068, - 1069, 1070, 105, 106, 1071, 107, 108, 109, 0, 111, - 112, 113, 750, 751, 0, 752, 753, 1072, 119, 120, - 121, 122, 123, 124, 1073, 1074, 125, 126, 754, 755, - 129, 1075, 130, 131, 132, 133, 756, 1076, 0, 1077, - 136, 137, 138, 139, 140, 141, 0, 143, 144, 145, - 1078, 146, 147, 148, 149, 150, 151, 1079, 0, 153, - 154, 155, 1080, 1081, 1082, 0, 1083, 1084, 1085, 157, - 158, 159, 160, 161, 162, 163, 757, 758, 166, 1086, - 167, 1087, 168, 169, 170, 171, 172, 173, 1088, 174, - 175, 176, 177, 178, 1089, 1090, 179, 180, 181, 182, - 183, 1091, 184, 185, 186, 1092, 187, 188, 189, 1093, - 190, 191, 192, 193, 759, 195, 196, 197, 198, 199, - 760, 1094, 201, 1095, 202, 203, 761, 205, 1096, 206, - 1097, 207, 0, 1098, 0, 210, 211, 762, 0, 214, - 1099, 215, 1100, 763, 764, 218, 1101, 219, 220, 221, - 222, 223, 224, 225, 0, 227, 228, 229, 230, 1102, - 231, 232, 233, 234, 235, 236, 1103, 237, 0, 765, - 240, 241, 242, 243, 244, 766, 767, 1104, 768, 1105, - 248, 0, 0, 251, 0, 253, 254, 255, 256, 257, - 258, 1106, 1107, 259, 0, 261, 0, 1108, 263, 264, - 265, 1109, 1110, 266, 267, 268, 269, 270, 769, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 770, 0, 771, - 293, 294, 295, 772, 1111, 297, 298, 0, 300, 1112, - 773, 302, 774, 304, 305, 306, 1113, 307, 308, 1114, - 1115, 309, 310, 311, 1116, 1117, 312, 775, 0, 315, - 0, 776, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 1118, 328, 329, 777, 331, 332, 778, 334, - 335, 336, 1119, 337, 338, 339, 340, 341, 342, 1120, - 343, 344, 345, 779, 347, 348, 349, 350, 1121, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 1122, 364, 365, 0, 367, 368, 369, 780, - 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, - 381, 1123, 382, 383, 384, 385, 386, 1124, 387, 781, - 389, 390, 391, 0, 393, 394, 782, 396, 1125, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 783, 410, 784, 412, 1126, 413, 414, 1127, 415, - 0, 417, 418, 419, 420, 421, 1128, 785, 786, 1129, - 1130, 424, 425, 787, 427, 788, 1131, 429, 430, 789, - 432, 433, 434, 435, 436, 1132, 1133, 437, 438, 439, - 440, 441, 1134, 1135, 442, 443, 444, 445, 446, 1136, - 791, 1137, 449, 0, 451, 452, 453, 454, 455, 1138, - 1139, 456, 1140, 1141, 457, 458, 459, 460, 461, 462, - 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, - 802, 474, 475, 476, 477, 1062, 0, 0, 0, 0, + 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, + 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, + 106, 0, 107, 108, 109, 110, 111, 112, 113, 114, + 115, 116, 117, 118, 0, 119, 120, 121, 122, 123, + 124, 0, 894, 125, 126, 127, 128, 129, 0, 130, + 131, 132, 133, 897, 0, 898, 0, 136, 137, 138, + 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, + 148, 149, 150, 151, 0, 152, 153, 154, 155, 899, + 900, 901, 902, 903, 904, 905, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 185, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 910, 0, 205, + 0, 206, 207, 208, 209, 0, 210, 0, 211, 212, + 0, 213, 214, 215, 216, 217, 218, 0, 219, 0, + 220, 221, 222, 0, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 0, 251, 0, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 264, 265, 266, 0, 267, 268, 269, 918, 919, + 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, + 300, 0, 301, 302, 303, 304, 0, 924, 306, 307, + 308, 309, 310, 0, 311, 312, 0, 0, 313, 314, + 315, 0, 0, 316, 317, 318, 319, 320, 927, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 928, 335, 336, 337, 338, 339, 340, 0, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 350, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 931, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, + 933, 417, 0, 418, 419, 0, 420, 421, 422, 423, + 424, 425, 426, 0, 427, 428, 0, 0, 429, 430, + 936, 432, 937, 0, 434, 435, 939, 437, 438, 439, + 440, 441, 0, 0, 442, 443, 444, 445, 446, 940, + 0, 448, 449, 450, 451, 452, 453, 454, 0, 455, + 456, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, 780, 0, 582, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 95, 96, 97, 1836, 99, 100, 101, - 1063, 102, 103, 104, 1064, 1065, 1066, 1067, 1068, 1069, - 1070, 105, 106, 1071, 107, 108, 109, 0, 111, 112, - 113, 750, 751, 0, 752, 753, 1072, 119, 120, 121, - 122, 123, 124, 1073, 1074, 125, 126, 754, 755, 129, - 1075, 130, 131, 132, 133, 756, 1076, 0, 1077, 136, - 137, 138, 139, 140, 141, 0, 143, 144, 145, 1078, - 146, 147, 148, 149, 150, 151, 1079, 0, 153, 154, - 155, 1080, 1081, 1082, 0, 1083, 1084, 1085, 157, 158, - 159, 160, 161, 162, 163, 757, 758, 166, 1086, 167, - 1087, 168, 169, 170, 171, 172, 173, 1088, 174, 175, - 176, 177, 178, 1089, 1090, 179, 180, 181, 1837, 183, - 1091, 184, 185, 186, 1092, 187, 188, 189, 1093, 190, - 191, 192, 193, 759, 195, 196, 197, 198, 199, 760, - 1094, 201, 1095, 202, 203, 761, 205, 1096, 206, 1097, - 207, 0, 1098, 0, 210, 211, 762, 0, 214, 1099, - 215, 1100, 763, 764, 218, 1101, 219, 220, 221, 222, - 223, 224, 225, 0, 227, 228, 229, 230, 1102, 231, - 232, 233, 234, 235, 236, 1103, 237, 0, 765, 240, - 241, 242, 243, 244, 766, 767, 1104, 768, 1105, 248, - 0, 0, 251, 0, 253, 254, 255, 256, 257, 258, - 1106, 1107, 259, 0, 261, 0, 1108, 263, 264, 265, - 1109, 1110, 266, 267, 268, 269, 270, 769, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 770, 0, 771, 293, - 294, 295, 772, 1111, 297, 298, 0, 300, 1112, 773, - 302, 774, 304, 305, 306, 1113, 307, 308, 1114, 1115, - 309, 310, 311, 1116, 1117, 312, 775, 0, 315, 0, - 776, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 1118, 328, 329, 777, 331, 332, 778, 334, 335, - 336, 1119, 337, 338, 339, 340, 341, 342, 1120, 343, - 344, 345, 779, 347, 348, 349, 350, 1121, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 1122, 364, 365, 0, 367, 368, 369, 780, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 1123, 382, 383, 384, 385, 386, 1124, 1838, 781, 389, - 390, 391, 0, 393, 394, 782, 396, 1125, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 783, 410, 784, 412, 1126, 413, 414, 1127, 415, 0, - 417, 418, 419, 420, 421, 1128, 785, 786, 1129, 1130, - 424, 425, 787, 427, 788, 1131, 429, 430, 789, 432, - 433, 434, 435, 436, 1132, 1133, 437, 438, 439, 440, - 441, 1134, 1135, 442, 443, 444, 445, 446, 1136, 791, - 1137, 449, 0, 451, 452, 453, 454, 455, 1138, 1139, - 456, 1140, 1141, 457, 458, 459, 460, 461, 462, 792, - 793, 794, 795, 796, 797, 798, 799, 800, 801, 802, - 474, 475, 476, 477, 93, 0, 0, 0, 0, 0, + 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, + 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, + 106, 0, 107, 108, 109, 781, 111, 112, 113, 782, + 783, 784, 785, 786, 0, 119, 120, 121, 122, 123, + 124, 0, 0, 125, 126, 787, 788, 129, 0, 130, + 131, 132, 133, 789, 0, 790, 0, 136, 137, 138, + 139, 140, 141, 791, 143, 144, 145, 0, 146, 147, + 148, 149, 150, 151, 0, 792, 153, 154, 155, 793, + 794, 795, 796, 0, 0, 797, 161, 162, 163, 164, + 165, 166, 167, 798, 799, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 185, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 800, 199, 200, 201, 202, 203, 801, 1303, 205, + 0, 206, 207, 802, 209, 0, 210, 0, 211, 803, + 0, 804, 214, 215, 805, 806, 218, 0, 219, 0, + 807, 808, 222, 0, 223, 224, 225, 226, 227, 228, + 229, 809, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 810, 811, 244, 245, 246, + 247, 248, 812, 813, 0, 814, 0, 252, 815, 816, + 255, 817, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 818, 265, 819, 0, 267, 268, 269, 0, 0, + 270, 271, 272, 273, 274, 820, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 821, 822, 823, 297, 298, 299, + 824, 0, 301, 302, 825, 304, 0, 826, 306, 827, + 308, 309, 310, 0, 311, 312, 1304, 0, 313, 314, + 315, 0, 0, 316, 828, 829, 319, 830, 831, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 832, 335, 336, 833, 338, 339, 340, 0, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 834, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 835, 371, 372, 373, 836, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 837, 392, 838, 394, 395, 396, + 839, 398, 399, 840, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 841, 415, + 842, 417, 0, 418, 419, 0, 420, 843, 422, 423, + 424, 425, 426, 0, 844, 845, 0, 0, 429, 430, + 846, 432, 847, 1305, 434, 435, 848, 437, 438, 439, + 440, 441, 0, 0, 442, 443, 444, 445, 446, 849, + 0, 448, 449, 450, 451, 452, 1197, 851, 0, 455, + 852, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 853, 854, 855, + 856, 857, 858, 859, 860, 861, 862, 863, 480, 481, + 482, 483, 780, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, - 102, 103, 104, 0, 0, 0, 0, 0, 0, 0, - 105, 106, 0, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 0, 119, 120, 121, 122, - 123, 124, 0, 833, 125, 126, 127, 128, 129, 0, - 130, 131, 132, 133, 836, 0, 837, 0, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, - 147, 148, 149, 150, 151, 0, 152, 153, 154, 155, - 838, 839, 840, 841, 842, 843, 844, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 0, 167, 0, - 168, 169, 170, 171, 172, 173, 0, 174, 175, 176, - 177, 178, 0, 0, 179, 180, 181, 182, 183, 0, - 184, 185, 186, 0, 187, 188, 189, 0, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 849, 0, - 201, 0, 202, 203, 204, 205, 0, 206, 0, 207, - 208, 0, 209, 210, 211, 212, 213, 214, 0, 215, - 0, 216, 217, 218, 0, 219, 220, 221, 222, 223, - 224, 225, 226, 227, 228, 229, 230, 0, 231, 232, - 233, 234, 235, 236, 0, 237, 238, 239, 240, 241, - 242, 243, 244, 245, 246, 0, 247, 0, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 0, - 0, 259, 260, 261, 262, 0, 263, 264, 265, 857, - 858, 266, 267, 268, 269, 270, 271, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, - 295, 296, 0, 297, 298, 299, 300, 0, 863, 302, - 303, 304, 305, 306, 0, 307, 308, 0, 0, 309, - 310, 311, 0, 0, 312, 313, 314, 315, 316, 866, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 0, 328, 329, 867, 331, 332, 333, 334, 335, 336, - 0, 337, 338, 339, 340, 341, 342, 0, 343, 344, - 345, 346, 347, 348, 349, 350, 0, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 0, 364, 365, 366, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, 379, 380, 381, 0, - 382, 383, 384, 385, 386, 870, 387, 388, 389, 390, - 391, 392, 393, 394, 395, 396, 0, 397, 398, 399, - 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, - 410, 872, 412, 0, 413, 414, 0, 415, 416, 417, - 418, 419, 420, 421, 0, 422, 423, 0, 0, 424, - 425, 875, 427, 876, 0, 429, 430, 878, 432, 433, - 434, 435, 436, 0, 0, 437, 438, 439, 440, 441, - 879, 0, 442, 443, 444, 445, 446, 447, 448, 0, - 449, 450, 451, 452, 453, 454, 455, 0, 0, 456, - 0, 0, 457, 458, 459, 460, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 93, 0, 0, 0, 0, 0, 0, + 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, + 103, 104, 3, 4, 0, 0, 0, 0, 0, 105, + 106, 0, 107, 108, 109, 781, 111, 112, 113, 782, + 783, 784, 785, 786, 0, 119, 120, 121, 122, 123, + 124, 0, 0, 125, 126, 787, 788, 129, 0, 130, + 131, 132, 133, 789, 0, 790, 0, 136, 137, 138, + 139, 140, 141, 791, 143, 144, 145, 0, 146, 147, + 148, 149, 150, 151, 0, 792, 153, 154, 155, 793, + 794, 795, 796, 0, 0, 797, 161, 162, 163, 164, + 165, 166, 167, 798, 799, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 185, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 800, 199, 200, 201, 202, 203, 801, 0, 205, + 0, 206, 207, 802, 209, 0, 210, 0, 211, 803, + 0, 804, 214, 215, 805, 806, 218, 0, 219, 0, + 807, 808, 222, 0, 223, 224, 225, 226, 227, 228, + 229, 809, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 810, 811, 244, 245, 246, + 247, 248, 812, 813, 0, 814, 0, 252, 815, 816, + 255, 817, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 818, 265, 819, 0, 267, 268, 269, 0, 0, + 270, 271, 272, 273, 274, 820, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 821, 822, 823, 297, 298, 299, + 824, 0, 301, 302, 825, 304, 0, 826, 306, 827, + 308, 309, 310, 0, 311, 312, 0, 0, 313, 314, + 315, 0, 0, 316, 828, 829, 319, 830, 831, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 832, 335, 336, 833, 338, 339, 340, 0, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 834, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 835, 371, 372, 373, 836, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 837, 392, 838, 394, 395, 396, + 839, 398, 399, 840, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 841, 415, + 842, 417, 0, 418, 419, 0, 420, 843, 422, 423, + 424, 425, 426, 0, 844, 845, 0, 0, 429, 430, + 846, 432, 847, 0, 434, 435, 848, 437, 438, 439, + 440, 441, 0, 0, 442, 443, 444, 445, 446, 849, + 0, 448, 449, 450, 451, 452, 1197, 851, 0, 455, + 852, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 853, 854, 855, + 856, 857, 858, 859, 860, 861, 862, 863, 480, 481, + 482, 483, 93, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, @@ -259247,238 +277472,285 @@ static const yytype_int16 yytable[] = 124, 0, 0, 125, 126, 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, 135, 0, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, 152, 153, 154, 155, 0, - 0, 0, 156, 0, 0, 0, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 0, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 181, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 0, 201, - 0, 202, 203, 204, 205, 0, 206, 0, 207, 208, - 0, 209, 210, 211, 212, 213, 214, 0, 215, 0, - 216, 217, 218, 0, 219, 220, 221, 222, 223, 224, - 225, 226, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 0, 247, 0, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 0, 0, - 259, 260, 261, 262, 0, 263, 264, 265, 0, 0, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, - 296, 0, 297, 298, 299, 300, 0, 301, 302, 303, - 304, 305, 306, 0, 307, 308, 0, 0, 309, 310, - 311, 0, 0, 312, 313, 314, 315, 316, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 330, 331, 332, 333, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 346, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 0, 382, - 383, 384, 385, 386, 0, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, - 411, 412, 0, 413, 414, 0, 415, 416, 417, 418, - 419, 420, 421, 0, 422, 423, 0, 0, 424, 425, - 426, 427, 428, 0, 429, 430, 431, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 0, - 0, 442, 443, 444, 445, 446, 447, 448, 0, 449, - 450, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 0, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 500, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, - 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, - 104, 0, 0, 0, 0, 0, 0, 0, 105, 106, - 0, 107, 108, 109, 0, 111, 112, 113, 114, 115, - 0, 117, 118, 0, 119, 120, 121, 122, 123, 124, - 0, 0, 125, 126, 127, 128, 129, 1441, 130, 131, - 132, 133, 134, 0, 0, 1442, 136, 137, 138, 139, - 140, 141, 0, 143, 144, 145, 1443, 146, 147, 148, - 149, 150, 151, 0, 0, 153, 154, 155, 0, 0, - 0, 0, 0, 0, 0, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 0, 167, 0, 168, 169, - 170, 171, 172, 173, 0, 174, 175, 176, 177, 178, - 0, 0, 179, 180, 181, 182, 183, 0, 184, 185, - 186, 0, 187, 188, 189, 0, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 0, 201, 0, - 202, 203, 204, 205, 0, 206, 1444, 207, 0, 0, - 0, 210, 211, 502, 0, 214, 0, 215, 0, 216, - 217, 218, 0, 219, 220, 221, 222, 223, 1445, 225, - 0, 227, 228, 229, 230, 0, 231, 232, 233, 234, - 235, 236, 0, 237, 0, 239, 240, 241, 242, 243, - 244, 245, 246, 0, 247, 0, 248, 0, 0, 251, - 0, 253, 254, 255, 256, 257, 258, 0, 0, 259, - 0, 261, 0, 0, 263, 264, 265, 0, 0, 266, - 267, 268, 269, 270, 503, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 0, 292, 293, 294, 295, 296, - 0, 297, 298, 0, 300, 0, 301, 302, 303, 304, - 305, 306, 0, 307, 308, 0, 0, 309, 310, 311, - 0, 0, 312, 313, 0, 315, 0, 317, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, 0, 328, - 329, 330, 331, 332, 333, 334, 335, 336, 1446, 337, - 338, 339, 340, 341, 342, 0, 343, 344, 345, 346, - 347, 348, 349, 350, 0, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 0, 364, - 365, 0, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, 379, 380, 381, 0, 382, 383, - 384, 385, 386, 0, 387, 388, 389, 390, 391, 0, - 393, 394, 395, 396, 0, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 505, 410, 411, - 412, 0, 413, 414, 0, 415, 0, 417, 418, 419, - 420, 421, 0, 422, 423, 0, 0, 424, 425, 426, - 427, 428, 0, 429, 430, 431, 432, 433, 434, 435, - 436, 0, 1447, 437, 438, 439, 440, 441, 0, 0, - 442, 443, 444, 445, 446, 447, 448, 0, 449, 0, - 451, 452, 453, 454, 455, 0, 0, 456, 0, 0, - 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, - 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, - 477, 500, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, - 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, - 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, - 107, 108, 109, 0, 111, 112, 113, 114, 115, 0, - 117, 118, 0, 119, 120, 121, 122, 123, 124, 0, - 0, 125, 126, 127, 128, 129, 1441, 130, 131, 132, - 133, 134, 0, 0, 0, 136, 137, 138, 139, 140, - 141, 0, 143, 144, 145, 1443, 146, 147, 148, 149, - 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, - 0, 0, 0, 0, 157, 158, 159, 160, 161, 162, - 163, 164, 165, 166, 0, 167, 0, 168, 169, 170, - 171, 172, 173, 0, 174, 175, 176, 177, 178, 0, - 0, 179, 180, 181, 182, 183, 0, 184, 185, 186, - 0, 187, 188, 189, 0, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 0, 201, 0, 202, - 203, 204, 205, 0, 206, 1444, 207, 0, 0, 0, - 210, 211, 502, 0, 214, 0, 215, 0, 216, 217, - 218, 0, 219, 220, 221, 222, 223, 224, 225, 0, - 227, 228, 229, 230, 0, 231, 232, 233, 234, 235, - 236, 0, 237, 0, 239, 240, 241, 242, 243, 244, - 245, 246, 0, 247, 0, 248, 0, 0, 251, 0, - 253, 254, 255, 256, 257, 258, 0, 0, 259, 0, - 261, 1906, 0, 263, 264, 265, 0, 0, 266, 267, - 268, 269, 270, 503, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 0, 292, 293, 294, 295, 296, 0, - 297, 298, 0, 300, 0, 301, 302, 303, 304, 305, - 306, 0, 307, 308, 0, 0, 309, 310, 311, 0, - 0, 312, 313, 0, 315, 0, 317, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 0, 328, 329, - 330, 331, 332, 333, 334, 335, 336, 1446, 337, 338, - 339, 340, 341, 342, 0, 343, 344, 345, 346, 347, - 348, 349, 350, 0, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 0, 364, 365, - 0, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 0, 382, 383, 384, - 385, 386, 0, 387, 388, 389, 390, 391, 0, 393, - 394, 395, 396, 0, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 505, 410, 411, 412, - 0, 413, 414, 0, 415, 0, 417, 418, 419, 420, - 421, 0, 422, 423, 0, 0, 424, 425, 426, 427, - 428, 0, 429, 430, 431, 432, 433, 434, 435, 436, - 0, 1447, 437, 438, 439, 440, 441, 0, 0, 442, - 443, 444, 445, 446, 447, 448, 0, 449, 0, 451, - 452, 453, 454, 455, 0, 0, 456, 0, 0, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 749, 0, 550, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, - 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, - 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, - 108, 109, 0, 111, 112, 113, 750, 751, 0, 752, - 753, 0, 119, 120, 121, 122, 123, 124, 0, 0, - 125, 126, 754, 755, 129, 0, 130, 131, 132, 133, - 756, 0, 0, 0, 136, 137, 138, 139, 140, 141, - 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, - 151, 0, 0, 153, 154, 155, 0, 0, 0, 0, - 0, 0, 0, 157, 158, 159, 160, 161, 162, 163, - 757, 758, 166, 0, 167, 0, 168, 169, 170, 171, - 172, 173, 0, 174, 175, 176, 177, 178, 0, 0, - 179, 180, 181, 182, 183, 0, 184, 185, 186, 0, - 187, 188, 189, 0, 190, 191, 192, 193, 759, 195, - 196, 197, 198, 199, 760, 1244, 201, 0, 202, 203, - 761, 205, 0, 206, 0, 207, 0, 0, 0, 210, - 211, 762, 0, 214, 0, 215, 0, 763, 764, 218, - 0, 219, 220, 221, 222, 223, 224, 225, 0, 227, - 228, 229, 230, 0, 231, 232, 233, 234, 235, 236, - 0, 237, 0, 765, 240, 241, 242, 243, 244, 766, - 767, 0, 768, 0, 248, 0, 0, 251, 0, 253, - 254, 255, 256, 257, 258, 0, 0, 259, 0, 261, - 0, 0, 263, 264, 265, 0, 0, 266, 267, 268, - 269, 270, 769, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 770, 0, 771, 293, 294, 295, 772, 0, 297, - 298, 0, 300, 0, 773, 302, 774, 304, 305, 306, - 0, 307, 308, 1245, 0, 309, 310, 311, 0, 0, - 312, 775, 0, 315, 0, 776, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, 0, 328, 329, 777, - 331, 332, 778, 334, 335, 336, 0, 337, 338, 339, - 340, 341, 342, 0, 343, 344, 345, 779, 347, 348, - 349, 350, 0, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 0, 364, 365, 0, - 367, 368, 369, 780, 371, 372, 373, 374, 375, 376, - 377, 378, 379, 380, 381, 0, 382, 383, 384, 385, - 386, 0, 387, 781, 389, 390, 391, 0, 393, 394, - 782, 396, 0, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 783, 410, 784, 412, 0, - 413, 414, 0, 415, 0, 417, 418, 419, 420, 421, - 0, 785, 786, 0, 0, 424, 425, 787, 427, 788, - 1246, 429, 430, 789, 432, 433, 434, 435, 436, 0, - 0, 437, 438, 439, 440, 441, 0, 0, 442, 443, - 444, 445, 446, 1136, 791, 0, 449, 0, 451, 452, - 453, 454, 455, 0, 0, 456, 0, 0, 457, 458, - 459, 460, 461, 462, 792, 793, 794, 795, 796, 797, - 798, 799, 800, 801, 802, 474, 475, 476, 477, 500, - 0, 582, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, - 98, 99, 100, 101, 0, 102, 103, 104, 3, 4, - 0, 0, 0, 0, 0, 105, 106, 0, 107, 108, - 109, 0, 111, 112, 113, 114, 115, 0, 117, 118, - 0, 119, 120, 121, 122, 123, 124, 0, 0, 125, - 126, 127, 128, 129, 0, 130, 131, 132, 133, 134, - 0, 0, 0, 136, 137, 138, 139, 140, 141, 0, - 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, - 0, 0, 153, 154, 155, 0, 0, 0, 0, 0, - 0, 0, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 0, 167, 0, 168, 169, 170, 171, 172, - 173, 0, 174, 175, 176, 177, 178, 0, 0, 179, - 180, 181, 182, 183, 0, 184, 185, 186, 0, 187, - 188, 189, 0, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 0, 201, 0, 202, 203, 204, - 205, 0, 206, 0, 207, 0, 0, 0, 210, 211, - 502, 0, 214, 0, 215, 0, 216, 217, 218, 0, - 219, 220, 221, 222, 223, 224, 225, 0, 227, 228, - 229, 230, 0, 231, 232, 233, 234, 235, 236, 0, - 237, 0, 239, 240, 241, 242, 243, 244, 245, 246, - 0, 247, 0, 248, 0, 0, 251, 0, 253, 254, - 255, 256, 257, 258, 0, 0, 259, 0, 261, 0, - 0, 263, 264, 265, 0, 0, 266, 267, 268, 269, - 270, 503, 272, 273, 274, 275, 276, 277, 278, 279, + 148, 149, 150, 151, 0, 152, 153, 154, 155, 156, + 157, 158, 159, 0, 0, 160, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 185, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 0, 205, + 0, 206, 207, 208, 209, 0, 210, 0, 211, 212, + 0, 213, 214, 215, 216, 217, 218, 0, 219, 0, + 220, 221, 222, 0, 223, 224, 225, 226, 227, 228, + 229, 230, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 0, 251, 0, 252, 253, 254, + 255, 256, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 264, 265, 266, 0, 267, 268, 269, 0, 0, + 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 0, 292, 293, 294, 295, 296, 0, 297, 298, - 0, 300, 0, 301, 302, 303, 304, 305, 306, 0, - 307, 308, 0, 0, 309, 310, 311, 0, 0, 312, - 313, 0, 315, 0, 317, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 0, 328, 329, 330, 331, - 332, 333, 334, 335, 336, 0, 337, 338, 339, 340, - 341, 342, 0, 343, 344, 345, 346, 347, 348, 349, - 350, 0, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 0, 364, 365, 0, 367, + 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, + 300, 0, 301, 302, 303, 304, 0, 305, 306, 307, + 308, 309, 310, 0, 311, 312, 0, 0, 313, 314, + 315, 0, 0, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 334, 335, 336, 337, 338, 339, 340, 0, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 350, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 0, 382, 383, 384, 385, 386, - 0, 387, 388, 389, 390, 391, 0, 393, 394, 395, - 396, 0, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 505, 410, 411, 412, 0, 413, - 414, 0, 415, 0, 417, 418, 419, 420, 421, 0, - 422, 423, 0, 0, 424, 425, 426, 427, 428, 0, - 429, 430, 431, 432, 433, 434, 435, 436, 0, 0, - 437, 438, 439, 440, 441, 0, 0, 442, 443, 444, - 445, 446, 447, 448, 0, 449, 0, 451, 452, 453, - 454, 455, 0, 0, 456, 0, 0, 457, 458, 459, - 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 500, 0, - 582, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, + 416, 417, 0, 418, 419, 0, 420, 421, 422, 423, + 424, 425, 426, 0, 427, 428, 0, 0, 429, 430, + 431, 432, 433, 0, 434, 435, 436, 437, 438, 439, + 440, 441, 0, 0, 442, 443, 444, 445, 446, 447, + 0, 448, 449, 450, 451, 452, 453, 454, 0, 455, + 456, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, 506, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, + 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, + 106, 0, 107, 108, 109, 0, 111, 112, 113, 114, + 115, 0, 117, 118, 0, 119, 120, 121, 122, 123, + 124, 0, 0, 125, 126, 127, 128, 129, 1504, 130, + 131, 132, 133, 134, 0, 0, 1505, 136, 137, 138, + 139, 140, 141, 0, 143, 144, 145, 1506, 146, 147, + 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, + 0, 0, 0, 0, 0, 0, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 185, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 0, 205, + 0, 206, 207, 208, 209, 0, 210, 1507, 211, 0, + 0, 0, 214, 215, 509, 0, 218, 0, 219, 0, + 220, 221, 222, 0, 223, 224, 225, 226, 227, 1508, + 229, 0, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 0, 243, 244, 245, 246, + 247, 248, 249, 250, 0, 251, 0, 252, 0, 0, + 255, 0, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 0, 265, 0, 0, 267, 268, 269, 0, 0, + 270, 271, 272, 273, 274, 510, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 0, 296, 297, 298, 299, + 300, 0, 301, 302, 0, 304, 0, 305, 306, 307, + 308, 309, 310, 0, 311, 312, 0, 0, 313, 314, + 315, 0, 0, 316, 317, 0, 319, 0, 321, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 334, 335, 336, 337, 338, 339, 340, 1509, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 350, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 0, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 0, 392, 393, 394, 395, 396, + 0, 398, 399, 400, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 512, 415, + 416, 417, 0, 418, 419, 0, 420, 0, 422, 423, + 424, 425, 426, 0, 427, 428, 0, 0, 429, 430, + 431, 432, 433, 0, 434, 435, 436, 437, 438, 439, + 440, 441, 0, 1510, 442, 443, 444, 445, 446, 0, + 0, 448, 449, 450, 451, 452, 453, 454, 0, 455, + 0, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, 506, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, + 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, + 106, 0, 107, 108, 109, 0, 111, 112, 113, 114, + 115, 0, 117, 118, 0, 119, 120, 121, 122, 123, + 124, 0, 0, 125, 126, 127, 128, 129, 1504, 130, + 131, 132, 133, 134, 0, 0, 0, 136, 137, 138, + 139, 140, 141, 0, 143, 144, 145, 1506, 146, 147, + 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, + 0, 0, 0, 0, 0, 0, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 185, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 0, 205, + 0, 206, 207, 208, 209, 0, 210, 1507, 211, 0, + 0, 0, 214, 215, 509, 0, 218, 0, 219, 0, + 220, 221, 222, 0, 223, 224, 225, 226, 227, 228, + 229, 0, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 0, 243, 244, 245, 246, + 247, 248, 249, 250, 0, 251, 0, 252, 0, 0, + 255, 0, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 0, 265, 1970, 0, 267, 268, 269, 0, 0, + 270, 271, 272, 273, 274, 510, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 0, 296, 297, 298, 299, + 300, 0, 301, 302, 0, 304, 0, 305, 306, 307, + 308, 309, 310, 0, 311, 312, 0, 0, 313, 314, + 315, 0, 0, 316, 317, 0, 319, 0, 321, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 334, 335, 336, 337, 338, 339, 340, 1509, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 350, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 0, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 0, 392, 393, 394, 395, 396, + 0, 398, 399, 400, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 512, 415, + 416, 417, 0, 418, 419, 0, 420, 0, 422, 423, + 424, 425, 426, 0, 427, 428, 0, 0, 429, 430, + 431, 432, 433, 0, 434, 435, 436, 437, 438, 439, + 440, 441, 0, 1510, 442, 443, 444, 445, 446, 0, + 0, 448, 449, 450, 451, 452, 453, 454, 0, 455, + 0, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, 506, 0, 507, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, + 103, 104, 3, 4, 0, 0, 0, 0, 0, 105, + 106, 0, 107, 108, 109, 0, 111, 112, 113, 114, + 115, 0, 117, 118, 0, 119, 120, 121, 122, 123, + 124, 0, 0, 125, 126, 127, 128, 129, 0, 130, + 131, 132, 133, 134, 0, 0, 0, 136, 137, 138, + 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, + 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, + 0, 0, 0, 0, 0, 0, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 185, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 0, 205, + 0, 206, 207, 208, 209, 0, 210, 0, 211, 0, + 0, 0, 214, 215, 509, 0, 218, 0, 219, 0, + 220, 221, 222, 0, 223, 224, 225, 226, 227, 228, + 229, 0, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 0, 243, 244, 245, 246, + 247, 248, 249, 250, 0, 251, 0, 252, 0, 0, + 255, 0, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 0, 265, 0, 0, 267, 268, 269, 0, 0, + 270, 271, 272, 273, 274, 510, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 0, 296, 297, 298, 299, + 300, 0, 301, 302, 0, 304, 0, 305, 306, 307, + 308, 309, 310, 0, 311, 312, 0, 0, 313, 314, + 315, 0, 0, 316, 317, 0, 319, 0, 321, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 334, 335, 336, 337, 338, 339, 340, 0, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 350, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 0, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 0, 392, 393, 394, 395, 396, + 0, 398, 399, 400, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 512, 415, + 416, 417, 0, 418, 419, 0, 420, 0, 422, 423, + 424, 425, 426, 0, 427, 428, 0, 0, 429, 430, + 431, 432, 433, 0, 434, 435, 436, 437, 438, 439, + 440, 441, 0, 0, 442, 443, 444, 445, 446, 0, + 0, 448, 449, 450, 451, 452, 453, 454, 0, 455, + 0, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, 694, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, + 103, 104, 0, 0, 0, 0, 0, -666, 0, 105, + 106, 0, 107, 108, 109, 695, 111, 112, 113, 0, + 696, 697, 698, 699, 0, 119, 120, 121, 122, 123, + 124, 0, 0, 125, 126, 700, 701, 129, 0, 130, + 131, 132, 133, 0, 0, 702, 0, 136, 137, 138, + 139, 140, 141, 703, 143, 144, 145, 0, 146, 147, + 148, 149, 150, 151, 0, 704, 153, 154, 155, 705, + 706, 707, 708, 0, 0, 709, 161, 162, 163, 164, + 165, 166, 167, 710, 711, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 712, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 0, 199, 200, 201, 202, 203, 0, 0, 205, + 0, 206, 207, 713, 209, 0, 210, 0, 211, 714, + 0, 715, 214, 215, -666, 716, 218, 0, 219, 0, + 0, 0, 222, 0, 223, 224, 225, 226, 227, 228, + 229, 718, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 719, 0, 244, 245, 246, + 247, 248, 720, 721, 0, 722, 0, 252, 723, 724, + 255, 725, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 726, 265, 727, 0, 267, 268, 269, 0, 0, + 270, 271, 272, 273, 274, 728, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 729, 730, 731, 297, 298, 299, + 0, 0, 301, 302, 732, 304, 0, 0, 306, 733, + 308, 309, 310, 0, 311, 312, 0, 0, 313, 314, + 315, 0, 0, 316, 0, 734, 319, 735, 0, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 0, 335, 336, 0, 338, 339, 340, 0, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 736, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 737, 371, 372, 373, 738, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 739, 392, 740, 394, 395, 396, + 741, 398, 399, 742, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 743, 415, + 0, 417, 0, 418, 419, 0, 420, 744, 422, 423, + 424, 425, 426, 0, 745, 746, 0, 0, 429, 430, + 0, 432, 0, 0, 434, 435, 747, 437, 438, 439, + 440, 441, 0, 0, 442, 443, 444, 445, 446, 748, + 0, 448, 449, 450, 451, 452, 0, 749, 0, 455, + 750, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 506, 0, 507, + 0, 0, 0, 0, 0, 0, 0, 0, 480, 481, + 482, 483, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 508, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 511, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 507, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, @@ -259488,476 +277760,285 @@ static const yytype_int16 yytable[] = 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, - 0, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 0, 167, 0, 168, 169, 170, 171, 172, 173, - 0, 174, 175, 176, 177, 178, 0, 0, 179, 180, - 181, 182, 183, 0, 184, 185, 186, 0, 187, 188, - 189, 0, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 0, 201, 0, 202, 203, 204, 205, - 0, 206, 0, 207, 0, 0, 0, 210, 211, 502, - 0, 214, 0, 215, 0, 216, 217, 218, 0, 219, - 220, 221, 222, 223, 224, 225, 0, 227, 228, 229, - 230, 0, 231, 232, 233, 234, 235, 236, 0, 237, - 0, 239, 240, 241, 242, 243, 244, 245, 246, 0, - 247, 0, 248, 0, 0, 251, 0, 253, 254, 255, - 256, 257, 258, 0, 0, 259, 0, 261, 0, 0, - 263, 264, 265, 0, 0, 266, 267, 268, 269, 270, - 503, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 0, 292, 293, 294, 295, 296, 0, 297, 298, 0, - 300, 0, 301, 302, 303, 304, 305, 306, 0, 307, - 308, 0, 583, 309, 310, 311, 0, 0, 312, 313, - 0, 315, 0, 317, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, 0, 328, 329, 330, 331, 332, - 333, 334, 335, 336, 0, 337, 338, 339, 340, 341, - 342, 0, 343, 344, 345, 346, 347, 348, 349, 350, - 0, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 0, 364, 365, 0, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - 379, 380, 381, 0, 382, 383, 384, 385, 386, 0, - 387, 388, 389, 390, 391, 0, 393, 394, 395, 396, - 0, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 505, 410, 411, 412, 0, 413, 414, - 0, 415, 0, 417, 418, 419, 420, 421, 0, 422, - 423, 0, 0, 424, 425, 426, 427, 428, 0, 429, - 430, 431, 432, 433, 434, 435, 436, 0, 0, 437, - 438, 439, 440, 441, 0, 0, 442, 443, 444, 445, - 446, 447, 448, 0, 449, 0, 451, 452, 453, 454, - 455, 0, 0, 456, 0, 0, 457, 458, 459, 460, - 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, - 471, 472, 473, 474, 475, 476, 477, 500, 0, 582, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 614, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, - 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, - 0, 0, 0, 105, 106, 0, 107, 108, 109, 0, - 111, 112, 113, 114, 115, 0, 117, 118, 0, 119, - 120, 121, 122, 123, 124, 0, 0, 125, 126, 127, - 128, 129, 0, 130, 131, 132, 133, 134, 0, 0, - 0, 136, 137, 138, 139, 140, 141, 0, 143, 144, - 145, 0, 146, 147, 148, 149, 150, 151, 0, 0, - 153, 154, 155, 0, 0, 0, 0, 0, 0, 0, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 0, 167, 0, 168, 169, 170, 171, 172, 173, 0, - 174, 175, 176, 177, 178, 0, 0, 179, 180, 181, - 182, 183, 0, 184, 185, 186, 0, 187, 188, 189, - 0, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 0, 201, 0, 202, 203, 204, 205, 0, - 206, 0, 207, 0, 0, 0, 210, 211, 502, 0, - 214, 0, 215, 0, 216, 217, 218, 0, 219, 220, - 221, 222, 223, 626, 225, 0, 227, 228, 229, 230, - 0, 231, 232, 233, 234, 235, 236, 0, 237, 0, - 239, 240, 241, 242, 243, 244, 245, 246, 0, 247, - 0, 248, 0, 0, 251, 0, 253, 254, 255, 256, - 257, 258, 0, 0, 259, 0, 261, 0, 0, 263, - 264, 265, 0, 0, 266, 267, 268, 269, 270, 503, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 0, - 292, 293, 294, 295, 296, 0, 297, 298, 0, 300, - 0, 301, 302, 303, 304, 305, 306, 0, 307, 308, - 0, 583, 309, 310, 311, 0, 0, 312, 313, 0, - 315, 0, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 0, 328, 329, 330, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 339, 340, 341, 342, - 0, 343, 344, 345, 346, 347, 348, 349, 350, 0, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 0, 364, 365, 0, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 0, 382, 383, 384, 385, 386, 0, 387, - 388, 389, 390, 391, 0, 393, 394, 395, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 505, 410, 411, 412, 0, 413, 414, 0, - 415, 0, 417, 418, 419, 420, 421, 0, 422, 423, - 0, 0, 424, 425, 426, 427, 428, 0, 429, 430, - 431, 432, 433, 434, 435, 436, 0, 0, 437, 438, - 439, 440, 441, 0, 0, 442, 443, 444, 445, 446, - 447, 448, 0, 449, 0, 451, 452, 453, 454, 455, - 0, 0, 456, 0, 0, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 749, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 657, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 614, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, - 101, 0, 102, 103, 104, 3, 4, 0, 0, 0, - 0, 0, 105, 106, 0, 107, 108, 109, 0, 111, - 112, 113, 750, 751, 0, 752, 753, 0, 119, 120, - 121, 122, 123, 124, 0, 0, 125, 126, 754, 755, - 129, 0, 130, 131, 132, 133, 756, 0, 0, 0, - 136, 137, 138, 139, 140, 141, 0, 143, 144, 145, - 0, 146, 147, 148, 149, 150, 151, 0, 0, 153, - 154, 155, 0, 0, 0, 0, 0, 0, 0, 157, - 158, 159, 160, 161, 162, 163, 757, 758, 166, 0, - 167, 0, 168, 169, 170, 171, 172, 173, 0, 174, - 175, 176, 177, 178, 0, 0, 179, 180, 181, 182, - 183, 0, 184, 185, 186, 0, 187, 188, 189, 0, - 190, 191, 192, 193, 759, 195, 196, 197, 198, 199, - 760, 0, 201, 0, 202, 203, 761, 205, 0, 206, - 0, 207, 0, 0, 0, 210, 211, 762, 0, 214, - 0, 215, 0, 763, 764, 218, 0, 219, 220, 221, - 222, 223, 224, 225, 0, 227, 228, 229, 230, 0, - 231, 232, 233, 234, 235, 236, 0, 237, 0, 765, - 240, 241, 242, 243, 244, 766, 767, 0, 768, 0, - 248, 0, 0, 251, 0, 253, 254, 255, 256, 257, - 258, 0, 0, 259, 0, 261, 0, 0, 263, 264, - 265, 0, 0, 266, 267, 268, 269, 270, 769, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 770, 0, 771, - 293, 294, 295, 772, 0, 297, 298, 0, 300, 0, - 773, 302, 774, 304, 305, 306, 0, 307, 308, 0, - 0, 309, 310, 311, 0, 0, 312, 775, 0, 315, - 0, 776, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 0, 328, 329, 777, 331, 332, 778, 334, - 335, 336, 0, 337, 338, 339, 340, 341, 342, 0, - 343, 344, 345, 779, 347, 348, 349, 350, 0, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 0, 364, 365, 0, 367, 368, 369, 780, - 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, - 381, 0, 382, 383, 384, 385, 386, 0, 387, 781, - 389, 390, 391, 0, 393, 394, 782, 396, 0, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 783, 410, 784, 412, 0, 413, 414, 0, 415, - 0, 417, 418, 419, 420, 421, 0, 785, 786, 0, - 0, 424, 425, 787, 427, 788, 0, 429, 430, 789, - 432, 433, 434, 435, 436, 0, 0, 437, 438, 439, - 440, 441, 0, 0, 442, 443, 444, 445, 446, 1136, - 791, 0, 449, 0, 451, 452, 453, 454, 455, 0, - 0, 456, 0, 0, 457, 458, 459, 460, 461, 462, - 792, 793, 794, 795, 796, 797, 798, 799, 800, 801, - 802, 474, 475, 476, 477, 500, 0, 582, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 685, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, - 0, 102, 103, 104, 0, 0, 0, 0, 0, 0, - 0, 105, 106, 0, 107, 108, 109, 0, 111, 112, - 113, 114, 115, 0, 117, 118, 0, 119, 120, 121, - 122, 123, 124, 0, 0, 125, 126, 127, 128, 129, - 0, 130, 131, 132, 133, 134, 0, 0, 0, 136, - 137, 138, 139, 140, 141, 0, 143, 144, 145, 0, - 146, 147, 148, 149, 150, 151, 0, 0, 153, 154, - 155, 0, 0, 0, 0, 0, 0, 0, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 0, 167, - 0, 168, 169, 170, 171, 172, 173, 0, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 181, 182, 183, - 0, 184, 185, 186, 0, 187, 188, 189, 0, 190, - 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 0, 201, 0, 202, 203, 204, 205, 0, 206, 0, - 207, 0, 0, 0, 210, 211, 502, 0, 1742, 0, - 215, 0, 216, 217, 218, 0, 219, 220, 221, 222, - 223, 224, 225, 0, 227, 228, 229, 230, 0, 231, - 232, 233, 234, 235, 236, 0, 237, 0, 239, 240, - 241, 242, 243, 244, 245, 246, 0, 247, 0, 248, - 0, 0, 251, 0, 253, 254, 255, 256, 257, 258, - 0, 0, 259, 0, 261, 0, 0, 263, 264, 1743, - 0, 0, 266, 267, 268, 269, 270, 503, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 0, 292, 293, - 294, 295, 296, 0, 297, 298, 0, 300, 0, 301, - 302, 303, 304, 305, 306, 0, 307, 308, 0, 0, - 309, 310, 311, 0, 0, 312, 313, 0, 315, 0, - 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 0, 328, 329, 330, 331, 332, 333, 334, 335, - 336, 0, 337, 338, 339, 340, 341, 342, 0, 343, - 344, 345, 346, 347, 348, 349, 350, 0, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 0, 364, 365, 0, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 0, 382, 383, 384, 385, 386, 0, 387, 388, 389, - 390, 391, 0, 393, 394, 395, 396, 0, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 505, 410, 411, 412, 0, 413, 414, 1744, 415, 0, - 417, 1745, 419, 1746, 421, 0, 422, 423, 0, 0, - 424, 425, 426, 427, 428, 0, 429, 430, 431, 432, - 433, 434, 435, 436, 0, 0, 437, 438, 1747, 440, - 441, 0, 0, 442, 443, 444, 445, 446, 447, 448, - 0, 449, 0, 451, 452, 453, 454, 455, 0, 0, - 456, 0, 0, 457, 458, 459, 460, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 500, 2717, 0, 0, 0, 0, - 2718, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, - 102, 103, 104, 0, 0, 0, 0, 0, 0, 0, - 105, 106, 0, 107, 108, 109, 0, 111, 112, 113, - 114, 115, 0, 117, 118, 0, 119, 120, 121, 122, - 123, 124, 0, 0, 125, 126, 127, 128, 129, 0, - 130, 131, 132, 133, 134, 0, 0, 0, 136, 137, - 138, 139, 140, 141, 0, 143, 144, 145, 0, 146, - 147, 148, 149, 150, 151, 0, 0, 153, 154, 155, - 0, 0, 0, 0, 0, 0, 0, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 0, 167, 0, - 168, 169, 170, 171, 172, 173, 0, 174, 175, 176, - 177, 178, 0, 0, 179, 180, 181, 182, 183, 0, - 184, 185, 186, 0, 187, 188, 189, 0, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 0, - 201, 0, 202, 203, 204, 205, 0, 206, 0, 207, - 0, 0, 0, 210, 211, 502, 0, 214, 0, 215, - 0, 216, 217, 218, 0, 219, 220, 221, 222, 223, - 224, 225, 0, 227, 228, 229, 230, 0, 231, 232, - 233, 234, 235, 236, 0, 237, 0, 239, 240, 241, - 242, 243, 244, 245, 246, 0, 247, 0, 248, 0, - 0, 251, 0, 253, 254, 255, 256, 257, 258, 0, - 0, 259, 0, 261, 0, 0, 263, 264, 265, 0, - 0, 266, 267, 268, 269, 270, 503, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 0, 292, 293, 294, - 295, 296, 0, 297, 298, 0, 300, 0, 301, 302, - 303, 304, 305, 306, 0, 307, 308, 0, 0, 309, - 310, 311, 0, 0, 312, 313, 0, 315, 0, 317, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 0, 328, 329, 330, 331, 332, 333, 334, 335, 336, - 0, 337, 338, 339, 340, 341, 342, 0, 343, 344, - 345, 346, 347, 348, 349, 350, 0, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 0, 364, 365, 0, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, 379, 380, 381, 0, - 382, 383, 384, 385, 386, 0, 387, 388, 389, 390, - 391, 0, 393, 394, 395, 396, 0, 397, 398, 399, - 400, 401, 402, 403, 404, 405, 406, 407, 408, 505, - 410, 411, 412, 0, 413, 414, 0, 415, 0, 417, - 418, 419, 420, 421, 0, 422, 423, 0, 0, 424, - 425, 426, 427, 428, 0, 429, 430, 431, 432, 433, - 434, 435, 436, 0, 0, 437, 438, 439, 440, 441, - 0, 0, 442, 443, 444, 445, 446, 447, 448, 0, - 449, 0, 451, 452, 453, 454, 455, 0, 0, 456, - 0, 0, 457, 458, 459, 460, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 500, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 1804, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 1805, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 1806, 420, 0, 422, 1807, 424, 1808, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 1809, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 2778, 0, + 0, 0, 0, 2779, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 94, 95, 96, 97, 98, 99, 100, 101, 501, 102, - 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, - 106, 0, 107, 108, 109, 0, 111, 112, 113, 114, - 115, 0, 117, 118, 0, 119, 120, 121, 122, 123, - 124, 0, 0, 125, 126, 127, 128, 129, 0, 130, - 131, 132, 133, 134, 0, 0, 0, 136, 137, 138, - 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, - 0, 0, 0, 0, 0, 0, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 0, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 181, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 0, 201, - 0, 202, 203, 204, 205, 0, 206, 0, 207, 0, - 0, 0, 210, 211, 502, 0, 214, 0, 215, 0, - 216, 217, 218, 0, 219, 220, 221, 222, 223, 224, - 225, 0, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 0, 239, 240, 241, 242, - 243, 244, 245, 246, 0, 247, 0, 248, 0, 0, - 251, 0, 253, 254, 255, 256, 257, 258, 0, 0, - 259, 0, 261, 0, 0, 263, 264, 265, 0, 0, - 266, 267, 268, 269, 270, 503, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 0, 292, 293, 294, 295, - 296, 0, 297, 298, 0, 300, 0, 301, 302, 303, - 304, 305, 306, 0, 307, 308, 0, 0, 309, 310, - 311, 0, 0, 312, 313, 0, 315, 0, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 330, 331, 332, 333, 504, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 346, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 0, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 0, 382, - 383, 384, 385, 386, 0, 387, 388, 389, 390, 391, - 0, 393, 394, 395, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 505, 410, - 411, 412, 0, 413, 414, 0, 415, 0, 417, 418, - 419, 420, 421, 0, 422, 423, 0, 0, 424, 425, - 426, 427, 428, 0, 429, 430, 431, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 0, - 0, 442, 443, 444, 445, 446, 447, 448, 0, 449, - 0, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 0, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 500, 0, 550, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, - 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, - 104, 0, 0, 0, 0, 0, 0, 0, 105, 106, - 0, 107, 108, 109, 0, 111, 112, 113, 114, 115, - 0, 117, 118, 0, 119, 120, 121, 122, 123, 124, - 0, 0, 125, 126, 127, 128, 129, 0, 130, 131, - 132, 133, 134, 0, 0, 0, 136, 137, 138, 139, - 140, 141, 0, 143, 144, 145, 0, 146, 147, 148, - 149, 150, 151, 0, 0, 153, 154, 155, 0, 0, - 0, 0, 0, 0, 0, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 0, 167, 0, 168, 169, - 170, 171, 172, 173, 0, 174, 175, 176, 177, 178, - 0, 0, 179, 180, 181, 182, 183, 0, 184, 185, - 186, 0, 187, 188, 189, 0, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 0, 201, 0, - 202, 203, 204, 205, 0, 206, 0, 207, 0, 0, - 0, 210, 211, 502, 0, 214, 0, 215, 0, 216, - 217, 218, 0, 219, 220, 221, 222, 223, 224, 225, - 0, 227, 228, 229, 230, 0, 231, 232, 233, 234, - 235, 236, 0, 237, 0, 239, 240, 241, 242, 243, - 244, 245, 246, 0, 247, 0, 248, 0, 0, 251, - 0, 253, 254, 255, 256, 257, 258, 0, 0, 259, - 0, 261, 0, 0, 263, 264, 265, 0, 0, 266, - 267, 268, 269, 270, 503, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 0, 292, 293, 294, 295, 296, - 0, 297, 298, 0, 300, 0, 301, 302, 303, 304, - 305, 306, 0, 307, 308, 0, 0, 309, 310, 311, - 0, 0, 312, 313, 0, 315, 0, 317, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, 0, 328, - 329, 330, 331, 332, 333, 334, 335, 336, 0, 337, - 338, 339, 340, 341, 342, 0, 343, 344, 345, 346, - 347, 348, 349, 350, 0, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 0, 364, - 365, 0, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, 379, 380, 381, 0, 382, 383, - 384, 385, 386, 0, 387, 388, 389, 390, 391, 0, - 393, 394, 395, 396, 0, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 505, 410, 411, - 412, 0, 413, 414, 0, 415, 0, 417, 418, 419, - 420, 421, 0, 422, 423, 0, 0, 424, 425, 426, - 427, 428, 0, 429, 430, 431, 432, 433, 434, 435, - 436, 0, 0, 437, 438, 439, 440, 441, 0, 0, - 442, 443, 444, 445, 446, 447, 448, 0, 449, 0, - 451, 452, 453, 454, 455, 0, 0, 456, 0, 0, - 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, - 477, 500, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, - 96, 97, 98, 99, 100, 101, 557, 102, 103, 104, - 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, - 107, 108, 109, 0, 111, 112, 113, 114, 115, 0, - 117, 118, 0, 119, 120, 121, 122, 123, 124, 0, - 0, 125, 126, 127, 128, 129, 0, 130, 131, 132, - 133, 134, 0, 0, 0, 136, 137, 138, 139, 140, - 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, - 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, - 0, 0, 0, 0, 157, 158, 159, 160, 161, 162, - 163, 164, 165, 166, 0, 167, 0, 168, 169, 170, - 171, 172, 173, 0, 174, 175, 176, 177, 178, 0, - 0, 179, 180, 181, 182, 183, 0, 184, 185, 186, - 0, 187, 188, 189, 0, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 0, 201, 0, 202, - 203, 204, 205, 0, 206, 0, 207, 0, 0, 0, - 210, 211, 502, 0, 214, 0, 215, 0, 216, 217, - 218, 0, 219, 220, 221, 222, 223, 224, 225, 0, - 227, 228, 229, 230, 0, 231, 232, 233, 234, 235, - 236, 0, 237, 0, 239, 240, 241, 242, 243, 244, - 245, 246, 0, 247, 0, 248, 0, 0, 251, 0, - 253, 254, 255, 256, 257, 258, 0, 0, 259, 0, - 261, 0, 0, 263, 264, 265, 0, 0, 266, 267, - 268, 269, 270, 503, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 0, 292, 293, 294, 295, 296, 0, - 297, 298, 0, 300, 0, 301, 302, 303, 304, 305, - 306, 0, 307, 308, 0, 0, 309, 310, 311, 0, - 0, 312, 313, 0, 315, 0, 317, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 0, 328, 329, - 330, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 339, 340, 341, 342, 0, 343, 344, 345, 346, 347, - 348, 349, 350, 0, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 0, 364, 365, - 0, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 0, 382, 383, 384, - 385, 386, 0, 387, 388, 389, 390, 391, 0, 393, - 394, 395, 396, 0, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 505, 410, 411, 412, - 0, 413, 414, 0, 415, 0, 417, 418, 419, 420, - 421, 0, 558, 423, 0, 0, 559, 425, 426, 427, - 428, 0, 429, 430, 431, 432, 433, 434, 435, 436, - 0, 0, 437, 438, 439, 440, 441, 0, 0, 442, - 443, 444, 445, 446, 447, 448, 0, 449, 0, 451, - 452, 453, 454, 455, 0, 0, 456, 0, 0, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 500, 0, 582, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, - 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, - 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, - 108, 109, 0, 111, 112, 113, 114, 115, 0, 117, - 118, 0, 119, 120, 121, 122, 123, 124, 0, 0, - 125, 126, 127, 128, 129, 0, 130, 131, 132, 133, - 134, 0, 0, 0, 136, 137, 138, 139, 140, 141, - 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, - 151, 0, 0, 153, 154, 155, 0, 0, 0, 0, - 0, 0, 0, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 0, 167, 0, 168, 169, 170, 171, - 172, 173, 0, 174, 175, 176, 177, 178, 0, 0, - 179, 180, 181, 182, 183, 0, 184, 185, 186, 0, - 187, 188, 189, 0, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 0, 201, 0, 202, 203, - 204, 205, 0, 206, 0, 207, 0, 0, 0, 210, - 211, 502, 0, 214, 0, 215, 0, 216, 217, 218, - 0, 219, 220, 221, 222, 223, 621, 225, 0, 227, - 228, 229, 230, 0, 231, 232, 233, 234, 235, 236, - 0, 237, 0, 239, 240, 241, 242, 243, 244, 245, - 246, 0, 247, 0, 248, 0, 0, 251, 0, 253, - 254, 255, 256, 257, 258, 0, 0, 259, 0, 261, - 0, 0, 263, 264, 265, 0, 0, 266, 267, 268, - 269, 270, 503, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 0, 292, 293, 294, 295, 296, 0, 297, - 298, 0, 300, 0, 301, 302, 303, 304, 305, 306, - 0, 307, 308, 0, 0, 309, 310, 311, 0, 0, - 312, 313, 0, 315, 0, 317, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, 0, 328, 329, 330, - 331, 332, 333, 334, 335, 336, 0, 337, 338, 339, - 340, 341, 342, 0, 343, 344, 345, 346, 347, 348, - 349, 350, 0, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 0, 364, 365, 0, - 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, - 377, 378, 379, 380, 381, 0, 382, 383, 384, 385, - 386, 0, 387, 388, 389, 390, 391, 0, 393, 394, - 395, 396, 0, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 505, 410, 411, 412, 0, - 413, 414, 0, 415, 0, 417, 418, 419, 420, 421, - 0, 422, 423, 0, 0, 424, 425, 426, 427, 428, - 0, 429, 430, 431, 432, 433, 434, 435, 436, 0, - 0, 437, 438, 439, 440, 441, 0, 0, 442, 443, - 444, 445, 446, 447, 448, 0, 449, 0, 451, 452, - 453, 454, 455, 0, 0, 456, 0, 0, 457, 458, - 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, 477, 500, - 0, 582, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, - 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, - 0, 0, 0, 0, 0, 105, 106, 0, 107, 108, - 109, 0, 111, 112, 113, 114, 115, 0, 117, 118, - 0, 119, 120, 121, 122, 123, 124, 0, 0, 125, - 126, 127, 128, 129, 0, 130, 131, 132, 133, 134, - 0, 0, 0, 136, 137, 138, 139, 140, 141, 0, - 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, - 0, 0, 153, 154, 155, 0, 0, 0, 0, 0, - 0, 0, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 0, 167, 0, 168, 169, 170, 171, 172, - 173, 0, 174, 175, 176, 177, 178, 0, 0, 179, - 180, 181, 182, 183, 0, 184, 185, 186, 0, 187, - 188, 189, 0, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 0, 201, 0, 202, 203, 204, - 205, 0, 206, 0, 207, 0, 0, 0, 210, 211, - 502, 0, 214, 0, 215, 0, 216, 217, 218, 0, - 219, 220, 221, 222, 223, 624, 225, 0, 227, 228, - 229, 230, 0, 231, 232, 233, 234, 235, 236, 0, - 237, 0, 239, 240, 241, 242, 243, 244, 245, 246, - 0, 247, 0, 248, 0, 0, 251, 0, 253, 254, - 255, 256, 257, 258, 0, 0, 259, 0, 261, 0, - 0, 263, 264, 265, 0, 0, 266, 267, 268, 269, - 270, 503, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 0, 292, 293, 294, 295, 296, 0, 297, 298, - 0, 300, 0, 301, 302, 303, 304, 305, 306, 0, - 307, 308, 0, 0, 309, 310, 311, 0, 0, 312, - 313, 0, 315, 0, 317, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 0, 328, 329, 330, 331, - 332, 333, 334, 335, 336, 0, 337, 338, 339, 340, - 341, 342, 0, 343, 344, 345, 346, 347, 348, 349, - 350, 0, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 0, 364, 365, 0, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 0, 382, 383, 384, 385, 386, - 0, 387, 388, 389, 390, 391, 0, 393, 394, 395, - 396, 0, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 505, 410, 411, 412, 0, 413, - 414, 0, 415, 0, 417, 418, 419, 420, 421, 0, - 422, 423, 0, 0, 424, 425, 426, 427, 428, 0, - 429, 430, 431, 432, 433, 434, 435, 436, 0, 0, - 437, 438, 439, 440, 441, 0, 0, 442, 443, 444, - 445, 446, 447, 448, 0, 449, 0, 451, 452, 453, - 454, 455, 0, 0, 456, 0, 0, 457, 458, 459, - 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 500, 0, - 582, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 582, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, @@ -259967,237 +278048,332 @@ static const yytype_int16 yytable[] = 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, - 0, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 0, 167, 0, 168, 169, 170, 171, 172, 173, - 0, 174, 175, 176, 177, 178, 0, 0, 179, 180, - 181, 182, 183, 0, 184, 185, 186, 0, 187, 188, - 189, 0, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 0, 201, 0, 202, 203, 204, 205, - 0, 206, 0, 207, 0, 0, 0, 210, 211, 502, - 0, 214, 0, 215, 0, 216, 217, 218, 0, 219, - 220, 221, 222, 223, 628, 225, 0, 227, 228, 229, - 230, 0, 231, 232, 233, 234, 235, 236, 0, 237, - 0, 239, 240, 241, 242, 243, 244, 245, 246, 0, - 247, 0, 248, 0, 0, 251, 0, 253, 254, 255, - 256, 257, 258, 0, 0, 259, 0, 261, 0, 0, - 263, 264, 265, 0, 0, 266, 267, 268, 269, 270, - 503, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 0, 292, 293, 294, 295, 296, 0, 297, 298, 0, - 300, 0, 301, 302, 303, 304, 305, 306, 0, 307, - 308, 0, 0, 309, 310, 311, 0, 0, 312, 313, - 0, 315, 0, 317, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, 0, 328, 329, 330, 331, 332, - 333, 334, 335, 336, 0, 337, 338, 339, 340, 341, - 342, 0, 343, 344, 345, 346, 347, 348, 349, 350, - 0, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 0, 364, 365, 0, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - 379, 380, 381, 0, 382, 383, 384, 385, 386, 0, - 387, 388, 389, 390, 391, 0, 393, 394, 395, 396, - 0, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 505, 410, 411, 412, 0, 413, 414, - 0, 415, 0, 417, 418, 419, 420, 421, 0, 422, - 423, 0, 0, 424, 425, 426, 427, 428, 0, 429, - 430, 431, 432, 433, 434, 435, 436, 0, 0, 437, - 438, 439, 440, 441, 0, 0, 442, 443, 444, 445, - 446, 447, 448, 0, 449, 0, 451, 452, 453, 454, - 455, 0, 0, 456, 0, 0, 457, 458, 459, 460, - 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, - 471, 472, 473, 474, 475, 476, 477, 500, 0, 582, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, - 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, - 0, 0, 0, 105, 106, 0, 107, 108, 109, 0, - 111, 112, 113, 114, 115, 0, 117, 118, 0, 119, - 120, 121, 122, 123, 124, 0, 0, 125, 126, 127, - 128, 129, 0, 130, 131, 132, 133, 134, 0, 0, - 0, 136, 137, 138, 139, 140, 141, 0, 143, 144, - 145, 0, 146, 147, 148, 149, 150, 151, 0, 0, - 153, 154, 155, 0, 0, 0, 0, 0, 0, 0, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 0, 167, 0, 168, 169, 170, 171, 172, 173, 0, - 174, 175, 176, 177, 178, 0, 0, 179, 180, 181, - 182, 183, 0, 184, 185, 186, 0, 187, 188, 189, - 0, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 0, 201, 0, 202, 203, 204, 205, 0, - 206, 0, 207, 0, 0, 0, 210, 211, 502, 0, - 214, 0, 215, 0, 216, 217, 218, 0, 219, 220, - 221, 222, 223, 224, 225, 0, 227, 228, 229, 230, - 0, 231, 232, 233, 234, 235, 236, 0, 237, 0, - 239, 240, 241, 242, 243, 244, 245, 246, 0, 247, - 0, 248, 0, 0, 251, 0, 253, 254, 255, 256, - 257, 258, 0, 0, 259, 0, 261, 0, 0, 263, - 264, 265, 0, 0, 266, 267, 268, 269, 270, 503, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 0, - 292, 293, 294, 295, 296, 0, 297, 298, 0, 300, - 0, 301, 302, 303, 304, 305, 306, 0, 307, 308, - 0, 0, 309, 310, 311, 0, 0, 312, 313, 0, - 315, 0, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 0, 328, 329, 330, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 339, 340, 341, 342, - 0, 343, 344, 345, 346, 347, 348, 349, 350, 0, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 0, 364, 365, 0, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 0, 382, 383, 384, 385, 386, 0, 387, - 388, 389, 390, 391, 0, 393, 394, 395, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 505, 410, 411, 412, 0, 413, 414, 0, - 415, 0, 417, 418, 419, 420, 421, 0, 422, 423, - 0, 0, 424, 425, 426, 427, 428, 0, 429, 430, - 431, 432, 433, 434, 435, 436, 0, 0, 437, 438, - 439, 440, 441, 0, 0, 442, 443, 444, 445, 446, - 447, 448, 0, 449, 0, 451, 452, 453, 454, 455, - 0, 0, 456, 0, 0, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 500, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 589, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 590, + 428, 0, 0, 591, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, - 101, 658, 102, 103, 104, 0, 0, 0, 0, 0, - 0, 0, 105, 106, 0, 107, 108, 109, 0, 111, - 112, 113, 114, 115, 0, 117, 118, 0, 119, 120, - 121, 122, 123, 124, 0, 0, 125, 126, 127, 128, - 129, 0, 130, 131, 132, 133, 134, 0, 0, 0, - 136, 137, 138, 139, 140, 141, 0, 143, 144, 145, - 0, 146, 147, 148, 149, 150, 151, 0, 0, 153, - 154, 155, 0, 0, 0, 0, 0, 0, 0, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 0, - 167, 0, 168, 169, 170, 171, 172, 173, 0, 174, - 175, 176, 177, 178, 0, 0, 179, 180, 181, 182, - 183, 0, 184, 185, 186, 0, 187, 188, 189, 0, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 0, 201, 0, 202, 203, 204, 205, 0, 206, - 0, 207, 0, 0, 0, 210, 211, 502, 0, 214, - 0, 215, 0, 216, 217, 218, 0, 219, 220, 221, - 222, 223, 224, 225, 0, 227, 228, 229, 230, 0, - 231, 232, 233, 234, 235, 236, 0, 237, 0, 239, - 240, 241, 242, 243, 244, 245, 246, 0, 247, 0, - 248, 0, 0, 251, 0, 253, 254, 255, 256, 257, - 258, 0, 0, 259, 0, 261, 0, 0, 263, 264, - 265, 0, 0, 266, 267, 268, 269, 270, 503, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 290, 0, 292, - 293, 294, 295, 296, 0, 297, 298, 0, 300, 0, - 301, 302, 303, 304, 305, 306, 0, 307, 308, 0, - 0, 309, 310, 311, 0, 0, 312, 313, 0, 315, - 0, 317, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 0, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 339, 340, 341, 342, 0, - 343, 344, 345, 346, 347, 348, 349, 350, 0, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 0, 364, 365, 0, 367, 368, 369, 370, - 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, - 381, 0, 382, 383, 384, 385, 386, 0, 387, 388, - 389, 390, 391, 0, 393, 394, 395, 396, 0, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 505, 410, 411, 412, 0, 413, 414, 0, 415, - 0, 417, 418, 419, 420, 421, 0, 422, 423, 0, - 0, 424, 425, 426, 427, 428, 0, 429, 430, 431, - 432, 433, 434, 435, 436, 0, 0, 437, 438, 439, - 440, 441, 0, 0, 442, 443, 444, 445, 446, 447, - 448, 0, 449, 0, 451, 452, 453, 454, 455, 0, - 0, 456, 0, 0, 457, 458, 459, 460, 461, 462, - 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, - 473, 474, 475, 476, 477, 500, 0, 582, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 623, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, - 0, 102, 103, 104, 0, 0, 0, 0, 0, 0, - 0, 105, 106, 0, 107, 108, 109, 0, 111, 112, - 113, 114, 115, 0, 117, 118, 0, 119, 120, 121, - 122, 123, 124, 0, 0, 125, 126, 127, 128, 129, - 0, 130, 131, 132, 133, 134, 0, 0, 0, 136, - 137, 138, 139, 140, 141, 0, 143, 144, 145, 0, - 146, 147, 148, 149, 150, 151, 0, 0, 153, 154, - 155, 0, 0, 0, 0, 0, 0, 0, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 0, 167, - 0, 168, 169, 170, 171, 172, 173, 0, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 181, 182, 183, - 0, 184, 185, 186, 0, 187, 188, 189, 0, 190, - 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 0, 201, 0, 202, 203, 204, 205, 0, 206, 0, - 207, 0, 0, 0, 210, 211, 502, 0, 214, 0, - 215, 0, 216, 217, 218, 0, 219, 220, 221, 222, - 223, 1158, 225, 0, 227, 228, 229, 230, 0, 231, - 232, 233, 234, 235, 236, 0, 237, 0, 239, 240, - 241, 242, 243, 244, 245, 246, 0, 247, 0, 248, - 0, 0, 251, 0, 253, 254, 255, 256, 257, 258, - 0, 0, 259, 0, 261, 0, 0, 263, 264, 265, - 0, 0, 266, 267, 268, 269, 270, 503, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 0, 292, 293, - 294, 295, 296, 0, 297, 298, 0, 300, 0, 301, - 302, 303, 304, 305, 306, 0, 307, 308, 0, 0, - 309, 310, 311, 0, 0, 312, 313, 0, 315, 0, - 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 0, 328, 329, 330, 331, 332, 333, 334, 335, - 336, 0, 337, 338, 339, 340, 341, 342, 0, 343, - 344, 345, 346, 347, 348, 349, 350, 0, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 0, 364, 365, 0, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 0, 382, 383, 384, 385, 386, 0, 387, 388, 389, - 390, 391, 0, 393, 394, 395, 396, 0, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 505, 410, 411, 412, 0, 413, 414, 0, 415, 0, - 417, 418, 419, 420, 421, 0, 422, 423, 0, 0, - 424, 425, 426, 427, 428, 0, 429, 430, 431, 432, - 433, 434, 435, 436, 0, 0, 437, 438, 439, 440, - 441, 0, 0, 442, 443, 444, 445, 446, 447, 448, - 0, 449, 0, 451, 452, 453, 454, 455, 0, 0, - 456, 0, 0, 457, 458, 459, 460, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 500, 0, 582, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 652, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, - 102, 103, 104, 0, 0, 0, 0, 0, 0, 0, - 105, 106, 0, 107, 108, 109, 0, 111, 112, 113, - 114, 115, 0, 117, 118, 0, 119, 120, 121, 122, - 123, 124, 0, 0, 125, 126, 127, 128, 129, 0, - 130, 131, 132, 133, 134, 0, 0, 0, 136, 137, - 138, 139, 140, 141, 0, 143, 144, 145, 0, 146, - 147, 148, 149, 150, 151, 0, 0, 153, 154, 155, - 0, 0, 0, 0, 0, 0, 0, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 0, 167, 0, - 168, 169, 170, 171, 172, 173, 0, 174, 175, 176, - 177, 178, 0, 0, 179, 180, 181, 182, 183, 0, - 184, 185, 186, 0, 187, 188, 189, 0, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 0, - 201, 0, 202, 203, 204, 205, 0, 206, 0, 207, - 0, 0, 0, 210, 211, 502, 0, 214, 0, 215, - 0, 216, 217, 218, 0, 219, 220, 221, 222, 223, - 1160, 225, 0, 227, 228, 229, 230, 0, 231, 232, - 233, 234, 235, 236, 0, 237, 0, 239, 240, 241, - 242, 243, 244, 245, 246, 0, 247, 0, 248, 0, - 0, 251, 0, 253, 254, 255, 256, 257, 258, 0, - 0, 259, 0, 261, 0, 0, 263, 264, 265, 0, - 0, 266, 267, 268, 269, 270, 503, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 0, 292, 293, 294, - 295, 296, 0, 297, 298, 0, 300, 0, 301, 302, - 303, 304, 305, 306, 0, 307, 308, 0, 0, 309, - 310, 311, 0, 0, 312, 313, 0, 315, 0, 317, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 0, 328, 329, 330, 331, 332, 333, 334, 335, 336, - 0, 337, 338, 339, 340, 341, 342, 0, 343, 344, - 345, 346, 347, 348, 349, 350, 0, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 0, 364, 365, 0, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, 379, 380, 381, 0, - 382, 383, 384, 385, 386, 0, 387, 388, 389, 390, - 391, 0, 393, 394, 395, 396, 0, 397, 398, 399, - 400, 401, 402, 403, 404, 405, 406, 407, 408, 505, - 410, 411, 412, 0, 413, 414, 0, 415, 0, 417, - 418, 419, 420, 421, 0, 422, 423, 0, 0, 424, - 425, 426, 427, 428, 0, 429, 430, 431, 432, 433, - 434, 435, 436, 0, 0, 437, 438, 439, 440, 441, - 0, 0, 442, 443, 444, 445, 446, 447, 448, 0, - 449, 0, 451, 452, 453, 454, 455, 0, 0, 456, - 0, 0, 457, 458, 459, 460, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 500, 0, 582, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 655, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 507, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 659, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 694, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 695, 111, 112, 113, 0, 696, 697, 698, 699, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 700, 701, 129, 0, 130, 131, 132, 133, 0, 0, + 702, 0, 136, 137, 138, 139, 140, 141, 703, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 704, 153, 154, 155, 705, 706, 707, 708, 0, 0, + 709, 161, 162, 163, 164, 165, 166, 167, 710, 711, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 712, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 0, 199, 200, 201, + 202, 203, 0, 0, 205, 0, 206, 207, 713, 209, + 0, 210, 0, 211, 714, 0, 715, 214, 215, 0, + 716, 218, 0, 219, 0, 0, 0, 222, 0, 223, + 224, 225, 226, 227, 717, 229, 718, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 719, 0, 244, 245, 246, 247, 248, 720, 721, 0, + 722, 0, 252, 723, 724, 255, 725, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 726, 265, 727, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 728, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 729, + 730, 731, 297, 298, 299, 0, 0, 301, 302, 732, + 304, 0, 0, 306, 733, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 0, + 734, 319, 735, 0, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 0, 335, 336, + 0, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 736, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 737, 371, 372, + 373, 738, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 739, + 392, 740, 394, 395, 396, 741, 398, 399, 742, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 743, 415, 0, 417, 0, 418, 419, + 0, 420, 744, 422, 423, 424, 425, 426, 0, 745, + 746, 0, 0, 429, 430, 0, 432, 0, 0, 434, + 435, 747, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 748, 0, 448, 449, 450, 451, + 452, 0, 749, 0, 455, 750, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 506, 0, 507, 0, 0, 0, 0, 0, + 0, 0, 0, 480, 481, 482, 483, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, 0, 111, 112, 113, 114, @@ -260206,236 +278382,379 @@ static const yytype_int16 yytable[] = 131, 132, 133, 134, 0, 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, - 0, 0, 0, 0, 0, 0, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 0, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 181, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 0, 201, - 0, 202, 203, 204, 205, 0, 206, 0, 207, 0, - 0, 0, 210, 211, 502, 0, 214, 0, 215, 0, - 216, 217, 218, 0, 219, 220, 221, 222, 223, 1573, - 225, 0, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 0, 239, 240, 241, 242, - 243, 244, 245, 246, 0, 247, 0, 248, 0, 0, - 251, 0, 253, 254, 255, 256, 257, 258, 0, 0, - 259, 0, 261, 0, 0, 263, 264, 265, 0, 0, - 266, 267, 268, 269, 270, 503, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 0, 292, 293, 294, 295, - 296, 0, 297, 298, 0, 300, 0, 301, 302, 303, - 304, 305, 306, 0, 307, 308, 0, 0, 309, 310, - 311, 0, 0, 312, 313, 0, 315, 0, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 330, 331, 332, 333, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 346, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 0, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 0, 382, - 383, 384, 385, 386, 0, 387, 388, 389, 390, 391, - 0, 393, 394, 395, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 505, 410, - 411, 412, 0, 413, 414, 0, 415, 0, 417, 418, - 419, 420, 421, 0, 422, 423, 0, 0, 424, 425, - 426, 427, 428, 0, 429, 430, 431, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 0, - 0, 442, 443, 444, 445, 446, 447, 448, 0, 449, - 0, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 0, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 500, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, - 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, - 104, 0, 0, 0, 0, 0, 2345, 0, 105, 106, - 0, 107, 108, 109, 0, 111, 112, 113, 114, 115, - 0, 117, 118, 0, 119, 120, 121, 122, 123, 124, - 0, 0, 125, 126, 127, 128, 129, 0, 130, 131, - 132, 133, 134, 0, 0, 0, 136, 137, 138, 139, - 140, 141, 0, 143, 144, 145, 0, 146, 147, 148, - 149, 150, 151, 0, 0, 153, 154, 155, 0, 0, - 0, 0, 0, 0, 0, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 0, 167, 0, 168, 169, - 170, 171, 172, 173, 0, 174, 175, 176, 177, 178, - 0, 0, 179, 180, 181, 182, 183, 0, 184, 185, - 186, 0, 187, 188, 189, 0, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 0, 201, 0, - 202, 203, 204, 205, 0, 206, 0, 207, 0, 0, - 0, 210, 211, 502, 0, 214, 0, 215, 0, 216, - 217, 218, 0, 219, 220, 221, 222, 223, 224, 225, - 0, 227, 228, 229, 230, 0, 231, 232, 233, 234, - 235, 236, 0, 237, 0, 239, 240, 241, 242, 243, - 244, 245, 246, 0, 247, 0, 248, 0, 0, 251, - 0, 253, 254, 255, 256, 257, 258, 0, 0, 259, - 0, 261, 0, 0, 263, 264, 265, 0, 0, 266, - 267, 268, 269, 270, 503, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 0, 292, 293, 294, 295, 296, - 0, 297, 298, 0, 300, 0, 301, 302, 303, 304, - 305, 306, 0, 307, 308, 0, 0, 309, 310, 311, - 0, 0, 312, 313, 0, 315, 0, 317, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, 0, 328, - 329, 330, 331, 332, 333, 334, 335, 336, 0, 337, - 338, 339, 340, 341, 342, 0, 343, 344, 345, 346, - 347, 348, 349, 350, 0, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 0, 364, - 365, 0, 367, 368, 369, 370, 371, 372, 373, 374, - 375, 376, 377, 378, 379, 380, 381, 0, 382, 383, - 384, 385, 386, 0, 387, 388, 389, 390, 391, 0, - 393, 394, 395, 396, 0, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 505, 410, 411, - 412, 0, 413, 414, 0, 415, 0, 417, 418, 419, - 420, 421, 0, 422, 423, 0, 0, 424, 425, 426, - 427, 428, 0, 429, 430, 431, 432, 433, 434, 435, - 436, 0, 0, 437, 438, 439, 440, 441, 0, 0, - 442, 443, 444, 445, 446, 447, 448, 0, 449, 0, - 451, 452, 453, 454, 455, 0, 0, 456, 0, 0, - 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, - 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, - 477, 500, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, - 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, - 0, 0, 0, 0, 0, 2359, 0, 105, 106, 0, - 107, 108, 109, 0, 111, 112, 113, 114, 115, 0, - 117, 118, 0, 119, 120, 121, 122, 123, 124, 0, - 0, 125, 126, 127, 128, 129, 0, 130, 131, 132, - 133, 134, 0, 0, 0, 136, 137, 138, 139, 140, - 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, - 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, - 0, 0, 0, 0, 157, 158, 159, 160, 161, 162, - 163, 164, 165, 166, 0, 167, 0, 168, 169, 170, - 171, 172, 173, 0, 174, 175, 176, 177, 178, 0, - 0, 179, 180, 181, 182, 183, 0, 184, 185, 186, - 0, 187, 188, 189, 0, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 0, 201, 0, 202, - 203, 204, 205, 0, 206, 0, 207, 0, 0, 0, - 210, 211, 502, 0, 214, 0, 215, 0, 216, 217, - 218, 0, 219, 220, 221, 222, 223, 224, 225, 0, - 227, 228, 229, 230, 0, 231, 232, 233, 234, 235, - 236, 0, 237, 0, 239, 240, 241, 242, 243, 244, - 245, 246, 0, 247, 0, 248, 0, 0, 251, 0, - 253, 254, 255, 256, 257, 258, 0, 0, 259, 0, - 261, 0, 0, 263, 264, 265, 0, 0, 266, 267, - 268, 269, 270, 503, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 0, 292, 293, 294, 295, 296, 0, - 297, 298, 0, 300, 0, 301, 302, 303, 304, 305, - 306, 0, 307, 308, 0, 0, 309, 310, 311, 0, - 0, 312, 313, 0, 315, 0, 317, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 0, 328, 329, - 330, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 339, 340, 341, 342, 0, 343, 344, 345, 346, 347, - 348, 349, 350, 0, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 0, 364, 365, - 0, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 0, 382, 383, 384, - 385, 386, 0, 387, 388, 389, 390, 391, 0, 393, - 394, 395, 396, 0, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 505, 410, 411, 412, - 0, 413, 414, 0, 415, 0, 417, 418, 419, 420, - 421, 0, 422, 423, 0, 0, 424, 425, 426, 427, - 428, 0, 429, 430, 431, 432, 433, 434, 435, 436, - 0, 0, 437, 438, 439, 440, 441, 0, 0, 442, - 443, 444, 445, 446, 447, 448, 0, 449, 0, 451, - 452, 453, 454, 455, 0, 0, 456, 0, 0, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 500, 0, 582, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, - 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, - 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, - 108, 109, 0, 111, 112, 113, 114, 115, 0, 117, - 118, 0, 119, 120, 121, 122, 123, 124, 0, 0, - 125, 126, 127, 128, 129, 0, 130, 131, 132, 133, - 134, 0, 0, 0, 136, 137, 138, 139, 140, 141, - 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, - 151, 0, 0, 153, 154, 155, 0, 0, 0, 0, - 0, 0, 0, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 0, 167, 0, 168, 169, 170, 171, - 172, 173, 0, 174, 175, 176, 177, 178, 0, 0, - 179, 180, 181, 182, 183, 0, 184, 185, 186, 0, - 187, 188, 189, 0, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 0, 201, 0, 202, 203, - 204, 205, 0, 206, 0, 207, 0, 0, 0, 210, - 211, 502, 0, 214, 0, 215, 0, 216, 217, 218, - 0, 219, 220, 221, 222, 223, 2515, 225, 0, 227, - 228, 229, 230, 0, 231, 232, 233, 234, 235, 236, - 0, 237, 0, 239, 240, 241, 242, 243, 244, 245, - 246, 0, 247, 0, 248, 0, 0, 251, 0, 253, - 254, 255, 256, 257, 258, 0, 0, 259, 0, 261, - 0, 0, 263, 264, 265, 0, 0, 266, 267, 268, - 269, 270, 503, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 0, 292, 293, 294, 295, 296, 0, 297, - 298, 0, 300, 0, 301, 302, 303, 304, 305, 306, - 0, 307, 308, 0, 0, 309, 310, 311, 0, 0, - 312, 313, 0, 315, 0, 317, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, 0, 328, 329, 330, - 331, 332, 333, 334, 335, 336, 0, 337, 338, 339, - 340, 341, 342, 0, 343, 344, 345, 346, 347, 348, - 349, 350, 0, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 0, 364, 365, 0, - 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, - 377, 378, 379, 380, 381, 0, 382, 383, 384, 385, - 386, 0, 387, 388, 389, 390, 391, 0, 393, 394, - 395, 396, 0, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 505, 410, 411, 412, 0, - 413, 414, 0, 415, 0, 417, 418, 419, 420, 421, - 0, 422, 423, 0, 0, 424, 425, 426, 427, 428, - 0, 429, 430, 431, 432, 433, 434, 435, 436, 0, - 0, 437, 438, 439, 440, 441, 0, 0, 442, 443, - 444, 445, 446, 447, 448, 0, 449, 0, 451, 452, - 453, 454, 455, 0, 0, 456, 0, 0, 457, 458, - 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, 477, 500, + 0, 0, 0, 0, 0, 0, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 185, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 0, 205, + 0, 206, 207, 208, 209, 0, 210, 0, 211, 0, + 0, 0, 214, 215, 509, 0, 218, 0, 219, 0, + 220, 221, 222, 0, 223, 224, 225, 226, 227, 772, + 229, 0, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 0, 243, 244, 245, 246, + 247, 248, 249, 250, 0, 251, 0, 252, 0, 0, + 255, 0, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 0, 265, 0, 0, 267, 268, 269, 0, 0, + 270, 271, 272, 273, 274, 510, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 0, 296, 297, 298, 299, + 300, 0, 301, 302, 0, 304, 0, 305, 306, 307, + 308, 309, 310, 0, 311, 312, 0, 0, 313, 314, + 315, 0, 0, 316, 317, 0, 319, 0, 321, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 334, 335, 336, 337, 338, 339, 340, 0, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 350, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 0, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 0, 392, 393, 394, 395, 396, + 0, 398, 399, 400, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 512, 415, + 416, 417, 0, 418, 419, 0, 420, 0, 422, 423, + 424, 425, 426, 0, 427, 428, 0, 0, 429, 430, + 431, 432, 433, 0, 434, 435, 436, 437, 438, 439, + 440, 441, 0, 0, 442, 443, 444, 445, 446, 0, + 0, 448, 449, 450, 451, 452, 453, 454, 0, 455, + 0, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, 506, 0, 507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, - 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, - 0, 0, 0, 0, 0, 105, 106, 0, 107, 108, - 109, 0, 111, 112, 113, 114, 115, 0, 117, 118, - 0, 119, 120, 121, 122, 123, 124, 0, 0, 125, - 126, 127, 128, 129, 0, 130, 131, 132, 133, 134, - 0, 0, 0, 136, 137, 138, 139, 140, 141, 0, - 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, - 0, 0, 153, 154, 155, 0, 0, 0, 0, 0, - 0, 0, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 0, 167, 0, 168, 169, 170, 171, 172, - 173, 0, 174, 175, 176, 177, 178, 0, 0, 179, - 180, 181, 182, 183, 0, 184, 185, 186, 0, 187, - 188, 189, 0, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 0, 201, 0, 202, 203, 204, - 205, 0, 206, 0, 207, 0, 0, 0, 210, 211, - 502, 0, 214, 0, 215, 0, 216, 217, 218, 0, - 219, 220, 221, 222, 223, 224, 225, 0, 227, 228, - 229, 230, 0, 231, 232, 233, 234, 235, 236, 0, - 237, 0, 239, 240, 241, 242, 243, 244, 245, 246, - 0, 247, 0, 248, 0, 0, 251, 0, 253, 254, - 255, 256, 257, 258, 0, 0, 259, 0, 261, 0, - 0, 263, 264, 265, 0, 0, 266, 267, 268, 269, - 270, 503, 272, 273, 274, 275, 276, 277, 278, 279, + 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, + 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, + 106, 0, 107, 108, 109, 0, 111, 112, 113, 114, + 115, 0, 117, 118, 0, 119, 120, 121, 122, 123, + 124, 0, 0, 125, 126, 127, 128, 129, 0, 130, + 131, 132, 133, 134, 0, 0, 0, 136, 137, 138, + 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, + 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, + 0, 0, 0, 0, 0, 0, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 185, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 0, 205, + 0, 206, 207, 208, 209, 0, 210, 0, 211, 0, + 0, 0, 214, 215, 509, 0, 218, 0, 219, 0, + 220, 221, 222, 0, 223, 224, 225, 226, 227, 775, + 229, 0, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 0, 243, 244, 245, 246, + 247, 248, 249, 250, 0, 251, 0, 252, 0, 0, + 255, 0, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 0, 265, 0, 0, 267, 268, 269, 0, 0, + 270, 271, 272, 273, 274, 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 0, 292, 293, 294, 295, 296, 0, 297, 298, - 0, 300, 0, 301, 302, 303, 304, 305, 306, 0, - 307, 308, 0, 0, 309, 310, 311, 0, 0, 312, - 313, 0, 315, 0, 317, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 0, 328, 329, 330, 331, - 332, 333, 334, 335, 336, 0, 337, 338, 339, 340, - 341, 342, 0, 343, 344, 345, 346, 347, 348, 349, - 350, 0, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 0, 364, 365, 0, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 0, 382, 383, 384, 385, 386, - 0, 387, 388, 389, 390, 391, 0, 393, 394, 395, - 396, 0, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 505, 410, 411, 412, 0, 413, - 414, 0, 415, 0, 417, 418, 419, 420, 421, 0, - 422, 423, 0, 0, 424, 425, 426, 427, 428, 0, - 429, 430, 431, 432, 433, 434, 435, 436, 0, 0, - 437, 438, 439, 440, 441, 0, 0, 442, 443, 444, - 445, 446, 447, 448, 0, 449, 0, 451, 452, 453, - 454, 455, 0, 0, 456, 0, 0, 457, 458, 459, - 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 500, 0, + 290, 291, 292, 293, 294, 0, 296, 297, 298, 299, + 300, 0, 301, 302, 0, 304, 0, 305, 306, 307, + 308, 309, 310, 0, 311, 312, 0, 0, 313, 314, + 315, 0, 0, 316, 317, 0, 319, 0, 321, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 334, 335, 336, 337, 338, 339, 340, 0, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 350, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 0, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 0, 392, 393, 394, 395, 396, + 0, 398, 399, 400, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 512, 415, + 416, 417, 0, 418, 419, 0, 420, 0, 422, 423, + 424, 425, 426, 0, 427, 428, 0, 0, 429, 430, + 431, 432, 433, 0, 434, 435, 436, 437, 438, 439, + 440, 441, 0, 0, 442, 443, 444, 445, 446, 0, + 0, 448, 449, 450, 451, 452, 453, 454, 0, 455, + 0, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, 506, 0, 507, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, + 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, + 106, 0, 107, 108, 109, 0, 111, 112, 113, 114, + 115, 0, 117, 118, 0, 119, 120, 121, 122, 123, + 124, 0, 0, 125, 126, 127, 128, 129, 0, 130, + 131, 132, 133, 134, 0, 0, 0, 136, 137, 138, + 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, + 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, + 0, 0, 0, 0, 0, 0, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 185, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 0, 205, + 0, 206, 207, 208, 209, 0, 210, 0, 211, 0, + 0, 0, 214, 215, 509, 0, 218, 0, 219, 0, + 220, 221, 222, 0, 223, 224, 225, 226, 227, 1219, + 229, 0, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 0, 243, 244, 245, 246, + 247, 248, 249, 250, 0, 251, 0, 252, 0, 0, + 255, 0, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 0, 265, 0, 0, 267, 268, 269, 0, 0, + 270, 271, 272, 273, 274, 510, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 0, 296, 297, 298, 299, + 300, 0, 301, 302, 0, 304, 0, 305, 306, 307, + 308, 309, 310, 0, 311, 312, 0, 0, 313, 314, + 315, 0, 0, 316, 317, 0, 319, 0, 321, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 334, 335, 336, 337, 338, 339, 340, 0, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 350, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 0, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 0, 392, 393, 394, 395, 396, + 0, 398, 399, 400, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 512, 415, + 416, 417, 0, 418, 419, 0, 420, 0, 422, 423, + 424, 425, 426, 0, 427, 428, 0, 0, 429, 430, + 431, 432, 433, 0, 434, 435, 436, 437, 438, 439, + 440, 441, 0, 0, 442, 443, 444, 445, 446, 0, + 0, 448, 449, 450, 451, 452, 453, 454, 0, 455, + 0, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, 506, 0, 507, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, + 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, + 106, 0, 107, 108, 109, 0, 111, 112, 113, 114, + 115, 0, 117, 118, 0, 119, 120, 121, 122, 123, + 124, 0, 0, 125, 126, 127, 128, 129, 0, 130, + 131, 132, 133, 134, 0, 0, 0, 136, 137, 138, + 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, + 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, + 0, 0, 0, 0, 0, 0, 161, 162, 163, 164, + 165, 166, 167, 168, 169, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 185, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 198, 199, 200, 201, 202, 203, 204, 0, 205, + 0, 206, 207, 208, 209, 0, 210, 0, 211, 0, + 0, 0, 214, 215, 509, 0, 218, 0, 219, 0, + 220, 221, 222, 0, 223, 224, 225, 226, 227, 1221, + 229, 0, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 0, 243, 244, 245, 246, + 247, 248, 249, 250, 0, 251, 0, 252, 0, 0, + 255, 0, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 0, 265, 0, 0, 267, 268, 269, 0, 0, + 270, 271, 272, 273, 274, 510, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 294, 0, 296, 297, 298, 299, + 300, 0, 301, 302, 0, 304, 0, 305, 306, 307, + 308, 309, 310, 0, 311, 312, 0, 0, 313, 314, + 315, 0, 0, 316, 317, 0, 319, 0, 321, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 334, 335, 336, 337, 338, 339, 340, 0, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 350, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 0, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 0, 392, 393, 394, 395, 396, + 0, 398, 399, 400, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 512, 415, + 416, 417, 0, 418, 419, 0, 420, 0, 422, 423, + 424, 425, 426, 0, 427, 428, 0, 0, 429, 430, + 431, 432, 433, 0, 434, 435, 436, 437, 438, 439, + 440, 441, 0, 0, 442, 443, 444, 445, 446, 0, + 0, 448, 449, 450, 451, 452, 453, 454, 0, 455, + 0, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, 694, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, + 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, + 106, 0, 107, 108, 109, 695, 111, 112, 113, 0, + 696, 697, 698, 699, 0, 119, 120, 121, 122, 123, + 124, 0, 0, 125, 126, 700, 701, 129, 0, 130, + 131, 132, 133, 0, 0, 702, 0, 136, 137, 138, + 139, 140, 141, 703, 143, 144, 145, 0, 146, 147, + 148, 149, 150, 151, 0, 704, 153, 154, 155, 705, + 706, 707, 708, 0, 0, 709, 161, 162, 163, 164, + 165, 166, 167, 710, 711, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 712, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 0, 199, 200, 201, 202, 203, 0, 0, 205, + 0, 206, 207, 713, 209, 0, 210, 0, 211, 714, + 0, 715, 214, 215, 0, 716, 218, 0, 219, 0, + 0, 0, 222, 0, 223, 224, 225, 226, 227, 228, + 229, 718, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 719, 0, 244, 245, 246, + 247, 248, 720, 721, 0, 722, 0, 252, 723, 724, + 255, 725, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 726, 265, 727, 0, 267, 268, 269, 0, 0, + 270, 271, 272, 273, 274, 728, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 729, 730, 731, 297, 298, 299, + 0, 0, 301, 302, 732, 304, 0, 0, 306, 733, + 308, 309, 310, 0, 311, 312, 0, 0, 313, 314, + 315, 0, 0, 316, 0, 734, 319, 735, 0, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 0, 335, 336, 0, 338, 339, 340, 0, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 736, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 737, 371, 372, 373, 738, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 739, 392, 740, 394, 395, 396, + 741, 398, 399, 742, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 743, 415, + 0, 417, 0, 418, 419, 0, 420, 744, 422, 423, + 424, 425, 426, 0, 745, 746, 0, 0, 429, 430, + 0, 432, 0, 0, 434, 435, 747, 437, 438, 439, + 440, 441, 0, 0, 442, 443, 444, 445, 446, 748, + 0, 448, 449, 450, 451, 452, 0, 749, 0, 455, + 750, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 506, 0, 507, + 0, 0, 0, 0, 0, 0, 0, 0, 480, 481, + 482, 483, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 1897, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 2403, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 2418, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 507, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, @@ -260446,475 +278765,332 @@ static const yytype_int16 yytable[] = 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, - 0, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 0, 167, 0, 168, 169, 170, 171, 172, 173, - 0, 174, 175, 176, 177, 178, 0, 0, 179, 180, - 181, 182, 183, 0, 184, 185, 186, 0, 187, 188, - 189, 0, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 0, 201, 0, 202, 203, 204, 205, - 0, 206, 0, 207, 0, 0, 0, 210, 211, 502, - 0, 569, 0, 215, 0, 216, 217, 218, 0, 219, - 220, 221, 222, 223, 224, 225, 0, 227, 228, 229, - 230, 0, 231, 232, 233, 234, 235, 236, 0, 237, - 0, 239, 240, 241, 242, 243, 244, 245, 246, 0, - 247, 0, 248, 0, 0, 251, 0, 253, 254, 255, - 256, 257, 258, 0, 0, 259, 0, 261, 0, 0, - 263, 264, 570, 0, 0, 266, 267, 268, 269, 270, - 503, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 0, 292, 293, 294, 295, 296, 0, 297, 298, 0, - 300, 0, 301, 302, 303, 304, 305, 306, 0, 307, - 308, 0, 0, 309, 310, 311, 0, 0, 312, 313, - 0, 315, 0, 317, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, 0, 328, 329, 330, 331, 332, - 333, 334, 335, 336, 0, 337, 338, 339, 340, 341, - 342, 0, 343, 344, 345, 346, 347, 348, 349, 350, - 0, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 0, 364, 365, 0, 367, 368, - 369, 370, 371, 372, 373, 374, 571, 376, 377, 378, - 379, 380, 381, 0, 382, 383, 384, 385, 572, 0, - 387, 388, 389, 390, 391, 0, 393, 394, 395, 396, - 0, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 505, 410, 411, 412, 0, 413, 414, - 0, 415, 0, 417, 418, 419, 420, 421, 0, 573, - 423, 0, 0, 424, 425, 426, 427, 428, 0, 429, - 430, 431, 432, 433, 434, 435, 436, 0, 0, 437, - 438, 439, 440, 441, 0, 0, 442, 443, 444, 445, - 446, 447, 448, 0, 449, 0, 451, 452, 453, 454, - 455, 0, 0, 456, 0, 0, 457, 458, 459, 460, - 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, - 471, 472, 473, 474, 475, 476, 477, 500, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 2580, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, - 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, - 0, 0, 0, 105, 106, 0, 107, 108, 109, 0, - 111, 112, 113, 114, 115, 0, 117, 118, 0, 119, - 120, 121, 122, 123, 124, 0, 0, 125, 126, 127, - 128, 129, 0, 130, 131, 132, 133, 134, 0, 0, - 0, 136, 137, 138, 139, 140, 141, 0, 143, 144, - 145, 0, 146, 147, 148, 149, 150, 151, 0, 0, - 153, 154, 155, 0, 0, 0, 0, 0, 0, 0, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 0, 167, 0, 168, 169, 170, 171, 172, 173, 0, - 174, 175, 176, 177, 178, 0, 0, 179, 180, 181, - 182, 183, 0, 184, 185, 186, 0, 187, 188, 189, - 0, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 0, 201, 0, 202, 203, 204, 205, 0, - 206, 0, 207, 0, 0, 0, 210, 211, 502, 0, - 214, 0, 215, 0, 216, 217, 218, 0, 219, 220, - 221, 222, 223, 224, 225, 0, 227, 228, 229, 230, - 0, 231, 232, 233, 234, 235, 236, 0, 237, 0, - 239, 240, 241, 242, 243, 244, 245, 246, 0, 247, - 0, 248, 0, 0, 251, 0, 253, 254, 255, 256, - 257, 258, 0, 0, 259, 0, 261, 0, 0, 263, - 264, 265, 0, 0, 266, 267, 268, 269, 270, 503, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 0, - 292, 293, 294, 295, 296, 0, 297, 298, 0, 300, - 0, 301, 302, 303, 304, 305, 306, 0, 307, 308, - 0, 0, 309, 310, 311, 0, 0, 312, 313, 0, - 315, 0, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 0, 328, 329, 330, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 339, 340, 341, 342, - 0, 343, 344, 345, 346, 347, 348, 592, 350, 0, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 0, 364, 365, 0, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 0, 382, 383, 384, 385, 386, 0, 387, - 388, 389, 390, 391, 0, 393, 394, 395, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 505, 410, 411, 412, 0, 413, 414, 0, - 415, 0, 417, 418, 419, 420, 421, 0, 422, 423, - 0, 0, 424, 425, 426, 427, 428, 0, 429, 430, - 431, 432, 433, 434, 435, 436, 0, 0, 437, 438, - 439, 440, 441, 0, 0, 442, 443, 444, 445, 446, - 447, 448, 0, 449, 0, 451, 452, 453, 454, 455, - 0, 0, 456, 0, 0, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 500, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, - 101, 0, 102, 103, 104, 0, 0, 0, 0, 0, - 0, 0, 105, 106, 0, 107, 108, 109, 0, 111, - 112, 113, 114, 115, 0, 117, 118, 0, 119, 120, - 121, 122, 123, 124, 0, 0, 125, 126, 127, 128, - 129, 0, 130, 131, 132, 133, 134, 0, 0, 0, - 136, 137, 138, 139, 140, 141, 0, 143, 144, 145, - 0, 146, 147, 148, 149, 150, 151, 0, 0, 153, - 154, 155, 0, 0, 0, 0, 0, 0, 0, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 0, - 167, 0, 168, 169, 170, 171, 172, 173, 0, 174, - 175, 176, 177, 178, 0, 0, 179, 180, 181, 182, - 183, 0, 184, 185, 186, 0, 187, 188, 189, 0, - 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 0, 201, 0, 202, 203, 204, 205, 0, 206, - 0, 207, 0, 0, 0, 210, 211, 502, 0, 214, - 0, 215, 0, 216, 217, 218, 0, 219, 220, 221, - 222, 223, 646, 225, 0, 227, 228, 229, 230, 0, - 231, 232, 233, 234, 235, 236, 0, 237, 0, 239, - 240, 241, 242, 243, 244, 245, 246, 0, 247, 0, - 248, 0, 0, 251, 0, 253, 254, 255, 256, 257, - 258, 0, 0, 259, 0, 261, 0, 0, 263, 264, - 265, 0, 0, 266, 267, 268, 269, 270, 503, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 290, 0, 292, - 293, 294, 295, 296, 0, 297, 298, 0, 300, 0, - 301, 302, 303, 304, 305, 306, 0, 307, 308, 0, - 0, 309, 310, 311, 0, 0, 312, 313, 0, 315, - 0, 317, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 0, 328, 329, 330, 331, 332, 333, 334, - 335, 336, 0, 337, 338, 339, 340, 341, 342, 0, - 343, 344, 345, 346, 347, 348, 349, 350, 0, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 0, 364, 365, 0, 367, 368, 369, 370, - 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, - 381, 0, 382, 383, 384, 385, 386, 0, 387, 388, - 389, 390, 391, 0, 393, 394, 395, 396, 0, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 505, 410, 411, 412, 0, 413, 414, 0, 415, - 0, 417, 418, 419, 420, 421, 0, 422, 423, 0, - 0, 424, 425, 426, 427, 428, 0, 429, 430, 431, - 432, 433, 434, 435, 436, 0, 0, 437, 438, 439, - 440, 441, 0, 0, 442, 443, 444, 445, 446, 447, - 448, 0, 449, 0, 451, 452, 453, 454, 455, 0, - 0, 456, 0, 0, 457, 458, 459, 460, 461, 462, - 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, - 473, 474, 475, 476, 477, 500, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 601, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 602, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 603, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 604, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 605, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, - 0, 102, 103, 104, 0, 0, 0, 0, 0, 0, - 0, 105, 106, 0, 107, 108, 109, 0, 111, 112, - 113, 114, 115, 0, 117, 118, 0, 119, 120, 121, - 122, 123, 124, 0, 0, 125, 126, 127, 128, 129, - 0, 130, 131, 132, 133, 134, 0, 0, 0, 136, - 137, 138, 139, 140, 141, 0, 143, 144, 145, 0, - 146, 147, 148, 149, 150, 151, 0, 0, 153, 154, - 155, 0, 0, 0, 0, 0, 0, 0, 157, 158, - 159, 160, 161, 162, 163, 164, 165, 166, 0, 167, - 0, 168, 169, 170, 171, 172, 173, 0, 174, 175, - 176, 177, 178, 0, 0, 179, 180, 181, 182, 183, - 0, 184, 185, 186, 0, 187, 188, 189, 0, 190, - 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, - 0, 201, 0, 202, 203, 204, 205, 0, 206, 0, - 207, 0, 0, 0, 210, 211, 502, 0, 214, 0, - 215, 0, 216, 217, 218, 0, 219, 220, 221, 222, - 223, 736, 225, 0, 227, 228, 229, 230, 0, 231, - 232, 233, 234, 235, 236, 0, 237, 0, 239, 240, - 241, 242, 243, 244, 245, 246, 0, 247, 0, 248, - 0, 0, 251, 0, 253, 254, 255, 256, 257, 258, - 0, 0, 259, 0, 261, 0, 0, 263, 264, 265, - 0, 0, 266, 267, 268, 269, 270, 503, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, - 284, 285, 286, 287, 288, 289, 290, 0, 292, 293, - 294, 295, 296, 0, 297, 298, 0, 300, 0, 301, - 302, 303, 304, 305, 306, 0, 307, 308, 0, 0, - 309, 310, 311, 0, 0, 312, 313, 0, 315, 0, - 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 0, 328, 329, 330, 331, 332, 333, 334, 335, - 336, 0, 337, 338, 339, 340, 341, 342, 0, 343, - 344, 345, 346, 347, 348, 349, 350, 0, 351, 352, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 0, 364, 365, 0, 367, 368, 369, 370, 371, - 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 0, 382, 383, 384, 385, 386, 0, 387, 388, 389, - 390, 391, 0, 393, 394, 395, 396, 0, 397, 398, - 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 505, 410, 411, 412, 0, 413, 414, 0, 415, 0, - 417, 418, 419, 420, 421, 0, 422, 423, 0, 0, - 424, 425, 426, 427, 428, 0, 429, 430, 431, 432, - 433, 434, 435, 436, 0, 0, 437, 438, 439, 440, - 441, 0, 0, 442, 443, 444, 445, 446, 447, 448, - 0, 449, 0, 451, 452, 453, 454, 455, 0, 0, - 456, 0, 0, 457, 458, 459, 460, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 500, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 673, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, - 102, 103, 104, 0, 0, 0, 0, 0, 0, 0, - 105, 106, 0, 107, 108, 109, 0, 111, 112, 113, - 114, 115, 0, 117, 118, 0, 119, 120, 121, 122, - 123, 124, 0, 0, 125, 126, 127, 128, 129, 0, - 130, 131, 132, 133, 134, 0, 0, 0, 136, 137, - 138, 139, 140, 141, 0, 143, 144, 145, 0, 146, - 147, 148, 149, 150, 151, 0, 0, 153, 154, 155, - 0, 0, 0, 0, 0, 0, 0, 157, 158, 159, - 160, 161, 162, 163, 164, 165, 166, 0, 167, 0, - 168, 169, 170, 171, 172, 173, 0, 174, 175, 176, - 177, 178, 0, 0, 179, 180, 181, 182, 183, 0, - 184, 185, 186, 0, 187, 188, 189, 0, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 0, - 201, 0, 202, 203, 204, 205, 0, 206, 0, 207, - 0, 0, 0, 210, 211, 502, 0, 214, 0, 215, - 0, 216, 217, 218, 0, 219, 220, 221, 222, 223, - 739, 225, 0, 227, 228, 229, 230, 0, 231, 232, - 233, 234, 235, 236, 0, 237, 0, 239, 240, 241, - 242, 243, 244, 245, 246, 0, 247, 0, 248, 0, - 0, 251, 0, 253, 254, 255, 256, 257, 258, 0, - 0, 259, 0, 261, 0, 0, 263, 264, 265, 0, - 0, 266, 267, 268, 269, 270, 503, 272, 273, 274, - 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, - 285, 286, 287, 288, 289, 290, 0, 292, 293, 294, - 295, 296, 0, 297, 298, 0, 300, 0, 301, 302, - 303, 304, 305, 306, 0, 307, 308, 0, 0, 309, - 310, 311, 0, 0, 312, 313, 0, 315, 0, 317, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 0, 328, 329, 330, 331, 332, 333, 334, 335, 336, - 0, 337, 338, 339, 340, 341, 342, 0, 343, 344, - 345, 346, 347, 348, 349, 350, 0, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 0, 364, 365, 0, 367, 368, 369, 370, 371, 372, - 373, 374, 375, 376, 377, 378, 379, 380, 381, 0, - 382, 383, 384, 385, 386, 0, 387, 388, 389, 390, - 391, 0, 393, 394, 395, 396, 0, 397, 398, 399, - 400, 401, 402, 403, 404, 405, 406, 407, 408, 505, - 410, 411, 412, 0, 413, 414, 0, 415, 0, 417, - 418, 419, 420, 421, 0, 422, 423, 0, 0, 424, - 425, 426, 427, 428, 0, 429, 430, 431, 432, 433, - 434, 435, 436, 0, 0, 437, 438, 439, 440, 441, - 0, 0, 442, 443, 444, 445, 446, 447, 448, 0, - 449, 0, 451, 452, 453, 454, 455, 0, 0, 456, - 0, 0, 457, 458, 459, 460, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 500, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 769, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, - 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, - 106, 0, 107, 108, 109, 0, 111, 112, 113, 114, - 115, 0, 117, 118, 0, 119, 120, 121, 122, 123, - 124, 0, 0, 125, 126, 127, 128, 129, 0, 130, - 131, 132, 133, 134, 0, 0, 0, 136, 137, 138, - 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, - 0, 0, 0, 0, 0, 0, 157, 158, 159, 160, - 161, 162, 163, 164, 165, 166, 0, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 181, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 194, 195, 196, 197, 198, 199, 200, 0, 201, - 0, 202, 203, 204, 205, 0, 206, 0, 207, 0, - 0, 0, 210, 211, 502, 0, 214, 0, 215, 0, - 216, 217, 218, 0, 219, 220, 221, 222, 223, 742, - 225, 0, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 0, 239, 240, 241, 242, - 243, 244, 245, 246, 0, 247, 0, 248, 0, 0, - 251, 0, 253, 254, 255, 256, 257, 258, 0, 0, - 259, 0, 261, 0, 0, 263, 264, 265, 0, 0, - 266, 267, 268, 269, 270, 503, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 0, 292, 293, 294, 295, - 296, 0, 297, 298, 0, 300, 0, 301, 302, 303, - 304, 305, 306, 0, 307, 308, 0, 0, 309, 310, - 311, 0, 0, 312, 313, 0, 315, 0, 317, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 330, 331, 332, 333, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 346, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 0, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 0, 382, - 383, 384, 385, 386, 0, 387, 388, 389, 390, 391, - 0, 393, 394, 395, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 505, 410, - 411, 412, 0, 413, 414, 0, 415, 0, 417, 418, - 419, 420, 421, 0, 422, 423, 0, 0, 424, 425, - 426, 427, 428, 0, 429, 430, 431, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 0, - 0, 442, 443, 444, 445, 446, 447, 448, 0, 449, - 0, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 0, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 500, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, - 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, - 104, 0, 0, 0, 0, 0, 0, 0, 105, 106, - 0, 107, 108, 109, 0, 111, 112, 113, 114, 115, - 0, 117, 118, 0, 119, 120, 121, 122, 123, 124, - 0, 0, 125, 126, 127, 128, 129, 0, 130, 131, - 132, 133, 134, 0, 0, 0, 136, 137, 138, 139, - 140, 141, 0, 143, 144, 145, 0, 146, 147, 148, - 149, 150, 151, 0, 0, 153, 154, 155, 0, 0, - 0, 0, 0, 0, 0, 157, 158, 159, 160, 161, - 162, 163, 164, 165, 166, 0, 167, 0, 168, 169, - 170, 171, 172, 173, 0, 174, 175, 176, 177, 178, - 0, 0, 179, 180, 181, 182, 183, 0, 184, 185, - 186, 0, 187, 188, 189, 0, 190, 191, 192, 193, - 194, 195, 196, 197, 198, 199, 200, 0, 201, 0, - 202, 203, 204, 205, 0, 206, 0, 207, 0, 0, - 0, 210, 211, 502, 0, 214, 0, 215, 0, 216, - 217, 218, 0, 219, 220, 221, 222, 223, 224, 225, - 0, 227, 228, 229, 230, 0, 231, 232, 233, 234, - 235, 236, 0, 237, 0, 239, 240, 241, 242, 243, - 244, 245, 246, 0, 247, 0, 248, 0, 0, 251, - 0, 253, 254, 255, 256, 257, 258, 0, 0, 259, - 0, 261, 0, 0, 263, 264, 265, 0, 0, 266, - 267, 268, 269, 270, 503, 272, 273, 274, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 0, 292, 293, 294, 295, 296, - 0, 297, 298, 0, 300, 0, 301, 302, 303, 304, - 305, 306, 0, 307, 308, 0, 0, 309, 310, 311, - 0, 0, 312, 313, 0, 315, 0, 317, 318, 319, - 320, 321, 322, 323, 324, 325, 326, 327, 0, 328, - 329, 330, 331, 332, 333, 334, 335, 336, 0, 337, - 338, 339, 340, 341, 342, 0, 343, 344, 345, 346, - 347, 348, 349, 350, 0, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 0, 364, - 365, 0, 367, 368, 369, 370, 371, 372, 373, 374, - 571, 376, 377, 378, 379, 380, 381, 0, 382, 383, - 384, 385, 386, 0, 387, 388, 389, 390, 391, 0, - 393, 394, 395, 396, 0, 397, 398, 399, 400, 401, - 402, 403, 404, 405, 406, 407, 408, 505, 410, 411, - 412, 0, 413, 414, 0, 415, 0, 417, 418, 419, - 420, 421, 0, 573, 423, 0, 0, 424, 425, 426, - 427, 428, 0, 429, 430, 431, 432, 433, 434, 435, - 436, 0, 0, 437, 438, 439, 440, 441, 0, 0, - 442, 443, 444, 445, 446, 447, 448, 0, 449, 0, - 451, 452, 453, 454, 455, 0, 0, 456, 0, 0, - 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 603, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 605, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, - 477, 500, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, - 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, - 0, 0, 0, 0, 0, 1395, 0, 105, 106, 0, - 107, 108, 109, 0, 111, 112, 113, 114, 115, 0, - 117, 118, 0, 119, 120, 121, 122, 123, 124, 0, - 0, 125, 126, 127, 128, 129, 0, 130, 131, 132, - 133, 134, 0, 0, 0, 136, 137, 138, 139, 140, - 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, - 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, - 0, 0, 0, 0, 157, 158, 159, 160, 161, 162, - 163, 164, 165, 166, 0, 167, 0, 168, 169, 170, - 171, 172, 173, 0, 174, 175, 176, 177, 178, 0, - 0, 179, 180, 181, 182, 183, 0, 184, 185, 186, - 0, 187, 188, 189, 0, 190, 191, 192, 193, 194, - 195, 196, 197, 198, 199, 200, 0, 201, 0, 202, - 203, 204, 205, 0, 206, 0, 207, 0, 0, 0, - 210, 211, 502, 0, 214, 0, 215, 0, 216, 217, - 218, 0, 219, 220, 221, 222, 223, 224, 225, 0, - 227, 228, 229, 230, 0, 231, 232, 233, 234, 235, - 236, 0, 237, 0, 239, 240, 241, 242, 243, 244, - 245, 246, 0, 247, 0, 248, 0, 0, 251, 0, - 253, 254, 255, 256, 257, 258, 0, 0, 259, 0, - 261, 0, 0, 263, 264, 265, 0, 0, 266, 267, - 268, 269, 270, 503, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 0, 292, 293, 294, 295, 296, 0, - 297, 298, 0, 300, 0, 301, 302, 303, 304, 305, - 306, 0, 307, 308, 0, 0, 309, 310, 311, 0, - 0, 312, 313, 0, 315, 0, 317, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 0, 328, 329, - 330, 331, 332, 333, 334, 335, 336, 0, 337, 338, - 339, 340, 341, 342, 0, 343, 344, 345, 346, 347, - 348, 349, 350, 0, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 0, 364, 365, - 0, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 0, 382, 383, 384, - 385, 386, 0, 0, 388, 389, 390, 391, 0, 393, - 394, 395, 396, 0, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 505, 410, 411, 412, - 0, 413, 414, 0, 415, 0, 417, 418, 419, 420, - 421, 0, 422, 423, 0, 0, 424, 425, 426, 427, - 428, 0, 429, 430, 431, 432, 433, 434, 435, 436, - 0, 0, 437, 438, 439, 440, 441, 0, 0, 442, - 443, 444, 445, 446, 447, 448, 0, 449, 0, 451, - 452, 453, 454, 455, 0, 0, 456, 0, 0, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 500, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, - 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, - 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, - 108, 109, 0, 111, 112, 113, 114, 115, 0, 117, - 118, 0, 119, 120, 121, 122, 123, 124, 0, 0, - 125, 126, 127, 128, 129, 0, 130, 131, 132, 133, - 134, 0, 0, 0, 136, 137, 138, 139, 140, 141, - 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, - 151, 0, 0, 153, 154, 155, 0, 0, 0, 0, - 0, 0, 0, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 0, 167, 0, 168, 169, 170, 171, - 172, 173, 0, 174, 175, 176, 177, 178, 0, 0, - 179, 180, 181, 182, 183, 0, 184, 185, 186, 0, - 187, 188, 189, 0, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 0, 201, 0, 202, 203, - 204, 205, 0, 206, 0, 207, 0, 0, 0, 210, - 211, 502, 0, 214, 0, 215, 0, 216, 217, 218, - 0, 219, 220, 221, 222, 223, 1537, 225, 0, 227, - 228, 229, 230, 0, 231, 232, 233, 234, 235, 236, - 0, 237, 0, 239, 240, 241, 242, 243, 244, 245, - 246, 0, 247, 0, 248, 0, 0, 251, 0, 253, - 254, 255, 256, 257, 258, 0, 0, 259, 0, 261, - 0, 0, 263, 264, 265, 0, 0, 266, 267, 268, - 269, 270, 503, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 0, 292, 293, 294, 295, 296, 0, 297, - 298, 0, 300, 0, 301, 302, 303, 304, 305, 306, - 0, 307, 308, 0, 0, 309, 310, 311, 0, 0, - 312, 313, 0, 315, 0, 317, 318, 319, 320, 321, - 322, 323, 324, 325, 326, 327, 0, 328, 329, 330, - 331, 332, 333, 334, 335, 336, 0, 337, 338, 339, - 340, 341, 342, 0, 343, 344, 345, 346, 347, 348, - 349, 350, 0, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 0, 364, 365, 0, - 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, - 377, 378, 379, 380, 381, 0, 382, 383, 384, 385, - 386, 0, 387, 388, 389, 390, 391, 0, 393, 394, - 395, 396, 0, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 505, 410, 411, 412, 0, - 413, 414, 0, 415, 0, 417, 418, 419, 420, 421, - 0, 422, 423, 0, 0, 424, 425, 426, 427, 428, - 0, 429, 430, 431, 432, 433, 434, 435, 436, 0, - 0, 437, 438, 439, 440, 441, 0, 0, 442, 443, - 444, 445, 446, 447, 448, 0, 449, 0, 451, 452, - 453, 454, 455, 0, 0, 456, 0, 0, 457, 458, - 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, 477, 500, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, - 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, - 0, 0, 0, 0, 0, 105, 106, 0, 107, 108, - 109, 0, 111, 112, 113, 114, 115, 0, 117, 118, - 0, 119, 120, 121, 122, 123, 124, 0, 0, 125, - 126, 127, 128, 129, 0, 130, 131, 132, 133, 134, - 0, 0, 0, 136, 137, 138, 139, 140, 141, 0, - 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, - 0, 0, 153, 154, 155, 0, 0, 0, 0, 0, - 0, 0, 157, 158, 159, 160, 161, 162, 163, 164, - 165, 166, 0, 167, 0, 168, 169, 170, 171, 172, - 173, 0, 174, 175, 176, 177, 178, 0, 0, 179, - 180, 181, 182, 183, 0, 184, 185, 186, 0, 187, - 188, 189, 0, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 0, 201, 0, 202, 203, 204, - 205, 0, 206, 0, 207, 0, 0, 0, 210, 211, - 502, 0, 214, 0, 215, 0, 216, 217, 218, 0, - 219, 220, 221, 222, 223, 1819, 225, 0, 227, 228, - 229, 230, 0, 231, 232, 233, 234, 235, 236, 0, - 237, 0, 239, 240, 241, 242, 243, 244, 245, 246, - 0, 247, 0, 248, 0, 0, 251, 0, 253, 254, - 255, 256, 257, 258, 0, 0, 259, 0, 261, 0, - 0, 263, 264, 265, 0, 0, 266, 267, 268, 269, - 270, 503, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 290, 0, 292, 293, 294, 295, 296, 0, 297, 298, - 0, 300, 0, 301, 302, 303, 304, 305, 306, 0, - 307, 308, 0, 0, 309, 310, 311, 0, 0, 312, - 313, 0, 315, 0, 317, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 0, 328, 329, 330, 331, - 332, 333, 334, 335, 336, 0, 337, 338, 339, 340, - 341, 342, 0, 343, 344, 345, 346, 347, 348, 349, - 350, 0, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 0, 364, 365, 0, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 0, 382, 383, 384, 385, 386, - 0, 387, 388, 389, 390, 391, 0, 393, 394, 395, - 396, 0, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 505, 410, 411, 412, 0, 413, - 414, 0, 415, 0, 417, 418, 419, 420, 421, 0, - 422, 423, 0, 0, 424, 425, 426, 427, 428, 0, - 429, 430, 431, 432, 433, 434, 435, 436, 0, 0, - 437, 438, 439, 440, 441, 0, 0, 442, 443, 444, - 445, 446, 447, 448, 0, 449, 0, 451, 452, 453, - 454, 455, 0, 0, 456, 0, 0, 457, 458, 459, - 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 500, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 1456, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 0, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, @@ -260925,6272 +279101,6317 @@ static const yytype_int16 yytable[] = 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, - 0, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 0, 167, 0, 168, 169, 170, 171, 172, 173, - 0, 174, 175, 176, 177, 178, 0, 0, 179, 180, - 181, 182, 183, 0, 184, 185, 186, 0, 187, 188, - 189, 0, 190, 191, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 0, 201, 0, 202, 203, 204, 205, - 0, 206, 0, 207, 0, 0, 0, 210, 211, 502, - 0, 214, 0, 215, 0, 216, 217, 218, 0, 219, - 220, 221, 222, 223, 1832, 225, 0, 227, 228, 229, - 230, 0, 231, 232, 233, 234, 235, 236, 0, 237, - 0, 239, 240, 241, 242, 243, 244, 245, 246, 0, - 247, 0, 248, 0, 0, 251, 0, 253, 254, 255, - 256, 257, 258, 0, 0, 259, 0, 261, 0, 0, - 263, 264, 265, 0, 0, 266, 267, 268, 269, 270, - 503, 272, 273, 274, 275, 276, 277, 278, 279, 280, - 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, - 0, 292, 293, 294, 295, 296, 0, 297, 298, 0, - 300, 0, 301, 302, 303, 304, 305, 306, 0, 307, - 308, 0, 0, 309, 310, 311, 0, 0, 312, 313, - 0, 315, 0, 317, 318, 319, 320, 321, 322, 323, - 324, 325, 326, 327, 0, 328, 329, 330, 331, 332, - 333, 334, 335, 336, 0, 337, 338, 339, 340, 341, - 342, 0, 343, 344, 345, 346, 347, 348, 349, 350, - 0, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 0, 364, 365, 0, 367, 368, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - 379, 380, 381, 0, 382, 383, 384, 385, 386, 0, - 387, 388, 389, 390, 391, 0, 393, 394, 395, 396, - 0, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, 407, 408, 505, 410, 411, 412, 0, 413, 414, - 0, 415, 0, 417, 418, 419, 420, 421, 0, 422, - 423, 0, 0, 424, 425, 426, 427, 428, 0, 429, - 430, 431, 432, 433, 434, 435, 436, 0, 0, 437, - 438, 439, 440, 441, 0, 0, 442, 443, 444, 445, - 446, 447, 448, 0, 449, 0, 451, 452, 453, 454, - 455, 0, 0, 456, 0, 0, 457, 458, 459, 460, - 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, - 471, 472, 473, 474, 475, 476, 477, 500, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 1598, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 94, 95, 96, 97, 98, 99, - 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, - 0, 0, 0, 105, 106, 0, 107, 108, 109, 0, - 111, 112, 113, 114, 115, 0, 117, 118, 0, 119, - 120, 121, 122, 123, 124, 0, 0, 125, 126, 127, - 128, 129, 0, 130, 131, 132, 133, 134, 0, 0, - 0, 136, 137, 138, 139, 140, 141, 0, 143, 144, - 145, 0, 146, 147, 148, 149, 150, 151, 0, 0, - 153, 154, 155, 0, 0, 0, 0, 0, 0, 0, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 0, 167, 0, 168, 169, 170, 171, 172, 173, 0, - 174, 175, 176, 177, 178, 0, 0, 179, 180, 181, - 182, 183, 0, 184, 185, 186, 0, 187, 188, 189, - 0, 190, 191, 192, 193, 194, 195, 196, 197, 198, - 199, 200, 0, 201, 0, 202, 203, 204, 205, 0, - 206, 0, 207, 0, 0, 0, 210, 211, 502, 0, - 214, 0, 215, 0, 216, 217, 218, 0, 219, 220, - 221, 222, 223, 1834, 225, 0, 227, 228, 229, 230, - 0, 231, 232, 233, 234, 235, 236, 0, 237, 0, - 239, 240, 241, 242, 243, 244, 245, 246, 0, 247, - 0, 248, 0, 0, 251, 0, 253, 254, 255, 256, - 257, 258, 0, 0, 259, 0, 261, 0, 0, 263, - 264, 265, 0, 0, 266, 267, 268, 269, 270, 503, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 290, 0, - 292, 293, 294, 295, 296, 0, 297, 298, 0, 300, - 0, 301, 302, 303, 304, 305, 306, 0, 307, 308, - 0, 0, 309, 310, 311, 0, 0, 312, 313, 0, - 315, 0, 317, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 0, 328, 329, 330, 331, 332, 333, - 334, 335, 336, 0, 337, 338, 339, 340, 341, 342, - 0, 343, 344, 345, 346, 347, 348, 349, 350, 0, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 0, 364, 365, 0, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 0, 382, 383, 384, 385, 386, 0, 387, - 388, 389, 390, 391, 0, 393, 394, 395, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 505, 410, 411, 412, 0, 413, 414, 0, - 415, 0, 417, 418, 419, 420, 421, 0, 422, 423, - 0, 0, 424, 425, 426, 427, 428, 0, 429, 430, - 431, 432, 433, 434, 435, 436, 0, 0, 437, 438, - 439, 440, 441, 0, 0, 442, 443, 444, 445, 446, - 447, 448, 0, 449, 0, 451, 452, 453, 454, 455, - 0, 0, 456, 0, 0, 457, 458, 459, 460, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 667, 0, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 1884, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 506, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, - 101, 0, 102, 103, 104, 0, 0, 0, 0, 0, - -668, 0, 105, 106, 0, 107, 108, 109, 668, 111, - 112, 113, 0, 669, 670, 671, 672, 0, 119, 120, - 121, 122, 123, 124, 0, 0, 125, 126, 673, 674, - 129, 0, 130, 131, 132, 133, 0, 0, 675, 0, - 136, 137, 138, 139, 140, 141, 676, 143, 144, 145, - 0, 146, 147, 148, 149, 150, 151, 0, 677, 153, - 154, 155, 0, 0, 0, 678, 0, 0, 0, 157, - 158, 159, 160, 161, 162, 163, 679, 680, 166, 0, - 167, 0, 168, 169, 170, 171, 172, 173, 0, 174, - 175, 176, 177, 178, 0, 0, 179, 180, 681, 182, - 183, 0, 184, 185, 186, 0, 187, 188, 189, 0, - 190, 191, 192, 193, 0, 195, 196, 197, 198, 199, - 0, 0, 201, 0, 202, 203, 682, 205, 0, 206, - 0, 207, 683, 0, 684, 210, 211, -668, 685, 214, - 0, 215, 0, 0, 0, 218, 0, 219, 220, 221, - 222, 223, 224, 225, 687, 227, 228, 229, 230, 0, - 231, 232, 233, 234, 235, 236, 0, 237, 688, 0, - 240, 241, 242, 243, 244, 689, 690, 0, 691, 0, - 248, 692, 693, 251, 694, 253, 254, 255, 256, 257, - 258, 0, 0, 259, 695, 261, 696, 0, 263, 264, - 265, 0, 0, 266, 267, 268, 269, 270, 697, 272, - 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 286, 287, 288, 289, 698, 699, 700, - 293, 294, 295, 0, 0, 297, 298, 701, 300, 0, - 0, 302, 702, 304, 305, 306, 0, 307, 308, 0, - 0, 309, 310, 311, 0, 0, 312, 0, 703, 315, - 704, 0, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 0, 328, 329, 0, 331, 332, 0, 334, - 335, 336, 0, 337, 338, 339, 340, 341, 342, 0, - 343, 344, 345, 705, 347, 348, 349, 350, 0, 351, - 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 0, 364, 365, 706, 367, 368, 369, 707, - 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, - 381, 0, 382, 383, 384, 385, 386, 0, 387, 708, - 389, 390, 391, 709, 393, 394, 710, 396, 0, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, - 408, 711, 410, 0, 412, 0, 413, 414, 0, 415, - 712, 417, 418, 419, 420, 421, 0, 713, 714, 0, - 0, 424, 425, 0, 427, 0, 0, 429, 430, 715, - 432, 433, 434, 435, 436, 0, 0, 437, 438, 439, - 440, 441, 0, 0, 442, 443, 444, 445, 446, 0, - 716, 0, 449, 717, 451, 452, 453, 454, 455, 0, - 0, 456, 0, 0, 457, 458, 459, 460, 461, 462, - 500, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 474, 475, 476, 477, 0, 0, 94, 95, 96, - 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, - 0, 0, 0, 0, 0, 0, 105, 106, 0, 107, - 108, 109, 0, 111, 112, 113, 114, 115, 0, 117, - 118, 0, 119, 120, 121, 122, 123, 124, 0, 0, - 125, 126, 127, 128, 129, 0, 130, 131, 132, 133, - 134, 0, 0, 0, 136, 137, 138, 139, 140, 141, - 0, 143, 144, 145, 0, 146, 147, 148, 149, 150, - 151, 0, 0, 153, 154, 155, 0, 0, 0, 0, - 0, 0, 0, 157, 158, 159, 160, 161, 162, 163, - 164, 165, 166, 0, 167, 0, 168, 169, 170, 171, - 172, 173, 0, 174, 175, 176, 177, 178, 0, 0, - 179, 180, 181, 182, 183, 0, 184, 185, 186, 0, - 187, 188, 189, 0, 190, 191, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 0, 201, 0, 202, 203, - 204, 205, 0, 206, 0, 207, 0, 0, 0, 210, - 211, 502, 0, 214, 0, 215, 0, 216, 217, 218, - 0, 219, 220, 221, 222, 223, 224, 225, 0, 227, - 228, 229, 230, 0, 231, 232, 233, 234, 235, 236, - 0, 237, 0, 239, 240, 241, 242, 243, 244, 245, - 246, 0, 247, 0, 248, 0, 0, 251, 0, 253, - 254, 255, 256, 257, 258, 0, 0, 259, 0, 261, - 0, 0, 263, 264, 265, 0, 0, 266, 267, 268, - 269, 270, 503, 272, 273, 274, 275, 276, 277, 278, - 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, - 289, 290, 0, 292, 293, 294, 295, 296, 0, 297, - 298, 0, 300, 0, 301, 302, 303, 304, 305, 306, - 0, 307, 308, 0, 0, 309, 310, 311, 0, 0, - 312, 313, 0, 315, 0, 317, 318, 319, 320, 321, - 322, 323, 0, 325, 326, 327, 0, 328, 329, 330, - 331, 332, 333, 334, 335, 336, 0, 337, 338, 339, - 340, 341, 342, 0, 343, 0, 345, 346, 347, 348, - 349, 350, 0, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 0, 364, 365, 0, - 367, 368, 369, 370, 0, 372, 373, 374, 375, 376, - 377, 378, 379, 380, 381, 0, 382, 383, 384, 385, - 386, 0, 387, 388, 389, 390, 391, 0, 393, 394, - 395, 396, 0, 397, 398, 399, 400, 401, 402, 403, - 404, 405, 406, 407, 408, 505, 410, 411, 412, 0, - 413, 414, 0, 415, 0, 417, 418, 419, 420, 421, - 0, 422, 423, 0, 0, 424, 425, 426, 427, 428, - 0, 429, 430, 431, 432, 433, 434, 435, 436, 0, - 0, 437, 438, 439, 440, 441, 0, 0, 442, 443, - 444, 445, 446, 447, 448, 0, 449, 0, 451, 452, - 453, 454, 455, 0, 0, 456, 0, 0, 457, 458, - 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, 477, 667, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 1899, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 2509, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 94, 95, 96, 97, - 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, - 0, 0, 0, 0, 0, 105, 106, 0, 107, 108, - 109, 668, 111, 112, 113, 0, 669, 670, 671, 672, - 0, 119, 120, 121, 122, 123, 124, 0, 0, 125, - 126, 673, 674, 129, 0, 130, 131, 132, 133, 0, - 0, 675, 0, 136, 137, 138, 139, 140, 141, 676, - 143, 144, 145, 0, 146, 147, 148, 149, 150, 151, - 0, 677, 153, 154, 155, 0, 0, 0, 678, 0, - 0, 0, 157, 158, 159, 160, 161, 162, 163, 679, - 680, 166, 0, 167, 0, 168, 169, 170, 171, 172, - 173, 0, 174, 175, 176, 177, 178, 0, 0, 179, - 180, 681, 182, 183, 0, 184, 185, 186, 0, 187, - 188, 189, 0, 190, 191, 192, 193, 0, 195, 196, - 197, 198, 199, 0, 0, 201, 0, 202, 203, 682, - 205, 0, 206, 0, 207, 683, 0, 684, 210, 211, - 0, 685, 214, 0, 215, 0, 0, 0, 218, 0, - 219, 220, 221, 222, 223, 686, 225, 687, 227, 228, - 229, 230, 0, 231, 232, 233, 234, 235, 236, 0, - 237, 688, 0, 240, 241, 242, 243, 244, 689, 690, - 0, 691, 0, 248, 692, 693, 251, 694, 253, 254, - 255, 256, 257, 258, 0, 0, 259, 695, 261, 696, - 0, 263, 264, 265, 0, 0, 266, 267, 268, 269, - 270, 697, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, - 698, 699, 700, 293, 294, 295, 0, 0, 297, 298, - 701, 300, 0, 0, 302, 702, 304, 305, 306, 0, - 307, 308, 0, 0, 309, 310, 311, 0, 0, 312, - 0, 703, 315, 704, 0, 318, 319, 320, 321, 322, - 323, 324, 325, 326, 327, 0, 328, 329, 0, 331, - 332, 0, 334, 335, 336, 0, 337, 338, 339, 340, - 341, 342, 0, 343, 344, 345, 705, 347, 348, 349, - 350, 0, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 0, 364, 365, 706, 367, - 368, 369, 707, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 0, 382, 383, 384, 385, 386, - 0, 387, 708, 389, 390, 391, 709, 393, 394, 710, - 396, 0, 397, 398, 399, 400, 401, 402, 403, 404, - 405, 406, 407, 408, 711, 410, 0, 412, 0, 413, - 414, 0, 415, 712, 417, 418, 419, 420, 421, 0, - 713, 714, 0, 0, 424, 425, 0, 427, 0, 0, - 429, 430, 715, 432, 433, 434, 435, 436, 0, 0, - 437, 438, 439, 440, 441, 0, 0, 442, 443, 444, - 445, 446, 0, 716, 0, 449, 717, 451, 452, 453, - 454, 455, 0, 0, 456, 0, 0, 457, 458, 459, - 460, 461, 462, 667, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 474, 475, 476, 477, 0, 0, + 0, 0, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 2510, 111, 112, 113, 0, 696, 2511, 698, 699, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 700, 701, 129, 0, 130, 131, 132, 133, 0, 0, + 2512, 0, 136, 137, 138, 139, 140, 141, 2513, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 2514, 153, 154, 155, 2515, 2516, 2517, 2518, 0, 0, + 2519, 161, 162, 163, 164, 165, 166, 167, 710, 711, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 712, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 0, 199, 200, 201, + 202, 203, 0, 0, 205, 0, 206, 207, 713, 209, + 0, 210, 0, 211, 2520, 0, 2521, 214, 215, 2522, + 2523, 218, 0, 219, 0, 0, 0, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 2524, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 2525, 0, 244, 245, 246, 247, 248, 720, 721, 0, + 722, 0, 252, 2526, 2527, 255, 2528, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 2529, 265, 2530, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 2723, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 729, + 2532, 731, 297, 298, 299, 0, 0, 301, 302, 2534, + 304, 0, 0, 306, 733, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 0, + 2536, 319, 2537, 0, 322, 323, 324, 325, 326, 327, + 328, 329, 330, 331, 0, 332, 333, 0, 335, 336, + 0, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 348, 349, 736, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 2538, 371, 372, + 373, 0, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 2539, + 392, 0, 394, 395, 396, 2541, 398, 399, 742, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 2724, 415, 0, 417, 0, 418, 419, + 0, 420, 2543, 422, 423, 424, 425, 426, 0, 745, + 746, 0, 0, 429, 430, 0, 432, 0, 0, 434, + 435, 2544, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 2545, 0, 448, 449, 450, 451, + 452, 0, 749, 0, 455, 2546, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 694, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 480, 481, 482, 483, 0, 0, 0, 94, 95, 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, 0, 0, 0, 105, - 106, 0, 107, 108, 109, 668, 111, 112, 113, 0, - 669, 670, 671, 672, 0, 119, 120, 121, 122, 123, - 124, 0, 0, 125, 126, 673, 674, 129, 0, 130, - 131, 132, 133, 0, 0, 675, 0, 136, 137, 138, - 139, 140, 141, 676, 143, 144, 145, 0, 146, 147, - 148, 149, 150, 151, 0, 677, 153, 154, 155, 0, - 0, 0, 678, 0, 0, 0, 157, 158, 159, 160, - 161, 162, 163, 679, 680, 166, 0, 167, 0, 168, - 169, 170, 171, 172, 173, 0, 174, 175, 176, 177, - 178, 0, 0, 179, 180, 681, 182, 183, 0, 184, - 185, 186, 0, 187, 188, 189, 0, 190, 191, 192, - 193, 0, 195, 196, 197, 198, 199, 0, 0, 201, - 0, 202, 203, 682, 205, 0, 206, 0, 207, 683, - 0, 684, 210, 211, 0, 685, 214, 0, 215, 0, - 0, 0, 218, 0, 219, 220, 221, 222, 223, 224, - 225, 687, 227, 228, 229, 230, 0, 231, 232, 233, - 234, 235, 236, 0, 237, 688, 0, 240, 241, 242, - 243, 244, 689, 690, 0, 691, 0, 248, 692, 693, - 251, 694, 253, 254, 255, 256, 257, 258, 0, 0, - 259, 695, 261, 696, 0, 263, 264, 265, 0, 0, - 266, 267, 268, 269, 270, 697, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 698, 699, 700, 293, 294, 295, - 0, 0, 297, 298, 701, 300, 0, 0, 302, 702, - 304, 305, 306, 0, 307, 308, 0, 0, 309, 310, - 311, 0, 0, 312, 0, 703, 315, 704, 0, 318, - 319, 320, 321, 322, 323, 324, 325, 326, 327, 0, - 328, 329, 0, 331, 332, 0, 334, 335, 336, 0, - 337, 338, 339, 340, 341, 342, 0, 343, 344, 345, - 705, 347, 348, 349, 350, 0, 351, 352, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 0, - 364, 365, 706, 367, 368, 369, 707, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 0, 382, - 383, 384, 385, 386, 0, 387, 708, 389, 390, 391, - 709, 393, 394, 710, 396, 0, 397, 398, 399, 400, - 401, 402, 403, 404, 405, 406, 407, 408, 711, 410, - 0, 412, 0, 413, 414, 0, 415, 712, 417, 418, - 419, 420, 421, 0, 713, 714, 0, 0, 424, 425, - 0, 427, 0, 0, 429, 430, 715, 432, 433, 434, - 435, 436, 0, 0, 437, 438, 439, 440, 441, 0, - 0, 442, 443, 444, 445, 446, 0, 716, 0, 449, - 717, 451, 452, 453, 454, 455, 0, 0, 456, 0, - 0, 457, 458, 459, 460, 461, 462, 2450, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 474, 475, - 476, 477, 0, 0, 94, 95, 96, 97, 98, 99, - 100, 101, 0, 102, 103, 104, 0, 0, 0, 0, - 0, 0, 0, 105, 106, 0, 107, 108, 109, 2451, - 111, 112, 113, 0, 669, 2452, 671, 672, 0, 119, - 120, 121, 122, 123, 124, 0, 0, 125, 126, 673, - 674, 129, 0, 130, 131, 132, 133, 0, 0, 2453, - 0, 136, 137, 138, 139, 140, 141, 2454, 143, 144, - 145, 0, 146, 147, 148, 149, 150, 151, 0, 2455, - 153, 154, 155, 0, 0, 0, 2456, 0, 0, 0, - 157, 158, 159, 160, 161, 162, 163, 679, 680, 166, - 0, 167, 0, 168, 169, 170, 171, 172, 173, 0, - 174, 175, 176, 177, 178, 0, 0, 179, 180, 681, - 182, 183, 0, 184, 185, 186, 0, 187, 188, 189, - 0, 190, 191, 192, 193, 0, 195, 196, 197, 198, - 199, 0, 0, 201, 0, 202, 203, 682, 205, 0, - 206, 0, 207, 2457, 0, 2458, 210, 211, 2459, 2460, - 214, 0, 215, 0, 0, 0, 218, 0, 219, 220, - 221, 222, 223, 224, 225, 2461, 227, 228, 229, 230, - 0, 231, 232, 233, 234, 235, 236, 0, 237, 2462, - 0, 240, 241, 242, 243, 244, 689, 690, 0, 691, - 0, 248, 2463, 2464, 251, 2465, 253, 254, 255, 256, - 257, 258, 0, 0, 259, 2466, 261, 2467, 0, 263, - 264, 265, 0, 0, 266, 267, 268, 269, 270, 2660, - 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, 283, 284, 285, 286, 287, 288, 289, 698, 2469, - 700, 293, 294, 295, 0, 0, 297, 298, 2471, 300, - 0, 0, 302, 702, 304, 305, 306, 0, 307, 308, - 0, 0, 309, 310, 311, 0, 0, 312, 0, 2473, - 315, 2474, 0, 318, 319, 320, 321, 322, 323, 324, - 325, 326, 327, 0, 328, 329, 0, 331, 332, 0, - 334, 335, 336, 0, 337, 338, 339, 340, 341, 342, - 0, 343, 344, 345, 705, 347, 348, 349, 350, 0, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 0, 364, 365, 2475, 367, 368, 369, - 0, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 0, 382, 383, 384, 385, 386, 0, 387, - 0, 389, 390, 391, 2477, 393, 394, 710, 396, 0, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 2661, 410, 0, 412, 0, 413, 414, 0, - 415, 2479, 417, 418, 419, 420, 421, 0, 713, 714, - 0, 0, 424, 425, 0, 427, 0, 0, 429, 430, - 2480, 432, 433, 434, 435, 436, 0, 0, 437, 438, - 439, 440, 441, 0, 0, 442, 443, 444, 445, 446, - 0, 716, 0, 449, 2481, 451, 452, 453, 454, 455, - 0, 0, 456, 0, 0, 457, 458, 459, 460, 461, - 462, 667, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 474, 475, 476, 477, 0, 0, 94, 95, - 96, 97, 98, 99, 100, 101, 0, 102, 103, 104, - 0, 0, 0, 0, 0, 0, 0, 105, 106, 0, - 107, 108, 109, 668, 111, 112, 113, 0, 669, 670, - 671, 672, 0, 119, 120, 121, 122, 123, 124, 0, - 0, 125, 126, 673, 674, 129, 0, 130, 131, 132, - 133, 0, 0, 675, 0, 136, 137, 138, 139, 140, - 141, 676, 143, 144, 145, 0, 146, 147, 148, 149, - 150, 151, 0, 677, 153, 154, 155, 0, 0, 0, - 678, 0, 0, 0, 157, 158, 159, 160, 161, 162, - 163, 679, 680, 166, 0, 167, 0, 168, 169, 170, - 171, 172, 173, 0, 174, 175, 176, 177, 178, 0, - 0, 179, 180, 681, 182, 183, 0, 184, 185, 186, - 0, 187, 188, 189, 0, 190, 191, 192, 193, 0, - 195, 196, 197, 198, 199, 0, 0, 201, 0, 202, - 203, 682, 205, 0, 206, 0, 207, 683, 0, 684, - 210, 211, 0, 685, 214, 0, 215, 0, 0, 0, - 218, 0, 219, 220, 221, 222, 223, 224, 225, 687, - 227, 228, 229, 230, 0, 231, 232, 233, 234, 235, - 236, 0, 237, 688, 0, 240, 241, 242, 243, 244, - 689, 690, 0, 691, 0, 248, 692, 693, 251, 694, - 253, 254, 255, 256, 257, 258, 0, 0, 259, 695, - 261, 696, 0, 263, 264, 265, 0, 0, 266, 267, - 268, 269, 270, 0, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 698, 699, 700, 293, 294, 295, 0, 0, - 297, 298, 701, 300, 0, 0, 302, 702, 304, 305, - 306, 0, 307, 308, 0, 0, 309, 310, 311, 0, - 0, 312, 0, 703, 315, 704, 0, 318, 319, 320, - 321, 322, 323, 324, 325, 326, 327, 0, 328, 329, - 0, 331, 332, 0, 334, 335, 336, 0, 337, 338, - 339, 340, 341, 342, 0, 343, 344, 345, 705, 347, - 348, 349, 350, 0, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 0, 364, 365, - 706, 367, 368, 369, 0, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 0, 382, 383, 384, - 385, 386, 0, 387, 0, 389, 390, 391, 709, 393, - 394, 710, 396, 0, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 0, 410, 0, 412, - 0, 413, 414, 0, 415, 712, 417, 418, 419, 420, - 421, 0, 713, 714, 0, 0, 424, 425, 0, 427, - 0, 0, 429, 430, 715, 432, 433, 434, 435, 436, - 0, 0, 437, 438, 439, 440, 441, 0, 0, 442, - 443, 444, 445, 446, 0, 716, 0, 449, 717, 451, - 452, 453, 454, 455, 0, 0, 456, 0, 0, 457, - 458, 459, 460, 461, 462, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 474, 475, 476, 477 + 106, 0, 107, 108, 109, 695, 111, 112, 113, 0, + 696, 697, 698, 699, 0, 119, 120, 121, 122, 123, + 124, 0, 0, 125, 126, 700, 701, 129, 0, 130, + 131, 132, 133, 0, 0, 702, 0, 136, 137, 138, + 139, 140, 141, 703, 143, 144, 145, 0, 146, 147, + 148, 149, 150, 151, 0, 704, 153, 154, 155, 705, + 706, 707, 708, 0, 0, 709, 161, 162, 163, 164, + 165, 166, 167, 710, 711, 170, 0, 171, 0, 172, + 173, 174, 175, 176, 177, 0, 178, 179, 180, 181, + 182, 0, 0, 183, 184, 712, 186, 187, 0, 188, + 189, 190, 0, 191, 192, 193, 0, 194, 195, 196, + 197, 0, 199, 200, 201, 202, 203, 0, 0, 205, + 0, 206, 207, 713, 209, 0, 210, 0, 211, 714, + 0, 715, 214, 215, 0, 716, 218, 0, 219, 0, + 0, 0, 222, 0, 223, 224, 225, 226, 227, 228, + 229, 718, 231, 232, 233, 234, 0, 235, 236, 237, + 238, 239, 240, 0, 241, 719, 0, 244, 245, 246, + 247, 248, 720, 721, 0, 722, 0, 252, 723, 724, + 255, 725, 257, 258, 259, 260, 261, 262, 0, 0, + 263, 726, 265, 727, 0, 267, 268, 269, 0, 0, + 270, 271, 272, 273, 274, 0, 276, 277, 278, 279, + 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, + 290, 291, 292, 293, 729, 730, 731, 297, 298, 299, + 0, 0, 301, 302, 732, 304, 0, 0, 306, 733, + 308, 309, 310, 0, 311, 312, 0, 0, 313, 314, + 315, 0, 0, 316, 0, 734, 319, 735, 0, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 0, + 332, 333, 0, 335, 336, 0, 338, 339, 340, 0, + 341, 342, 343, 344, 345, 346, 0, 347, 348, 349, + 736, 351, 352, 353, 354, 0, 355, 356, 357, 358, + 359, 360, 361, 362, 363, 364, 365, 366, 367, 0, + 368, 369, 737, 371, 372, 373, 0, 375, 376, 377, + 378, 379, 380, 381, 382, 383, 384, 385, 0, 386, + 387, 388, 389, 390, 739, 392, 0, 394, 395, 396, + 741, 398, 399, 742, 401, 0, 402, 403, 404, 405, + 406, 407, 408, 409, 410, 411, 412, 413, 0, 415, + 0, 417, 0, 418, 419, 0, 420, 744, 422, 423, + 424, 425, 426, 0, 745, 746, 0, 0, 429, 430, + 0, 432, 0, 0, 434, 435, 747, 437, 438, 439, + 440, 441, 0, 0, 442, 443, 444, 445, 446, 748, + 0, 448, 449, 450, 451, 452, 0, 749, 0, 455, + 750, 457, 458, 459, 460, 461, 0, 0, 462, 0, + 0, 463, 464, 465, 466, 467, 468, 506, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 480, 481, + 482, 483, 0, 0, 0, 94, 95, 96, 97, 98, + 99, 100, 101, 0, 102, 103, 104, 0, 0, 0, + 0, 0, 0, 0, 105, 106, 0, 107, 108, 109, + 0, 111, 112, 113, 114, 115, 0, 117, 118, 0, + 119, 120, 121, 122, 123, 124, 0, 0, 125, 126, + 127, 128, 129, 0, 130, 131, 132, 133, 134, 0, + 0, 0, 136, 137, 138, 139, 140, 141, 0, 143, + 144, 145, 0, 146, 147, 148, 149, 150, 151, 0, + 0, 153, 154, 155, 0, 0, 0, 0, 0, 0, + 0, 161, 162, 163, 164, 165, 166, 167, 168, 169, + 170, 0, 171, 0, 172, 173, 174, 175, 176, 177, + 0, 178, 179, 180, 181, 182, 0, 0, 183, 184, + 185, 186, 187, 0, 188, 189, 190, 0, 191, 192, + 193, 0, 194, 195, 196, 197, 198, 199, 200, 201, + 202, 203, 204, 0, 205, 0, 206, 207, 208, 209, + 0, 210, 0, 211, 0, 0, 0, 214, 215, 509, + 0, 218, 0, 219, 0, 220, 221, 222, 0, 223, + 224, 225, 226, 227, 228, 229, 0, 231, 232, 233, + 234, 0, 235, 236, 237, 238, 239, 240, 0, 241, + 0, 243, 244, 245, 246, 247, 248, 249, 250, 0, + 251, 0, 252, 0, 0, 255, 0, 257, 258, 259, + 260, 261, 262, 0, 0, 263, 0, 265, 0, 0, + 267, 268, 269, 0, 0, 270, 271, 272, 273, 274, + 510, 276, 277, 278, 279, 280, 281, 282, 283, 284, + 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, + 0, 296, 297, 298, 299, 300, 0, 301, 302, 0, + 304, 0, 305, 306, 307, 308, 309, 310, 0, 311, + 312, 0, 0, 313, 314, 315, 0, 0, 316, 317, + 0, 319, 0, 321, 322, 323, 324, 325, 326, 327, + 0, 329, 330, 331, 0, 332, 333, 334, 335, 336, + 337, 338, 339, 340, 0, 341, 342, 343, 344, 345, + 346, 0, 347, 0, 349, 350, 351, 352, 353, 354, + 0, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 0, 368, 369, 0, 371, 372, + 373, 374, 0, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 0, 386, 387, 388, 389, 390, 0, + 392, 393, 394, 395, 396, 0, 398, 399, 400, 401, + 0, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 512, 415, 416, 417, 0, 418, 419, + 0, 420, 0, 422, 423, 424, 425, 426, 0, 427, + 428, 0, 0, 429, 430, 431, 432, 433, 0, 434, + 435, 436, 437, 438, 439, 440, 441, 0, 0, 442, + 443, 444, 445, 446, 0, 0, 448, 449, 450, 451, + 452, 453, 454, 0, 455, 0, 457, 458, 459, 460, + 461, 0, 0, 462, 0, 0, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, 1, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 2, 2, 3, + 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, + 0, 0, 0, 0, 6, 6, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 7, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 8, 8, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, + 9, 10, 10, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, + 11, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 12, 12, 0, 0, 0, 0, 0, + 0, 0, 0, 13, 13, 0, 0, 0, 0, 14, + 14, 0, 0, 0, 0, 0, 0, 15, 15, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 18, 18, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 20, 20, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 21, 21, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 22, 22, 0, 23, 23, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 24, 24, 0, 0, 0, 0, 0, 0, + 0, 25, 25, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 26, 26, 0, 0, 0, + 0, 0, 27, 27, 0, 0, 28, 28, 0, 0, + 0, 0, 0, 0, 0, 0, 29, 29, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 30, 30, + 0, 0, 31, 31, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, + 0, 0, 0, 33, 33, 0, 0, 544, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 34, 34, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 35, 35, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 545, 36 }; static const yytype_int16 yycheck[] = { - 6, 495, 59, 625, 611, 1009, 807, 529, 708, 0, - 0, 640, 886, 0, 807, 536, 1287, 887, 1007, 982, - 1183, 632, 36, 0, 586, 16, 1362, 591, 654, 1401, - 1153, 538, 1404, 714, 16, 987, 1830, 531, 889, 1153, - 61, 1153, 1783, 1153, 6, 1786, 529, 31, 1669, 61, - 1754, 529, 634, 984, 905, 6, 1049, 2181, 2181, 2210, - 978, 2208, 537, 1750, 538, 0, 815, 918, 532, 1188, - 2229, 737, 1317, 1318, 740, 1712, 1826, 2085, 1765, 0, - 2222, 1012, 1774, 1874, 1875, 1876, 1889, 35, 21, 1648, - 1649, 0, 1268, 2037, 1653, 9, 9, 3, 5, 2092, - 74, 5, 5, 5, 5, 5, 90, 5, 51, 30, - 13, 14, 13, 14, 59, 13, 14, 4, 673, 674, - 59, 0, 9, 2524, 645, 926, 32, 33, 5, 59, - 625, 1370, 627, 2578, 629, 5, 1695, 1696, 543, 5, - 5, 5, 608, 13, 14, 700, 5, 0, 13, 14, - 1422, 13, 14, 1903, 13, 14, 5, 5, 5, 80, - 9, 9, 171, 16, 118, 5, 5, 2512, 1154, 2614, - 5, 5, 1420, 138, 5, 5, 5, 30, 5, 108, - 744, 608, 2527, 36, 41, 94, 708, 1282, 68, 11, - 3, 4, 5, 874, 16, 996, 9, 2508, 999, 1000, - 123, 121, 1282, 41, 28, 2600, 11, 1282, 61, 59, - 121, 16, 1282, 11, 11, 94, 28, 28, 16, 16, - 1970, 1971, 292, 35, 35, 708, 4, 80, 2664, 188, - 2117, 9, 243, 2091, 284, 308, 2490, 42, 2697, 108, - 2795, 308, 2763, 118, 272, 42, 356, 49, 286, 292, - 223, 69, 2697, 171, 24, 79, 223, 377, 190, 2023, - 30, 28, 170, 169, 88, 171, 2864, 121, 35, 74, - 116, 1020, 116, 131, 275, 2149, 119, 74, 1027, 834, - 835, 162, 136, 38, 357, 13, 14, 167, 28, 209, - 11, 418, 11, 117, 816, 995, 269, 16, 60, 395, - 807, 440, 269, 116, 487, 860, 68, 814, 2099, 160, - 162, 440, 28, 76, 1995, 11, 76, 500, 20, 21, - 16, 885, 131, 42, 87, 404, 2996, 87, 890, 271, - 109, 146, 328, 816, 276, 810, 463, 37, 2683, 2734, - 2895, 2349, 498, 2024, 188, 2353, 119, 2340, 109, 192, - 361, 933, 2476, 74, 2148, 74, 1993, 919, 454, 498, - 439, 357, 329, 2237, 188, 0, 136, 3037, 2519, 498, - 125, 164, 243, 175, 2521, 227, 200, 286, 498, 2977, - 2825, 382, 24, 234, 946, 327, 304, 268, 498, 191, - 2131, 131, 210, 2794, 196, 2145, 2083, 2147, 2085, 214, - 269, 276, 215, 348, 926, 378, 2927, 286, 2662, 348, - 438, 378, 148, 977, 346, 131, 2861, 1291, 348, 192, - 493, 928, 929, 281, 237, 436, 493, 271, 170, 501, - 276, 233, 502, 1746, 1747, 450, 59, 165, 2993, 319, - 349, 1712, 2001, 2002, 2003, 2004, 2005, 1054, 498, 2008, - 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 502, - 498, 197, 271, 381, 318, 438, 502, 1562, 32, 33, - 349, 438, 281, 995, 174, 237, 405, 292, 498, 1442, - 2791, 2339, 1562, 1563, 1564, 949, 1561, 498, 442, 498, - 361, 456, 1562, 1563, 136, 2896, 487, 487, 348, 2386, - 487, 2960, 2938, 2062, 2063, 1498, 2256, 2271, 416, 975, - 487, 1756, 995, 2908, 1785, 2960, 2424, 440, 438, 1791, - 290, 314, 496, 529, 538, 1529, 500, 438, 392, 393, - 94, 2673, 538, 343, 1163, 243, 1522, 942, 1777, 498, - 2664, 2664, 1790, 1154, 450, 402, 537, 462, 975, 449, - 199, 460, 2897, 433, 611, 498, 538, 502, 462, 580, - 462, 567, 568, 502, 402, 436, 487, 391, 580, 484, - 394, 341, 502, 385, 385, 345, 489, 490, 380, 2587, - 484, 460, 484, 497, 2592, 591, 2579, 2595, 1764, 496, - 499, 498, 501, 500, 498, 498, 498, 498, 498, 2402, - 498, 2395, 489, 490, 493, 375, 1599, 589, 2552, 600, - 600, 500, 1176, 600, 1240, 548, 1365, 432, 385, 603, - 499, 498, 501, 600, 630, 631, 632, 498, 498, 1184, - 1185, 11, 498, 498, 487, 15, 498, 84, 493, 498, - 250, 2800, 2793, 23, 592, 500, 269, 1258, 290, 498, - 498, 498, 172, 416, 34, 35, 416, 2799, 498, 498, - 1182, 1183, 2349, 498, 498, 600, 2353, 498, 498, 498, - 1471, 498, 494, 443, 416, 1197, 489, 490, 421, 600, - 1481, 128, 460, 1484, 537, 538, 491, 492, 493, 494, - 1272, 37, 2384, 491, 492, 493, 494, 494, 405, 1182, - 1183, 347, 708, 345, 1182, 347, 484, 1271, 88, 1273, - 107, 489, 490, 1277, 1197, 2623, 2507, 1328, 1239, 1197, - 176, 2729, 1993, 452, 244, 348, 1290, 580, 436, 375, - 1312, 1313, 31, 375, 2642, 1242, 1230, 1231, 744, 118, - 364, 1303, 24, 1237, 333, 487, 2893, 600, 30, 333, - 1314, 2902, 375, 2390, 487, 333, 55, 1368, 500, 2429, - 2510, 2074, 2075, 2076, 2077, 498, 1241, 2437, 1242, 1233, - 489, 490, 491, 492, 493, 494, 498, 1359, 176, 160, - 369, 237, 24, 1584, 165, 1367, 1535, 1369, 30, 243, - 498, 1584, 160, 489, 490, 491, 492, 493, 494, 1321, - 2045, 807, 255, 256, 368, 368, 1676, 2954, 814, 815, - 816, 1930, 460, 333, 2938, 2938, 405, 1936, 3, 810, - 5, 405, 5, 1674, 203, 4, 832, 405, 174, 4, - 9, 2625, 243, 68, 9, 291, 484, 1331, 1321, 237, - 1758, 405, 405, 1321, 546, 1467, 548, 549, 1459, 369, - 1854, 498, 249, 234, 136, 861, 303, 496, 2417, 171, - 257, 500, 116, 452, 481, 1739, 234, 11, 452, 571, - 131, 3022, 886, 220, 452, 881, 882, 883, 1544, 885, - 886, 116, 446, 446, 1877, 405, 450, 1494, 1495, 1496, - 269, 2578, 271, 205, 136, 2058, 460, 158, 42, 1565, - 2587, 1567, 283, 909, 1570, 2592, 76, 361, 2595, 221, - 2181, 1522, 365, 366, 409, 283, 411, 87, 24, 231, - 484, 95, 928, 929, 30, 110, 111, 2614, 1779, 1451, - 74, 1862, 452, 499, 498, 498, 502, 24, 24, 960, - 961, 24, 963, 30, 30, 1440, 500, 30, 960, 961, - 361, 963, 286, 409, 243, 411, 962, 810, 76, 481, - 966, 967, 1914, 410, 243, 65, 66, 1919, 1451, 87, - 954, 977, 1467, 1451, 2768, 499, 462, 1541, 502, 199, - 436, 462, 436, 1477, 491, 110, 111, 2546, 1482, 995, - 409, 1486, 411, 80, 1515, 848, 1491, 171, 484, 502, - 94, 186, 187, 484, 4, 460, 169, 462, 290, 9, - 2697, 409, 498, 411, 1020, 276, 498, 498, 146, 4, - 281, 1027, 1589, 499, 9, 436, 1593, 1011, 1595, 499, - 136, 205, 160, 886, 1556, 496, 271, 165, 436, 500, - 352, 276, 2729, 1049, 498, 299, 2358, 221, 290, 2361, - 136, 170, 496, 136, 498, 216, 500, 231, 409, 341, - 411, 186, 187, 345, 13, 14, 251, 252, 253, 254, - 255, 256, 361, 1556, 259, 260, 55, 1584, 1556, 1601, - 569, 570, 361, 572, 319, 498, 214, 498, 2211, 499, - 1597, 265, 502, 375, 409, 2716, 411, 2211, 1662, 2211, - 335, 2211, 1836, 345, 1838, 807, 234, 960, 961, 481, - 963, 24, 814, 2734, 368, 150, 131, 30, 1601, 2390, - 13, 14, 499, 1601, 504, 502, 251, 252, 253, 254, - 255, 256, 220, 375, 259, 260, 1700, 1661, 2825, 1663, - 1664, 361, 2701, 158, 2145, 1752, 2147, 436, 1154, 369, - 2354, 405, 2356, 533, 2317, 283, 2860, 436, 2162, 13, - 14, 443, 423, 2037, 292, 13, 14, 1833, 1961, 1835, - 1176, 151, 2161, 434, 2861, 37, 1182, 1183, 352, 499, - 365, 366, 502, 2146, 290, 405, 499, 13, 14, 502, - 892, 1197, 446, 499, 56, 341, 502, 499, 433, 901, - 502, 443, 13, 14, 290, 440, 460, 290, 2160, 498, - 2162, 151, 592, 915, 2203, 499, 151, 2838, 502, 498, - 3014, 151, 5, 136, 926, 8, 928, 929, 160, 499, - 484, 14, 452, 165, 498, 341, 1242, 2978, 2979, 345, - 365, 366, 25, 500, 498, 107, 29, 605, 499, 607, - 1241, 502, 1258, 1934, 1935, 341, 271, 2961, 341, 345, - 1242, 276, 345, 271, 2115, 1271, 281, 1273, 1897, 375, - 1276, 1277, 499, 2960, 368, 502, 2980, 1268, 1268, 1905, - 1286, 1268, 1288, 1289, 1290, 1291, 1292, 1293, 1294, 375, - 3031, 1268, 375, 478, 479, 499, 499, 499, 502, 502, - 502, 37, 234, 499, 432, 150, 502, 452, 1314, 499, - 1316, 405, 502, 13, 14, 1321, 1322, 1323, 1324, 1325, - 1326, 1327, 1328, 13, 14, 83, 1332, 1333, 13, 14, - 95, 1337, 3036, 368, 464, 1341, 198, 443, 1344, 1345, - 1346, 1347, 1348, 1349, 1350, 1351, 1352, 1268, 1959, 1355, - 449, 283, 446, 478, 479, 498, 1362, 443, 499, 1365, - 443, 502, 1368, 368, 37, 315, 460, 498, 496, 151, - 405, 499, 500, 498, 186, 187, 499, 290, 498, 502, - 2181, 1387, 37, 56, 13, 14, 2549, 249, 1241, 499, - 484, 1913, 502, 2664, 499, 257, 498, 502, 36, 967, - 405, 56, 1408, 1385, 498, 498, 171, 269, 423, 499, - 151, 446, 502, 1419, 1420, 1268, 286, 68, 499, 434, - 2756, 502, 151, 74, 499, 460, 499, 502, 341, 502, - 1913, 151, 345, 2396, 107, 1913, 87, 343, 300, 2443, - 205, 446, 405, 255, 256, 1451, 13, 14, 498, 484, - 176, 1457, 107, 1459, 1961, 460, 221, 37, 2040, 1953, - 1982, 499, 375, 498, 502, 116, 231, 118, 2032, 13, - 14, 499, 1393, 199, 502, 2345, 232, 499, 2000, 484, - 502, 1334, 5, 499, 498, 347, 502, 499, 499, 2359, - 502, 502, 1498, 498, 496, 1501, 1502, 5, 1504, 1982, - 265, 174, 165, 499, 1982, 2027, 502, 369, 13, 14, - 498, 237, 2034, 13, 14, 498, 1522, 2000, 13, 14, - 498, 286, 2000, 368, 498, 198, 498, 389, 498, 1535, - 443, 13, 14, 680, 2096, 1541, 2058, 13, 14, 2702, - 1393, 498, 2124, 198, 2027, 13, 14, 13, 14, 2027, - 1556, 2034, 203, 365, 366, 702, 2034, 498, 146, 2931, - 405, 2933, 13, 14, 5, 291, 5, 176, 948, 2180, - 498, 2182, 160, 13, 14, 2058, 249, 165, 1584, 498, - 1282, 498, 2248, 498, 257, 5, 733, 352, 498, 2196, - 199, 1597, 5, 1599, 249, 1601, 269, 13, 14, 498, - 1606, 446, 257, 13, 14, 1611, 356, 357, 356, 357, - 259, 260, 1533, 498, 269, 460, 365, 366, 356, 357, - 271, 356, 357, 2249, 498, 276, 214, 300, 237, 498, - 928, 929, 498, 2434, 498, 361, 1650, 499, 3010, 484, - 147, 9, 1648, 1649, 1650, 300, 234, 1653, 498, 297, - 502, 461, 216, 498, 98, 1661, 1662, 1663, 1664, 2181, - 502, 499, 37, 375, 165, 1671, 283, 2938, 319, 1675, - 281, 165, 1678, 1375, 347, 440, 232, 498, 498, 416, - 1533, 2670, 291, 409, 335, 411, 1700, 87, 502, 1695, - 1696, 2212, 347, 416, 1700, 283, 369, 55, 2181, 846, - 55, 427, 416, 2181, 292, 262, 416, 433, 1714, 499, - 436, 1717, 507, 1719, 369, 416, 389, 864, 460, 151, - 8, 1289, 94, 2245, 500, 271, 271, 498, 16, 17, - 18, 19, 37, 1739, 389, 498, 6, 498, 9, 36, - 299, 11, 414, 414, 1750, 15, 416, 2540, 416, 496, - 20, 21, 22, 23, 24, 1769, 496, 27, 416, 1765, - 30, 31, 2245, 416, 34, 35, 499, 2245, 502, 456, - 498, 11, 343, 1764, 1764, 497, 2476, 1764, 1784, 504, - 2446, 2447, 433, 2365, 502, 502, 507, 1764, 1750, 440, - 414, 498, 276, 1799, 1800, 2317, 498, 1650, 2380, 1750, - 409, 416, 411, 1765, 161, 179, 170, 499, 440, 368, - 80, 37, 1818, 51, 1765, 498, 214, 87, 88, 89, - 90, 91, 502, 378, 433, 287, 223, 436, 308, 308, - 1836, 1837, 1838, 502, 2317, 499, 498, 223, 271, 223, - 1408, 324, 292, 1764, 432, 452, 405, 1700, 284, 151, - 151, 498, 498, 37, 1234, 460, 1236, 271, 96, 286, - 499, 496, 499, 2664, 286, 1718, 499, 481, 2742, 481, - 405, 1877, 499, 499, 499, 271, 37, 37, 499, 497, - 8, 1734, 1584, 11, 122, 170, 1588, 446, 16, 17, - 18, 19, 500, 499, 481, 1597, 499, 1750, 499, 499, - 499, 460, 140, 499, 499, 499, 144, 1913, 499, 499, - 502, 1764, 1765, 499, 499, 499, 1769, 1923, 170, 498, - 416, 2415, 498, 2445, 498, 484, 498, 154, 166, 457, - 457, 169, 446, 286, 502, 2939, 487, 287, 287, 498, - 8, 483, 287, 11, 502, 438, 184, 242, 16, 17, - 18, 19, 416, 1959, 2476, 1961, 271, 498, 151, 151, - 199, 151, 2445, 416, 416, 278, 34, 2445, 416, 416, - 278, 497, 37, 1979, 499, 499, 1982, 498, 343, 286, - 502, 284, 1988, 460, 37, 1991, 151, 499, 1994, 151, - 276, 497, 142, 2476, 2000, 2001, 2002, 2003, 2004, 2005, - 288, 170, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, - 2016, 2017, 497, 2070, 2643, 2021, 2022, 11, 165, 2025, - 498, 2027, 170, 2037, 499, 499, 2032, 2549, 2034, 499, - 2904, 2037, 457, 2540, 499, 502, 1957, 296, 276, 499, - 2046, 499, 405, 2049, 170, 2051, 284, 502, 179, 484, - 499, 349, 2058, 2059, 2068, 445, 2062, 2063, 85, 287, - 498, 2067, 2068, 1443, 151, 499, 2549, 498, 196, 174, - 499, 2085, 502, 1453, 498, 1455, 427, 2083, 1458, 2085, - 1648, 1649, 499, 502, 1464, 1653, 1466, 499, 499, 327, - 218, 2097, 499, 498, 37, 80, 440, 499, 1478, 502, - 170, 2107, 497, 1483, 1957, 498, 498, 1487, 1488, 1489, - 1490, 499, 1492, 1493, 499, 502, 499, 2123, 499, 499, - 407, 2083, 498, 2085, 221, 295, 221, 1695, 1696, 498, - 293, 55, 2083, 183, 2085, 487, 460, 2938, 499, 499, - 1842, 201, 2664, 499, 116, 37, 223, 82, 189, 276, - 218, 498, 276, 416, 500, 416, 37, 500, 2769, 500, - 288, 500, 500, 500, 500, 500, 500, 500, 500, 500, - 2176, 500, 500, 500, 2180, 2181, 2182, 500, 500, 500, - 2702, 2664, 500, 500, 2037, 1887, 2664, 487, 500, 500, - 500, 500, 271, 108, 500, 460, 500, 485, 486, 487, - 1902, 489, 490, 491, 492, 493, 494, 500, 500, 499, - 286, 2733, 37, 170, 2736, 2068, 2823, 498, 488, 2702, - 288, 498, 492, 498, 498, 495, 221, 459, 132, 498, - 2083, 87, 2085, 499, 504, 502, 335, 37, 2867, 2245, - 498, 151, 74, 499, 123, 151, 37, 357, 499, 357, - 2733, 110, 111, 2736, 2876, 2733, 2262, 305, 2736, 1961, - 37, 531, 532, 533, 1966, 498, 1968, 498, 502, 499, - 1972, 1973, 326, 498, 498, 498, 74, 445, 548, 498, - 276, 247, 2846, 188, 2848, 440, 427, 498, 2209, 2783, - 68, 289, 68, 55, 498, 502, 499, 567, 568, 569, - 570, 498, 572, 37, 440, 2311, 2312, 487, 375, 269, - 2316, 2317, 2233, 583, 2235, 2321, 286, 37, 2324, 2325, - 427, 498, 592, 2329, 289, 289, 2937, 186, 187, 359, - 201, 498, 498, 603, 286, 499, 286, 9, 342, 121, - 499, 499, 499, 2349, 438, 615, 499, 2353, 499, 356, - 499, 34, 498, 23, 9, 499, 2209, 485, 486, 487, - 2163, 489, 490, 491, 492, 493, 494, 1465, 2862, 2375, - 2176, 600, 1831, 87, 2379, 89, 2121, 91, 2610, 2861, - 2233, 2934, 2235, 653, 654, 655, 656, 2349, 2439, 2882, - 2218, 2353, 251, 252, 253, 254, 255, 256, 2349, 2988, - 259, 260, 2353, 2409, 2940, 2636, 2949, 2981, 2685, 982, - 1824, 2417, 1837, 2947, 2937, 2223, 2938, 485, 486, 487, - 2155, 489, 490, 491, 492, 493, 494, 2180, 1821, 2935, - 2436, 1230, 1959, 2001, 2002, 2003, 2004, 2005, 1182, 2445, - 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, - 1893, 2540, 2206, 1784, 1436, 2938, 2377, 2378, 948, 920, - 2938, 970, 2835, 2856, 2976, 969, 1799, 2101, 2917, 1408, - 2476, 2850, 2371, 2755, 1435, 972, 2085, 1765, 2730, 2181, - 2340, 2355, 2083, 2825, 2824, 2842, 1282, 2843, 1282, 1156, - 1282, 1282, 2606, 2921, 2062, 2063, 2349, 2920, 1676, 2964, - 2353, 1360, 1785, 1273, 2206, 1718, 365, 366, 1715, 1504, - 8, 1607, 2375, 11, 1753, 2100, 568, 2817, 16, 17, - 18, 19, 1898, 1242, 2377, 2378, 1597, 1385, 954, 2122, - 1386, -1, -1, -1, 2540, -1, 34, 1917, -1, -1, - 2546, -1, -1, 2549, -1, -1, 2552, -1, -1, -1, - 820, -1, -1, -1, -1, 2561, 2562, -1, -1, 2565, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 2578, -1, -1, -1, -1, -1, -1, -1, - -1, 2587, -1, -1, -1, -1, 2592, -1, -1, 2595, - -1, -1, -1, -1, -1, 8, 2602, 2603, 11, -1, - -1, 2522, -1, 16, 17, 18, 19, -1, 2614, -1, - 2616, -1, -1, -1, -1, -1, 2578, 887, -1, 478, - 479, -1, -1, -1, -1, 2587, -1, 2578, 2634, -1, - 2592, -1, -1, 2595, -1, 529, 2587, -1, -1, -1, - -1, 2592, -1, -1, 2595, -1, -1, -1, -1, -1, - -1, -1, 2614, -1, -1, -1, -1, -1, 2664, -1, - 930, -1, -1, 2614, -1, -1, -1, -1, -1, 2522, - 2372, -1, 8, -1, -1, 11, -1, -1, 948, 949, - 16, 17, 18, 19, 954, 955, 956, -1, -1, -1, - -1, 2697, -1, -1, -1, 2701, 2702, -1, 34, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 981, 982, -1, -1, -1, -1, -1, -1, 2725, - 218, -1, -1, 2729, 994, -1, -1, 2733, 2742, -1, - 2736, -1, -1, -1, 2587, 2697, 2742, -1, -1, 2592, - -1, 1011, 2595, -1, -1, 1015, 2697, -1, -1, 8, - 2756, -1, 11, 2759, 2675, -1, -1, 16, 17, 18, - 19, 2141, -1, 2769, -1, -1, -1, 2729, 2774, -1, - -1, -1, -1, -1, 488, 34, -1, 2698, 2729, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 2168, -1, - 288, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 2183, 2184, 2185, 2186, 2187, 2188, 2189, - 2190, 2191, 2192, -1, 708, -1, 2518, -1, 529, 2825, - -1, -1, 2675, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 2540, -1, - 2846, -1, 2848, -1, 2850, 2698, -1, -1, 2854, 2417, - -1, -1, -1, -1, -1, 2861, -1, -1, -1, -1, - 529, -1, -1, 2825, -1, 529, -1, -1, -1, 583, - -1, -1, -1, -1, 2825, 288, 2729, 2798, 2884, 1149, - -1, -1, 218, -1, -1, -1, -1, 1157, 0, 2742, - -1, -1, -1, -1, -1, -1, 1166, -1, 2904, 2861, - -1, 615, -1, 2605, -1, -1, 529, -1, -1, -1, - 2861, 2917, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 2301, 816, -1, -1, -1, -1, -1, -1, 1199, - -1, 2937, 2938, -1, -1, -1, 2857, -1, -1, 653, - 654, 655, 656, -1, -1, 2798, -1, -1, -1, -1, - -1, -1, 288, -1, 2960, -1, -1, 2963, 2964, 218, - 1230, 1231, 2664, 1233, 1234, -1, 1236, 1237, -1, -1, - 1240, -1, -1, -1, -1, -1, -1, -1, 2546, -1, - -1, -1, 94, -1, -1, -1, -1, 485, 486, 487, - 2996, 489, 490, 491, 492, 493, 494, 708, 2960, -1, - -1, -1, -1, -1, 2857, -1, -1, -1, -1, 2960, - -1, -1, -1, -1, -1, -1, -1, 1287, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 1298, 288, - -1, 3037, 2953, -1, 146, -1, 2416, -1, -1, 708, - -1, -1, -1, -1, 708, -1, -1, -1, 160, -1, - -1, -1, -1, 165, -1, -1, -1, -1, 170, -1, - -1, 1331, -1, -1, -1, -1, -1, 179, -1, -1, - -1, 183, 485, 486, 487, -1, 489, 490, 491, 492, - 493, 494, -1, -1, -1, 708, -1, -1, -1, -1, - 2792, -1, 1362, 1363, -1, -1, -1, -1, -1, -1, - 2953, 995, 214, -1, -1, 816, -1, -1, -1, -1, - -1, -1, -1, -1, 1384, -1, 1386, -1, -1, -1, - -1, -1, 234, -1, -1, 1395, -1, 1397, -1, -1, - 0, -1, -1, 2701, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 816, -1, 485, - 486, 487, 816, 489, 490, 491, 492, 493, 494, -1, - -1, -1, -1, 1433, -1, -1, -1, -1, -1, -1, - -1, 283, 1442, 1443, 286, -1, -1, -1, -1, -1, - 292, -1, -1, 1453, 1454, 1455, 1456, -1, 1458, -1, - -1, -1, -1, 816, 1464, -1, 1466, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1477, 1478, -1, - -1, -1, 1482, 1483, 326, -1, 930, 1487, 1488, 1489, - 1490, -1, 1492, 1493, 94, -1, 485, 486, 487, -1, - 489, 490, 491, 492, 493, 494, 2938, 349, -1, -1, - -1, 955, 1512, 1513, 1514, -1, -1, -1, -1, 8, - -1, -1, 11, -1, -1, 0, -1, 16, 17, 18, - 19, 1531, -1, -1, -1, 2645, -1, 981, -1, -1, - -1, -1, -1, -1, -1, -1, 146, -1, -1, -1, - 994, -1, -1, -1, 995, 2665, 2666, -1, 1182, 1183, - 160, -1, -1, 405, -1, 165, -1, -1, -1, -1, - 170, 1015, 2682, 1197, -1, -1, -1, -1, -1, 179, - -1, -1, -1, 183, -1, -1, -1, -1, -1, -1, - 432, -1, -1, -1, -1, -1, 995, -1, 440, -1, - -1, 995, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 214, 457, -1, 459, 460, 94, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 234, -1, -1, -1, -1, -1, - -1, -1, 995, -1, -1, -1, -1, -1, 2758, -1, - -1, -1, -1, -1, 496, -1, -1, 499, 500, 501, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 1669, - -1, 146, -1, -1, -1, -1, 1676, -1, -1, -1, - -1, -1, -1, 283, -1, 160, 286, -1, -1, -1, - 165, -1, 292, -1, -1, 170, -1, 1321, -1, -1, - -1, -1, -1, -1, 179, -1, -1, -1, 183, -1, - -1, -1, 1712, 1157, -1, -1, -1, -1, 567, 568, - -1, -1, -1, -1, -1, -1, 326, -1, -1, 218, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 214, - -1, 1182, 1183, -1, 1744, -1, -1, -1, -1, 349, - 1750, -1, -1, -1, 24, -1, 1197, -1, -1, 234, - 30, -1, -1, -1, -1, 1765, -1, 37, -1, 1769, - -1, -1, 1772, -1, 1774, -1, -1, -1, -1, -1, - -1, 630, 631, 1182, 1183, -1, 56, -1, 1182, 1183, - -1, -1, -1, -1, -1, -1, 1240, -1, 1197, 288, - -1, -1, -1, 1197, -1, 405, -1, -1, 283, -1, - -1, 286, -1, 8, -1, -1, 11, 292, -1, -1, - -1, 16, 17, 18, 19, -1, 1826, 1451, -1, 1182, - 1183, -1, 432, -1, -1, -1, -1, 107, -1, -1, - 440, -1, -1, -1, 1197, -1, -1, -1, -1, -1, - -1, 326, -1, -1, -1, -1, -1, 457, -1, 459, - 460, -1, -1, -1, -1, -1, 136, -1, -1, -1, - -1, -1, -1, -1, 349, -1, -1, -1, -1, -1, - 1321, -1, -1, -1, -1, -1, -1, -1, -1, 1889, - -1, -1, -1, -1, 1894, -1, 496, -1, -1, 499, - 500, 501, -1, 1903, 1904, 1905, 1906, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 1917, -1, 1363, - -1, -1, 1321, -1, -1, 1925, -1, 1321, 198, -1, - 405, -1, 1556, -1, -1, -1, -1, 1937, -1, -1, - 1384, -1, 1386, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 1953, -1, 1955, -1, 432, -1, -1, - -1, -1, -1, -1, -1, 440, 815, -1, 1321, -1, - 1970, 1971, -1, -1, -1, -1, -1, 1601, -1, 249, - -1, -1, 457, 832, 459, 460, -1, 257, -1, 1433, - -1, -1, -1, 1993, -1, -1, 485, 486, 487, 269, - 489, 490, 491, 492, 493, 494, -1, -1, -1, -1, - 1451, -1, 861, -1, -1, -1, -1, -1, -1, -1, - 290, 496, -1, 218, 499, 500, 501, -1, -1, -1, - 300, -1, 881, 882, 883, -1, -1, 886, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 1451, -1, -1, -1, -1, 1451, -1, -1, - 909, -1, -1, -1, -1, -1, -1, -1, 1512, 1513, - -1, 341, -1, -1, -1, 345, -1, 347, -1, -1, - 2080, 2081, 2082, 2083, -1, 2085, 2086, -1, -1, -1, - -1, 2091, 2092, 288, -1, -1, -1, -1, 1451, 369, - -1, -1, -1, -1, -1, 375, -1, -1, -1, -1, - -1, -1, -1, 962, -1, 1556, -1, 966, 967, 389, - -1, 2121, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 807, -1, -1, 2139, - -1, 2141, -1, 814, -1, 2145, 2146, 2147, -1, 2149, - -1, -1, -1, -1, -1, -1, -1, 1556, -1, -1, - 1601, -1, 1556, -1, -1, -1, -1, -1, 2168, -1, - 2170, 1020, -1, 443, -1, -1, -1, -1, 1027, -1, - -1, -1, -1, 2183, 2184, 2185, 2186, 2187, 2188, 2189, - 2190, 2191, 2192, -1, -1, -1, -1, -1, -1, -1, - 1049, -1, 1601, 1556, -1, -1, -1, 1601, 2208, -1, - -1, -1, -1, 2213, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 2223, -1, -1, -1, -1, -1, -1, - 901, -1, -1, -1, -1, -1, -1, 2237, 8, -1, - -1, 11, -1, -1, -1, -1, 16, -1, 1601, 2249, - -1, -1, -1, -1, -1, 926, 2256, 928, 929, -1, + 6, 6, 501, 667, 0, 0, 656, 59, 0, 0, + 0, 947, 1070, 642, 740, 868, 1068, 622, 770, 1010, + 1043, 773, 16, 537, 545, 672, 1244, 617, 0, 0, + 0, 61, 36, 0, 746, 663, 1462, 1895, 30, 1465, + 539, 1422, 1846, 1045, 16, 1849, 31, 1048, 6, 1347, + 950, 665, 1116, 1039, 544, 2271, 545, 1249, 537, 1891, + 656, 2242, 658, 61, 660, 540, 966, 2242, 1816, 0, + 2269, 1073, 1376, 1377, 868, 1812, 876, 1774, 0, 979, + 0, 1709, 1710, 537, 0, 1837, 1714, 21, 80, 0, + 0, 1828, 0, 1939, 1940, 1941, 35, 0, 2280, 2287, + 0, 2097, 0, 1954, 0, 90, 0, 700, 701, 52, + 2147, 0, 5, 0, 9, 0, 2153, 0, 0, 9, + 0, 1575, 0, 0, 2145, 60, 5, 56, 0, 1757, + 1758, 0, 60, 60, 16, 1967, 0, 5, 731, 0, + 3, 0, 13, 14, 568, 1430, 11, 5, 30, 5, + 15, 5, 639, 5, 36, 9, 5, 5, 20, 21, + 5, 13, 14, 75, 13, 14, 639, 1485, 13, 14, + 33, 34, 777, 5, 5, 5, 5, 1215, 9, 61, + 5, 13, 14, 13, 14, 5, 5, 5, 13, 14, + 1483, 5, 5, 987, 5, 13, 14, 2587, 80, 2031, + 2032, 5, 13, 14, 5, 5, 139, 5, 95, 13, + 14, 1812, 13, 14, 5, 13, 14, 95, 5, 5, + 5, 11, 1028, 935, 77, 15, 2577, 1828, 13, 14, + 5, 172, 69, 77, 29, 88, 122, 42, 189, 2590, + 147, 36, 5, 85, 88, 60, 1342, 2727, 42, 124, + 2178, 60, 177, 43, 2759, 2152, 1342, 171, 244, 285, + 2084, 740, 29, 1057, 29, 1342, 1060, 1061, 109, 36, + 293, 36, 5, 2856, 2663, 200, 287, 117, 357, 293, + 5, 1081, 5, 5, 5, 75, 740, 129, 2483, 309, + 309, 25, 1092, 273, 2555, 119, 4, 31, 3, 4, + 5, 9, 895, 896, 9, 2573, 122, 170, 215, 172, + 122, 132, 334, 238, 2160, 2824, 70, 109, 1237, 61, + 276, 38, 29, 38, 210, 137, 29, 69, 921, 39, + 1056, 168, 120, 117, 191, 378, 163, 396, 358, 2925, + 4, 946, 3057, 149, 161, 9, 441, 868, 119, 189, + 110, 2209, 13, 14, 875, 463, 499, 2054, 11, 2540, + 2397, 951, 15, 2400, 405, 348, 2582, 292, 11, 2210, + 110, 488, 15, 2956, 2206, 11, 2208, 485, 461, 15, + 994, 871, 499, 3098, 406, 2584, 293, 2408, 2192, 172, + 980, 2412, 198, 376, 2745, 1342, 455, 0, 877, 440, + 287, 228, 485, 137, 499, 193, 2795, 43, 2145, 287, + 256, 257, 117, 1332, 349, 1351, 126, 1007, 235, 163, + 499, 349, 349, 877, 502, 132, 161, 383, 165, 132, + 503, 453, 272, 1038, 2062, 2063, 2064, 2065, 2066, 75, + 369, 2069, 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, + 2078, 437, 3038, 277, 2295, 270, 499, 211, 175, 439, + 175, 282, 304, 350, 2725, 2855, 11, 284, 989, 990, + 15, 3054, 350, 499, 494, 494, 1774, 406, 270, 2988, + 503, 2313, 1505, 320, 499, 410, 120, 412, 499, 503, + 347, 2686, 1121, 277, 2122, 2123, 238, 1561, 43, 2396, + 235, 493, 451, 417, 2328, 166, 344, 319, 987, 434, + 2705, 216, 437, 499, 1818, 1969, 3021, 2445, 447, 2999, + 366, 367, 305, 441, 457, 269, 433, 1623, 1624, 1625, + 75, 537, 1590, 238, 349, 393, 394, 1623, 1856, 545, + 349, 545, 2143, 1349, 2145, 1622, 2727, 1585, 499, 1036, + 1848, 545, 2727, 439, 2736, 1840, 499, 291, 499, 193, + 1224, 376, 1855, 1036, 417, 406, 441, 2957, 503, 411, + 499, 450, 544, 417, 461, 503, 503, 1056, 315, 1003, + 2969, 499, 612, 461, 2852, 497, 200, 1215, 451, 501, + 642, 386, 1656, 599, 600, 463, 2454, 434, 403, 382, + 490, 491, 1056, 498, 497, 2642, 499, 2958, 501, 403, + 2461, 493, 346, 500, 612, 502, 622, 485, 2614, 386, + 499, 386, 500, 439, 502, 1425, 620, 251, 499, 2650, + 495, 499, 1237, 11, 2655, 631, 631, 2658, 2854, 631, + 631, 631, 376, 499, 463, 499, 580, 499, 422, 634, + 499, 499, 1245, 1246, 499, 661, 662, 663, 11, 631, + 631, 631, 544, 545, 631, 1471, 485, 499, 499, 499, + 499, 2408, 443, 2861, 499, 2412, 1623, 1624, 2860, 499, + 499, 499, 132, 32, 623, 499, 499, 4, 499, 1317, + 43, 2443, 9, 77, 2488, 499, 453, 75, 499, 499, + 631, 499, 2496, 1217, 88, 495, 406, 56, 499, 631, + 444, 631, 499, 499, 499, 631, 578, 1331, 580, 581, + 631, 631, 75, 631, 499, 1330, 2572, 1332, 631, 1243, + 612, 631, 1337, 631, 740, 631, 499, 631, 1217, 1730, + 1534, 603, 631, 2575, 1258, 1350, 631, 2963, 631, 631, + 1544, 631, 2449, 1547, 631, 2954, 2054, 1371, 1372, 631, + 1388, 119, 631, 1217, 1243, 1244, 499, 631, 1373, 2790, + 631, 777, 631, 1363, 499, 365, 499, 499, 499, 1258, + 1301, 25, 490, 491, 419, 490, 491, 31, 1641, 1243, + 1244, 5, 1291, 1292, 187, 188, 1596, 461, 77, 1298, + 1428, 2105, 1994, 25, 1258, 1419, 244, 2408, 2000, 88, + 1300, 2412, 1301, 1427, 329, 1429, 3015, 24, 2999, 1294, + 117, 485, 272, 30, 2999, 499, 490, 491, 108, 464, + 2688, 488, 282, 151, 1820, 1735, 2641, 490, 491, 492, + 493, 494, 495, 358, 501, 177, 204, 1641, 2476, 492, + 493, 494, 495, 1605, 490, 491, 492, 493, 494, 495, + 171, 1919, 868, 256, 257, 1801, 1380, 3083, 499, 875, + 876, 877, 2677, 80, 1626, 25, 1628, 494, 1942, 1631, + 1530, 31, 221, 132, 501, 2407, 4, 893, 2056, 334, + 482, 9, 1391, 137, 1522, 2417, 501, 244, 2420, 871, + 2118, 1380, 287, 1709, 1710, 151, 238, 1503, 1714, 200, + 159, 244, 270, 2650, 272, 137, 922, 2085, 2655, 1808, + 1809, 2658, 224, 482, 362, 1927, 1380, 69, 1557, 1558, + 1559, 1578, 500, 25, 1530, 503, 942, 943, 944, 31, + 946, 947, 1842, 947, 2242, 492, 147, 492, 493, 494, + 495, 1757, 1758, 1549, 2759, 170, 494, 1585, 1554, 29, + 161, 406, 272, 501, 970, 166, 244, 277, 270, 50, + 250, 2829, 503, 366, 367, 117, 463, 1978, 258, 244, + 2608, 4, 1983, 989, 990, 4, 9, 137, 499, 871, + 9, 1021, 1022, 1722, 1024, 1724, 1725, 1602, 485, 437, + 1514, 601, 602, 300, 604, 1646, 868, 889, 453, 1650, + 80, 1652, 499, 875, 215, 362, 500, 1023, 328, 89, + 463, 1027, 1028, 1021, 1022, 500, 1024, 909, 277, 362, + 1015, 171, 1038, 282, 235, 1514, 500, 25, 217, 503, + 2641, 1540, 485, 31, 56, 137, 1545, 291, 118, 2650, + 1056, 369, 8, 2790, 2655, 11, 499, 2658, 132, 15, + 1514, 499, 18, 19, 20, 947, 497, 499, 499, 291, + 501, 362, 369, 13, 14, 1081, 2677, 379, 410, 370, + 412, 2886, 482, 284, 362, 159, 1092, 1072, 406, 497, + 437, 953, 293, 501, 221, 176, 244, 362, 342, 497, + 962, 499, 346, 1617, 437, 437, 417, 499, 497, 406, + 1116, 192, 501, 152, 976, 406, 197, 2922, 1723, 189, + 1641, 342, 224, 369, 346, 987, 348, 989, 990, 447, + 272, 201, 376, 1654, 2762, 277, 152, 439, 1617, 1021, + 1022, 291, 1024, 461, 1658, 461, 1898, 463, 1900, 137, + 447, 2449, 499, 234, 376, 2373, 152, 1762, 2759, 437, + 406, 2097, 453, 1617, 461, 2223, 499, 485, 270, 2022, + 2222, 334, 437, 2921, 410, 424, 412, 488, 320, 1658, + 500, 499, 152, 503, 2207, 1814, 435, 500, 485, 2790, + 501, 172, 342, 410, 336, 412, 346, 272, 272, 291, + 444, 447, 499, 277, 1658, 66, 67, 370, 282, 1215, + 173, 1217, 2264, 501, 362, 461, 3021, 3075, 1214, 1214, + 2221, 499, 2223, 1214, 1214, 206, 376, 25, 330, 13, + 14, 1237, 433, 31, 499, 3039, 3040, 1243, 1244, 485, + 410, 222, 412, 406, 38, 2134, 2135, 2136, 2137, 453, + 342, 232, 1258, 499, 346, 84, 2062, 2063, 2064, 2065, + 2066, 13, 14, 2069, 2070, 2071, 2072, 2073, 2074, 2075, + 2076, 2077, 2078, 465, 3022, 500, 2176, 379, 503, 499, + 537, 369, 245, 711, 376, 2886, 1998, 1999, 3092, 437, + 453, 450, 434, 3041, 444, 1301, 13, 14, 1962, 441, + 381, 500, 537, 291, 503, 733, 500, 1301, 316, 503, + 500, 1317, 500, 503, 499, 503, 2122, 2123, 406, 152, + 500, 2922, 392, 503, 1330, 395, 1332, 499, 1300, 500, + 1336, 1337, 503, 289, 499, 1327, 161, 439, 766, 137, + 1346, 166, 1348, 1349, 1350, 1351, 1352, 1353, 1354, 3097, + 424, 499, 444, 37, 342, 1327, 1327, 1327, 346, 447, + 1327, 435, 500, 500, 499, 503, 503, 1373, 410, 1375, + 412, 334, 353, 461, 1380, 1381, 1382, 1383, 1384, 1385, + 1386, 1387, 1388, 1901, 152, 1903, 1392, 1393, 376, 369, + 152, 1397, 2020, 2611, 2206, 1401, 2208, 485, 1404, 1405, + 1406, 1407, 1408, 1409, 1410, 1411, 1412, 370, 152, 1415, + 235, 499, 13, 14, 147, 300, 1422, 287, 1300, 1425, + 3021, 500, 1428, 636, 503, 638, 406, 500, 161, 2727, + 503, 500, 2455, 166, 503, 499, 2817, 5, 1468, 38, + 8, 1447, 8, 406, 2502, 1327, 14, 500, 2242, 15, + 503, 1445, 18, 19, 20, 500, 444, 25, 503, 284, + 233, 29, 1454, 1977, 499, 1471, 500, 447, 161, 503, + 1468, 500, 500, 166, 503, 503, 1482, 1483, 500, 907, + 1342, 503, 215, 740, 369, 2413, 2100, 2415, 2093, 500, + 453, 5, 503, 291, 25, 5, 500, 925, 1977, 503, + 31, 2022, 235, 500, 52, 740, 503, 500, 1514, 499, + 503, 166, 1394, 499, 1520, 499, 1522, 500, 2017, 499, + 503, 406, 500, 1977, 500, 503, 499, 503, 499, 2043, + 486, 487, 488, 499, 490, 491, 492, 493, 494, 495, + 500, 499, 235, 503, 342, 2763, 499, 2061, 346, 97, + 500, 284, 5, 503, 2306, 1561, 13, 14, 1564, 1565, + 293, 1567, 447, 5, 2043, 499, 2992, 2157, 2994, 13, + 14, 2185, 1454, 1435, 2088, 123, 461, 499, 376, 1585, + 499, 2095, 2061, 13, 14, 499, 1468, 13, 14, 2043, + 1596, 284, 499, 141, 13, 14, 1602, 145, 13, 14, + 485, 499, 1594, 13, 14, 5, 137, 2061, 499, 2088, + 5, 1617, 96, 2241, 499, 2243, 2095, 13, 14, 167, + 877, 96, 170, 13, 14, 499, 2273, 499, 2257, 13, + 14, 177, 13, 14, 2088, 1641, 499, 185, 9, 2118, + 499, 2095, 877, 13, 14, 3071, 444, 148, 1654, 499, + 1656, 462, 1658, 298, 200, 13, 14, 503, 6, 13, + 14, 1667, 217, 11, 2118, 99, 1672, 15, 13, 14, + 2476, 503, 20, 21, 22, 23, 24, 13, 14, 27, + 500, 2733, 30, 31, 13, 14, 34, 35, 172, 13, + 14, 38, 238, 357, 358, 357, 358, 172, 376, 2493, + 433, 2999, 166, 1709, 1710, 1711, 284, 1711, 1714, 260, + 261, 166, 1594, 366, 367, 282, 1722, 1723, 1724, 1725, + 357, 358, 206, 289, 357, 358, 1732, 233, 2242, 277, + 1736, 206, 80, 1739, 989, 990, 499, 285, 222, 87, + 88, 89, 90, 91, 417, 499, 292, 222, 232, 2602, + 88, 1757, 1758, 2505, 2506, 69, 1762, 232, 1762, 417, + 291, 75, 503, 2242, 497, 56, 537, 500, 501, 56, + 1776, 417, 263, 1779, 88, 1781, 417, 500, 508, 1641, + 328, 417, 266, 1645, 461, 152, 2777, 95, 2242, 2303, + 501, 266, 1654, 272, 272, 1801, 11, 499, 38, 1056, + 15, 499, 2608, 117, 2795, 119, 1812, 1812, 23, 499, + 2424, 342, 287, 9, 2540, 346, 362, 37, 415, 34, + 35, 1056, 1828, 1828, 2303, 2439, 415, 497, 1832, 1711, + 497, 417, 417, 417, 417, 1827, 457, 500, 503, 499, + 11, 1847, 344, 415, 498, 376, 503, 503, 499, 2303, + 277, 499, 417, 505, 1812, 1827, 1827, 1827, 1864, 1865, + 1827, 508, 180, 162, 410, 171, 412, 2803, 500, 353, + 1828, 500, 503, 88, 499, 38, 215, 1883, 353, 441, + 1762, 503, 428, 263, 379, 288, 309, 224, 434, 309, + 204, 437, 503, 500, 2373, 1901, 1902, 1903, 1780, 499, + 272, 224, 224, 325, 293, 499, 285, 152, 2899, 453, + 152, 461, 38, 444, 1796, 272, 497, 38, 287, 2373, + 486, 487, 488, 500, 490, 491, 492, 493, 494, 495, + 1812, 500, 287, 2727, 498, 482, 1942, 482, 171, 500, + 500, 500, 3000, 500, 500, 1827, 1828, 500, 500, 503, + 1832, 500, 171, 482, 417, 155, 2762, 500, 272, 500, + 1217, 500, 500, 277, 501, 500, 441, 500, 500, 740, + 500, 1977, 500, 500, 499, 2474, 499, 499, 499, 447, + 287, 1987, 1217, 503, 458, 458, 1243, 1244, 488, 439, + 2504, 484, 288, 288, 288, 503, 243, 272, 152, 417, + 499, 1258, 200, 152, 152, 417, 320, 279, 1243, 1244, + 417, 417, 417, 279, 2020, 500, 2022, 498, 38, 499, + 503, 285, 336, 1258, 344, 2504, 287, 38, 500, 2965, + 461, 500, 152, 498, 2040, 143, 498, 2043, 277, 171, + 11, 166, 2706, 2049, 500, 1907, 2052, 171, 500, 2055, + 2504, 500, 500, 500, 499, 2061, 2062, 2063, 2064, 2065, + 2066, 2540, 500, 2069, 2070, 2071, 2072, 2073, 2074, 2075, + 2076, 2077, 2078, 297, 406, 171, 2082, 2083, 2130, 503, + 2086, 2602, 2088, 485, 500, 180, 2540, 2093, 38, 2095, + 1952, 2097, 500, 2097, 350, 446, 86, 288, 499, 152, + 2106, 175, 500, 2109, 503, 2111, 877, 57, 499, 428, + 38, 499, 2118, 2119, 500, 500, 2122, 2123, 500, 81, + 434, 2127, 2128, 1380, 2128, 2131, 499, 441, 441, 503, + 498, 171, 2611, 222, 500, 499, 499, 2143, 2143, 2145, + 2145, 2145, 503, 408, 500, 1380, 494, 500, 500, 499, + 498, 500, 2158, 501, 500, 296, 222, 2611, 108, 499, + 2022, 294, 2168, 511, 56, 2027, 184, 2029, 461, 500, + 500, 2033, 2034, 488, 500, 202, 117, 38, 2184, 224, + 83, 190, 499, 277, 277, 2143, 417, 2145, 417, 501, + 501, 539, 540, 541, 38, 272, 501, 501, 501, 501, + 501, 501, 2830, 501, 501, 2999, 461, 109, 287, 501, + 171, 501, 501, 2727, 500, 2097, 501, 501, 501, 501, + 501, 501, 87, 501, 89, 501, 91, 501, 501, 499, + 501, 2237, 580, 501, 501, 2241, 2242, 2243, 501, 501, + 488, 501, 501, 501, 501, 222, 2128, 501, 2727, 199, + 501, 599, 600, 601, 602, 2884, 604, 1514, 499, 460, + 503, 2143, 499, 2145, 2928, 499, 614, 499, 88, 133, + 500, 336, 38, 2727, 499, 623, 2272, 2272, 2270, 1514, + 2794, 2272, 2272, 2797, 2763, 1056, 634, 2937, 38, 152, + 75, 57, 500, 124, 152, 38, 511, 2303, 646, 2291, + 250, 2293, 2907, 500, 2909, 306, 358, 358, 258, 2763, + 38, 499, 499, 2319, 500, 2794, 499, 499, 2797, 499, + 270, 327, 503, 446, 75, 540, 541, 499, 277, 248, + 189, 441, 680, 681, 682, 683, 428, 499, 69, 290, + 2794, 56, 108, 2797, 38, 2844, 69, 499, 503, 500, + 38, 301, 499, 441, 376, 270, 287, 488, 428, 38, + 1617, 2367, 2368, 57, 499, 290, 2372, 2373, 290, 499, + 2998, 2377, 500, 500, 2380, 2381, 360, 202, 500, 2385, + 2242, 500, 1617, 499, 9, 500, 287, 287, 2270, 343, + 122, 500, 439, 357, 500, 499, 24, 35, 348, 9, + 500, 1658, 2408, 2408, 631, 2267, 2412, 2412, 623, 2291, + 1896, 2293, 1528, 2438, 108, 2237, 2224, 2922, 11, 2673, + 370, 2182, 15, 1658, 2923, 2995, 2276, 2498, 2434, 3049, + 23, 2943, 2699, 199, 3001, 3010, 3042, 1043, 2747, 1902, + 390, 34, 35, 1889, 2436, 2437, 1217, 2281, 8, 2998, + 2408, 11, 2216, 3008, 2412, 15, 1886, 2996, 1243, 2241, + 1291, 1958, 2468, 2020, 2602, 2267, 981, 1009, 1847, 1499, + 2476, 2896, 1243, 1244, 2917, 3037, 1864, 1471, 2162, 2911, + 2978, 175, 2430, 43, 250, 2999, 2816, 1258, 1498, 2495, + 50, 1031, 258, 1828, 1030, 88, 8, 2145, 2504, 11, + 2397, 2414, 2791, 15, 270, 199, 18, 19, 20, 1033, + 2143, 2886, 2885, 2903, 1342, 75, 2904, 2669, 1342, 1342, + 2999, 1342, 2981, 3025, 2982, 1420, 2408, 1737, 1780, 1848, + 2412, 43, 1668, 881, 2540, 301, 1567, 1777, 50, 600, + 38, 1815, 2434, 2161, 1827, 2999, 1963, 2878, 1301, 1654, + 500, 1445, -1, 2183, 2436, 2437, 250, 1015, 1446, 57, + -1, -1, -1, 75, 258, -1, -1, -1, -1, 2431, + -1, -1, -1, -1, -1, -1, 270, -1, -1, -1, + -1, -1, 348, -1, -1, 145, -1, -1, -1, -1, + -1, -1, -1, 2585, -1, -1, 2602, -1, -1, -1, + 948, -1, 2608, -1, 370, 2611, -1, 301, 2614, 1380, + 108, 109, -1, -1, -1, -1, 176, 2623, 2624, 117, + -1, 2627, -1, -1, 390, -1, -1, -1, -1, 494, + -1, -1, 192, -1, -1, 2641, 2641, 197, -1, -1, + -1, -1, -1, 991, 2650, 2650, -1, -1, -1, 2655, + 2655, -1, 2658, 2658, 348, -1, -1, -1, -1, 2665, + 2666, 1009, 1010, -1, 176, -1, -1, 1015, 1016, 1017, + -1, 2677, 2677, 2679, 234, -1, 370, 175, -1, -1, + 192, -1, -1, 2641, -1, 197, -1, -1, -1, -1, + -1, 2697, 2650, -1, 1042, 1043, 390, 2655, -1, -1, + 2658, 199, -1, 2585, -1, -1, -1, 1055, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 2677, + 1977, 2727, 234, -1, 1072, -1, -1, -1, 1076, 289, + -1, -1, -1, 948, -1, -1, -1, -1, -1, -1, + 2602, -1, 1977, 1514, -1, -1, 2738, -1, -1, 614, + -1, -1, 250, 2759, 2759, 537, 2762, 2763, -1, -1, + 258, -1, -1, -1, -1, -1, -1, -1, 2650, -1, + -1, -1, 270, 2655, 272, -1, 2658, 289, -1, -1, + 2786, 646, -1, -1, 2790, 2790, 2043, -1, 2794, -1, + -1, 2797, -1, -1, 1009, 1010, -1, 2803, -1, 2803, + -1, 2759, -1, 301, 2061, -1, 2668, -1, 2043, -1, + -1, 2817, -1, -1, 2820, 680, 681, 682, 683, -1, + -1, 381, -1, -1, 2830, -1, 2061, -1, -1, 2835, + -1, 2088, 2790, -1, -1, -1, -1, -1, 2095, -1, + -1, -1, -1, -1, -1, -1, 1617, 537, -1, -1, + 348, -1, -1, 2088, -1, -1, 2738, -1, -1, -1, + 2095, 2118, 1210, -1, -1, 2727, -1, 2859, -1, 381, + 1218, -1, 370, -1, -1, -1, -1, -1, -1, 1227, + 2886, 2886, -1, 2118, -1, -1, -1, 1658, -1, -1, + -1, -1, 390, -1, 392, -1, -1, 395, -1, -1, + -1, 2907, -1, 2909, -1, 2911, -1, -1, 2790, 2915, + -1, -1, 1260, -1, -1, -1, 2922, 2922, 511, -1, + -1, 2803, -1, 483, -1, -1, 2918, -1, 2886, -1, + 490, 491, 492, 493, 494, 495, -1, -1, -1, 2945, + -1, -1, -1, 1291, 1292, -1, 1294, 1295, 541, 1297, + 1298, -1, -1, -1, -1, -1, -1, -1, 740, 2965, + -1, -1, -1, -1, 2922, -1, -1, -1, -1, -1, + -1, 483, 2978, -1, 486, 487, 488, 2859, 490, 491, + 492, 493, 494, 495, -1, 2242, -1, -1, -1, -1, + -1, 2853, 2998, 2999, -1, -1, -1, -1, -1, 1347, + -1, 499, -1, -1, -1, -1, -1, 2242, -1, -1, + 1358, -1, -1, -1, -1, 3021, 3021, -1, 3024, 3025, + -1, -1, 3014, -1, -1, -1, -1, -1, -1, -1, + 623, -1, -1, -1, -1, -1, 2918, -1, -1, -1, + -1, -1, -1, 1391, -1, -1, 2303, -1, -1, -1, + 740, 3057, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 3021, -1, -1, -1, -1, 2303, -1, + -1, -1, -1, -1, 1422, 1423, -1, -1, -1, 1294, + 1295, -1, 1297, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 3098, -1, -1, 877, 1444, -1, 1446, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 1456, -1, + 1458, -1, -1, -1, -1, 0, 2373, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 991, -1, -1, -1, + -1, -1, 3014, -1, -1, -1, -1, 2999, 2373, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 1496, -1, + -1, 1016, -1, -1, -1, -1, -1, 1505, 1506, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 1516, 1517, + 1518, 1519, -1, 1521, -1, -1, -1, 1042, -1, 1527, + -1, 1529, -1, -1, -1, 0, -1, 877, -1, -1, + 1055, -1, 1540, 1541, -1, -1, -1, 1545, 1546, -1, + -1, -1, 1550, 1551, 1552, 1553, 1977, 1555, 1556, -1, + 95, 1076, -1, -1, 8, -1, -1, 11, -1, -1, + -1, 15, -1, -1, 18, 19, 20, 1575, 1576, 1577, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 42, -1, -1, -1, -1, -1, -1, 49, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 1913, - 485, 486, 487, -1, 489, 490, 491, 492, 493, 494, - 1744, 2301, -1, -1, 74, -1, -1, 2307, -1, -1, + -1, -1, 8, -1, 1592, 11, -1, 2504, -1, 15, + -1, -1, 18, 19, 20, -1, -1, -1, -1, -1, + -1, -1, 147, -1, -1, -1, -1, -1, -1, 2504, + -1, -1, 2043, -1, 1056, -1, 161, -1, -1, -1, + 95, 166, -1, 2540, -1, -1, 171, -1, -1, -1, + 2061, 1506, -1, -1, -1, 180, -1, -1, -1, 184, + -1, 1516, -1, 1518, -1, 2540, 1521, -1, -1, -1, + -1, -1, 1527, -1, 1529, -1, -1, 2088, -1, -1, + -1, -1, -1, -1, 2095, -1, 1541, -1, -1, -1, + 215, 1546, 147, -1, -1, 1550, 1551, 1552, 1553, -1, + 1555, 1556, -1, -1, -1, -1, 161, 2118, -1, -1, + 235, 166, -1, 1218, 2611, -1, 171, -1, -1, -1, + -1, -1, -1, -1, -1, 180, 1056, -1, -1, 184, + -1, -1, -1, -1, -1, -1, 2611, -1, -1, -1, + -1, -1, 1730, -1, -1, -1, -1, -1, -1, 1737, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 284, + 215, -1, 287, 197, -1, -1, -1, -1, 293, -1, + -1, -1, -1, -1, -1, -1, 1009, -1, -1, -1, + 235, -1, -1, -1, -1, 219, 1774, -1, -1, -1, + -1, -1, -1, -1, -1, 1217, -1, -1, -1, -1, + -1, -1, 327, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 219, -1, -1, -1, -1, 1806, -1, + -1, 1243, 1244, -1, 1812, 350, -1, -1, -1, 284, + 2727, 2242, 287, -1, -1, -1, 1258, 1825, 293, -1, + 1828, -1, -1, -1, 1832, -1, -1, 1835, -1, 1837, + -1, -1, 2727, -1, -1, 289, -1, 8, -1, -1, + 11, -1, -1, -1, 15, -1, 2763, 18, 19, 20, + -1, -1, 327, -1, -1, 1730, -1, -1, -1, -1, + -1, 406, 1737, 289, 35, -1, -1, 1217, 2763, -1, + -1, -1, 2303, -1, -1, 350, -1, 2794, -1, -1, + 2797, -1, -1, 1891, -1, -1, -1, -1, 433, -1, + -1, -1, -1, 1243, 1244, -1, 441, -1, 1423, 2794, + -1, -1, 2797, -1, -1, -1, -1, -1, 1258, -1, + -1, -1, -1, 458, -1, 460, 461, -1, -1, 1444, + -1, 1446, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 406, -1, -1, -1, -1, -1, 8, 1380, -1, + 11, -1, 2373, -1, 15, -1, 1954, 18, 19, 20, + 1825, 1959, 497, -1, -1, 500, 501, 502, 433, 1967, + 1968, 1969, 1970, -1, 35, -1, 441, -1, -1, -1, + -1, 1496, 43, 1981, -1, -1, -1, -1, -1, 50, + -1, 1989, -1, 458, -1, 460, 461, -1, -1, -1, + -1, -1, -1, 2001, -1, -1, -1, -1, -1, 0, + -1, -1, -1, -1, 75, -1, -1, -1, -1, 2017, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 996, -1, -1, 999, 1000, - 2330, -1, 2332, 2333, 2334, 2335, -1, -1, -1, 2339, - 2340, -1, 2342, -1, -1, 2345, -1, -1, -1, 2349, - -1, -1, -1, 2353, -1, -1, -1, -1, 1982, 2359, + -1, -1, 497, 2031, 2032, 500, 501, 502, 8, -1, + 1380, 11, 486, 487, 488, 15, 490, 491, 492, 493, + 494, 495, 1295, -1, 1297, -1, 2054, -1, 219, -1, + 1575, 1576, -1, -1, -1, -1, -1, -1, -1, -1, + 486, 487, 488, 43, 490, 491, 492, 493, 494, 495, + 50, -1, 1514, 2504, -1, -1, -1, -1, -1, -1, + -1, -1, 2999, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 95, 75, -1, -1, -1, -1, + -1, -1, -1, -1, 2999, 176, 1981, -1, -1, 2540, + -1, -1, -1, -1, -1, -1, -1, -1, 289, -1, + -1, 192, -1, -1, -1, -1, 197, -1, -1, -1, + -1, -1, 2140, 2141, 2142, 2143, -1, 2145, 2146, 2147, + -1, -1, -1, -1, 2152, 2153, 147, -1, 219, 220, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 144, 2375, 2000, -1, -1, 2379, - -1, -1, -1, -1, 2384, -1, -1, -1, -1, -1, - 2390, -1, -1, -1, -1, -1, 2396, -1, -1, -1, - -1, -1, 2402, 2027, -1, 175, -1, -1, -1, -1, - 2034, -1, -1, -1, -1, 2415, 2416, -1, -1, -1, - -1, 191, -1, 2423, -1, -1, 196, 1276, -1, -1, - -1, -1, -1, -1, 2058, -1, -1, 1286, -1, 1288, - 2440, -1, 1291, 1292, 1293, 1294, -1, -1, -1, -1, - 1894, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1904, 1905, 1906, 233, -1, -1, -1, 1316, -1, -1, - -1, -1, 1913, 1322, 1323, 1324, 1325, 1326, 1327, -1, - -1, 1925, -1, 1332, 1333, -1, -1, -1, 1337, -1, - -1, -1, 1341, -1, -1, 1344, 1345, 1346, 1347, 1348, - 1349, 1350, 1351, 1352, -1, -1, 1355, -1, -1, 1180, - 2510, 1955, -1, 1362, 1913, -1, 1365, -1, 288, 1913, - 1191, 2521, 1193, -1, -1, -1, -1, -1, -1, -1, - -1, 1202, -1, 2533, -1, -1, -1, -1, 1387, -1, - -1, 1982, -1, -1, -1, -1, -1, -1, 1219, -1, - -1, -1, -1, -1, -1, -1, -1, 2181, -1, 2000, - 1913, -1, -1, -1, -1, -1, -1, -1, -1, 2569, - 1419, 1420, -1, -1, -1, -1, 1247, 1248, 2578, 2579, - -1, -1, 2582, 1982, -1, 2585, 2027, 2587, 1982, -1, - -1, -1, 2592, 2034, -1, 2595, -1, 2597, -1, -1, - 2600, 2000, -1, -1, -1, -1, 2000, -1, 1279, 1280, - 380, -1, 1283, 1284, 2614, -1, -1, 2058, -1, -1, - -1, 2245, -1, -1, -1, -1, -1, -1, 2027, 1982, - -1, -1, -1, 2027, -1, 2034, 2080, 2081, 2082, -1, - 2034, -1, -1, -1, -1, 2645, -1, 2000, -1, 1498, - -1, -1, 1501, 1502, -1, 1504, -1, -1, 22, 2058, - -1, -1, -1, -1, 2058, 2665, 2666, -1, -1, -1, - -1, -1, -1, -1, 2027, -1, 2676, -1, 2678, -1, - -1, 2034, 2682, -1, -1, -1, 1535, -1, -1, -1, - -1, -1, -1, 2317, 2694, 2139, -1, 2697, -1, -1, - -1, -1, -1, -1, -1, 2058, -1, -1, -1, -1, - -1, 75, 482, -1, -1, -1, 2716, -1, -1, 489, - 490, 491, 492, 493, 494, -1, -1, 91, -1, 2729, - -1, -1, -1, -1, 2734, -1, -1, -1, -1, -1, - 2181, -1, -1, -1, -1, -1, -1, -1, 1419, 1420, - 1599, -1, 2752, -1, -1, -1, 2756, 1606, 2758, -1, - -1, -1, 1611, -1, -1, -1, -1, 2767, -1, 2213, + 161, -1, -1, 234, 1514, 166, -1, -1, -1, -1, + 171, -1, -1, -1, 2182, 1617, -1, -1, -1, 180, + 2611, -1, -1, 184, -1, -1, -1, -1, -1, -1, + -1, -1, 2200, -1, 2202, -1, 176, -1, 2206, 2207, + 2208, 272, 2210, -1, 275, -1, -1, -1, -1, -1, + -1, -1, 192, -1, 215, -1, 1658, 197, 289, -1, + -1, 2229, -1, 2231, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 235, -1, 2244, 2245, 2246, 2247, + 2248, 2249, 2250, 2251, 2252, 2253, -1, -1, -1, -1, + -1, -1, -1, 1506, 234, -1, -1, -1, -1, -1, + -1, 2269, -1, 1516, -1, 1518, 2274, 1617, 1521, -1, + -1, -1, -1, 2281, 1527, -1, 1529, -1, -1, -1, + -1, 1806, -1, 284, -1, -1, 287, 2295, 1541, -1, + -1, -1, 293, 1546, -1, -1, 2727, 1550, 1551, 1552, + 1553, -1, 1555, 1556, -1, 2313, -1, -1, 1658, 289, + 381, -1, -1, -1, -1, 486, 487, 488, -1, 490, + 491, 492, 493, 494, 495, -1, 327, 2202, -1, -1, + -1, -1, 2763, -1, 599, 600, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 350, + -1, -1, -1, -1, 2229, 2363, -1, -1, -1, -1, + -1, -1, -1, 2794, -1, -1, 2797, -1, -1, 2244, + 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2387, + -1, 2389, 2390, 2391, 2392, -1, -1, -1, 2396, 2397, + -1, 2399, 2400, -1, -1, 2403, 661, 662, -1, -1, + 2408, 381, -1, -1, 2412, 406, -1, -1, -1, -1, + 2418, -1, 483, -1, -1, 486, 487, 488, -1, 490, + 491, 492, 493, 494, 495, -1, 2434, -1, -1, -1, + 2438, -1, 433, -1, 1959, 2443, -1, -1, -1, -1, + 441, 2449, -1, 1968, 1969, 1970, -1, 2455, -1, -1, + -1, -1, -1, 2461, -1, -1, -1, 458, -1, 460, + 461, -1, -1, -1, 1989, -1, 2474, 2475, -1, -1, + -1, -1, -1, -1, 2482, -1, -1, -1, -1, -1, + -1, -1, -1, 8, -1, -1, 11, -1, -1, -1, + 15, 2499, -1, -1, -1, -1, 497, -1, -1, 500, + 501, 502, -1, 483, -1, -1, -1, -1, -1, -1, + 490, 491, 492, 493, 494, 495, -1, -1, 43, -1, + -1, -1, -1, -1, -1, 50, -1, -1, 2403, -1, + -1, -1, -1, -1, -1, 1977, -1, -1, -1, -1, + -1, -1, -1, 2418, -1, -1, -1, -1, -1, -1, + 75, 8, -1, -1, 11, -1, -1, -1, 15, -1, + -1, -1, -1, -1, -1, -1, -1, 2575, 2999, -1, + -1, -1, 1825, -1, -1, -1, 2584, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 43, -1, 2596, -1, + -1, -1, -1, 50, -1, -1, -1, -1, -1, -1, + 2475, 2043, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 876, -1, -1, -1, 2140, 2141, 2142, 75, 2061, + 145, -1, -1, -1, 2632, -1, -1, 1977, 893, -1, + -1, -1, -1, 2641, 2642, -1, 2644, -1, -1, 2647, + -1, -1, 2650, -1, -1, -1, 2088, 2655, -1, -1, + 2658, 176, 2660, 2095, -1, 2663, -1, 922, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 192, -1, 2677, + -1, -1, 197, -1, -1, 2200, 2118, 942, 943, 944, + -1, -1, 947, -1, -1, -1, -1, -1, 145, -1, + -1, -1, -1, 2043, -1, -1, -1, -1, -1, -1, + 2708, -1, -1, -1, -1, 970, -1, -1, -1, 234, + -1, 2061, -1, -1, -1, -1, -1, -1, -1, 176, + 2728, 2729, -1, -1, -1, -1, -1, -1, 1981, -1, + -1, 2739, -1, 2741, -1, 192, 2744, -1, 2088, -1, + 197, -1, -1, -1, -1, 2095, -1, -1, 2756, 2274, + -1, 2759, -1, -1, -1, -1, -1, -1, 1023, -1, + -1, -1, 1027, 1028, 289, -1, -1, -1, 2118, 2777, + -1, -1, 2647, -1, -1, -1, -1, 234, -1, -1, + -1, -1, 2790, -1, -1, 2660, -1, 2795, 2663, -1, + -1, -1, -1, -1, -1, 8, -1, -1, 11, -1, + 2242, -1, 15, -1, -1, 2813, -1, -1, -1, 2817, + -1, 2819, -1, -1, -1, -1, 1081, -1, -1, -1, + 2828, -1, -1, -1, -1, -1, -1, 1092, -1, -1, + 43, -1, 289, 2708, -1, -1, 2844, 50, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 145, 2181, 2783, -1, -1, -1, 2181, -1, -1, - -1, 155, -1, -1, -1, -1, -1, 2797, -1, -1, - 1471, 1650, -1, 167, 2245, 2249, -1, -1, 172, -1, - 1481, -1, 1661, 1484, 1663, 1664, -1, -1, -1, -1, - -1, 2445, 1671, -1, -1, 2825, 1675, -1, 2181, 1678, - -1, -1, -1, -1, 2834, 199, -1, -1, 2838, -1, - -1, -1, 2842, -1, -1, -1, 2245, -1, -1, -1, - -1, 2245, 2476, -1, -1, -1, -1, -1, -1, -1, - -1, 2861, 2862, 2863, 2864, 1714, -1, -1, 1717, -1, - 1719, -1, -1, -1, -1, -1, 2317, -1, -1, -1, - 244, -1, -1, -1, 248, -1, 1557, 1558, 2332, 2333, - 2334, 2335, 2245, 2893, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 2908, -1, - -1, -1, -1, 1584, -1, -1, -1, -1, 2317, -1, - 2920, -1, -1, 2317, -1, 2549, 1597, -1, -1, -1, - -1, -1, -1, -1, 2934, 1784, -1, 8, -1, -1, - 11, -1, -1, -1, -1, 16, -1, 311, -1, -1, - 1799, 1800, -1, -1, 2954, 8, -1, -1, 11, -1, - 2960, 325, -1, 16, 2317, -1, -1, -1, -1, 1818, - -1, 42, -1, -1, -1, -1, 2976, 2977, 49, 2423, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, - -1, -1, -1, -1, 358, -1, 49, 361, -1, -1, - -1, -1, -1, 74, 2445, 369, -1, -1, 372, -1, + 2858, 1116, -1, 2728, 2729, -1, 381, -1, -1, -1, + -1, 2303, 75, -1, 2389, 2390, 2391, 2392, -1, 2744, + -1, -1, -1, -1, -1, -1, -1, -1, 2886, -1, + -1, -1, -1, -1, -1, -1, -1, 2895, -1, -1, + -1, 2899, 2242, -1, -1, 2903, 8, -1, -1, 11, + -1, -1, 2777, 15, -1, -1, 18, 19, 20, -1, + -1, -1, -1, -1, 2922, 2923, 2924, 2925, -1, -1, + 2795, -1, -1, 35, 381, -1, -1, -1, -1, -1, + -1, 2373, 145, -1, -1, -1, -1, -1, -1, -1, + 8, -1, -1, 11, 2819, -1, 2954, 15, -1, 2202, + 18, 19, 20, 2303, -1, -1, -1, 2482, 483, -1, + -1, 2969, -1, 176, -1, 490, 491, 492, 493, 494, + 495, -1, -1, 2981, -1, -1, 2229, -1, 868, 192, + -1, -1, -1, -1, 197, 875, -1, 2995, -1, -1, + -1, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, + 2253, -1, -1, -1, -1, -1, -1, 3015, -1, -1, + -1, 8, -1, 3021, 11, -1, -1, -1, 15, -1, + -1, 234, -1, 2373, 2899, -1, 483, -1, 2903, 3037, + 3038, -1, -1, 490, 491, 492, 493, 494, 495, -1, + -1, -1, -1, -1, -1, -1, 43, 8, -1, -1, + 11, -1, -1, 50, 15, -1, -1, 18, 19, 20, + -1, -1, 2504, -1, -1, -1, -1, -1, -1, -1, + -1, 1336, 962, -1, 35, -1, 289, -1, 75, -1, + -1, 1346, -1, 1348, -1, -1, 1351, 1352, 1353, 1354, + -1, -1, -1, -1, 2969, -1, -1, 987, 2540, 989, + 990, -1, -1, -1, -1, -1, -1, 219, -1, -1, + 1375, -1, -1, -1, -1, -1, 1381, 1382, 1383, 1384, + 1385, 1386, 1387, -1, -1, -1, -1, 1392, 1393, -1, + 8, -1, 1397, 11, -1, -1, 1401, 15, -1, 1404, + 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 145, -1, + 1415, 219, -1, -1, 2504, -1, -1, 1422, -1, -1, + 1425, -1, -1, -1, -1, 43, -1, 1057, 381, 2611, + 1060, 1061, 50, -1, -1, -1, -1, 289, -1, 176, + -1, -1, 1447, -1, -1, -1, -1, -1, -1, -1, + 2540, -1, -1, -1, -1, 192, -1, 75, -1, -1, + 197, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 2739, -1, -1, 1482, 1483, -1, + -1, 289, 2475, 8, -1, -1, 11, -1, -1, -1, + 15, 2756, -1, 18, 19, 20, -1, 234, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 74, -1, -1, -1, -1, -1, 391, 1877, -1, - -1, -1, -1, -1, -1, 2476, -1, -1, -1, -1, - 2664, 405, -1, -1, -1, -1, 2445, -1, 412, -1, - -1, 2445, -1, -1, -1, -1, -1, 421, -1, -1, - -1, -1, -1, 427, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 144, 1923, -1, -1, 2476, 2702, -1, - -1, -1, 2476, -1, 1755, -1, -1, -1, 452, -1, - -1, 144, 2445, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 175, -1, -1, -1, 2549, 2733, - -1, -1, 2736, -1, -1, -1, -1, -1, 1789, 1790, - 191, -1, 175, 2476, -1, 196, -1, -1, -1, -1, - 1979, -1, -1, -1, -1, -1, 902, -1, 191, 1988, - -1, -1, 1991, 196, -1, 1994, -1, -1, -1, -1, - 2549, -1, -1, -1, -1, 2549, -1, -1, -1, -1, - -1, -1, 233, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 2021, 2022, -1, -1, 2025, 943, -1, -1, - 233, -1, -1, -1, -1, -1, -1, -1, 2037, -1, - -1, -1, -1, -1, -1, -1, 2549, 2046, -1, -1, - 2049, -1, 2051, -1, -1, 8, -1, -1, 11, -1, - 2059, -1, -1, 16, 17, 18, 19, 288, 2067, 2068, - -1, 0, -1, 2664, -1, -1, -1, -1, -1, -1, - -1, -1, 2676, -1, -1, 288, -1, -1, -1, 42, - -1, 20, -1, -1, -1, -1, 49, -1, 2097, -1, - 2694, 30, -1, 32, 33, -1, -1, -1, 2107, -1, - 1931, 2702, -1, -1, -1, 2664, -1, -1, -1, 48, - 2664, 74, -1, -1, 2123, -1, -1, -1, 57, -1, - -1, -1, -1, -1, -1, -1, -1, 1053, -1, -1, - 69, -1, 2733, -1, 1060, 2736, -1, -1, -1, -1, - -1, 80, -1, 2702, -1, -1, -1, -1, 2702, 380, - -1, 2664, -1, 92, 2938, 94, -1, -1, -1, -1, - -1, -1, -1, 2767, -1, -1, -1, 380, -1, -1, - -1, -1, -1, 112, 2733, -1, -1, 2736, -1, 2733, - -1, -1, 2736, -1, -1, -1, -1, 126, -1, 2702, - -1, -1, -1, 2797, -1, -1, -1, 136, -1, -1, - -1, -1, -1, 142, -1, -1, -1, -1, -1, -1, - -1, 150, 175, 152, 153, -1, -1, -1, -1, -1, - 2733, -1, -1, 2736, -1, 37, -1, 166, 191, -1, - -1, -1, -1, 196, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 56, -1, -1, -1, -1, -1, - -1, 482, -1, 2262, -1, -1, 195, -1, 489, 490, - 491, 492, 493, 494, -1, -1, -1, -1, -1, 482, - 233, 210, -1, -1, -1, -1, 489, 490, 491, 492, - 493, 494, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 107, 108, 236, -1, -1, - -1, -1, 2311, 2312, 116, -1, -1, 2316, -1, -1, - -1, -1, 2321, -1, -1, 2324, 2325, -1, -1, -1, - 2329, -1, -1, -1, -1, 288, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 2938, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 1274, -1, - 2181, -1, -1, -1, -1, -1, -1, -1, -1, 1285, - -1, -1, 174, 1289, -1, -1, 2375, -1, -1, 1295, - 1296, 1297, -1, -1, 313, -1, -1, 316, 1304, 2938, - -1, -1, -1, -1, 2938, -1, 198, -1, -1, -1, + 35, -1, -1, -1, -1, -1, -1, -1, 219, -1, + -1, 2611, -1, -1, -1, -1, -1, 145, -1, -1, + 483, -1, -1, -1, -1, -1, -1, 490, 491, 492, + 493, 494, 495, -1, -1, 2727, -1, -1, -1, -1, + -1, -1, 289, -1, -1, -1, 1561, -1, 176, 1564, + 1565, -1, 1567, 2828, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 192, -1, -1, -1, -1, 197, + -1, 2763, 3, -1, 5, -1, -1, -1, 289, -1, + -1, 1596, -1, 2858, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 2409, -1, -1, -1, -1, -1, 345, -1, -1, -1, - -1, -1, -1, 8, -1, 354, 11, 380, -1, -1, - 15, 16, 17, 18, 19, 2938, -1, 2436, -1, 368, - -1, -1, -1, -1, -1, 1361, 375, 249, -1, 34, - 379, -1, -1, -1, -1, 257, -1, 42, -1, -1, - 389, -1, -1, -1, 49, -1, -1, 269, -1, 271, - -1, -1, 401, -1, -1, -1, 405, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 1404, 74, - -1, -1, -1, -1, -1, -1, -1, -1, 300, -1, - -1, -1, 1418, -1, -1, -1, -1, 1423, -1, -1, - -1, -1, 441, -1, -1, -1, -1, 446, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 482, - -1, 460, 485, 486, 487, -1, 489, 490, 491, 492, - 493, 494, -1, -1, -1, 347, -1, -1, -1, -1, - -1, -1, -1, 2552, -1, 484, -1, -1, -1, -1, - -1, -1, 2561, 2562, -1, -1, 2565, 369, -1, 498, - -1, -1, 501, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 389, -1, 391, - 175, -1, 394, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 2602, 2603, -1, 191, -1, -1, -1, - -1, 196, -1, 2434, -1, -1, -1, 2616, 2439, -1, + -1, 1241, 2794, -1, -1, 2797, 234, -1, -1, -1, + -1, -1, 1252, -1, 1254, -1, -1, -1, -1, -1, + -1, -1, -1, 1263, 486, 487, 488, 2727, 490, 491, + 492, 493, 494, 495, 381, -1, -1, -1, -1, -1, + 1280, 1656, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 1667, -1, -1, -1, -1, 1672, -1, -1, + -1, 289, -1, 2763, -1, -1, 1306, 1307, 486, 487, + 488, -1, 490, 491, 492, 493, 494, 495, -1, -1, + 111, 112, -1, -1, 219, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 2794, -1, 1711, 2797, -1, 1339, + 1340, -1, -1, 1343, 1344, 2708, -1, 1722, -1, 1724, + 1725, -1, -1, -1, -1, -1, -1, 1732, -1, -1, + -1, 1736, -1, -1, 1739, 2728, 2729, -1, 963, -1, + -1, -1, -1, -1, -1, -1, 483, -1, 111, 112, + -1, 2744, -1, 490, 491, 492, 493, 494, 495, -1, + -1, -1, -1, 381, 289, -1, 187, 188, -1, -1, + -1, 1776, -1, -1, 1779, -1, 1781, -1, -1, 1004, + -1, -1, -1, -1, -1, 486, 487, 488, 0, 490, + 491, 492, 493, 494, 495, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, + -1, -1, -1, -1, -1, -1, -1, 2999, -1, 31, + -1, 33, 34, -1, 187, 188, 2819, -1, -1, -1, + -1, 252, 253, 254, 255, 256, 257, 49, -1, 260, + 261, -1, 1847, -1, 8, -1, 58, 11, -1, -1, + -1, 15, 1482, 1483, 18, 19, 20, -1, 70, 1864, + 1865, -1, -1, -1, -1, 483, -1, -1, -1, 81, + -1, 35, 490, 491, 492, 493, 494, 495, 1883, 43, + -1, 93, -1, 95, -1, -1, 50, -1, -1, 252, + 253, 254, 255, 256, 257, 1120, -1, 260, 261, -1, + -1, 113, 1127, -1, 1534, -1, -1, -1, -1, 2999, + -1, 75, -1, -1, 1544, 127, -1, 1547, -1, -1, + -1, -1, -1, -1, -1, 137, -1, -1, -1, -1, + -1, 143, -1, -1, -1, -1, -1, 1942, -1, 151, + -1, 153, 154, -1, -1, 366, 367, -1, -1, -1, + -1, -1, -1, -1, -1, 167, -1, -1, -1, -1, + -1, 486, 487, 488, -1, 490, 491, 492, 493, 494, + 495, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 1987, -1, 196, -1, -1, -1, 1618, 1619, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 211, + -1, -1, -1, 366, 367, -1, -1, -1, -1, -1, + -1, 1641, 176, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 1654, 237, -1, -1, 192, -1, + -1, -1, 25, 197, -1, 2040, -1, -1, 31, -1, + -1, -1, -1, -1, 2049, 38, -1, 2052, -1, -1, + 2055, -1, -1, -1, -1, 219, 220, -1, 479, 480, + -1, -1, -1, -1, 57, -1, -1, -1, -1, -1, + 234, -1, -1, -1, -1, -1, -1, 2082, 2083, -1, + -1, 2086, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 2097, -1, -1, -1, -1, -1, -1, -1, + -1, 2106, 314, -1, 2109, 317, 2111, -1, 272, 1334, + -1, 275, -1, -1, 2119, 108, 479, 480, -1, -1, + 1345, -1, 2127, 2128, 1349, 289, 2131, -1, 292, -1, + 1355, 1356, 1357, -1, 346, -1, 499, -1, -1, 1364, + -1, -1, -1, 355, 137, -1, -1, -1, -1, -1, + 111, 112, -1, 2158, -1, -1, -1, 369, -1, -1, + -1, -1, -1, 2168, 376, -1, -1, -1, 380, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 390, 2184, + -1, -1, -1, -1, -1, -1, -1, 1817, -1, -1, + 402, -1, -1, -1, 406, -1, 1421, -1, -1, -1, + -1, -1, 8, -1, -1, 11, 199, -1, -1, 15, + 16, 17, 18, 19, 20, -1, -1, 381, -1, -1, + -1, -1, -1, -1, 1854, 1855, 187, 188, -1, 35, + 442, -1, -1, -1, -1, 447, -1, 43, -1, -1, + 1465, -1, -1, -1, 50, -1, -1, -1, 23, 461, + -1, -1, -1, -1, -1, -1, 1481, 250, -1, -1, + -1, 1486, -1, -1, -1, 258, -1, -1, -1, 75, + -1, -1, -1, 485, -1, -1, -1, 270, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 499, -1, -1, + 502, 252, 253, 254, 255, 256, 257, -1, 291, 260, + 261, 76, -1, -1, -1, -1, -1, -1, 301, -1, + -1, -1, -1, -1, 2319, -1, -1, 92, -1, 483, + -1, -1, 486, 487, 488, -1, 490, 491, 492, 493, + 494, 495, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 342, + -1, -1, -1, 346, -1, 348, -1, -1, -1, -1, + -1, -1, 2367, 2368, -1, 1995, -1, 2372, -1, -1, + 176, 146, 2377, -1, -1, 2380, 2381, 370, -1, -1, + 2385, 156, -1, 376, -1, -1, 192, -1, -1, -1, + -1, 197, -1, 168, -1, -1, -1, 390, 173, -1, + -1, -1, -1, -1, -1, 366, 367, -1, -1, -1, + -1, -1, -1, 219, 220, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 200, -1, -1, 234, 2434, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 218, 219, 2634, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 233, -1, - -1, 3, -1, -1, -1, -1, 8, -1, -1, 11, - -1, 2482, 2483, 15, 16, 17, 18, 19, -1, -1, + -1, 3, -1, -1, -1, 1670, 8, -1, -1, 11, + -1, 444, -1, 15, 16, 17, 18, 19, 20, -1, + -1, -1, -1, 2468, 1689, -1, 272, -1, -1, 275, + 245, -1, -1, 35, 249, -1, 38, -1, -1, -1, + -1, 43, 1707, 289, 1709, 1710, 292, 1712, 50, 1714, + 2495, -1, -1, 1718, -1, -1, 1721, -1, -1, -1, + -1, 1726, -1, -1, 1729, -1, -1, -1, -1, -1, + -1, -1, -1, 75, -1, -1, 1741, -1, 479, 480, + 1745, 1746, 1747, 1748, 1749, 1750, 1751, -1, -1, -1, + -1, -1, 1757, 1758, -1, 1760, 1761, 312, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 1772, -1, -1, + 1775, 326, -1, -1, -1, -1, -1, -1, 1783, 1784, + 1785, 1786, 1787, 1788, 1789, 1790, 1791, 1792, -1, -1, + -1, -1, -1, -1, -1, 381, -1, -1, -1, -1, + -1, -1, -1, -1, 359, -1, -1, 362, -1, -1, + -1, -1, -1, -1, -1, 370, -1, -1, 373, 1824, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 2614, + -1, -1, 2242, -1, 176, -1, -1, 392, 2623, 2624, + -1, -1, 2627, -1, -1, -1, -1, -1, -1, -1, + 192, 406, -1, -1, -1, 197, -1, -1, 413, -1, + -1, -1, -1, -1, -1, -1, -1, 422, -1, -1, + -1, -1, -1, 428, -1, -1, -1, 219, 220, -1, + 2665, 2666, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 234, -1, 2679, -1, -1, 483, 453, -1, + 486, 487, 488, -1, 490, 491, 492, 493, 494, 495, + -1, -1, 2697, -1, -1, -1, -1, 503, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 34, -1, -1, 37, 271, -1, -1, 274, - 42, -1, -1, 1609, -1, -1, 498, 49, -1, -1, - -1, -1, -1, 288, -1, -1, 291, -1, -1, -1, - -1, -1, 1628, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 74, -1, -1, -1, 2725, -1, -1, -1, - 1646, -1, 1648, 1649, -1, 1651, -1, 1653, -1, -1, - -1, 1657, -1, 2742, 1660, -1, -1, -1, -1, 1665, - -1, -1, 1668, -1, -1, -1, -1, 2756, -1, -1, - 2759, -1, -1, -1, 1680, -1, -1, -1, 1684, 1685, - 1686, 1687, 1688, 1689, -1, 2774, -1, -1, -1, 1695, - 1696, -1, 1698, 1699, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8, 1710, 380, 11, 1713, -1, -1, - 15, 16, 17, 18, 19, 1721, 1722, 1723, 1724, 1725, - 1726, 1727, 1728, 1729, 1730, -1, -1, -1, -1, 34, - -1, -1, 37, 175, -1, -1, -1, 42, -1, -1, - -1, -1, 2653, 2654, 49, -1, -1, -1, -1, 191, - -1, -1, -1, 2664, 196, -1, 1762, -1, -1, -1, - -1, 2850, -1, -1, -1, 2854, -1, -1, -1, 74, - -1, -1, -1, -1, -1, -1, 218, 219, -1, -1, + 272, -1, -1, 275, -1, -1, -1, -1, -1, -1, + -1, -1, 1947, 1948, 1949, -1, -1, 289, -1, -1, + 292, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 233, -1, -1, -1, 2884, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 482, -1, -1, - 485, 486, 487, -1, 489, 490, 491, 492, 493, 494, - -1, -1, -1, -1, -1, -1, -1, 502, 2917, 271, - -1, -1, 274, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 288, -1, -1, 291, - -1, 8, -1, -1, 11, -1, -1, -1, -1, 16, - 17, 18, 19, -1, -1, -1, -1, -1, -1, -1, - 175, -1, -1, -1, 2963, 2964, 1882, 1883, 1884, -1, - -1, -1, -1, -1, -1, 42, 191, -1, -1, -1, - -1, 196, 49, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 2996, -1, -1, - -1, -1, -1, 218, 219, -1, -1, 74, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 233, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 380, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 3037, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 271, -1, -1, 274, - -1, -1, 1978, -1, -1, -1, -1, -1, 1984, -1, - -1, -1, -1, 288, -1, -1, 291, -1, -1, -1, - -1, 1997, 1998, 1999, -1, 2001, 2002, 2003, 2004, 2005, - -1, -1, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, - 2016, 2017, 2018, -1, -1, -1, -1, -1, 175, -1, - -1, -1, -1, -1, -1, -1, -1, 2938, -1, -1, - -1, -1, 2038, -1, 191, 2041, -1, 2043, -1, 196, - 482, 2047, 2048, 485, 486, 487, -1, 489, 490, 491, - 492, 493, 494, -1, -1, 2061, 2062, 2063, 2064, -1, - 2066, 218, 219, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 380, 233, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 8, -1, -1, 11, -1, + -1, 2786, 15, 16, 17, 18, 19, 20, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 2803, -1, + -1, -1, 35, -1, -1, 38, -1, -1, -1, -1, + 43, -1, 2817, -1, 2039, 2820, -1, 50, -1, 381, + 2045, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 2835, -1, -1, 2058, 2059, 2060, -1, 2062, 2063, 2064, + 2065, 2066, 75, -1, 2069, 2070, 2071, 2072, 2073, 2074, + 2075, 2076, 2077, 2078, 2079, -1, -1, -1, -1, -1, + -1, -1, -1, 2493, -1, -1, -1, -1, 2498, -1, + -1, -1, -1, 2098, -1, -1, 2101, -1, 2103, -1, + -1, -1, 2107, 2108, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 2121, 2122, 2123, 2124, + -1, 2126, -1, -1, -1, -1, 2911, -1, -1, -1, + 2915, -1, -1, -1, -1, -1, -1, 2547, 2548, -1, + -1, 483, -1, -1, 486, 487, 488, -1, 490, 491, + 492, 493, 494, 495, -1, -1, -1, -1, -1, -1, + 2945, -1, -1, 176, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 8, 192, + -1, 11, -1, -1, 197, 15, 16, 17, 18, 19, + 20, -1, -1, 2978, -1, -1, -1, -1, 2203, -1, + -1, -1, -1, -1, -1, 35, 219, 220, -1, -1, + -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, + 50, 234, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 3024, + 3025, -1, -1, 8, -1, 75, 11, -1, -1, -1, + 15, 16, 17, 18, 19, 20, -1, -1, -1, 272, + -1, -1, 275, -1, -1, -1, -1, -1, -1, -1, + 35, -1, 3057, -1, -1, -1, 289, -1, 43, 292, + -1, -1, -1, -1, -1, 50, -1, -1, -1, 2294, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 2716, 2717, -1, -1, + 75, -1, -1, 3098, -1, 2320, -1, 2727, -1, 2324, + 2325, -1, 2327, -1, -1, 2330, 2331, 2332, 2333, 2334, + -1, -1, -1, 2338, 2339, 2340, 2341, 2342, 2343, 2344, + 2345, 2346, 2347, 2348, 2349, -1, 176, -1, -1, -1, + -1, -1, -1, -1, 2359, -1, -1, -1, -1, -1, + -1, 2366, 192, -1, 2369, -1, 2371, 197, 381, -1, + 2375, -1, -1, 2378, 2379, -1, -1, 2382, 2383, -1, + -1, 2386, -1, -1, -1, -1, -1, -1, -1, 219, + 220, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 234, -1, -1, -1, -1, -1, + -1, 176, -1, -1, -1, -1, -1, -1, -1, -1, + 2425, -1, -1, -1, -1, -1, 8, 192, 2433, 11, + -1, -1, 197, 15, 16, 17, 18, 19, 20, -1, + -1, 2446, 272, -1, -1, 275, -1, -1, -1, -1, + -1, -1, -1, 35, 219, 220, -1, -1, -1, 289, + -1, 43, 292, -1, -1, -1, -1, -1, 50, 234, + 483, 2476, -1, 486, 487, 488, -1, 490, 491, 492, + 493, 494, 495, -1, -1, -1, -1, 500, -1, -1, + -1, -1, -1, 75, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 272, 8, -1, + 275, 11, -1, -1, -1, 15, 16, 17, 18, 19, + 20, -1, -1, -1, 289, -1, -1, 292, -1, -1, + -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, + -1, -1, -1, 43, -1, -1, -1, -1, -1, -1, + 50, 381, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 271, -1, -1, 274, -1, -1, + -1, -1, -1, -1, -1, 75, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 2999, + -1, -1, -1, -1, 176, -1, -1, -1, -1, 2604, + -1, -1, -1, 2608, -1, -1, -1, -1, -1, -1, + 192, -1, 2617, 2618, 2619, 197, 381, 2622, -1, -1, + 2625, 2626, -1, -1, -1, 2630, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 219, 220, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 288, -1, -1, -1, -1, 2142, -1, -1, -1, + -1, -1, 234, 483, -1, -1, 486, 487, 488, -1, + 490, 491, 492, 493, 494, 495, -1, -1, -1, -1, + 500, -1, -1, -1, -1, -1, 176, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 2694, + 272, -1, 192, 275, -1, 2700, -1, 197, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 289, 2713, -1, + 292, -1, -1, -1, -1, -1, -1, -1, 483, 219, + 220, 486, 487, 488, -1, 490, 491, 492, 493, 494, + 495, -1, -1, -1, 234, 500, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 2761, 2762, -1, -1, + -1, -1, 2767, 2768, 2769, -1, -1, -1, -1, -1, + -1, -1, 272, -1, -1, 275, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 289, + -1, -1, 292, -1, -1, -1, -1, -1, -1, 381, + -1, -1, -1, -1, -1, -1, 2811, 2812, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 2826, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 2836, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 482, -1, -1, - 485, 486, 487, -1, 489, 490, 491, 492, 493, 494, - -1, -1, 8, -1, 499, 11, -1, -1, -1, 15, - 16, 17, 18, 19, -1, -1, -1, 8, -1, -1, - 11, -1, -1, -1, -1, 16, -1, -1, 34, -1, - -1, -1, -1, 380, -1, -1, 42, -1, -1, -1, - 2236, -1, -1, 49, -1, -1, -1, -1, -1, -1, - -1, 42, -1, -1, -1, -1, -1, -1, 49, -1, - -1, -1, -1, -1, -1, -1, -1, 2263, 74, -1, - -1, 2267, 2268, -1, 2270, -1, -1, 2273, 2274, 2275, - 2276, 2277, -1, 74, -1, 2281, 2282, 2283, 2284, 2285, - 2286, 2287, 2288, 2289, 2290, 2291, 2292, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 2303, -1, -1, - -1, -1, -1, -1, 2310, -1, -1, 2313, -1, 2315, - -1, -1, -1, 2319, -1, -1, 2322, 2323, -1, -1, - 2326, 2327, -1, -1, -1, 482, -1, -1, 485, 486, - 487, -1, 489, 490, 491, 492, 493, 494, -1, -1, - -1, -1, 8, 144, -1, 11, -1, -1, -1, -1, - 16, 17, 18, 19, -1, 8, -1, -1, 11, 175, - 2366, -1, -1, 16, -1, -1, -1, -1, 2374, -1, - -1, -1, -1, -1, 175, 191, 42, -1, -1, -1, - 196, 2387, -1, 49, -1, -1, -1, -1, -1, 42, - 191, -1, -1, -1, -1, 196, 49, -1, -1, -1, - -1, -1, 218, 219, -1, -1, -1, -1, 74, -1, - -1, 2417, -1, -1, -1, -1, 8, 233, -1, 11, - -1, 74, -1, 15, 16, 17, 18, 19, -1, -1, - -1, -1, 233, -1, -1, -1, 8, -1, -1, 11, - -1, -1, 34, -1, 16, -1, -1, -1, -1, -1, - 42, -1, -1, -1, -1, 271, -1, 49, 274, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 42, -1, 288, -1, -1, 291, -1, 49, -1, -1, - -1, -1, 74, -1, -1, -1, -1, 288, -1, -1, - -1, 144, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 74, -1, -1, -1, -1, -1, -1, 175, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 175, -1, -1, 191, -1, -1, -1, -1, - 196, 24, -1, -1, -1, -1, 2542, 30, 191, -1, - 2546, -1, -1, 196, 37, -1, -1, -1, -1, 2555, - 2556, 2557, 218, 219, 2560, -1, -1, 2563, 2564, -1, - -1, -1, 2568, 56, 380, -1, -1, 233, -1, -1, - -1, -1, 144, -1, -1, -1, -1, -1, -1, 380, - 233, -1, -1, 175, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 191, - -1, -1, -1, 175, 196, -1, -1, -1, 274, -1, - -1, -1, -1, -1, 107, -1, -1, -1, -1, 191, - -1, -1, 288, -1, 196, 2631, 218, 219, -1, -1, - -1, 2637, -1, -1, -1, 288, -1, -1, -1, -1, - -1, 233, -1, 136, 2650, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 2880, -1, -1, -1, -1, + -1, 381, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 2898, -1, -1, -1, -1, -1, -1, + -1, 483, -1, -1, 486, 487, 488, -1, 490, 491, + 492, 493, 494, 495, -1, 2920, -1, -1, 500, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 233, -1, -1, -1, -1, 482, -1, -1, 485, - 486, 487, -1, 489, 490, 491, 492, 493, 494, 271, - -1, 482, 274, 499, -1, -1, -1, -1, 489, 490, - 491, 492, 493, 494, 2700, 2701, 288, -1, -1, 291, - 2706, 2707, 2708, -1, -1, 198, -1, -1, -1, -1, - -1, -1, -1, -1, 380, -1, 288, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 380, -1, -1, + -1, -1, -1, -1, 2939, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 2750, 2751, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 249, -1, -1, 2765, - -1, -1, -1, -1, 257, -1, -1, -1, -1, 2775, - -1, -1, -1, -1, -1, -1, 269, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 380, -1, - -1, -1, -1, -1, -1, -1, -1, 290, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 300, 380, -1, - -1, -1, -1, 2819, -1, -1, 482, -1, -1, 485, - 486, 487, -1, 489, 490, 491, 492, 493, 494, 482, - -1, 2837, -1, -1, -1, -1, 489, 490, 491, 492, - 493, 494, -1, -1, -1, -1, -1, -1, 341, -1, - -1, -1, 345, 2859, 347, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 2878, -1, -1, -1, 369, -1, -1, -1, - -1, -1, 375, -1, -1, -1, -1, -1, -1, -1, - 482, -1, -1, 485, 486, 487, 389, 489, 490, 491, - 492, 493, 494, -1, -1, -1, -1, 499, -1, -1, - 482, -1, -1, -1, -1, -1, 2922, 489, 490, 491, - 492, 493, 494, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 2951, -1, -1, -1, -1, - 443, -1, -1, -1, -1, 3, 4, 5, 6, 7, - 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, -1, -1, -1, -1, 36, -1, - -1, 39, 40, 2999, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, -1, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - -1, 69, 70, 71, 72, 73, -1, 75, -1, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, -1, - 88, 89, 90, 91, 92, 93, -1, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - -1, 119, 120, 121, 122, 123, 124, -1, 126, 127, - 128, 129, 130, 131, -1, 133, 134, 135, 136, 137, - -1, 139, 140, 141, -1, 143, 144, 145, -1, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, -1, 161, 162, 163, 164, -1, 166, -1, - 168, 169, -1, 171, 172, 173, 174, 175, 176, -1, - 178, -1, 180, 181, 182, -1, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, -1, 197, - 198, 199, 200, 201, 202, -1, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, -1, 215, -1, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - -1, -1, 230, 231, 232, 233, -1, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, -1, 284, 285, -1, -1, - 288, 289, 290, -1, -1, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, -1, 310, 311, 312, 313, 314, 315, 316, 317, - 318, -1, 320, 321, 322, 323, 324, 325, -1, 327, - 328, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, - 348, -1, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - -1, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 382, 383, 384, -1, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, -1, 403, 404, -1, 406, 407, - 408, 409, 410, 411, 412, -1, 414, 415, -1, -1, - 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 430, 431, -1, -1, 434, 435, 436, 437, - 438, 439, -1, 441, 442, 443, 444, 445, 446, 447, - 448, 449, 450, 451, 452, 453, 454, 455, -1, -1, - 458, -1, -1, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 478, 479, 480, 481, 482, -1, -1, -1, -1, -1, - -1, 489, 490, 491, -1, -1, -1, -1, 496, -1, - 498, 499, -1, -1, -1, 503, -1, 505, 506, 3, - 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, - 24, 25, 26, 27, -1, 29, 30, 31, -1, -1, - -1, -1, 36, -1, -1, 39, 40, -1, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - -1, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, -1, 69, 70, 71, 72, 73, - -1, 75, -1, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, -1, 88, 89, 90, 91, 92, 93, - -1, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, -1, 119, 120, 121, 122, 123, - 124, -1, 126, 127, 128, 129, 130, -1, -1, 133, - 134, 135, 136, 137, -1, 139, 140, 141, -1, 143, - 144, 145, -1, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, -1, 161, 162, 163, - 164, -1, 166, -1, 168, 169, -1, 171, 172, 173, - 174, 175, 176, -1, 178, -1, 180, 181, 182, -1, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, -1, 197, 198, 199, 200, 201, 202, -1, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - -1, 215, -1, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, -1, -1, 230, 231, 232, 233, - -1, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, -1, - 284, 285, -1, -1, 288, 289, 290, -1, -1, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, -1, 310, 311, 312, 313, - 314, 315, 316, 317, 318, -1, 320, 321, 322, 323, - 324, 325, -1, 327, 328, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, -1, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, - 384, -1, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, -1, 403, - 404, 405, 406, 407, 408, 409, 410, 411, 412, -1, - 414, 415, -1, -1, 418, 419, 420, 421, 422, 423, - 424, 425, 426, 427, 428, 429, 430, 431, -1, -1, - 434, 435, 436, 437, 438, 439, -1, 441, 442, 443, - 444, 445, 446, 447, -1, 449, 450, 451, 452, 453, - 454, 455, -1, -1, 458, -1, 460, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 482, -1, - 484, -1, -1, -1, -1, 489, 490, -1, -1, -1, - -1, -1, 496, -1, 498, 499, -1, -1, -1, 503, - -1, 505, 506, 3, 4, 5, 6, 7, 8, 9, - 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, 36, -1, -1, 39, - 40, -1, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, -1, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, 75, -1, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, 169, - -1, 171, 172, 173, 174, 175, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, -1, -1, - 230, 231, 232, 233, -1, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, -1, 284, 285, -1, -1, 288, 289, - 290, -1, -1, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, 405, 406, 407, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, 439, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - 450, 451, 452, 453, 454, 455, -1, -1, 458, -1, - 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, 482, -1, 484, -1, -1, -1, -1, 489, - 490, -1, -1, -1, -1, -1, 496, -1, 498, -1, - -1, -1, -1, 503, -1, 505, 506, 3, 4, 5, - 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, - 26, 27, -1, 29, 30, 31, -1, -1, -1, -1, - 36, -1, -1, 39, 40, -1, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, -1, 75, - -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, -1, 88, 89, 90, 91, 92, 93, -1, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, -1, 119, 120, 121, 122, 123, 124, -1, - 126, 127, 128, 129, 130, -1, -1, 133, 134, 135, - 136, 137, -1, 139, 140, 141, -1, 143, 144, 145, - -1, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, -1, 161, 162, 163, 164, -1, - 166, -1, 168, 169, 170, 171, 172, 173, 174, 175, - 176, -1, 178, -1, 180, 181, 182, -1, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - -1, 197, 198, 199, 200, 201, 202, -1, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, -1, 215, - -1, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, -1, 229, 230, 231, 232, 233, -1, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, -1, 284, 285, - -1, -1, 288, 289, 290, -1, -1, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, -1, 310, 311, 312, 313, 314, 315, - 316, 317, 318, -1, 320, 321, 322, 323, 324, 325, - -1, 327, 328, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, -1, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 382, 383, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, -1, 403, 404, -1, - 406, 407, 408, 409, 410, 411, 412, -1, 414, 415, - -1, 417, 418, 419, 420, 421, 422, 423, 424, 425, - 426, 427, 428, 429, 430, 431, -1, -1, 434, 435, - 436, 437, 438, 439, -1, 441, 442, 443, 444, 445, - 446, 447, -1, 449, 450, 451, 452, 453, 454, 455, - -1, -1, 458, -1, -1, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, 482, -1, -1, -1, - -1, -1, -1, 489, 490, -1, -1, -1, -1, -1, - 496, -1, 498, -1, -1, -1, -1, 503, -1, 505, - 506, 3, 4, 5, 6, 7, 8, 9, 10, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - -1, -1, -1, 35, 36, -1, -1, 39, 40, -1, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, -1, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, -1, 69, 70, 71, - 72, 73, -1, 75, -1, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, -1, 88, 89, 90, 91, - 92, 93, -1, 95, 96, 97, 98, 99, 100, 101, + -1, -1, -1, -1, -1, -1, -1, -1, 2983, -1, + -1, -1, -1, 483, -1, -1, 486, 487, 488, -1, + 490, 491, 492, 493, 494, 495, -1, -1, -1, -1, + 500, -1, -1, -1, -1, -1, -1, 3012, -1, -1, + -1, -1, -1, -1, -1, -1, 3, 4, 5, 6, + 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, + 37, -1, -1, 40, 41, 3060, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, 132, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, 234, -1, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, + 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, -1, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, -1, 404, 405, -1, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, + -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, -1, -1, -1, + -1, -1, -1, 490, 491, 492, -1, -1, -1, -1, + 497, -1, 499, 500, -1, -1, -1, 504, -1, 506, + 507, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, -1, 30, 31, + 32, -1, -1, -1, -1, 37, -1, -1, 40, 41, + -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, -1, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, -1, 70, 71, + 72, 73, 74, -1, 76, -1, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, -1, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, -1, 119, 120, 121, - 122, 123, 124, -1, 126, 127, 128, 129, 130, -1, - -1, 133, 134, 135, 136, 137, -1, 139, 140, 141, - -1, 143, 144, 145, -1, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, - 162, 163, 164, -1, 166, -1, 168, 169, -1, 171, - 172, 173, 174, 175, 176, -1, 178, -1, 180, 181, - 182, -1, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, -1, 197, 198, 199, 200, 201, - 202, -1, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, -1, 215, -1, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, -1, -1, 230, 231, - 232, 233, -1, 235, 236, 237, 238, 239, 240, 241, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, + 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, + 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, + 182, 183, -1, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, -1, 198, 199, 200, 201, + 202, 203, -1, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, -1, 216, -1, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, -1, -1, 231, + 232, 233, 234, -1, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, -1, 284, 285, -1, -1, 288, 289, 290, -1, - -1, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, -1, 310, 311, - 312, 313, 314, 315, 316, 317, 318, -1, 320, 321, - 322, 323, 324, 325, -1, 327, 328, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 346, 347, 348, -1, 350, 351, + 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, + -1, -1, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, -1, 311, + 312, 313, 314, 315, 316, 317, 318, 319, -1, 321, + 322, 323, 324, 325, 326, -1, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, -1, 369, 370, 371, + 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - -1, 403, 404, -1, 406, 407, 408, 409, 410, 411, - 412, -1, 414, 415, -1, -1, 418, 419, 420, 421, + 402, -1, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, -1, 415, 416, -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, - -1, -1, 434, 435, 436, 437, 438, 439, -1, 441, - 442, 443, 444, 445, 446, 447, -1, 449, 450, 451, - 452, 453, 454, 455, -1, -1, 458, -1, -1, 461, + 432, -1, -1, 435, 436, 437, 438, 439, 440, -1, + 442, 443, 444, 445, 446, 447, 448, -1, 450, 451, + 452, 453, 454, 455, 456, -1, -1, 459, -1, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, - 482, -1, -1, -1, -1, -1, -1, 489, 490, -1, - -1, -1, -1, -1, 496, -1, 498, -1, -1, -1, - -1, 503, -1, 505, 506, 3, 4, 5, 6, 7, - 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, -1, -1, -1, -1, 36, -1, - -1, 39, 40, -1, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, -1, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - -1, 69, 70, 71, 72, 73, -1, 75, -1, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, -1, - 88, 89, 90, 91, 92, 93, -1, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - -1, 119, 120, 121, 122, 123, 124, -1, 126, 127, - 128, 129, 130, -1, -1, 133, 134, 135, 136, 137, - -1, 139, 140, 141, -1, 143, 144, 145, -1, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, -1, 161, 162, 163, 164, -1, 166, -1, - 168, 169, -1, 171, 172, 173, 174, 175, 176, -1, - 178, -1, 180, 181, 182, -1, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, -1, 197, - 198, 199, 200, 201, 202, -1, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, -1, 215, -1, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - -1, -1, 230, 231, 232, 233, -1, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, -1, 284, 285, -1, -1, - 288, 289, 290, -1, -1, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, -1, 310, 311, 312, 313, 314, 315, 316, 317, - 318, -1, 320, 321, 322, 323, 324, 325, -1, 327, - 328, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, - 348, -1, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - -1, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 382, 383, 384, -1, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, -1, 403, 404, -1, 406, 407, - 408, 409, 410, 411, 412, -1, 414, 415, -1, -1, - 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 430, 431, -1, -1, 434, 435, 436, 437, - 438, 439, -1, 441, 442, 443, 444, 445, 446, 447, - -1, 449, 450, 451, 452, 453, 454, 455, -1, -1, - 458, -1, -1, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 478, 479, 480, 481, 482, -1, -1, -1, -1, -1, - -1, 489, 490, 491, -1, -1, -1, -1, 496, -1, - 498, -1, -1, -1, -1, 503, -1, 505, 506, 3, - 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, -1, -1, - -1, -1, 36, -1, -1, 39, 40, -1, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - -1, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, -1, 69, 70, 71, 72, 73, - -1, 75, -1, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, -1, 88, 89, 90, 91, 92, 93, - -1, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, -1, 119, 120, 121, 122, 123, - 124, -1, 126, 127, 128, 129, 130, -1, -1, 133, - 134, 135, 136, 137, -1, 139, 140, 141, -1, 143, - 144, 145, -1, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, -1, 161, 162, 163, - 164, -1, 166, -1, 168, 169, -1, 171, 172, 173, - 174, 175, 176, -1, 178, -1, 180, 181, 182, -1, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, -1, 197, 198, 199, 200, 201, 202, -1, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - -1, 215, -1, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, -1, -1, 230, 231, 232, 233, - -1, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, -1, - 284, 285, -1, -1, 288, 289, 290, -1, -1, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, -1, 310, 311, 312, 313, - 314, 315, 316, 317, 318, -1, 320, 321, 322, 323, - 324, 325, -1, 327, 328, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, -1, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, -1, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, - 384, -1, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, -1, 403, - 404, -1, 406, 407, 408, 409, 410, 411, 412, -1, - 414, 415, -1, -1, 418, 419, 420, 421, 422, 423, - 424, 425, 426, 427, 428, 429, 430, 431, -1, -1, - 434, 435, 436, 437, 438, 439, -1, 441, 442, 443, - 444, 445, 446, 447, -1, 449, 450, 451, 452, 453, - 454, 455, -1, -1, 458, -1, -1, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 482, -1, - -1, -1, -1, -1, -1, 489, 490, 491, -1, -1, - -1, -1, 496, -1, 498, -1, -1, -1, -1, 503, - -1, 505, 506, 3, 4, 5, 6, 7, 8, 9, - 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, 36, -1, -1, 39, - 40, -1, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, -1, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, 75, -1, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, 169, - -1, 171, 172, 173, 174, 175, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, -1, -1, - 230, 231, 232, 233, -1, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, -1, 284, 285, -1, -1, 288, 289, - 290, -1, -1, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, -1, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, -1, 406, 407, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, 439, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - 450, 451, 452, 453, 454, 455, -1, -1, 458, -1, - -1, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, 482, -1, -1, -1, -1, -1, -1, 489, - 490, 491, -1, -1, -1, -1, 496, -1, 498, -1, - -1, -1, -1, 503, -1, 505, 506, 3, 4, 5, - 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, -1, -1, -1, -1, - 36, -1, -1, 39, 40, -1, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, -1, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, -1, 75, - -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, -1, 88, 89, 90, 91, 92, 93, -1, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, -1, 119, 120, 121, 122, 123, 124, -1, - 126, 127, 128, 129, 130, -1, -1, 133, 134, 135, - 136, 137, -1, 139, 140, 141, -1, 143, 144, 145, - -1, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, -1, 161, 162, 163, 164, -1, - 166, -1, 168, 169, -1, 171, 172, 173, 174, 175, - 176, -1, 178, -1, 180, 181, 182, -1, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - -1, 197, 198, 199, 200, 201, 202, -1, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, -1, 215, - -1, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, -1, -1, 230, 231, 232, 233, -1, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, -1, 284, 285, - -1, -1, 288, 289, 290, -1, -1, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, -1, 310, 311, 312, 313, 314, 315, - 316, 317, 318, -1, 320, 321, 322, 323, 324, 325, - -1, 327, 328, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, -1, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 382, 383, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, -1, 403, 404, -1, - 406, 407, 408, 409, 410, 411, 412, -1, 414, 415, - -1, -1, 418, 419, 420, 421, 422, 423, 424, 425, - 426, 427, 428, 429, 430, 431, -1, -1, 434, 435, - 436, 437, 438, 439, -1, 441, 442, 443, 444, 445, - 446, 447, -1, 449, 450, 451, 452, 453, 454, 455, - -1, -1, 458, -1, -1, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, 482, -1, -1, -1, - -1, -1, -1, 489, 490, -1, -1, -1, -1, -1, - 496, -1, 498, -1, -1, -1, -1, 503, -1, 505, - 506, 3, 4, 5, 6, 7, 8, 9, 10, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, - 22, 23, 24, 25, 26, 27, -1, 29, 30, 31, - -1, -1, -1, -1, 36, -1, -1, 39, 40, -1, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, -1, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, -1, 69, 70, 71, - 72, 73, -1, 75, -1, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, -1, 88, 89, 90, 91, - 92, 93, -1, 95, 96, 97, 98, 99, 100, 101, + 482, 483, -1, 485, -1, -1, -1, -1, 490, 491, + -1, -1, -1, -1, -1, 497, -1, 499, 500, -1, + -1, -1, 504, -1, 506, 507, 3, 4, 5, 6, + 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, -1, 30, 31, 32, -1, -1, -1, -1, + 37, -1, -1, 40, 41, -1, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, 234, -1, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, + 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, -1, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, -1, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, -1, 450, 451, 452, 453, 454, 455, 456, + -1, -1, 459, -1, 461, 462, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, -1, 485, -1, + -1, -1, -1, 490, 491, -1, -1, -1, -1, -1, + 497, -1, 499, -1, -1, -1, -1, 504, -1, 506, + 507, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, -1, 30, 31, + 32, -1, -1, -1, -1, 37, -1, -1, 40, 41, + -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, -1, 70, 71, + 72, 73, 74, -1, 76, -1, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, -1, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, -1, 119, 120, 121, - 122, 123, 124, -1, 126, 127, 128, 129, 130, -1, - -1, 133, 134, 135, 136, 137, -1, 139, 140, 141, - -1, 143, 144, 145, -1, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, - 162, 163, 164, -1, 166, -1, 168, 169, -1, 171, - 172, 173, 174, 175, 176, -1, 178, -1, 180, 181, - 182, -1, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, -1, 197, 198, 199, 200, 201, - 202, -1, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, -1, 215, -1, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, -1, -1, 230, 231, - 232, 233, -1, 235, 236, 237, 238, 239, 240, 241, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, + 162, 163, 164, 165, -1, 167, -1, 169, 170, 171, + 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, + 182, 183, -1, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, -1, 198, 199, 200, 201, + 202, 203, -1, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, -1, 216, -1, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, -1, 230, 231, + 232, 233, 234, -1, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, -1, 284, 285, -1, -1, 288, 289, 290, -1, - -1, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, -1, 310, 311, - 312, 313, 314, 315, 316, 317, 318, -1, 320, 321, - 322, 323, 324, 325, -1, 327, 328, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 346, 347, 348, -1, 350, 351, + 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, + -1, -1, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, -1, 311, + 312, 313, 314, 315, 316, 317, 318, 319, -1, 321, + 322, 323, 324, 325, 326, -1, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, -1, 369, 370, 371, + 362, 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, -1, 386, 387, 388, 389, 390, 391, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - -1, 403, 404, -1, 406, 407, 408, 409, 410, 411, - 412, -1, 414, 415, -1, -1, 418, 419, 420, 421, + 402, -1, 404, 405, -1, 407, 408, 409, 410, 411, + 412, 413, -1, 415, 416, -1, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, - -1, -1, 434, 435, 436, 437, 438, 439, -1, 441, - 442, 443, 444, 445, 446, 447, -1, 449, 450, 451, - 452, 453, 454, 455, -1, -1, 458, -1, -1, 461, + 432, -1, -1, 435, 436, 437, 438, 439, 440, -1, + 442, 443, 444, 445, 446, 447, 448, -1, 450, 451, + 452, 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, - 482, -1, -1, -1, -1, -1, -1, 489, 490, -1, - -1, -1, -1, -1, 496, -1, 498, 499, -1, -1, - -1, 503, -1, 505, 506, 3, 4, 5, 6, 7, - 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, - -1, 29, 30, 31, -1, -1, -1, -1, 36, -1, - -1, 39, 40, -1, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, -1, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - -1, 69, 70, 71, 72, 73, -1, 75, -1, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, -1, - 88, 89, 90, 91, 92, 93, -1, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - -1, 119, 120, 121, 122, 123, 124, -1, 126, 127, - 128, 129, 130, -1, -1, 133, 134, 135, 136, 137, - -1, 139, 140, 141, -1, 143, 144, 145, -1, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, -1, 161, 162, 163, 164, -1, 166, -1, - 168, 169, -1, 171, 172, 173, 174, 175, 176, -1, - 178, -1, 180, 181, 182, -1, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, -1, 197, - 198, 199, 200, 201, 202, -1, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, -1, 215, -1, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - -1, -1, 230, 231, 232, 233, -1, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, -1, 284, 285, -1, -1, - 288, 289, 290, -1, -1, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, -1, 310, 311, 312, 313, 314, 315, 316, 317, - 318, -1, 320, 321, 322, 323, 324, 325, -1, 327, - 328, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, - 348, -1, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - -1, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 382, 383, 384, -1, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, -1, 403, 404, -1, 406, 407, - 408, 409, 410, 411, 412, -1, 414, 415, -1, -1, - 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 430, 431, -1, -1, 434, 435, 436, 437, - 438, 439, -1, 441, 442, 443, 444, 445, 446, 447, - 448, 449, 450, 451, 452, 453, 454, 455, -1, -1, - 458, -1, -1, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 478, 479, 480, 481, 482, -1, -1, -1, -1, -1, - -1, 489, 490, -1, -1, -1, -1, -1, 496, -1, - 498, -1, -1, -1, -1, 503, -1, 505, 506, 3, - 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, - 24, 25, 26, 27, -1, 29, 30, 31, -1, -1, - -1, -1, 36, -1, -1, 39, 40, -1, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - -1, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, -1, 69, 70, 71, 72, 73, - -1, 75, -1, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, -1, 88, 89, 90, 91, 92, 93, - -1, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, -1, 119, 120, 121, 122, 123, - 124, -1, 126, 127, 128, 129, 130, -1, -1, 133, - 134, 135, 136, 137, -1, 139, 140, 141, -1, 143, - 144, 145, -1, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, -1, 161, 162, 163, - 164, -1, 166, -1, 168, 169, -1, 171, 172, 173, - 174, 175, 176, -1, 178, -1, 180, 181, 182, -1, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, -1, 197, 198, 199, 200, 201, 202, -1, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - -1, 215, -1, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, -1, -1, 230, 231, 232, 233, - -1, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, -1, - 284, 285, -1, -1, 288, 289, 290, -1, -1, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, -1, 310, 311, 312, 313, - 314, 315, 316, 317, 318, -1, 320, 321, 322, 323, - 324, 325, -1, 327, 328, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, -1, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, -1, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, - 384, -1, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, -1, 403, - 404, -1, 406, 407, 408, 409, 410, 411, 412, -1, - 414, 415, -1, -1, 418, 419, 420, 421, 422, 423, - 424, 425, 426, 427, 428, 429, 430, 431, -1, -1, - 434, 435, 436, 437, 438, 439, -1, 441, 442, 443, - 444, 445, 446, 447, -1, 449, 450, 451, 452, 453, - 454, 455, -1, -1, 458, -1, -1, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 482, -1, - -1, -1, -1, -1, -1, 489, 490, -1, -1, -1, - -1, -1, 496, -1, 498, 499, -1, -1, -1, 503, - -1, 505, 506, 3, 4, 5, 6, 7, 8, 9, - 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, 36, -1, -1, 39, - 40, -1, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, -1, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, 75, -1, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, 169, - 170, 171, 172, 173, 174, 175, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, -1, -1, - 230, 231, 232, 233, -1, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, -1, 284, 285, -1, -1, 288, 289, - 290, -1, -1, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, -1, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, -1, 406, 407, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, 439, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - 450, 451, 452, 453, 454, 455, -1, -1, 458, -1, - -1, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, 482, -1, -1, -1, -1, -1, -1, 489, - 490, -1, -1, -1, -1, -1, 496, -1, 498, -1, - -1, -1, -1, 503, -1, 505, 506, 3, 4, 5, - 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, - 26, 27, -1, 29, 30, 31, -1, -1, -1, -1, - 36, -1, -1, 39, 40, -1, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, -1, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, -1, 75, - -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, -1, 88, 89, 90, 91, 92, 93, -1, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, -1, 119, 120, 121, 122, 123, 124, -1, - 126, 127, 128, 129, 130, -1, -1, 133, 134, 135, - 136, 137, -1, 139, 140, 141, -1, 143, 144, 145, - -1, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, -1, 161, 162, 163, 164, -1, - 166, -1, 168, 169, -1, 171, 172, 173, 174, 175, - 176, -1, 178, -1, 180, 181, 182, -1, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - -1, 197, 198, 199, 200, 201, 202, -1, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, -1, 215, - -1, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, -1, -1, 230, 231, 232, 233, -1, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, -1, 284, 285, - -1, -1, 288, 289, 290, -1, -1, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, -1, 310, 311, 312, 313, 314, 315, - 316, 317, 318, -1, 320, 321, 322, 323, 324, 325, - -1, 327, 328, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, -1, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 382, 383, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, -1, 403, 404, 405, - 406, 407, 408, 409, 410, 411, 412, -1, 414, 415, - -1, -1, 418, 419, 420, 421, 422, 423, 424, 425, - 426, 427, 428, 429, 430, 431, -1, -1, 434, 435, - 436, 437, 438, 439, -1, 441, 442, 443, 444, 445, - 446, 447, -1, 449, 450, 451, 452, 453, 454, 455, - -1, -1, 458, -1, -1, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, 482, -1, -1, -1, - -1, -1, -1, 489, 490, -1, -1, -1, -1, -1, - 496, -1, 498, -1, -1, -1, -1, 503, -1, 505, - 506, 3, 4, 5, 6, 7, 8, 9, 10, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, - 22, 23, 24, 25, 26, 27, -1, 29, 30, 31, - -1, -1, -1, -1, 36, -1, -1, 39, 40, -1, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, -1, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, -1, 69, 70, 71, - 72, 73, -1, 75, -1, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, -1, 88, 89, 90, 91, - 92, 93, -1, 95, 96, 97, 98, 99, 100, 101, + 482, 483, -1, -1, -1, -1, -1, -1, 490, 491, + -1, -1, -1, -1, -1, 497, -1, 499, -1, -1, + -1, -1, 504, -1, 506, 507, 3, 4, 5, 6, + 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, -1, 36, + 37, -1, -1, 40, 41, -1, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, 234, -1, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, + 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, -1, 404, 405, -1, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, -1, 450, 451, 452, 453, 454, 455, 456, + -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, -1, -1, -1, + -1, -1, -1, 490, 491, -1, -1, -1, -1, -1, + 497, -1, 499, -1, -1, -1, -1, 504, -1, 506, + 507, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, -1, -1, -1, -1, 37, -1, -1, 40, 41, + -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, -1, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, -1, 70, 71, + 72, 73, 74, -1, 76, -1, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, -1, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, -1, 119, 120, 121, - 122, 123, 124, -1, 126, 127, 128, 129, 130, -1, - -1, 133, 134, 135, 136, 137, -1, 139, 140, 141, - -1, 143, 144, 145, -1, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, - 162, 163, 164, -1, 166, -1, 168, 169, -1, 171, - 172, 173, 174, 175, 176, -1, 178, -1, 180, 181, - 182, -1, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, -1, 197, 198, 199, 200, 201, - 202, -1, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, -1, 215, -1, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, -1, -1, 230, 231, - 232, 233, -1, 235, 236, 237, 238, 239, 240, 241, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, + 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, + 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, + 182, 183, -1, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, -1, 198, 199, 200, 201, + 202, 203, -1, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, -1, 216, -1, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, -1, -1, 231, + 232, 233, 234, -1, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, -1, 284, 285, -1, -1, 288, 289, 290, -1, - -1, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, -1, 310, 311, - 312, 313, 314, 315, 316, 317, 318, -1, 320, 321, - 322, 323, 324, 325, -1, 327, 328, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 346, 347, 348, -1, 350, 351, + 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, + -1, -1, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, -1, 311, + 312, 313, 314, 315, 316, 317, 318, 319, -1, 321, + 322, 323, 324, 325, 326, -1, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, -1, 369, 370, 371, + 362, 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, -1, 386, 387, 388, 389, 390, 391, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - -1, 403, 404, -1, 406, 407, 408, 409, 410, 411, - 412, -1, 414, 415, -1, -1, 418, 419, 420, 421, + 402, -1, 404, 405, -1, 407, 408, 409, 410, 411, + 412, 413, -1, 415, 416, -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, - -1, -1, 434, 435, 436, 437, 438, 439, -1, 441, - 442, 443, 444, 445, 446, 447, -1, 449, 450, 451, - 452, 453, 454, 455, -1, -1, 458, -1, -1, 461, + 432, -1, -1, 435, 436, 437, 438, 439, 440, -1, + 442, 443, 444, 445, 446, 447, 448, -1, 450, 451, + 452, 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, - 482, -1, -1, -1, -1, -1, -1, 489, 490, -1, - -1, -1, -1, -1, 496, -1, 498, -1, -1, -1, - -1, 503, -1, 505, 506, 3, 4, 5, 6, 7, - 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, - -1, 29, 30, 31, -1, -1, -1, -1, 36, -1, - -1, 39, 40, -1, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, -1, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - -1, 69, 70, 71, 72, 73, -1, 75, -1, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, -1, - 88, 89, 90, 91, 92, 93, -1, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - -1, 119, 120, 121, 122, 123, 124, -1, 126, 127, - 128, 129, 130, -1, -1, 133, 134, 135, 136, 137, - -1, 139, 140, 141, -1, 143, 144, 145, -1, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, -1, 161, 162, 163, 164, -1, 166, -1, - 168, 169, -1, 171, 172, 173, 174, 175, 176, -1, - 178, -1, 180, 181, 182, -1, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, -1, 197, - 198, 199, 200, 201, 202, -1, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, -1, 215, -1, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - -1, -1, 230, 231, 232, 233, -1, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, -1, 284, 285, -1, -1, - 288, 289, 290, -1, -1, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, -1, 310, 311, 312, 313, 314, 315, 316, 317, - 318, -1, 320, 321, 322, 323, 324, 325, -1, 327, - 328, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, - 348, -1, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - -1, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 382, 383, 384, -1, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, -1, 403, 404, -1, 406, 407, - 408, 409, 410, 411, 412, -1, 414, 415, -1, -1, - 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 430, 431, -1, -1, 434, 435, 436, 437, - 438, 439, -1, 441, 442, 443, 444, 445, 446, 447, - -1, 449, 450, 451, 452, 453, 454, 455, -1, -1, - 458, -1, -1, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 478, 479, 480, 481, 482, -1, -1, -1, -1, -1, - -1, 489, 490, -1, -1, -1, -1, -1, 496, -1, - 498, -1, -1, -1, -1, 503, -1, 505, 506, 3, - 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, - 24, 25, 26, 27, -1, 29, 30, 31, -1, -1, - -1, -1, 36, -1, -1, 39, 40, -1, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - -1, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, -1, 69, 70, 71, 72, 73, - -1, 75, -1, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, -1, 88, 89, 90, 91, 92, 93, - -1, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, -1, 119, 120, 121, 122, 123, - 124, -1, 126, 127, 128, 129, 130, -1, -1, 133, - 134, 135, 136, 137, -1, 139, 140, 141, -1, 143, - 144, 145, -1, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, -1, 161, 162, 163, - 164, -1, 166, -1, 168, 169, -1, 171, 172, 173, - 174, 175, 176, -1, 178, -1, 180, 181, 182, -1, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, -1, 197, 198, 199, 200, 201, 202, -1, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - -1, 215, -1, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, -1, -1, 230, 231, 232, 233, - -1, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, -1, - 284, 285, -1, -1, 288, 289, 290, -1, -1, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, -1, 310, 311, 312, 313, - 314, 315, 316, 317, 318, -1, 320, 321, 322, 323, - 324, 325, -1, 327, 328, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, -1, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, -1, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, - 384, -1, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, -1, 403, - 404, -1, 406, 407, 408, 409, 410, 411, 412, -1, - 414, 415, -1, -1, 418, 419, 420, 421, 422, 423, - 424, 425, 426, 427, 428, 429, 430, 431, -1, -1, - 434, 435, 436, 437, 438, 439, -1, 441, 442, 443, - 444, 445, 446, 447, -1, 449, 450, 451, 452, 453, - 454, 455, -1, -1, 458, -1, -1, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 482, -1, - -1, -1, -1, -1, -1, 489, 490, -1, -1, -1, - -1, -1, 496, -1, 498, -1, -1, -1, -1, 503, - -1, 505, 506, 3, 4, 5, 6, 7, 8, 9, - 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, 36, -1, -1, 39, - 40, -1, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, -1, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, 75, -1, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, 169, - -1, 171, 172, 173, 174, 175, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, -1, -1, - 230, 231, 232, 233, -1, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, - 280, 281, 282, -1, 284, 285, -1, -1, 288, 289, - 290, -1, -1, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, -1, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, -1, 406, 407, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, 439, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - 450, 451, 452, 453, 454, 455, -1, -1, 458, -1, - -1, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, 482, -1, -1, -1, -1, -1, -1, 489, - 490, -1, -1, -1, -1, -1, 496, -1, 498, -1, - -1, -1, -1, 503, -1, 505, 506, 3, 4, 5, - 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, - 26, 27, -1, 29, 30, 31, -1, -1, -1, -1, - 36, -1, -1, 39, 40, -1, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, -1, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, -1, 75, - -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, -1, 88, 89, 90, 91, 92, 93, -1, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, -1, 119, 120, 121, 122, 123, 124, -1, - 126, 127, 128, 129, 130, -1, -1, 133, 134, 135, - 136, 137, -1, 139, 140, 141, -1, 143, 144, 145, - -1, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, -1, 161, 162, 163, 164, -1, - 166, -1, 168, 169, -1, 171, 172, 173, 174, 175, - 176, -1, 178, -1, 180, 181, 182, -1, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - -1, 197, 198, 199, 200, 201, 202, -1, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, -1, 215, - -1, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, -1, -1, 230, 231, 232, 233, -1, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, -1, 284, 285, - -1, -1, 288, 289, 290, -1, -1, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, -1, 310, 311, 312, 313, 314, 315, - 316, 317, 318, -1, 320, 321, 322, 323, 324, 325, - -1, 327, 328, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, -1, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 382, 383, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, -1, 403, 404, -1, - 406, 407, 408, 409, 410, 411, 412, -1, 414, 415, - -1, -1, 418, 419, 420, 421, 422, 423, 424, 425, - 426, 427, 428, 429, 430, 431, -1, -1, 434, 435, - 436, 437, 438, 439, -1, 441, 442, 443, 444, 445, - 446, 447, -1, 449, 450, 451, 452, 453, 454, 455, - -1, -1, 458, -1, -1, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, 482, -1, -1, -1, - -1, -1, -1, 489, 490, -1, -1, -1, -1, -1, - 496, -1, 498, -1, -1, -1, -1, 503, -1, 505, - 506, 3, 4, 5, 6, 7, 8, 9, 10, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, - 22, 23, 24, 25, 26, 27, -1, 29, 30, 31, - -1, -1, -1, -1, 36, -1, -1, 39, 40, -1, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, -1, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, -1, 69, 70, 71, - 72, 73, -1, 75, -1, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, -1, 88, 89, 90, 91, - 92, 93, -1, 95, 96, 97, 98, 99, 100, 101, + 482, 483, -1, -1, -1, -1, -1, -1, 490, 491, + 492, -1, -1, -1, -1, 497, -1, 499, -1, -1, + -1, -1, 504, -1, 506, 507, 3, 4, 5, 6, + 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, + 37, -1, -1, 40, 41, -1, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, 234, -1, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, + 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, -1, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, -1, 404, 405, -1, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, -1, 450, 451, 452, 453, 454, 455, 456, + -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, -1, -1, -1, + -1, -1, -1, 490, 491, 492, -1, -1, -1, -1, + 497, -1, 499, -1, -1, -1, -1, 504, -1, 506, + 507, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, -1, 30, 31, + 32, -1, -1, -1, -1, 37, -1, -1, 40, 41, + -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, -1, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, -1, 70, 71, + 72, 73, 74, -1, 76, -1, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, -1, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, 116, 117, -1, 119, 120, 121, - 122, 123, 124, -1, 126, 127, 128, 129, 130, -1, - -1, 133, 134, 135, 136, 137, -1, 139, 140, 141, - -1, 143, 144, 145, -1, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, - 162, 163, 164, -1, 166, -1, 168, 169, -1, 171, - 172, 173, 174, 175, 176, -1, 178, -1, 180, 181, - 182, -1, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, -1, 197, 198, 199, 200, 201, - 202, -1, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, -1, 215, -1, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, -1, -1, 230, 231, - 232, 233, -1, 235, 236, 237, 238, 239, 240, 241, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, + 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, + 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, + 182, 183, -1, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, -1, 198, 199, 200, 201, + 202, 203, -1, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, -1, 216, -1, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, -1, -1, 231, + 232, 233, 234, -1, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, -1, 284, 285, -1, -1, 288, 289, 290, -1, - -1, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, -1, 310, 311, - 312, 313, 314, 315, 316, 317, 318, -1, 320, 321, - 322, 323, 324, 325, -1, 327, 328, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 346, 347, 348, -1, 350, 351, + 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, + -1, -1, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, -1, 311, + 312, 313, 314, 315, 316, 317, 318, 319, -1, 321, + 322, 323, 324, 325, 326, -1, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, -1, 369, 370, 371, + 362, 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, -1, 386, 387, 388, 389, 390, 391, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - -1, 403, 404, -1, 406, 407, 408, 409, 410, 411, - 412, -1, 414, 415, -1, -1, 418, 419, 420, 421, + 402, -1, 404, 405, -1, 407, 408, 409, 410, 411, + 412, 413, -1, 415, 416, -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, - -1, -1, 434, 435, 436, 437, 438, 439, -1, 441, - 442, 443, 444, 445, 446, 447, -1, 449, 450, 451, - 452, 453, 454, 455, -1, -1, 458, -1, -1, 461, + 432, -1, -1, 435, 436, 437, 438, 439, 440, -1, + 442, 443, 444, 445, 446, 447, 448, -1, 450, 451, + 452, 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, - 482, -1, -1, -1, -1, -1, -1, 489, 490, -1, - -1, -1, -1, -1, 496, -1, 498, -1, -1, -1, - -1, 503, -1, 505, 506, 3, 4, 5, 6, 7, - 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, - -1, 29, 30, 31, -1, -1, -1, -1, 36, -1, - -1, 39, 40, -1, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, -1, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - -1, 69, 70, 71, 72, 73, -1, 75, -1, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, -1, - 88, 89, 90, 91, 92, 93, -1, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - -1, 119, 120, 121, 122, 123, 124, -1, 126, 127, - 128, 129, 130, -1, -1, 133, 134, 135, 136, 137, - -1, 139, 140, 141, -1, 143, 144, 145, -1, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, -1, 161, 162, 163, 164, -1, 166, -1, - 168, 169, -1, 171, 172, 173, 174, 175, 176, -1, - 178, -1, 180, 181, 182, -1, 184, 185, 186, 187, - 188, 189, 190, 191, 192, 193, 194, 195, -1, 197, - 198, 199, 200, 201, 202, -1, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, -1, 215, -1, 217, - 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - -1, -1, 230, 231, 232, 233, -1, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, - 278, 279, 280, 281, 282, -1, 284, 285, -1, -1, - 288, 289, 290, -1, -1, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, -1, 310, 311, 312, 313, 314, 315, 316, 317, - 318, -1, 320, 321, 322, 323, 324, 325, -1, 327, - 328, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, - 348, -1, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - -1, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 381, 382, 383, 384, -1, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, -1, 403, 404, -1, 406, 407, - 408, 409, 410, 411, 412, -1, 414, 415, -1, -1, - 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 430, 431, -1, -1, 434, 435, 436, 437, - 438, 439, -1, 441, 442, 443, 444, 445, 446, 447, - -1, 449, 450, 451, 452, 453, 454, 455, -1, -1, - 458, -1, -1, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 478, 479, 480, 481, 482, -1, -1, -1, -1, -1, - -1, 489, 490, -1, -1, -1, -1, -1, 496, -1, - 498, -1, -1, -1, -1, 503, -1, 505, 506, 3, - 4, 5, 6, 7, 8, 9, 10, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, - 24, 25, 26, 27, -1, 29, 30, 31, -1, -1, - -1, -1, 36, -1, -1, 39, 40, -1, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, - -1, 55, 56, 57, 58, 59, 60, 61, 62, 63, - 64, 65, 66, 67, -1, 69, 70, 71, 72, 73, - -1, 75, -1, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, -1, 88, 89, 90, 91, 92, 93, - -1, 95, 96, 97, 98, 99, 100, 101, 102, 103, - 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, -1, 119, 120, 121, 122, 123, - 124, -1, 126, 127, 128, 129, 130, -1, -1, 133, - 134, 135, 136, 137, -1, 139, 140, 141, -1, 143, - 144, 145, -1, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, 158, 159, -1, 161, 162, 163, - 164, -1, 166, -1, 168, 169, -1, 171, 172, 173, - 174, 175, 176, -1, 178, -1, 180, 181, 182, -1, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, -1, 197, 198, 199, 200, 201, 202, -1, - 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - -1, 215, -1, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, -1, -1, 230, 231, 232, 233, - -1, 235, 236, 237, 238, 239, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, - 274, 275, 276, 277, 278, 279, 280, 281, 282, -1, - 284, 285, -1, -1, 288, 289, 290, -1, -1, 293, - 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, -1, 310, 311, 312, 313, - 314, 315, 316, 317, 318, -1, 320, 321, 322, 323, - 324, 325, -1, 327, 328, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, -1, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, -1, 369, 370, 371, 372, 373, - 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, - 384, -1, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, -1, 403, - 404, -1, 406, 407, 408, 409, 410, 411, 412, -1, - 414, 415, -1, -1, 418, 419, 420, 421, 422, 423, - 424, 425, 426, 427, 428, 429, 430, 431, -1, -1, - 434, 435, 436, 437, 438, 439, -1, 441, 442, 443, - 444, 445, 446, 447, -1, 449, 450, 451, 452, 453, - 454, 455, -1, -1, 458, -1, -1, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 482, -1, - -1, -1, -1, -1, -1, 489, 490, -1, -1, -1, - -1, -1, 496, -1, 498, -1, -1, -1, -1, 503, - -1, 505, 506, 3, 4, 5, 6, 7, 8, 9, - 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, 36, -1, -1, 39, - 40, -1, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, -1, 55, 56, 57, 58, 59, - 60, 61, 62, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, 75, -1, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, 169, - -1, 171, 172, 173, 174, 175, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, -1, -1, - 220, 221, 222, 223, 224, 225, 226, 227, -1, -1, - 230, 231, 232, 233, -1, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, -1, 272, 273, -1, 275, 276, 277, 278, 279, - 280, 281, 282, -1, 284, 285, -1, -1, 288, 289, - 290, -1, -1, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, -1, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, -1, 406, 407, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, 439, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - 450, 451, 452, 453, 454, 455, -1, -1, 458, -1, - -1, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, 482, -1, -1, -1, -1, -1, -1, 489, - 490, -1, -1, -1, -1, -1, 496, -1, 498, -1, - -1, -1, -1, 503, -1, 505, 506, 3, 4, 5, - 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, - 26, 27, -1, 29, 30, 31, -1, -1, -1, -1, - -1, -1, -1, 39, 40, -1, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, -1, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, -1, 75, - -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, -1, 88, 89, 90, 91, 92, 93, -1, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - -1, 117, -1, 119, 120, 121, 122, 123, 124, -1, - 126, 127, 128, 129, 130, -1, -1, 133, 134, 135, - 136, 137, -1, 139, 140, 141, -1, 143, 144, 145, - -1, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, -1, 161, 162, 163, 164, -1, - 166, -1, 168, 169, -1, 171, 172, 173, 174, 175, - 176, -1, 178, -1, 180, 181, 182, -1, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - -1, 197, 198, 199, 200, 201, 202, -1, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, -1, 215, - -1, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, -1, -1, 230, 231, 232, 233, -1, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, -1, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, -1, 284, 285, - -1, -1, 288, 289, 290, -1, -1, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, -1, 310, 311, 312, 313, 314, 315, - 316, 317, 318, -1, 320, 321, 322, 323, 324, 325, - -1, 327, 328, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, -1, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 382, 383, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, -1, 403, 404, -1, - 406, 407, 408, 409, 410, 411, 412, -1, 414, 415, - -1, -1, 418, 419, 420, 421, 422, 423, 424, 425, - 426, 427, 428, 429, 430, 431, -1, -1, 434, 435, - 436, 437, 438, 439, -1, 441, 442, 443, 444, 445, - 446, 447, -1, 449, 450, 451, 452, 453, 454, 455, - -1, -1, 458, -1, -1, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, -1, -1, -1, -1, - -1, -1, -1, 489, 490, -1, -1, 3, 4, 5, - 6, 7, 498, 9, 10, -1, -1, -1, -1, 505, - 506, -1, -1, -1, 20, 21, 22, 23, 24, 25, - 26, 27, -1, 29, 30, 31, -1, -1, -1, -1, - -1, -1, -1, 39, 40, -1, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, -1, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, -1, 75, - -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, -1, 88, 89, 90, 91, 92, 93, -1, 95, - 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - -1, 117, -1, 119, 120, 121, 122, 123, 124, -1, - 126, 127, 128, 129, 130, -1, -1, 133, 134, 135, - 136, 137, -1, 139, 140, 141, -1, 143, 144, 145, - -1, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, -1, 161, 162, 163, 164, -1, - 166, -1, 168, 169, -1, 171, 172, 173, 174, 175, - 176, -1, 178, -1, 180, 181, 182, -1, 184, 185, - 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - -1, 197, 198, 199, 200, 201, 202, -1, 204, 205, - 206, 207, 208, 209, 210, 211, 212, 213, -1, 215, - -1, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, -1, -1, 230, 231, 232, 233, -1, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, 270, -1, 272, 273, 274, 275, - 276, 277, 278, 279, 280, 281, 282, -1, 284, 285, - -1, -1, 288, 289, 290, -1, -1, 293, 294, 295, - 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, -1, 310, 311, 312, 313, 314, 315, - 316, 317, 318, -1, 320, 321, 322, 323, 324, 325, - -1, 327, 328, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, -1, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, 380, 381, 382, 383, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, -1, 403, 404, -1, - 406, 407, 408, 409, 410, 411, 412, -1, 414, 415, - -1, -1, 418, 419, 420, 421, 422, 423, 424, 425, - 426, 427, 428, 429, 430, 431, -1, -1, 434, 435, - 436, 437, 438, 439, -1, 441, 442, 443, 444, 445, - 446, 447, -1, 449, 450, 451, 452, 453, 454, 455, - -1, -1, 458, -1, -1, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, -1, -1, -1, -1, - -1, -1, -1, 489, 490, -1, -1, -1, -1, -1, - -1, -1, 498, -1, -1, -1, -1, -1, -1, 505, - 506, 3, 4, 5, 6, 7, 8, 9, 10, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, - 22, 23, 24, 25, 26, 27, -1, 29, 30, 31, - -1, -1, -1, -1, -1, -1, -1, 39, 40, -1, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, -1, 55, 56, 57, 58, 59, 60, 61, - 62, 63, 64, 65, 66, 67, -1, 69, 70, 71, - 72, 73, -1, 75, -1, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, -1, 88, 89, 90, 91, - 92, 93, -1, 95, 96, 97, 98, 99, 100, 101, + 482, 483, -1, -1, -1, -1, -1, -1, 490, 491, + 492, -1, -1, -1, -1, 497, -1, 499, -1, -1, + -1, -1, 504, -1, 506, 507, 3, 4, 5, 6, + 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, + 37, -1, -1, 40, 41, -1, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, 234, -1, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, + 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, -1, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, -1, 404, 405, -1, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, -1, 450, 451, 452, 453, 454, 455, 456, + -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, -1, -1, -1, + -1, -1, -1, 490, 491, -1, -1, -1, -1, -1, + 497, -1, 499, -1, -1, -1, -1, 504, -1, 506, + 507, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, -1, 30, 31, + 32, -1, -1, -1, -1, 37, -1, -1, 40, 41, + -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, -1, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, -1, 70, 71, + 72, 73, 74, -1, 76, -1, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, -1, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, -1, 117, -1, 119, 120, 121, - 122, 123, 124, -1, 126, 127, 128, 129, 130, -1, - -1, 133, 134, 135, 136, 137, -1, 139, 140, 141, - -1, 143, 144, 145, -1, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, - 162, 163, 164, -1, 166, -1, 168, 169, -1, 171, - 172, 173, 174, 175, 176, -1, 178, -1, 180, 181, - 182, -1, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, -1, 197, 198, 199, 200, 201, - 202, -1, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, -1, 215, -1, 217, -1, 219, 220, 221, - 222, 223, 224, 225, 226, 227, -1, -1, 230, 231, - 232, 233, -1, 235, 236, 237, 238, 239, 240, 241, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, + 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, + 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, + 182, 183, -1, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, -1, 198, 199, 200, 201, + 202, 203, -1, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, -1, 216, -1, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, -1, -1, 231, + 232, 233, 234, -1, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, -1, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, - 282, -1, 284, 285, -1, -1, 288, 289, 290, -1, - -1, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, -1, 310, 311, - 312, 313, 314, 315, 316, 317, 318, -1, 320, 321, - 322, 323, 324, 325, -1, 327, 328, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 346, 347, 348, -1, 350, 351, + 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, + -1, -1, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, -1, 311, + 312, 313, 314, 315, 316, 317, 318, 319, -1, 321, + 322, 323, 324, 325, 326, -1, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, -1, 369, 370, 371, + 362, 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, -1, 386, 387, 388, 389, 390, 391, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - -1, 403, 404, -1, 406, 407, 408, 409, 410, 411, - 412, -1, 414, 415, -1, -1, 418, 419, 420, 421, + 402, -1, 404, 405, -1, 407, 408, 409, 410, 411, + 412, 413, -1, 415, 416, -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, - -1, -1, 434, 435, 436, 437, 438, 439, -1, 441, - 442, 443, 444, 445, 446, 447, -1, 449, 450, 451, - 452, 453, 454, 455, -1, -1, 458, -1, -1, 461, + 432, -1, -1, 435, 436, 437, 438, 439, 440, -1, + 442, 443, 444, 445, 446, 447, 448, -1, 450, 451, + 452, 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, - -1, -1, -1, -1, -1, -1, -1, 489, 490, -1, - -1, -1, -1, -1, -1, -1, 498, -1, -1, -1, - -1, -1, -1, 505, 506, 3, 4, 5, 6, 7, - 8, 9, 10, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, - -1, 29, 30, 31, -1, -1, -1, -1, 36, -1, - -1, 39, 40, -1, 42, 43, 44, 45, 46, 47, - 48, -1, 50, 51, 52, 53, -1, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - -1, 69, 70, 71, 72, 73, -1, 75, -1, 77, - 78, 79, 80, 81, 82, 83, 84, 85, 86, -1, - 88, 89, 90, 91, 92, 93, -1, 95, 96, 97, - 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - -1, 119, 120, 121, 122, 123, 124, -1, 126, 127, - 128, 129, 130, -1, -1, 133, 134, 135, 136, 137, - -1, 139, 140, 141, -1, 143, -1, 145, -1, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, -1, 161, 162, 163, 164, -1, 166, -1, - 168, 169, -1, 171, 172, 173, 174, -1, 176, -1, - 178, -1, 180, 181, 182, -1, 184, 185, 186, 187, - 188, 189, 190, -1, 192, 193, 194, 195, -1, 197, - 198, 199, 200, 201, 202, -1, 204, 205, 206, 207, - 208, 209, 210, 211, 212, 213, -1, 215, -1, 217, - -1, -1, 220, 221, 222, 223, 224, 225, 226, 227, - -1, -1, 230, 231, 232, -1, -1, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, - 268, 269, 270, -1, 272, 273, -1, 275, 276, 277, - 278, 279, 280, 281, 282, -1, 284, 285, -1, -1, - 288, 289, 290, -1, -1, 293, 294, 295, 296, 297, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, -1, 310, 311, 312, 313, 314, 315, 316, 317, - 318, -1, 320, 321, 322, 323, 324, 325, -1, 327, - 328, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, - 348, -1, 350, 351, 352, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - -1, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, -1, 381, 382, 383, 384, -1, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, -1, 403, 404, -1, 406, 407, - 408, 409, 410, 411, 412, -1, 414, 415, -1, -1, - 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 430, 431, -1, -1, 434, 435, 436, 437, - 438, 439, -1, 441, 442, 443, 444, 445, 446, 447, - -1, 449, 450, 451, 452, 453, 454, 455, -1, -1, - 458, -1, -1, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 478, 479, 480, 481, -1, -1, -1, -1, -1, -1, - -1, 489, 490, 3, -1, -1, -1, -1, 496, -1, - 498, -1, -1, -1, -1, 503, -1, 505, 506, -1, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, -1, 37, -1, 39, - 40, -1, 42, 43, 44, -1, 46, 47, 48, 49, - 50, -1, 52, 53, -1, 55, 56, 57, 58, 59, - 60, -1, -1, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, -1, -1, 77, 78, 79, - 80, 81, 82, -1, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, 95, 96, 97, 98, -1, - -1, -1, -1, -1, -1, -1, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, -1, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, -1, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, -1, - -1, 171, 172, 173, 174, -1, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, -1, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, -1, -1, - 220, 221, 222, 223, 224, 225, 226, 227, -1, -1, - 230, 231, 232, -1, -1, 235, 236, 237, -1, -1, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, -1, 272, 273, -1, 275, -1, 277, 278, 279, - 280, 281, 282, -1, 284, 285, -1, -1, 288, 289, - 290, -1, -1, 293, 294, -1, 296, -1, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, -1, 369, - 370, 371, 372, 373, -1, 375, 376, 377, 378, 379, - -1, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, -1, 406, 407, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, -1, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, -1, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - -1, 451, 452, 453, 454, 455, -1, -1, 458, -1, - -1, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, -1, 3, -1, 5, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 499, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, -1, -1, -1, 39, - 40, -1, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, -1, 55, 56, 57, 58, 59, - 60, -1, 62, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, 75, -1, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, -1, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, -1, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, 169, - -1, 171, 172, 173, 174, 175, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, -1, - 230, 231, 232, 233, -1, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, -1, 272, 273, 274, 275, -1, 277, 278, 279, - 280, 281, 282, -1, 284, 285, -1, 287, 288, 289, - 290, -1, -1, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, 405, 406, 407, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, -1, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, 439, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - 450, 451, 452, 453, 454, 455, -1, -1, 458, -1, - 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, -1, 3, 484, 5, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 498, -1, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, -1, -1, -1, 39, - 40, -1, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, -1, 55, 56, 57, 58, 59, - 60, -1, 62, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, 75, -1, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, 95, 96, 97, 98, 99, - 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, -1, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, -1, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, 169, - -1, 171, 172, 173, 174, 175, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, 228, -1, - 230, 231, 232, 233, -1, 235, 236, 237, 238, 239, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, -1, 272, 273, 274, 275, -1, 277, 278, 279, - 280, 281, 282, -1, 284, 285, -1, 287, 288, 289, - 290, -1, -1, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, -1, 369, - 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, -1, 406, 407, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, -1, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, 439, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - 450, 451, 452, 453, 454, 455, -1, -1, 458, -1, - -1, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, 3, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 498, 20, - 21, 22, 23, 24, 25, 26, 27, -1, 29, 30, - 31, -1, -1, -1, -1, -1, -1, -1, 39, 40, - -1, 42, 43, 44, 45, 46, 47, 48, 49, 50, - 51, 52, 53, -1, 55, 56, 57, 58, 59, 60, - -1, 62, 63, 64, 65, 66, 67, -1, 69, 70, - 71, 72, 73, -1, 75, -1, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, -1, 88, 89, 90, - 91, 92, 93, -1, 95, 96, 97, 98, 99, 100, - 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, -1, 117, -1, 119, 120, - 121, 122, 123, 124, -1, 126, 127, 128, 129, 130, - -1, -1, 133, 134, 135, 136, 137, -1, 139, 140, - 141, -1, 143, 144, 145, -1, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, -1, 159, -1, - 161, 162, 163, 164, -1, 166, -1, 168, 169, -1, - 171, 172, 173, 174, 175, 176, -1, 178, -1, 180, - 181, 182, -1, 184, 185, 186, 187, 188, 189, 190, - 191, 192, 193, 194, 195, -1, 197, 198, 199, 200, - 201, 202, -1, 204, 205, 206, 207, 208, 209, 210, - 211, 212, 213, -1, 215, -1, 217, 218, 219, 220, - 221, 222, 223, 224, 225, 226, 227, -1, -1, 230, - 231, 232, 233, -1, 235, 236, 237, 238, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, - -1, 272, 273, 274, 275, -1, 277, 278, 279, 280, - 281, 282, -1, 284, 285, -1, -1, 288, 289, 290, - -1, -1, 293, 294, 295, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, -1, 310, - 311, 312, 313, 314, 315, 316, 317, 318, -1, 320, - 321, 322, 323, 324, 325, -1, 327, 328, 329, 330, - 331, 332, 333, 334, -1, 336, 337, 338, 339, 340, - 341, 342, 343, 344, 345, 346, 347, 348, -1, 350, - 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 364, 365, 366, 367, -1, 369, 370, - 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, - 381, 382, 383, 384, -1, 386, 387, 388, 389, 390, - 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, - 401, -1, 403, 404, -1, 406, 407, 408, 409, 410, - 411, 412, -1, 414, 415, -1, -1, 418, 419, 420, - 421, 422, -1, 424, 425, 426, 427, 428, 429, 430, - 431, -1, -1, 434, 435, 436, 437, 438, 439, -1, - 441, 442, 443, 444, 445, 446, 447, -1, 449, 450, - 451, 452, 453, 454, 455, -1, -1, 458, -1, -1, - 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, - 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, - 481, 3, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 498, 20, 21, - 22, 23, 24, 25, 26, 27, -1, 29, 30, 31, - -1, -1, -1, -1, -1, -1, -1, 39, 40, -1, - 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, -1, 55, 56, 57, 58, 59, 60, -1, - 62, 63, 64, 65, 66, 67, -1, 69, 70, 71, - 72, 73, -1, 75, -1, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, -1, 88, 89, 90, 91, - 92, 93, -1, 95, 96, 97, 98, 99, 100, 101, + 482, 483, -1, -1, -1, -1, -1, -1, 490, 491, + -1, -1, -1, -1, -1, 497, -1, 499, 500, -1, + -1, -1, 504, -1, 506, 507, 3, 4, 5, 6, + 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, -1, 30, 31, 32, -1, -1, -1, -1, + 37, -1, -1, 40, 41, -1, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, 234, -1, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, + 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, -1, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, -1, 404, 405, -1, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, + -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, -1, -1, -1, + -1, -1, -1, 490, 491, -1, -1, -1, -1, -1, + 497, -1, 499, -1, -1, -1, -1, 504, -1, 506, + 507, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, -1, 30, 31, + 32, -1, -1, -1, -1, 37, -1, -1, 40, 41, + -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, -1, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, -1, 70, 71, + 72, 73, 74, -1, 76, -1, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, -1, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, -1, 117, -1, 119, 120, 121, - 122, 123, 124, -1, 126, 127, 128, 129, 130, -1, - -1, 133, 134, 135, 136, 137, -1, 139, 140, 141, - -1, 143, 144, 145, -1, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, -1, 159, -1, 161, - 162, 163, 164, -1, 166, -1, 168, 169, -1, 171, - 172, 173, 174, 175, 176, -1, 178, -1, 180, 181, - 182, -1, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, -1, 197, 198, 199, 200, 201, - 202, -1, 204, 205, 206, 207, 208, 209, 210, 211, - 212, 213, -1, 215, -1, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, -1, -1, 230, 231, - 232, 233, -1, 235, 236, 237, 238, 239, 240, 241, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, + 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, + 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, + 182, 183, -1, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, -1, 198, 199, 200, 201, + 202, 203, -1, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, -1, 216, -1, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, -1, -1, 231, + 232, 233, 234, -1, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, 270, -1, - 272, 273, 274, 275, -1, 277, 278, 279, 280, 281, - 282, -1, 284, 285, -1, -1, 288, 289, 290, -1, - -1, 293, 294, 295, 296, 297, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, -1, 310, 311, - 312, 313, 314, 315, 316, 317, 318, -1, 320, 321, - 322, 323, 324, 325, -1, 327, 328, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 346, 347, 348, -1, 350, 351, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, + -1, -1, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, -1, 311, + 312, 313, 314, 315, 316, 317, 318, 319, -1, 321, + 322, 323, 324, 325, 326, -1, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, -1, 369, 370, 371, + 362, 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, - 382, 383, 384, -1, 386, 387, 388, 389, 390, 391, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - -1, 403, 404, -1, 406, 407, 408, 409, 410, 411, - 412, -1, 414, 415, -1, -1, 418, 419, 420, 421, - 422, -1, 424, 425, 426, 427, 428, 429, 430, 431, - -1, -1, 434, 435, 436, 437, 438, 439, -1, 441, - 442, 443, 444, 445, 446, 447, -1, 449, 450, 451, - 452, 453, 454, 455, -1, -1, 458, -1, -1, 461, + 402, -1, 404, 405, -1, 407, 408, 409, 410, 411, + 412, 413, -1, 415, 416, -1, -1, 419, 420, 421, + 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, + 432, -1, -1, 435, 436, 437, 438, 439, 440, -1, + 442, 443, 444, 445, 446, 447, 448, -1, 450, 451, + 452, 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, - 3, 4, 5, -1, -1, -1, 9, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 498, 20, 21, 22, - 23, 24, 25, 26, 27, -1, 29, 30, 31, -1, - -1, -1, -1, -1, -1, -1, 39, 40, -1, 42, - 43, 44, -1, 46, 47, 48, 49, 50, -1, 52, - 53, -1, 55, 56, 57, 58, 59, 60, -1, -1, - 63, 64, 65, 66, 67, -1, 69, 70, 71, 72, - 73, -1, -1, -1, 77, 78, 79, 80, 81, 82, - -1, 84, 85, 86, -1, 88, 89, 90, 91, 92, - 93, -1, -1, 96, 97, 98, -1, -1, -1, -1, - -1, -1, -1, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, -1, 117, -1, 119, 120, 121, 122, - 123, 124, -1, 126, 127, 128, 129, 130, -1, -1, - 133, 134, 135, 136, 137, -1, 139, 140, 141, -1, - 143, 144, 145, -1, 147, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158, 159, -1, 161, 162, - 163, 164, -1, 166, -1, 168, -1, -1, -1, 172, - 173, 174, -1, 176, -1, 178, -1, 180, 181, 182, - -1, 184, 185, 186, 187, 188, 189, 190, -1, 192, - 193, 194, 195, -1, 197, 198, 199, 200, 201, 202, - -1, 204, -1, 206, 207, 208, 209, 210, 211, 212, - 213, -1, 215, -1, 217, -1, -1, 220, -1, 222, - 223, 224, 225, 226, 227, -1, -1, 230, -1, 232, - -1, -1, 235, 236, 237, -1, -1, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, -1, 266, 267, 268, 269, 270, -1, 272, - 273, -1, 275, -1, 277, 278, 279, 280, 281, 282, - -1, 284, 285, 286, -1, 288, 289, 290, -1, -1, - 293, 294, -1, 296, -1, 298, 299, 300, 301, 302, - 303, 304, 305, 306, 307, 308, -1, 310, 311, 312, - 313, 314, 315, 316, 317, 318, -1, 320, 321, 322, - 323, 324, 325, -1, 327, 328, 329, 330, 331, 332, - 333, 334, -1, 336, 337, 338, 339, 340, 341, 342, - 343, 344, 345, 346, 347, 348, -1, 350, 351, -1, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 364, 365, 366, 367, -1, 369, 370, 371, 372, - 373, -1, 375, 376, 377, 378, 379, -1, 381, 382, - 383, 384, -1, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 397, 398, 399, 400, 401, -1, - 403, 404, -1, 406, -1, 408, 409, 410, 411, 412, - -1, 414, 415, -1, -1, 418, 419, 420, 421, 422, - 423, 424, 425, 426, 427, 428, 429, 430, 431, -1, - -1, 434, 435, 436, 437, 438, -1, -1, 441, 442, - 443, 444, 445, 446, 447, -1, 449, -1, 451, 452, - 453, 454, 455, -1, -1, 458, -1, -1, 461, 462, - 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, - 473, 474, 475, 476, 477, 478, 479, 480, 481, 3, - -1, -1, -1, -1, -1, -1, 489, 490, 491, -1, - -1, -1, -1, -1, -1, 498, 20, 21, 22, 23, - 24, 25, 26, 27, -1, 29, 30, 31, 32, 33, - -1, -1, -1, -1, -1, 39, 40, -1, 42, 43, - 44, -1, 46, 47, 48, 49, 50, -1, 52, 53, - -1, 55, 56, 57, 58, 59, 60, -1, -1, 63, - 64, 65, 66, 67, -1, 69, 70, 71, 72, 73, - -1, -1, -1, 77, 78, 79, 80, 81, 82, -1, - 84, 85, 86, -1, 88, 89, 90, 91, 92, 93, - -1, -1, 96, 97, 98, -1, -1, -1, -1, -1, - -1, -1, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, -1, 117, -1, 119, 120, 121, 122, 123, - 124, -1, 126, 127, 128, 129, 130, -1, -1, 133, - 134, 135, 136, 137, -1, 139, 140, 141, -1, 143, - 144, 145, -1, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, -1, 159, -1, 161, 162, 163, - 164, -1, 166, -1, 168, -1, -1, -1, 172, 173, - 174, -1, 176, -1, 178, -1, 180, 181, 182, -1, - 184, 185, 186, 187, 188, 189, 190, -1, 192, 193, - 194, 195, -1, 197, 198, 199, 200, 201, 202, -1, - 204, -1, 206, 207, 208, 209, 210, 211, 212, 213, - -1, 215, -1, 217, -1, -1, 220, -1, 222, 223, - 224, 225, 226, 227, -1, -1, 230, -1, 232, -1, - -1, 235, 236, 237, -1, -1, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, -1, 266, 267, 268, 269, 270, -1, 272, 273, - -1, 275, -1, 277, 278, 279, 280, 281, 282, -1, - 284, 285, -1, -1, 288, 289, 290, -1, -1, 293, - 294, -1, 296, -1, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, -1, 310, 311, 312, 313, - 314, 315, 316, 317, 318, -1, 320, 321, 322, 323, - 324, 325, -1, 327, 328, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, -1, 350, 351, -1, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, - -1, 375, 376, 377, 378, 379, -1, 381, 382, 383, - 384, -1, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, -1, 403, - 404, 405, 406, -1, 408, 409, 410, 411, 412, -1, - 414, 415, -1, -1, 418, 419, 420, 421, 422, -1, - 424, 425, 426, 427, 428, 429, 430, 431, -1, -1, - 434, 435, 436, 437, 438, -1, -1, 441, 442, 443, - 444, 445, 446, 447, -1, 449, -1, 451, 452, 453, - 454, 455, -1, -1, 458, -1, 460, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 3, -1, - 484, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 498, 20, 21, 22, 23, 24, - 25, 26, 27, 28, 29, 30, 31, -1, -1, -1, - -1, -1, -1, -1, 39, 40, -1, 42, 43, 44, - -1, 46, 47, 48, 49, 50, -1, 52, 53, -1, - 55, 56, 57, 58, 59, 60, -1, -1, 63, 64, - 65, 66, 67, -1, 69, 70, 71, 72, 73, -1, - -1, -1, 77, 78, 79, 80, 81, 82, -1, 84, - 85, 86, -1, 88, 89, 90, 91, 92, 93, -1, - -1, 96, 97, 98, -1, -1, -1, -1, -1, -1, - -1, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, -1, 117, -1, 119, 120, 121, 122, 123, 124, - -1, 126, 127, 128, 129, 130, -1, -1, 133, 134, - 135, 136, 137, -1, 139, 140, 141, -1, 143, 144, - 145, -1, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, -1, 159, -1, 161, 162, 163, 164, - -1, 166, -1, 168, -1, -1, -1, 172, 173, 174, - -1, 176, -1, 178, -1, 180, 181, 182, -1, 184, - 185, 186, 187, 188, 189, 190, -1, 192, 193, 194, - 195, -1, 197, 198, 199, 200, 201, 202, -1, 204, - -1, 206, 207, 208, 209, 210, 211, 212, 213, -1, - 215, -1, 217, -1, -1, 220, -1, 222, 223, 224, - 225, 226, 227, -1, -1, 230, -1, 232, -1, -1, - 235, 236, 237, -1, -1, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - -1, 266, 267, 268, 269, 270, -1, 272, 273, -1, - 275, -1, 277, 278, 279, 280, 281, 282, -1, 284, - 285, -1, -1, 288, 289, 290, -1, -1, 293, 294, - -1, 296, -1, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, -1, 310, 311, 312, 313, 314, - 315, 316, 317, 318, -1, 320, 321, 322, 323, 324, - 325, -1, 327, 328, 329, 330, 331, 332, 333, 334, - -1, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, -1, 350, 351, -1, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, 368, 369, 370, 371, 372, 373, -1, - 375, 376, 377, 378, 379, -1, 381, 382, 383, 384, - -1, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 397, 398, 399, 400, 401, -1, 403, 404, - 405, 406, -1, 408, 409, 410, 411, 412, -1, 414, - 415, -1, -1, 418, 419, 420, 421, 422, -1, 424, - 425, 426, 427, 428, 429, 430, 431, -1, -1, 434, - 435, 436, 437, 438, -1, -1, 441, 442, 443, 444, - 445, 446, 447, -1, 449, -1, 451, 452, 453, 454, - 455, -1, -1, 458, -1, 460, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 478, 479, 480, 481, 3, -1, 484, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 498, 20, 21, 22, 23, 24, 25, - 26, 27, -1, 29, 30, 31, -1, -1, -1, -1, - -1, -1, -1, 39, 40, -1, 42, 43, 44, -1, - 46, 47, 48, 49, 50, -1, 52, 53, -1, 55, - 56, 57, 58, 59, 60, -1, -1, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, -1, -1, - -1, 77, 78, 79, 80, 81, 82, -1, 84, 85, - 86, -1, 88, 89, 90, 91, 92, 93, -1, -1, - 96, 97, 98, -1, -1, -1, -1, -1, -1, -1, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - -1, 117, -1, 119, 120, 121, 122, 123, 124, -1, - 126, 127, 128, 129, 130, -1, -1, 133, 134, 135, - 136, 137, -1, 139, 140, 141, -1, 143, 144, 145, - -1, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, -1, 159, -1, 161, 162, 163, 164, -1, - 166, -1, 168, -1, -1, -1, 172, 173, 174, -1, - 176, -1, 178, -1, 180, 181, 182, -1, 184, 185, - 186, 187, 188, 189, 190, -1, 192, 193, 194, 195, - -1, 197, 198, 199, 200, 201, 202, -1, 204, -1, - 206, 207, 208, 209, 210, 211, 212, 213, -1, 215, - -1, 217, -1, -1, 220, -1, 222, 223, 224, 225, - 226, 227, -1, -1, 230, -1, 232, -1, -1, 235, - 236, 237, -1, -1, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, -1, - 266, 267, 268, 269, 270, -1, 272, 273, -1, 275, - -1, 277, 278, 279, 280, 281, 282, -1, 284, 285, - -1, -1, 288, 289, 290, -1, -1, 293, 294, -1, - 296, -1, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, -1, 310, 311, 312, 313, 314, 315, - 316, 317, 318, -1, 320, 321, 322, 323, 324, 325, - -1, 327, 328, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, 350, 351, -1, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, 368, 369, 370, 371, 372, 373, -1, 375, - 376, 377, 378, 379, -1, 381, 382, 383, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, -1, 403, 404, 405, - 406, -1, 408, 409, 410, 411, 412, -1, 414, 415, - -1, -1, 418, 419, 420, 421, 422, -1, 424, 425, - 426, 427, 428, 429, 430, 431, -1, -1, 434, 435, - 436, 437, 438, -1, -1, 441, 442, 443, 444, 445, - 446, 447, -1, 449, -1, 451, 452, 453, 454, 455, - -1, -1, 458, -1, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, -1, 3, 484, 5, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 498, -1, 20, 21, 22, 23, 24, 25, - 26, 27, -1, 29, 30, 31, -1, -1, -1, -1, - -1, -1, -1, 39, 40, -1, 42, 43, 44, -1, - 46, 47, 48, 49, 50, -1, 52, 53, -1, 55, - 56, 57, 58, 59, 60, -1, -1, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, -1, -1, - -1, 77, 78, 79, 80, 81, 82, -1, 84, 85, - 86, -1, 88, 89, 90, 91, 92, 93, -1, -1, - 96, 97, 98, -1, -1, -1, -1, -1, -1, -1, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - -1, 117, -1, 119, 120, 121, 122, 123, 124, -1, - 126, 127, 128, 129, 130, -1, -1, 133, 134, 135, - 136, 137, -1, 139, 140, 141, -1, 143, 144, 145, - -1, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, -1, 159, -1, 161, 162, 163, 164, -1, - 166, -1, 168, -1, -1, -1, 172, 173, 174, -1, - 176, -1, 178, -1, 180, 181, 182, -1, 184, 185, - 186, 187, 188, 189, 190, -1, 192, 193, 194, 195, - -1, 197, 198, 199, 200, 201, 202, -1, 204, -1, - 206, 207, 208, 209, 210, 211, 212, 213, -1, 215, - -1, 217, -1, -1, 220, -1, 222, 223, 224, 225, - 226, 227, -1, -1, 230, -1, 232, -1, -1, 235, - 236, 237, -1, -1, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, -1, - 266, 267, 268, 269, 270, -1, 272, 273, -1, 275, - -1, 277, 278, 279, 280, 281, 282, -1, 284, 285, - -1, -1, 288, 289, 290, -1, -1, 293, 294, -1, - 296, -1, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, -1, 310, 311, 312, 313, 314, 315, - 316, 317, 318, -1, 320, 321, 322, 323, 324, 325, - -1, 327, 328, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, 350, 351, -1, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, -1, 369, 370, 371, 372, 373, -1, 375, - 376, 377, 378, 379, -1, 381, 382, 383, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, -1, 403, 404, -1, - 406, -1, 408, 409, 410, 411, 412, -1, 414, 415, - -1, -1, 418, 419, 420, 421, 422, -1, 424, 425, - 426, 427, 428, 429, 430, 431, -1, -1, 434, 435, - 436, 437, 438, -1, -1, 441, 442, 443, 444, 445, - 446, 447, -1, 449, -1, 451, 452, 453, 454, 455, - -1, -1, 458, -1, -1, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, 3, -1, 5, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 498, 20, 21, 22, 23, 24, 25, 26, - 27, -1, 29, 30, 31, -1, -1, -1, -1, -1, - -1, -1, 39, 40, -1, 42, 43, 44, -1, 46, - 47, 48, 49, 50, -1, 52, 53, -1, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, -1, 69, 70, 71, 72, 73, -1, -1, -1, - 77, 78, 79, 80, 81, 82, -1, 84, 85, 86, - -1, 88, 89, 90, 91, 92, 93, -1, -1, 96, - 97, 98, -1, -1, -1, -1, -1, -1, -1, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, -1, - 117, -1, 119, 120, 121, 122, 123, 124, -1, 126, - 127, 128, 129, 130, -1, -1, 133, 134, 135, 136, - 137, -1, 139, 140, 141, -1, 143, 144, 145, -1, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, -1, 159, -1, 161, 162, 163, 164, -1, 166, - -1, 168, -1, -1, -1, 172, 173, 174, -1, 176, - -1, 178, -1, 180, 181, 182, -1, 184, 185, 186, - 187, 188, 189, 190, -1, 192, 193, 194, 195, -1, - 197, 198, 199, 200, 201, 202, -1, 204, -1, 206, - 207, 208, 209, 210, 211, 212, 213, -1, 215, -1, - 217, -1, -1, 220, -1, 222, 223, 224, 225, 226, - 227, -1, -1, 230, -1, 232, -1, -1, 235, 236, - 237, -1, -1, 240, 241, 242, 243, 244, 245, 246, + 482, 483, -1, -1, -1, -1, -1, -1, 490, 491, + -1, -1, -1, -1, -1, 497, -1, 499, 500, -1, + -1, -1, 504, -1, 506, 507, 3, 4, 5, 6, + 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, -1, 30, 31, 32, -1, -1, -1, -1, + 37, -1, -1, 40, 41, -1, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, 171, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, 234, -1, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, -1, 266, - 267, 268, 269, 270, -1, 272, 273, -1, 275, -1, - 277, 278, 279, 280, 281, 282, -1, 284, 285, -1, - -1, 288, 289, 290, -1, -1, 293, 294, -1, 296, - -1, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, -1, 310, 311, 312, 313, 314, 315, 316, - 317, 318, -1, 320, 321, 322, 323, 324, 325, -1, - 327, 328, 329, 330, 331, 332, 333, 334, -1, 336, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, - 347, 348, -1, 350, 351, -1, 353, 354, 355, 356, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, - 367, -1, 369, 370, 371, 372, 373, -1, 375, 376, - 377, 378, 379, -1, 381, 382, 383, 384, -1, 386, + 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 397, 398, 399, 400, 401, -1, 403, 404, -1, 406, - -1, 408, 409, 410, 411, 412, -1, 414, 415, -1, - -1, 418, 419, 420, 421, 422, -1, 424, 425, 426, - 427, 428, 429, 430, 431, -1, -1, 434, 435, 436, - 437, 438, -1, -1, 441, 442, 443, 444, 445, 446, - 447, -1, 449, -1, 451, 452, 453, 454, 455, -1, - -1, 458, -1, -1, 461, 462, 463, 464, 465, 466, + 397, 398, 399, 400, 401, 402, -1, 404, 405, -1, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, -1, 450, 451, 452, 453, 454, 455, 456, + -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, - 477, 478, 479, 480, 481, 3, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 498, 20, 21, 22, 23, 24, 25, 26, 27, - -1, 29, 30, 31, -1, -1, -1, -1, -1, -1, - -1, 39, 40, -1, 42, 43, 44, -1, 46, 47, - 48, 49, 50, -1, 52, 53, -1, 55, 56, 57, - 58, 59, 60, -1, -1, 63, 64, 65, 66, 67, - -1, 69, 70, 71, 72, 73, -1, -1, -1, 77, - 78, 79, 80, 81, 82, -1, 84, 85, 86, -1, - 88, 89, 90, 91, 92, 93, -1, -1, 96, 97, - 98, -1, -1, -1, -1, -1, -1, -1, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, -1, 117, - -1, 119, 120, 121, 122, 123, 124, -1, 126, 127, - 128, 129, 130, -1, -1, 133, 134, 135, 136, 137, - -1, 139, 140, 141, -1, 143, 144, 145, -1, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - -1, 159, -1, 161, 162, 163, 164, -1, 166, -1, - 168, -1, -1, -1, 172, 173, 174, -1, 176, -1, - 178, -1, 180, 181, 182, -1, 184, 185, 186, 187, - 188, 189, 190, -1, 192, 193, 194, 195, -1, 197, - 198, 199, 200, 201, 202, -1, 204, -1, 206, 207, - 208, 209, 210, 211, 212, 213, -1, 215, -1, 217, - -1, -1, 220, -1, 222, 223, 224, 225, 226, 227, - -1, -1, 230, -1, 232, -1, -1, 235, 236, 237, - -1, -1, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, -1, 266, 267, - 268, 269, 270, -1, 272, 273, -1, 275, -1, 277, - 278, 279, 280, 281, 282, -1, 284, 285, -1, -1, - 288, 289, 290, -1, -1, 293, 294, -1, 296, -1, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, -1, 310, 311, 312, 313, 314, 315, 316, 317, - 318, -1, 320, 321, 322, 323, 324, 325, -1, 327, - 328, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, - 348, -1, 350, 351, -1, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - -1, 369, 370, 371, 372, 373, -1, 375, 376, 377, - 378, 379, -1, 381, 382, 383, 384, -1, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, -1, 403, 404, -1, 406, -1, - 408, 409, 410, 411, 412, -1, 414, 415, -1, -1, - 418, 419, 420, 421, 422, -1, 424, 425, 426, 427, - 428, 429, 430, 431, -1, -1, 434, 435, 436, 437, - 438, -1, -1, 441, 442, 443, 444, 445, 446, 447, - -1, 449, -1, 451, 452, 453, 454, 455, -1, -1, - 458, -1, -1, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 478, 479, 480, 481, 3, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 498, 20, 21, 22, 23, 24, 25, 26, 27, -1, - 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, - 39, 40, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, -1, 52, 53, -1, 55, 56, 57, 58, - 59, 60, -1, -1, 63, 64, 65, 66, 67, -1, - 69, 70, 71, 72, 73, -1, -1, -1, 77, 78, - 79, 80, 81, 82, -1, 84, 85, 86, -1, 88, - 89, 90, 91, 92, 93, -1, -1, 96, 97, 98, - -1, -1, -1, -1, -1, -1, -1, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, -1, 117, -1, - 119, 120, 121, 122, 123, 124, -1, 126, 127, 128, - 129, 130, -1, -1, 133, 134, 135, 136, 137, -1, - 139, 140, 141, -1, 143, 144, 145, -1, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, -1, - 159, -1, 161, 162, 163, 164, -1, 166, -1, 168, - -1, -1, -1, 172, 173, 174, -1, 176, -1, 178, - -1, 180, 181, 182, -1, 184, 185, 186, 187, 188, - 189, 190, -1, 192, 193, 194, 195, -1, 197, 198, - 199, 200, 201, 202, -1, 204, -1, 206, 207, 208, - 209, 210, 211, 212, 213, -1, 215, -1, 217, -1, - -1, 220, -1, 222, 223, 224, 225, 226, 227, -1, - -1, 230, -1, 232, -1, -1, 235, 236, 237, -1, - -1, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, -1, 266, 267, 268, - 269, 270, -1, 272, 273, -1, 275, -1, 277, 278, - 279, 280, 281, 282, -1, 284, 285, -1, -1, 288, - 289, 290, -1, -1, 293, 294, -1, 296, -1, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - -1, 310, 311, 312, 313, 314, 315, 316, 317, 318, - -1, 320, 321, 322, 323, 324, 325, -1, 327, 328, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, - -1, 350, 351, -1, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 364, 365, 366, 367, -1, - 369, 370, 371, 372, 373, -1, 375, 376, 377, 378, - 379, -1, 381, 382, 383, 384, -1, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, - 399, 400, 401, -1, 403, 404, -1, 406, -1, 408, - 409, 410, 411, 412, -1, 414, 415, -1, -1, 418, - 419, 420, 421, 422, -1, 424, 425, 426, 427, 428, - 429, 430, 431, -1, -1, 434, 435, 436, 437, 438, - -1, -1, 441, 442, 443, 444, 445, 446, 447, -1, - 449, -1, 451, 452, 453, 454, 455, -1, -1, 458, - -1, -1, 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, - 479, 480, 481, 3, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 498, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, -1, -1, -1, 39, - 40, -1, 42, 43, 44, -1, 46, 47, 48, 49, - 50, -1, 52, 53, -1, 55, 56, 57, 58, 59, - 60, -1, -1, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, -1, -1, 77, 78, 79, - 80, 81, 82, -1, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, -1, 96, 97, 98, -1, - -1, -1, -1, -1, -1, -1, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, -1, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, -1, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, -1, - -1, -1, 172, 173, 174, -1, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, -1, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, -1, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, -1, -1, - 220, -1, 222, 223, 224, 225, 226, 227, -1, -1, - 230, -1, 232, -1, -1, 235, 236, 237, -1, -1, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, -1, 266, 267, 268, 269, - 270, -1, 272, 273, -1, 275, -1, 277, 278, 279, - 280, 281, 282, -1, 284, 285, -1, -1, 288, 289, - 290, -1, -1, 293, 294, -1, 296, -1, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, -1, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, -1, 369, - 370, 371, 372, 373, -1, 375, 376, 377, 378, 379, - -1, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, -1, 406, -1, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, -1, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, -1, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - -1, 451, 452, 453, 454, 455, -1, -1, 458, -1, - -1, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, -1, -1, -1, -1, 3, 4, 5, -1, - -1, 8, 9, -1, -1, -1, -1, -1, 498, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, - 47, 48, -1, 50, 51, 52, 53, 54, 55, 56, + 477, 478, 479, 480, 481, 482, 483, -1, -1, -1, + -1, -1, -1, 490, 491, -1, -1, -1, -1, -1, + 497, -1, 499, -1, -1, -1, -1, 504, -1, 506, + 507, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, -1, 30, 31, + 32, -1, -1, -1, -1, 37, -1, -1, 40, 41, + -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, -1, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, -1, 70, 71, + 72, 73, 74, -1, 76, -1, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, -1, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, + 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, + 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, + 182, 183, -1, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, -1, 198, 199, 200, 201, + 202, 203, -1, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, -1, 216, -1, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, -1, -1, 231, + 232, 233, 234, -1, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, + -1, -1, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, -1, 311, + 312, 313, 314, 315, 316, 317, 318, 319, -1, 321, + 322, 323, 324, 325, 326, -1, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, -1, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 368, -1, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 402, -1, 404, 405, 406, 407, 408, 409, 410, 411, + 412, 413, -1, 415, 416, -1, -1, 419, 420, 421, + 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, + 432, -1, -1, 435, 436, 437, 438, 439, 440, -1, + 442, 443, 444, 445, 446, 447, 448, -1, 450, 451, + 452, 453, 454, 455, 456, -1, -1, 459, -1, -1, + 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, -1, -1, -1, -1, -1, -1, 490, 491, + -1, -1, -1, -1, -1, 497, -1, 499, -1, -1, + -1, -1, 504, -1, 506, 507, 3, 4, 5, 6, + 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, -1, 30, 31, 32, -1, -1, -1, -1, + 37, -1, -1, 40, 41, -1, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, -1, 74, 75, 76, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, -1, 152, 153, 154, 155, 156, - -1, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, - 177, 178, 179, -1, -1, 182, 183, 184, 185, 186, + 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, 205, -1, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, 234, -1, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, - -1, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, -1, 295, 296, - 297, -1, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, -1, 313, 314, -1, 316, - 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, + 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, - 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, - 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, - 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, + 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 397, 398, 399, -1, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 417, 418, 419, -1, 421, -1, 423, 424, 425, 426, - 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 443, 444, 445, -1, - 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, - 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 478, 479, 480, 481, -1, 3, -1, 485, 486, - 487, 8, 489, 490, 491, 492, 493, 494, -1, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, - 27, -1, 29, 30, 31, -1, -1, -1, -1, -1, - -1, -1, 39, 40, -1, 42, 43, 44, -1, 46, - 47, 48, 49, 50, -1, 52, 53, -1, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, -1, 69, 70, 71, 72, 73, -1, -1, -1, - 77, 78, 79, 80, 81, 82, -1, 84, 85, 86, - -1, 88, 89, 90, 91, 92, 93, -1, -1, 96, - 97, 98, -1, -1, -1, -1, -1, -1, -1, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, -1, - 117, -1, 119, 120, 121, 122, 123, 124, -1, 126, - 127, 128, 129, 130, -1, -1, 133, 134, 135, 136, - 137, -1, 139, 140, 141, -1, 143, 144, 145, -1, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, -1, 159, -1, 161, 162, 163, 164, -1, 166, - -1, 168, -1, -1, -1, 172, 173, 174, -1, 176, - -1, 178, -1, 180, 181, 182, -1, 184, 185, 186, - 187, 188, 189, 190, -1, 192, 193, 194, 195, -1, - 197, 198, 199, 200, 201, 202, -1, 204, -1, 206, - 207, 208, 209, 210, 211, 212, 213, -1, 215, -1, - 217, -1, -1, 220, -1, 222, 223, 224, 225, 226, - 227, -1, -1, 230, -1, 232, -1, -1, 235, 236, - 237, -1, -1, 240, 241, 242, 243, 244, 245, 246, + 397, 398, 399, 400, 401, 402, -1, 404, 405, -1, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, -1, 450, 451, 452, 453, 454, 455, 456, + -1, 458, 459, -1, -1, 462, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, -1, -1, -1, + -1, -1, -1, 490, 491, -1, -1, -1, -1, -1, + 497, -1, 499, -1, -1, -1, -1, 504, -1, 506, + 507, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, -1, 30, 31, + 32, -1, -1, -1, -1, 37, -1, -1, 40, 41, + -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, -1, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, -1, 70, 71, + 72, 73, 74, -1, 76, -1, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, -1, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, + 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, + 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, + 182, 183, -1, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, -1, 198, 199, 200, 201, + 202, 203, -1, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, -1, 216, -1, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, -1, -1, 231, + 232, 233, 234, -1, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, + -1, -1, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, -1, 311, + 312, 313, 314, 315, 316, 317, 318, 319, -1, 321, + 322, 323, 324, 325, 326, -1, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, -1, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 368, -1, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 402, -1, 404, 405, -1, 407, 408, 409, 410, 411, + 412, 413, -1, 415, 416, -1, -1, 419, 420, 421, + 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, + 432, -1, -1, 435, 436, 437, 438, 439, 440, -1, + 442, 443, 444, 445, 446, 447, 448, -1, 450, 451, + 452, 453, 454, 455, 456, -1, -1, 459, -1, -1, + 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, -1, -1, -1, -1, -1, -1, 490, 491, + -1, -1, -1, -1, -1, 497, -1, 499, -1, -1, + -1, -1, 504, -1, 506, 507, 3, 4, 5, 6, + 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, -1, 30, 31, 32, -1, -1, -1, -1, + 37, -1, -1, 40, 41, -1, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, 234, -1, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, -1, 266, - 267, 268, 269, 270, -1, 272, 273, -1, 275, -1, - 277, 278, 279, 280, 281, 282, -1, 284, 285, -1, - -1, 288, 289, 290, -1, -1, 293, 294, -1, 296, - -1, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, -1, 310, 311, 312, 313, 314, 315, 316, - 317, 318, -1, 320, 321, 322, 323, 324, 325, -1, - 327, 328, 329, 330, 331, 332, 333, 334, -1, 336, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, - 347, 348, -1, 350, 351, -1, 353, 354, 355, 356, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, - 367, -1, 369, 370, 371, 372, 373, -1, 375, 376, - 377, 378, 379, -1, 381, 382, 383, 384, -1, 386, + 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 397, 398, 399, 400, 401, -1, 403, 404, -1, 406, - -1, 408, 409, 410, 411, 412, -1, 414, 415, -1, - -1, 418, 419, 420, 421, 422, -1, 424, 425, 426, - 427, 428, 429, 430, 431, -1, -1, 434, 435, 436, - 437, 438, -1, -1, 441, 442, 443, 444, 445, 446, - 447, -1, 449, -1, 451, 452, 453, 454, 455, -1, - -1, 458, -1, -1, 461, 462, 463, 464, 465, 466, + 397, 398, 399, 400, 401, 402, -1, 404, 405, -1, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, -1, 450, 451, 452, 453, 454, 455, 456, + -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, - 477, 478, 479, 480, 481, -1, -1, -1, 485, 486, - 487, -1, 489, 490, 491, 492, 493, 494, 8, -1, - -1, 11, -1, -1, -1, 15, 16, 17, 18, 19, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 34, -1, -1, 8, -1, -1, - 11, -1, 42, -1, 15, 16, 17, 18, 19, 49, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, - -1, 42, 8, -1, 74, 11, -1, -1, 49, 15, - 16, 17, 18, 19, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, - -1, 8, -1, 74, 11, -1, 42, -1, 15, 16, - 17, 18, 19, 49, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, - -1, -1, -1, -1, -1, 42, -1, -1, 74, -1, - 8, -1, 49, 11, -1, -1, -1, 15, 16, 17, - 18, 19, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 34, 74, -1, -1, - -1, -1, -1, -1, 42, 175, -1, -1, -1, -1, - -1, 49, -1, -1, -1, -1, -1, -1, -1, -1, - 8, 191, -1, 11, -1, -1, 196, -1, 16, -1, - -1, -1, -1, -1, 175, -1, 74, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 218, 219, - 191, -1, -1, -1, 42, 196, -1, -1, -1, -1, - -1, 49, -1, 233, -1, -1, -1, -1, -1, 175, - -1, -1, -1, -1, -1, -1, -1, 218, 219, -1, - -1, -1, -1, -1, -1, 191, 74, -1, -1, -1, - 196, -1, 233, -1, -1, -1, -1, -1, 175, -1, - -1, 271, -1, -1, 274, -1, -1, -1, -1, -1, - -1, -1, 218, 219, 191, -1, -1, -1, 288, 196, - -1, 291, -1, -1, -1, -1, -1, 233, -1, -1, - 271, -1, -1, 274, -1, -1, -1, 175, -1, -1, - -1, 218, 219, -1, -1, -1, -1, 288, -1, -1, - 291, -1, -1, 191, -1, -1, 233, -1, 196, -1, - -1, -1, -1, -1, -1, 271, -1, -1, 274, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 218, 219, 288, -1, -1, 291, -1, 175, -1, -1, - -1, -1, -1, -1, 271, 233, -1, 274, -1, -1, - -1, -1, -1, 191, -1, -1, -1, -1, 196, -1, - 380, 288, -1, -1, 291, 8, -1, -1, 11, -1, - -1, -1, 15, 16, 17, 18, 19, -1, -1, -1, - -1, -1, -1, 271, -1, -1, 274, -1, -1, 380, - -1, 34, -1, -1, -1, 233, -1, -1, -1, 42, - 288, -1, -1, 291, -1, -1, 49, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 380, -1, -1, -1, -1, -1, - -1, 74, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 8, - 288, -1, 11, 380, -1, -1, 15, 16, 17, 18, - 19, -1, 482, -1, -1, 485, 486, 487, -1, 489, - 490, 491, 492, 493, 494, 34, -1, -1, -1, 499, - -1, -1, -1, 42, -1, -1, -1, -1, -1, -1, - 49, 482, 380, -1, 485, 486, 487, -1, 489, 490, - 491, 492, 493, 494, -1, -1, -1, -1, 499, -1, - -1, -1, -1, 8, -1, 74, 11, -1, -1, -1, - 15, 16, 17, 18, 19, -1, 482, -1, -1, 485, - 486, 487, 175, 489, 490, 491, 492, 493, 494, 34, - -1, -1, 380, 499, -1, -1, -1, 42, 191, -1, - -1, -1, -1, 196, 49, 482, -1, -1, 485, 486, - 487, -1, 489, 490, 491, 492, 493, 494, -1, -1, - -1, -1, 499, -1, 8, 218, 219, 11, -1, 74, - -1, 15, 16, 17, 18, 19, -1, -1, -1, -1, - 233, -1, -1, -1, 482, -1, -1, 485, 486, 487, - 34, 489, 490, 491, 492, 493, 494, -1, 42, -1, - -1, 499, -1, -1, -1, 49, 175, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 271, -1, - -1, 274, 191, -1, -1, -1, -1, 196, -1, -1, - 74, -1, -1, -1, 482, 288, -1, -1, 291, -1, - -1, 489, 490, 491, 492, 493, 494, -1, -1, 218, - 219, -1, -1, -1, -1, -1, -1, 50, -1, 52, - 53, -1, -1, -1, 233, -1, -1, -1, -1, -1, - 175, -1, 65, 66, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 191, -1, -1, 8, - -1, 196, 11, -1, -1, -1, 15, 16, 17, 18, - 19, -1, 271, -1, -1, 274, -1, -1, -1, -1, - -1, -1, -1, 218, 219, 34, -1, -1, -1, 288, - 113, 114, 291, 42, -1, -1, -1, 380, 233, -1, - 49, 175, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 135, -1, -1, -1, -1, 191, -1, -1, - 143, -1, 196, -1, -1, 74, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 271, -1, -1, 274, - 163, -1, -1, -1, 218, 219, -1, -1, -1, -1, - -1, -1, -1, 288, -1, -1, 291, -1, -1, 233, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 380, -1, -1, -1, -1, -1, -1, -1, 212, - 213, -1, -1, -1, -1, -1, -1, 271, -1, 482, - 274, -1, 485, 486, 487, -1, 489, 490, 491, 492, - 493, 494, 8, -1, 288, 11, 499, 291, -1, 15, - 16, 17, 18, 19, -1, -1, 175, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 34, -1, - -1, 264, 191, 266, -1, 380, 42, 196, -1, -1, - -1, -1, -1, 49, -1, -1, 279, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 218, - 219, -1, -1, -1, -1, -1, -1, -1, 74, -1, - -1, -1, -1, 482, 233, -1, 485, 486, 487, -1, - 489, 490, 491, 492, 493, 494, -1, -1, -1, -1, - 499, -1, -1, -1, -1, -1, 380, 330, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 271, -1, -1, 274, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, - -1, -1, 291, -1, -1, -1, -1, 482, -1, -1, - 485, 486, 487, -1, 489, 490, 491, 492, 493, 494, - 383, -1, -1, -1, 499, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 175, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 414, 415, -1, -1, 191, -1, -1, -1, -1, - 196, -1, -1, -1, -1, -1, -1, -1, 482, -1, - -1, 485, 486, 487, -1, 489, 490, 491, 492, 493, - 494, -1, 218, 219, 447, 499, -1, -1, -1, -1, - -1, 380, -1, -1, -1, -1, -1, 233, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 271, -1, -1, 274, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 288, -1, -1, 291, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 477, 478, 479, 480, 481, 482, 483, -1, -1, -1, + -1, -1, -1, 490, 491, -1, -1, -1, -1, -1, + 497, -1, 499, -1, -1, -1, -1, 504, -1, 506, + 507, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, -1, 30, 31, + 32, -1, -1, -1, -1, 37, -1, -1, 40, 41, + -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, -1, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, -1, 70, 71, + 72, 73, 74, -1, 76, -1, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, -1, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, + 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, + 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, + 182, 183, -1, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, -1, 198, 199, 200, 201, + 202, 203, -1, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, -1, 216, -1, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, -1, -1, 231, + 232, 233, 234, -1, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, + -1, -1, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, -1, 311, + 312, 313, 314, 315, 316, 317, 318, 319, -1, 321, + 322, 323, 324, 325, 326, -1, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, -1, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 368, -1, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 402, -1, 404, 405, -1, 407, 408, 409, 410, 411, + 412, 413, -1, 415, 416, -1, -1, 419, 420, 421, + 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, + 432, -1, -1, 435, 436, 437, 438, 439, 440, -1, + 442, 443, 444, 445, 446, 447, 448, -1, 450, 451, + 452, 453, 454, 455, 456, -1, -1, 459, -1, -1, + 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, -1, -1, -1, -1, -1, -1, 490, 491, + -1, -1, -1, -1, -1, 497, -1, 499, -1, -1, + -1, -1, 504, -1, 506, 507, 3, 4, 5, 6, + 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, -1, 30, 31, 32, -1, -1, -1, -1, + 37, -1, -1, 40, 41, -1, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, 234, -1, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, + 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, -1, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, -1, 404, 405, -1, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, -1, 450, 451, 452, 453, 454, 455, 456, + -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, -1, -1, -1, + -1, -1, -1, 490, 491, -1, -1, -1, -1, -1, + 497, -1, 499, -1, -1, -1, -1, 504, -1, 506, + 507, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, -1, 30, 31, + 32, -1, -1, -1, -1, 37, -1, -1, 40, 41, + -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, -1, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, -1, 70, 71, + 72, 73, 74, -1, 76, -1, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, -1, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, + 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, + 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, + 182, 183, -1, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, -1, 198, 199, 200, 201, + 202, 203, -1, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, -1, 216, -1, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, -1, -1, 231, + 232, 233, 234, -1, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, + -1, -1, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, -1, 311, + 312, 313, 314, 315, 316, 317, 318, 319, -1, 321, + 322, 323, 324, 325, 326, -1, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, -1, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 368, -1, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 402, -1, 404, 405, -1, 407, 408, 409, 410, 411, + 412, 413, -1, 415, 416, -1, -1, 419, 420, 421, + 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, + 432, -1, -1, 435, 436, 437, 438, 439, 440, -1, + 442, 443, 444, 445, 446, 447, 448, -1, 450, 451, + 452, 453, 454, 455, 456, -1, -1, 459, -1, -1, + 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, -1, -1, -1, -1, -1, -1, 490, 491, + -1, -1, -1, -1, -1, 497, -1, 499, -1, -1, + -1, -1, 504, -1, 506, 507, 3, 4, 5, 6, + 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, -1, 30, 31, 32, -1, -1, -1, -1, + 37, -1, -1, 40, 41, -1, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, 234, -1, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, + 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, -1, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, -1, 404, 405, -1, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, -1, 450, 451, 452, 453, 454, 455, 456, + -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, -1, -1, -1, + -1, -1, -1, 490, 491, -1, -1, -1, -1, -1, + 497, -1, 499, -1, -1, -1, -1, 504, -1, 506, + 507, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, -1, 30, 31, + 32, -1, -1, -1, -1, 37, -1, -1, 40, 41, + -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, -1, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, -1, 70, 71, + 72, 73, 74, -1, 76, -1, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, -1, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, + 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, + 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, + 182, 183, -1, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, -1, 198, 199, 200, 201, + 202, 203, -1, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, -1, 216, -1, 218, 219, 220, 221, + 222, 223, 224, 225, 226, 227, 228, -1, -1, 231, + 232, 233, 234, -1, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, + 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, + -1, -1, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, -1, 311, + 312, 313, 314, 315, 316, 317, 318, 319, -1, 321, + 322, 323, 324, 325, 326, -1, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, -1, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 368, -1, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 402, -1, 404, 405, -1, 407, 408, 409, 410, 411, + 412, 413, -1, 415, 416, -1, -1, 419, 420, 421, + 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, + 432, -1, -1, 435, 436, 437, 438, 439, 440, -1, + 442, 443, 444, 445, 446, 447, 448, -1, 450, 451, + 452, 453, 454, 455, 456, -1, -1, 459, -1, -1, + 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, -1, -1, -1, -1, -1, -1, 490, 491, + -1, -1, -1, -1, -1, 497, -1, 499, -1, -1, + -1, -1, 504, -1, 506, 507, 3, 4, 5, 6, + 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, -1, 30, 31, 32, -1, -1, -1, -1, + 37, -1, -1, 40, 41, -1, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + 117, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, 234, -1, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, + 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, -1, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, -1, 404, 405, -1, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, -1, 450, 451, 452, 453, 454, 455, 456, + -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 483, -1, -1, -1, + -1, -1, -1, 490, 491, -1, -1, -1, -1, -1, + 497, -1, 499, -1, -1, -1, -1, 504, -1, 506, + 507, 3, 4, 5, 6, 7, 8, 9, 10, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, + 22, 23, 24, 25, 26, 27, 28, -1, 30, 31, + 32, -1, -1, -1, -1, 37, -1, -1, 40, 41, + -1, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, -1, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, -1, 70, 71, + 72, 73, 74, -1, 76, -1, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, -1, 89, 90, 91, + 92, 93, 94, -1, 96, 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, -1, 120, 121, + 122, 123, 124, 125, -1, 127, 128, 129, 130, 131, + -1, -1, 134, 135, 136, 137, 138, -1, 140, 141, + 142, -1, 144, 145, 146, -1, 148, 149, 150, 151, + 152, 153, 154, 155, 156, 157, 158, 159, 160, -1, + 162, 163, 164, 165, -1, 167, -1, 169, 170, -1, + 172, 173, 174, 175, 176, 177, -1, 179, -1, 181, + 182, 183, -1, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, -1, 198, 199, 200, 201, + 202, 203, -1, 205, 206, 207, 208, 209, 210, 211, + 212, 213, 214, -1, 216, -1, 218, -1, -1, 221, + 222, 223, 224, 225, 226, 227, 228, -1, -1, 231, + 232, 233, 234, -1, 236, 237, 238, 239, 240, 241, + 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, + 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, + 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, + -1, 273, 274, -1, 276, 277, 278, 279, 280, 281, + 282, 283, -1, 285, 286, -1, -1, 289, 290, 291, + -1, -1, 294, 295, 296, 297, 298, 299, 300, 301, + 302, 303, 304, 305, 306, 307, 308, 309, -1, 311, + 312, 313, 314, 315, 316, 317, 318, 319, -1, 321, + 322, 323, 324, 325, 326, -1, 328, 329, 330, 331, + 332, 333, 334, 335, -1, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, -1, 351, + 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, + 362, 363, 364, 365, 366, 367, 368, -1, 370, 371, + 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, + 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, + 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, + 402, -1, 404, 405, -1, 407, 408, 409, 410, 411, + 412, 413, -1, 415, 416, -1, -1, 419, 420, 421, + 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, + 432, -1, -1, 435, 436, 437, 438, 439, 440, -1, + 442, 443, 444, 445, 446, 447, 448, -1, 450, 451, + 452, 453, 454, 455, 456, -1, -1, 459, -1, -1, + 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, + 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, + 482, 483, -1, -1, -1, -1, -1, -1, 490, 491, + -1, -1, -1, -1, -1, 497, -1, 499, -1, -1, + -1, -1, 504, -1, 506, 507, 3, 4, 5, 6, + 7, 8, 9, 10, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, -1, 30, 31, 32, -1, -1, -1, -1, + -1, -1, -1, 40, 41, -1, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + -1, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, 159, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, 234, -1, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, -1, 273, 274, 275, 276, + 277, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, + 367, 368, -1, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, -1, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, -1, 404, 405, -1, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, 424, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, -1, 450, 451, 452, 453, 454, 455, 456, + -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, -1, -1, -1, -1, + -1, -1, -1, 490, 491, -1, -1, 3, 4, 5, + 6, 7, 499, 9, 10, -1, -1, -1, -1, 506, + 507, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, -1, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + 76, -1, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, 170, -1, 172, 173, 174, 175, + 176, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + 206, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 228, -1, -1, 231, 232, 233, 234, -1, + 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, -1, 273, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, 408, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, 424, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, 440, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, 451, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, -1, -1, -1, + -1, -1, -1, -1, 490, 491, -1, -1, -1, -1, + -1, -1, -1, 499, -1, -1, -1, -1, -1, -1, + 506, 507, 3, 4, 5, 6, 7, 8, 9, 10, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, -1, -1, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, -1, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, -1, 70, + 71, 72, 73, 74, -1, 76, -1, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, -1, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, + -1, 162, 163, 164, 165, -1, 167, -1, 169, 170, + -1, 172, 173, 174, 175, 176, 177, -1, 179, -1, + 181, 182, 183, -1, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, -1, 220, + 221, 222, 223, 224, 225, 226, 227, 228, -1, -1, + 231, 232, 233, 234, -1, 236, 237, 238, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, -1, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, 313, 314, 315, 316, 317, 318, 319, -1, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, -1, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, -1, 404, 405, -1, 407, 408, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, + 431, 432, -1, -1, 435, 436, 437, 438, 439, 440, + -1, 442, 443, 444, 445, 446, 447, 448, -1, 450, + 451, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, -1, -1, -1, -1, -1, -1, -1, 490, + 491, -1, -1, -1, -1, -1, -1, -1, 499, -1, + -1, -1, -1, -1, -1, 506, 507, 3, 4, 5, + 6, 7, 8, 9, 10, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, 37, -1, -1, 40, 41, -1, 43, 44, 45, + 46, 47, 48, 49, -1, 51, 52, 53, 54, -1, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + 76, -1, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 117, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, -1, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, 170, -1, 172, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + 206, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, 222, 223, 224, 225, + 226, 227, 228, -1, -1, 231, 232, 233, -1, -1, + 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, 277, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, 408, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, 424, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, 440, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, 451, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, -1, -1, -1, + -1, -1, -1, -1, 490, 491, 3, -1, -1, -1, + -1, 497, -1, 499, -1, -1, -1, -1, 504, -1, + 506, 507, -1, -1, 21, 22, 23, 24, 25, 26, + 27, 28, -1, 30, 31, 32, -1, -1, -1, -1, + -1, 38, -1, 40, 41, -1, 43, 44, 45, -1, + 47, 48, 49, 50, 51, -1, 53, 54, -1, 56, + 57, 58, 59, 60, 61, -1, -1, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, -1, + -1, 78, 79, 80, 81, 82, 83, -1, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, -1, -1, -1, -1, -1, -1, -1, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + -1, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, -1, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, -1, -1, 172, 173, 174, 175, -1, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, -1, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, -1, -1, 221, 222, 223, 224, 225, 226, + 227, 228, -1, -1, 231, 232, 233, -1, -1, 236, + 237, 238, -1, -1, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, -1, 273, 274, -1, 276, + -1, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, -1, 289, 290, 291, -1, -1, 294, 295, -1, + 297, -1, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, + 367, 368, -1, 370, 371, 372, 373, 374, -1, 376, + 377, 378, 379, 380, -1, 382, 383, 384, 385, -1, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, -1, 404, 405, -1, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, -1, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, -1, -1, 442, 443, 444, 445, 446, + 447, 448, -1, 450, -1, 452, 453, 454, 455, 456, + -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, 3, -1, 5, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 500, 21, 22, 23, 24, 25, 26, + 27, 28, -1, 30, 31, 32, -1, -1, -1, -1, + -1, -1, -1, 40, 41, -1, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 54, -1, 56, + 57, 58, 59, 60, 61, -1, 63, 64, 65, 66, + 67, 68, -1, 70, 71, 72, 73, 74, -1, 76, + -1, 78, 79, 80, 81, 82, 83, 84, 85, 86, + 87, -1, 89, 90, 91, 92, 93, 94, -1, 96, + 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, + 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, + -1, 118, -1, 120, 121, 122, 123, 124, 125, -1, + 127, 128, 129, 130, 131, -1, -1, 134, 135, 136, + 137, 138, -1, 140, 141, 142, -1, 144, 145, 146, + -1, 148, 149, 150, 151, 152, 153, 154, 155, 156, + 157, 158, -1, 160, -1, 162, 163, 164, 165, -1, + 167, -1, 169, 170, -1, 172, 173, 174, 175, 176, + 177, -1, 179, -1, 181, 182, 183, -1, 185, 186, + 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, + -1, 198, 199, 200, 201, 202, 203, -1, 205, 206, + 207, 208, 209, 210, 211, 212, 213, 214, -1, 216, + -1, 218, 219, 220, 221, 222, 223, 224, 225, 226, + 227, 228, 229, -1, 231, 232, 233, 234, -1, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, + 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, + 267, 268, 269, 270, 271, -1, 273, 274, 275, 276, + -1, 278, 279, 280, 281, 282, 283, -1, 285, 286, + -1, 288, 289, 290, 291, -1, -1, 294, 295, 296, + 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, + 307, 308, 309, -1, 311, 312, 313, 314, 315, 316, + 317, 318, 319, -1, 321, 322, 323, 324, 325, 326, + -1, 328, 329, 330, 331, 332, 333, 334, 335, -1, + 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, + 347, 348, 349, -1, 351, 352, 353, 354, 355, 356, + 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, + 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 381, 382, 383, 384, 385, -1, + 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 402, -1, 404, 405, 406, + 407, 408, 409, 410, 411, 412, 413, -1, 415, 416, + -1, -1, 419, 420, 421, 422, 423, -1, 425, 426, + 427, 428, 429, 430, 431, 432, -1, -1, 435, 436, + 437, 438, 439, 440, -1, 442, 443, 444, 445, 446, + 447, 448, -1, 450, 451, 452, 453, 454, 455, 456, + -1, -1, 459, -1, 461, 462, 463, 464, 465, 466, + 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, + 477, 478, 479, 480, 481, 482, -1, -1, 485, 3, + 4, 5, -1, -1, -1, 9, -1, -1, -1, -1, + -1, -1, 499, -1, -1, -1, -1, 21, 22, 23, + 24, 25, 26, 27, 28, -1, 30, 31, 32, -1, + -1, -1, -1, -1, -1, -1, 40, 41, -1, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, -1, 56, 57, 58, 59, 60, 61, -1, -1, + 64, 65, 66, 67, 68, -1, 70, 71, 72, 73, + 74, -1, 76, -1, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, + 94, -1, 96, 97, 98, 99, 100, 101, 102, 103, + -1, -1, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, + 124, 125, -1, 127, 128, 129, 130, 131, -1, -1, + 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, + 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, -1, 162, 163, + 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, + 174, 175, 176, 177, -1, 179, -1, 181, 182, 183, + -1, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, -1, 198, 199, 200, 201, 202, 203, + -1, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, -1, 216, -1, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, -1, -1, 231, 232, 233, + 234, -1, 236, 237, 238, -1, -1, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, -1, 273, + 274, 275, 276, -1, 278, 279, 280, 281, 282, 283, + -1, 285, 286, 287, -1, 289, 290, 291, -1, -1, + 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, + 304, 305, 306, 307, 308, 309, -1, 311, 312, 313, + 314, 315, 316, 317, 318, 319, -1, 321, 322, 323, + 324, 325, 326, -1, 328, 329, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, 347, 348, 349, -1, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 368, -1, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 401, 402, -1, + 404, 405, -1, 407, 408, 409, 410, 411, 412, 413, + -1, 415, 416, -1, -1, 419, 420, 421, 422, 423, + 424, 425, 426, 427, 428, 429, 430, 431, 432, -1, + -1, 435, 436, 437, 438, 439, 440, -1, 442, 443, + 444, 445, 446, 447, 448, -1, 450, 451, 452, 453, + 454, 455, 456, -1, -1, 459, -1, -1, 462, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, 482, 3, + -1, 5, -1, -1, -1, -1, 490, 491, 492, -1, + -1, -1, -1, -1, -1, 499, -1, 21, 22, 23, + 24, 25, 26, 27, 28, -1, 30, 31, 32, -1, + -1, -1, -1, -1, -1, -1, 40, 41, -1, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, -1, 56, 57, 58, 59, 60, 61, -1, 63, + 64, 65, 66, 67, 68, -1, 70, 71, 72, 73, + 74, -1, 76, -1, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, + 94, -1, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, + 124, 125, -1, 127, 128, 129, 130, 131, -1, -1, + 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, + 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, + 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, + 174, 175, 176, 177, -1, 179, -1, 181, 182, 183, + -1, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, -1, 198, 199, 200, 201, 202, 203, + -1, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, -1, 216, -1, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, 229, -1, 231, 232, 233, + 234, -1, 236, 237, 238, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, -1, 273, + 274, 275, 276, -1, 278, 279, 280, 281, 282, 283, + -1, 285, 286, -1, 288, 289, 290, 291, -1, -1, + 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, + 304, 305, 306, 307, 308, 309, -1, 311, 312, 313, + 314, 315, 316, 317, 318, 319, -1, 321, 322, 323, + 324, 325, 326, -1, 328, 329, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, 347, 348, 349, -1, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 368, -1, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 401, 402, -1, + 404, 405, -1, 407, 408, 409, 410, 411, 412, 413, + -1, 415, 416, -1, -1, 419, 420, 421, 422, 423, + -1, 425, 426, 427, 428, 429, 430, 431, 432, -1, + -1, 435, 436, 437, 438, 439, 440, -1, 442, 443, + 444, 445, 446, 447, 448, -1, 450, 451, 452, 453, + 454, 455, 456, -1, -1, 459, -1, -1, 462, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, 482, 3, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 499, -1, 21, 22, 23, + 24, 25, 26, 27, 28, -1, 30, 31, 32, 33, + 34, -1, -1, -1, -1, -1, 40, 41, -1, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, -1, 56, 57, 58, 59, 60, 61, -1, -1, + 64, 65, 66, 67, 68, -1, 70, 71, 72, 73, + 74, -1, 76, -1, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, + 94, -1, 96, 97, 98, 99, 100, 101, 102, 103, + -1, -1, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, + 124, 125, -1, 127, 128, 129, 130, 131, -1, -1, + 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, + 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, + 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, + 174, 175, 176, 177, -1, 179, -1, 181, 182, 183, + -1, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, -1, 198, 199, 200, 201, 202, 203, + -1, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, -1, 216, -1, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, -1, -1, 231, 232, 233, + 234, -1, 236, 237, 238, -1, -1, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, -1, 273, + 274, 275, 276, -1, 278, 279, 280, 281, 282, 283, + -1, 285, 286, -1, -1, 289, 290, 291, -1, -1, + 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, + 304, 305, 306, 307, 308, 309, -1, 311, 312, 313, + 314, 315, 316, 317, 318, 319, -1, 321, 322, 323, + 324, 325, 326, -1, 328, 329, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, 347, 348, 349, -1, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 401, 402, -1, + 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, + -1, 415, 416, -1, -1, 419, 420, 421, 422, 423, + -1, 425, 426, 427, 428, 429, 430, 431, 432, -1, + -1, 435, 436, 437, 438, 439, 440, -1, 442, 443, + 444, 445, 446, 447, 448, -1, 450, 451, 452, 453, + 454, 455, 456, -1, -1, 459, -1, 461, 462, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, 482, 3, + -1, 485, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 499, -1, 21, 22, 23, + 24, 25, 26, 27, 28, -1, 30, 31, 32, -1, + -1, -1, -1, -1, -1, -1, 40, 41, -1, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, -1, 56, 57, 58, 59, 60, 61, -1, 63, + 64, 65, 66, 67, 68, -1, 70, 71, 72, 73, + 74, -1, 76, -1, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, + 94, -1, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, + 124, 125, -1, 127, 128, 129, 130, 131, -1, -1, + 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, + 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, + 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, + 174, 175, 176, 177, -1, 179, -1, 181, 182, 183, + -1, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, -1, 198, 199, 200, 201, 202, 203, + -1, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, -1, 216, -1, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, -1, -1, 231, 232, 233, + 234, -1, 236, 237, 238, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, -1, 273, + 274, 275, 276, -1, 278, 279, 280, 281, 282, 283, + -1, 285, 286, -1, -1, 289, 290, 291, -1, -1, + 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, + 304, 305, 306, 307, 308, 309, -1, 311, 312, 313, + 314, 315, 316, 317, 318, 319, -1, 321, 322, 323, + 324, 325, 326, -1, 328, 329, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, 347, 348, 349, -1, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 368, -1, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 401, 402, -1, + 404, 405, -1, 407, 408, 409, 410, 411, 412, 413, + -1, 415, 416, -1, -1, 419, 420, 421, 422, 423, + -1, 425, 426, 427, 428, 429, 430, 431, 432, -1, + -1, 435, 436, 437, 438, 439, 440, -1, 442, 443, + 444, 445, 446, 447, 448, -1, 450, 451, 452, 453, + 454, 455, 456, -1, -1, 459, -1, -1, 462, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, 482, 3, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 499, -1, 21, 22, 23, + 24, 25, 26, 27, 28, -1, 30, 31, 32, -1, + -1, -1, -1, -1, -1, -1, 40, 41, -1, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, + 54, -1, 56, 57, 58, 59, 60, 61, -1, 63, + 64, 65, 66, 67, 68, -1, 70, 71, 72, 73, + 74, -1, 76, -1, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, -1, 89, 90, 91, 92, 93, + 94, -1, 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, + 124, 125, -1, 127, 128, 129, 130, 131, -1, -1, + 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, + 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, + 164, 165, -1, 167, -1, 169, 170, -1, 172, 173, + 174, 175, 176, 177, -1, 179, -1, 181, 182, 183, + -1, 185, 186, 187, 188, 189, 190, 191, 192, 193, + 194, 195, 196, -1, 198, 199, 200, 201, 202, 203, + -1, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, -1, 216, -1, 218, 219, 220, 221, 222, 223, + 224, 225, 226, 227, 228, -1, -1, 231, 232, 233, + 234, -1, 236, 237, 238, 239, 240, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, 266, 267, 268, 269, 270, 271, -1, 273, + 274, 275, 276, -1, 278, 279, 280, 281, 282, 283, + -1, 285, 286, -1, -1, 289, 290, 291, -1, -1, + 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, + 304, 305, 306, 307, 308, 309, -1, 311, 312, 313, + 314, 315, 316, 317, 318, 319, -1, 321, 322, 323, + 324, 325, 326, -1, 328, 329, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, 347, 348, 349, -1, 351, 352, 353, + 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 368, -1, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 401, 402, -1, + 404, 405, -1, 407, 408, 409, 410, 411, 412, 413, + -1, 415, 416, -1, -1, 419, 420, 421, 422, 423, + -1, 425, 426, 427, 428, 429, 430, 431, 432, -1, + -1, 435, 436, 437, 438, 439, 440, -1, 442, 443, + 444, 445, 446, 447, 448, -1, 450, 451, 452, 453, + 454, 455, 456, -1, -1, 459, -1, -1, 462, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, 482, 3, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 499, -1, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, + -1, -1, -1, -1, -1, -1, 40, 41, -1, 43, + 44, 45, -1, 47, 48, 49, 50, 51, -1, 53, + 54, -1, 56, 57, 58, 59, 60, 61, -1, -1, + 64, 65, 66, 67, 68, -1, 70, 71, 72, 73, + 74, -1, -1, -1, 78, 79, 80, 81, 82, 83, + -1, 85, 86, 87, -1, 89, 90, 91, 92, 93, + 94, -1, -1, 97, 98, 99, -1, -1, -1, -1, + -1, -1, -1, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, + 124, 125, -1, 127, 128, 129, 130, 131, -1, -1, + 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, + 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, + 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, + 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, + -1, 185, 186, 187, 188, 189, 190, 191, -1, 193, + 194, 195, 196, -1, 198, 199, 200, 201, 202, 203, + -1, 205, -1, 207, 208, 209, 210, 211, 212, 213, + 214, -1, 216, -1, 218, -1, -1, 221, -1, 223, + 224, 225, 226, 227, 228, -1, -1, 231, -1, 233, + -1, -1, 236, 237, 238, -1, -1, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, -1, 267, 268, 269, 270, 271, -1, 273, + 274, -1, 276, -1, 278, 279, 280, 281, 282, 283, + -1, 285, 286, -1, -1, 289, 290, 291, -1, -1, + 294, 295, -1, 297, -1, 299, 300, 301, 302, 303, + 304, 305, 306, 307, 308, 309, -1, 311, 312, 313, + 314, 315, 316, 317, 318, 319, -1, 321, 322, 323, + 324, 325, 326, -1, 328, 329, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, 347, 348, 349, -1, 351, 352, -1, + 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, -1, 376, 377, 378, 379, 380, -1, 382, 383, + 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 401, 402, -1, + 404, 405, 406, 407, -1, 409, 410, 411, 412, 413, + -1, 415, 416, -1, -1, 419, 420, 421, 422, 423, + -1, 425, 426, 427, 428, 429, 430, 431, 432, -1, + -1, 435, 436, 437, 438, 439, -1, -1, 442, 443, + 444, 445, 446, 447, 448, -1, 450, -1, 452, 453, + 454, 455, 456, -1, -1, 459, -1, 461, 462, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, 482, 3, + -1, 485, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 499, -1, 21, 22, 23, + 24, 25, 26, 27, 28, -1, 30, 31, 32, -1, + -1, -1, -1, -1, -1, -1, 40, 41, -1, 43, + 44, 45, -1, 47, 48, 49, 50, 51, -1, 53, + 54, -1, 56, 57, 58, 59, 60, 61, -1, -1, + 64, 65, 66, 67, 68, -1, 70, 71, 72, 73, + 74, -1, -1, -1, 78, 79, 80, 81, 82, 83, + -1, 85, 86, 87, -1, 89, 90, 91, 92, 93, + 94, -1, -1, 97, 98, 99, -1, -1, -1, -1, + -1, -1, -1, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, -1, 118, -1, 120, 121, 122, 123, + 124, 125, -1, 127, 128, 129, 130, 131, -1, -1, + 134, 135, 136, 137, 138, -1, 140, 141, 142, -1, + 144, 145, 146, -1, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, -1, 160, -1, 162, 163, + 164, 165, -1, 167, -1, 169, -1, -1, -1, 173, + 174, 175, -1, 177, -1, 179, -1, 181, 182, 183, + -1, 185, 186, 187, 188, 189, 190, 191, -1, 193, + 194, 195, 196, -1, 198, 199, 200, 201, 202, 203, + -1, 205, -1, 207, 208, 209, 210, 211, 212, 213, + 214, -1, 216, -1, 218, -1, -1, 221, -1, 223, + 224, 225, 226, 227, 228, -1, -1, 231, -1, 233, + -1, -1, 236, 237, 238, -1, -1, 241, 242, 243, + 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, + 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, + 264, 265, -1, 267, 268, 269, 270, 271, -1, 273, + 274, -1, 276, -1, 278, 279, 280, 281, 282, 283, + -1, 285, 286, -1, -1, 289, 290, 291, -1, -1, + 294, 295, -1, 297, -1, 299, 300, 301, 302, 303, + 304, 305, 306, 307, 308, 309, -1, 311, 312, 313, + 314, 315, 316, 317, 318, 319, -1, 321, 322, 323, + 324, 325, 326, -1, 328, 329, 330, 331, 332, 333, + 334, 335, -1, 337, 338, 339, 340, 341, 342, 343, + 344, 345, 346, 347, 348, 349, -1, 351, 352, -1, + 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, + 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, + 374, -1, 376, 377, 378, 379, 380, -1, 382, 383, + 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, + 394, 395, 396, 397, 398, 399, 400, 401, 402, -1, + 404, 405, 406, 407, -1, 409, 410, 411, 412, 413, + -1, 415, 416, -1, -1, 419, 420, 421, 422, 423, + -1, 425, 426, 427, 428, 429, 430, 431, 432, -1, + -1, 435, 436, 437, 438, 439, -1, -1, 442, 443, + 444, 445, 446, 447, 448, -1, 450, -1, 452, 453, + 454, 455, 456, -1, -1, 459, -1, 461, 462, 463, + 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, + 474, 475, 476, 477, 478, 479, 480, 481, 482, -1, + 3, 485, 5, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 499, -1, -1, 21, 22, + 23, 24, 25, 26, 27, 28, -1, 30, 31, 32, + -1, -1, -1, -1, -1, -1, -1, 40, 41, -1, + 43, 44, 45, -1, 47, 48, 49, 50, 51, -1, + 53, 54, -1, 56, 57, 58, 59, 60, 61, -1, + -1, 64, 65, 66, 67, 68, -1, 70, 71, 72, + 73, 74, -1, -1, -1, 78, 79, 80, 81, 82, + 83, -1, 85, 86, 87, -1, 89, 90, 91, 92, + 93, 94, -1, -1, 97, 98, 99, -1, -1, -1, + -1, -1, -1, -1, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, + 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, -1, 160, -1, 162, + 163, 164, 165, -1, 167, -1, 169, -1, -1, -1, + 173, 174, 175, -1, 177, -1, 179, -1, 181, 182, + 183, -1, 185, 186, 187, 188, 189, 190, 191, -1, + 193, 194, 195, 196, -1, 198, 199, 200, 201, 202, + 203, -1, 205, -1, 207, 208, 209, 210, 211, 212, + 213, 214, -1, 216, -1, 218, -1, -1, 221, -1, + 223, 224, 225, 226, 227, 228, -1, -1, 231, -1, + 233, -1, -1, 236, 237, 238, -1, -1, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, -1, 267, 268, 269, 270, 271, -1, + 273, 274, -1, 276, -1, 278, 279, 280, 281, 282, + 283, -1, 285, 286, -1, -1, 289, 290, 291, -1, + -1, 294, 295, -1, 297, -1, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, -1, 311, 312, + 313, 314, 315, 316, 317, 318, 319, -1, 321, 322, + 323, 324, 325, 326, -1, 328, 329, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, + -1, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, + 373, 374, -1, 376, 377, 378, 379, 380, -1, 382, + 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + -1, 404, 405, -1, 407, -1, 409, 410, 411, 412, + 413, -1, 415, 416, -1, -1, 419, 420, 421, 422, + 423, -1, 425, 426, 427, 428, 429, 430, 431, 432, + -1, -1, 435, 436, 437, 438, 439, -1, -1, 442, + 443, 444, 445, 446, 447, 448, -1, 450, -1, 452, + 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 499, -1, 21, 22, + 23, 24, 25, 26, 27, 28, -1, 30, 31, 32, + -1, -1, -1, -1, -1, -1, -1, 40, 41, -1, + 43, 44, 45, -1, 47, 48, 49, 50, 51, -1, + 53, 54, -1, 56, 57, 58, 59, 60, 61, -1, + -1, 64, 65, 66, 67, 68, -1, 70, 71, 72, + 73, 74, -1, -1, -1, 78, 79, 80, 81, 82, + 83, -1, 85, 86, 87, -1, 89, 90, 91, 92, + 93, 94, -1, -1, 97, 98, 99, -1, -1, -1, + -1, -1, -1, -1, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, + 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, -1, 160, -1, 162, + 163, 164, 165, -1, 167, -1, 169, -1, -1, -1, + 173, 174, 175, -1, 177, -1, 179, -1, 181, 182, + 183, -1, 185, 186, 187, 188, 189, 190, 191, -1, + 193, 194, 195, 196, -1, 198, 199, 200, 201, 202, + 203, -1, 205, -1, 207, 208, 209, 210, 211, 212, + 213, 214, -1, 216, -1, 218, -1, -1, 221, -1, + 223, 224, 225, 226, 227, 228, -1, -1, 231, -1, + 233, -1, -1, 236, 237, 238, -1, -1, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, -1, 267, 268, 269, 270, 271, -1, + 273, 274, -1, 276, -1, 278, 279, 280, 281, 282, + 283, -1, 285, 286, -1, -1, 289, 290, 291, -1, + -1, 294, 295, -1, 297, -1, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, -1, 311, 312, + 313, 314, 315, 316, 317, 318, 319, -1, 321, 322, + 323, 324, 325, 326, -1, 328, 329, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, + -1, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, + 373, 374, -1, 376, 377, 378, 379, 380, -1, 382, + 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + -1, 404, 405, -1, 407, -1, 409, 410, 411, 412, + 413, -1, 415, 416, -1, -1, 419, 420, 421, 422, + 423, -1, 425, 426, 427, 428, 429, 430, 431, 432, + -1, -1, 435, 436, 437, 438, 439, -1, -1, 442, + 443, 444, 445, 446, 447, 448, -1, 450, -1, 452, + 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 499, -1, 21, 22, + 23, 24, 25, 26, 27, 28, -1, 30, 31, 32, + -1, -1, -1, -1, -1, -1, -1, 40, 41, -1, + 43, 44, 45, -1, 47, 48, 49, 50, 51, -1, + 53, 54, -1, 56, 57, 58, 59, 60, 61, -1, + -1, 64, 65, 66, 67, 68, -1, 70, 71, 72, + 73, 74, -1, -1, -1, 78, 79, 80, 81, 82, + 83, -1, 85, 86, 87, -1, 89, 90, 91, 92, + 93, 94, -1, -1, 97, 98, 99, -1, -1, -1, + -1, -1, -1, -1, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, + 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, -1, 160, -1, 162, + 163, 164, 165, -1, 167, -1, 169, -1, -1, -1, + 173, 174, 175, -1, 177, -1, 179, -1, 181, 182, + 183, -1, 185, 186, 187, 188, 189, 190, 191, -1, + 193, 194, 195, 196, -1, 198, 199, 200, 201, 202, + 203, -1, 205, -1, 207, 208, 209, 210, 211, 212, + 213, 214, -1, 216, -1, 218, -1, -1, 221, -1, + 223, 224, 225, 226, 227, 228, -1, -1, 231, -1, + 233, -1, -1, 236, 237, 238, -1, -1, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, -1, 267, 268, 269, 270, 271, -1, + 273, 274, -1, 276, -1, 278, 279, 280, 281, 282, + 283, -1, 285, 286, -1, -1, 289, 290, 291, -1, + -1, 294, 295, -1, 297, -1, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, -1, 311, 312, + 313, 314, 315, 316, 317, 318, 319, -1, 321, 322, + 323, 324, 325, 326, -1, 328, 329, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, + -1, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, + 373, 374, -1, 376, 377, 378, 379, 380, -1, 382, + 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + -1, 404, 405, -1, 407, -1, 409, 410, 411, 412, + 413, -1, 415, 416, -1, -1, 419, 420, 421, 422, + 423, -1, 425, 426, 427, 428, 429, 430, 431, 432, + -1, -1, 435, 436, 437, 438, 439, -1, -1, 442, + 443, 444, 445, 446, 447, 448, -1, 450, -1, 452, + 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 499, -1, 21, 22, + 23, 24, 25, 26, 27, 28, -1, 30, 31, 32, + -1, -1, -1, -1, -1, -1, -1, 40, 41, -1, + 43, 44, 45, -1, 47, 48, 49, 50, 51, -1, + 53, 54, -1, 56, 57, 58, 59, 60, 61, -1, + -1, 64, 65, 66, 67, 68, -1, 70, 71, 72, + 73, 74, -1, -1, -1, 78, 79, 80, 81, 82, + 83, -1, 85, 86, 87, -1, 89, 90, 91, 92, + 93, 94, -1, -1, 97, 98, 99, -1, -1, -1, + -1, -1, -1, -1, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, + 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, -1, 160, -1, 162, + 163, 164, 165, -1, 167, -1, 169, -1, -1, -1, + 173, 174, 175, -1, 177, -1, 179, -1, 181, 182, + 183, -1, 185, 186, 187, 188, 189, 190, 191, -1, + 193, 194, 195, 196, -1, 198, 199, 200, 201, 202, + 203, -1, 205, -1, 207, 208, 209, 210, 211, 212, + 213, 214, -1, 216, -1, 218, -1, -1, 221, -1, + 223, 224, 225, 226, 227, 228, -1, -1, 231, -1, + 233, -1, -1, 236, 237, 238, -1, -1, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, -1, 267, 268, 269, 270, 271, -1, + 273, 274, -1, 276, -1, 278, 279, 280, 281, 282, + 283, -1, 285, 286, -1, -1, 289, 290, 291, -1, + -1, 294, 295, -1, 297, -1, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, -1, 311, 312, + 313, 314, 315, 316, 317, 318, 319, -1, 321, 322, + 323, 324, 325, 326, -1, 328, 329, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, + -1, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, + 373, 374, -1, 376, 377, 378, 379, 380, -1, 382, + 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + -1, 404, 405, -1, 407, -1, 409, 410, 411, 412, + 413, -1, 415, 416, -1, -1, 419, 420, 421, 422, + 423, -1, 425, 426, 427, 428, 429, 430, 431, 432, + -1, -1, 435, 436, 437, 438, 439, -1, -1, 442, + 443, 444, 445, 446, 447, 448, -1, 450, -1, 452, + 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 499, -1, 21, 22, + 23, 24, 25, 26, 27, 28, -1, 30, 31, 32, + -1, -1, -1, -1, -1, -1, -1, 40, 41, -1, + 43, 44, 45, -1, 47, 48, 49, 50, 51, -1, + 53, 54, -1, 56, 57, 58, 59, 60, 61, -1, + -1, 64, 65, 66, 67, 68, -1, 70, 71, 72, + 73, 74, -1, -1, -1, 78, 79, 80, 81, 82, + 83, -1, 85, 86, 87, -1, 89, 90, 91, 92, + 93, 94, -1, -1, 97, 98, 99, -1, -1, -1, + -1, -1, -1, -1, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, + 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, -1, 160, -1, 162, + 163, 164, 165, -1, 167, -1, 169, -1, -1, -1, + 173, 174, 175, -1, 177, -1, 179, -1, 181, 182, + 183, -1, 185, 186, 187, 188, 189, 190, 191, -1, + 193, 194, 195, 196, -1, 198, 199, 200, 201, 202, + 203, -1, 205, -1, 207, 208, 209, 210, 211, 212, + 213, 214, -1, 216, -1, 218, -1, -1, 221, -1, + 223, 224, 225, 226, 227, 228, -1, -1, 231, -1, + 233, -1, -1, 236, 237, 238, -1, -1, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, -1, 267, 268, 269, 270, 271, -1, + 273, 274, -1, 276, -1, 278, 279, 280, 281, 282, + 283, -1, 285, 286, -1, -1, 289, 290, 291, -1, + -1, 294, 295, -1, 297, -1, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, -1, 311, 312, + 313, 314, 315, 316, 317, 318, 319, -1, 321, 322, + 323, 324, 325, 326, -1, 328, 329, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, + -1, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, + 373, 374, -1, 376, 377, 378, 379, 380, -1, 382, + 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + -1, 404, 405, -1, 407, -1, 409, 410, 411, 412, + 413, -1, 415, 416, -1, -1, 419, 420, 421, 422, + 423, -1, 425, 426, 427, 428, 429, 430, 431, 432, + -1, -1, 435, 436, 437, 438, 439, -1, -1, 442, + 443, 444, 445, 446, 447, 448, -1, 450, -1, 452, + 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + -1, -1, 3, 4, 5, -1, -1, 8, 9, -1, + -1, -1, -1, -1, 15, -1, 499, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, -1, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, -1, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, -1, 153, 154, 155, 156, 157, -1, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, + -1, -1, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, + 201, 202, 203, 204, 205, 206, -1, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, 272, 273, 274, 275, 276, 277, -1, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, -1, 296, 297, 298, -1, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, -1, 314, 315, -1, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, + 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + -1, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + -1, 422, -1, 424, 425, 426, 427, 428, 429, 430, + 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, -1, 448, 449, 450, + 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, + 461, 462, 463, 464, 465, 466, 467, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 479, 480, + 481, 482, -1, 3, -1, 486, 487, 488, 8, 490, + 491, 492, 493, 494, 495, 15, -1, -1, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, -1, + 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, + 40, 41, -1, 43, 44, 45, -1, 47, 48, 49, + 50, 51, -1, 53, 54, -1, 56, 57, 58, 59, + 60, 61, -1, -1, 64, 65, 66, 67, 68, -1, + 70, 71, 72, 73, 74, -1, -1, -1, 78, 79, + 80, 81, 82, 83, -1, 85, 86, 87, -1, 89, + 90, 91, 92, 93, 94, -1, -1, 97, 98, 99, + -1, -1, -1, -1, -1, -1, -1, 107, 108, 109, + 110, 111, 112, 113, 114, 115, 116, -1, 118, -1, + 120, 121, 122, 123, 124, 125, -1, 127, 128, 129, + 130, 131, -1, -1, 134, 135, 136, 137, 138, -1, + 140, 141, 142, -1, 144, 145, 146, -1, 148, 149, + 150, 151, 152, 153, 154, 155, 156, 157, 158, -1, + 160, -1, 162, 163, 164, 165, -1, 167, -1, 169, + -1, -1, -1, 173, 174, 175, -1, 177, -1, 179, + -1, 181, 182, 183, -1, 185, 186, 187, 188, 189, + 190, 191, -1, 193, 194, 195, 196, -1, 198, 199, + 200, 201, 202, 203, -1, 205, -1, 207, 208, 209, + 210, 211, 212, 213, 214, -1, 216, -1, 218, -1, + -1, 221, -1, 223, 224, 225, 226, 227, 228, -1, + -1, 231, -1, 233, -1, -1, 236, 237, 238, -1, + -1, 241, 242, 243, 244, 245, 246, 247, 248, 249, + 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, + 260, 261, 262, 263, 264, 265, -1, 267, 268, 269, + 270, 271, -1, 273, 274, -1, 276, -1, 278, 279, + 280, 281, 282, 283, -1, 285, 286, -1, -1, 289, + 290, 291, -1, -1, 294, 295, -1, 297, -1, 299, + 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, + -1, 311, 312, 313, 314, 315, 316, 317, 318, 319, + -1, 321, 322, 323, 324, 325, 326, -1, 328, 329, + 330, 331, 332, 333, 334, 335, -1, 337, 338, 339, + 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, + -1, 351, 352, -1, 354, 355, 356, 357, 358, 359, + 360, 361, 362, 363, 364, 365, 366, 367, 368, -1, + 370, 371, 372, 373, 374, -1, 376, 377, 378, 379, + 380, -1, 382, 383, 384, 385, -1, 387, 388, 389, + 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, + 400, 401, 402, -1, 404, 405, -1, 407, -1, 409, + 410, 411, 412, 413, -1, 415, 416, -1, -1, 419, + 420, 421, 422, 423, -1, 425, 426, 427, 428, 429, + 430, 431, 432, -1, -1, 435, 436, 437, 438, 439, + -1, -1, 442, 443, 444, 445, 446, 447, 448, -1, + 450, -1, 452, 453, 454, 455, 456, -1, -1, 459, + -1, -1, 462, 463, 464, 465, 466, 467, 468, 469, + 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, + 480, 481, 482, -1, -1, -1, 486, 487, 488, -1, + 490, 491, 492, 493, 494, 495, 8, -1, -1, 11, + -1, -1, -1, 15, 16, 17, 18, 19, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 35, -1, 8, -1, -1, 11, -1, + -1, 43, 15, 16, 17, 18, 19, 20, 50, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 482, -1, -1, 485, 486, 487, -1, - 489, 490, 491, 492, 493, 494, -1, -1, -1, -1, - 499, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, + 43, 8, -1, 75, 11, -1, -1, 50, 15, 16, + 17, 18, 19, 20, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 35, -1, + 8, -1, 75, 11, -1, -1, 43, 15, 16, 17, + 18, 19, 20, 50, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, + -1, -1, -1, -1, -1, 43, -1, -1, 75, -1, + -1, -1, 50, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 75, -1, -1, + -1, -1, -1, -1, 176, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 380, -1, -1, -1, -1, -1, + 192, -1, -1, -1, -1, 197, -1, -1, 8, -1, + -1, 11, -1, 176, -1, 15, 16, 17, 18, 19, + 20, -1, -1, -1, -1, -1, -1, 219, 220, 192, + -1, -1, -1, -1, 197, 35, -1, -1, -1, -1, + -1, -1, 234, 43, -1, -1, -1, -1, -1, 176, + 50, -1, -1, -1, -1, -1, 219, 220, -1, -1, + -1, -1, -1, -1, -1, 192, -1, -1, -1, -1, + 197, 234, -1, -1, -1, 75, -1, -1, 176, -1, + 272, -1, -1, 275, -1, -1, -1, -1, -1, -1, + -1, -1, 219, 220, 192, -1, -1, 289, -1, 197, + 292, -1, -1, -1, -1, -1, -1, 234, -1, 272, + -1, -1, 275, -1, -1, -1, -1, -1, -1, -1, + -1, 219, 220, -1, -1, -1, 289, -1, -1, 292, + -1, -1, -1, -1, -1, -1, 234, -1, -1, -1, + -1, -1, -1, -1, -1, 272, -1, -1, 275, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 289, -1, -1, 292, -1, -1, -1, -1, + -1, -1, -1, -1, 272, -1, 176, 275, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 381, + -1, 289, 192, -1, 292, -1, -1, 197, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 381, 219, + 220, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 234, -1, -1, -1, 8, -1, + -1, 11, -1, -1, -1, 15, 16, 17, 18, 19, + 20, -1, -1, -1, 381, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, + -1, -1, 272, 43, -1, 275, -1, -1, -1, -1, + 50, -1, -1, 381, -1, -1, -1, -1, -1, 289, + -1, 483, 292, -1, 486, 487, 488, -1, 490, 491, + 492, 493, 494, 495, -1, 75, -1, -1, 500, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 483, -1, -1, 486, 487, 488, -1, 490, 491, 492, + 493, 494, 495, -1, -1, -1, -1, 500, -1, -1, + -1, -1, 8, -1, -1, 11, -1, -1, -1, 15, + 16, 17, 18, 19, 20, -1, 483, -1, -1, 486, + 487, 488, -1, 490, 491, 492, 493, 494, 495, 35, + -1, -1, -1, 500, -1, -1, -1, 43, -1, -1, + -1, 381, -1, -1, 50, 483, -1, -1, 486, 487, + 488, -1, 490, 491, 492, 493, 494, 495, -1, -1, + -1, -1, 500, -1, 8, -1, 176, 11, -1, 75, + -1, 15, 16, 17, 18, 19, 20, -1, -1, -1, + -1, -1, 192, -1, -1, -1, -1, 197, -1, -1, + -1, 35, -1, -1, -1, -1, -1, -1, -1, 43, + -1, -1, -1, -1, -1, -1, 50, -1, -1, 219, + 220, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 234, -1, -1, -1, -1, 8, + -1, 75, 11, -1, -1, -1, 15, 16, 17, 18, + 19, 20, -1, 483, -1, -1, 486, 487, 488, -1, + 490, 491, 492, 493, 494, 495, 35, -1, -1, -1, + 500, -1, 272, -1, 43, 275, -1, -1, -1, -1, + 176, 50, -1, -1, -1, -1, -1, -1, -1, 289, + -1, -1, 292, -1, -1, -1, 192, 25, -1, -1, + -1, 197, -1, 31, -1, -1, 75, -1, -1, -1, + 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 219, 220, -1, -1, -1, -1, 57, + -1, -1, -1, -1, -1, -1, -1, -1, 234, -1, + -1, -1, 176, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 8, 192, -1, + 11, -1, -1, 197, 15, 16, 17, 18, 19, 20, + -1, -1, -1, -1, -1, -1, 272, -1, -1, 275, + 108, 381, -1, -1, 35, 219, 220, -1, -1, -1, + -1, -1, 43, 289, -1, -1, 292, -1, -1, 50, + 234, -1, -1, -1, -1, -1, -1, 176, -1, 137, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 192, 75, -1, -1, -1, 197, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 272, -1, + -1, 275, -1, -1, -1, -1, -1, -1, -1, -1, + 219, 220, -1, -1, -1, 289, -1, -1, 292, -1, + -1, -1, -1, -1, -1, 234, -1, -1, -1, -1, + -1, 199, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 483, -1, 381, 486, 487, 488, -1, + 490, 491, 492, 493, 494, 495, -1, -1, -1, -1, + 500, -1, -1, 272, -1, -1, 275, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 289, -1, 250, 292, -1, 176, -1, -1, -1, -1, + 258, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 192, 270, -1, -1, -1, 197, 381, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 291, -1, -1, -1, -1, 219, 220, + -1, -1, -1, 301, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 234, -1, -1, -1, 483, -1, -1, + 486, 487, 488, -1, 490, 491, 492, 493, 494, 495, + -1, -1, -1, -1, 500, -1, -1, -1, -1, -1, + -1, -1, 381, -1, 342, -1, -1, -1, 346, -1, + 348, 272, -1, -1, 275, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 289, -1, + -1, 292, 370, -1, -1, -1, -1, -1, 376, 483, + -1, -1, 486, 487, 488, -1, 490, 491, 492, 493, + 494, 495, 390, -1, -1, -1, 500, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 3, 482, -1, -1, 485, - 486, 487, -1, 489, 490, 491, 492, 493, 494, -1, - -1, 497, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, -1, 46, 47, - 48, 49, 50, -1, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, -1, 76, 77, - 78, 79, 80, 81, 82, -1, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, -1, 96, 97, - 98, 99, 100, 101, -1, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, -1, 170, -1, 172, 173, 174, -1, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, -1, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, -1, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - -1, -1, 220, -1, 222, 223, 224, 225, 226, 227, - 228, 229, 230, -1, 232, -1, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, -1, 266, 267, - 268, 269, 270, 271, 272, 273, -1, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, -1, 296, -1, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, - 348, 349, 350, 351, -1, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, -1, 381, 382, 383, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, -1, - 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, - 448, 449, -1, 451, 452, 453, 454, 455, 456, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 478, 479, 480, 481, 3, -1, -1, -1, -1, -1, - -1, -1, -1, 491, -1, -1, -1, -1, -1, -1, - -1, 20, 21, 22, 23, 24, 25, 26, 27, -1, - 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, - 39, 40, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, -1, 52, 53, -1, 55, 56, 57, 58, - 59, 60, -1, -1, 63, 64, 65, 66, 67, -1, - 69, 70, 71, 72, 73, -1, -1, -1, 77, 78, - 79, 80, 81, 82, -1, 84, 85, 86, -1, 88, - 89, 90, 91, 92, 93, -1, -1, 96, 97, 98, - -1, -1, -1, -1, -1, -1, -1, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, -1, 117, -1, - 119, 120, 121, 122, 123, 124, -1, 126, 127, 128, - 129, 130, -1, -1, 133, 134, 135, 136, 137, -1, - 139, 140, 141, -1, 143, 144, 145, -1, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, -1, - 159, -1, 161, 162, 163, 164, -1, 166, -1, 168, - -1, -1, -1, 172, 173, 174, -1, 176, -1, 178, - -1, 180, 181, 182, -1, 184, 185, 186, 187, 188, - 189, 190, -1, 192, 193, 194, 195, -1, 197, 198, - 199, 200, 201, 202, -1, 204, -1, 206, 207, 208, - 209, 210, 211, 212, 213, -1, 215, -1, 217, -1, - -1, 220, -1, 222, 223, 224, 225, 226, 227, -1, - -1, 230, -1, 232, -1, -1, 235, 236, 237, -1, - -1, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, -1, 266, 267, 268, - 269, 270, -1, 272, 273, -1, 275, -1, 277, 278, - 279, 280, 281, 282, -1, 284, 285, -1, -1, 288, - 289, 290, -1, -1, 293, 294, -1, 296, -1, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - -1, 310, 311, 312, 313, 314, 315, 316, 317, 318, - -1, 320, 321, 322, 323, 324, 325, -1, 327, 328, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, - -1, 350, 351, -1, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 364, 365, 366, 367, -1, - 369, 370, 371, 372, 373, -1, 375, 376, 377, 378, - 379, -1, 381, 382, 383, 384, -1, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, - 399, 400, 401, -1, 403, 404, -1, 406, -1, 408, - 409, 410, 411, 412, -1, 414, 415, -1, -1, 418, - 419, 420, 421, 422, -1, 424, 425, 426, 427, 428, - 429, 430, 431, -1, -1, 434, 435, 436, 437, 438, - -1, -1, 441, 442, 443, 444, 445, 446, 447, -1, - 449, -1, 451, 452, 453, 454, 455, -1, -1, 458, - -1, -1, 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, - 479, 480, 481, 3, 4, 5, -1, -1, -1, 9, - -1, -1, 491, -1, -1, -1, -1, -1, -1, -1, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, -1, -1, -1, 39, - 40, -1, 42, 43, 44, -1, 46, 47, 48, 49, - 50, -1, 52, 53, -1, 55, 56, 57, 58, 59, - 60, -1, -1, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, -1, -1, 77, 78, 79, - 80, 81, 82, -1, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, -1, 96, 97, 98, -1, - -1, -1, -1, -1, -1, -1, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, 116, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, -1, - -1, -1, 172, 173, 174, -1, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, -1, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, -1, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, -1, -1, - 220, -1, 222, 223, 224, 225, 226, 227, -1, -1, - 230, -1, 232, -1, -1, 235, 236, 237, -1, -1, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, -1, 266, 267, 268, 269, - 270, -1, 272, 273, -1, 275, -1, 277, 278, 279, - 280, 281, 282, -1, 284, 285, 286, -1, 288, 289, - 290, -1, -1, 293, 294, -1, 296, -1, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, -1, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, -1, 369, - 370, 371, 372, 373, -1, 375, 376, 377, 378, 379, - -1, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, -1, 406, -1, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, -1, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - -1, 451, 452, 453, 454, 455, -1, -1, 458, -1, - -1, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, 3, 4, 5, -1, -1, -1, 9, 489, - 490, -1, -1, -1, -1, -1, -1, -1, -1, 20, - 21, 22, 23, 24, 25, 26, 27, -1, 29, 30, - 31, -1, -1, -1, -1, -1, -1, -1, 39, 40, - -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, - -1, 52, 53, -1, 55, 56, 57, 58, 59, 60, - -1, -1, 63, 64, 65, 66, 67, -1, 69, 70, - 71, 72, 73, -1, -1, -1, 77, 78, 79, 80, - 81, 82, -1, 84, 85, 86, -1, 88, 89, 90, - 91, 92, 93, -1, -1, 96, 97, 98, -1, -1, - -1, -1, -1, -1, -1, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, 116, 117, -1, 119, 120, - 121, 122, 123, 124, -1, 126, 127, 128, 129, 130, - -1, -1, 133, 134, 135, 136, 137, -1, 139, 140, - 141, -1, 143, 144, 145, -1, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, 158, 159, -1, - 161, 162, 163, 164, -1, 166, -1, 168, -1, -1, - -1, 172, 173, 174, -1, 176, -1, 178, -1, 180, - 181, 182, -1, 184, 185, 186, 187, 188, 189, 190, - -1, 192, 193, 194, 195, -1, 197, 198, 199, 200, - 201, 202, -1, 204, -1, 206, 207, 208, 209, 210, - 211, 212, 213, -1, 215, -1, 217, -1, -1, 220, - -1, 222, 223, 224, 225, 226, 227, -1, -1, 230, - -1, 232, -1, -1, 235, 236, 237, -1, -1, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, - 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, -1, 266, 267, 268, 269, 270, - -1, 272, 273, -1, 275, -1, 277, 278, 279, 280, - 281, 282, -1, 284, 285, 286, -1, 288, 289, 290, - -1, -1, 293, 294, -1, 296, -1, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, -1, 310, - 311, 312, 313, 314, 315, 316, 317, 318, -1, 320, - 321, 322, 323, 324, 325, -1, 327, 328, 329, 330, - 331, 332, 333, 334, -1, 336, 337, 338, 339, 340, - 341, 342, 343, 344, 345, 346, 347, 348, -1, 350, - 351, -1, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 364, 365, 366, 367, -1, 369, 370, - 371, 372, 373, -1, 375, 376, 377, 378, 379, -1, - 381, 382, 383, 384, -1, 386, 387, 388, 389, 390, - 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, - 401, -1, 403, 404, -1, 406, -1, 408, 409, 410, - 411, 412, -1, 414, 415, -1, -1, 418, 419, 420, - 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, - 431, -1, -1, 434, 435, 436, 437, 438, -1, -1, - 441, 442, 443, 444, 445, 446, 447, -1, 449, -1, - 451, 452, 453, 454, 455, -1, -1, 458, -1, -1, - 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, - 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, - 481, 3, 4, 5, -1, -1, -1, 9, 489, 490, - -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, - 22, 23, 24, 25, 26, 27, -1, 29, 30, 31, - -1, -1, -1, -1, -1, -1, -1, 39, 40, -1, - 42, 43, 44, -1, 46, 47, 48, 49, 50, -1, - 52, 53, -1, 55, 56, 57, 58, 59, 60, -1, - -1, 63, 64, 65, 66, 67, -1, 69, 70, 71, - 72, 73, -1, -1, -1, 77, 78, 79, 80, 81, - 82, -1, 84, 85, 86, -1, 88, 89, 90, 91, - 92, 93, -1, -1, 96, 97, 98, -1, -1, -1, - -1, -1, -1, -1, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, -1, 117, -1, 119, 120, 121, - 122, 123, 124, -1, 126, 127, 128, 129, 130, -1, - -1, 133, 134, 135, 136, 137, -1, 139, 140, 141, - -1, 143, 144, 145, -1, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, 158, 159, -1, 161, - 162, 163, 164, -1, 166, -1, 168, -1, -1, -1, - 172, 173, 174, -1, 176, -1, 178, -1, 180, 181, - 182, -1, 184, 185, 186, 187, 188, 189, 190, -1, - 192, 193, 194, 195, -1, 197, 198, 199, 200, 201, - 202, -1, 204, -1, 206, 207, 208, 209, 210, 211, - 212, 213, -1, 215, -1, 217, -1, -1, 220, -1, - 222, 223, 224, 225, 226, 227, -1, -1, 230, -1, - 232, -1, -1, 235, 236, 237, -1, -1, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, -1, 266, 267, 268, 269, 270, -1, - 272, 273, -1, 275, -1, 277, 278, 279, 280, 281, - 282, -1, 284, 285, 286, -1, 288, 289, 290, -1, - -1, 293, 294, -1, 296, -1, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, -1, 310, 311, - 312, 313, 314, 315, 316, 317, 318, -1, 320, 321, - 322, 323, 324, 325, -1, 327, 328, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 346, 347, 348, -1, 350, 351, - -1, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, -1, 369, 370, 371, - 372, 373, -1, 375, 376, 377, 378, 379, -1, 381, - 382, 383, 384, -1, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - -1, 403, 404, -1, 406, -1, 408, 409, 410, 411, - 412, -1, 414, 415, -1, -1, 418, 419, 420, 421, - 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, - -1, -1, 434, 435, 436, 437, 438, -1, -1, 441, - 442, 443, 444, 445, 446, 447, -1, 449, -1, 451, - 452, 453, 454, 455, -1, -1, 458, -1, -1, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, - -1, -1, 8, -1, -1, 11, -1, 489, 490, 15, - 16, 17, 18, 19, -1, 8, -1, -1, 11, -1, - -1, -1, 15, 16, 17, 18, 19, -1, 34, -1, - -1, -1, 38, -1, -1, -1, 42, -1, -1, -1, - -1, 34, -1, 49, -1, -1, -1, -1, -1, 42, - 8, -1, -1, 11, -1, -1, 49, 15, 16, 17, - 18, 19, -1, 8, -1, -1, 11, -1, 74, -1, - 15, 16, 17, 18, 19, -1, 34, -1, -1, -1, - -1, 74, -1, -1, 42, -1, -1, -1, -1, 34, - -1, 49, 37, -1, -1, -1, -1, 42, -1, -1, - -1, -1, -1, -1, 49, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 74, -1, -1, 125, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 74, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 483, -1, 444, 486, 487, 488, + -1, 490, 491, 492, 493, 494, 495, -1, -1, -1, + 381, 500, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 8, -1, -1, 11, -1, -1, -1, - 15, 16, 17, 18, 19, -1, -1, -1, -1, 175, - -1, -1, 165, -1, -1, -1, -1, 170, -1, 34, - -1, -1, 175, -1, -1, 191, -1, 42, -1, -1, - 196, -1, -1, -1, 49, -1, -1, -1, 191, -1, - -1, -1, -1, 196, -1, -1, 164, -1, -1, -1, - -1, -1, 218, 219, -1, -1, -1, 175, -1, 74, - -1, -1, -1, -1, -1, 218, 219, 233, -1, -1, - 175, -1, -1, 191, -1, -1, -1, -1, 196, -1, - 233, -1, -1, -1, -1, -1, 191, -1, -1, -1, - -1, 196, -1, -1, -1, -1, -1, -1, -1, -1, - 218, 219, -1, -1, -1, 271, -1, -1, 274, -1, - -1, -1, -1, 218, 219, 233, -1, -1, 271, -1, - -1, 274, 288, -1, -1, 291, -1, -1, 233, -1, - -1, -1, -1, -1, -1, 288, -1, -1, 291, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 271, -1, -1, 274, -1, -1, -1, - 175, -1, -1, -1, -1, -1, 271, -1, -1, 274, - 288, -1, -1, 291, -1, -1, 191, -1, -1, -1, - -1, 196, -1, 288, -1, -1, 291, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 314, -1, -1, -1, - -1, -1, -1, 218, 219, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 380, -1, -1, -1, 233, -1, - -1, -1, -1, 8, -1, -1, 11, 380, -1, -1, - 15, 16, 17, 18, 19, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, - -1, -1, 37, -1, -1, -1, 271, 42, -1, 274, - -1, -1, 380, -1, 49, -1, -1, -1, -1, -1, - -1, -1, -1, 288, 440, 380, 291, 8, -1, -1, - 11, -1, -1, -1, 15, 16, 17, 18, 19, 74, - -1, -1, -1, -1, 309, -1, -1, -1, -1, -1, - -1, -1, -1, 34, -1, -1, -1, -1, -1, -1, - -1, 42, -1, -1, -1, -1, 482, -1, 49, 485, - 486, 487, -1, 489, 490, 491, 492, 493, 494, 482, - -1, -1, 485, 486, 487, -1, 489, 490, 491, 492, - 493, 494, -1, 74, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 482, 380, -1, 485, 486, 487, - -1, 489, 490, 491, 492, 493, 494, 482, -1, -1, - 485, 486, 487, -1, 489, 490, 491, 492, 493, 494, - 175, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 191, -1, -1, -1, - -1, 196, -1, -1, -1, -1, 8, -1, -1, 11, - -1, -1, -1, 15, 16, 17, 18, 19, -1, -1, - -1, -1, -1, 218, 219, -1, -1, -1, -1, 170, - -1, -1, 34, -1, 175, 37, -1, -1, 233, -1, - 42, -1, -1, -1, -1, -1, -1, 49, -1, -1, - 191, -1, -1, -1, -1, 196, -1, 482, -1, -1, - 485, 486, 487, -1, 489, 490, 491, 492, 493, 494, - -1, -1, 74, -1, -1, -1, 271, 218, 219, 274, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 8, 233, 288, 11, -1, 291, -1, 15, 16, - 17, 18, 19, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 34, -1, -1, - -1, -1, -1, -1, -1, 42, -1, -1, -1, -1, - 271, -1, 49, 274, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 8, -1, 288, 11, -1, - 291, -1, 15, 16, 17, 18, 19, 74, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 34, -1, 175, 37, -1, -1, -1, -1, 42, - -1, -1, -1, -1, -1, 380, 49, -1, -1, 191, - -1, -1, -1, -1, 196, -1, -1, -1, -1, 8, - -1, -1, 11, -1, -1, -1, 15, 16, 17, 18, - 19, 74, -1, -1, -1, -1, 218, 219, -1, -1, - -1, -1, -1, -1, -1, 34, -1, -1, -1, -1, - -1, 233, -1, 42, 8, -1, -1, 11, -1, 380, - 49, -1, 16, 17, 18, 19, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 175, -1, - 34, -1, -1, -1, -1, 74, -1, -1, 42, 271, - -1, -1, 274, -1, 191, 49, -1, -1, -1, 196, - -1, -1, -1, -1, -1, -1, 288, 482, -1, 291, - 485, 486, 487, -1, 489, 490, 491, 492, 493, 494, - 74, 218, 219, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 175, -1, -1, -1, 233, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 191, -1, - -1, -1, -1, 196, -1, -1, -1, -1, -1, -1, - -1, 482, -1, -1, 485, 486, 487, -1, 489, 490, - 491, 492, 493, 494, 271, 218, 219, 274, -1, -1, - -1, -1, -1, -1, -1, -1, 175, -1, -1, -1, - 233, 288, -1, -1, 291, -1, -1, -1, 380, -1, - -1, -1, 191, -1, -1, -1, -1, 196, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 175, -1, -1, -1, -1, -1, -1, 271, 218, - 219, 274, -1, -1, -1, -1, -1, 191, -1, -1, - -1, -1, 196, -1, 233, 288, -1, 8, 291, -1, - 11, -1, -1, -1, 15, 16, 17, 18, 19, -1, - -1, -1, -1, -1, 218, 219, -1, -1, -1, -1, - -1, -1, -1, 34, -1, -1, -1, -1, -1, 233, - -1, 42, 271, 380, -1, 274, -1, -1, 49, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 288, - 482, -1, 291, 485, 486, 487, -1, 489, 490, 491, - 492, 493, 494, 74, -1, -1, 413, 271, -1, -1, - 274, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 288, -1, -1, 380, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 3, -1, 483, -1, -1, 486, 487, 488, -1, 490, + 491, 492, 493, 494, 495, -1, -1, 498, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, + 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, + 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, + 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, + 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, + 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, + 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, + 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, + 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, + 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, + 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, + 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, + 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, + 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, + 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, + 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 3, -1, -1, -1, -1, -1, -1, -1, -1, 492, + -1, -1, -1, -1, -1, -1, -1, -1, 21, 22, + 23, 24, 25, 26, 27, 28, -1, 30, 31, 32, + -1, -1, -1, -1, -1, -1, -1, 40, 41, -1, + 43, 44, 45, -1, 47, 48, 49, 50, 51, -1, + 53, 54, -1, 56, 57, 58, 59, 60, 61, -1, + -1, 64, 65, 66, 67, 68, -1, 70, 71, 72, + 73, 74, -1, -1, -1, 78, 79, 80, 81, 82, + 83, -1, 85, 86, 87, -1, 89, 90, 91, 92, + 93, 94, -1, -1, 97, 98, 99, -1, -1, -1, + -1, -1, -1, -1, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, + 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, -1, 160, -1, 162, + 163, 164, 165, -1, 167, -1, 169, -1, -1, -1, + 173, 174, 175, -1, 177, -1, 179, -1, 181, 182, + 183, -1, 185, 186, 187, 188, 189, 190, 191, -1, + 193, 194, 195, 196, -1, 198, 199, 200, 201, 202, + 203, -1, 205, -1, 207, 208, 209, 210, 211, 212, + 213, 214, -1, 216, -1, 218, -1, -1, 221, -1, + 223, 224, 225, 226, 227, 228, -1, -1, 231, -1, + 233, -1, -1, 236, 237, 238, -1, -1, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, -1, 267, 268, 269, 270, 271, -1, + 273, 274, -1, 276, -1, 278, 279, 280, 281, 282, + 283, -1, 285, 286, -1, -1, 289, 290, 291, -1, + -1, 294, 295, -1, 297, -1, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, -1, 311, 312, + 313, 314, 315, 316, 317, 318, 319, -1, 321, 322, + 323, 324, 325, 326, -1, 328, 329, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, + -1, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, + 373, 374, -1, 376, 377, 378, 379, 380, -1, 382, + 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + -1, 404, 405, -1, 407, -1, 409, 410, 411, 412, + 413, -1, 415, 416, -1, -1, 419, 420, 421, 422, + 423, -1, 425, 426, 427, 428, 429, 430, 431, 432, + -1, -1, 435, 436, 437, 438, 439, -1, -1, 442, + 443, 444, 445, 446, 447, 448, -1, 450, -1, 452, + 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 3, 4, 5, -1, -1, -1, 9, -1, -1, 492, + -1, -1, -1, -1, -1, -1, -1, -1, 21, 22, + 23, 24, 25, 26, 27, 28, -1, 30, 31, 32, + -1, -1, -1, -1, -1, -1, -1, 40, 41, -1, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, -1, 56, 57, 58, 59, 60, 61, -1, + -1, 64, 65, 66, 67, 68, -1, 70, 71, 72, + 73, 74, -1, 76, -1, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, + 93, 94, -1, 96, 97, 98, 99, 100, 101, 102, + 103, -1, -1, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, -1, 120, 121, 122, + 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, 160, -1, 162, + 163, 164, 165, -1, 167, -1, 169, 170, -1, 172, + 173, 174, 175, 176, 177, -1, 179, -1, 181, 182, + 183, -1, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, -1, 198, 199, 200, 201, 202, + 203, -1, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, -1, 216, -1, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, -1, -1, 231, 232, + 233, 234, -1, 236, 237, 238, -1, -1, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, 266, 267, 268, 269, 270, 271, -1, + 273, 274, 275, 276, -1, 278, 279, 280, 281, 282, + 283, -1, 285, 286, 287, -1, 289, 290, 291, -1, + -1, 294, 295, 296, 297, 298, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, -1, 311, 312, + 313, 314, 315, 316, 317, 318, 319, -1, 321, 322, + 323, 324, 325, 326, -1, 328, 329, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + -1, 404, 405, -1, 407, 408, 409, 410, 411, 412, + 413, -1, 415, 416, -1, -1, 419, 420, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, + -1, -1, 435, 436, 437, 438, 439, 440, -1, 442, + 443, 444, 445, 446, 447, 448, -1, 450, 451, 452, + 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 3, 4, 5, -1, -1, -1, 9, 490, 491, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 21, 22, + 23, 24, 25, 26, 27, 28, -1, 30, 31, 32, + -1, -1, -1, -1, -1, -1, -1, 40, 41, -1, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, -1, 56, 57, 58, 59, 60, 61, -1, + -1, 64, 65, 66, 67, 68, -1, 70, 71, 72, + 73, 74, -1, 76, -1, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, + 93, 94, -1, 96, 97, 98, 99, 100, 101, 102, + 103, -1, -1, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, -1, 120, 121, 122, + 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, 160, -1, 162, + 163, 164, 165, -1, 167, -1, 169, 170, -1, 172, + 173, 174, 175, 176, 177, -1, 179, -1, 181, 182, + 183, -1, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, -1, 198, 199, 200, 201, 202, + 203, -1, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, -1, 216, -1, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, -1, -1, 231, 232, + 233, 234, -1, 236, 237, 238, -1, -1, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, 266, 267, 268, 269, 270, 271, -1, + 273, 274, 275, 276, -1, 278, 279, 280, 281, 282, + 283, -1, 285, 286, 287, -1, 289, 290, 291, -1, + -1, 294, 295, 296, 297, 298, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, -1, 311, 312, + 313, 314, 315, 316, 317, 318, 319, -1, 321, 322, + 323, 324, 325, 326, -1, 328, 329, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + -1, 404, 405, -1, 407, 408, 409, 410, 411, 412, + 413, -1, 415, 416, -1, -1, 419, 420, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, + -1, -1, 435, 436, 437, 438, 439, 440, -1, 442, + 443, 444, 445, 446, 447, 448, -1, 450, 451, 452, + 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + 3, 4, 5, -1, -1, -1, 9, 490, 491, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 21, 22, + 23, 24, 25, 26, 27, 28, -1, 30, 31, 32, + -1, -1, -1, -1, -1, -1, -1, 40, 41, -1, + 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, -1, 56, 57, 58, 59, 60, 61, -1, + -1, 64, 65, 66, 67, 68, -1, 70, 71, 72, + 73, 74, -1, 76, -1, 78, 79, 80, 81, 82, + 83, 84, 85, 86, 87, -1, 89, 90, 91, 92, + 93, 94, -1, 96, 97, 98, 99, 100, 101, 102, + 103, -1, -1, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, -1, 118, -1, 120, 121, 122, + 123, 124, 125, -1, 127, 128, 129, 130, 131, -1, + -1, 134, 135, 136, 137, 138, -1, 140, 141, 142, + -1, 144, 145, 146, -1, 148, 149, 150, 151, 152, + 153, 154, 155, 156, 157, 158, 159, 160, -1, 162, + 163, 164, 165, -1, 167, -1, 169, 170, -1, 172, + 173, 174, 175, 176, 177, -1, 179, -1, 181, 182, + 183, -1, 185, 186, 187, 188, 189, 190, 191, 192, + 193, 194, 195, 196, -1, 198, 199, 200, 201, 202, + 203, -1, 205, 206, 207, 208, 209, 210, 211, 212, + 213, 214, -1, 216, -1, 218, 219, 220, 221, 222, + 223, 224, 225, 226, 227, 228, -1, -1, 231, 232, + 233, 234, -1, 236, 237, 238, -1, -1, 241, 242, + 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, + 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, + 263, 264, 265, 266, 267, 268, 269, 270, 271, -1, + 273, 274, 275, 276, -1, 278, 279, 280, 281, 282, + 283, -1, 285, 286, 287, -1, 289, 290, 291, -1, + -1, 294, 295, 296, 297, 298, 299, 300, 301, 302, + 303, 304, 305, 306, 307, 308, 309, -1, 311, 312, + 313, 314, 315, 316, 317, 318, 319, -1, 321, 322, + 323, 324, 325, 326, -1, 328, 329, 330, 331, 332, + 333, 334, 335, -1, 337, 338, 339, 340, 341, 342, + 343, 344, 345, 346, 347, 348, 349, -1, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, -1, 370, 371, 372, + 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, + 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, + 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, + -1, 404, 405, -1, 407, 408, 409, 410, 411, 412, + 413, -1, 415, 416, -1, -1, 419, 420, 421, 422, + 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, + -1, -1, 435, 436, 437, 438, 439, 440, -1, 442, + 443, 444, 445, 446, 447, 448, -1, 450, 451, 452, + 453, 454, 455, 456, -1, -1, 459, -1, -1, 462, + 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, + 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, + -1, -1, 8, -1, -1, 11, -1, 490, 491, 15, + 16, 17, 18, 19, 20, 8, -1, -1, 11, -1, + -1, -1, 15, 16, 17, 18, 19, 20, -1, 35, + -1, -1, -1, 39, -1, -1, -1, 43, -1, -1, + -1, -1, 35, -1, 50, -1, -1, -1, -1, -1, + 43, 8, -1, -1, 11, -1, -1, 50, 15, 16, + 17, 18, 19, 20, 8, -1, -1, 11, -1, 75, + -1, 15, 16, 17, 18, 19, 20, -1, 35, -1, + -1, -1, 75, -1, -1, -1, 43, -1, -1, -1, + -1, 35, -1, 50, 38, -1, -1, -1, -1, 43, + 8, -1, -1, 11, -1, -1, 50, 15, 16, 17, + 18, 19, 20, -1, -1, -1, -1, -1, 75, -1, + 126, -1, -1, -1, -1, -1, -1, 35, -1, -1, + -1, 75, -1, -1, -1, 43, -1, -1, -1, -1, + -1, -1, 50, -1, -1, 8, -1, -1, 11, -1, + -1, -1, 15, 16, 17, 18, 19, 20, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 75, -1, -1, + 176, -1, 35, 166, -1, 38, -1, -1, 171, -1, + 43, -1, -1, 176, -1, -1, 192, 50, -1, -1, + -1, 197, -1, -1, -1, -1, -1, -1, -1, 192, + -1, -1, -1, -1, 197, -1, -1, -1, 165, -1, + -1, -1, 75, 219, 220, -1, -1, -1, -1, 176, + -1, -1, -1, -1, -1, -1, 219, 220, 234, -1, + -1, -1, 176, -1, -1, 192, -1, -1, -1, -1, + 197, 234, -1, -1, -1, -1, -1, -1, 192, -1, + -1, -1, -1, 197, -1, -1, -1, -1, -1, -1, + -1, -1, 219, 220, -1, -1, 272, -1, 176, 275, + -1, -1, -1, -1, -1, 219, 220, 234, -1, 272, + -1, -1, 275, 289, 192, -1, 292, -1, -1, 197, + 234, -1, -1, -1, -1, -1, 289, -1, -1, 292, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 219, 220, 176, -1, 272, -1, -1, 275, -1, + -1, -1, -1, -1, -1, -1, 234, -1, 272, 192, + -1, 275, 289, -1, 197, 292, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 289, -1, -1, 292, -1, + -1, -1, -1, -1, -1, -1, 219, 220, 315, -1, + -1, -1, -1, -1, 272, -1, -1, 275, -1, -1, + -1, 234, -1, -1, -1, 381, -1, -1, -1, -1, + -1, 289, -1, -1, 292, -1, -1, -1, 381, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 310, -1, -1, -1, -1, -1, -1, 272, + -1, -1, 275, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 381, -1, 289, -1, -1, 292, + -1, -1, -1, -1, -1, 441, -1, 381, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 482, -1, -1, 485, 486, - 487, 380, 489, 490, 491, 492, 493, 494, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 175, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 380, -1, -1, -1, - 191, -1, -1, -1, -1, 196, -1, -1, -1, 482, - -1, -1, 485, 486, 487, -1, 489, 490, 491, 492, - 493, 494, -1, -1, -1, -1, -1, 218, 219, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 233, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 381, -1, -1, -1, 483, -1, -1, + 486, 487, 488, -1, 490, 491, 492, 493, 494, 495, + 483, -1, -1, 486, 487, 488, -1, 490, 491, 492, + 493, 494, 495, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 381, -1, + -1, -1, -1, -1, -1, -1, 483, -1, -1, 486, + 487, 488, -1, 490, 491, 492, 493, 494, 495, 483, + -1, -1, 486, 487, 488, -1, 490, 491, 492, 493, + 494, 495, -1, -1, 8, -1, -1, 11, -1, -1, + -1, 15, 16, 17, 18, 19, 20, -1, -1, -1, + -1, -1, -1, -1, -1, 483, -1, -1, 486, 487, + 488, 35, 490, 491, 492, 493, 494, 495, -1, 43, + -1, -1, -1, -1, -1, -1, 50, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 482, -1, -1, 485, 486, 487, -1, - 489, 490, 491, 492, 493, 494, -1, -1, -1, -1, - 271, -1, -1, 274, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 288, 482, -1, - 291, 485, 486, 487, -1, 489, 490, 491, 492, 493, - 494, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 483, 75, -1, 486, 487, 488, -1, 490, 491, 492, + 493, 494, 495, 8, -1, -1, 11, -1, -1, -1, + 15, 16, 17, 18, 19, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 35, -1, 8, 38, -1, 11, -1, -1, 43, 15, + 16, 17, 18, 19, 20, 50, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, + -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, + 75, -1, -1, -1, 50, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 171, -1, -1, + -1, -1, 176, -1, -1, -1, -1, -1, -1, 75, + -1, -1, -1, -1, -1, -1, -1, -1, 192, -1, + -1, 8, -1, 197, 11, -1, -1, -1, 15, 16, + 17, 18, 19, 20, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 219, 220, -1, 35, -1, + -1, 38, -1, -1, -1, -1, 43, -1, -1, -1, + 234, -1, -1, 50, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 176, -1, -1, -1, -1, -1, -1, 75, -1, + -1, -1, -1, -1, -1, -1, -1, 192, 272, -1, + -1, 275, 197, -1, -1, -1, -1, -1, -1, -1, + 176, -1, -1, -1, -1, 289, -1, -1, 292, -1, + -1, -1, -1, -1, 219, 220, 192, -1, -1, -1, + -1, 197, -1, -1, -1, -1, -1, -1, -1, 234, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 219, 220, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 234, -1, + -1, -1, -1, -1, -1, -1, -1, 272, -1, -1, + 275, -1, -1, -1, -1, -1, -1, -1, -1, 176, + -1, -1, 8, -1, 289, 11, -1, 292, -1, 15, + 16, 17, 18, 19, 20, 192, 272, 381, -1, 275, + 197, -1, -1, -1, -1, -1, -1, -1, -1, 35, + -1, -1, -1, 289, -1, -1, 292, 43, -1, -1, + -1, -1, 219, 220, 50, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 234, -1, -1, + -1, -1, -1, -1, -1, 8, -1, -1, 11, 75, + -1, -1, 15, 16, 17, 18, 19, 20, 8, -1, + -1, 11, -1, -1, -1, 15, -1, -1, 18, 19, + 20, -1, 35, -1, -1, 272, 381, -1, 275, -1, + 43, -1, -1, -1, -1, -1, -1, 50, -1, -1, + -1, -1, 289, 43, -1, 292, -1, -1, -1, 483, + 50, -1, 486, 487, 488, 381, 490, 491, 492, 493, + 494, 495, 75, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 75, -1, -1, -1, -1, + -1, -1, 8, -1, -1, 11, -1, -1, 414, 15, + -1, -1, 18, 19, 20, -1, -1, -1, -1, -1, + 176, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 192, 43, -1, -1, + -1, 197, -1, -1, 50, -1, -1, -1, 483, -1, + -1, 486, 487, 488, 381, 490, 491, 492, 493, 494, + 495, -1, -1, 219, 220, -1, -1, -1, -1, 75, + -1, -1, -1, -1, -1, -1, -1, 483, 234, -1, + 486, 487, 488, 176, 490, 491, 492, 493, 494, 495, + -1, -1, -1, -1, -1, -1, 176, -1, -1, 192, + -1, -1, -1, -1, 197, -1, -1, -1, -1, -1, + -1, -1, 192, -1, -1, -1, 272, 197, -1, 275, + -1, -1, -1, -1, -1, -1, 219, 220, -1, -1, + -1, -1, -1, 289, -1, -1, 292, -1, -1, 219, + 220, 234, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 234, -1, 483, -1, -1, 486, + 487, 488, -1, 490, 491, 492, 493, 494, 495, -1, + 176, -1, -1, -1, -1, -1, -1, -1, -1, 272, + -1, -1, 275, -1, -1, -1, 192, -1, -1, -1, + -1, 197, 272, -1, -1, 275, 289, -1, -1, 292, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 289, + -1, -1, -1, 219, 220, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 381, -1, -1, 234, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 380, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 275, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 289, -1, -1, -1, -1, 381, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 381, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 483, -1, -1, + 486, 487, 488, -1, 490, 491, 492, 493, 494, 495, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 381, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 483, -1, -1, 486, 487, 488, -1, 490, 491, 492, + 493, 494, 495, 483, -1, -1, 486, 487, 488, -1, + 490, 491, 492, 493, 494, 495, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 3, -1, 5, - -1, 482, -1, -1, 485, 486, 487, -1, 489, 490, - 491, 492, 493, 494, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, 44, -1, - 46, 47, 48, 49, 50, -1, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, - 66, 67, 68, 69, 70, 71, 72, 73, 74, -1, - 76, 77, 78, 79, 80, 81, 82, -1, 84, 85, - 86, 87, 88, 89, 90, 91, 92, 93, 94, -1, - 96, 97, 98, 99, 100, 101, -1, 103, 104, 105, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, - 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, - 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, - 166, 167, 168, -1, 170, -1, 172, 173, 174, -1, - 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, -1, 192, 193, 194, 195, - 196, 197, 198, 199, 200, 201, 202, 203, 204, -1, - 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, - 216, 217, -1, -1, 220, -1, 222, 223, 224, 225, - 226, 227, 228, 229, 230, -1, 232, -1, 234, 235, - 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, -1, - 266, 267, 268, 269, 270, 271, 272, 273, -1, 275, - 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, - 286, 287, 288, 289, 290, 291, 292, 293, 294, -1, - 296, -1, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, - 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, - 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, 349, 350, 351, -1, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, - 376, 377, 378, 379, -1, 381, 382, 383, 384, 385, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, - 406, -1, 408, 409, 410, 411, 412, 413, 414, 415, - 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, - 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, - 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, - 446, 447, 448, 449, -1, 451, 452, 453, 454, 455, - 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, - 37, 38, 39, 40, 41, 42, 43, 44, -1, 46, - 47, 48, 49, 50, -1, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, - 67, 68, 69, 70, 71, 72, 73, 74, -1, 76, - 77, 78, 79, 80, 81, 82, -1, 84, 85, 86, - 87, 88, 89, 90, 91, 92, 93, 94, -1, 96, - 97, 98, 99, 100, 101, -1, 103, 104, 105, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, - 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, - 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, - 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, - 167, 168, -1, 170, -1, 172, 173, 174, -1, 176, - 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, - 187, 188, 189, 190, -1, 192, 193, 194, 195, 196, - 197, 198, 199, 200, 201, 202, 203, 204, -1, 206, - 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, - 217, -1, -1, 220, -1, 222, 223, 224, 225, 226, - 227, 228, 229, 230, -1, 232, -1, 234, 235, 236, - 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, -1, 266, - 267, 268, 269, 270, 271, 272, 273, -1, 275, 276, - 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, - 287, 288, 289, 290, 291, 292, 293, 294, -1, 296, - -1, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, - 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, - 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, - 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, - 347, 348, 349, 350, 351, -1, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, - 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, - 377, 378, 379, -1, 381, 382, 383, 384, 385, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - -1, 408, 409, 410, 411, 412, 413, 414, 415, 416, - 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, - 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, - 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, - 447, 448, 449, -1, 451, 452, 453, 454, 455, 456, - 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, - 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, - 477, 478, 479, 480, 481, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, -1, 46, 47, - 48, 49, 50, -1, 52, 53, 54, 55, 56, 57, - 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 70, 71, 72, 73, 74, -1, 76, 77, - 78, 79, 80, 81, 82, -1, 84, 85, 86, 87, - 88, 89, 90, 91, 92, 93, 94, -1, 96, 97, - 98, 99, 100, 101, -1, 103, 104, 105, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, - 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, - 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, -1, 170, -1, 172, 173, 174, -1, 176, 177, - 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, - 188, 189, 190, -1, 192, 193, 194, 195, 196, 197, - 198, 199, 200, 201, 202, 203, 204, -1, 206, 207, - 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, - -1, -1, 220, -1, 222, 223, 224, 225, 226, 227, - 228, 229, 230, -1, 232, -1, 234, 235, 236, 237, - 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, -1, 266, 267, - 268, 269, 270, 271, 272, 273, -1, 275, 276, 277, - 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, - 288, 289, 290, 291, 292, 293, 294, -1, 296, -1, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, - 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, - 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, - 348, 349, 350, 351, -1, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, -1, 381, 382, 383, 384, 385, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, 402, 403, 404, 405, 406, -1, - 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, - 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, - 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, - 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, - 448, 449, -1, 451, 452, 453, 454, 455, 456, 457, - 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 478, 479, 480, 481, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 20, 21, 22, 23, 24, 25, 26, 27, -1, - 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, - 39, 40, -1, 42, 43, 44, 45, 46, 47, 48, - 49, 50, 51, 52, 53, -1, 55, 56, 57, 58, - 59, 60, -1, 62, 63, 64, 65, 66, 67, -1, - 69, 70, 71, 72, 73, -1, 75, -1, 77, 78, - 79, 80, 81, 82, 83, 84, 85, 86, -1, 88, - 89, 90, 91, 92, 93, -1, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, -1, 117, -1, - 119, 120, 121, 122, 123, 124, -1, 126, 127, 128, - 129, 130, -1, -1, 133, 134, 135, 136, 137, -1, - 139, 140, 141, -1, 143, 144, 145, -1, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, -1, - 159, -1, 161, 162, 163, 164, -1, 166, -1, 168, - 169, -1, 171, 172, 173, 174, 175, 176, -1, 178, - -1, 180, 181, 182, -1, 184, 185, 186, 187, 188, - 189, 190, 191, 192, 193, 194, 195, -1, 197, 198, - 199, 200, 201, 202, -1, 204, 205, 206, 207, 208, - 209, 210, 211, 212, 213, -1, 215, -1, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, -1, - -1, 230, 231, 232, 233, -1, 235, 236, 237, 238, - 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, - 269, 270, -1, 272, 273, 274, 275, -1, 277, 278, - 279, 280, 281, 282, -1, 284, 285, -1, -1, 288, - 289, 290, -1, -1, 293, 294, 295, 296, 297, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - -1, 310, 311, 312, 313, 314, 315, 316, 317, 318, - -1, 320, 321, 322, 323, 324, 325, -1, 327, 328, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, - -1, 350, 351, 352, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 364, 365, 366, 367, -1, - 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, - 379, 380, 381, 382, 383, 384, -1, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, - 399, 400, 401, -1, 403, 404, -1, 406, 407, 408, - 409, 410, 411, 412, -1, 414, 415, -1, -1, 418, - 419, 420, 421, 422, -1, 424, 425, 426, 427, 428, - 429, 430, 431, -1, -1, 434, 435, 436, 437, 438, - 439, -1, 441, 442, 443, 444, 445, 446, 447, -1, - 449, 450, 451, 452, 453, 454, 455, -1, -1, 458, - -1, -1, 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, - 479, 480, 481, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, -1, -1, -1, 39, - 40, -1, 42, 43, 44, 45, 46, 47, 48, 49, - 50, 51, 52, 53, -1, 55, 56, 57, 58, 59, - 60, -1, -1, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, 75, -1, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, 95, 96, 97, 98, -1, - -1, -1, 102, -1, -1, -1, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, -1, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, -1, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, 169, - -1, 171, 172, 173, 174, 175, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, 205, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, -1, -1, - 230, 231, 232, 233, -1, 235, 236, 237, -1, -1, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - 270, -1, 272, 273, 274, 275, -1, 277, 278, 279, - 280, 281, 282, -1, 284, 285, -1, -1, 288, 289, - 290, -1, -1, 293, 294, 295, 296, 297, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, -1, 369, - 370, 371, 372, 373, -1, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, -1, 406, 407, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, -1, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, -1, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - 450, 451, 452, 453, 454, 455, -1, -1, 458, -1, - -1, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, 3, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, - 21, 22, 23, 24, 25, 26, 27, -1, 29, 30, - 31, -1, -1, -1, -1, -1, -1, -1, 39, 40, - -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, - -1, 52, 53, -1, 55, 56, 57, 58, 59, 60, - -1, -1, 63, 64, 65, 66, 67, 68, 69, 70, - 71, 72, 73, -1, -1, 76, 77, 78, 79, 80, - 81, 82, -1, 84, 85, 86, 87, 88, 89, 90, - 91, 92, 93, -1, -1, 96, 97, 98, -1, -1, - -1, -1, -1, -1, -1, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, -1, 117, -1, 119, 120, - 121, 122, 123, 124, -1, 126, 127, 128, 129, 130, - -1, -1, 133, 134, 135, 136, 137, -1, 139, 140, - 141, -1, 143, 144, 145, -1, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, -1, 159, -1, - 161, 162, 163, 164, -1, 166, 167, 168, -1, -1, - -1, 172, 173, 174, -1, 176, -1, 178, -1, 180, - 181, 182, -1, 184, 185, 186, 187, 188, 189, 190, - -1, 192, 193, 194, 195, -1, 197, 198, 199, 200, - 201, 202, -1, 204, -1, 206, 207, 208, 209, 210, - 211, 212, 213, -1, 215, -1, 217, -1, -1, 220, - -1, 222, 223, 224, 225, 226, 227, -1, -1, 230, - -1, 232, -1, -1, 235, 236, 237, -1, -1, 240, + -1, -1, 3, -1, 5, -1, -1, 483, -1, -1, + 486, 487, 488, -1, 490, 491, 492, 493, 494, 495, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, + 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, -1, 266, 267, 268, 269, 270, - -1, 272, 273, -1, 275, -1, 277, 278, 279, 280, - 281, 282, -1, 284, 285, -1, -1, 288, 289, 290, - -1, -1, 293, 294, -1, 296, -1, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, -1, 310, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, - 321, 322, 323, 324, 325, -1, 327, 328, 329, 330, - 331, 332, 333, 334, -1, 336, 337, 338, 339, 340, - 341, 342, 343, 344, 345, 346, 347, 348, -1, 350, - 351, -1, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 364, 365, 366, 367, -1, 369, 370, - 371, 372, 373, -1, 375, 376, 377, 378, 379, -1, - 381, 382, 383, 384, -1, 386, 387, 388, 389, 390, + 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, + 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, - 401, -1, 403, 404, -1, 406, -1, 408, 409, 410, - 411, 412, -1, 414, 415, -1, -1, 418, 419, 420, - 421, 422, -1, 424, 425, 426, 427, 428, 429, 430, - 431, -1, 433, 434, 435, 436, 437, 438, -1, -1, - 441, 442, 443, 444, 445, 446, 447, -1, 449, -1, - 451, 452, 453, 454, 455, -1, -1, 458, -1, -1, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, + 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, + 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, - 481, 3, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, - 22, 23, 24, 25, 26, 27, -1, 29, 30, 31, - -1, -1, -1, -1, -1, -1, -1, 39, 40, -1, - 42, 43, 44, -1, 46, 47, 48, 49, 50, -1, - 52, 53, -1, 55, 56, 57, 58, 59, 60, -1, - -1, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, -1, -1, -1, 77, 78, 79, 80, 81, - 82, -1, 84, 85, 86, 87, 88, 89, 90, 91, - 92, 93, -1, -1, 96, 97, 98, -1, -1, -1, - -1, -1, -1, -1, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, -1, 117, -1, 119, 120, 121, - 122, 123, 124, -1, 126, 127, 128, 129, 130, -1, - -1, 133, 134, 135, 136, 137, -1, 139, 140, 141, - -1, 143, 144, 145, -1, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, -1, 159, -1, 161, - 162, 163, 164, -1, 166, 167, 168, -1, -1, -1, - 172, 173, 174, -1, 176, -1, 178, -1, 180, 181, - 182, -1, 184, 185, 186, 187, 188, 189, 190, -1, - 192, 193, 194, 195, -1, 197, 198, 199, 200, 201, - 202, -1, 204, -1, 206, 207, 208, 209, 210, 211, - 212, 213, -1, 215, -1, 217, -1, -1, 220, -1, - 222, 223, 224, 225, 226, 227, -1, -1, 230, -1, - 232, 233, -1, 235, 236, 237, -1, -1, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, -1, 266, 267, 268, 269, 270, -1, - 272, 273, -1, 275, -1, 277, 278, 279, 280, 281, - 282, -1, 284, 285, -1, -1, 288, 289, 290, -1, - -1, 293, 294, -1, 296, -1, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, -1, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, - 322, 323, 324, 325, -1, 327, 328, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 346, 347, 348, -1, 350, 351, - -1, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, -1, 369, 370, 371, - 372, 373, -1, 375, 376, 377, 378, 379, -1, 381, - 382, 383, 384, -1, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - -1, 403, 404, -1, 406, -1, 408, 409, 410, 411, - 412, -1, 414, 415, -1, -1, 418, 419, 420, 421, - 422, -1, 424, 425, 426, 427, 428, 429, 430, 431, - -1, 433, 434, 435, 436, 437, 438, -1, -1, 441, - 442, 443, 444, 445, 446, 447, -1, 449, -1, 451, - 452, 453, 454, 455, -1, -1, 458, -1, -1, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, - 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 20, 21, 22, - 23, 24, 25, 26, 27, -1, 29, 30, 31, -1, - -1, -1, -1, -1, -1, -1, 39, 40, -1, 42, - 43, 44, -1, 46, 47, 48, 49, 50, -1, 52, - 53, -1, 55, 56, 57, 58, 59, 60, -1, -1, - 63, 64, 65, 66, 67, -1, 69, 70, 71, 72, - 73, -1, -1, -1, 77, 78, 79, 80, 81, 82, - -1, 84, 85, 86, -1, 88, 89, 90, 91, 92, - 93, -1, -1, 96, 97, 98, -1, -1, -1, -1, - -1, -1, -1, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, -1, 117, -1, 119, 120, 121, 122, - 123, 124, -1, 126, 127, 128, 129, 130, -1, -1, - 133, 134, 135, 136, 137, -1, 139, 140, 141, -1, - 143, 144, 145, -1, 147, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, 158, 159, -1, 161, 162, - 163, 164, -1, 166, -1, 168, -1, -1, -1, 172, - 173, 174, -1, 176, -1, 178, -1, 180, 181, 182, - -1, 184, 185, 186, 187, 188, 189, 190, -1, 192, - 193, 194, 195, -1, 197, 198, 199, 200, 201, 202, - -1, 204, -1, 206, 207, 208, 209, 210, 211, 212, - 213, -1, 215, -1, 217, -1, -1, 220, -1, 222, - 223, 224, 225, 226, 227, -1, -1, 230, -1, 232, - -1, -1, 235, 236, 237, -1, -1, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, -1, 266, 267, 268, 269, 270, -1, 272, - 273, -1, 275, -1, 277, 278, 279, 280, 281, 282, - -1, 284, 285, 286, -1, 288, 289, 290, -1, -1, - 293, 294, -1, 296, -1, 298, 299, 300, 301, 302, - 303, 304, 305, 306, 307, 308, -1, 310, 311, 312, - 313, 314, 315, 316, 317, 318, -1, 320, 321, 322, - 323, 324, 325, -1, 327, 328, 329, 330, 331, 332, - 333, 334, -1, 336, 337, 338, 339, 340, 341, 342, - 343, 344, 345, 346, 347, 348, -1, 350, 351, -1, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 364, 365, 366, 367, -1, 369, 370, 371, 372, - 373, -1, 375, 376, 377, 378, 379, -1, 381, 382, - 383, 384, -1, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 397, 398, 399, 400, 401, -1, - 403, 404, -1, 406, -1, 408, 409, 410, 411, 412, - -1, 414, 415, -1, -1, 418, 419, 420, 421, 422, - 423, 424, 425, 426, 427, 428, 429, 430, 431, -1, - -1, 434, 435, 436, 437, 438, -1, -1, 441, 442, - 443, 444, 445, 446, 447, -1, 449, -1, 451, 452, - 453, 454, 455, -1, -1, 458, -1, -1, 461, 462, - 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, - 473, 474, 475, 476, 477, 478, 479, 480, 481, 3, - -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, - 24, 25, 26, 27, -1, 29, 30, 31, 32, 33, - -1, -1, -1, -1, -1, 39, 40, -1, 42, 43, - 44, -1, 46, 47, 48, 49, 50, -1, 52, 53, - -1, 55, 56, 57, 58, 59, 60, -1, -1, 63, - 64, 65, 66, 67, -1, 69, 70, 71, 72, 73, - -1, -1, -1, 77, 78, 79, 80, 81, 82, -1, - 84, 85, 86, -1, 88, 89, 90, 91, 92, 93, - -1, -1, 96, 97, 98, -1, -1, -1, -1, -1, - -1, -1, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, -1, 117, -1, 119, 120, 121, 122, 123, - 124, -1, 126, 127, 128, 129, 130, -1, -1, 133, - 134, 135, 136, 137, -1, 139, 140, 141, -1, 143, - 144, 145, -1, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, -1, 159, -1, 161, 162, 163, - 164, -1, 166, -1, 168, -1, -1, -1, 172, 173, - 174, -1, 176, -1, 178, -1, 180, 181, 182, -1, - 184, 185, 186, 187, 188, 189, 190, -1, 192, 193, - 194, 195, -1, 197, 198, 199, 200, 201, 202, -1, - 204, -1, 206, 207, 208, 209, 210, 211, 212, 213, - -1, 215, -1, 217, -1, -1, 220, -1, 222, 223, - 224, 225, 226, 227, -1, -1, 230, -1, 232, -1, - -1, 235, 236, 237, -1, -1, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, -1, 266, 267, 268, 269, 270, -1, 272, 273, - -1, 275, -1, 277, 278, 279, 280, 281, 282, -1, - 284, 285, -1, -1, 288, 289, 290, -1, -1, 293, - 294, -1, 296, -1, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, -1, 310, 311, 312, 313, - 314, 315, 316, 317, 318, -1, 320, 321, 322, 323, - 324, 325, -1, 327, 328, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, -1, 350, 351, -1, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, -1, 369, 370, 371, 372, 373, - -1, 375, 376, 377, 378, 379, -1, 381, 382, 383, - 384, -1, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, -1, 403, - 404, -1, 406, -1, 408, 409, 410, 411, 412, -1, - 414, 415, -1, -1, 418, 419, 420, 421, 422, -1, - 424, 425, 426, 427, 428, 429, 430, 431, -1, -1, - 434, 435, 436, 437, 438, -1, -1, 441, 442, 443, - 444, 445, 446, 447, -1, 449, -1, 451, 452, 453, - 454, 455, -1, -1, 458, -1, -1, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 3, -1, - 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 20, 21, 22, 23, 24, - 25, 26, 27, -1, 29, 30, 31, -1, -1, -1, - -1, -1, -1, -1, 39, 40, -1, 42, 43, 44, - -1, 46, 47, 48, 49, 50, -1, 52, 53, -1, - 55, 56, 57, 58, 59, 60, -1, -1, 63, 64, - 65, 66, 67, -1, 69, 70, 71, 72, 73, -1, - -1, -1, 77, 78, 79, 80, 81, 82, -1, 84, - 85, 86, -1, 88, 89, 90, 91, 92, 93, -1, - -1, 96, 97, 98, -1, -1, -1, -1, -1, -1, - -1, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, -1, 117, -1, 119, 120, 121, 122, 123, 124, - -1, 126, 127, 128, 129, 130, -1, -1, 133, 134, - 135, 136, 137, -1, 139, 140, 141, -1, 143, 144, - 145, -1, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, -1, 159, -1, 161, 162, 163, 164, - -1, 166, -1, 168, -1, -1, -1, 172, 173, 174, - -1, 176, -1, 178, -1, 180, 181, 182, -1, 184, - 185, 186, 187, 188, 189, 190, -1, 192, 193, 194, - 195, -1, 197, 198, 199, 200, 201, 202, -1, 204, - -1, 206, 207, 208, 209, 210, 211, 212, 213, -1, - 215, -1, 217, -1, -1, 220, -1, 222, 223, 224, - 225, 226, 227, -1, -1, 230, -1, 232, -1, -1, - 235, 236, 237, -1, -1, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - -1, 266, 267, 268, 269, 270, -1, 272, 273, -1, - 275, -1, 277, 278, 279, 280, 281, 282, -1, 284, - 285, -1, 287, 288, 289, 290, -1, -1, 293, 294, - -1, 296, -1, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, -1, 310, 311, 312, 313, 314, - 315, 316, 317, 318, -1, 320, 321, 322, 323, 324, - 325, -1, 327, 328, 329, 330, 331, 332, 333, 334, - -1, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, -1, 350, 351, -1, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, -1, 369, 370, 371, 372, 373, -1, - 375, 376, 377, 378, 379, -1, 381, 382, 383, 384, - -1, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 397, 398, 399, 400, 401, -1, 403, 404, - -1, 406, -1, 408, 409, 410, 411, 412, -1, 414, - 415, -1, -1, 418, 419, 420, 421, 422, -1, 424, - 425, 426, 427, 428, 429, 430, 431, -1, -1, 434, - 435, 436, 437, 438, -1, -1, 441, 442, 443, 444, - 445, 446, 447, -1, 449, -1, 451, 452, 453, 454, - 455, -1, -1, 458, -1, -1, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 478, 479, 480, 481, 3, -1, 5, + 481, 482, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, - 26, 27, -1, 29, 30, 31, -1, -1, -1, -1, - -1, -1, -1, 39, 40, -1, 42, 43, 44, -1, - 46, 47, 48, 49, 50, -1, 52, 53, -1, 55, - 56, 57, 58, 59, 60, -1, -1, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, -1, -1, - -1, 77, 78, 79, 80, 81, 82, -1, 84, 85, - 86, -1, 88, 89, 90, 91, 92, 93, -1, -1, - 96, 97, 98, -1, -1, -1, -1, -1, -1, -1, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - -1, 117, -1, 119, 120, 121, 122, 123, 124, -1, - 126, 127, 128, 129, 130, -1, -1, 133, 134, 135, - 136, 137, -1, 139, 140, 141, -1, 143, 144, 145, - -1, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, -1, 159, -1, 161, 162, 163, 164, -1, - 166, -1, 168, -1, -1, -1, 172, 173, 174, -1, - 176, -1, 178, -1, 180, 181, 182, -1, 184, 185, - 186, 187, 188, 189, 190, -1, 192, 193, 194, 195, - -1, 197, 198, 199, 200, 201, 202, -1, 204, -1, - 206, 207, 208, 209, 210, 211, 212, 213, -1, 215, - -1, 217, -1, -1, 220, -1, 222, 223, 224, 225, - 226, 227, -1, -1, 230, -1, 232, -1, -1, 235, - 236, 237, -1, -1, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, -1, - 266, 267, 268, 269, 270, -1, 272, 273, -1, 275, - -1, 277, 278, 279, 280, 281, 282, -1, 284, 285, - -1, 287, 288, 289, 290, -1, -1, 293, 294, -1, - 296, -1, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, -1, 310, 311, 312, 313, 314, 315, - 316, 317, 318, -1, 320, 321, 322, 323, 324, 325, - -1, 327, 328, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, 350, 351, -1, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, -1, 369, 370, 371, 372, 373, -1, 375, - 376, 377, 378, 379, -1, 381, 382, 383, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, -1, 403, 404, -1, - 406, -1, 408, 409, 410, 411, 412, -1, 414, 415, - -1, -1, 418, 419, 420, 421, 422, -1, 424, 425, - 426, 427, 428, 429, 430, 431, -1, -1, 434, 435, - 436, 437, 438, -1, -1, 441, 442, 443, 444, 445, - 446, 447, -1, 449, -1, 451, 452, 453, 454, 455, - -1, -1, 458, -1, -1, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, 3, -1, -1, -1, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, + 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, + 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, + 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, + 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, + 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 20, 21, 22, 23, 24, 25, 26, - 27, -1, 29, 30, 31, 32, 33, -1, -1, -1, - -1, -1, 39, 40, -1, 42, 43, 44, -1, 46, - 47, 48, 49, 50, -1, 52, 53, -1, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, -1, 69, 70, 71, 72, 73, -1, -1, -1, - 77, 78, 79, 80, 81, 82, -1, 84, 85, 86, - -1, 88, 89, 90, 91, 92, 93, -1, -1, 96, - 97, 98, -1, -1, -1, -1, -1, -1, -1, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, -1, - 117, -1, 119, 120, 121, 122, 123, 124, -1, 126, - 127, 128, 129, 130, -1, -1, 133, 134, 135, 136, - 137, -1, 139, 140, 141, -1, 143, 144, 145, -1, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, -1, 159, -1, 161, 162, 163, 164, -1, 166, - -1, 168, -1, -1, -1, 172, 173, 174, -1, 176, - -1, 178, -1, 180, 181, 182, -1, 184, 185, 186, - 187, 188, 189, 190, -1, 192, 193, 194, 195, -1, - 197, 198, 199, 200, 201, 202, -1, 204, -1, 206, - 207, 208, 209, 210, 211, 212, 213, -1, 215, -1, - 217, -1, -1, 220, -1, 222, 223, 224, 225, 226, - 227, -1, -1, 230, -1, 232, -1, -1, 235, 236, - 237, -1, -1, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, -1, 266, - 267, 268, 269, 270, -1, 272, 273, -1, 275, -1, - 277, 278, 279, 280, 281, 282, -1, 284, 285, -1, - -1, 288, 289, 290, -1, -1, 293, 294, -1, 296, - -1, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, -1, 310, 311, 312, 313, 314, 315, 316, - 317, 318, -1, 320, 321, 322, 323, 324, 325, -1, - 327, 328, 329, 330, 331, 332, 333, 334, -1, 336, - 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, - 347, 348, -1, 350, 351, -1, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, - 367, -1, 369, 370, 371, 372, 373, -1, 375, 376, - 377, 378, 379, -1, 381, 382, 383, 384, -1, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 397, 398, 399, 400, 401, -1, 403, 404, -1, 406, - -1, 408, 409, 410, 411, 412, -1, 414, 415, -1, - -1, 418, 419, 420, 421, 422, -1, 424, 425, 426, - 427, 428, 429, 430, 431, -1, -1, 434, 435, 436, - 437, 438, -1, -1, 441, 442, 443, 444, 445, 446, - 447, -1, 449, -1, 451, 452, 453, 454, 455, -1, - -1, 458, -1, -1, 461, 462, 463, 464, 465, 466, - 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, - 477, 478, 479, 480, 481, 3, -1, 5, -1, -1, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, + 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, + 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, + 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, + 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, + 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, + 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, + 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, + 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, + 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, + 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, + 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, + 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, + 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, + 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, + 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, - -1, 29, 30, 31, -1, -1, -1, -1, -1, -1, - -1, 39, 40, -1, 42, 43, 44, -1, 46, 47, - 48, 49, 50, -1, 52, 53, -1, 55, 56, 57, - 58, 59, 60, -1, -1, 63, 64, 65, 66, 67, - -1, 69, 70, 71, 72, 73, -1, -1, -1, 77, - 78, 79, 80, 81, 82, -1, 84, 85, 86, -1, - 88, 89, 90, 91, 92, 93, -1, -1, 96, 97, - 98, -1, -1, -1, -1, -1, -1, -1, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, -1, 117, - -1, 119, 120, 121, 122, 123, 124, -1, 126, 127, - 128, 129, 130, -1, -1, 133, 134, 135, 136, 137, - -1, 139, 140, 141, -1, 143, 144, 145, -1, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - -1, 159, -1, 161, 162, 163, 164, -1, 166, -1, - 168, -1, -1, -1, 172, 173, 174, -1, 176, -1, - 178, -1, 180, 181, 182, -1, 184, 185, 186, 187, - 188, 189, 190, -1, 192, 193, 194, 195, -1, 197, - 198, 199, 200, 201, 202, -1, 204, -1, 206, 207, - 208, 209, 210, 211, 212, 213, -1, 215, -1, 217, - -1, -1, 220, -1, 222, 223, 224, 225, 226, 227, - -1, -1, 230, -1, 232, -1, -1, 235, 236, 237, - -1, -1, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, -1, 266, 267, - 268, 269, 270, -1, 272, 273, -1, 275, -1, 277, - 278, 279, 280, 281, 282, -1, 284, 285, -1, -1, - 288, 289, 290, -1, -1, 293, 294, -1, 296, -1, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, -1, 310, 311, 312, 313, 314, 315, 316, 317, - 318, -1, 320, 321, 322, 323, 324, 325, -1, 327, - 328, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, - 348, -1, 350, 351, -1, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - -1, 369, 370, 371, 372, 373, -1, 375, 376, 377, - 378, 379, -1, 381, 382, 383, 384, -1, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, -1, 403, 404, 405, 406, -1, - 408, 409, 410, 411, 412, -1, 414, 415, -1, -1, - 418, 419, 420, 421, 422, -1, 424, 425, 426, 427, - 428, 429, 430, 431, -1, -1, 434, 435, 436, 437, - 438, -1, -1, 441, 442, 443, 444, 445, 446, 447, - -1, 449, -1, 451, 452, 453, 454, 455, -1, -1, - 458, -1, -1, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 478, 479, 480, 481, 3, 4, -1, -1, -1, -1, - 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 20, 21, 22, 23, 24, 25, 26, 27, -1, - 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, - 39, 40, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, -1, 52, 53, -1, 55, 56, 57, 58, - 59, 60, -1, -1, 63, 64, 65, 66, 67, -1, - 69, 70, 71, 72, 73, -1, -1, -1, 77, 78, - 79, 80, 81, 82, -1, 84, 85, 86, -1, 88, - 89, 90, 91, 92, 93, -1, -1, 96, 97, 98, - -1, -1, -1, -1, -1, -1, -1, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, -1, 117, -1, - 119, 120, 121, 122, 123, 124, -1, 126, 127, 128, - 129, 130, -1, -1, 133, 134, 135, 136, 137, -1, - 139, 140, 141, -1, 143, 144, 145, -1, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, -1, - 159, -1, 161, 162, 163, 164, -1, 166, -1, 168, - -1, -1, -1, 172, 173, 174, -1, 176, -1, 178, - -1, 180, 181, 182, -1, 184, 185, 186, 187, 188, - 189, 190, -1, 192, 193, 194, 195, -1, 197, 198, - 199, 200, 201, 202, -1, 204, -1, 206, 207, 208, - 209, 210, 211, 212, 213, -1, 215, -1, 217, -1, - -1, 220, -1, 222, 223, 224, 225, 226, 227, -1, - -1, 230, -1, 232, -1, -1, 235, 236, 237, -1, - -1, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, -1, 266, 267, 268, - 269, 270, -1, 272, 273, -1, 275, -1, 277, 278, - 279, 280, 281, 282, -1, 284, 285, -1, -1, 288, - 289, 290, -1, -1, 293, 294, -1, 296, -1, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - -1, 310, 311, 312, 313, 314, 315, 316, 317, 318, - -1, 320, 321, 322, 323, 324, 325, -1, 327, 328, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, - -1, 350, 351, -1, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 364, 365, 366, 367, -1, - 369, 370, 371, 372, 373, -1, 375, 376, 377, 378, - 379, -1, 381, 382, 383, 384, -1, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, - 399, 400, 401, -1, 403, 404, -1, 406, -1, 408, - 409, 410, 411, 412, -1, 414, 415, -1, -1, 418, - 419, 420, 421, 422, -1, 424, 425, 426, 427, 428, - 429, 430, 431, -1, -1, 434, 435, 436, 437, 438, - -1, -1, 441, 442, 443, 444, 445, 446, 447, -1, - 449, -1, 451, 452, 453, 454, 455, -1, -1, 458, - -1, -1, 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, - 479, 480, 481, 3, -1, -1, -1, -1, -1, -1, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, -1, -1, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, 63, 64, 65, 66, 67, 68, -1, 70, + 71, 72, 73, 74, -1, 76, -1, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, -1, 96, 97, 98, 99, 100, + 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, -1, 160, + -1, 162, 163, 164, 165, -1, 167, -1, 169, 170, + -1, 172, 173, 174, 175, 176, 177, -1, 179, -1, + 181, 182, 183, -1, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, -1, -1, + 231, 232, 233, 234, -1, 236, 237, 238, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, -1, 273, 274, 275, 276, -1, 278, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, 313, 314, 315, 316, 317, 318, 319, -1, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, -1, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, -1, 404, 405, -1, 407, 408, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + 421, 422, 423, -1, 425, 426, 427, 428, 429, 430, + 431, 432, -1, -1, 435, 436, 437, 438, 439, 440, + -1, 442, 443, 444, 445, 446, 447, 448, -1, 450, + 451, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, -1, -1, -1, -1, -1, -1, -1, 39, - 40, -1, 42, 43, 44, -1, 46, 47, 48, 49, - 50, -1, 52, 53, -1, 55, 56, 57, 58, 59, - 60, -1, -1, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, -1, -1, 77, 78, 79, - 80, 81, 82, -1, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, -1, 96, 97, 98, -1, - -1, -1, -1, -1, -1, -1, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, -1, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, -1, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, -1, - -1, -1, 172, 173, 174, -1, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, -1, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, -1, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, -1, -1, - 220, -1, 222, 223, 224, 225, 226, 227, -1, -1, - 230, -1, 232, -1, -1, 235, 236, 237, -1, -1, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, -1, 266, 267, 268, 269, - 270, -1, 272, 273, -1, 275, -1, 277, 278, 279, - 280, 281, 282, -1, 284, 285, -1, -1, 288, 289, - 290, -1, -1, 293, 294, -1, 296, -1, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, -1, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, -1, 369, - 370, 371, 372, 373, -1, 375, 376, 377, 378, 379, - -1, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, -1, 406, -1, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, -1, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, -1, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - -1, 451, 452, 453, 454, 455, -1, -1, 458, -1, - -1, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, 3, -1, 5, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, - 21, 22, 23, 24, 25, 26, 27, -1, 29, 30, - 31, -1, -1, -1, -1, -1, -1, -1, 39, 40, - -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, - -1, 52, 53, -1, 55, 56, 57, 58, 59, 60, - -1, -1, 63, 64, 65, 66, 67, -1, 69, 70, - 71, 72, 73, -1, -1, -1, 77, 78, 79, 80, - 81, 82, -1, 84, 85, 86, -1, 88, 89, 90, - 91, 92, 93, -1, -1, 96, 97, 98, -1, -1, - -1, -1, -1, -1, -1, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, -1, 117, -1, 119, 120, - 121, 122, 123, 124, -1, 126, 127, 128, 129, 130, - -1, -1, 133, 134, 135, 136, 137, -1, 139, 140, - 141, -1, 143, 144, 145, -1, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, -1, 159, -1, - 161, 162, 163, 164, -1, 166, -1, 168, -1, -1, - -1, 172, 173, 174, -1, 176, -1, 178, -1, 180, - 181, 182, -1, 184, 185, 186, 187, 188, 189, 190, - -1, 192, 193, 194, 195, -1, 197, 198, 199, 200, - 201, 202, -1, 204, -1, 206, 207, 208, 209, 210, - 211, 212, 213, -1, 215, -1, 217, -1, -1, 220, - -1, 222, 223, 224, 225, 226, 227, -1, -1, 230, - -1, 232, -1, -1, 235, 236, 237, -1, -1, 240, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, -1, -1, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, -1, 64, 65, 66, 67, 68, -1, 70, + 71, 72, 73, 74, -1, 76, -1, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, -1, 96, 97, 98, 99, 100, + 101, 102, 103, -1, -1, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, + -1, 162, 163, 164, 165, -1, 167, -1, 169, 170, + -1, 172, 173, 174, 175, 176, 177, -1, 179, -1, + 181, 182, 183, -1, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, -1, -1, + 231, 232, 233, 234, -1, 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, -1, 266, 267, 268, 269, 270, - -1, 272, 273, -1, 275, -1, 277, 278, 279, 280, - 281, 282, -1, 284, 285, -1, -1, 288, 289, 290, - -1, -1, 293, 294, -1, 296, -1, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, -1, 310, - 311, 312, 313, 314, 315, 316, 317, 318, -1, 320, - 321, 322, 323, 324, 325, -1, 327, 328, 329, 330, - 331, 332, 333, 334, -1, 336, 337, 338, 339, 340, - 341, 342, 343, 344, 345, 346, 347, 348, -1, 350, - 351, -1, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 364, 365, 366, 367, -1, 369, 370, - 371, 372, 373, -1, 375, 376, 377, 378, 379, -1, - 381, 382, 383, 384, -1, 386, 387, 388, 389, 390, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, -1, 273, 274, 275, 276, -1, 278, 279, 280, + 281, 282, 283, -1, 285, 286, 287, -1, 289, 290, + 291, -1, -1, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, 313, 314, 315, 316, 317, 318, 319, -1, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, - 401, -1, 403, 404, -1, 406, -1, 408, 409, 410, - 411, 412, -1, 414, 415, -1, -1, 418, 419, 420, - 421, 422, -1, 424, 425, 426, 427, 428, 429, 430, - 431, -1, -1, 434, 435, 436, 437, 438, -1, -1, - 441, 442, 443, 444, 445, 446, 447, -1, 449, -1, - 451, 452, 453, 454, 455, -1, -1, 458, -1, -1, - 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 401, 402, -1, 404, 405, -1, 407, 408, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, + 431, 432, -1, -1, 435, 436, 437, 438, 439, 440, + -1, 442, 443, 444, 445, 446, 447, 448, -1, 450, + 451, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, - 481, 3, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - -1, -1, -1, -1, -1, -1, -1, 39, 40, -1, - 42, 43, 44, -1, 46, 47, 48, 49, 50, -1, - 52, 53, -1, 55, 56, 57, 58, 59, 60, -1, - -1, 63, 64, 65, 66, 67, -1, 69, 70, 71, - 72, 73, -1, -1, -1, 77, 78, 79, 80, 81, - 82, -1, 84, 85, 86, -1, 88, 89, 90, 91, - 92, 93, -1, -1, 96, 97, 98, -1, -1, -1, - -1, -1, -1, -1, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, -1, 117, -1, 119, 120, 121, - 122, 123, 124, -1, 126, 127, 128, 129, 130, -1, - -1, 133, 134, 135, 136, 137, -1, 139, 140, 141, - -1, 143, 144, 145, -1, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, -1, 159, -1, 161, - 162, 163, 164, -1, 166, -1, 168, -1, -1, -1, - 172, 173, 174, -1, 176, -1, 178, -1, 180, 181, - 182, -1, 184, 185, 186, 187, 188, 189, 190, -1, - 192, 193, 194, 195, -1, 197, 198, 199, 200, 201, - 202, -1, 204, -1, 206, 207, 208, 209, 210, 211, - 212, 213, -1, 215, -1, 217, -1, -1, 220, -1, - 222, 223, 224, 225, 226, 227, -1, -1, 230, -1, - 232, -1, -1, 235, 236, 237, -1, -1, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, -1, 266, 267, 268, 269, 270, -1, - 272, 273, -1, 275, -1, 277, 278, 279, 280, 281, - 282, -1, 284, 285, -1, -1, 288, 289, 290, -1, - -1, 293, 294, -1, 296, -1, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, -1, 310, 311, - 312, 313, 314, 315, 316, 317, 318, -1, 320, 321, - 322, 323, 324, 325, -1, 327, 328, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 346, 347, 348, -1, 350, 351, - -1, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, -1, 369, 370, 371, - 372, 373, -1, 375, 376, 377, 378, 379, -1, 381, - 382, 383, 384, -1, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - -1, 403, 404, -1, 406, -1, 408, 409, 410, 411, - 412, -1, 414, 415, -1, -1, 418, 419, 420, 421, - 422, -1, 424, 425, 426, 427, 428, 429, 430, 431, - -1, -1, 434, 435, 436, 437, 438, -1, -1, 441, - 442, 443, 444, 445, 446, 447, -1, 449, -1, 451, - 452, 453, 454, 455, -1, -1, 458, -1, -1, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, - 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 20, 21, 22, - 23, 24, 25, 26, 27, -1, 29, 30, 31, -1, - -1, -1, -1, -1, -1, -1, 39, 40, -1, 42, - 43, 44, -1, 46, 47, 48, 49, 50, -1, 52, - 53, -1, 55, 56, 57, 58, 59, 60, -1, -1, - 63, 64, 65, 66, 67, -1, 69, 70, 71, 72, - 73, -1, -1, -1, 77, 78, 79, 80, 81, 82, - -1, 84, 85, 86, -1, 88, 89, 90, 91, 92, - 93, -1, -1, 96, 97, 98, -1, -1, -1, -1, - -1, -1, -1, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, -1, 117, -1, 119, 120, 121, 122, - 123, 124, -1, 126, 127, 128, 129, 130, -1, -1, - 133, 134, 135, 136, 137, -1, 139, 140, 141, -1, - 143, 144, 145, -1, 147, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, -1, 159, -1, 161, 162, - 163, 164, -1, 166, -1, 168, -1, -1, -1, 172, - 173, 174, -1, 176, -1, 178, -1, 180, 181, 182, - -1, 184, 185, 186, 187, 188, 189, 190, -1, 192, - 193, 194, 195, -1, 197, 198, 199, 200, 201, 202, - -1, 204, -1, 206, 207, 208, 209, 210, 211, 212, - 213, -1, 215, -1, 217, -1, -1, 220, -1, 222, - 223, 224, 225, 226, 227, -1, -1, 230, -1, 232, - -1, -1, 235, 236, 237, -1, -1, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, -1, 266, 267, 268, 269, 270, -1, 272, - 273, -1, 275, -1, 277, 278, 279, 280, 281, 282, - -1, 284, 285, -1, -1, 288, 289, 290, -1, -1, - 293, 294, -1, 296, -1, 298, 299, 300, 301, 302, - 303, 304, 305, 306, 307, 308, -1, 310, 311, 312, - 313, 314, 315, 316, 317, 318, -1, 320, 321, 322, - 323, 324, 325, -1, 327, 328, 329, 330, 331, 332, - 333, 334, -1, 336, 337, 338, 339, 340, 341, 342, - 343, 344, 345, 346, 347, 348, -1, 350, 351, -1, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 364, 365, 366, 367, -1, 369, 370, 371, 372, - 373, -1, 375, 376, 377, 378, 379, -1, 381, 382, - 383, 384, -1, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 397, 398, 399, 400, 401, -1, - 403, 404, -1, 406, -1, 408, 409, 410, 411, 412, - -1, 414, 415, -1, -1, 418, 419, 420, 421, 422, - -1, 424, 425, 426, 427, 428, 429, 430, 431, -1, - -1, 434, 435, 436, 437, 438, -1, -1, 441, 442, - 443, 444, 445, 446, 447, -1, 449, -1, 451, 452, - 453, 454, 455, -1, -1, 458, -1, -1, 461, 462, - 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, - 473, 474, 475, 476, 477, 478, 479, 480, 481, 3, - -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, - 24, 25, 26, 27, -1, 29, 30, 31, -1, -1, - -1, -1, -1, -1, -1, 39, 40, -1, 42, 43, - 44, -1, 46, 47, 48, 49, 50, -1, 52, 53, - -1, 55, 56, 57, 58, 59, 60, -1, -1, 63, - 64, 65, 66, 67, -1, 69, 70, 71, 72, 73, - -1, -1, -1, 77, 78, 79, 80, 81, 82, -1, - 84, 85, 86, -1, 88, 89, 90, 91, 92, 93, - -1, -1, 96, 97, 98, -1, -1, -1, -1, -1, - -1, -1, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, -1, 117, -1, 119, 120, 121, 122, 123, - 124, -1, 126, 127, 128, 129, 130, -1, -1, 133, - 134, 135, 136, 137, -1, 139, 140, 141, -1, 143, - 144, 145, -1, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, -1, 159, -1, 161, 162, 163, - 164, -1, 166, -1, 168, -1, -1, -1, 172, 173, - 174, -1, 176, -1, 178, -1, 180, 181, 182, -1, - 184, 185, 186, 187, 188, 189, 190, -1, 192, 193, - 194, 195, -1, 197, 198, 199, 200, 201, 202, -1, - 204, -1, 206, 207, 208, 209, 210, 211, 212, 213, - -1, 215, -1, 217, -1, -1, 220, -1, 222, 223, - 224, 225, 226, 227, -1, -1, 230, -1, 232, -1, - -1, 235, 236, 237, -1, -1, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, -1, 266, 267, 268, 269, 270, -1, 272, 273, - -1, 275, -1, 277, 278, 279, 280, 281, 282, -1, - 284, 285, -1, -1, 288, 289, 290, -1, -1, 293, - 294, -1, 296, -1, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, -1, 310, 311, 312, 313, - 314, 315, 316, 317, 318, -1, 320, 321, 322, 323, - 324, 325, -1, 327, 328, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, -1, 350, 351, -1, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, -1, 369, 370, 371, 372, 373, - -1, 375, 376, 377, 378, 379, -1, 381, 382, 383, - 384, -1, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, -1, 403, - 404, -1, 406, -1, 408, 409, 410, 411, 412, -1, - 414, 415, -1, -1, 418, 419, 420, 421, 422, -1, - 424, 425, 426, 427, 428, 429, 430, 431, -1, -1, - 434, 435, 436, 437, 438, -1, -1, 441, 442, 443, - 444, 445, 446, 447, -1, 449, -1, 451, 452, 453, - 454, 455, -1, -1, 458, -1, -1, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 3, -1, - 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 20, 21, 22, 23, 24, - 25, 26, 27, -1, 29, 30, 31, -1, -1, -1, - -1, -1, -1, -1, 39, 40, -1, 42, 43, 44, - -1, 46, 47, 48, 49, 50, -1, 52, 53, -1, - 55, 56, 57, 58, 59, 60, -1, -1, 63, 64, - 65, 66, 67, -1, 69, 70, 71, 72, 73, -1, - -1, -1, 77, 78, 79, 80, 81, 82, -1, 84, - 85, 86, -1, 88, 89, 90, 91, 92, 93, -1, - -1, 96, 97, 98, -1, -1, -1, -1, -1, -1, - -1, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, -1, 117, -1, 119, 120, 121, 122, 123, 124, - -1, 126, 127, 128, 129, 130, -1, -1, 133, 134, - 135, 136, 137, -1, 139, 140, 141, -1, 143, 144, - 145, -1, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, -1, 159, -1, 161, 162, 163, 164, - -1, 166, -1, 168, -1, -1, -1, 172, 173, 174, - -1, 176, -1, 178, -1, 180, 181, 182, -1, 184, - 185, 186, 187, 188, 189, 190, -1, 192, 193, 194, - 195, -1, 197, 198, 199, 200, 201, 202, -1, 204, - -1, 206, 207, 208, 209, 210, 211, 212, 213, -1, - 215, -1, 217, -1, -1, 220, -1, 222, 223, 224, - 225, 226, 227, -1, -1, 230, -1, 232, -1, -1, - 235, 236, 237, -1, -1, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - -1, 266, 267, 268, 269, 270, -1, 272, 273, -1, - 275, -1, 277, 278, 279, 280, 281, 282, -1, 284, - 285, -1, -1, 288, 289, 290, -1, -1, 293, 294, - -1, 296, -1, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, -1, 310, 311, 312, 313, 314, - 315, 316, 317, 318, -1, 320, 321, 322, 323, 324, - 325, -1, 327, 328, 329, 330, 331, 332, 333, 334, - -1, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, -1, 350, 351, -1, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, -1, 369, 370, 371, 372, 373, -1, - 375, 376, 377, 378, 379, -1, 381, 382, 383, 384, - -1, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 397, 398, 399, 400, 401, -1, 403, 404, - -1, 406, -1, 408, 409, 410, 411, 412, -1, 414, - 415, -1, -1, 418, 419, 420, 421, 422, -1, 424, - 425, 426, 427, 428, 429, 430, 431, -1, -1, 434, - 435, 436, 437, 438, -1, -1, 441, 442, 443, 444, - 445, 446, 447, -1, 449, -1, 451, 452, 453, 454, - 455, -1, -1, 458, -1, -1, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 478, 479, 480, 481, 3, -1, 5, + 481, 482, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, - 26, 27, -1, 29, 30, 31, -1, -1, -1, -1, - -1, -1, -1, 39, 40, -1, 42, 43, 44, -1, - 46, 47, 48, 49, 50, -1, 52, 53, -1, 55, - 56, 57, 58, 59, 60, -1, -1, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, -1, -1, - -1, 77, 78, 79, 80, 81, 82, -1, 84, 85, - 86, -1, 88, 89, 90, 91, 92, 93, -1, -1, - 96, 97, 98, -1, -1, -1, -1, -1, -1, -1, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - -1, 117, -1, 119, 120, 121, 122, 123, 124, -1, - 126, 127, 128, 129, 130, -1, -1, 133, 134, 135, - 136, 137, -1, 139, 140, 141, -1, 143, 144, 145, - -1, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, -1, 159, -1, 161, 162, 163, 164, -1, - 166, -1, 168, -1, -1, -1, 172, 173, 174, -1, - 176, -1, 178, -1, 180, 181, 182, -1, 184, 185, - 186, 187, 188, 189, 190, -1, 192, 193, 194, 195, - -1, 197, 198, 199, 200, 201, 202, -1, 204, -1, - 206, 207, 208, 209, 210, 211, 212, 213, -1, 215, - -1, 217, -1, -1, 220, -1, 222, 223, 224, 225, - 226, 227, -1, -1, 230, -1, 232, -1, -1, 235, - 236, 237, -1, -1, 240, 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, -1, - 266, 267, 268, 269, 270, -1, 272, 273, -1, 275, - -1, 277, 278, 279, 280, 281, 282, -1, 284, 285, - -1, -1, 288, 289, 290, -1, -1, 293, 294, -1, - 296, -1, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, -1, 310, 311, 312, 313, 314, 315, - 316, 317, 318, -1, 320, 321, 322, 323, 324, 325, - -1, 327, 328, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, 350, 351, -1, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, -1, 369, 370, 371, 372, 373, -1, 375, - 376, 377, 378, 379, -1, 381, 382, 383, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, -1, 403, 404, -1, - 406, -1, 408, 409, 410, 411, 412, -1, 414, 415, - -1, -1, 418, 419, 420, 421, 422, -1, 424, 425, - 426, 427, 428, 429, 430, 431, -1, -1, 434, 435, - 436, 437, 438, -1, -1, 441, 442, 443, 444, 445, - 446, 447, -1, 449, -1, 451, 452, 453, 454, 455, - -1, -1, 458, -1, -1, 461, 462, 463, 464, 465, - 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, 3, -1, -1, -1, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, 33, 34, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, -1, 64, 65, 66, 67, 68, -1, 70, + 71, 72, 73, 74, -1, 76, -1, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, -1, 96, 97, 98, 99, 100, + 101, 102, 103, -1, -1, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, -1, 160, + -1, 162, 163, 164, 165, -1, 167, -1, 169, 170, + -1, 172, 173, 174, 175, 176, 177, -1, 179, -1, + 181, 182, 183, -1, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, -1, -1, + 231, 232, 233, 234, -1, 236, 237, 238, -1, -1, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, -1, 273, 274, 275, 276, -1, 278, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, 313, 314, 315, 316, 317, 318, 319, -1, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, -1, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, -1, 404, 405, -1, 407, 408, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + 421, 422, 423, -1, 425, 426, 427, 428, 429, 430, + 431, 432, -1, -1, 435, 436, 437, 438, 439, 440, + -1, 442, 443, 444, 445, 446, 447, 448, -1, 450, + 451, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 20, 21, 22, 23, 24, 25, 26, - 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, - -1, -1, 39, 40, -1, 42, 43, 44, -1, 46, - 47, 48, 49, 50, -1, 52, 53, -1, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, -1, 69, 70, 71, 72, 73, -1, -1, -1, - 77, 78, 79, 80, 81, 82, -1, 84, 85, 86, - -1, 88, 89, 90, 91, 92, 93, -1, -1, 96, - 97, 98, -1, -1, -1, -1, -1, -1, -1, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, -1, - 117, -1, 119, 120, 121, 122, 123, 124, -1, 126, - 127, 128, 129, 130, -1, -1, 133, 134, 135, 136, - 137, -1, 139, 140, 141, -1, 143, 144, 145, -1, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, -1, 159, -1, 161, 162, 163, 164, -1, 166, - -1, 168, -1, -1, -1, 172, 173, 174, -1, 176, - -1, 178, -1, 180, 181, 182, -1, 184, 185, 186, - 187, 188, 189, 190, -1, 192, 193, 194, 195, -1, - 197, 198, 199, 200, 201, 202, -1, 204, -1, 206, - 207, 208, 209, 210, 211, 212, 213, -1, 215, -1, - 217, -1, -1, 220, -1, 222, 223, 224, 225, 226, - 227, -1, -1, 230, -1, 232, -1, -1, 235, 236, - 237, -1, -1, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, -1, 266, - 267, 268, 269, 270, -1, 272, 273, -1, 275, -1, - 277, 278, 279, 280, 281, 282, -1, 284, 285, -1, - -1, 288, 289, 290, -1, -1, 293, 294, -1, 296, - -1, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, -1, 310, 311, 312, 313, 314, 315, 316, - 317, 318, -1, 320, 321, 322, 323, 324, 325, -1, - 327, 328, 329, 330, 331, 332, 333, 334, -1, 336, - 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, - 347, 348, -1, 350, 351, -1, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, - 367, -1, 369, 370, 371, 372, 373, -1, 375, 376, - 377, 378, 379, -1, 381, 382, 383, 384, -1, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 397, 398, 399, 400, 401, -1, 403, 404, -1, 406, - -1, 408, 409, 410, 411, 412, -1, 414, 415, -1, - -1, 418, 419, 420, 421, 422, -1, 424, 425, 426, - 427, 428, 429, 430, 431, -1, -1, 434, 435, 436, - 437, 438, -1, -1, 441, 442, 443, 444, 445, 446, - 447, -1, 449, -1, 451, 452, 453, 454, 455, -1, - -1, 458, -1, -1, 461, 462, 463, 464, 465, 466, - 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, - 477, 478, 479, 480, 481, 3, -1, 5, -1, -1, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, -1, -1, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, -1, 64, 65, 66, 67, 68, -1, 70, + 71, 72, 73, 74, -1, 76, -1, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, -1, 96, 97, 98, 99, 100, + 101, 102, 103, -1, -1, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, -1, 160, + -1, 162, 163, 164, 165, -1, 167, -1, 169, 170, + -1, 172, 173, 174, 175, 176, 177, -1, 179, -1, + 181, 182, 183, -1, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, 206, 207, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, -1, -1, + 231, 232, 233, 234, -1, 236, 237, 238, -1, -1, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, -1, 273, 274, 275, 276, -1, 278, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, 295, 296, 297, 298, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, 313, 314, 315, 316, 317, 318, 319, -1, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, -1, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, -1, 404, 405, -1, 407, 408, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + 421, 422, 423, -1, 425, 426, 427, 428, 429, 430, + 431, 432, -1, -1, 435, 436, 437, 438, 439, 440, + -1, 442, 443, 444, 445, 446, 447, 448, -1, 450, + 451, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, - -1, 29, 30, 31, -1, -1, -1, -1, -1, -1, - -1, 39, 40, -1, 42, 43, 44, -1, 46, 47, - 48, 49, 50, -1, 52, 53, -1, 55, 56, 57, - 58, 59, 60, -1, -1, 63, 64, 65, 66, 67, - -1, 69, 70, 71, 72, 73, -1, -1, -1, 77, - 78, 79, 80, 81, 82, -1, 84, 85, 86, -1, - 88, 89, 90, 91, 92, 93, -1, -1, 96, 97, - 98, -1, -1, -1, -1, -1, -1, -1, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, -1, 117, - -1, 119, 120, 121, 122, 123, 124, -1, 126, 127, - 128, 129, 130, -1, -1, 133, 134, 135, 136, 137, - -1, 139, 140, 141, -1, 143, 144, 145, -1, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - -1, 159, -1, 161, 162, 163, 164, -1, 166, -1, - 168, -1, -1, -1, 172, 173, 174, -1, 176, -1, - 178, -1, 180, 181, 182, -1, 184, 185, 186, 187, - 188, 189, 190, -1, 192, 193, 194, 195, -1, 197, - 198, 199, 200, 201, 202, -1, 204, -1, 206, 207, - 208, 209, 210, 211, 212, 213, -1, 215, -1, 217, - -1, -1, 220, -1, 222, 223, 224, 225, 226, 227, - -1, -1, 230, -1, 232, -1, -1, 235, 236, 237, - -1, -1, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, -1, 266, 267, - 268, 269, 270, -1, 272, 273, -1, 275, -1, 277, - 278, 279, 280, 281, 282, -1, 284, 285, -1, -1, - 288, 289, 290, -1, -1, 293, 294, -1, 296, -1, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, -1, 310, 311, 312, 313, 314, 315, 316, 317, - 318, -1, 320, 321, 322, 323, 324, 325, -1, 327, - 328, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, - 348, -1, 350, 351, -1, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - -1, 369, 370, 371, 372, 373, -1, 375, 376, 377, - 378, 379, -1, 381, 382, 383, 384, -1, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, -1, 403, 404, -1, 406, -1, - 408, 409, 410, 411, 412, -1, 414, 415, -1, -1, - 418, 419, 420, 421, 422, -1, 424, 425, 426, 427, - 428, 429, 430, 431, -1, -1, 434, 435, 436, 437, - 438, -1, -1, 441, 442, 443, 444, 445, 446, 447, - -1, 449, -1, 451, 452, 453, 454, 455, -1, -1, - 458, -1, -1, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 478, 479, 480, 481, 3, -1, 5, -1, -1, -1, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, -1, -1, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, -1, 47, 48, 49, 50, + 51, -1, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, -1, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, -1, -1, 77, 78, 79, 80, + 81, 82, 83, -1, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, -1, -1, 97, 98, 99, -1, + -1, -1, -1, -1, -1, -1, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, -1, 160, + -1, 162, 163, 164, 165, -1, 167, 168, 169, -1, + -1, -1, 173, 174, 175, -1, 177, -1, 179, -1, + 181, 182, 183, -1, 185, 186, 187, 188, 189, 190, + 191, -1, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, -1, 207, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, -1, -1, + 221, -1, 223, 224, 225, 226, 227, 228, -1, -1, + 231, -1, 233, -1, -1, 236, 237, 238, -1, -1, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, -1, 267, 268, 269, 270, + 271, -1, 273, 274, -1, 276, -1, 278, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, 295, -1, 297, -1, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, -1, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, -1, 376, 377, 378, 379, 380, + -1, 382, 383, 384, 385, -1, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, -1, 404, 405, -1, 407, -1, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + 421, 422, 423, -1, 425, 426, 427, 428, 429, 430, + 431, 432, -1, 434, 435, 436, 437, 438, 439, -1, + -1, 442, 443, 444, 445, 446, 447, 448, -1, 450, + -1, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 20, 21, 22, 23, 24, 25, 26, 27, -1, - 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, - 39, 40, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, -1, 52, 53, -1, 55, 56, 57, 58, - 59, 60, -1, -1, 63, 64, 65, 66, 67, -1, - 69, 70, 71, 72, 73, -1, -1, -1, 77, 78, - 79, 80, 81, 82, -1, 84, 85, 86, -1, 88, - 89, 90, 91, 92, 93, -1, -1, 96, 97, 98, - -1, -1, -1, -1, -1, -1, -1, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, -1, 117, -1, - 119, 120, 121, 122, 123, 124, -1, 126, 127, 128, - 129, 130, -1, -1, 133, 134, 135, 136, 137, -1, - 139, 140, 141, -1, 143, 144, 145, -1, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, -1, - 159, -1, 161, 162, 163, 164, -1, 166, -1, 168, - -1, -1, -1, 172, 173, 174, -1, 176, -1, 178, - -1, 180, 181, 182, -1, 184, 185, 186, 187, 188, - 189, 190, -1, 192, 193, 194, 195, -1, 197, 198, - 199, 200, 201, 202, -1, 204, -1, 206, 207, 208, - 209, 210, 211, 212, 213, -1, 215, -1, 217, -1, - -1, 220, -1, 222, 223, 224, 225, 226, 227, -1, - -1, 230, -1, 232, -1, -1, 235, 236, 237, -1, - -1, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, -1, 266, 267, 268, - 269, 270, -1, 272, 273, -1, 275, -1, 277, 278, - 279, 280, 281, 282, -1, 284, 285, -1, -1, 288, - 289, 290, -1, -1, 293, 294, -1, 296, -1, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - -1, 310, 311, 312, 313, 314, 315, 316, 317, 318, - -1, 320, 321, 322, 323, 324, 325, -1, 327, 328, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, - -1, 350, 351, -1, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 364, 365, 366, 367, -1, - 369, 370, 371, 372, 373, -1, 375, 376, 377, 378, - 379, -1, 381, 382, 383, 384, -1, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, - 399, 400, 401, -1, 403, 404, -1, 406, -1, 408, - 409, 410, 411, 412, -1, 414, 415, -1, -1, 418, - 419, 420, 421, 422, -1, 424, 425, 426, 427, 428, - 429, 430, 431, -1, -1, 434, 435, 436, 437, 438, - -1, -1, 441, 442, 443, 444, 445, 446, 447, -1, - 449, -1, 451, 452, 453, 454, 455, -1, -1, 458, - -1, -1, 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, - 479, 480, 481, 3, -1, 5, -1, -1, -1, -1, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, -1, -1, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, -1, 47, 48, 49, 50, + 51, -1, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, -1, 64, 65, 66, 67, 68, 69, 70, + 71, 72, 73, 74, -1, -1, -1, 78, 79, 80, + 81, 82, 83, -1, 85, 86, 87, 88, 89, 90, + 91, 92, 93, 94, -1, -1, 97, 98, 99, -1, + -1, -1, -1, -1, -1, -1, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, -1, 160, + -1, 162, 163, 164, 165, -1, 167, 168, 169, -1, + -1, -1, 173, 174, 175, -1, 177, -1, 179, -1, + 181, 182, 183, -1, 185, 186, 187, 188, 189, 190, + 191, -1, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, -1, 207, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, -1, -1, + 221, -1, 223, 224, 225, 226, 227, 228, -1, -1, + 231, -1, 233, 234, -1, 236, 237, 238, -1, -1, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, -1, 267, 268, 269, 270, + 271, -1, 273, 274, -1, 276, -1, 278, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, 295, -1, 297, -1, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, -1, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, -1, 376, 377, 378, 379, 380, + -1, 382, 383, 384, 385, -1, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, -1, 404, 405, -1, 407, -1, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + 421, 422, 423, -1, 425, 426, 427, 428, 429, 430, + 431, 432, -1, 434, 435, 436, 437, 438, 439, -1, + -1, 442, 443, 444, 445, 446, 447, 448, -1, 450, + -1, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, -1, -1, -1, 39, - 40, -1, 42, 43, 44, -1, 46, 47, 48, 49, - 50, -1, 52, 53, -1, 55, 56, 57, 58, 59, - 60, -1, -1, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, -1, -1, 77, 78, 79, - 80, 81, 82, -1, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, -1, 96, 97, 98, -1, - -1, -1, -1, -1, -1, -1, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, -1, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, -1, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, -1, - -1, -1, 172, 173, 174, -1, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, -1, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, -1, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, -1, -1, - 220, -1, 222, 223, 224, 225, 226, 227, -1, -1, - 230, -1, 232, -1, -1, 235, 236, 237, -1, -1, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, -1, 266, 267, 268, 269, - 270, -1, 272, 273, -1, 275, -1, 277, 278, 279, - 280, 281, 282, -1, 284, 285, -1, -1, 288, 289, - 290, -1, -1, 293, 294, -1, 296, -1, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, -1, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, -1, 369, - 370, 371, 372, 373, -1, 375, 376, 377, 378, 379, - -1, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, -1, 406, -1, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, -1, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, -1, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - -1, 451, 452, 453, 454, 455, -1, -1, 458, -1, - -1, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, 3, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, - 21, 22, 23, 24, 25, 26, 27, -1, 29, 30, - 31, -1, -1, -1, -1, -1, 37, -1, 39, 40, - -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, - -1, 52, 53, -1, 55, 56, 57, 58, 59, 60, - -1, -1, 63, 64, 65, 66, 67, -1, 69, 70, - 71, 72, 73, -1, -1, -1, 77, 78, 79, 80, - 81, 82, -1, 84, 85, 86, -1, 88, 89, 90, - 91, 92, 93, -1, -1, 96, 97, 98, -1, -1, - -1, -1, -1, -1, -1, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, -1, 117, -1, 119, 120, - 121, 122, 123, 124, -1, 126, 127, 128, 129, 130, - -1, -1, 133, 134, 135, 136, 137, -1, 139, 140, - 141, -1, 143, 144, 145, -1, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, -1, 159, -1, - 161, 162, 163, 164, -1, 166, -1, 168, -1, -1, - -1, 172, 173, 174, -1, 176, -1, 178, -1, 180, - 181, 182, -1, 184, 185, 186, 187, 188, 189, 190, - -1, 192, 193, 194, 195, -1, 197, 198, 199, 200, - 201, 202, -1, 204, -1, 206, 207, 208, 209, 210, - 211, 212, 213, -1, 215, -1, 217, -1, -1, 220, - -1, 222, 223, 224, 225, 226, 227, -1, -1, 230, - -1, 232, -1, -1, 235, 236, 237, -1, -1, 240, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, 33, 34, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, -1, 47, 48, 49, 50, + 51, -1, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, -1, 64, 65, 66, 67, 68, -1, 70, + 71, 72, 73, 74, -1, -1, -1, 78, 79, 80, + 81, 82, 83, -1, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, -1, -1, 97, 98, 99, -1, + -1, -1, -1, -1, -1, -1, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, -1, 160, + -1, 162, 163, 164, 165, -1, 167, -1, 169, -1, + -1, -1, 173, 174, 175, -1, 177, -1, 179, -1, + 181, 182, 183, -1, 185, 186, 187, 188, 189, 190, + 191, -1, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, -1, 207, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, -1, -1, + 221, -1, 223, 224, 225, 226, 227, 228, -1, -1, + 231, -1, 233, -1, -1, 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, -1, 266, 267, 268, 269, 270, - -1, 272, 273, -1, 275, -1, 277, 278, 279, 280, - 281, 282, -1, 284, 285, -1, -1, 288, 289, 290, - -1, -1, 293, 294, -1, 296, -1, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, -1, 310, - 311, 312, 313, 314, 315, 316, 317, 318, -1, 320, - 321, 322, 323, 324, 325, -1, 327, 328, 329, 330, - 331, 332, 333, 334, -1, 336, 337, 338, 339, 340, - 341, 342, 343, 344, 345, 346, 347, 348, -1, 350, - 351, -1, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 364, 365, 366, 367, -1, 369, 370, - 371, 372, 373, -1, 375, 376, 377, 378, 379, -1, - 381, 382, 383, 384, -1, 386, 387, 388, 389, 390, + 261, 262, 263, 264, 265, -1, 267, 268, 269, 270, + 271, -1, 273, 274, -1, 276, -1, 278, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, 295, -1, 297, -1, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, 313, 314, 315, 316, 317, 318, 319, -1, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, -1, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, -1, 376, 377, 378, 379, 380, + -1, 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, - 401, -1, 403, 404, -1, 406, -1, 408, 409, 410, - 411, 412, -1, 414, 415, -1, -1, 418, 419, 420, - 421, 422, -1, 424, 425, 426, 427, 428, 429, 430, - 431, -1, -1, 434, 435, 436, 437, 438, -1, -1, - 441, 442, 443, 444, 445, 446, 447, -1, 449, -1, - 451, 452, 453, 454, 455, -1, -1, 458, -1, -1, - 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 401, 402, -1, 404, 405, -1, 407, -1, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + 421, 422, 423, -1, 425, 426, 427, 428, 429, 430, + 431, 432, -1, -1, 435, 436, 437, 438, 439, -1, + -1, 442, 443, 444, 445, 446, 447, 448, -1, 450, + -1, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, - 481, 3, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, - 22, 23, 24, 25, 26, 27, -1, 29, 30, 31, - -1, -1, -1, -1, -1, 37, -1, 39, 40, -1, - 42, 43, 44, -1, 46, 47, 48, 49, 50, -1, - 52, 53, -1, 55, 56, 57, 58, 59, 60, -1, - -1, 63, 64, 65, 66, 67, -1, 69, 70, 71, - 72, 73, -1, -1, -1, 77, 78, 79, 80, 81, - 82, -1, 84, 85, 86, -1, 88, 89, 90, 91, - 92, 93, -1, -1, 96, 97, 98, -1, -1, -1, - -1, -1, -1, -1, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, -1, 117, -1, 119, 120, 121, - 122, 123, 124, -1, 126, 127, 128, 129, 130, -1, - -1, 133, 134, 135, 136, 137, -1, 139, 140, 141, - -1, 143, 144, 145, -1, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, -1, 159, -1, 161, - 162, 163, 164, -1, 166, -1, 168, -1, -1, -1, - 172, 173, 174, -1, 176, -1, 178, -1, 180, 181, - 182, -1, 184, 185, 186, 187, 188, 189, 190, -1, - 192, 193, 194, 195, -1, 197, 198, 199, 200, 201, - 202, -1, 204, -1, 206, 207, 208, 209, 210, 211, - 212, 213, -1, 215, -1, 217, -1, -1, 220, -1, - 222, 223, 224, 225, 226, 227, -1, -1, 230, -1, - 232, -1, -1, 235, 236, 237, -1, -1, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, -1, 266, 267, 268, 269, 270, -1, - 272, 273, -1, 275, -1, 277, 278, 279, 280, 281, - 282, -1, 284, 285, -1, -1, 288, 289, 290, -1, - -1, 293, 294, -1, 296, -1, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, -1, 310, 311, - 312, 313, 314, 315, 316, 317, 318, -1, 320, 321, - 322, 323, 324, 325, -1, 327, 328, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 346, 347, 348, -1, 350, 351, - -1, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, -1, 369, 370, 371, - 372, 373, -1, 375, 376, 377, 378, 379, -1, 381, - 382, 383, 384, -1, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - -1, 403, 404, -1, 406, -1, 408, 409, 410, 411, - 412, -1, 414, 415, -1, -1, 418, 419, 420, 421, - 422, -1, 424, 425, 426, 427, 428, 429, 430, 431, - -1, -1, 434, 435, 436, 437, 438, -1, -1, 441, - 442, 443, 444, 445, 446, 447, -1, 449, -1, 451, - 452, 453, 454, 455, -1, -1, 458, -1, -1, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, - 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 20, 21, 22, - 23, 24, 25, 26, 27, -1, 29, 30, 31, -1, - -1, -1, -1, -1, -1, -1, 39, 40, -1, 42, - 43, 44, -1, 46, 47, 48, 49, 50, -1, 52, - 53, -1, 55, 56, 57, 58, 59, 60, -1, -1, - 63, 64, 65, 66, 67, -1, 69, 70, 71, 72, - 73, -1, -1, -1, 77, 78, 79, 80, 81, 82, - -1, 84, 85, 86, -1, 88, 89, 90, 91, 92, - 93, -1, -1, 96, 97, 98, -1, -1, -1, -1, - -1, -1, -1, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, -1, 117, -1, 119, 120, 121, 122, - 123, 124, -1, 126, 127, 128, 129, 130, -1, -1, - 133, 134, 135, 136, 137, -1, 139, 140, 141, -1, - 143, 144, 145, -1, 147, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, -1, 159, -1, 161, 162, - 163, 164, -1, 166, -1, 168, -1, -1, -1, 172, - 173, 174, -1, 176, -1, 178, -1, 180, 181, 182, - -1, 184, 185, 186, 187, 188, 189, 190, -1, 192, - 193, 194, 195, -1, 197, 198, 199, 200, 201, 202, - -1, 204, -1, 206, 207, 208, 209, 210, 211, 212, - 213, -1, 215, -1, 217, -1, -1, 220, -1, 222, - 223, 224, 225, 226, 227, -1, -1, 230, -1, 232, - -1, -1, 235, 236, 237, -1, -1, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, -1, 266, 267, 268, 269, 270, -1, 272, - 273, -1, 275, -1, 277, 278, 279, 280, 281, 282, - -1, 284, 285, -1, -1, 288, 289, 290, -1, -1, - 293, 294, -1, 296, -1, 298, 299, 300, 301, 302, - 303, 304, 305, 306, 307, 308, -1, 310, 311, 312, - 313, 314, 315, 316, 317, 318, -1, 320, 321, 322, - 323, 324, 325, -1, 327, 328, 329, 330, 331, 332, - 333, 334, -1, 336, 337, 338, 339, 340, 341, 342, - 343, 344, 345, 346, 347, 348, -1, 350, 351, -1, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 364, 365, 366, 367, -1, 369, 370, 371, 372, - 373, -1, 375, 376, 377, 378, 379, -1, 381, 382, - 383, 384, -1, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 397, 398, 399, 400, 401, -1, - 403, 404, -1, 406, -1, 408, 409, 410, 411, 412, - -1, 414, 415, -1, -1, 418, 419, 420, 421, 422, - -1, 424, 425, 426, 427, 428, 429, 430, 431, -1, - -1, 434, 435, 436, 437, 438, -1, -1, 441, 442, - 443, 444, 445, 446, 447, -1, 449, -1, 451, 452, - 453, 454, 455, -1, -1, 458, -1, -1, 461, 462, - 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, - 473, 474, 475, 476, 477, 478, 479, 480, 481, 3, + 481, 482, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, - 24, 25, 26, 27, -1, 29, 30, 31, -1, -1, - -1, -1, -1, -1, -1, 39, 40, -1, 42, 43, - 44, -1, 46, 47, 48, 49, 50, -1, 52, 53, - -1, 55, 56, 57, 58, 59, 60, -1, -1, 63, - 64, 65, 66, 67, -1, 69, 70, 71, 72, 73, - -1, -1, -1, 77, 78, 79, 80, 81, 82, -1, - 84, 85, 86, -1, 88, 89, 90, 91, 92, 93, - -1, -1, 96, 97, 98, -1, -1, -1, -1, -1, - -1, -1, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, -1, 117, -1, 119, 120, 121, 122, 123, - 124, -1, 126, 127, 128, 129, 130, -1, -1, 133, - 134, 135, 136, 137, -1, 139, 140, 141, -1, 143, - 144, 145, -1, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, -1, 159, -1, 161, 162, 163, - 164, -1, 166, -1, 168, -1, -1, -1, 172, 173, - 174, -1, 176, -1, 178, -1, 180, 181, 182, -1, - 184, 185, 186, 187, 188, 189, 190, -1, 192, 193, - 194, 195, -1, 197, 198, 199, 200, 201, 202, -1, - 204, -1, 206, 207, 208, 209, 210, 211, 212, 213, - -1, 215, -1, 217, -1, -1, 220, -1, 222, 223, - 224, 225, 226, 227, -1, -1, 230, -1, 232, -1, - -1, 235, 236, 237, -1, -1, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, -1, 266, 267, 268, 269, 270, -1, 272, 273, - -1, 275, -1, 277, 278, 279, 280, 281, 282, -1, - 284, 285, -1, -1, 288, 289, 290, -1, -1, 293, - 294, -1, 296, -1, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, -1, 310, 311, 312, 313, - 314, 315, 316, 317, 318, -1, 320, 321, 322, 323, - 324, 325, -1, 327, 328, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, -1, 350, 351, -1, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, -1, 369, 370, 371, 372, 373, - -1, 375, 376, 377, 378, 379, -1, 381, 382, 383, - 384, -1, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, -1, 403, - 404, -1, 406, -1, 408, 409, 410, 411, 412, -1, - 414, 415, -1, -1, 418, 419, 420, 421, 422, -1, - 424, 425, 426, 427, 428, 429, 430, 431, -1, -1, - 434, 435, 436, 437, 438, -1, -1, 441, 442, 443, - 444, 445, 446, 447, -1, 449, -1, 451, 452, 453, - 454, 455, -1, -1, 458, -1, -1, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 3, -1, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, -1, -1, -1, -1, -1, 38, -1, 40, + 41, -1, 43, 44, 45, 46, 47, 48, 49, -1, + 51, 52, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, -1, 64, 65, 66, 67, 68, -1, 70, + 71, 72, 73, -1, -1, 76, -1, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, -1, 96, 97, 98, 99, 100, + 101, 102, 103, -1, -1, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, -1, 153, 154, 155, 156, 157, -1, -1, 160, + -1, 162, 163, 164, 165, -1, 167, -1, 169, 170, + -1, 172, 173, 174, 175, 176, 177, -1, 179, -1, + -1, -1, 183, -1, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, 206, -1, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, -1, -1, + 231, 232, 233, 234, -1, 236, 237, 238, -1, -1, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + -1, -1, 273, 274, 275, 276, -1, -1, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, -1, 296, 297, 298, -1, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, -1, 314, 315, -1, 317, 318, 319, -1, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, -1, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + -1, 402, -1, 404, 405, -1, 407, 408, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + -1, 422, -1, -1, 425, 426, 427, 428, 429, 430, + 431, 432, -1, -1, 435, 436, 437, 438, 439, 440, + -1, 442, 443, 444, 445, 446, -1, 448, -1, 450, + 451, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 3, -1, 5, + -1, -1, -1, -1, -1, -1, -1, -1, 479, 480, + 481, 482, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 20, 21, 22, 23, 24, - 25, 26, 27, -1, 29, 30, 31, -1, -1, -1, - -1, -1, -1, -1, 39, 40, -1, 42, 43, 44, - -1, 46, 47, 48, 49, 50, -1, 52, 53, -1, - 55, 56, 57, 58, 59, 60, -1, -1, 63, 64, - 65, 66, 67, -1, 69, 70, 71, 72, 73, -1, - -1, -1, 77, 78, 79, 80, 81, 82, -1, 84, - 85, 86, -1, 88, 89, 90, 91, 92, 93, -1, - -1, 96, 97, 98, -1, -1, -1, -1, -1, -1, - -1, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, -1, 117, -1, 119, 120, 121, 122, 123, 124, - -1, 126, 127, 128, 129, 130, -1, -1, 133, 134, - 135, 136, 137, -1, 139, 140, 141, -1, 143, 144, - 145, -1, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, -1, 159, -1, 161, 162, 163, 164, - -1, 166, -1, 168, -1, -1, -1, 172, 173, 174, - -1, 176, -1, 178, -1, 180, 181, 182, -1, 184, - 185, 186, 187, 188, 189, 190, -1, 192, 193, 194, - 195, -1, 197, 198, 199, 200, 201, 202, -1, 204, - -1, 206, 207, 208, 209, 210, 211, 212, 213, -1, - 215, -1, 217, -1, -1, 220, -1, 222, 223, 224, - 225, 226, 227, -1, -1, 230, -1, 232, -1, -1, - 235, 236, 237, -1, -1, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - -1, 266, 267, 268, 269, 270, -1, 272, 273, -1, - 275, -1, 277, 278, 279, 280, 281, 282, -1, 284, - 285, -1, -1, 288, 289, 290, -1, -1, 293, 294, - -1, 296, -1, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, -1, 310, 311, 312, 313, 314, - 315, 316, 317, 318, -1, 320, 321, 322, 323, 324, - 325, -1, 327, 328, 329, 330, 331, 332, 333, 334, - -1, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, -1, 350, 351, -1, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, -1, 369, 370, 371, 372, 373, -1, - 375, 376, 377, 378, 379, -1, 381, 382, 383, 384, - -1, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 397, 398, 399, 400, 401, -1, 403, 404, - -1, 406, -1, 408, 409, 410, 411, 412, -1, 414, - 415, -1, -1, 418, 419, 420, 421, 422, -1, 424, - 425, 426, 427, 428, 429, 430, 431, -1, -1, 434, - 435, 436, 437, 438, -1, -1, 441, 442, 443, 444, - 445, 446, 447, -1, 449, -1, 451, 452, 453, 454, - 455, -1, -1, 458, -1, -1, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 478, 479, 480, 481, 3, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, 288, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, - 26, 27, -1, 29, 30, 31, -1, -1, -1, -1, - -1, -1, -1, 39, 40, -1, 42, 43, 44, -1, - 46, 47, 48, 49, 50, -1, 52, 53, -1, 55, - 56, 57, 58, 59, 60, -1, -1, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, -1, -1, - -1, 77, 78, 79, 80, 81, 82, -1, 84, 85, - 86, -1, 88, 89, 90, 91, 92, 93, -1, -1, - 96, 97, 98, -1, -1, -1, -1, -1, -1, -1, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - -1, 117, -1, 119, 120, 121, 122, 123, 124, -1, - 126, 127, 128, 129, 130, -1, -1, 133, 134, 135, - 136, 137, -1, 139, 140, 141, -1, 143, 144, 145, - -1, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, -1, 159, -1, 161, 162, 163, 164, -1, - 166, -1, 168, -1, -1, -1, 172, 173, 174, -1, - 176, -1, 178, -1, 180, 181, 182, -1, 184, 185, - 186, 187, 188, 189, 190, -1, 192, 193, 194, 195, - -1, 197, 198, 199, 200, 201, 202, -1, 204, -1, - 206, 207, 208, 209, 210, 211, 212, 213, -1, 215, - -1, 217, -1, -1, 220, -1, 222, 223, 224, 225, - 226, 227, -1, -1, 230, -1, 232, -1, -1, 235, - 236, 237, -1, -1, 240, 241, 242, 243, 244, 245, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, -1, - 266, 267, 268, 269, 270, -1, 272, 273, -1, 275, - -1, 277, 278, 279, 280, 281, 282, -1, 284, 285, - -1, -1, 288, 289, 290, -1, -1, 293, 294, -1, - 296, -1, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, -1, 310, 311, 312, 313, 314, 315, - 316, 317, 318, -1, 320, 321, 322, 323, 324, 325, - -1, 327, 328, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, 350, 351, -1, 353, 354, 355, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, 288, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, -1, 369, 370, 371, 372, 373, -1, 375, - 376, 377, 378, 379, -1, 381, 382, 383, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, -1, 403, 404, -1, - 406, -1, 408, 409, 410, 411, 412, -1, 414, 415, - -1, -1, 418, 419, 420, 421, 422, -1, 424, 425, - 426, 427, 428, 429, 430, 431, -1, -1, 434, 435, - 436, 437, 438, -1, -1, 441, 442, 443, 444, 445, - 446, 447, -1, 449, -1, 451, 452, 453, 454, 455, - -1, -1, 458, -1, -1, 461, 462, 463, 464, 465, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, 3, -1, -1, -1, + 476, 477, 478, 479, 480, 481, 482, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 20, 21, 22, 23, 24, 25, 26, - 27, -1, 29, 30, 31, -1, -1, -1, -1, -1, - -1, -1, 39, 40, -1, 42, 43, 44, -1, 46, - 47, 48, 49, 50, -1, 52, 53, -1, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, -1, 69, 70, 71, 72, 73, -1, -1, -1, - 77, 78, 79, 80, 81, 82, -1, 84, 85, 86, - -1, 88, 89, 90, 91, 92, 93, -1, -1, 96, - 97, 98, -1, -1, -1, -1, -1, -1, -1, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, -1, - 117, -1, 119, 120, 121, 122, 123, 124, -1, 126, - 127, 128, 129, 130, -1, -1, 133, 134, 135, 136, - 137, -1, 139, 140, 141, -1, 143, 144, 145, -1, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, -1, 159, -1, 161, 162, 163, 164, -1, 166, - -1, 168, -1, -1, -1, 172, 173, 174, -1, 176, - -1, 178, -1, 180, 181, 182, -1, 184, 185, 186, - 187, 188, 189, 190, -1, 192, 193, 194, 195, -1, - 197, 198, 199, 200, 201, 202, -1, 204, -1, 206, - 207, 208, 209, 210, 211, 212, 213, -1, 215, -1, - 217, -1, -1, 220, -1, 222, 223, 224, 225, 226, - 227, -1, -1, 230, -1, 232, -1, -1, 235, 236, - 237, -1, -1, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, -1, 266, - 267, 268, 269, 270, -1, 272, 273, -1, 275, -1, - 277, 278, 279, 280, 281, 282, -1, 284, 285, -1, - -1, 288, 289, 290, -1, -1, 293, 294, -1, 296, - -1, 298, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, -1, 310, 311, 312, 313, 314, 315, 316, - 317, 318, -1, 320, 321, 322, 323, 324, 325, -1, - 327, 328, 329, 330, 331, 332, 333, 334, -1, 336, - 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, - 347, 348, -1, 350, 351, -1, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, - 367, -1, 369, 370, 371, 372, 373, -1, 375, 376, - 377, 378, 379, -1, 381, 382, 383, 384, -1, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 397, 398, 399, 400, 401, -1, 403, 404, -1, 406, - -1, 408, 409, 410, 411, 412, -1, 414, 415, -1, - -1, 418, 419, 420, 421, 422, -1, 424, 425, 426, - 427, 428, 429, 430, 431, -1, -1, 434, 435, 436, - 437, 438, -1, -1, 441, 442, 443, 444, 445, 446, - 447, -1, 449, -1, 451, 452, 453, 454, 455, -1, - -1, 458, -1, -1, 461, 462, 463, 464, 465, 466, - 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, - 477, 478, 479, 480, 481, 3, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 20, 21, 22, 23, 24, 25, 26, 27, - -1, 29, 30, 31, -1, -1, -1, -1, -1, -1, - -1, 39, 40, -1, 42, 43, 44, -1, 46, 47, - 48, 49, 50, -1, 52, 53, -1, 55, 56, 57, - 58, 59, 60, -1, -1, 63, 64, 65, 66, 67, - -1, 69, 70, 71, 72, 73, -1, -1, -1, 77, - 78, 79, 80, 81, 82, -1, 84, 85, 86, -1, - 88, 89, 90, 91, 92, 93, -1, -1, 96, 97, - 98, -1, -1, -1, -1, -1, -1, -1, 106, 107, - 108, 109, 110, 111, 112, 113, 114, 115, -1, 117, - -1, 119, 120, 121, 122, 123, 124, -1, 126, 127, - 128, 129, 130, -1, -1, 133, 134, 135, 136, 137, - -1, 139, 140, 141, -1, 143, 144, 145, -1, 147, - 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, - -1, 159, -1, 161, 162, 163, 164, -1, 166, -1, - 168, -1, -1, -1, 172, 173, 174, -1, 176, -1, - 178, -1, 180, 181, 182, -1, 184, 185, 186, 187, - 188, 189, 190, -1, 192, 193, 194, 195, -1, 197, - 198, 199, 200, 201, 202, -1, 204, -1, 206, 207, - 208, 209, 210, 211, 212, 213, -1, 215, -1, 217, - -1, -1, 220, -1, 222, 223, 224, 225, 226, 227, - -1, -1, 230, -1, 232, -1, -1, 235, 236, 237, - -1, -1, 240, 241, 242, 243, 244, 245, 246, 247, - 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, - 258, 259, 260, 261, 262, 263, 264, -1, 266, 267, - 268, 269, 270, -1, 272, 273, -1, 275, -1, 277, - 278, 279, 280, 281, 282, -1, 284, 285, -1, -1, - 288, 289, 290, -1, -1, 293, 294, -1, 296, -1, - 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, - 308, -1, 310, 311, 312, 313, 314, 315, 316, 317, - 318, -1, 320, 321, 322, 323, 324, 325, -1, 327, - 328, 329, 330, 331, 332, 333, 334, -1, 336, 337, - 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, - 348, -1, 350, 351, -1, 353, 354, 355, 356, 357, - 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, - -1, 369, 370, 371, 372, 373, -1, 375, 376, 377, - 378, 379, -1, 381, 382, 383, 384, -1, 386, 387, - 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, - 398, 399, 400, 401, -1, 403, 404, -1, 406, -1, - 408, 409, 410, 411, 412, -1, 414, 415, -1, -1, - 418, 419, 420, 421, 422, -1, 424, 425, 426, 427, - 428, 429, 430, 431, -1, -1, 434, 435, 436, 437, - 438, -1, -1, 441, 442, 443, 444, 445, 446, 447, - -1, 449, -1, 451, 452, 453, 454, 455, -1, -1, - 458, -1, -1, 461, 462, 463, 464, 465, 466, 467, - 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, - 478, 479, 480, 481, 3, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + 406, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, 4, -1, + -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 20, 21, 22, 23, 24, 25, 26, 27, -1, - 29, 30, 31, -1, -1, -1, -1, -1, -1, -1, - 39, 40, -1, 42, 43, 44, -1, 46, 47, 48, - 49, 50, -1, 52, 53, -1, 55, 56, 57, 58, - 59, 60, -1, -1, 63, 64, 65, 66, 67, -1, - 69, 70, 71, 72, 73, -1, -1, -1, 77, 78, - 79, 80, 81, 82, -1, 84, 85, 86, -1, 88, - 89, 90, 91, 92, 93, -1, -1, 96, 97, 98, - -1, -1, -1, -1, -1, -1, -1, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, -1, 117, -1, - 119, 120, 121, 122, 123, 124, -1, 126, 127, 128, - 129, 130, -1, -1, 133, 134, 135, 136, 137, -1, - 139, 140, 141, -1, 143, 144, 145, -1, 147, 148, - 149, 150, 151, 152, 153, 154, 155, 156, 157, -1, - 159, -1, 161, 162, 163, 164, -1, 166, -1, 168, - -1, -1, -1, 172, 173, 174, -1, 176, -1, 178, - -1, 180, 181, 182, -1, 184, 185, 186, 187, 188, - 189, 190, -1, 192, 193, 194, 195, -1, 197, 198, - 199, 200, 201, 202, -1, 204, -1, 206, 207, 208, - 209, 210, 211, 212, 213, -1, 215, -1, 217, -1, - -1, 220, -1, 222, 223, 224, 225, 226, 227, -1, - -1, 230, -1, 232, -1, -1, 235, 236, 237, -1, - -1, 240, 241, 242, 243, 244, 245, 246, 247, 248, - 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, - 259, 260, 261, 262, 263, 264, -1, 266, 267, 268, - 269, 270, -1, 272, 273, -1, 275, -1, 277, 278, - 279, 280, 281, 282, -1, 284, 285, -1, -1, 288, - 289, 290, -1, -1, 293, 294, -1, 296, -1, 298, - 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, - -1, 310, 311, 312, 313, 314, 315, 316, 317, 318, - -1, 320, 321, 322, 323, 324, 325, -1, 327, 328, - 329, 330, 331, 332, 333, 334, -1, 336, 337, 338, - 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, - -1, 350, 351, -1, 353, 354, 355, 356, 357, 358, - 359, 360, 361, 362, 363, 364, 365, 366, 367, -1, - 369, 370, 371, 372, 373, -1, 375, 376, 377, 378, - 379, -1, 381, 382, 383, 384, -1, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, - 399, 400, 401, -1, 403, 404, -1, 406, -1, 408, - 409, 410, 411, 412, -1, 414, 415, -1, -1, 418, - 419, 420, 421, 422, -1, 424, 425, 426, 427, 428, - 429, 430, 431, -1, -1, 434, 435, 436, 437, 438, - -1, -1, 441, 442, 443, 444, 445, 446, 447, -1, - 449, -1, 451, 452, 453, 454, 455, -1, -1, 458, - -1, -1, 461, 462, 463, 464, 465, 466, 467, 468, - 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, - 479, 480, 481, 3, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, -1, -1, -1, 39, - 40, -1, 42, 43, 44, -1, 46, 47, 48, 49, - 50, -1, 52, 53, -1, 55, 56, 57, 58, 59, - 60, -1, -1, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, 73, -1, -1, -1, 77, 78, 79, - 80, 81, 82, -1, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, -1, 96, 97, 98, -1, - -1, -1, -1, -1, -1, -1, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, -1, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, 151, 152, 153, 154, 155, 156, 157, -1, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, -1, - -1, -1, 172, 173, 174, -1, 176, -1, 178, -1, - 180, 181, 182, -1, 184, 185, 186, 187, 188, 189, - 190, -1, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, -1, 206, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, -1, -1, - 220, -1, 222, 223, 224, 225, 226, 227, -1, -1, - 230, -1, 232, -1, -1, 235, 236, 237, -1, -1, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, -1, 266, 267, 268, 269, - 270, -1, 272, 273, -1, 275, -1, 277, 278, 279, - 280, 281, 282, -1, 284, 285, -1, -1, 288, 289, - 290, -1, -1, 293, 294, -1, 296, -1, 298, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, 312, 313, 314, 315, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, -1, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, -1, 369, - 370, 371, 372, 373, -1, 375, 376, 377, 378, 379, - -1, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, 403, 404, -1, 406, -1, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - 420, 421, 422, -1, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, -1, - -1, 441, 442, 443, 444, 445, 446, 447, -1, 449, - -1, 451, 452, 453, 454, 455, -1, -1, 458, -1, - -1, 461, 462, 463, 464, 465, 466, 467, 468, 469, - 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, - 480, 481, 3, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, - 21, 22, 23, 24, 25, 26, 27, -1, 29, 30, - 31, -1, -1, -1, -1, -1, -1, -1, 39, 40, - -1, 42, 43, 44, -1, 46, 47, 48, 49, 50, - -1, 52, 53, -1, 55, 56, 57, 58, 59, 60, - -1, -1, 63, 64, 65, 66, 67, -1, 69, 70, - 71, 72, 73, -1, -1, -1, 77, 78, 79, 80, - 81, 82, -1, 84, 85, 86, -1, 88, 89, 90, - 91, 92, 93, -1, -1, 96, 97, 98, -1, -1, - -1, -1, -1, -1, -1, 106, 107, 108, 109, 110, - 111, 112, 113, 114, 115, -1, 117, -1, 119, 120, - 121, 122, 123, 124, -1, 126, 127, 128, 129, 130, - -1, -1, 133, 134, 135, 136, 137, -1, 139, 140, - 141, -1, 143, 144, 145, -1, 147, 148, 149, 150, - 151, 152, 153, 154, 155, 156, 157, -1, 159, -1, - 161, 162, 163, 164, -1, 166, -1, 168, -1, -1, - -1, 172, 173, 174, -1, 176, -1, 178, -1, 180, - 181, 182, -1, 184, 185, 186, 187, 188, 189, 190, - -1, 192, 193, 194, 195, -1, 197, 198, 199, 200, - 201, 202, -1, 204, -1, 206, 207, 208, 209, 210, - 211, 212, 213, -1, 215, -1, 217, -1, -1, 220, - -1, 222, 223, 224, 225, 226, 227, -1, -1, 230, - -1, 232, -1, -1, 235, 236, 237, -1, -1, 240, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, 5, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, 5, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, 5, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, 5, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + 46, 47, 48, 49, -1, 51, 52, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, -1, -1, + 76, -1, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, -1, 153, 154, 155, + 156, 157, -1, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, 170, -1, 172, 173, 174, -1, + 176, 177, -1, 179, -1, -1, -1, 183, -1, 185, + 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + 206, -1, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 228, -1, -1, 231, 232, 233, 234, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + 266, 267, 268, 269, 270, -1, -1, 273, 274, 275, + 276, -1, -1, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, -1, + 296, 297, 298, -1, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, -1, 314, 315, + -1, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, 353, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, 375, + 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, -1, 402, -1, 404, 405, + -1, 407, 408, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, -1, 422, -1, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, 440, -1, 442, 443, 444, 445, + 446, -1, 448, -1, 450, 451, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 3, -1, 5, -1, -1, -1, -1, -1, + -1, -1, -1, 479, 480, 481, 482, -1, -1, -1, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, -1, -1, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, -1, 47, 48, 49, 50, + 51, -1, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, -1, 64, 65, 66, 67, 68, -1, 70, + 71, 72, 73, 74, -1, -1, -1, 78, 79, 80, + 81, 82, 83, -1, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, -1, -1, 97, 98, 99, -1, + -1, -1, -1, -1, -1, -1, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, -1, 160, + -1, 162, 163, 164, 165, -1, 167, -1, 169, -1, + -1, -1, 173, 174, 175, -1, 177, -1, 179, -1, + 181, 182, 183, -1, 185, 186, 187, 188, 189, 190, + 191, -1, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, -1, 207, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, -1, -1, + 221, -1, 223, 224, 225, 226, 227, 228, -1, -1, + 231, -1, 233, -1, -1, 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, - 261, 262, 263, 264, -1, 266, 267, 268, 269, 270, - -1, 272, 273, -1, 275, -1, 277, 278, 279, 280, - 281, 282, -1, 284, 285, -1, -1, 288, 289, 290, - -1, -1, 293, 294, -1, 296, -1, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, -1, 310, - 311, 312, 313, 314, 315, 316, 317, 318, -1, 320, - 321, 322, 323, 324, 325, -1, 327, 328, 329, 330, - 331, 332, 333, 334, -1, 336, 337, 338, 339, 340, - 341, 342, 343, 344, 345, 346, 347, 348, -1, 350, - 351, -1, 353, 354, 355, 356, 357, 358, 359, 360, - 361, 362, 363, 364, 365, 366, 367, -1, 369, 370, - 371, 372, 373, -1, 375, 376, 377, 378, 379, -1, - 381, 382, 383, 384, -1, 386, 387, 388, 389, 390, + 261, 262, 263, 264, 265, -1, 267, 268, 269, 270, + 271, -1, 273, 274, -1, 276, -1, 278, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, 295, -1, 297, -1, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, 313, 314, 315, 316, 317, 318, 319, -1, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, -1, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, -1, 376, 377, 378, 379, 380, + -1, 382, 383, 384, 385, -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, - 401, -1, 403, 404, -1, 406, -1, 408, 409, 410, - 411, 412, -1, 414, 415, -1, -1, 418, 419, 420, - 421, 422, -1, 424, 425, 426, 427, 428, 429, 430, - 431, -1, -1, 434, 435, 436, 437, 438, -1, -1, - 441, 442, 443, 444, 445, 446, 447, -1, 449, -1, - 451, 452, 453, 454, 455, -1, -1, 458, -1, -1, - 461, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 401, 402, -1, 404, 405, -1, 407, -1, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + 421, 422, 423, -1, 425, 426, 427, 428, 429, 430, + 431, 432, -1, -1, 435, 436, 437, 438, 439, -1, + -1, 442, 443, 444, 445, 446, 447, 448, -1, 450, + -1, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, - 481, 3, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 20, 21, - 22, 23, 24, 25, 26, 27, -1, 29, 30, 31, - -1, -1, -1, -1, -1, 37, -1, 39, 40, -1, - 42, 43, 44, -1, 46, 47, 48, 49, 50, -1, - 52, 53, -1, 55, 56, 57, 58, 59, 60, -1, - -1, 63, 64, 65, 66, 67, -1, 69, 70, 71, - 72, 73, -1, -1, -1, 77, 78, 79, 80, 81, - 82, -1, 84, 85, 86, -1, 88, 89, 90, 91, - 92, 93, -1, -1, 96, 97, 98, -1, -1, -1, - -1, -1, -1, -1, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, -1, 117, -1, 119, 120, 121, - 122, 123, 124, -1, 126, 127, 128, 129, 130, -1, - -1, 133, 134, 135, 136, 137, -1, 139, 140, 141, - -1, 143, 144, 145, -1, 147, 148, 149, 150, 151, - 152, 153, 154, 155, 156, 157, -1, 159, -1, 161, - 162, 163, 164, -1, 166, -1, 168, -1, -1, -1, - 172, 173, 174, -1, 176, -1, 178, -1, 180, 181, - 182, -1, 184, 185, 186, 187, 188, 189, 190, -1, - 192, 193, 194, 195, -1, 197, 198, 199, 200, 201, - 202, -1, 204, -1, 206, 207, 208, 209, 210, 211, - 212, 213, -1, 215, -1, 217, -1, -1, 220, -1, - 222, 223, 224, 225, 226, 227, -1, -1, 230, -1, - 232, -1, -1, 235, 236, 237, -1, -1, 240, 241, - 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, -1, 266, 267, 268, 269, 270, -1, - 272, 273, -1, 275, -1, 277, 278, 279, 280, 281, - 282, -1, 284, 285, -1, -1, 288, 289, 290, -1, - -1, 293, 294, -1, 296, -1, 298, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, -1, 310, 311, - 312, 313, 314, 315, 316, 317, 318, -1, 320, 321, - 322, 323, 324, 325, -1, 327, 328, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 346, 347, 348, -1, 350, 351, - -1, 353, 354, 355, 356, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, -1, 369, 370, 371, - 372, 373, -1, -1, 376, 377, 378, 379, -1, 381, - 382, 383, 384, -1, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - -1, 403, 404, -1, 406, -1, 408, 409, 410, 411, - 412, -1, 414, 415, -1, -1, 418, 419, 420, 421, - 422, -1, 424, 425, 426, 427, 428, 429, 430, 431, - -1, -1, 434, 435, 436, 437, 438, -1, -1, 441, - 442, 443, 444, 445, 446, 447, -1, 449, -1, 451, - 452, 453, 454, 455, -1, -1, 458, -1, -1, 461, - 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, - 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, - 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 20, 21, 22, - 23, 24, 25, 26, 27, -1, 29, 30, 31, -1, - -1, -1, -1, -1, -1, -1, 39, 40, -1, 42, - 43, 44, -1, 46, 47, 48, 49, 50, -1, 52, - 53, -1, 55, 56, 57, 58, 59, 60, -1, -1, - 63, 64, 65, 66, 67, -1, 69, 70, 71, 72, - 73, -1, -1, -1, 77, 78, 79, 80, 81, 82, - -1, 84, 85, 86, -1, 88, 89, 90, 91, 92, - 93, -1, -1, 96, 97, 98, -1, -1, -1, -1, - -1, -1, -1, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, -1, 117, -1, 119, 120, 121, 122, - 123, 124, -1, 126, 127, 128, 129, 130, -1, -1, - 133, 134, 135, 136, 137, -1, 139, 140, 141, -1, - 143, 144, 145, -1, 147, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, -1, 159, -1, 161, 162, - 163, 164, -1, 166, -1, 168, -1, -1, -1, 172, - 173, 174, -1, 176, -1, 178, -1, 180, 181, 182, - -1, 184, 185, 186, 187, 188, 189, 190, -1, 192, - 193, 194, 195, -1, 197, 198, 199, 200, 201, 202, - -1, 204, -1, 206, 207, 208, 209, 210, 211, 212, - 213, -1, 215, -1, 217, -1, -1, 220, -1, 222, - 223, 224, 225, 226, 227, -1, -1, 230, -1, 232, - -1, -1, 235, 236, 237, -1, -1, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, -1, 266, 267, 268, 269, 270, -1, 272, - 273, -1, 275, -1, 277, 278, 279, 280, 281, 282, - -1, 284, 285, -1, -1, 288, 289, 290, -1, -1, - 293, 294, -1, 296, -1, 298, 299, 300, 301, 302, - 303, 304, 305, 306, 307, 308, -1, 310, 311, 312, - 313, 314, 315, 316, 317, 318, -1, 320, 321, 322, - 323, 324, 325, -1, 327, 328, 329, 330, 331, 332, - 333, 334, -1, 336, 337, 338, 339, 340, 341, 342, - 343, 344, 345, 346, 347, 348, -1, 350, 351, -1, - 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, - 363, 364, 365, 366, 367, -1, 369, 370, 371, 372, - 373, -1, 375, 376, 377, 378, 379, -1, 381, 382, - 383, 384, -1, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 397, 398, 399, 400, 401, -1, - 403, 404, -1, 406, -1, 408, 409, 410, 411, 412, - -1, 414, 415, -1, -1, 418, 419, 420, 421, 422, - -1, 424, 425, 426, 427, 428, 429, 430, 431, -1, - -1, 434, 435, 436, 437, 438, -1, -1, 441, 442, - 443, 444, 445, 446, 447, -1, 449, -1, 451, 452, - 453, 454, 455, -1, -1, 458, -1, -1, 461, 462, - 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, - 473, 474, 475, 476, 477, 478, 479, 480, 481, 3, + 481, 482, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, - 24, 25, 26, 27, -1, 29, 30, 31, -1, -1, - -1, -1, -1, -1, -1, 39, 40, -1, 42, 43, - 44, -1, 46, 47, 48, 49, 50, -1, 52, 53, - -1, 55, 56, 57, 58, 59, 60, -1, -1, 63, - 64, 65, 66, 67, -1, 69, 70, 71, 72, 73, - -1, -1, -1, 77, 78, 79, 80, 81, 82, -1, - 84, 85, 86, -1, 88, 89, 90, 91, 92, 93, - -1, -1, 96, 97, 98, -1, -1, -1, -1, -1, - -1, -1, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, -1, 117, -1, 119, 120, 121, 122, 123, - 124, -1, 126, 127, 128, 129, 130, -1, -1, 133, - 134, 135, 136, 137, -1, 139, 140, 141, -1, 143, - 144, 145, -1, 147, 148, 149, 150, 151, 152, 153, - 154, 155, 156, 157, -1, 159, -1, 161, 162, 163, - 164, -1, 166, -1, 168, -1, -1, -1, 172, 173, - 174, -1, 176, -1, 178, -1, 180, 181, 182, -1, - 184, 185, 186, 187, 188, 189, 190, -1, 192, 193, - 194, 195, -1, 197, 198, 199, 200, 201, 202, -1, - 204, -1, 206, 207, 208, 209, 210, 211, 212, 213, - -1, 215, -1, 217, -1, -1, 220, -1, 222, 223, - 224, 225, 226, 227, -1, -1, 230, -1, 232, -1, - -1, 235, 236, 237, -1, -1, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, -1, 266, 267, 268, 269, 270, -1, 272, 273, - -1, 275, -1, 277, 278, 279, 280, 281, 282, -1, - 284, 285, -1, -1, 288, 289, 290, -1, -1, 293, - 294, -1, 296, -1, 298, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, -1, 310, 311, 312, 313, - 314, 315, 316, 317, 318, -1, 320, 321, 322, 323, - 324, 325, -1, 327, 328, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, -1, 350, 351, -1, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, -1, 369, 370, 371, 372, 373, - -1, 375, 376, 377, 378, 379, -1, 381, 382, 383, - 384, -1, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, 400, 401, -1, 403, - 404, -1, 406, -1, 408, 409, 410, 411, 412, -1, - 414, 415, -1, -1, 418, 419, 420, 421, 422, -1, - 424, 425, 426, 427, 428, 429, 430, 431, -1, -1, - 434, 435, 436, 437, 438, -1, -1, 441, 442, 443, - 444, 445, 446, 447, -1, 449, -1, 451, 452, 453, - 454, 455, -1, -1, 458, -1, -1, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 3, -1, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, -1, -1, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, -1, 47, 48, 49, 50, + 51, -1, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, -1, 64, 65, 66, 67, 68, -1, 70, + 71, 72, 73, 74, -1, -1, -1, 78, 79, 80, + 81, 82, 83, -1, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, -1, -1, 97, 98, 99, -1, + -1, -1, -1, -1, -1, -1, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, -1, 160, + -1, 162, 163, 164, 165, -1, 167, -1, 169, -1, + -1, -1, 173, 174, 175, -1, 177, -1, 179, -1, + 181, 182, 183, -1, 185, 186, 187, 188, 189, 190, + 191, -1, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, -1, 207, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, -1, -1, + 221, -1, 223, 224, 225, 226, 227, 228, -1, -1, + 231, -1, 233, -1, -1, 236, 237, 238, -1, -1, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, -1, 267, 268, 269, 270, + 271, -1, 273, 274, -1, 276, -1, 278, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, 295, -1, 297, -1, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, 313, 314, 315, 316, 317, 318, 319, -1, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, -1, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, -1, 376, 377, 378, 379, 380, + -1, 382, 383, 384, 385, -1, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, -1, 404, 405, -1, 407, -1, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + 421, 422, 423, -1, 425, 426, 427, 428, 429, 430, + 431, 432, -1, -1, 435, 436, 437, 438, 439, -1, + -1, 442, 443, 444, 445, 446, 447, 448, -1, 450, + -1, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 20, 21, 22, 23, 24, - 25, 26, 27, -1, 29, 30, 31, -1, -1, -1, - -1, -1, -1, -1, 39, 40, -1, 42, 43, 44, - -1, 46, 47, 48, 49, 50, -1, 52, 53, -1, - 55, 56, 57, 58, 59, 60, -1, -1, 63, 64, - 65, 66, 67, -1, 69, 70, 71, 72, 73, -1, - -1, -1, 77, 78, 79, 80, 81, 82, -1, 84, - 85, 86, -1, 88, 89, 90, 91, 92, 93, -1, - -1, 96, 97, 98, -1, -1, -1, -1, -1, -1, - -1, 106, 107, 108, 109, 110, 111, 112, 113, 114, - 115, -1, 117, -1, 119, 120, 121, 122, 123, 124, - -1, 126, 127, 128, 129, 130, -1, -1, 133, 134, - 135, 136, 137, -1, 139, 140, 141, -1, 143, 144, - 145, -1, 147, 148, 149, 150, 151, 152, 153, 154, - 155, 156, 157, -1, 159, -1, 161, 162, 163, 164, - -1, 166, -1, 168, -1, -1, -1, 172, 173, 174, - -1, 176, -1, 178, -1, 180, 181, 182, -1, 184, - 185, 186, 187, 188, 189, 190, -1, 192, 193, 194, - 195, -1, 197, 198, 199, 200, 201, 202, -1, 204, - -1, 206, 207, 208, 209, 210, 211, 212, 213, -1, - 215, -1, 217, -1, -1, 220, -1, 222, 223, 224, - 225, 226, 227, -1, -1, 230, -1, 232, -1, -1, - 235, 236, 237, -1, -1, 240, 241, 242, 243, 244, - 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, - 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, - -1, 266, 267, 268, 269, 270, -1, 272, 273, -1, - 275, -1, 277, 278, 279, 280, 281, 282, -1, 284, - 285, -1, -1, 288, 289, 290, -1, -1, 293, 294, - -1, 296, -1, 298, 299, 300, 301, 302, 303, 304, - 305, 306, 307, 308, -1, 310, 311, 312, 313, 314, - 315, 316, 317, 318, -1, 320, 321, 322, 323, 324, - 325, -1, 327, 328, 329, 330, 331, 332, 333, 334, - -1, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, -1, 350, 351, -1, 353, 354, - 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, - 365, 366, 367, -1, 369, 370, 371, 372, 373, -1, - 375, 376, 377, 378, 379, -1, 381, 382, 383, 384, - -1, 386, 387, 388, 389, 390, 391, 392, 393, 394, - 395, 396, 397, 398, 399, 400, 401, -1, 403, 404, - -1, 406, -1, 408, 409, 410, 411, 412, -1, 414, - 415, -1, -1, 418, 419, 420, 421, 422, -1, 424, - 425, 426, 427, 428, 429, 430, 431, -1, -1, 434, - 435, 436, 437, 438, -1, -1, 441, 442, 443, 444, - 445, 446, 447, -1, 449, -1, 451, 452, 453, 454, - 455, -1, -1, 458, -1, -1, 461, 462, 463, 464, - 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 478, 479, 480, 481, 3, -1, -1, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, -1, -1, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, -1, 47, 48, 49, 50, + 51, -1, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, -1, 64, 65, 66, 67, 68, -1, 70, + 71, 72, 73, 74, -1, -1, -1, 78, 79, 80, + 81, 82, 83, -1, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, -1, -1, 97, 98, 99, -1, + -1, -1, -1, -1, -1, -1, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, -1, 160, + -1, 162, 163, 164, 165, -1, 167, -1, 169, -1, + -1, -1, 173, 174, 175, -1, 177, -1, 179, -1, + 181, 182, 183, -1, 185, 186, 187, 188, 189, 190, + 191, -1, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, -1, 207, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, -1, -1, + 221, -1, 223, 224, 225, 226, 227, 228, -1, -1, + 231, -1, 233, -1, -1, 236, 237, 238, -1, -1, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, -1, 267, 268, 269, 270, + 271, -1, 273, 274, -1, 276, -1, 278, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, 295, -1, 297, -1, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, 313, 314, 315, 316, 317, 318, 319, -1, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, -1, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, -1, 376, 377, 378, 379, 380, + -1, 382, 383, 384, 385, -1, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, -1, 404, 405, -1, 407, -1, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + 421, 422, 423, -1, 425, 426, 427, 428, 429, 430, + 431, 432, -1, -1, 435, 436, 437, 438, 439, -1, + -1, 442, 443, 444, 445, 446, 447, 448, -1, 450, + -1, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 3, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 20, 21, 22, 23, 24, 25, - 26, 27, -1, 29, 30, 31, -1, -1, -1, -1, - -1, -1, -1, 39, 40, -1, 42, 43, 44, -1, - 46, 47, 48, 49, 50, -1, 52, 53, -1, 55, - 56, 57, 58, 59, 60, -1, -1, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, 73, -1, -1, - -1, 77, 78, 79, 80, 81, 82, -1, 84, 85, - 86, -1, 88, 89, 90, 91, 92, 93, -1, -1, - 96, 97, 98, -1, -1, -1, -1, -1, -1, -1, - 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - -1, 117, -1, 119, 120, 121, 122, 123, 124, -1, - 126, 127, 128, 129, 130, -1, -1, 133, 134, 135, - 136, 137, -1, 139, 140, 141, -1, 143, 144, 145, - -1, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 156, 157, -1, 159, -1, 161, 162, 163, 164, -1, - 166, -1, 168, -1, -1, -1, 172, 173, 174, -1, - 176, -1, 178, -1, 180, 181, 182, -1, 184, 185, - 186, 187, 188, 189, 190, -1, 192, 193, 194, 195, - -1, 197, 198, 199, 200, 201, 202, -1, 204, -1, - 206, 207, 208, 209, 210, 211, 212, 213, -1, 215, - -1, 217, -1, -1, 220, -1, 222, 223, 224, 225, - 226, 227, -1, -1, 230, -1, 232, -1, -1, 235, - 236, 237, -1, -1, 240, 241, 242, 243, 244, 245, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, -1, -1, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, -1, 47, 48, 49, 50, + 51, -1, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, -1, 64, 65, 66, 67, 68, -1, 70, + 71, 72, 73, 74, -1, -1, -1, 78, 79, 80, + 81, 82, 83, -1, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, -1, -1, 97, 98, 99, -1, + -1, -1, -1, -1, -1, -1, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, 152, 153, 154, 155, 156, 157, 158, -1, 160, + -1, 162, 163, 164, 165, -1, 167, -1, 169, -1, + -1, -1, 173, 174, 175, -1, 177, -1, 179, -1, + 181, 182, 183, -1, 185, 186, 187, 188, 189, 190, + 191, -1, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, -1, 207, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, -1, -1, + 221, -1, 223, 224, 225, 226, 227, 228, -1, -1, + 231, -1, 233, -1, -1, 236, 237, 238, -1, -1, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, -1, 267, 268, 269, 270, + 271, -1, 273, 274, -1, 276, -1, 278, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, 295, -1, 297, -1, 299, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, 313, 314, 315, 316, 317, 318, 319, -1, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, -1, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, -1, 376, 377, 378, 379, 380, + -1, 382, 383, 384, 385, -1, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + 401, 402, -1, 404, 405, -1, 407, -1, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + 421, 422, 423, -1, 425, 426, 427, 428, 429, 430, + 431, 432, -1, -1, 435, 436, 437, 438, 439, -1, + -1, 442, 443, 444, 445, 446, 447, 448, -1, 450, + -1, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, + 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, + 481, 482, 3, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, -1, -1, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, 46, 47, 48, 49, -1, + 51, 52, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, -1, 64, 65, 66, 67, 68, -1, 70, + 71, 72, 73, -1, -1, 76, -1, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, -1, 96, 97, 98, 99, 100, + 101, 102, 103, -1, -1, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, -1, 153, 154, 155, 156, 157, -1, -1, 160, + -1, 162, 163, 164, 165, -1, 167, -1, 169, 170, + -1, 172, 173, 174, -1, 176, 177, -1, 179, -1, + -1, -1, 183, -1, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, 206, -1, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, -1, -1, + 231, 232, 233, 234, -1, 236, 237, 238, -1, -1, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + -1, -1, 273, 274, 275, 276, -1, -1, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, -1, 296, 297, 298, -1, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, -1, 314, 315, -1, 317, 318, 319, -1, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, + 381, 382, 383, 384, 385, -1, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, + -1, 402, -1, 404, 405, -1, 407, 408, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + -1, 422, -1, -1, 425, 426, 427, 428, 429, 430, + 431, 432, -1, -1, 435, 436, 437, 438, 439, 440, + -1, 442, 443, 444, 445, 446, -1, 448, -1, 450, + 451, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 3, -1, 5, + -1, -1, -1, -1, -1, -1, -1, -1, 479, 480, + 481, 482, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, - 256, 257, 258, 259, 260, 261, 262, 263, 264, -1, - 266, 267, 268, 269, 270, -1, 272, 273, -1, 275, - -1, 277, 278, 279, 280, 281, 282, -1, 284, 285, - -1, -1, 288, 289, 290, -1, -1, 293, 294, -1, - 296, -1, 298, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, -1, 310, 311, 312, 313, 314, 315, - 316, 317, 318, -1, 320, 321, 322, 323, 324, 325, - -1, 327, 328, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, 350, 351, -1, 353, 354, 355, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, -1, 369, 370, 371, 372, 373, -1, 375, - 376, 377, 378, 379, -1, 381, 382, 383, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, 400, 401, -1, 403, 404, -1, - 406, -1, 408, 409, 410, 411, 412, -1, 414, 415, - -1, -1, 418, 419, 420, 421, 422, -1, 424, 425, - 426, 427, 428, 429, 430, 431, -1, -1, 434, 435, - 436, 437, 438, -1, -1, 441, 442, 443, 444, 445, - 446, 447, -1, 449, -1, 451, 452, 453, 454, 455, - -1, -1, 458, -1, -1, 461, 462, 463, 464, 465, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, - 476, 477, 478, 479, 480, 481, 3, -1, -1, -1, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 20, 21, 22, 23, 24, 25, 26, - 27, -1, 29, 30, 31, -1, -1, -1, -1, -1, - 37, -1, 39, 40, -1, 42, 43, 44, 45, 46, - 47, 48, -1, 50, 51, 52, 53, -1, 55, 56, - 57, 58, 59, 60, -1, -1, 63, 64, 65, 66, - 67, -1, 69, 70, 71, 72, -1, -1, 75, -1, - 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, - -1, 88, 89, 90, 91, 92, 93, -1, 95, 96, - 97, 98, -1, -1, -1, 102, -1, -1, -1, 106, - 107, 108, 109, 110, 111, 112, 113, 114, 115, -1, - 117, -1, 119, 120, 121, 122, 123, 124, -1, 126, - 127, 128, 129, 130, -1, -1, 133, 134, 135, 136, - 137, -1, 139, 140, 141, -1, 143, 144, 145, -1, - 147, 148, 149, 150, -1, 152, 153, 154, 155, 156, - -1, -1, 159, -1, 161, 162, 163, 164, -1, 166, - -1, 168, 169, -1, 171, 172, 173, 174, 175, 176, - -1, 178, -1, -1, -1, 182, -1, 184, 185, 186, - 187, 188, 189, 190, 191, 192, 193, 194, 195, -1, - 197, 198, 199, 200, 201, 202, -1, 204, 205, -1, - 207, 208, 209, 210, 211, 212, 213, -1, 215, -1, - 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, - 227, -1, -1, 230, 231, 232, 233, -1, 235, 236, - 237, -1, -1, 240, 241, 242, 243, 244, 245, 246, - 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, - 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, - 267, 268, 269, -1, -1, 272, 273, 274, 275, -1, - -1, 278, 279, 280, 281, 282, -1, 284, 285, -1, - -1, 288, 289, 290, -1, -1, 293, -1, 295, 296, - 297, -1, 299, 300, 301, 302, 303, 304, 305, 306, - 307, 308, -1, 310, 311, -1, 313, 314, -1, 316, - 317, 318, -1, 320, 321, 322, 323, 324, 325, -1, - 327, 328, 329, 330, 331, 332, 333, 334, -1, 336, - 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, - 347, 348, -1, 350, 351, 352, 353, 354, 355, 356, - 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, - 367, -1, 369, 370, 371, 372, 373, -1, 375, 376, - 377, 378, 379, 380, 381, 382, 383, 384, -1, 386, - 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, - 397, 398, 399, -1, 401, -1, 403, 404, -1, 406, - 407, 408, 409, 410, 411, 412, -1, 414, 415, -1, - -1, 418, 419, -1, 421, -1, -1, 424, 425, 426, - 427, 428, 429, 430, 431, -1, -1, 434, 435, 436, - 437, 438, -1, -1, 441, 442, 443, 444, 445, -1, - 447, -1, 449, 450, 451, 452, 453, 454, 455, -1, - -1, 458, -1, -1, 461, 462, 463, 464, 465, 466, - 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 478, 479, 480, 481, -1, -1, 20, 21, 22, - 23, 24, 25, 26, 27, -1, 29, 30, 31, -1, - -1, -1, -1, -1, -1, -1, 39, 40, -1, 42, - 43, 44, -1, 46, 47, 48, 49, 50, -1, 52, - 53, -1, 55, 56, 57, 58, 59, 60, -1, -1, - 63, 64, 65, 66, 67, -1, 69, 70, 71, 72, - 73, -1, -1, -1, 77, 78, 79, 80, 81, 82, - -1, 84, 85, 86, -1, 88, 89, 90, 91, 92, - 93, -1, -1, 96, 97, 98, -1, -1, -1, -1, - -1, -1, -1, 106, 107, 108, 109, 110, 111, 112, - 113, 114, 115, -1, 117, -1, 119, 120, 121, 122, - 123, 124, -1, 126, 127, 128, 129, 130, -1, -1, - 133, 134, 135, 136, 137, -1, 139, 140, 141, -1, - 143, 144, 145, -1, 147, 148, 149, 150, 151, 152, - 153, 154, 155, 156, 157, -1, 159, -1, 161, 162, - 163, 164, -1, 166, -1, 168, -1, -1, -1, 172, - 173, 174, -1, 176, -1, 178, -1, 180, 181, 182, - -1, 184, 185, 186, 187, 188, 189, 190, -1, 192, - 193, 194, 195, -1, 197, 198, 199, 200, 201, 202, - -1, 204, -1, 206, 207, 208, 209, 210, 211, 212, - 213, -1, 215, -1, 217, -1, -1, 220, -1, 222, - 223, 224, 225, 226, 227, -1, -1, 230, -1, 232, - -1, -1, 235, 236, 237, -1, -1, 240, 241, 242, - 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, - 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, - 263, 264, -1, 266, 267, 268, 269, 270, -1, 272, - 273, -1, 275, -1, 277, 278, 279, 280, 281, 282, - -1, 284, 285, -1, -1, 288, 289, 290, -1, -1, - 293, 294, -1, 296, -1, 298, 299, 300, 301, 302, - 303, 304, -1, 306, 307, 308, -1, 310, 311, 312, - 313, 314, 315, 316, 317, 318, -1, 320, 321, 322, - 323, 324, 325, -1, 327, -1, 329, 330, 331, 332, - 333, 334, -1, 336, 337, 338, 339, 340, 341, 342, - 343, 344, 345, 346, 347, 348, -1, 350, 351, -1, - 353, 354, 355, 356, -1, 358, 359, 360, 361, 362, - 363, 364, 365, 366, 367, -1, 369, 370, 371, 372, - 373, -1, 375, 376, 377, 378, 379, -1, 381, 382, - 383, 384, -1, 386, 387, 388, 389, 390, 391, 392, - 393, 394, 395, 396, 397, 398, 399, 400, 401, -1, - 403, 404, -1, 406, -1, 408, 409, 410, 411, 412, - -1, 414, 415, -1, -1, 418, 419, 420, 421, 422, - -1, 424, 425, 426, 427, 428, 429, 430, 431, -1, - -1, 434, 435, 436, 437, 438, -1, -1, 441, 442, - 443, 444, 445, 446, 447, -1, 449, -1, 451, 452, - 453, 454, 455, -1, -1, 458, -1, -1, 461, 462, - 463, 464, 465, 466, 467, 468, 469, 470, 471, 472, - 473, 474, 475, 476, 477, 478, 479, 480, 481, 3, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, 38, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 20, 21, 22, 23, - 24, 25, 26, 27, -1, 29, 30, 31, -1, -1, - -1, -1, -1, -1, -1, 39, 40, -1, 42, 43, - 44, 45, 46, 47, 48, -1, 50, 51, 52, 53, - -1, 55, 56, 57, 58, 59, 60, -1, -1, 63, - 64, 65, 66, 67, -1, 69, 70, 71, 72, -1, - -1, 75, -1, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, -1, 88, 89, 90, 91, 92, 93, - -1, 95, 96, 97, 98, -1, -1, -1, 102, -1, - -1, -1, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, -1, 117, -1, 119, 120, 121, 122, 123, - 124, -1, 126, 127, 128, 129, 130, -1, -1, 133, - 134, 135, 136, 137, -1, 139, 140, 141, -1, 143, - 144, 145, -1, 147, 148, 149, 150, -1, 152, 153, - 154, 155, 156, -1, -1, 159, -1, 161, 162, 163, - 164, -1, 166, -1, 168, 169, -1, 171, 172, 173, - -1, 175, 176, -1, 178, -1, -1, -1, 182, -1, - 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, - 194, 195, -1, 197, 198, 199, 200, 201, 202, -1, - 204, 205, -1, 207, 208, 209, 210, 211, 212, 213, - -1, 215, -1, 217, 218, 219, 220, 221, 222, 223, - 224, 225, 226, 227, -1, -1, 230, 231, 232, 233, - -1, 235, 236, 237, -1, -1, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, -1, -1, 272, 273, - 274, 275, -1, -1, 278, 279, 280, 281, 282, -1, - 284, 285, -1, -1, 288, 289, 290, -1, -1, 293, - -1, 295, 296, 297, -1, 299, 300, 301, 302, 303, - 304, 305, 306, 307, 308, -1, 310, 311, -1, 313, - 314, -1, 316, 317, 318, -1, 320, 321, 322, 323, - 324, 325, -1, 327, 328, 329, 330, 331, 332, 333, - 334, -1, 336, 337, 338, 339, 340, 341, 342, 343, - 344, 345, 346, 347, 348, -1, 350, 351, 352, 353, - 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, - 364, 365, 366, 367, -1, 369, 370, 371, 372, 373, - -1, 375, 376, 377, 378, 379, 380, 381, 382, 383, - 384, -1, 386, 387, 388, 389, 390, 391, 392, 393, - 394, 395, 396, 397, 398, 399, -1, 401, -1, 403, - 404, -1, 406, 407, 408, 409, 410, 411, 412, -1, - 414, 415, -1, -1, 418, 419, -1, 421, -1, -1, - 424, 425, 426, 427, 428, 429, 430, 431, -1, -1, - 434, 435, 436, 437, 438, -1, -1, 441, 442, 443, - 444, 445, -1, 447, -1, 449, 450, 451, 452, 453, - 454, 455, -1, -1, 458, -1, -1, 461, 462, 463, - 464, 465, 466, 3, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 478, 479, 480, 481, -1, -1, - 20, 21, 22, 23, 24, 25, 26, 27, -1, 29, - 30, 31, -1, -1, -1, -1, -1, -1, -1, 39, - 40, -1, 42, 43, 44, 45, 46, 47, 48, -1, - 50, 51, 52, 53, -1, 55, 56, 57, 58, 59, - 60, -1, -1, 63, 64, 65, 66, 67, -1, 69, - 70, 71, 72, -1, -1, 75, -1, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, -1, 88, 89, - 90, 91, 92, 93, -1, 95, 96, 97, 98, -1, - -1, -1, 102, -1, -1, -1, 106, 107, 108, 109, - 110, 111, 112, 113, 114, 115, -1, 117, -1, 119, - 120, 121, 122, 123, 124, -1, 126, 127, 128, 129, - 130, -1, -1, 133, 134, 135, 136, 137, -1, 139, - 140, 141, -1, 143, 144, 145, -1, 147, 148, 149, - 150, -1, 152, 153, 154, 155, 156, -1, -1, 159, - -1, 161, 162, 163, 164, -1, 166, -1, 168, 169, - -1, 171, 172, 173, -1, 175, 176, -1, 178, -1, - -1, -1, 182, -1, 184, 185, 186, 187, 188, 189, - 190, 191, 192, 193, 194, 195, -1, 197, 198, 199, - 200, 201, 202, -1, 204, 205, -1, 207, 208, 209, - 210, 211, 212, 213, -1, 215, -1, 217, 218, 219, - 220, 221, 222, 223, 224, 225, 226, 227, -1, -1, - 230, 231, 232, 233, -1, 235, 236, 237, -1, -1, - 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, - 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, - 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, - -1, -1, 272, 273, 274, 275, -1, -1, 278, 279, - 280, 281, 282, -1, 284, 285, -1, -1, 288, 289, - 290, -1, -1, 293, -1, 295, 296, 297, -1, 299, - 300, 301, 302, 303, 304, 305, 306, 307, 308, -1, - 310, 311, -1, 313, 314, -1, 316, 317, 318, -1, - 320, 321, 322, 323, 324, 325, -1, 327, 328, 329, - 330, 331, 332, 333, 334, -1, 336, 337, 338, 339, - 340, 341, 342, 343, 344, 345, 346, 347, 348, -1, - 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, - 360, 361, 362, 363, 364, 365, 366, 367, -1, 369, - 370, 371, 372, 373, -1, 375, 376, 377, 378, 379, - 380, 381, 382, 383, 384, -1, 386, 387, 388, 389, - 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, - -1, 401, -1, 403, 404, -1, 406, 407, 408, 409, - 410, 411, 412, -1, 414, 415, -1, -1, 418, 419, - -1, 421, -1, -1, 424, 425, 426, 427, 428, 429, - 430, 431, -1, -1, 434, 435, 436, 437, 438, -1, - -1, 441, 442, 443, 444, 445, -1, 447, -1, 449, - 450, 451, 452, 453, 454, 455, -1, -1, 458, -1, - -1, 461, 462, 463, 464, 465, 466, 3, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 478, 479, - 480, 481, -1, -1, 20, 21, 22, 23, 24, 25, - 26, 27, -1, 29, 30, 31, -1, -1, -1, -1, - -1, -1, -1, 39, 40, -1, 42, 43, 44, 45, - 46, 47, 48, -1, 50, 51, 52, 53, -1, 55, - 56, 57, 58, 59, 60, -1, -1, 63, 64, 65, - 66, 67, -1, 69, 70, 71, 72, -1, -1, 75, - -1, 77, 78, 79, 80, 81, 82, 83, 84, 85, - 86, -1, 88, 89, 90, 91, 92, 93, -1, 95, - 96, 97, 98, -1, -1, -1, 102, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, 38, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, 5, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, 38, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + -1, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + 46, 47, 48, 49, -1, 51, 52, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, -1, -1, + 76, -1, 78, 79, 80, 81, 82, 83, 84, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + 96, 97, 98, 99, 100, 101, 102, 103, -1, -1, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, - -1, 117, -1, 119, 120, 121, 122, 123, 124, -1, - 126, 127, 128, 129, 130, -1, -1, 133, 134, 135, - 136, 137, -1, 139, 140, 141, -1, 143, 144, 145, - -1, 147, 148, 149, 150, -1, 152, 153, 154, 155, - 156, -1, -1, 159, -1, 161, 162, 163, 164, -1, - 166, -1, 168, 169, -1, 171, 172, 173, 174, 175, - 176, -1, 178, -1, -1, -1, 182, -1, 184, 185, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, -1, 153, 154, 155, + 156, 157, -1, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, 170, -1, 172, 173, 174, 175, + 176, 177, -1, 179, -1, -1, -1, 183, -1, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, - -1, 197, 198, 199, 200, 201, 202, -1, 204, 205, - -1, 207, 208, 209, 210, 211, 212, 213, -1, 215, - -1, 217, 218, 219, 220, 221, 222, 223, 224, 225, - 226, 227, -1, -1, 230, 231, 232, 233, -1, 235, - 236, 237, -1, -1, 240, 241, 242, 243, 244, 245, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + 206, -1, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 228, -1, -1, 231, 232, 233, 234, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, - 266, 267, 268, 269, -1, -1, 272, 273, 274, 275, - -1, -1, 278, 279, 280, 281, 282, -1, 284, 285, - -1, -1, 288, 289, 290, -1, -1, 293, -1, 295, - 296, 297, -1, 299, 300, 301, 302, 303, 304, 305, - 306, 307, 308, -1, 310, 311, -1, 313, 314, -1, - 316, 317, 318, -1, 320, 321, 322, 323, 324, 325, - -1, 327, 328, 329, 330, 331, 332, 333, 334, -1, - 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, - 346, 347, 348, -1, 350, 351, 352, 353, 354, 355, - -1, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, -1, 369, 370, 371, 372, 373, -1, 375, - -1, 377, 378, 379, 380, 381, 382, 383, 384, -1, - 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, - 396, 397, 398, 399, -1, 401, -1, 403, 404, -1, - 406, 407, 408, 409, 410, 411, 412, -1, 414, 415, - -1, -1, 418, 419, -1, 421, -1, -1, 424, 425, - 426, 427, 428, 429, 430, 431, -1, -1, 434, 435, - 436, 437, 438, -1, -1, 441, 442, 443, 444, 445, - -1, 447, -1, 449, 450, 451, 452, 453, 454, 455, - -1, -1, 458, -1, -1, 461, 462, 463, 464, 465, - 466, 3, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 478, 479, 480, 481, -1, -1, 20, 21, - 22, 23, 24, 25, 26, 27, -1, 29, 30, 31, - -1, -1, -1, -1, -1, -1, -1, 39, 40, -1, - 42, 43, 44, 45, 46, 47, 48, -1, 50, 51, - 52, 53, -1, 55, 56, 57, 58, 59, 60, -1, - -1, 63, 64, 65, 66, 67, -1, 69, 70, 71, - 72, -1, -1, 75, -1, 77, 78, 79, 80, 81, - 82, 83, 84, 85, 86, -1, 88, 89, 90, 91, - 92, 93, -1, 95, 96, 97, 98, -1, -1, -1, - 102, -1, -1, -1, 106, 107, 108, 109, 110, 111, - 112, 113, 114, 115, -1, 117, -1, 119, 120, 121, - 122, 123, 124, -1, 126, 127, 128, 129, 130, -1, - -1, 133, 134, 135, 136, 137, -1, 139, 140, 141, - -1, 143, 144, 145, -1, 147, 148, 149, 150, -1, - 152, 153, 154, 155, 156, -1, -1, 159, -1, 161, - 162, 163, 164, -1, 166, -1, 168, 169, -1, 171, - 172, 173, -1, 175, 176, -1, 178, -1, -1, -1, - 182, -1, 184, 185, 186, 187, 188, 189, 190, 191, - 192, 193, 194, 195, -1, 197, 198, 199, 200, 201, - 202, -1, 204, 205, -1, 207, 208, 209, 210, 211, - 212, 213, -1, 215, -1, 217, 218, 219, 220, 221, - 222, 223, 224, 225, 226, 227, -1, -1, 230, 231, - 232, 233, -1, 235, 236, 237, -1, -1, 240, 241, - 242, 243, 244, -1, 246, 247, 248, 249, 250, 251, - 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, - 262, 263, 264, 265, 266, 267, 268, 269, -1, -1, - 272, 273, 274, 275, -1, -1, 278, 279, 280, 281, - 282, -1, 284, 285, -1, -1, 288, 289, 290, -1, - -1, 293, -1, 295, 296, 297, -1, 299, 300, 301, - 302, 303, 304, 305, 306, 307, 308, -1, 310, 311, - -1, 313, 314, -1, 316, 317, 318, -1, 320, 321, - 322, 323, 324, 325, -1, 327, 328, 329, 330, 331, - 332, 333, 334, -1, 336, 337, 338, 339, 340, 341, - 342, 343, 344, 345, 346, 347, 348, -1, 350, 351, - 352, 353, 354, 355, -1, 357, 358, 359, 360, 361, - 362, 363, 364, 365, 366, 367, -1, 369, 370, 371, - 372, 373, -1, 375, -1, 377, 378, 379, 380, 381, - 382, 383, 384, -1, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 397, -1, 399, -1, 401, - -1, 403, 404, -1, 406, 407, 408, 409, 410, 411, - 412, -1, 414, 415, -1, -1, 418, 419, -1, 421, - -1, -1, 424, 425, 426, 427, 428, 429, 430, 431, - -1, -1, 434, 435, 436, 437, 438, -1, -1, 441, - 442, 443, 444, 445, -1, 447, -1, 449, 450, 451, - 452, 453, 454, 455, -1, -1, 458, -1, -1, 461, - 462, 463, 464, 465, 466, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 478, 479, 480, 481 + 266, 267, 268, 269, 270, -1, -1, 273, 274, 275, + 276, -1, -1, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, -1, + 296, 297, 298, -1, 300, 301, 302, 303, 304, 305, + 306, 307, 308, 309, -1, 311, 312, -1, 314, 315, + -1, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, 329, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, 353, 354, 355, + 356, -1, 358, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, 375, + 376, -1, 378, 379, 380, 381, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, -1, 402, -1, 404, 405, + -1, 407, 408, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, -1, 422, -1, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, 440, -1, 442, 443, 444, 445, + 446, -1, 448, -1, 450, 451, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 3, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 479, 480, 481, 482, -1, -1, -1, + 21, 22, 23, 24, 25, 26, 27, 28, -1, 30, + 31, 32, -1, -1, -1, -1, -1, -1, -1, 40, + 41, -1, 43, 44, 45, 46, 47, 48, 49, -1, + 51, 52, 53, 54, -1, 56, 57, 58, 59, 60, + 61, -1, -1, 64, 65, 66, 67, 68, -1, 70, + 71, 72, 73, -1, -1, 76, -1, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, -1, 89, 90, + 91, 92, 93, 94, -1, 96, 97, 98, 99, 100, + 101, 102, 103, -1, -1, 106, 107, 108, 109, 110, + 111, 112, 113, 114, 115, 116, -1, 118, -1, 120, + 121, 122, 123, 124, 125, -1, 127, 128, 129, 130, + 131, -1, -1, 134, 135, 136, 137, 138, -1, 140, + 141, 142, -1, 144, 145, 146, -1, 148, 149, 150, + 151, -1, 153, 154, 155, 156, 157, -1, -1, 160, + -1, 162, 163, 164, 165, -1, 167, -1, 169, 170, + -1, 172, 173, 174, -1, 176, 177, -1, 179, -1, + -1, -1, 183, -1, 185, 186, 187, 188, 189, 190, + 191, 192, 193, 194, 195, 196, -1, 198, 199, 200, + 201, 202, 203, -1, 205, 206, -1, 208, 209, 210, + 211, 212, 213, 214, -1, 216, -1, 218, 219, 220, + 221, 222, 223, 224, 225, 226, 227, 228, -1, -1, + 231, 232, 233, 234, -1, 236, 237, 238, -1, -1, + 241, 242, 243, 244, 245, -1, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + -1, -1, 273, 274, 275, 276, -1, -1, 279, 280, + 281, 282, 283, -1, 285, 286, -1, -1, 289, 290, + 291, -1, -1, 294, -1, 296, 297, 298, -1, 300, + 301, 302, 303, 304, 305, 306, 307, 308, 309, -1, + 311, 312, -1, 314, 315, -1, 317, 318, 319, -1, + 321, 322, 323, 324, 325, 326, -1, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, 338, 339, 340, + 341, 342, 343, 344, 345, 346, 347, 348, 349, -1, + 351, 352, 353, 354, 355, 356, -1, 358, 359, 360, + 361, 362, 363, 364, 365, 366, 367, 368, -1, 370, + 371, 372, 373, 374, 375, 376, -1, 378, 379, 380, + 381, 382, 383, 384, 385, -1, 387, 388, 389, 390, + 391, 392, 393, 394, 395, 396, 397, 398, -1, 400, + -1, 402, -1, 404, 405, -1, 407, 408, 409, 410, + 411, 412, 413, -1, 415, 416, -1, -1, 419, 420, + -1, 422, -1, -1, 425, 426, 427, 428, 429, 430, + 431, 432, -1, -1, 435, 436, 437, 438, 439, 440, + -1, 442, 443, 444, 445, 446, -1, 448, -1, 450, + 451, 452, 453, 454, 455, 456, -1, -1, 459, -1, + -1, 462, 463, 464, 465, 466, 467, 3, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 479, 480, + 481, 482, -1, -1, -1, 21, 22, 23, 24, 25, + 26, 27, 28, -1, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, 40, 41, -1, 43, 44, 45, + -1, 47, 48, 49, 50, 51, -1, 53, 54, -1, + 56, 57, 58, 59, 60, 61, -1, -1, 64, 65, + 66, 67, 68, -1, 70, 71, 72, 73, 74, -1, + -1, -1, 78, 79, 80, 81, 82, 83, -1, 85, + 86, 87, -1, 89, 90, 91, 92, 93, 94, -1, + -1, 97, 98, 99, -1, -1, -1, -1, -1, -1, + -1, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, -1, 118, -1, 120, 121, 122, 123, 124, 125, + -1, 127, 128, 129, 130, 131, -1, -1, 134, 135, + 136, 137, 138, -1, 140, 141, 142, -1, 144, 145, + 146, -1, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, -1, 160, -1, 162, 163, 164, 165, + -1, 167, -1, 169, -1, -1, -1, 173, 174, 175, + -1, 177, -1, 179, -1, 181, 182, 183, -1, 185, + 186, 187, 188, 189, 190, 191, -1, 193, 194, 195, + 196, -1, 198, 199, 200, 201, 202, 203, -1, 205, + -1, 207, 208, 209, 210, 211, 212, 213, 214, -1, + 216, -1, 218, -1, -1, 221, -1, 223, 224, 225, + 226, 227, 228, -1, -1, 231, -1, 233, -1, -1, + 236, 237, 238, -1, -1, 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, + 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, + -1, 267, 268, 269, 270, 271, -1, 273, 274, -1, + 276, -1, 278, 279, 280, 281, 282, 283, -1, 285, + 286, -1, -1, 289, 290, 291, -1, -1, 294, 295, + -1, 297, -1, 299, 300, 301, 302, 303, 304, 305, + -1, 307, 308, 309, -1, 311, 312, 313, 314, 315, + 316, 317, 318, 319, -1, 321, 322, 323, 324, 325, + 326, -1, 328, -1, 330, 331, 332, 333, 334, 335, + -1, 337, 338, 339, 340, 341, 342, 343, 344, 345, + 346, 347, 348, 349, -1, 351, 352, -1, 354, 355, + 356, 357, -1, 359, 360, 361, 362, 363, 364, 365, + 366, 367, 368, -1, 370, 371, 372, 373, 374, -1, + 376, 377, 378, 379, 380, -1, 382, 383, 384, 385, + -1, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 402, -1, 404, 405, + -1, 407, -1, 409, 410, 411, 412, 413, -1, 415, + 416, -1, -1, 419, 420, 421, 422, 423, -1, 425, + 426, 427, 428, 429, 430, 431, 432, -1, -1, 435, + 436, 437, 438, 439, -1, -1, 442, 443, 444, 445, + 446, 447, 448, -1, 450, -1, 452, 453, 454, 455, + 456, -1, -1, 459, -1, -1, 462, 463, 464, 465, + 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, + 476, 477, 478, 479, 480, 481, 482, 21, 21, -1, + -1, -1, -1, -1, -1, -1, -1, 31, 31, 33, + 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 49, 49, -1, -1, -1, + -1, -1, -1, -1, 58, 58, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 70, 70, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 81, 81, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 93, + 93, 95, 95, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 113, + 113, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 127, 127, -1, -1, -1, -1, -1, + -1, -1, -1, 137, 137, -1, -1, -1, -1, 143, + 143, -1, -1, -1, -1, -1, -1, 151, 151, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 167, 167, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 211, 211, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 237, 237, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 314, 314, -1, 317, 317, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 346, 346, -1, -1, -1, -1, -1, -1, + -1, 355, 355, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 369, 369, -1, -1, -1, + -1, -1, 376, 376, -1, -1, 380, 380, -1, -1, + -1, -1, -1, -1, -1, -1, 390, 390, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 402, 402, + -1, -1, 406, 406, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 442, 442, + -1, -1, -1, 447, 447, -1, -1, 451, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 461, 461, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 485, 485, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 499, 499 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const yytype_uint16 yystos[] = { - 0, 20, 30, 32, 33, 48, 57, 69, 80, 92, - 94, 112, 126, 136, 142, 150, 152, 153, 166, 195, - 210, 236, 313, 316, 345, 354, 368, 375, 379, 389, - 401, 405, 441, 446, 460, 484, 498, 509, 510, 511, - 512, 523, 524, 526, 530, 545, 548, 549, 551, 553, - 560, 562, 610, 617, 620, 621, 638, 639, 640, 641, - 642, 643, 694, 695, 840, 843, 846, 853, 854, 855, + 0, 21, 31, 33, 34, 49, 58, 70, 81, 93, + 95, 113, 127, 137, 143, 151, 153, 154, 167, 196, + 211, 237, 314, 317, 346, 355, 369, 376, 380, 390, + 402, 406, 442, 447, 461, 485, 499, 510, 511, 512, + 513, 524, 525, 527, 531, 546, 547, 548, 550, 552, + 559, 561, 609, 616, 619, 620, 637, 638, 639, 640, + 641, 642, 694, 695, 840, 843, 846, 853, 854, 855, 856, 857, 864, 868, 874, 876, 881, 885, 886, 889, - 890, 892, 893, 895, 418, 463, 561, 199, 361, 369, - 405, 452, 561, 3, 20, 21, 22, 23, 24, 25, - 26, 27, 29, 30, 31, 39, 40, 42, 43, 44, - 45, 46, 47, 48, 49, 50, 51, 52, 53, 55, - 56, 57, 58, 59, 60, 63, 64, 65, 66, 67, - 69, 70, 71, 72, 73, 75, 77, 78, 79, 80, - 81, 82, 83, 84, 85, 86, 88, 89, 90, 91, - 92, 93, 95, 96, 97, 98, 102, 106, 107, 108, - 109, 110, 111, 112, 113, 114, 115, 117, 119, 120, - 121, 122, 123, 124, 126, 127, 128, 129, 130, 133, - 134, 135, 136, 137, 139, 140, 141, 143, 144, 145, - 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, - 157, 159, 161, 162, 163, 164, 166, 168, 169, 171, - 172, 173, 174, 175, 176, 178, 180, 181, 182, 184, - 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, - 195, 197, 198, 199, 200, 201, 202, 204, 205, 206, - 207, 208, 209, 210, 211, 212, 213, 215, 217, 218, - 219, 220, 221, 222, 223, 224, 225, 226, 227, 230, - 231, 232, 233, 235, 236, 237, 240, 241, 242, 243, - 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, - 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, - 264, 265, 266, 267, 268, 269, 270, 272, 273, 274, - 275, 277, 278, 279, 280, 281, 282, 284, 285, 288, - 289, 290, 293, 294, 295, 296, 297, 298, 299, 300, - 301, 302, 303, 304, 305, 306, 307, 308, 310, 311, - 312, 313, 314, 315, 316, 317, 318, 320, 321, 322, - 323, 324, 325, 327, 328, 329, 330, 331, 332, 333, - 334, 336, 337, 338, 339, 340, 341, 342, 343, 344, - 345, 346, 347, 348, 350, 351, 352, 353, 354, 355, - 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, - 366, 367, 369, 370, 371, 372, 373, 375, 376, 377, - 378, 379, 380, 381, 382, 383, 384, 386, 387, 388, - 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, - 399, 400, 401, 403, 404, 406, 407, 408, 409, 410, - 411, 412, 414, 415, 418, 419, 420, 421, 422, 424, - 425, 426, 427, 428, 429, 430, 431, 434, 435, 436, - 437, 438, 441, 442, 443, 444, 445, 446, 447, 449, - 450, 451, 452, 453, 454, 455, 458, 461, 462, 463, - 464, 465, 466, 467, 468, 469, 470, 471, 472, 473, - 474, 475, 476, 477, 478, 479, 480, 481, 753, 825, - 829, 832, 898, 899, 900, 561, 51, 498, 633, 176, - 237, 291, 361, 409, 411, 427, 433, 436, 608, 852, - 3, 28, 174, 245, 316, 398, 823, 829, 898, 22, - 75, 91, 145, 155, 167, 172, 199, 244, 248, 311, - 325, 358, 361, 369, 372, 391, 405, 412, 421, 427, - 452, 611, 612, 615, 561, 823, 94, 450, 498, 526, - 620, 638, 860, 864, 881, 895, 109, 69, 210, 109, - 5, 828, 829, 875, 875, 829, 823, 28, 414, 418, - 829, 887, 888, 891, 561, 28, 131, 650, 651, 176, - 237, 361, 373, 414, 869, 870, 891, 561, 446, 638, - 643, 891, 5, 287, 707, 820, 829, 830, 171, 498, - 878, 498, 333, 644, 645, 823, 644, 639, 640, 0, - 501, 121, 209, 438, 146, 214, 292, 432, 653, 654, - 639, 641, 642, 502, 450, 858, 28, 414, 418, 638, - 891, 189, 820, 823, 189, 820, 189, 707, 189, 820, - 498, 496, 500, 804, 806, 526, 620, 638, 842, 881, - 820, 409, 411, 409, 411, 343, 189, 829, 829, 834, - 172, 244, 333, 369, 405, 452, 618, 199, 28, 823, - 250, 421, 108, 405, 405, 452, 364, 3, 45, 50, - 51, 52, 53, 65, 66, 75, 83, 95, 102, 113, - 114, 135, 163, 169, 171, 175, 189, 191, 205, 212, - 213, 215, 218, 219, 221, 231, 233, 245, 264, 265, - 266, 274, 279, 295, 297, 330, 352, 356, 376, 380, - 383, 398, 407, 414, 415, 426, 447, 450, 616, 718, - 720, 722, 724, 726, 728, 730, 731, 732, 734, 735, - 736, 738, 739, 833, 898, 901, 189, 613, 834, 189, - 821, 823, 189, 823, 498, 552, 291, 608, 860, 3, - 49, 50, 52, 53, 65, 66, 73, 113, 114, 151, - 157, 163, 174, 180, 181, 206, 212, 213, 215, 245, - 264, 266, 270, 277, 279, 294, 298, 312, 315, 330, - 356, 376, 383, 398, 400, 414, 415, 420, 422, 426, - 446, 447, 467, 468, 469, 470, 471, 472, 473, 474, - 475, 476, 477, 861, 863, 864, 866, 867, 898, 902, - 858, 828, 875, 828, 487, 498, 498, 841, 481, 220, - 500, 286, 4, 6, 7, 8, 9, 10, 36, 50, - 52, 53, 61, 62, 65, 66, 73, 75, 99, 100, - 101, 102, 103, 104, 105, 113, 114, 116, 151, 157, - 158, 163, 180, 181, 212, 213, 215, 238, 239, 264, - 266, 271, 276, 277, 279, 288, 298, 312, 330, 356, - 374, 383, 400, 414, 415, 420, 422, 423, 426, 439, - 447, 482, 489, 490, 491, 496, 498, 503, 505, 506, - 639, 684, 723, 726, 729, 730, 731, 733, 734, 735, - 738, 739, 750, 752, 753, 754, 756, 770, 771, 778, - 798, 803, 810, 811, 812, 825, 826, 827, 828, 829, - 809, 811, 869, 869, 828, 869, 481, 170, 416, 487, - 498, 820, 491, 806, 3, 169, 171, 450, 864, 877, - 879, 169, 880, 750, 782, 783, 829, 644, 502, 498, - 836, 499, 499, 511, 170, 216, 707, 882, 28, 131, - 649, 649, 55, 649, 160, 165, 234, 283, 659, 661, - 662, 687, 689, 690, 691, 653, 654, 498, 820, 481, - 220, 151, 24, 30, 136, 290, 341, 345, 375, 443, - 517, 520, 521, 341, 151, 37, 56, 107, 198, 249, - 257, 269, 300, 341, 347, 369, 375, 389, 520, 554, - 557, 151, 341, 375, 520, 151, 341, 375, 520, 3, - 28, 45, 51, 75, 83, 95, 102, 131, 169, 171, - 174, 175, 191, 205, 218, 219, 221, 231, 233, 245, - 265, 274, 295, 297, 352, 380, 398, 407, 426, 448, - 450, 491, 499, 750, 785, 786, 831, 837, 898, 903, - 750, 805, 3, 28, 32, 33, 34, 35, 36, 37, - 38, 41, 54, 61, 62, 68, 74, 76, 87, 94, - 99, 100, 101, 103, 104, 105, 116, 118, 125, 131, - 132, 138, 142, 146, 158, 160, 165, 167, 170, 177, - 179, 183, 196, 203, 214, 216, 228, 229, 234, 238, - 239, 271, 276, 283, 286, 287, 291, 292, 309, 319, - 326, 335, 349, 368, 374, 385, 402, 405, 413, 416, - 417, 423, 432, 433, 439, 440, 446, 448, 456, 457, - 459, 460, 824, 838, 898, 902, 904, 804, 499, 498, - 597, 608, 271, 844, 500, 835, 37, 452, 189, 820, - 189, 820, 897, 820, 820, 83, 849, 464, 84, 128, - 303, 410, 449, 737, 737, 737, 498, 725, 725, 315, - 498, 727, 151, 498, 65, 66, 737, 725, 722, 462, - 484, 498, 740, 498, 740, 59, 348, 502, 614, 498, - 36, 721, 498, 110, 111, 186, 187, 251, 252, 253, - 254, 255, 256, 259, 260, 365, 366, 478, 479, 498, - 741, 742, 743, 744, 745, 746, 747, 748, 749, 725, - 151, 502, 614, 151, 502, 614, 151, 286, 783, 343, - 405, 499, 502, 4, 158, 286, 423, 489, 490, 556, - 559, 827, 828, 859, 861, 862, 865, 860, 498, 628, - 632, 556, 865, 871, 873, 785, 720, 787, 37, 232, - 829, 498, 807, 496, 750, 802, 498, 498, 165, 498, - 498, 639, 498, 498, 498, 750, 498, 498, 498, 498, - 498, 498, 498, 498, 498, 750, 750, 750, 147, 813, - 814, 783, 784, 639, 750, 782, 772, 773, 774, 829, - 830, 9, 807, 806, 498, 828, 498, 827, 828, 3, - 8, 11, 15, 16, 17, 18, 19, 34, 37, 42, - 49, 74, 175, 191, 196, 218, 219, 233, 271, 274, - 288, 291, 380, 482, 485, 486, 487, 489, 490, 491, - 492, 493, 494, 776, 777, 778, 780, 461, 757, 807, - 297, 750, 502, 216, 646, 498, 828, 807, 500, 806, - 646, 3, 116, 237, 556, 739, 828, 872, 98, 116, - 873, 116, 873, 820, 499, 502, 858, 502, 499, 645, - 821, 37, 882, 528, 820, 37, 829, 375, 641, 641, - 28, 491, 655, 656, 750, 641, 162, 268, 675, 223, - 269, 329, 378, 438, 4, 9, 28, 670, 750, 489, - 490, 671, 672, 750, 752, 687, 688, 662, 661, 659, - 660, 165, 690, 281, 692, 659, 687, 783, 836, 232, - 820, 68, 76, 87, 167, 189, 319, 433, 579, 589, - 604, 829, 76, 87, 525, 87, 525, 498, 416, 498, - 577, 243, 436, 577, 87, 502, 416, 820, 722, 556, - 55, 558, 556, 556, 107, 249, 257, 55, 416, 460, - 484, 555, 262, 361, 555, 557, 707, 87, 416, 525, - 361, 820, 416, 361, 785, 785, 786, 499, 502, 653, - 654, 13, 14, 497, 507, 416, 596, 601, 829, 460, - 631, 333, 405, 452, 151, 94, 549, 562, 845, 846, - 893, 824, 500, 135, 143, 723, 820, 271, 550, 554, - 271, 498, 597, 37, 597, 498, 619, 189, 591, 829, - 850, 498, 783, 827, 616, 787, 737, 737, 36, 721, - 414, 414, 827, 827, 720, 717, 829, 496, 496, 827, - 827, 416, 416, 416, 416, 613, 834, 821, 823, 823, - 834, 499, 608, 189, 820, 897, 860, 866, 4, 827, - 4, 827, 630, 637, 838, 51, 96, 122, 140, 144, - 166, 169, 184, 276, 284, 327, 634, 502, 499, 502, - 499, 502, 842, 783, 804, 784, 456, 799, 800, 750, - 783, 498, 827, 827, 3, 741, 742, 743, 744, 745, - 746, 747, 748, 788, 789, 828, 827, 827, 750, 8, - 16, 17, 18, 19, 485, 486, 487, 489, 490, 491, - 492, 493, 494, 776, 781, 829, 750, 790, 489, 490, - 498, 751, 752, 778, 792, 499, 783, 750, 782, 793, - 750, 54, 170, 229, 417, 750, 783, 796, 750, 498, - 829, 343, 818, 497, 499, 502, 502, 504, 507, 783, - 750, 749, 749, 720, 750, 750, 750, 750, 750, 750, - 5, 838, 839, 414, 41, 402, 808, 834, 750, 750, - 498, 639, 797, 131, 158, 271, 276, 281, 423, 434, - 750, 276, 498, 750, 416, 49, 175, 191, 196, 233, - 380, 750, 750, 750, 750, 750, 750, 750, 750, 750, - 750, 28, 35, 385, 775, 179, 161, 758, 356, 498, - 771, 812, 176, 237, 405, 409, 411, 436, 647, 820, - 170, 696, 785, 491, 696, 498, 828, 499, 820, 877, - 820, 885, 750, 499, 498, 440, 884, 116, 299, 498, - 527, 638, 37, 829, 498, 532, 541, 542, 544, 829, - 38, 125, 657, 657, 502, 440, 657, 356, 357, 489, - 490, 672, 674, 752, 378, 223, 287, 308, 308, 502, - 493, 4, 673, 827, 673, 356, 357, 674, 819, 820, - 275, 382, 693, 688, 660, 499, 341, 520, 498, 189, - 589, 823, 223, 271, 223, 440, 498, 582, 719, 720, - 823, 829, 189, 823, 189, 829, 24, 136, 375, 516, - 519, 573, 587, 838, 823, 581, 600, 838, 823, 517, - 823, 341, 375, 520, 554, 556, 834, 823, 556, 834, - 823, 556, 341, 375, 520, 823, 823, 823, 823, 341, - 375, 520, 823, 823, 653, 653, 653, 448, 786, 190, - 346, 652, 750, 750, 750, 805, 324, 627, 499, 502, - 284, 170, 416, 622, 452, 820, 897, 820, 829, 291, - 608, 824, 498, 498, 151, 151, 233, 579, 589, 592, - 595, 605, 607, 829, 460, 462, 584, 150, 638, 460, - 851, 499, 785, 37, 271, 286, 783, 499, 499, 614, - 499, 496, 481, 481, 499, 499, 499, 502, 720, 827, - 497, 827, 499, 499, 742, 744, 745, 746, 745, 746, - 746, 614, 614, 286, 614, 405, 271, 37, 499, 502, - 491, 498, 556, 629, 865, 37, 626, 828, 626, 271, - 276, 327, 626, 626, 871, 720, 499, 497, 750, 138, - 800, 801, 37, 499, 750, 499, 499, 499, 170, 499, - 499, 502, 499, 500, 309, 791, 499, 751, 751, 750, - 11, 16, 17, 18, 19, 196, 218, 288, 485, 486, - 487, 489, 490, 491, 492, 493, 494, 778, 751, 499, - 499, 165, 170, 794, 795, 502, 499, 37, 796, 783, - 796, 796, 170, 499, 37, 821, 822, 498, 750, 815, - 807, 750, 772, 750, 499, 499, 481, 751, 751, 144, - 783, 170, 131, 158, 276, 281, 423, 434, 498, 144, - 781, 750, 402, 808, 750, 797, 750, 416, 498, 639, - 498, 498, 154, 759, 409, 411, 409, 411, 820, 405, - 648, 648, 648, 228, 357, 498, 639, 697, 698, 699, - 700, 707, 708, 753, 755, 756, 829, 457, 713, 653, - 814, 713, 827, 749, 836, 842, 698, 457, 883, 446, - 404, 439, 536, 531, 540, 829, 286, 533, 829, 537, - 544, 502, 696, 487, 807, 483, 658, 658, 656, 288, - 776, 779, 658, 4, 827, 674, 287, 438, 671, 502, - 242, 416, 750, 271, 604, 498, 151, 498, 582, 199, - 601, 602, 563, 37, 174, 572, 598, 563, 24, 136, - 345, 347, 375, 513, 514, 515, 521, 522, 151, 614, - 151, 614, 573, 587, 573, 499, 502, 566, 828, 499, - 502, 487, 500, 416, 361, 87, 416, 525, 361, 416, - 416, 416, 361, 652, 652, 652, 786, 278, 278, 499, - 497, 392, 393, 636, 828, 596, 627, 820, 498, 37, - 597, 844, 343, 405, 546, 547, 828, 601, 820, 820, - 897, 820, 499, 502, 284, 577, 284, 286, 576, 823, - 460, 896, 577, 37, 499, 405, 750, 151, 820, 499, - 721, 827, 740, 740, 721, 829, 497, 497, 834, 151, - 630, 624, 635, 865, 828, 828, 276, 601, 491, 601, - 828, 828, 413, 750, 142, 720, 499, 750, 750, 781, - 750, 794, 720, 751, 751, 751, 751, 751, 131, 271, - 281, 751, 751, 751, 751, 751, 751, 751, 751, 751, - 751, 750, 750, 795, 794, 720, 499, 499, 499, 783, - 720, 502, 499, 750, 815, 816, 817, 37, 499, 749, - 750, 34, 34, 750, 499, 750, 170, 498, 787, 750, - 499, 144, 751, 751, 144, 144, 750, 750, 654, 457, - 296, 763, 648, 648, 648, 648, 820, 820, 820, 639, - 708, 170, 639, 699, 700, 37, 701, 702, 829, 502, - 95, 171, 205, 221, 231, 265, 352, 704, 702, 37, - 701, 703, 829, 484, 712, 806, 750, 179, 676, 652, - 818, 676, 499, 499, 750, 349, 535, 445, 499, 502, - 807, 85, 535, 499, 502, 532, 883, 750, 162, 227, - 498, 658, 287, 820, 823, 499, 151, 602, 589, 602, - 563, 591, 502, 499, 118, 203, 269, 271, 588, 498, - 31, 55, 609, 598, 68, 74, 87, 116, 118, 203, - 271, 276, 319, 335, 433, 440, 568, 569, 583, 174, - 116, 188, 271, 577, 555, 108, 116, 174, 271, 391, - 394, 557, 577, 375, 515, 427, 823, 829, 519, 600, - 3, 45, 51, 75, 83, 95, 102, 169, 171, 174, - 175, 191, 205, 218, 219, 221, 231, 233, 245, 265, - 270, 274, 288, 295, 297, 352, 376, 380, 398, 407, - 426, 450, 489, 490, 556, 564, 603, 720, 779, 828, - 831, 898, 904, 838, 823, 823, 823, 823, 823, 823, - 823, 823, 823, 823, 499, 499, 499, 653, 555, 636, - 498, 595, 638, 851, 608, 189, 820, 499, 502, 499, - 550, 498, 37, 586, 584, 592, 80, 552, 108, 269, - 638, 638, 591, 440, 848, 497, 720, 614, 897, 499, - 502, 601, 750, 499, 499, 795, 170, 131, 281, 498, - 499, 499, 502, 499, 829, 750, 750, 750, 787, 499, - 750, 34, 34, 750, 750, 144, 499, 499, 750, 498, - 764, 829, 820, 820, 820, 820, 702, 703, 498, 499, - 829, 830, 407, 667, 668, 498, 699, 221, 295, 705, - 699, 705, 221, 704, 705, 221, 668, 498, 829, 668, - 498, 293, 55, 183, 685, 499, 685, 828, 810, 638, - 299, 638, 531, 286, 498, 529, 487, 544, 535, 781, - 563, 589, 499, 499, 460, 594, 119, 192, 201, 118, - 442, 750, 116, 37, 498, 834, 823, 751, 119, 192, - 118, 276, 223, 820, 594, 82, 609, 189, 276, 556, - 750, 609, 276, 489, 490, 559, 829, 720, 614, 614, - 245, 398, 831, 835, 487, 416, 416, 652, 628, 440, - 623, 625, 601, 499, 896, 37, 405, 271, 498, 828, - 851, 595, 150, 638, 148, 197, 576, 121, 136, 318, - 896, 108, 460, 894, 286, 829, 847, 498, 37, 635, - 751, 170, 498, 787, 815, 499, 750, 750, 750, 499, - 765, 829, 709, 710, 755, 701, 498, 4, 9, 663, - 665, 666, 829, 822, 699, 286, 440, 706, 699, 221, - 699, 714, 715, 829, 498, 714, 829, 28, 97, 180, - 355, 491, 498, 677, 678, 679, 680, 681, 682, 683, - 750, 750, 459, 760, 828, 760, 502, 536, 87, 498, - 534, 543, 755, 829, 132, 750, 499, 335, 594, 498, - 585, 563, 499, 188, 498, 750, 271, 569, 594, 597, - 823, 37, 151, 74, 716, 835, 493, 564, 823, 823, - 499, 555, 123, 499, 584, 638, 820, 151, 37, 499, - 823, 896, 28, 79, 88, 117, 188, 200, 391, 394, - 580, 580, 357, 357, 60, 68, 237, 820, 543, 751, - 787, 499, 305, 766, 499, 502, 37, 711, 822, 308, - 493, 308, 357, 493, 498, 498, 499, 750, 498, 699, - 706, 499, 502, 720, 714, 499, 498, 377, 498, 499, - 502, 761, 762, 829, 326, 686, 686, 445, 823, 750, - 499, 502, 74, 538, 538, 272, 438, 820, 563, 590, - 593, 838, 395, 454, 570, 571, 498, 565, 750, 499, - 247, 606, 188, 834, 440, 518, 493, 427, 628, 828, - 851, 576, 894, 498, 820, 638, 584, 552, 68, 289, - 68, 848, 499, 499, 55, 653, 712, 709, 498, 499, - 829, 663, 822, 715, 716, 499, 783, 498, 783, 679, - 502, 37, 750, 440, 664, 664, 638, 499, 713, 534, - 834, 539, 834, 539, 375, 597, 499, 502, 487, 554, - 499, 269, 578, 171, 304, 381, 286, 574, 575, 599, - 565, 750, 427, 37, 498, 894, 576, 896, 289, 289, - 498, 851, 782, 328, 357, 767, 714, 499, 502, 499, - 499, 499, 678, 499, 762, 764, 359, 538, 657, 657, - 542, 606, 593, 564, 499, 571, 201, 121, 438, 286, - 599, 286, 574, 638, 543, 713, 49, 98, 429, 750, - 768, 769, 768, 499, 499, 9, 342, 669, 499, 666, - 539, 658, 658, 713, 575, 59, 269, 348, 375, 567, - 567, 894, 499, 769, 356, 164, 314, 164, 314, 499, - 498, 657, 563, 23, 116, 276, 851, 34, 9, 658, - 713, 769, 499 + 890, 892, 893, 895, 419, 464, 560, 200, 362, 370, + 406, 453, 560, 3, 21, 22, 23, 24, 25, 26, + 27, 28, 30, 31, 32, 40, 41, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 56, + 57, 58, 59, 60, 61, 64, 65, 66, 67, 68, + 70, 71, 72, 73, 74, 76, 78, 79, 80, 81, + 82, 83, 84, 85, 86, 87, 89, 90, 91, 92, + 93, 94, 96, 97, 98, 99, 100, 101, 102, 103, + 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, + 116, 118, 120, 121, 122, 123, 124, 125, 127, 128, + 129, 130, 131, 134, 135, 136, 137, 138, 140, 141, + 142, 144, 145, 146, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 160, 162, 163, 164, 165, + 167, 169, 170, 172, 173, 174, 175, 176, 177, 179, + 181, 182, 183, 185, 186, 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 198, 199, 200, 201, 202, + 203, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, 216, 218, 219, 220, 221, 222, 223, 224, 225, + 226, 227, 228, 231, 232, 233, 234, 236, 237, 238, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, + 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, + 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, + 271, 273, 274, 275, 276, 278, 279, 280, 281, 282, + 283, 285, 286, 289, 290, 291, 294, 295, 296, 297, + 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, + 308, 309, 311, 312, 313, 314, 315, 316, 317, 318, + 319, 321, 322, 323, 324, 325, 326, 328, 329, 330, + 331, 332, 333, 334, 335, 337, 338, 339, 340, 341, + 342, 343, 344, 345, 346, 347, 348, 349, 351, 352, + 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, + 363, 364, 365, 366, 367, 368, 370, 371, 372, 373, + 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, + 384, 385, 387, 388, 389, 390, 391, 392, 393, 394, + 395, 396, 397, 398, 399, 400, 401, 402, 404, 405, + 407, 408, 409, 410, 411, 412, 413, 415, 416, 419, + 420, 421, 422, 423, 425, 426, 427, 428, 429, 430, + 431, 432, 435, 436, 437, 438, 439, 440, 442, 443, + 444, 445, 446, 447, 448, 450, 451, 452, 453, 454, + 455, 456, 459, 462, 463, 464, 465, 466, 467, 468, + 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, + 479, 480, 481, 482, 753, 825, 829, 832, 898, 899, + 900, 560, 52, 499, 632, 177, 238, 292, 362, 410, + 412, 428, 434, 437, 607, 852, 3, 5, 29, 175, + 246, 317, 399, 823, 829, 830, 898, 23, 76, 92, + 146, 156, 168, 173, 200, 245, 249, 312, 326, 359, + 362, 370, 373, 392, 406, 413, 422, 428, 453, 610, + 611, 614, 560, 823, 451, 499, 513, 524, 525, 527, + 546, 547, 548, 550, 552, 559, 561, 609, 616, 619, + 620, 637, 840, 843, 846, 853, 854, 860, 864, 868, + 874, 876, 881, 886, 889, 892, 893, 895, 110, 70, + 211, 110, 5, 828, 829, 875, 875, 829, 823, 29, + 415, 419, 829, 887, 888, 891, 560, 29, 132, 650, + 651, 177, 238, 362, 374, 415, 869, 870, 891, 560, + 447, 637, 642, 891, 288, 707, 820, 829, 830, 172, + 499, 878, 499, 334, 643, 644, 823, 643, 638, 639, + 0, 502, 122, 210, 439, 147, 215, 293, 433, 653, + 654, 638, 640, 641, 503, 451, 858, 29, 415, 419, + 637, 891, 190, 820, 823, 190, 820, 190, 707, 190, + 820, 499, 497, 501, 804, 806, 637, 820, 410, 412, + 410, 412, 344, 190, 829, 829, 834, 173, 245, 334, + 370, 406, 453, 617, 200, 29, 823, 251, 422, 109, + 406, 406, 453, 365, 3, 46, 51, 52, 53, 54, + 66, 67, 76, 84, 96, 100, 101, 102, 103, 106, + 114, 115, 136, 164, 170, 172, 176, 190, 192, 206, + 213, 214, 216, 219, 220, 222, 232, 234, 246, 265, + 266, 267, 275, 280, 296, 298, 331, 353, 357, 375, + 377, 381, 384, 399, 408, 415, 416, 427, 440, 448, + 451, 615, 718, 720, 722, 724, 726, 728, 730, 731, + 732, 734, 735, 736, 738, 739, 833, 898, 901, 190, + 612, 834, 190, 821, 823, 190, 823, 499, 551, 860, + 3, 46, 50, 51, 52, 53, 54, 66, 67, 74, + 76, 84, 96, 100, 101, 102, 103, 106, 114, 115, + 152, 158, 164, 170, 172, 175, 176, 181, 182, 192, + 206, 207, 213, 214, 216, 219, 220, 222, 232, 234, + 246, 265, 266, 267, 271, 275, 278, 280, 295, 296, + 298, 299, 313, 316, 331, 353, 357, 375, 377, 381, + 384, 399, 401, 408, 415, 416, 421, 423, 427, 440, + 447, 448, 451, 468, 469, 470, 471, 472, 473, 474, + 475, 476, 477, 478, 861, 863, 864, 866, 867, 898, + 902, 858, 828, 875, 828, 488, 499, 499, 841, 482, + 221, 501, 287, 4, 6, 7, 8, 9, 10, 37, + 51, 53, 54, 62, 63, 66, 67, 74, 76, 100, + 101, 102, 103, 104, 105, 106, 114, 115, 117, 152, + 158, 159, 164, 181, 182, 213, 214, 216, 239, 240, + 265, 267, 272, 277, 278, 280, 289, 299, 313, 331, + 357, 375, 384, 401, 415, 416, 421, 423, 424, 427, + 440, 448, 483, 490, 491, 492, 497, 499, 504, 506, + 507, 638, 684, 723, 726, 729, 730, 731, 733, 734, + 735, 738, 739, 750, 752, 753, 754, 756, 770, 771, + 778, 798, 803, 810, 811, 812, 825, 826, 827, 828, + 829, 809, 811, 869, 869, 828, 869, 482, 171, 417, + 488, 499, 820, 492, 806, 3, 170, 172, 451, 864, + 877, 879, 170, 880, 750, 782, 783, 829, 643, 503, + 499, 836, 500, 500, 512, 171, 217, 707, 882, 29, + 132, 648, 648, 56, 648, 161, 166, 235, 284, 659, + 661, 662, 687, 689, 690, 691, 653, 654, 499, 820, + 482, 221, 152, 25, 31, 137, 291, 342, 346, 376, + 444, 518, 521, 522, 342, 152, 38, 57, 108, 199, + 250, 258, 270, 301, 342, 348, 370, 376, 390, 521, + 553, 556, 152, 342, 376, 521, 152, 342, 376, 521, + 3, 29, 46, 52, 76, 84, 96, 100, 101, 102, + 103, 106, 132, 170, 172, 175, 176, 192, 206, 219, + 220, 222, 232, 234, 246, 266, 275, 296, 298, 353, + 375, 381, 399, 408, 427, 440, 449, 451, 492, 500, + 750, 785, 786, 831, 837, 898, 903, 750, 805, 3, + 29, 33, 34, 35, 36, 37, 38, 39, 42, 55, + 62, 63, 69, 75, 77, 88, 95, 104, 105, 117, + 119, 126, 132, 133, 139, 143, 147, 159, 161, 166, + 168, 171, 178, 180, 184, 197, 204, 215, 217, 229, + 230, 235, 239, 240, 272, 277, 284, 287, 288, 292, + 293, 310, 320, 327, 336, 350, 369, 386, 403, 406, + 414, 417, 418, 424, 433, 434, 441, 447, 449, 457, + 458, 460, 461, 824, 838, 898, 902, 904, 804, 500, + 499, 596, 607, 272, 844, 501, 835, 38, 453, 190, + 820, 190, 820, 897, 820, 820, 84, 849, 465, 85, + 129, 304, 411, 450, 737, 737, 737, 499, 725, 725, + 316, 499, 727, 152, 499, 66, 67, 737, 725, 722, + 463, 485, 499, 740, 499, 740, 60, 349, 503, 613, + 499, 37, 721, 499, 111, 112, 187, 188, 252, 253, + 254, 255, 256, 257, 260, 261, 366, 367, 479, 480, + 499, 741, 742, 743, 744, 745, 746, 747, 748, 749, + 725, 152, 503, 613, 152, 503, 613, 152, 287, 783, + 500, 503, 4, 159, 287, 424, 490, 491, 555, 558, + 827, 828, 859, 861, 862, 865, 860, 499, 627, 631, + 555, 865, 871, 873, 785, 720, 787, 38, 233, 829, + 499, 807, 497, 638, 750, 802, 499, 499, 166, 499, + 499, 638, 499, 499, 499, 750, 499, 499, 499, 499, + 499, 499, 499, 499, 499, 750, 750, 750, 148, 813, + 814, 783, 784, 638, 750, 782, 772, 773, 774, 830, + 9, 807, 806, 499, 828, 499, 827, 828, 3, 8, + 11, 15, 16, 17, 18, 19, 20, 35, 38, 43, + 50, 75, 176, 192, 197, 219, 220, 234, 272, 275, + 289, 292, 381, 483, 486, 487, 488, 490, 491, 492, + 493, 494, 495, 776, 777, 778, 780, 462, 757, 807, + 298, 750, 503, 217, 645, 499, 828, 807, 501, 806, + 645, 3, 117, 238, 555, 739, 828, 872, 99, 117, + 873, 117, 873, 820, 500, 503, 858, 503, 500, 644, + 821, 822, 38, 882, 529, 820, 38, 829, 376, 640, + 640, 29, 492, 655, 656, 750, 56, 640, 649, 163, + 269, 675, 224, 270, 330, 379, 439, 4, 9, 29, + 670, 750, 490, 491, 671, 672, 750, 752, 687, 688, + 662, 661, 659, 660, 166, 690, 282, 692, 659, 687, + 783, 836, 233, 820, 69, 77, 88, 168, 190, 320, + 434, 578, 588, 603, 829, 77, 88, 526, 88, 526, + 499, 417, 499, 576, 244, 437, 576, 88, 503, 417, + 820, 722, 555, 56, 557, 555, 555, 108, 250, 258, + 56, 417, 461, 485, 554, 263, 362, 554, 556, 707, + 88, 417, 526, 362, 820, 417, 362, 785, 785, 786, + 500, 503, 653, 654, 13, 14, 498, 508, 417, 595, + 600, 829, 461, 630, 334, 406, 453, 152, 95, 548, + 561, 845, 846, 893, 824, 501, 720, 820, 272, 549, + 553, 272, 499, 596, 38, 596, 499, 618, 190, 590, + 829, 850, 499, 784, 827, 615, 787, 737, 737, 37, + 721, 415, 415, 827, 827, 720, 717, 829, 497, 497, + 827, 827, 417, 417, 417, 417, 612, 834, 821, 823, + 823, 834, 500, 860, 866, 4, 827, 4, 827, 629, + 636, 838, 52, 97, 123, 141, 145, 167, 170, 185, + 277, 285, 328, 633, 503, 500, 503, 500, 503, 527, + 619, 637, 842, 881, 783, 804, 784, 457, 799, 800, + 750, 783, 499, 827, 827, 3, 741, 742, 743, 744, + 745, 746, 747, 748, 788, 789, 828, 827, 827, 750, + 8, 15, 18, 19, 20, 486, 487, 488, 490, 491, + 492, 493, 494, 495, 776, 781, 829, 750, 790, 490, + 491, 499, 751, 752, 778, 792, 500, 783, 750, 782, + 793, 750, 55, 171, 230, 418, 750, 783, 796, 750, + 499, 829, 344, 818, 498, 500, 503, 503, 505, 508, + 783, 750, 749, 749, 720, 750, 750, 750, 750, 750, + 750, 750, 5, 838, 839, 415, 42, 403, 808, 834, + 750, 750, 499, 638, 797, 132, 159, 272, 277, 282, + 424, 435, 750, 277, 499, 750, 417, 50, 176, 192, + 197, 234, 381, 750, 750, 750, 750, 750, 750, 750, + 750, 750, 750, 29, 36, 386, 775, 180, 162, 758, + 357, 499, 771, 812, 177, 238, 406, 410, 412, 437, + 646, 820, 171, 696, 785, 492, 696, 499, 828, 500, + 820, 877, 820, 885, 750, 503, 500, 499, 441, 884, + 117, 300, 499, 528, 637, 38, 829, 499, 533, 542, + 543, 545, 829, 39, 126, 657, 657, 503, 441, 657, + 263, 640, 357, 358, 490, 491, 672, 674, 752, 379, + 224, 288, 309, 309, 503, 494, 4, 673, 827, 673, + 357, 358, 674, 819, 820, 276, 383, 693, 688, 660, + 500, 342, 521, 499, 190, 588, 823, 224, 272, 224, + 441, 499, 581, 719, 720, 823, 829, 190, 823, 190, + 829, 25, 137, 376, 517, 520, 572, 586, 838, 823, + 580, 599, 838, 823, 518, 823, 342, 376, 521, 553, + 555, 834, 823, 555, 834, 823, 555, 342, 376, 521, + 823, 823, 823, 823, 342, 376, 521, 823, 823, 653, + 653, 653, 449, 786, 191, 347, 652, 750, 750, 750, + 805, 325, 626, 500, 503, 285, 171, 417, 621, 453, + 820, 897, 820, 829, 292, 607, 824, 499, 152, 152, + 234, 578, 588, 591, 594, 604, 606, 829, 461, 463, + 583, 151, 637, 461, 851, 500, 785, 38, 272, 287, + 783, 500, 500, 613, 500, 497, 482, 482, 500, 500, + 500, 503, 720, 827, 498, 827, 500, 500, 742, 744, + 745, 746, 745, 746, 746, 613, 613, 287, 613, 500, + 503, 492, 499, 555, 628, 865, 38, 625, 828, 625, + 272, 277, 328, 625, 625, 871, 720, 500, 498, 750, + 139, 800, 801, 38, 500, 750, 500, 500, 500, 171, + 500, 500, 503, 500, 501, 310, 791, 500, 751, 751, + 750, 11, 15, 18, 19, 20, 197, 219, 289, 486, + 487, 488, 490, 491, 492, 493, 494, 495, 778, 751, + 500, 500, 166, 171, 794, 795, 503, 500, 38, 796, + 783, 796, 796, 171, 500, 38, 822, 499, 750, 815, + 807, 750, 772, 750, 500, 500, 482, 751, 751, 145, + 783, 171, 132, 159, 277, 282, 424, 435, 499, 145, + 781, 750, 403, 808, 750, 797, 750, 417, 499, 638, + 499, 499, 155, 759, 410, 412, 410, 412, 820, 406, + 647, 647, 647, 229, 358, 499, 638, 695, 697, 698, + 699, 700, 707, 708, 753, 755, 756, 829, 458, 713, + 653, 814, 713, 827, 749, 836, 842, 698, 458, 883, + 447, 405, 440, 537, 532, 541, 829, 287, 534, 829, + 538, 545, 503, 696, 488, 807, 484, 658, 658, 656, + 289, 776, 779, 658, 4, 827, 674, 288, 439, 671, + 503, 243, 417, 750, 272, 603, 499, 152, 499, 581, + 200, 600, 601, 562, 38, 175, 571, 597, 562, 25, + 137, 346, 348, 376, 514, 515, 516, 522, 523, 152, + 613, 152, 613, 572, 586, 572, 500, 503, 565, 828, + 500, 503, 488, 501, 417, 362, 88, 417, 526, 362, + 417, 417, 417, 362, 652, 652, 652, 786, 279, 279, + 500, 498, 393, 394, 635, 828, 595, 626, 820, 499, + 38, 596, 844, 344, 406, 600, 820, 820, 897, 820, + 500, 503, 285, 576, 285, 287, 575, 823, 461, 896, + 576, 38, 500, 406, 750, 152, 820, 500, 721, 827, + 740, 740, 721, 829, 498, 498, 834, 629, 623, 634, + 865, 828, 828, 277, 600, 492, 600, 828, 828, 414, + 750, 143, 720, 500, 750, 750, 781, 750, 794, 720, + 751, 751, 751, 751, 751, 132, 272, 282, 751, 751, + 751, 751, 751, 751, 751, 751, 751, 751, 750, 750, + 795, 794, 720, 500, 500, 500, 783, 720, 500, 750, + 815, 816, 817, 38, 500, 749, 750, 35, 35, 750, + 500, 750, 171, 499, 787, 750, 500, 145, 751, 751, + 145, 145, 750, 750, 654, 458, 750, 297, 763, 647, + 647, 647, 647, 820, 820, 820, 638, 708, 171, 638, + 695, 699, 700, 38, 701, 702, 829, 701, 503, 96, + 172, 206, 222, 232, 266, 353, 704, 702, 38, 701, + 703, 829, 485, 712, 806, 750, 180, 676, 652, 818, + 676, 500, 500, 750, 350, 536, 446, 500, 503, 807, + 86, 536, 500, 503, 533, 883, 750, 163, 228, 499, + 658, 288, 820, 823, 500, 152, 601, 588, 601, 562, + 590, 503, 500, 119, 204, 270, 272, 587, 499, 32, + 56, 608, 597, 69, 75, 88, 117, 119, 204, 272, + 277, 320, 336, 434, 441, 567, 568, 582, 175, 117, + 189, 272, 576, 554, 109, 117, 175, 272, 392, 395, + 556, 576, 376, 516, 428, 823, 829, 520, 599, 3, + 46, 52, 76, 84, 96, 100, 101, 102, 103, 106, + 170, 172, 175, 176, 192, 206, 219, 220, 222, 232, + 234, 246, 266, 271, 275, 289, 296, 298, 353, 375, + 377, 381, 399, 408, 427, 440, 451, 490, 491, 555, + 563, 602, 720, 779, 828, 831, 898, 904, 838, 823, + 823, 823, 823, 823, 823, 823, 823, 823, 823, 500, + 500, 500, 653, 554, 635, 499, 594, 637, 851, 607, + 190, 820, 500, 549, 499, 38, 585, 583, 591, 81, + 551, 109, 270, 637, 637, 590, 441, 848, 498, 720, + 613, 500, 503, 600, 750, 500, 500, 795, 171, 132, + 282, 499, 500, 500, 503, 500, 829, 750, 750, 750, + 787, 500, 750, 35, 35, 750, 750, 145, 500, 500, + 750, 500, 499, 764, 829, 820, 820, 820, 820, 702, + 703, 499, 500, 830, 408, 667, 668, 499, 668, 699, + 222, 296, 705, 699, 705, 222, 704, 705, 222, 668, + 499, 830, 668, 499, 294, 56, 184, 685, 500, 685, + 828, 810, 637, 300, 637, 532, 287, 499, 530, 488, + 545, 536, 781, 562, 588, 500, 500, 461, 593, 120, + 193, 202, 119, 443, 750, 117, 38, 499, 834, 823, + 751, 120, 193, 119, 277, 224, 820, 593, 83, 608, + 190, 277, 555, 750, 608, 277, 490, 491, 558, 829, + 720, 613, 613, 246, 399, 831, 835, 488, 417, 417, + 652, 627, 441, 622, 624, 600, 500, 896, 38, 406, + 272, 499, 851, 594, 151, 637, 149, 198, 575, 122, + 137, 319, 896, 109, 461, 894, 287, 829, 847, 499, + 634, 751, 171, 499, 787, 815, 500, 750, 750, 750, + 500, 765, 829, 709, 710, 755, 701, 499, 4, 9, + 663, 665, 666, 829, 822, 699, 287, 441, 706, 699, + 222, 699, 714, 715, 830, 499, 714, 830, 29, 98, + 181, 356, 492, 499, 677, 678, 679, 680, 681, 682, + 683, 750, 750, 460, 760, 828, 760, 503, 537, 88, + 499, 535, 544, 755, 829, 133, 750, 500, 336, 593, + 499, 584, 562, 500, 189, 499, 750, 272, 568, 593, + 596, 823, 38, 152, 75, 716, 835, 494, 563, 823, + 823, 500, 554, 124, 500, 583, 637, 820, 152, 38, + 500, 823, 896, 29, 80, 89, 118, 189, 201, 392, + 395, 579, 579, 358, 358, 61, 69, 238, 820, 544, + 751, 787, 500, 306, 766, 500, 503, 38, 711, 822, + 309, 494, 309, 358, 494, 499, 499, 500, 750, 499, + 699, 706, 500, 503, 720, 714, 500, 499, 378, 499, + 500, 503, 761, 762, 829, 327, 686, 686, 446, 823, + 750, 500, 503, 75, 539, 539, 273, 439, 820, 562, + 589, 592, 838, 396, 455, 569, 570, 499, 564, 750, + 500, 248, 605, 189, 834, 441, 519, 494, 428, 627, + 828, 851, 575, 894, 499, 820, 637, 583, 551, 69, + 290, 69, 848, 500, 500, 56, 653, 712, 709, 499, + 500, 829, 663, 822, 715, 716, 500, 783, 499, 783, + 679, 503, 38, 750, 441, 664, 664, 637, 500, 713, + 535, 834, 540, 834, 540, 376, 596, 500, 503, 488, + 553, 500, 270, 577, 172, 305, 382, 287, 573, 574, + 598, 564, 750, 428, 38, 499, 894, 575, 896, 290, + 290, 499, 851, 782, 329, 358, 767, 714, 500, 503, + 500, 500, 500, 678, 500, 762, 764, 360, 539, 657, + 657, 543, 605, 592, 563, 500, 570, 202, 122, 439, + 287, 598, 287, 573, 637, 544, 713, 50, 99, 430, + 750, 768, 769, 768, 500, 500, 9, 343, 669, 500, + 666, 540, 658, 658, 713, 574, 60, 270, 349, 376, + 566, 566, 894, 500, 769, 357, 165, 315, 165, 315, + 500, 499, 657, 562, 24, 117, 277, 851, 35, 9, + 658, 713, 769, 500 }; #define yyerrok (yyerrstatus = 0) @@ -267203,16402 +285424,43205 @@ static const yytype_uint16 yystos[] = #define YYERROR goto yyerrorlab -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (&yylloc, yyscanner, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval, &yylloc, yyscanner) +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, Location, yyscanner); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, core_yyscan_t yyscanner) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, yyscanner) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + YYLTYPE const * const yylocationp; + core_yyscan_t yyscanner; +#endif +{ + if (!yyvaluep) + return; + YYUSE (yylocationp); + YYUSE (yyscanner); +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, core_yyscan_t yyscanner) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, yyscanner) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + YYLTYPE const * const yylocationp; + core_yyscan_t yyscanner; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + YY_LOCATION_PRINT (yyoutput, *yylocationp); + YYFPRINTF (yyoutput, ": "); + yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, yyscanner); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) +#else +static void +yy_stack_print (bottom, top) + yytype_int16 *bottom; + yytype_int16 *top; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; bottom <= top; ++bottom) + YYFPRINTF (stderr, " %d", *bottom); + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, core_yyscan_t yyscanner) +#else +static void +yy_reduce_print (yyvsp, yylsp, yyrule, yyscanner) + YYSTYPE *yyvsp; + YYLTYPE *yylsp; + int yyrule; + core_yyscan_t yyscanner; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + fprintf (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , &(yylsp[(yyi + 1) - (yynrhs)]) , yyscanner); + fprintf (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, yylsp, Rule, yyscanner); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, core_yyscan_t yyscanner) +#else +static void +yydestruct (yymsg, yytype, yyvaluep, yylocationp, yyscanner) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; + YYLTYPE *yylocationp; + core_yyscan_t yyscanner; +#endif +{ + YYUSE (yyvaluep); + YYUSE (yylocationp); + YYUSE (yyscanner); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + + +/* Prevent warnings from -Wmissing-prototypes. */ + +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (core_yyscan_t yyscanner); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + + +/*----------. +| yyparse. | +`----------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (core_yyscan_t yyscanner) +#else +int +yyparse (yyscanner) + core_yyscan_t yyscanner; +#endif +#endif +{ + /* The look-ahead symbol. */ +int yychar; + +/* The semantic value of the look-ahead symbol. */ +YYSTYPE yylval; + +/* Number of syntax errors so far. */ +int yynerrs; +/* Location data for the look-ahead symbol. */ +YYLTYPE yylloc; + + int yystate; + int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Look-ahead token as an internal (translated) token number. */ + int yytoken = 0; +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss = yyssa; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + YYSTYPE *yyvsp; + + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + /* The locations where the error started and ended. */ + YYLTYPE yyerror_range[2]; + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) + + YYSIZE_T yystacksize = YYINITDEPTH; + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + YYLTYPE yyloc; + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; + yylsp = yyls; +#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL + /* Initialize the default location before parsing starts. */ + yylloc.first_line = yylloc.last_line = 1; + yylloc.first_column = yylloc.last_column = 0; +#endif + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + YYLTYPE *yyls1 = yyls; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); + yyls = yyls1; + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); + YYSTACK_RELOCATE (yyls); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + yylsp = yyls + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + look-ahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to look-ahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a look-ahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + if (yyn == YYFINAL) + YYACCEPT; + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the look-ahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + *++yylsp = yylloc; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + /* Default location. */ + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 2: +#line 467 "third_party/libpg_query/grammar/grammar.y" + { + pg_yyget_extra(yyscanner)->parsetree = (yyvsp[(1) - (1)].list); + ;} + break; + + case 3: +#line 483 "third_party/libpg_query/grammar/grammar.y" + { + if ((yyvsp[(1) - (3)].list) != NIL) + { + /* update length of previous stmt */ + updateRawStmtEnd(llast_node(PGRawStmt, (yyvsp[(1) - (3)].list)), (yylsp[(2) - (3)])); + } + if ((yyvsp[(3) - (3)].node) != NULL) + (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeRawStmt((yyvsp[(3) - (3)].node), (yylsp[(2) - (3)]) + 1)); + else + (yyval.list) = (yyvsp[(1) - (3)].list); + ;} + break; + + case 4: +#line 495 "third_party/libpg_query/grammar/grammar.y" + { + if ((yyvsp[(1) - (1)].node) != NULL) + (yyval.list) = list_make1(makeRawStmt((yyvsp[(1) - (1)].node), 0)); + else + (yyval.list) = NIL; + ;} + break; + + case 39: +#line 538 "third_party/libpg_query/grammar/grammar.y" + { (yyval.node) = NULL; ;} + break; + + case 40: +#line 10 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableStmt *n = makeNode(PGAlterTableStmt); + n->relation = (yyvsp[(3) - (4)].range); + n->cmds = (yyvsp[(4) - (4)].list); + n->relkind = PG_OBJECT_TABLE; + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 41: +#line 19 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableStmt *n = makeNode(PGAlterTableStmt); + n->relation = (yyvsp[(5) - (6)].range); + n->cmds = (yyvsp[(6) - (6)].list); + n->relkind = PG_OBJECT_TABLE; + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 42: +#line 28 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableStmt *n = makeNode(PGAlterTableStmt); + n->relation = (yyvsp[(3) - (4)].range); + n->cmds = (yyvsp[(4) - (4)].list); + n->relkind = PG_OBJECT_INDEX; + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 43: +#line 37 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableStmt *n = makeNode(PGAlterTableStmt); + n->relation = (yyvsp[(5) - (6)].range); + n->cmds = (yyvsp[(6) - (6)].list); + n->relkind = PG_OBJECT_INDEX; + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 44: +#line 46 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableStmt *n = makeNode(PGAlterTableStmt); + n->relation = (yyvsp[(3) - (4)].range); + n->cmds = (yyvsp[(4) - (4)].list); + n->relkind = PG_OBJECT_SEQUENCE; + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 45: +#line 55 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableStmt *n = makeNode(PGAlterTableStmt); + n->relation = (yyvsp[(5) - (6)].range); + n->cmds = (yyvsp[(6) - (6)].list); + n->relkind = PG_OBJECT_SEQUENCE; + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 46: +#line 64 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableStmt *n = makeNode(PGAlterTableStmt); + n->relation = (yyvsp[(3) - (4)].range); + n->cmds = (yyvsp[(4) - (4)].list); + n->relkind = PG_OBJECT_VIEW; + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 47: +#line 73 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableStmt *n = makeNode(PGAlterTableStmt); + n->relation = (yyvsp[(5) - (6)].range); + n->cmds = (yyvsp[(6) - (6)].list); + n->relkind = PG_OBJECT_VIEW; + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 48: +#line 86 "third_party/libpg_query/grammar/statements/alter_table.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); ;} + break; + + case 49: +#line 88 "third_party/libpg_query/grammar/statements/alter_table.y" + { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].defelt)); ;} + break; + + case 50: +#line 93 "third_party/libpg_query/grammar/statements/alter_table.y" + { (yyval.node) = (yyvsp[(3) - (3)].node); ;} + break; + + case 51: +#line 94 "third_party/libpg_query/grammar/statements/alter_table.y" + { (yyval.node) = NULL; ;} + break; + + case 52: +#line 100 "third_party/libpg_query/grammar/statements/alter_table.y" + { + (yyval.defelt) = makeDefElem("restart", NULL, (yylsp[(1) - (1)])); + ;} + break; + + case 53: +#line 104 "third_party/libpg_query/grammar/statements/alter_table.y" + { + (yyval.defelt) = makeDefElem("restart", (PGNode *)(yyvsp[(3) - (3)].value), (yylsp[(1) - (3)])); + ;} + break; + + case 54: +#line 108 "third_party/libpg_query/grammar/statements/alter_table.y" + { + if (strcmp((yyvsp[(2) - (2)].defelt)->defname, "as") == 0 || + strcmp((yyvsp[(2) - (2)].defelt)->defname, "restart") == 0 || + strcmp((yyvsp[(2) - (2)].defelt)->defname, "owned_by") == 0) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("sequence option \"%s\" not supported here", (yyvsp[(2) - (2)].defelt)->defname), + parser_errposition((yylsp[(2) - (2)])))); + (yyval.defelt) = (yyvsp[(2) - (2)].defelt); + ;} + break; + + case 55: +#line 119 "third_party/libpg_query/grammar/statements/alter_table.y" + { + (yyval.defelt) = makeDefElem("generated", (PGNode *) makeInteger((yyvsp[(3) - (3)].ival)), (yylsp[(1) - (3)])); + ;} + break; + + case 56: +#line 127 "third_party/libpg_query/grammar/statements/alter_table.y" + { + (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); + ;} + break; + + case 57: +#line 131 "third_party/libpg_query/grammar/statements/alter_table.y" + { + (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); + ;} + break; + + case 58: +#line 140 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_AddColumn; + n->def = (yyvsp[(2) - (2)].node); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 59: +#line 149 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_AddColumn; + n->def = (yyvsp[(5) - (5)].node); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 60: +#line 158 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_AddColumn; + n->def = (yyvsp[(3) - (3)].node); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 61: +#line 167 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_AddColumn; + n->def = (yyvsp[(6) - (6)].node); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 62: +#line 176 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_ColumnDefault; + n->name = (yyvsp[(3) - (4)].str); + n->def = (yyvsp[(4) - (4)].node); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 63: +#line 185 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_DropNotNull; + n->name = (yyvsp[(3) - (6)].str); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 64: +#line 193 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_SetNotNull; + n->name = (yyvsp[(3) - (6)].str); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 65: +#line 201 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_SetStatistics; + n->name = (yyvsp[(3) - (6)].str); + n->def = (PGNode *) makeInteger((yyvsp[(6) - (6)].ival)); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 66: +#line 210 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_SetOptions; + n->name = (yyvsp[(3) - (5)].str); + n->def = (PGNode *) (yyvsp[(5) - (5)].list); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 67: +#line 219 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_ResetOptions; + n->name = (yyvsp[(3) - (5)].str); + n->def = (PGNode *) (yyvsp[(5) - (5)].list); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 68: +#line 228 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_SetStorage; + n->name = (yyvsp[(3) - (6)].str); + n->def = (PGNode *) makeString((yyvsp[(6) - (6)].str)); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 69: +#line 237 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + PGConstraint *c = makeNode(PGConstraint); + + c->contype = PG_CONSTR_IDENTITY; + c->generated_when = (yyvsp[(6) - (9)].ival); + c->options = (yyvsp[(9) - (9)].list); + c->location = (yylsp[(5) - (9)]); + + n->subtype = PG_AT_AddIdentity; + n->name = (yyvsp[(3) - (9)].str); + n->def = (PGNode *) c; + + (yyval.node) = (PGNode *)n; + ;} + break; + + case 70: +#line 254 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_SetIdentity; + n->name = (yyvsp[(3) - (4)].str); + n->def = (PGNode *) (yyvsp[(4) - (4)].list); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 71: +#line 263 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = AT_DropIdentity; + n->name = (yyvsp[(3) - (5)].str); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 72: +#line 272 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = AT_DropIdentity; + n->name = (yyvsp[(3) - (7)].str); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 73: +#line 281 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_DropColumn; + n->name = (yyvsp[(5) - (6)].str); + n->behavior = (yyvsp[(6) - (6)].dbehavior); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 74: +#line 291 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_DropColumn; + n->name = (yyvsp[(3) - (4)].str); + n->behavior = (yyvsp[(4) - (4)].dbehavior); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 75: +#line 304 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + PGColumnDef *def = makeNode(PGColumnDef); + n->subtype = PG_AT_AlterColumnType; + n->name = (yyvsp[(3) - (8)].str); + n->def = (PGNode *) def; + /* We only use these fields of the PGColumnDef node */ + def->typeName = (yyvsp[(6) - (8)].typnam); + def->collClause = (PGCollateClause *) (yyvsp[(7) - (8)].node); + def->raw_default = (yyvsp[(8) - (8)].node); + def->location = (yylsp[(3) - (8)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 76: +#line 319 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_AlterColumnGenericOptions; + n->name = (yyvsp[(3) - (4)].str); + n->def = (PGNode *) (yyvsp[(4) - (4)].list); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 77: +#line 328 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_AddConstraint; + n->def = (yyvsp[(2) - (2)].node); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 78: +#line 336 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + PGConstraint *c = makeNode(PGConstraint); + n->subtype = PG_AT_AlterConstraint; + n->def = (PGNode *) c; + c->contype = PG_CONSTR_FOREIGN; /* others not supported, yet */ + c->conname = (yyvsp[(3) - (4)].str); + processCASbits((yyvsp[(4) - (4)].ival), (yylsp[(4) - (4)]), "ALTER CONSTRAINT statement", + &c->deferrable, + &c->initdeferred, + NULL, NULL, yyscanner); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 79: +#line 351 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_ValidateConstraint; + n->name = (yyvsp[(3) - (3)].str); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 80: +#line 359 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_DropConstraint; + n->name = (yyvsp[(5) - (6)].str); + n->behavior = (yyvsp[(6) - (6)].dbehavior); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 81: +#line 369 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_DropConstraint; + n->name = (yyvsp[(3) - (4)].str); + n->behavior = (yyvsp[(4) - (4)].dbehavior); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 82: +#line 379 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_SetLogged; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 83: +#line 386 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_SetUnLogged; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 84: +#line 393 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_SetRelOptions; + n->def = (PGNode *)(yyvsp[(2) - (2)].list); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 85: +#line 401 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_ResetRelOptions; + n->def = (PGNode *)(yyvsp[(2) - (2)].list); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 86: +#line 408 "third_party/libpg_query/grammar/statements/alter_table.y" + { + PGAlterTableCmd *n = makeNode(PGAlterTableCmd); + n->subtype = PG_AT_GenericOptions; + n->def = (PGNode *)(yyvsp[(1) - (1)].list); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 87: +#line 418 "third_party/libpg_query/grammar/statements/alter_table.y" + { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + break; + + case 88: +#line 419 "third_party/libpg_query/grammar/statements/alter_table.y" + { (yyval.node) = NULL; ;} + break; + + case 89: +#line 425 "third_party/libpg_query/grammar/statements/alter_table.y" + { + (yyval.defelt) = (yyvsp[(1) - (1)].defelt); + ;} + break; + + case 90: +#line 429 "third_party/libpg_query/grammar/statements/alter_table.y" + { + (yyval.defelt) = (yyvsp[(2) - (2)].defelt); + (yyval.defelt)->defaction = PG_DEFELEM_SET; + ;} + break; + + case 91: +#line 434 "third_party/libpg_query/grammar/statements/alter_table.y" + { + (yyval.defelt) = (yyvsp[(2) - (2)].defelt); + (yyval.defelt)->defaction = PG_DEFELEM_ADD; + ;} + break; + + case 92: +#line 439 "third_party/libpg_query/grammar/statements/alter_table.y" + { + (yyval.defelt) = makeDefElemExtended(NULL, (yyvsp[(2) - (2)].str), NULL, DEFELEM_DROP, (yylsp[(2) - (2)])); + ;} + break; + + case 93: +#line 446 "third_party/libpg_query/grammar/statements/alter_table.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + break; + + case 94: +#line 447 "third_party/libpg_query/grammar/statements/alter_table.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} + break; + + case 95: +#line 452 "third_party/libpg_query/grammar/statements/alter_table.y" + { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + break; + + case 96: +#line 456 "third_party/libpg_query/grammar/statements/alter_table.y" + { (yyval.ival) = 1; ;} + break; + + case 97: +#line 457 "third_party/libpg_query/grammar/statements/alter_table.y" + { (yyval.ival) = 0; ;} + break; + + case 98: +#line 458 "third_party/libpg_query/grammar/statements/alter_table.y" + { (yyval.ival) = 0; ;} + break; + + case 99: +#line 8 "third_party/libpg_query/grammar/statements/deallocate.y" + { + PGDeallocateStmt *n = makeNode(PGDeallocateStmt); + n->name = (yyvsp[(2) - (2)].str); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 100: +#line 14 "third_party/libpg_query/grammar/statements/deallocate.y" + { + PGDeallocateStmt *n = makeNode(PGDeallocateStmt); + n->name = (yyvsp[(3) - (3)].str); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 101: +#line 20 "third_party/libpg_query/grammar/statements/deallocate.y" + { + PGDeallocateStmt *n = makeNode(PGDeallocateStmt); + n->name = NULL; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 102: +#line 26 "third_party/libpg_query/grammar/statements/deallocate.y" + { + PGDeallocateStmt *n = makeNode(PGDeallocateStmt); + n->name = NULL; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 103: +#line 7 "third_party/libpg_query/grammar/statements/rename.y" + { + PGRenameStmt *n = makeNode(PGRenameStmt); + n->renameType = PG_OBJECT_SCHEMA; + n->subname = (yyvsp[(3) - (6)].str); + n->newname = (yyvsp[(6) - (6)].str); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 104: +#line 16 "third_party/libpg_query/grammar/statements/rename.y" + { + PGRenameStmt *n = makeNode(PGRenameStmt); + n->renameType = PG_OBJECT_TABLE; + n->relation = (yyvsp[(3) - (6)].range); + n->subname = NULL; + n->newname = (yyvsp[(6) - (6)].str); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 105: +#line 26 "third_party/libpg_query/grammar/statements/rename.y" + { + PGRenameStmt *n = makeNode(PGRenameStmt); + n->renameType = PG_OBJECT_TABLE; + n->relation = (yyvsp[(5) - (8)].range); + n->subname = NULL; + n->newname = (yyvsp[(8) - (8)].str); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 106: +#line 36 "third_party/libpg_query/grammar/statements/rename.y" + { + PGRenameStmt *n = makeNode(PGRenameStmt); + n->renameType = PG_OBJECT_SEQUENCE; + n->relation = (yyvsp[(3) - (6)].range); + n->subname = NULL; + n->newname = (yyvsp[(6) - (6)].str); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 107: +#line 46 "third_party/libpg_query/grammar/statements/rename.y" + { + PGRenameStmt *n = makeNode(PGRenameStmt); + n->renameType = PG_OBJECT_SEQUENCE; + n->relation = (yyvsp[(5) - (8)].range); + n->subname = NULL; + n->newname = (yyvsp[(8) - (8)].str); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 108: +#line 56 "third_party/libpg_query/grammar/statements/rename.y" + { + PGRenameStmt *n = makeNode(PGRenameStmt); + n->renameType = PG_OBJECT_VIEW; + n->relation = (yyvsp[(3) - (6)].range); + n->subname = NULL; + n->newname = (yyvsp[(6) - (6)].str); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 109: +#line 66 "third_party/libpg_query/grammar/statements/rename.y" + { + PGRenameStmt *n = makeNode(PGRenameStmt); + n->renameType = PG_OBJECT_VIEW; + n->relation = (yyvsp[(5) - (8)].range); + n->subname = NULL; + n->newname = (yyvsp[(8) - (8)].str); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 110: +#line 76 "third_party/libpg_query/grammar/statements/rename.y" + { + PGRenameStmt *n = makeNode(PGRenameStmt); + n->renameType = PG_OBJECT_INDEX; + n->relation = (yyvsp[(3) - (6)].range); + n->subname = NULL; + n->newname = (yyvsp[(6) - (6)].str); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 111: +#line 86 "third_party/libpg_query/grammar/statements/rename.y" + { + PGRenameStmt *n = makeNode(PGRenameStmt); + n->renameType = PG_OBJECT_INDEX; + n->relation = (yyvsp[(5) - (8)].range); + n->subname = NULL; + n->newname = (yyvsp[(8) - (8)].str); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 112: +#line 96 "third_party/libpg_query/grammar/statements/rename.y" + { + PGRenameStmt *n = makeNode(PGRenameStmt); + n->renameType = PG_OBJECT_COLUMN; + n->relationType = PG_OBJECT_TABLE; + n->relation = (yyvsp[(3) - (8)].range); + n->subname = (yyvsp[(6) - (8)].str); + n->newname = (yyvsp[(8) - (8)].str); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 113: +#line 107 "third_party/libpg_query/grammar/statements/rename.y" + { + PGRenameStmt *n = makeNode(PGRenameStmt); + n->renameType = PG_OBJECT_COLUMN; + n->relationType = PG_OBJECT_TABLE; + n->relation = (yyvsp[(5) - (10)].range); + n->subname = (yyvsp[(8) - (10)].str); + n->newname = (yyvsp[(10) - (10)].str); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 114: +#line 118 "third_party/libpg_query/grammar/statements/rename.y" + { + PGRenameStmt *n = makeNode(PGRenameStmt); + n->renameType = PG_OBJECT_TABCONSTRAINT; + n->relation = (yyvsp[(3) - (8)].range); + n->subname = (yyvsp[(6) - (8)].str); + n->newname = (yyvsp[(8) - (8)].str); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 115: +#line 128 "third_party/libpg_query/grammar/statements/rename.y" + { + PGRenameStmt *n = makeNode(PGRenameStmt); + n->renameType = PG_OBJECT_TABCONSTRAINT; + n->relation = (yyvsp[(5) - (10)].range); + n->subname = (yyvsp[(8) - (10)].str); + n->newname = (yyvsp[(10) - (10)].str); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 116: +#line 140 "third_party/libpg_query/grammar/statements/rename.y" + { (yyval.ival) = COLUMN; ;} + break; + + case 117: +#line 141 "third_party/libpg_query/grammar/statements/rename.y" + { (yyval.ival) = 0; ;} + break; + + case 118: +#line 10 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyvsp[(5) - (7)].istmt)->relation = (yyvsp[(4) - (7)].range); + (yyvsp[(5) - (7)].istmt)->onConflictClause = (yyvsp[(6) - (7)].onconflict); + (yyvsp[(5) - (7)].istmt)->returningList = (yyvsp[(7) - (7)].list); + (yyvsp[(5) - (7)].istmt)->withClause = (yyvsp[(1) - (7)].with); + (yyval.node) = (PGNode *) (yyvsp[(5) - (7)].istmt); + ;} + break; + + case 119: +#line 22 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.istmt) = makeNode(PGInsertStmt); + (yyval.istmt)->cols = NIL; + (yyval.istmt)->selectStmt = (yyvsp[(1) - (1)].node); + ;} + break; + + case 120: +#line 28 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.istmt) = makeNode(PGInsertStmt); + (yyval.istmt)->cols = NIL; + (yyval.istmt)->override = (yyvsp[(2) - (4)].override); + (yyval.istmt)->selectStmt = (yyvsp[(4) - (4)].node); + ;} + break; + + case 121: +#line 35 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.istmt) = makeNode(PGInsertStmt); + (yyval.istmt)->cols = (yyvsp[(2) - (4)].list); + (yyval.istmt)->selectStmt = (yyvsp[(4) - (4)].node); + ;} + break; + + case 122: +#line 41 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.istmt) = makeNode(PGInsertStmt); + (yyval.istmt)->cols = (yyvsp[(2) - (7)].list); + (yyval.istmt)->override = (yyvsp[(5) - (7)].override); + (yyval.istmt)->selectStmt = (yyvsp[(7) - (7)].node); + ;} + break; + + case 123: +#line 48 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.istmt) = makeNode(PGInsertStmt); + (yyval.istmt)->cols = NIL; + (yyval.istmt)->selectStmt = NULL; + ;} + break; + + case 124: +#line 58 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.range) = (yyvsp[(1) - (1)].range); + ;} + break; + + case 125: +#line 62 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyvsp[(1) - (3)].range)->alias = makeAlias((yyvsp[(3) - (3)].str), NIL); + (yyval.range) = (yyvsp[(1) - (3)].range); + ;} + break; + + case 126: +#line 71 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.infer) = makeNode(PGInferClause); + (yyval.infer)->indexElems = (yyvsp[(2) - (4)].list); + (yyval.infer)->whereClause = (yyvsp[(4) - (4)].node); + (yyval.infer)->conname = NULL; + (yyval.infer)->location = (yylsp[(1) - (4)]); + ;} + break; + + case 127: +#line 80 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.infer) = makeNode(PGInferClause); + (yyval.infer)->indexElems = NIL; + (yyval.infer)->whereClause = NULL; + (yyval.infer)->conname = (yyvsp[(3) - (3)].str); + (yyval.infer)->location = (yylsp[(1) - (3)]); + ;} + break; + + case 128: +#line 88 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.infer) = NULL; + ;} + break; + + case 129: +#line 95 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.with) = (yyvsp[(1) - (1)].with); ;} + break; + + case 130: +#line 96 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.with) = NULL; ;} + break; + + case 131: +#line 102 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.target) = makeNode(PGResTarget); + (yyval.target)->name = (yyvsp[(1) - (2)].str); + (yyval.target)->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); + (yyval.target)->val = NULL; + (yyval.target)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 132: +#line 114 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyvsp[(1) - (3)].target)->val = (PGNode *) (yyvsp[(3) - (3)].node); + (yyval.list) = list_make1((yyvsp[(1) - (3)].target)); + ;} + break; + + case 133: +#line 119 "third_party/libpg_query/grammar/statements/insert.y" + { + int ncolumns = list_length((yyvsp[(2) - (5)].list)); + int i = 1; + PGListCell *col_cell; + + /* Create a PGMultiAssignRef source for each target */ + foreach(col_cell, (yyvsp[(2) - (5)].list)) + { + PGResTarget *res_col = (PGResTarget *) lfirst(col_cell); + PGMultiAssignRef *r = makeNode(PGMultiAssignRef); + + r->source = (PGNode *) (yyvsp[(5) - (5)].node); + r->colno = i; + r->ncolumns = ncolumns; + res_col->val = (PGNode *) r; + i++; + } + + (yyval.list) = (yyvsp[(2) - (5)].list); + ;} + break; + + case 134: +#line 144 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.onconflict) = makeNode(PGOnConflictClause); + (yyval.onconflict)->action = PG_ONCONFLICT_UPDATE; + (yyval.onconflict)->infer = (yyvsp[(3) - (8)].infer); + (yyval.onconflict)->targetList = (yyvsp[(7) - (8)].list); + (yyval.onconflict)->whereClause = (yyvsp[(8) - (8)].node); + (yyval.onconflict)->location = (yylsp[(1) - (8)]); + ;} + break; + + case 135: +#line 154 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.onconflict) = makeNode(PGOnConflictClause); + (yyval.onconflict)->action = PG_ONCONFLICT_NOTHING; + (yyval.onconflict)->infer = (yyvsp[(3) - (5)].infer); + (yyval.onconflict)->targetList = NIL; + (yyval.onconflict)->whereClause = NULL; + (yyval.onconflict)->location = (yylsp[(1) - (5)]); + ;} + break; + + case 136: +#line 163 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.onconflict) = NULL; + ;} + break; + + case 137: +#line 170 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.ielem) = makeNode(PGIndexElem); + (yyval.ielem)->name = (yyvsp[(1) - (5)].str); + (yyval.ielem)->expr = NULL; + (yyval.ielem)->indexcolname = NULL; + (yyval.ielem)->collation = (yyvsp[(2) - (5)].list); + (yyval.ielem)->opclass = (yyvsp[(3) - (5)].list); + (yyval.ielem)->ordering = (yyvsp[(4) - (5)].sortorder); + (yyval.ielem)->nulls_ordering = (yyvsp[(5) - (5)].nullorder); + ;} + break; + + case 138: +#line 181 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.ielem) = makeNode(PGIndexElem); + (yyval.ielem)->name = NULL; + (yyval.ielem)->expr = (yyvsp[(1) - (5)].node); + (yyval.ielem)->indexcolname = NULL; + (yyval.ielem)->collation = (yyvsp[(2) - (5)].list); + (yyval.ielem)->opclass = (yyvsp[(3) - (5)].list); + (yyval.ielem)->ordering = (yyvsp[(4) - (5)].sortorder); + (yyval.ielem)->nulls_ordering = (yyvsp[(5) - (5)].nullorder); + ;} + break; + + case 139: +#line 192 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.ielem) = makeNode(PGIndexElem); + (yyval.ielem)->name = NULL; + (yyval.ielem)->expr = (yyvsp[(2) - (7)].node); + (yyval.ielem)->indexcolname = NULL; + (yyval.ielem)->collation = (yyvsp[(4) - (7)].list); + (yyval.ielem)->opclass = (yyvsp[(5) - (7)].list); + (yyval.ielem)->ordering = (yyvsp[(6) - (7)].sortorder); + (yyval.ielem)->nulls_ordering = (yyvsp[(7) - (7)].nullorder); + ;} + break; + + case 140: +#line 206 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + break; + + case 141: +#line 207 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = NIL; ;} + break; + + case 142: +#line 213 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.override) = PG_OVERRIDING_USER_VALUE; ;} + break; + + case 143: +#line 214 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.override) = OVERRIDING_SYSTEM_VALUE; ;} + break; + + case 144: +#line 219 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].target)); ;} + break; + + case 145: +#line 220 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list),(yyvsp[(3) - (3)].target)); ;} + break; + + case 146: +#line 226 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + break; + + case 147: +#line 227 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = NIL; ;} + break; + + case 148: +#line 231 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 149: +#line 232 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = NIL; ;} + break; + + case 150: +#line 238 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].target)); ;} + break; + + case 151: +#line 240 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].target)); ;} + break; + + case 152: +#line 245 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 153: +#line 246 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = list_concat((yyvsp[(1) - (3)].list),(yyvsp[(3) - (3)].list)); ;} + break; + + case 154: +#line 250 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 155: +#line 251 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + break; + + case 156: +#line 254 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].ielem)); ;} + break; + + case 157: +#line 255 "third_party/libpg_query/grammar/statements/insert.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].ielem)); ;} + break; + + case 158: +#line 261 "third_party/libpg_query/grammar/statements/insert.y" + { + (yyval.target) = makeNode(PGResTarget); + (yyval.target)->name = (yyvsp[(1) - (2)].str); + (yyval.target)->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); + (yyval.target)->val = NULL; /* upper production sets this */ + (yyval.target)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 159: +#line 8 "third_party/libpg_query/grammar/statements/create_type.y" + { + PGCreateTypeStmt *n = makeNode(PGCreateTypeStmt); + n->typeName = (yyvsp[(3) - (5)].list); + auto name = std::string(reinterpret_cast((yyvsp[(5) - (5)].typnam)->names->tail->data.ptr_value)->val.str); + if (name == "enum") { + n->kind = PG_NEWTYPE_ENUM; + n->vals = (yyvsp[(5) - (5)].typnam)->typmods; + } else { + n->kind = PG_NEWTYPE_ALIAS; + n->ofType = (yyvsp[(5) - (5)].typnam); + } + (yyval.node) = (PGNode *)n; + ;} + break; + + case 160: +#line 8 "third_party/libpg_query/grammar/statements/pragma.y" + { + PGPragmaStmt *n = makeNode(PGPragmaStmt); + n->kind = PG_PRAGMA_TYPE_NOTHING; + n->name = (yyvsp[(2) - (2)].str); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 161: +#line 15 "third_party/libpg_query/grammar/statements/pragma.y" + { + PGPragmaStmt *n = makeNode(PGPragmaStmt); + n->kind = PG_PRAGMA_TYPE_ASSIGNMENT; + n->name = (yyvsp[(2) - (4)].str); + n->args = (yyvsp[(4) - (4)].list); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 162: +#line 23 "third_party/libpg_query/grammar/statements/pragma.y" + { + PGPragmaStmt *n = makeNode(PGPragmaStmt); + n->kind = PG_PRAGMA_TYPE_CALL; + n->name = (yyvsp[(2) - (5)].str); + n->args = (yyvsp[(4) - (5)].list); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 163: +#line 10 "third_party/libpg_query/grammar/statements/create_sequence.y" + { + PGCreateSeqStmt *n = makeNode(PGCreateSeqStmt); + (yyvsp[(4) - (5)].range)->relpersistence = (yyvsp[(2) - (5)].ival); + n->sequence = (yyvsp[(4) - (5)].range); + n->options = (yyvsp[(5) - (5)].list); + n->ownerId = InvalidOid; + n->onconflict = PG_ERROR_ON_CONFLICT; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 164: +#line 20 "third_party/libpg_query/grammar/statements/create_sequence.y" + { + PGCreateSeqStmt *n = makeNode(PGCreateSeqStmt); + (yyvsp[(7) - (8)].range)->relpersistence = (yyvsp[(2) - (8)].ival); + n->sequence = (yyvsp[(7) - (8)].range); + n->options = (yyvsp[(8) - (8)].list); + n->ownerId = InvalidOid; + n->onconflict = PG_IGNORE_ON_CONFLICT; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 165: +#line 32 "third_party/libpg_query/grammar/statements/create_sequence.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 166: +#line 33 "third_party/libpg_query/grammar/statements/create_sequence.y" + { (yyval.list) = NIL; ;} + break; + + case 167: +#line 8 "third_party/libpg_query/grammar/statements/execute.y" + { + PGExecuteStmt *n = makeNode(PGExecuteStmt); + n->name = (yyvsp[(2) - (3)].str); + n->params = (yyvsp[(3) - (3)].list); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 168: +#line 16 "third_party/libpg_query/grammar/statements/execute.y" + { + PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); + PGExecuteStmt *n = makeNode(PGExecuteStmt); + n->name = (yyvsp[(7) - (9)].str); + n->params = (yyvsp[(8) - (9)].list); + ctas->query = (PGNode *) n; + ctas->into = (yyvsp[(4) - (9)].into); + ctas->relkind = PG_OBJECT_TABLE; + ctas->is_select_into = false; + ctas->onconflict = PG_ERROR_ON_CONFLICT; + /* cram additional flags into the PGIntoClause */ + (yyvsp[(4) - (9)].into)->rel->relpersistence = (yyvsp[(2) - (9)].ival); + (yyvsp[(4) - (9)].into)->skipData = !((yyvsp[(9) - (9)].boolean)); + (yyval.node) = (PGNode *) ctas; + ;} + break; + + case 169: +#line 33 "third_party/libpg_query/grammar/statements/execute.y" + { + PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); + PGExecuteStmt *n = makeNode(PGExecuteStmt); + n->name = (yyvsp[(10) - (12)].str); + n->params = (yyvsp[(11) - (12)].list); + ctas->query = (PGNode *) n; + ctas->into = (yyvsp[(7) - (12)].into); + ctas->relkind = PG_OBJECT_TABLE; + ctas->is_select_into = false; + ctas->onconflict = PG_IGNORE_ON_CONFLICT; + /* cram additional flags into the PGIntoClause */ + (yyvsp[(7) - (12)].into)->rel->relpersistence = (yyvsp[(2) - (12)].ival); + (yyvsp[(7) - (12)].into)->skipData = !((yyvsp[(12) - (12)].boolean)); + (yyval.node) = (PGNode *) ctas; + ;} + break; + + case 170: +#line 51 "third_party/libpg_query/grammar/statements/execute.y" + { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + break; + + case 171: +#line 52 "third_party/libpg_query/grammar/statements/execute.y" + { (yyval.list) = NIL; ;} + break; + + case 172: +#line 10 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + PGAlterSeqStmt *n = makeNode(PGAlterSeqStmt); + n->sequence = (yyvsp[(3) - (4)].range); + n->options = (yyvsp[(4) - (4)].list); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 173: +#line 18 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + PGAlterSeqStmt *n = makeNode(PGAlterSeqStmt); + n->sequence = (yyvsp[(5) - (6)].range); + n->options = (yyvsp[(6) - (6)].list); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 174: +#line 29 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); ;} + break; + + case 175: +#line 30 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].defelt)); ;} + break; + + case 176: +#line 34 "third_party/libpg_query/grammar/statements/alter_sequence.y" + {;} + break; + + case 177: +#line 35 "third_party/libpg_query/grammar/statements/alter_sequence.y" + {;} + break; + + case 178: +#line 36 "third_party/libpg_query/grammar/statements/alter_sequence.y" + {;} + break; + + case 179: +#line 41 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { (yyval.value) = makeFloat((yyvsp[(1) - (1)].str)); ;} + break; + + case 180: +#line 42 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { (yyval.value) = makeFloat((yyvsp[(2) - (2)].str)); ;} + break; + + case 181: +#line 44 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.value) = makeFloat((yyvsp[(2) - (2)].str)); + doNegateFloat((yyval.value)); + ;} + break; + + case 182: +#line 48 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { (yyval.value) = makeInteger((yyvsp[(1) - (1)].ival)); ;} + break; + + case 183: +#line 53 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.defelt) = makeDefElem("as", (PGNode *)(yyvsp[(2) - (2)].typnam), (yylsp[(1) - (2)])); + ;} + break; + + case 184: +#line 57 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.defelt) = makeDefElem("cache", (PGNode *)(yyvsp[(2) - (2)].value), (yylsp[(1) - (2)])); + ;} + break; + + case 185: +#line 61 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.defelt) = makeDefElem("cycle", (PGNode *)makeInteger(true), (yylsp[(1) - (1)])); + ;} + break; + + case 186: +#line 65 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.defelt) = makeDefElem("cycle", (PGNode *)makeInteger(false), (yylsp[(1) - (2)])); + ;} + break; + + case 187: +#line 69 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.defelt) = makeDefElem("increment", (PGNode *)(yyvsp[(3) - (3)].value), (yylsp[(1) - (3)])); + ;} + break; + + case 188: +#line 73 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.defelt) = makeDefElem("maxvalue", (PGNode *)(yyvsp[(2) - (2)].value), (yylsp[(1) - (2)])); + ;} + break; + + case 189: +#line 77 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.defelt) = makeDefElem("minvalue", (PGNode *)(yyvsp[(2) - (2)].value), (yylsp[(1) - (2)])); + ;} + break; + + case 190: +#line 81 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.defelt) = makeDefElem("maxvalue", NULL, (yylsp[(1) - (2)])); + ;} + break; + + case 191: +#line 85 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.defelt) = makeDefElem("minvalue", NULL, (yylsp[(1) - (2)])); + ;} + break; + + case 192: +#line 89 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.defelt) = makeDefElem("owned_by", (PGNode *)(yyvsp[(3) - (3)].list), (yylsp[(1) - (3)])); + ;} + break; + + case 193: +#line 93 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + /* not documented, only used by pg_dump */ + (yyval.defelt) = makeDefElem("sequence_name", (PGNode *)(yyvsp[(3) - (3)].list), (yylsp[(1) - (3)])); + ;} + break; + + case 194: +#line 98 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.defelt) = makeDefElem("start", (PGNode *)(yyvsp[(3) - (3)].value), (yylsp[(1) - (3)])); + ;} + break; + + case 195: +#line 102 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.defelt) = makeDefElem("restart", NULL, (yylsp[(1) - (1)])); + ;} + break; + + case 196: +#line 106 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { + (yyval.defelt) = makeDefElem("restart", (PGNode *)(yyvsp[(3) - (3)].value), (yylsp[(1) - (3)])); + ;} + break; + + case 197: +#line 112 "third_party/libpg_query/grammar/statements/alter_sequence.y" + {;} + break; + + case 198: +#line 113 "third_party/libpg_query/grammar/statements/alter_sequence.y" + {;} + break; + + case 199: +#line 117 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;} + break; + + case 200: +#line 118 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { (yyval.ival) = + (yyvsp[(2) - (2)].ival); ;} + break; + + case 201: +#line 119 "third_party/libpg_query/grammar/statements/alter_sequence.y" + { (yyval.ival) = - (yyvsp[(2) - (2)].ival); ;} + break; + + case 202: +#line 3 "third_party/libpg_query/grammar/statements/transaction.y" + { + PGTransactionStmt *n = makeNode(PGTransactionStmt); + n->kind = PG_TRANS_STMT_ROLLBACK; + n->options = NIL; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 203: +#line 10 "third_party/libpg_query/grammar/statements/transaction.y" + { + PGTransactionStmt *n = makeNode(PGTransactionStmt); + n->kind = PG_TRANS_STMT_BEGIN; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 204: +#line 16 "third_party/libpg_query/grammar/statements/transaction.y" + { + PGTransactionStmt *n = makeNode(PGTransactionStmt); + n->kind = PG_TRANS_STMT_START; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 205: +#line 22 "third_party/libpg_query/grammar/statements/transaction.y" + { + PGTransactionStmt *n = makeNode(PGTransactionStmt); + n->kind = PG_TRANS_STMT_COMMIT; + n->options = NIL; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 206: +#line 29 "third_party/libpg_query/grammar/statements/transaction.y" + { + PGTransactionStmt *n = makeNode(PGTransactionStmt); + n->kind = PG_TRANS_STMT_COMMIT; + n->options = NIL; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 207: +#line 36 "third_party/libpg_query/grammar/statements/transaction.y" + { + PGTransactionStmt *n = makeNode(PGTransactionStmt); + n->kind = PG_TRANS_STMT_ROLLBACK; + n->options = NIL; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 208: +#line 45 "third_party/libpg_query/grammar/statements/transaction.y" + {;} + break; + + case 209: +#line 46 "third_party/libpg_query/grammar/statements/transaction.y" + {;} + break; + + case 210: +#line 47 "third_party/libpg_query/grammar/statements/transaction.y" + {;} + break; + + case 211: +#line 9 "third_party/libpg_query/grammar/statements/create.y" + { + PGCreateStmt *n = makeNode(PGCreateStmt); + (yyvsp[(4) - (9)].range)->relpersistence = (yyvsp[(2) - (9)].ival); + n->relation = (yyvsp[(4) - (9)].range); + n->tableElts = (yyvsp[(6) - (9)].list); + n->ofTypename = NULL; + n->constraints = NIL; + n->options = (yyvsp[(8) - (9)].list); + n->oncommit = (yyvsp[(9) - (9)].oncommit); + n->onconflict = PG_ERROR_ON_CONFLICT; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 212: +#line 24 "third_party/libpg_query/grammar/statements/create.y" + { + PGCreateStmt *n = makeNode(PGCreateStmt); + (yyvsp[(7) - (12)].range)->relpersistence = (yyvsp[(2) - (12)].ival); + n->relation = (yyvsp[(7) - (12)].range); + n->tableElts = (yyvsp[(9) - (12)].list); + n->ofTypename = NULL; + n->constraints = NIL; + n->options = (yyvsp[(11) - (12)].list); + n->oncommit = (yyvsp[(12) - (12)].oncommit); + n->onconflict = PG_IGNORE_ON_CONFLICT; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 213: +#line 39 "third_party/libpg_query/grammar/statements/create.y" + { + PGCreateStmt *n = makeNode(PGCreateStmt); + (yyvsp[(6) - (11)].range)->relpersistence = (yyvsp[(4) - (11)].ival); + n->relation = (yyvsp[(6) - (11)].range); + n->tableElts = (yyvsp[(8) - (11)].list); + n->ofTypename = NULL; + n->constraints = NIL; + n->options = (yyvsp[(10) - (11)].list); + n->oncommit = (yyvsp[(11) - (11)].oncommit); + n->onconflict = PG_REPLACE_ON_CONFLICT; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 214: +#line 56 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = 0; ;} + break; + + case 215: +#line 58 "third_party/libpg_query/grammar/statements/create.y" + { + /* + * We must complain about conflicting options. + * We could, but choose not to, complain about redundant + * options (ie, where $2's bit is already set in $1). + */ + int newspec = (yyvsp[(1) - (2)].ival) | (yyvsp[(2) - (2)].ival); + + /* special message for this case */ + if ((newspec & (CAS_NOT_DEFERRABLE | CAS_INITIALLY_DEFERRED)) == (CAS_NOT_DEFERRABLE | CAS_INITIALLY_DEFERRED)) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"), + parser_errposition((yylsp[(2) - (2)])))); + /* generic message for other conflicts */ + if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE) || + (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("conflicting constraint properties"), + parser_errposition((yylsp[(2) - (2)])))); + (yyval.ival) = newspec; + ;} + break; + + case 216: +#line 84 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.node) = (PGNode *)(yyvsp[(1) - (1)].typnam); ;} + break; + + case 217: +#line 85 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.node) = (PGNode *)makeString(pstrdup((yyvsp[(1) - (1)].keyword))); ;} + break; + + case 218: +#line 86 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.node) = (PGNode *)(yyvsp[(1) - (1)].list); ;} + break; + + case 219: +#line 87 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.node) = (PGNode *)(yyvsp[(1) - (1)].value); ;} + break; + + case 220: +#line 88 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.node) = (PGNode *)makeString((yyvsp[(1) - (1)].str)); ;} + break; + + case 221: +#line 89 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.node) = (PGNode *)makeString(pstrdup((yyvsp[(1) - (1)].keyword))); ;} + break; + + case 222: +#line 93 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + break; + + case 223: +#line 94 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = NIL; ;} + break; + + case 224: +#line 99 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); ;} + break; + + case 225: +#line 104 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_FKCONSTR_ACTION_NOACTION; ;} + break; + + case 226: +#line 105 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_FKCONSTR_ACTION_RESTRICT; ;} + break; + + case 227: +#line 106 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_FKCONSTR_ACTION_CASCADE; ;} + break; + + case 228: +#line 107 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_FKCONSTR_ACTION_SETNULL; ;} + break; + + case 229: +#line 108 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_FKCONSTR_ACTION_SETDEFAULT; ;} + break; + + case 230: +#line 114 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = castNode(PGConstraint, (yyvsp[(3) - (3)].node)); + n->conname = (yyvsp[(2) - (3)].str); + n->location = (yylsp[(1) - (3)]); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 231: +#line 120 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 232: +#line 121 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 233: +#line 123 "third_party/libpg_query/grammar/statements/create.y" + { + /* + * Note: the PGCollateClause is momentarily included in + * the list built by ColQualList, but we split it out + * again in SplitColQualList. + */ + PGCollateClause *n = makeNode(PGCollateClause); + n->arg = NULL; + n->collname = (yyvsp[(2) - (2)].list); + n->location = (yylsp[(1) - (2)]); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 234: +#line 140 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_NOTNULL; + n->location = (yylsp[(1) - (2)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 235: +#line 147 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_NULL; + n->location = (yylsp[(1) - (1)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 236: +#line 154 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_UNIQUE; + n->location = (yylsp[(1) - (2)]); + n->keys = NULL; + n->options = (yyvsp[(2) - (2)].list); + n->indexname = NULL; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 237: +#line 164 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_PRIMARY; + n->location = (yylsp[(1) - (3)]); + n->keys = NULL; + n->options = (yyvsp[(3) - (3)].list); + n->indexname = NULL; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 238: +#line 174 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_CHECK; + n->location = (yylsp[(1) - (5)]); + n->is_no_inherit = (yyvsp[(5) - (5)].boolean); + n->raw_expr = (yyvsp[(3) - (5)].node); + n->cooked_expr = NULL; + n->skip_validation = false; + n->initially_valid = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 239: +#line 186 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_COMPRESSION; + n->location = (yylsp[(1) - (3)]); + n->compression_name = (yyvsp[(3) - (3)].str); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 240: +#line 194 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_DEFAULT; + n->location = (yylsp[(1) - (2)]); + n->raw_expr = (yyvsp[(2) - (2)].node); + n->cooked_expr = NULL; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 241: +#line 203 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_FOREIGN; + n->location = (yylsp[(1) - (5)]); + n->pktable = (yyvsp[(2) - (5)].range); + n->fk_attrs = NIL; + n->pk_attrs = (yyvsp[(3) - (5)].list); + n->fk_matchtype = (yyvsp[(4) - (5)].ival); + n->fk_upd_action = (char) ((yyvsp[(5) - (5)].ival) >> 8); + n->fk_del_action = (char) ((yyvsp[(5) - (5)].ival) & 0xFF); + n->skip_validation = false; + n->initially_valid = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 242: +#line 220 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.constr) = PG_CONSTR_GENERATED_VIRTUAL; ;} + break; + + case 243: +#line 221 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.constr) = PG_CONSTR_GENERATED_STORED; ;} + break; + + case 244: +#line 225 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.constr) = (yyvsp[(1) - (1)].constr); ;} + break; + + case 245: +#line 226 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.constr) = PG_CONSTR_GENERATED_VIRTUAL; ;} + break; + + case 246: +#line 231 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_IDENTITY; + n->generated_when = (yyvsp[(2) - (5)].ival); + n->options = (yyvsp[(5) - (5)].list); + n->location = (yylsp[(1) - (5)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 247: +#line 240 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = (yyvsp[(7) - (7)].constr); + n->generated_when = (yyvsp[(2) - (7)].ival); + n->raw_expr = (yyvsp[(5) - (7)].node); + n->cooked_expr = NULL; + n->location = (yylsp[(1) - (7)]); + + /* + * Can't do this in the grammar because of shift/reduce + * conflicts. (IDENTITY allows both ALWAYS and BY + * DEFAULT, but generated columns only allow ALWAYS.) We + * can also give a more useful error message and location. + */ + if ((yyvsp[(2) - (7)].ival) != PG_ATTRIBUTE_IDENTITY_ALWAYS) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("for a generated column, GENERATED ALWAYS must be specified"), + parser_errposition((yylsp[(2) - (7)])))); + + (yyval.node) = (PGNode *)n; + ;} + break; + + case 248: +#line 263 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = (yyvsp[(5) - (5)].constr); + n->generated_when = PG_ATTRIBUTE_IDENTITY_ALWAYS; + n->raw_expr = (yyvsp[(3) - (5)].node); + n->cooked_expr = NULL; + n->location = (yylsp[(1) - (5)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 249: +#line 277 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.defelt) = makeDefElem((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); + ;} + break; + + case 250: +#line 283 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = (yyvsp[(3) - (3)].ival); ;} + break; + + case 251: +#line 289 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = ((yyvsp[(1) - (1)].ival) << 8) | (PG_FKCONSTR_ACTION_NOACTION & 0xFF); ;} + break; + + case 252: +#line 291 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = (PG_FKCONSTR_ACTION_NOACTION << 8) | ((yyvsp[(1) - (1)].ival) & 0xFF); ;} + break; + + case 253: +#line 293 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = ((yyvsp[(1) - (2)].ival) << 8) | ((yyvsp[(2) - (2)].ival) & 0xFF); ;} + break; + + case 254: +#line 295 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = ((yyvsp[(2) - (2)].ival) << 8) | ((yyvsp[(1) - (2)].ival) & 0xFF); ;} + break; + + case 255: +#line 297 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = (PG_FKCONSTR_ACTION_NOACTION << 8) | (PG_FKCONSTR_ACTION_NOACTION & 0xFF); ;} + break; + + case 256: +#line 300 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.oncommit) = ONCOMMIT_DROP; ;} + break; + + case 257: +#line 301 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.oncommit) = PG_ONCOMMIT_DELETE_ROWS; ;} + break; + + case 258: +#line 302 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.oncommit) = PG_ONCOMMIT_PRESERVE_ROWS; ;} + break; + + case 259: +#line 303 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.oncommit) = PG_ONCOMMIT_NOOP; ;} + break; + + case 260: +#line 308 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + break; + + case 261: +#line 312 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.boolean) = true; ;} + break; + + case 262: +#line 313 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.boolean) = false; ;} + break; + + case 263: +#line 319 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = castNode(PGConstraint, (yyvsp[(3) - (3)].node)); + n->conname = (yyvsp[(2) - (3)].str); + n->location = (yylsp[(1) - (3)]); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 264: +#line 325 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 265: +#line 330 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_CREATE_TABLE_LIKE_COMMENTS; ;} + break; + + case 266: +#line 331 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_CREATE_TABLE_LIKE_CONSTRAINTS; ;} + break; + + case 267: +#line 332 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_CREATE_TABLE_LIKE_DEFAULTS; ;} + break; + + case 268: +#line 333 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_CREATE_TABLE_LIKE_IDENTITY; ;} + break; + + case 269: +#line 334 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_CREATE_TABLE_LIKE_INDEXES; ;} + break; + + case 270: +#line 335 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_CREATE_TABLE_LIKE_STATISTICS; ;} + break; + + case 271: +#line 336 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_CREATE_TABLE_LIKE_STORAGE; ;} + break; + + case 272: +#line 337 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_CREATE_TABLE_LIKE_ALL; ;} + break; + + case 273: +#line 343 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); ;} + break; + + case 274: +#line 344 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); ;} + break; + + case 275: +#line 348 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.str) = (yyvsp[(3) - (3)].str); ;} + break; + + case 276: +#line 354 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_ATTR_DEFERRABLE; + n->location = (yylsp[(1) - (1)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 277: +#line 361 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_ATTR_NOT_DEFERRABLE; + n->location = (yylsp[(1) - (2)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 278: +#line 368 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_ATTR_DEFERRED; + n->location = (yylsp[(1) - (2)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 279: +#line 375 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_ATTR_IMMEDIATE; + n->location = (yylsp[(1) - (2)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 280: +#line 386 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + break; + + case 281: +#line 387 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = list_make1(makeDefElem("oids", (PGNode *) makeInteger(true), (yylsp[(1) - (2)]))); ;} + break; + + case 282: +#line 388 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = list_make1(makeDefElem("oids", (PGNode *) makeInteger(false), (yylsp[(1) - (2)]))); ;} + break; + + case 283: +#line 389 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = NIL; ;} + break; + + case 284: +#line 393 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + break; + + case 285: +#line 398 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = (yyvsp[(1) - (3)].ival) | (yyvsp[(3) - (3)].ival); ;} + break; + + case 286: +#line 399 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = (yyvsp[(1) - (3)].ival) & ~(yyvsp[(3) - (3)].ival); ;} + break; + + case 287: +#line 400 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = 0; ;} + break; + + case 288: +#line 405 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 289: +#line 410 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = CAS_NOT_DEFERRABLE; ;} + break; + + case 290: +#line 411 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = CAS_DEFERRABLE; ;} + break; + + case 291: +#line 412 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = CAS_INITIALLY_IMMEDIATE; ;} + break; + + case 292: +#line 413 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = CAS_INITIALLY_DEFERRED; ;} + break; + + case 293: +#line 414 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = CAS_NOT_VALID; ;} + break; + + case 294: +#line 415 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = CAS_NO_INHERIT; ;} + break; + + case 295: +#line 421 "third_party/libpg_query/grammar/statements/create.y" + { + PGColumnDef *n = makeNode(PGColumnDef); + n->category = COL_STANDARD; + n->colname = (yyvsp[(1) - (3)].str); + n->typeName = (yyvsp[(2) - (3)].typnam); + n->inhcount = 0; + n->is_local = true; + n->is_not_null = false; + n->is_from_type = false; + n->storage = 0; + n->raw_default = NULL; + n->cooked_default = NULL; + n->collOid = InvalidOid; + SplitColQualList((yyvsp[(3) - (3)].list), &n->constraints, &n->collClause, + yyscanner); + n->location = (yylsp[(1) - (3)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 296: +#line 441 "third_party/libpg_query/grammar/statements/create.y" + { + PGColumnDef *n = makeNode(PGColumnDef); + n->category = COL_GENERATED; + n->colname = (yyvsp[(1) - (4)].str); + n->typeName = (yyvsp[(2) - (4)].typnam); + n->inhcount = 0; + n->is_local = true; + n->is_not_null = false; + n->is_from_type = false; + n->storage = 0; + n->raw_default = NULL; + n->cooked_default = NULL; + n->collOid = InvalidOid; + // merge the constraints with the generated column constraint + auto constraints = (yyvsp[(4) - (4)].list); + if (constraints) { + constraints = lappend(constraints, (yyvsp[(3) - (4)].node)); + } else { + constraints = list_make1((yyvsp[(3) - (4)].node)); + } + SplitColQualList(constraints, &n->constraints, &n->collClause, + yyscanner); + n->location = (yylsp[(1) - (4)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 297: +#line 469 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); ;} + break; + + case 298: +#line 470 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); ;} + break; + + case 299: +#line 474 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 300: +#line 478 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 301: +#line 479 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 302: +#line 480 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 303: +#line 485 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.defelt) = makeDefElem((yyvsp[(1) - (3)].str), (PGNode *) (yyvsp[(3) - (3)].node), (yylsp[(1) - (3)])); + ;} + break; + + case 304: +#line 489 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.defelt) = makeDefElem((yyvsp[(1) - (1)].str), NULL, (yylsp[(1) - (1)])); + ;} + break; + + case 305: +#line 496 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + break; + + case 306: +#line 497 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = NIL; ;} + break; + + case 307: +#line 502 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 308: +#line 503 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + break; + + case 309: +#line 504 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = NIL; ;} + break; + + case 310: +#line 509 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); + ;} + break; + + case 311: +#line 516 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + break; + + case 312: +#line 517 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = NIL; ;} + break; + + case 313: +#line 522 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} + break; + + case 314: +#line 523 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = NIL; ;} + break; + + case 315: +#line 527 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = (yyvsp[(3) - (3)].ival); ;} + break; + + case 316: +#line 533 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.defelt) = makeDefElem((yyvsp[(1) - (3)].str), (PGNode *) (yyvsp[(3) - (3)].node), (yylsp[(1) - (3)])); + ;} + break; + + case 317: +#line 537 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.defelt) = makeDefElem((yyvsp[(1) - (1)].str), NULL, (yylsp[(1) - (1)])); + ;} + break; + + case 318: +#line 541 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.defelt) = makeDefElemExtended((yyvsp[(1) - (5)].str), (yyvsp[(3) - (5)].str), (PGNode *) (yyvsp[(5) - (5)].node), + PG_DEFELEM_UNSPEC, (yylsp[(1) - (5)])); + ;} + break; + + case 319: +#line 546 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.defelt) = makeDefElemExtended((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str), NULL, PG_DEFELEM_UNSPEC, (yylsp[(1) - (3)])); + ;} + break; + + case 320: +#line 553 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + break; + + case 321: +#line 554 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} + break; + + case 322: +#line 558 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 323: +#line 559 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + break; + + case 324: +#line 563 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + break; + + case 325: +#line 565 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.typnam) = makeTypeNameFromNameList(lcons(makeString((yyvsp[(1) - (4)].str)), (yyvsp[(2) - (4)].list))); + (yyval.typnam)->pct_type = true; + (yyval.typnam)->location = (yylsp[(1) - (4)]); + ;} + break; + + case 326: +#line 571 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.typnam) = makeTypeNameFromNameList(lcons(makeString((yyvsp[(2) - (5)].str)), (yyvsp[(3) - (5)].list))); + (yyval.typnam)->pct_type = true; + (yyval.typnam)->setof = true; + (yyval.typnam)->location = (yylsp[(2) - (5)]); + ;} + break; + + case 327: +#line 582 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_CHECK; + n->location = (yylsp[(1) - (5)]); + n->raw_expr = (yyvsp[(3) - (5)].node); + n->cooked_expr = NULL; + processCASbits((yyvsp[(5) - (5)].ival), (yylsp[(5) - (5)]), "CHECK", + NULL, NULL, &n->skip_validation, + &n->is_no_inherit, yyscanner); + n->initially_valid = !n->skip_validation; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 328: +#line 596 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_UNIQUE; + n->location = (yylsp[(1) - (6)]); + n->keys = (yyvsp[(3) - (6)].list); + n->options = (yyvsp[(5) - (6)].list); + n->indexname = NULL; + processCASbits((yyvsp[(6) - (6)].ival), (yylsp[(6) - (6)]), "UNIQUE", + &n->deferrable, &n->initdeferred, NULL, + NULL, yyscanner); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 329: +#line 609 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_UNIQUE; + n->location = (yylsp[(1) - (3)]); + n->keys = NIL; + n->options = NIL; + n->indexname = (yyvsp[(2) - (3)].str); + n->indexspace = NULL; + processCASbits((yyvsp[(3) - (3)].ival), (yylsp[(3) - (3)]), "UNIQUE", + &n->deferrable, &n->initdeferred, NULL, + NULL, yyscanner); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 330: +#line 624 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_PRIMARY; + n->location = (yylsp[(1) - (7)]); + n->keys = (yyvsp[(4) - (7)].list); + n->options = (yyvsp[(6) - (7)].list); + n->indexname = NULL; + processCASbits((yyvsp[(7) - (7)].ival), (yylsp[(7) - (7)]), "PRIMARY KEY", + &n->deferrable, &n->initdeferred, NULL, + NULL, yyscanner); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 331: +#line 637 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_PRIMARY; + n->location = (yylsp[(1) - (4)]); + n->keys = NIL; + n->options = NIL; + n->indexname = (yyvsp[(3) - (4)].str); + n->indexspace = NULL; + processCASbits((yyvsp[(4) - (4)].ival), (yylsp[(4) - (4)]), "PRIMARY KEY", + &n->deferrable, &n->initdeferred, NULL, + NULL, yyscanner); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 332: +#line 652 "third_party/libpg_query/grammar/statements/create.y" + { + PGConstraint *n = makeNode(PGConstraint); + n->contype = PG_CONSTR_FOREIGN; + n->location = (yylsp[(1) - (11)]); + n->pktable = (yyvsp[(7) - (11)].range); + n->fk_attrs = (yyvsp[(4) - (11)].list); + n->pk_attrs = (yyvsp[(8) - (11)].list); + n->fk_matchtype = (yyvsp[(9) - (11)].ival); + n->fk_upd_action = (char) ((yyvsp[(10) - (11)].ival) >> 8); + n->fk_del_action = (char) ((yyvsp[(10) - (11)].ival) & 0xFF); + processCASbits((yyvsp[(11) - (11)].ival), (yylsp[(11) - (11)]), "FOREIGN KEY", + &n->deferrable, &n->initdeferred, + &n->skip_validation, NULL, + yyscanner); + n->initially_valid = !n->skip_validation; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 333: +#line 674 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); + ;} + break; + + case 334: +#line 678 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); + ;} + break; + + case 335: +#line 685 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.ival) = PG_FKCONSTR_MATCH_FULL; + ;} + break; + + case 336: +#line 689 "third_party/libpg_query/grammar/statements/create.y" + { + ereport(ERROR, + (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("MATCH PARTIAL not yet implemented"), + parser_errposition((yylsp[(1) - (2)])))); + (yyval.ival) = PG_FKCONSTR_MATCH_PARTIAL; + ;} + break; + + case 337: +#line 697 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.ival) = PG_FKCONSTR_MATCH_SIMPLE; + ;} + break; + + case 338: +#line 701 "third_party/libpg_query/grammar/statements/create.y" + { + (yyval.ival) = PG_FKCONSTR_MATCH_SIMPLE; + ;} + break; + + case 339: +#line 709 "third_party/libpg_query/grammar/statements/create.y" + { + PGTableLikeClause *n = makeNode(PGTableLikeClause); + n->relation = (yyvsp[(2) - (3)].range); + n->options = (yyvsp[(3) - (3)].ival); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 340: +#line 718 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_RELPERSISTENCE_TEMP; ;} + break; + + case 341: +#line 719 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_RELPERSISTENCE_TEMP; ;} + break; + + case 342: +#line 720 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_RELPERSISTENCE_TEMP; ;} + break; + + case 343: +#line 721 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_RELPERSISTENCE_TEMP; ;} + break; + + case 344: +#line 723 "third_party/libpg_query/grammar/statements/create.y" + { + ereport(PGWARNING, + (errmsg("GLOBAL is deprecated in temporary table creation"), + parser_errposition((yylsp[(1) - (2)])))); + (yyval.ival) = PG_RELPERSISTENCE_TEMP; + ;} + break; + + case 345: +#line 730 "third_party/libpg_query/grammar/statements/create.y" + { + ereport(PGWARNING, + (errmsg("GLOBAL is deprecated in temporary table creation"), + parser_errposition((yylsp[(1) - (2)])))); + (yyval.ival) = PG_RELPERSISTENCE_TEMP; + ;} + break; + + case 346: +#line 736 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_RELPERSISTENCE_UNLOGGED; ;} + break; + + case 347: +#line 737 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = RELPERSISTENCE_PERMANENT; ;} + break; + + case 348: +#line 742 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = PG_ATTRIBUTE_IDENTITY_ALWAYS; ;} + break; + + case 349: +#line 743 "third_party/libpg_query/grammar/statements/create.y" + { (yyval.ival) = ATTRIBUTE_IDENTITY_BY_DEFAULT; ;} + break; + + case 350: +#line 10 "third_party/libpg_query/grammar/statements/drop.y" + { + PGDropStmt *n = makeNode(PGDropStmt); + n->removeType = (yyvsp[(2) - (6)].objtype); + n->missing_ok = true; + n->objects = (yyvsp[(5) - (6)].list); + n->behavior = (yyvsp[(6) - (6)].dbehavior); + n->concurrent = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 351: +#line 20 "third_party/libpg_query/grammar/statements/drop.y" + { + PGDropStmt *n = makeNode(PGDropStmt); + n->removeType = (yyvsp[(2) - (4)].objtype); + n->missing_ok = false; + n->objects = (yyvsp[(3) - (4)].list); + n->behavior = (yyvsp[(4) - (4)].dbehavior); + n->concurrent = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 352: +#line 30 "third_party/libpg_query/grammar/statements/drop.y" + { + PGDropStmt *n = makeNode(PGDropStmt); + n->removeType = (yyvsp[(2) - (6)].objtype); + n->missing_ok = true; + n->objects = (yyvsp[(5) - (6)].list); + n->behavior = (yyvsp[(6) - (6)].dbehavior); + n->concurrent = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 353: +#line 40 "third_party/libpg_query/grammar/statements/drop.y" + { + PGDropStmt *n = makeNode(PGDropStmt); + n->removeType = (yyvsp[(2) - (4)].objtype); + n->missing_ok = false; + n->objects = (yyvsp[(3) - (4)].list); + n->behavior = (yyvsp[(4) - (4)].dbehavior); + n->concurrent = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 354: +#line 50 "third_party/libpg_query/grammar/statements/drop.y" + { + PGDropStmt *n = makeNode(PGDropStmt); + n->removeType = (yyvsp[(2) - (6)].objtype); + n->objects = list_make1(lappend((yyvsp[(5) - (6)].list), makeString((yyvsp[(3) - (6)].str)))); + n->behavior = (yyvsp[(6) - (6)].dbehavior); + n->missing_ok = false; + n->concurrent = false; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 355: +#line 60 "third_party/libpg_query/grammar/statements/drop.y" + { + PGDropStmt *n = makeNode(PGDropStmt); + n->removeType = (yyvsp[(2) - (8)].objtype); + n->objects = list_make1(lappend((yyvsp[(7) - (8)].list), makeString((yyvsp[(5) - (8)].str)))); + n->behavior = (yyvsp[(8) - (8)].dbehavior); + n->missing_ok = true; + n->concurrent = false; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 356: +#line 70 "third_party/libpg_query/grammar/statements/drop.y" + { + PGDropStmt *n = makeNode(PGDropStmt); + n->removeType = PG_OBJECT_TYPE; + n->missing_ok = false; + n->objects = (yyvsp[(3) - (4)].list); + n->behavior = (yyvsp[(4) - (4)].dbehavior); + n->concurrent = false; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 357: +#line 80 "third_party/libpg_query/grammar/statements/drop.y" + { + PGDropStmt *n = makeNode(PGDropStmt); + n->removeType = PG_OBJECT_TYPE; + n->missing_ok = true; + n->objects = (yyvsp[(5) - (6)].list); + n->behavior = (yyvsp[(6) - (6)].dbehavior); + n->concurrent = false; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 358: +#line 93 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_TABLE; ;} + break; + + case 359: +#line 94 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_SEQUENCE; ;} + break; + + case 360: +#line 95 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_FUNCTION; ;} + break; + + case 361: +#line 96 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_FUNCTION; ;} + break; + + case 362: +#line 97 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_TABLE_MACRO; ;} + break; + + case 363: +#line 98 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_VIEW; ;} + break; + + case 364: +#line 99 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_MATVIEW; ;} + break; + + case 365: +#line 100 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_INDEX; ;} + break; + + case 366: +#line 101 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_FOREIGN_TABLE; ;} + break; + + case 367: +#line 102 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_COLLATION; ;} + break; + + case 368: +#line 103 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_CONVERSION; ;} + break; + + case 369: +#line 104 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_STATISTIC_EXT; ;} + break; + + case 370: +#line 105 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_TSPARSER; ;} + break; + + case 371: +#line 106 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_TSDICTIONARY; ;} + break; + + case 372: +#line 107 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_TSTEMPLATE; ;} + break; + + case 373: +#line 108 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_TSCONFIGURATION; ;} + break; + + case 374: +#line 113 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_ACCESS_METHOD; ;} + break; + + case 375: +#line 114 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_EVENT_TRIGGER; ;} + break; + + case 376: +#line 115 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_EXTENSION; ;} + break; + + case 377: +#line 116 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_FDW; ;} + break; + + case 378: +#line 117 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_PUBLICATION; ;} + break; + + case 379: +#line 118 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_SCHEMA; ;} + break; + + case 380: +#line 119 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_FOREIGN_SERVER; ;} + break; + + case 381: +#line 124 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].list)); ;} + break; + + case 382: +#line 125 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); ;} + break; + + case 383: +#line 130 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.dbehavior) = PG_DROP_CASCADE; ;} + break; + + case 384: +#line 131 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.dbehavior) = PG_DROP_RESTRICT; ;} + break; + + case 385: +#line 132 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.dbehavior) = PG_DROP_RESTRICT; /* default */ ;} + break; + + case 386: +#line 137 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_POLICY; ;} + break; + + case 387: +#line 138 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_RULE; ;} + break; + + case 388: +#line 139 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.objtype) = PG_OBJECT_TRIGGER; ;} + break; + + case 389: +#line 142 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].typnam)); ;} + break; + + case 390: +#line 143 "third_party/libpg_query/grammar/statements/drop.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].typnam)); ;} + break; + + case 391: +#line 9 "third_party/libpg_query/grammar/statements/create_function.y" + { + PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt); + n->relpersistence=(yyvsp[(2) - (8)].ival); + n->name = (yyvsp[(4) - (8)].range); + n->params = (yyvsp[(5) - (8)].list); + n->function = NULL; + n->query = (yyvsp[(8) - (8)].node); + (yyval.node) = (PGNode *)n; + + ;} + break; + + case 392: +#line 21 "third_party/libpg_query/grammar/statements/create_function.y" + { + PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt); + n->relpersistence=(yyvsp[(2) - (7)].ival); + n->name = (yyvsp[(4) - (7)].range); + n->params = (yyvsp[(5) - (7)].list); + n->function = (yyvsp[(7) - (7)].node); + n->query = NULL; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 395: +#line 42 "third_party/libpg_query/grammar/statements/create_function.y" + { + (yyval.list) = NIL; + ;} + break; + + case 396: +#line 46 "third_party/libpg_query/grammar/statements/create_function.y" + { + (yyval.list) = (yyvsp[(2) - (3)].list); + ;} + break; + + case 397: +#line 12 "third_party/libpg_query/grammar/statements/update.y" + { + PGUpdateStmt *n = makeNode(PGUpdateStmt); + n->relation = (yyvsp[(3) - (8)].range); + n->targetList = (yyvsp[(5) - (8)].list); + n->fromClause = (yyvsp[(6) - (8)].list); + n->whereClause = (yyvsp[(7) - (8)].node); + n->returningList = (yyvsp[(8) - (8)].list); + n->withClause = (yyvsp[(1) - (8)].with); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 398: +#line 3 "third_party/libpg_query/grammar/statements/copy.y" + { + PGCopyStmt *n = makeNode(PGCopyStmt); + n->relation = (yyvsp[(3) - (11)].range); + n->query = NULL; + n->attlist = (yyvsp[(4) - (11)].list); + n->is_from = (yyvsp[(6) - (11)].boolean); + n->is_program = (yyvsp[(7) - (11)].boolean); + n->filename = (yyvsp[(8) - (11)].str); + + if (n->is_program && n->filename == NULL) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("STDIN/STDOUT not allowed with PROGRAM"), + parser_errposition((yylsp[(8) - (11)])))); + + n->options = NIL; + /* Concatenate user-supplied flags */ + if ((yyvsp[(2) - (11)].defelt)) + n->options = lappend(n->options, (yyvsp[(2) - (11)].defelt)); + if ((yyvsp[(5) - (11)].defelt)) + n->options = lappend(n->options, (yyvsp[(5) - (11)].defelt)); + if ((yyvsp[(9) - (11)].defelt)) + n->options = lappend(n->options, (yyvsp[(9) - (11)].defelt)); + if ((yyvsp[(11) - (11)].list)) + n->options = list_concat(n->options, (yyvsp[(11) - (11)].list)); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 399: +#line 31 "third_party/libpg_query/grammar/statements/copy.y" + { + PGCopyStmt *n = makeNode(PGCopyStmt); + n->relation = NULL; + n->query = (yyvsp[(3) - (9)].node); + n->attlist = NIL; + n->is_from = false; + n->is_program = (yyvsp[(6) - (9)].boolean); + n->filename = (yyvsp[(7) - (9)].str); + n->options = (yyvsp[(9) - (9)].list); + + if (n->is_program && n->filename == NULL) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("STDIN/STDOUT not allowed with PROGRAM"), + parser_errposition((yylsp[(5) - (9)])))); + + (yyval.node) = (PGNode *)n; + ;} + break; + + case 400: +#line 53 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.boolean) = true; ;} + break; + + case 401: +#line 54 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.boolean) = false; ;} + break; + + case 402: +#line 60 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("delimiter", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(2) - (3)])); + ;} + break; + + case 403: +#line 63 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.defelt) = NULL; ;} + break; + + case 404: +#line 69 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); + ;} + break; + + case 405: +#line 73 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); + ;} + break; + + case 406: +#line 80 "third_party/libpg_query/grammar/statements/copy.y" + {;} + break; + + case 407: +#line 81 "third_party/libpg_query/grammar/statements/copy.y" + {;} + break; + + case 408: +#line 85 "third_party/libpg_query/grammar/statements/copy.y" + {;} + break; + + case 409: +#line 86 "third_party/libpg_query/grammar/statements/copy.y" + {;} + break; + + case 410: +#line 91 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.boolean) = true; ;} + break; + + case 411: +#line 92 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.boolean) = false; ;} + break; + + case 412: +#line 96 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 413: +#line 97 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + break; + + case 414: +#line 102 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); ;} + break; + + case 415: +#line 103 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.node) = (PGNode *) (yyvsp[(1) - (1)].value); ;} + break; + + case 416: +#line 104 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.node) = (PGNode *) makeNode(PGAStar); ;} + break; + + case 417: +#line 105 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.node) = (PGNode *) (yyvsp[(2) - (3)].list); ;} + break; + + case 418: +#line 106 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.node) = NULL; ;} + break; + + case 419: +#line 112 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); + ;} + break; + + case 420: +#line 120 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("oids", (PGNode *)makeInteger(true), (yylsp[(1) - (2)])); + ;} + break; + + case 421: +#line 123 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.defelt) = NULL; ;} + break; + + case 422: +#line 128 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].defelt)); ;} + break; + + case 423: +#line 129 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.list) = NIL; ;} + break; + + case 424: +#line 135 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("format", (PGNode *)makeString("binary"), (yylsp[(1) - (1)])); + ;} + break; + + case 425: +#line 138 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.defelt) = NULL; ;} + break; + + case 426: +#line 144 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("format", (PGNode *)makeString("binary"), (yylsp[(1) - (1)])); + ;} + break; + + case 427: +#line 148 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("oids", (PGNode *)makeInteger(true), (yylsp[(1) - (1)])); + ;} + break; + + case 428: +#line 152 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("freeze", (PGNode *)makeInteger(true), (yylsp[(1) - (1)])); + ;} + break; + + case 429: +#line 156 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("delimiter", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(1) - (3)])); + ;} + break; + + case 430: +#line 160 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("null", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(1) - (3)])); + ;} + break; + + case 431: +#line 164 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("format", (PGNode *)makeString("csv"), (yylsp[(1) - (1)])); + ;} + break; + + case 432: +#line 168 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("header", (PGNode *)makeInteger(true), (yylsp[(1) - (1)])); + ;} + break; + + case 433: +#line 172 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("quote", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(1) - (3)])); + ;} + break; + + case 434: +#line 176 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("escape", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(1) - (3)])); + ;} + break; + + case 435: +#line 180 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("force_quote", (PGNode *)(yyvsp[(3) - (3)].list), (yylsp[(1) - (3)])); + ;} + break; + + case 436: +#line 184 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("force_quote", (PGNode *)makeNode(PGAStar), (yylsp[(1) - (3)])); + ;} + break; + + case 437: +#line 188 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("force_not_null", (PGNode *)(yyvsp[(4) - (4)].list), (yylsp[(1) - (4)])); + ;} + break; + + case 438: +#line 192 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("force_null", (PGNode *)(yyvsp[(3) - (3)].list), (yylsp[(1) - (3)])); + ;} + break; + + case 439: +#line 196 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.defelt) = makeDefElem("encoding", (PGNode *)makeString((yyvsp[(2) - (2)].str)), (yylsp[(1) - (2)])); + ;} + break; + + case 440: +#line 203 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); ;} + break; + + case 441: +#line 209 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 442: +#line 210 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.str) = NULL; ;} + break; + + case 443: +#line 211 "third_party/libpg_query/grammar/statements/copy.y" + { (yyval.str) = NULL; ;} + break; + + case 444: +#line 217 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); + ;} + break; + + case 445: +#line 221 "third_party/libpg_query/grammar/statements/copy.y" + { + (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); + ;} + break; + + case 448: +#line 52 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(2) - (3)].node); ;} + break; + + case 449: +#line 53 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(2) - (3)].node); ;} + break; + + case 450: +#line 68 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 451: +#line 70 "third_party/libpg_query/grammar/statements/select.y" + { + insertSelectOptions((PGSelectStmt *) (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].list), NIL, + NULL, NULL, NULL, + yyscanner); + (yyval.node) = (yyvsp[(1) - (2)].node); + ;} + break; + + case 452: +#line 77 "third_party/libpg_query/grammar/statements/select.y" + { + insertSelectOptions((PGSelectStmt *) (yyvsp[(1) - (4)].node), (yyvsp[(2) - (4)].list), (yyvsp[(3) - (4)].list), + (PGNode*) list_nth((yyvsp[(4) - (4)].list), 0), (PGNode*) list_nth((yyvsp[(4) - (4)].list), 1), + NULL, + yyscanner); + (yyval.node) = (yyvsp[(1) - (4)].node); + ;} + break; + + case 453: +#line 85 "third_party/libpg_query/grammar/statements/select.y" + { + insertSelectOptions((PGSelectStmt *) (yyvsp[(1) - (4)].node), (yyvsp[(2) - (4)].list), (yyvsp[(4) - (4)].list), + (PGNode*) list_nth((yyvsp[(3) - (4)].list), 0), (PGNode*) list_nth((yyvsp[(3) - (4)].list), 1), + NULL, + yyscanner); + (yyval.node) = (yyvsp[(1) - (4)].node); + ;} + break; + + case 454: +#line 93 "third_party/libpg_query/grammar/statements/select.y" + { + insertSelectOptions((PGSelectStmt *) (yyvsp[(2) - (2)].node), NULL, NIL, + NULL, NULL, + (yyvsp[(1) - (2)].with), + yyscanner); + (yyval.node) = (yyvsp[(2) - (2)].node); + ;} + break; + + case 455: +#line 101 "third_party/libpg_query/grammar/statements/select.y" + { + insertSelectOptions((PGSelectStmt *) (yyvsp[(2) - (3)].node), (yyvsp[(3) - (3)].list), NIL, + NULL, NULL, + (yyvsp[(1) - (3)].with), + yyscanner); + (yyval.node) = (yyvsp[(2) - (3)].node); + ;} + break; + + case 456: +#line 109 "third_party/libpg_query/grammar/statements/select.y" + { + insertSelectOptions((PGSelectStmt *) (yyvsp[(2) - (5)].node), (yyvsp[(3) - (5)].list), (yyvsp[(4) - (5)].list), + (PGNode*) list_nth((yyvsp[(5) - (5)].list), 0), (PGNode*) list_nth((yyvsp[(5) - (5)].list), 1), + (yyvsp[(1) - (5)].with), + yyscanner); + (yyval.node) = (yyvsp[(2) - (5)].node); + ;} + break; + + case 457: +#line 117 "third_party/libpg_query/grammar/statements/select.y" + { + insertSelectOptions((PGSelectStmt *) (yyvsp[(2) - (5)].node), (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list), + (PGNode*) list_nth((yyvsp[(4) - (5)].list), 0), (PGNode*) list_nth((yyvsp[(4) - (5)].list), 1), + (yyvsp[(1) - (5)].with), + yyscanner); + (yyval.node) = (yyvsp[(2) - (5)].node); + ;} + break; + + case 458: +#line 127 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 459: +#line 128 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 460: +#line 158 "third_party/libpg_query/grammar/statements/select.y" + { + PGSelectStmt *n = makeNode(PGSelectStmt); + n->targetList = (yyvsp[(3) - (11)].list); + n->intoClause = (yyvsp[(4) - (11)].into); + n->fromClause = (yyvsp[(5) - (11)].list); + n->whereClause = (yyvsp[(6) - (11)].node); + n->groupClause = (yyvsp[(7) - (11)].list); + n->havingClause = (yyvsp[(8) - (11)].node); + n->windowClause = (yyvsp[(9) - (11)].list); + n->qualifyClause = (yyvsp[(10) - (11)].node); + n->sampleOptions = (yyvsp[(11) - (11)].node); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 461: +#line 174 "third_party/libpg_query/grammar/statements/select.y" + { + PGSelectStmt *n = makeNode(PGSelectStmt); + n->distinctClause = (yyvsp[(2) - (11)].list); + n->targetList = (yyvsp[(3) - (11)].list); + n->intoClause = (yyvsp[(4) - (11)].into); + n->fromClause = (yyvsp[(5) - (11)].list); + n->whereClause = (yyvsp[(6) - (11)].node); + n->groupClause = (yyvsp[(7) - (11)].list); + n->havingClause = (yyvsp[(8) - (11)].node); + n->windowClause = (yyvsp[(9) - (11)].list); + n->qualifyClause = (yyvsp[(10) - (11)].node); + n->sampleOptions = (yyvsp[(11) - (11)].node); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 462: +#line 188 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 463: +#line 190 "third_party/libpg_query/grammar/statements/select.y" + { + /* same as SELECT * FROM relation_expr */ + PGColumnRef *cr = makeNode(PGColumnRef); + PGResTarget *rt = makeNode(PGResTarget); + PGSelectStmt *n = makeNode(PGSelectStmt); + + cr->fields = list_make1(makeNode(PGAStar)); + cr->location = -1; + + rt->name = NULL; + rt->indirection = NIL; + rt->val = (PGNode *)cr; + rt->location = -1; + + n->targetList = list_make1(rt); + n->fromClause = list_make1((yyvsp[(2) - (2)].range)); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 464: +#line 209 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSetOp(PG_SETOP_UNION_BY_NAME, (yyvsp[(3) - (5)].boolean), (yyvsp[(1) - (5)].node), (yyvsp[(5) - (5)].node)); + ;} + break; + + case 465: +#line 213 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSetOp(PG_SETOP_UNION, (yyvsp[(3) - (4)].boolean), (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node)); + ;} + break; + + case 466: +#line 217 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSetOp(PG_SETOP_INTERSECT, (yyvsp[(3) - (4)].boolean), (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node)); + ;} + break; + + case 467: +#line 221 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSetOp(PG_SETOP_EXCEPT, (yyvsp[(3) - (4)].boolean), (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node)); + ;} + break; + + case 468: +#line 238 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.with) = makeNode(PGWithClause); + (yyval.with)->ctes = (yyvsp[(2) - (2)].list); + (yyval.with)->recursive = false; + (yyval.with)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 469: +#line 245 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.with) = makeNode(PGWithClause); + (yyval.with)->ctes = (yyvsp[(2) - (2)].list); + (yyval.with)->recursive = false; + (yyval.with)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 470: +#line 252 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.with) = makeNode(PGWithClause); + (yyval.with)->ctes = (yyvsp[(3) - (3)].list); + (yyval.with)->recursive = true; + (yyval.with)->location = (yylsp[(1) - (3)]); + ;} + break; + + case 471: +#line 261 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + break; + + case 472: +#line 262 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} + break; + + case 473: +#line 266 "third_party/libpg_query/grammar/statements/select.y" + { + PGCommonTableExpr *n = makeNode(PGCommonTableExpr); + n->ctename = (yyvsp[(1) - (6)].str); + n->aliascolnames = (yyvsp[(2) - (6)].list); + n->ctequery = (yyvsp[(5) - (6)].node); + n->location = (yylsp[(1) - (6)]); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 474: +#line 278 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.into) = makeNode(PGIntoClause); + (yyval.into)->rel = (yyvsp[(2) - (2)].range); + (yyval.into)->colNames = NIL; + (yyval.into)->options = NIL; + (yyval.into)->onCommit = PG_ONCOMMIT_NOOP; + (yyval.into)->viewQuery = NULL; + (yyval.into)->skipData = false; + ;} + break; + + case 475: +#line 288 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.into) = NULL; ;} + break; + + case 476: +#line 297 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.range) = (yyvsp[(3) - (3)].range); + (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; + ;} + break; + + case 477: +#line 302 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.range) = (yyvsp[(3) - (3)].range); + (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; + ;} + break; + + case 478: +#line 307 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.range) = (yyvsp[(4) - (4)].range); + (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; + ;} + break; + + case 479: +#line 312 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.range) = (yyvsp[(4) - (4)].range); + (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; + ;} + break; + + case 480: +#line 317 "third_party/libpg_query/grammar/statements/select.y" + { + ereport(PGWARNING, + (errmsg("GLOBAL is deprecated in temporary table creation"), + parser_errposition((yylsp[(1) - (4)])))); + (yyval.range) = (yyvsp[(4) - (4)].range); + (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; + ;} + break; + + case 481: +#line 325 "third_party/libpg_query/grammar/statements/select.y" + { + ereport(PGWARNING, + (errmsg("GLOBAL is deprecated in temporary table creation"), + parser_errposition((yylsp[(1) - (4)])))); + (yyval.range) = (yyvsp[(4) - (4)].range); + (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; + ;} + break; + + case 482: +#line 333 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.range) = (yyvsp[(3) - (3)].range); + (yyval.range)->relpersistence = PG_RELPERSISTENCE_UNLOGGED; + ;} + break; + + case 483: +#line 338 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.range) = (yyvsp[(2) - (2)].range); + (yyval.range)->relpersistence = RELPERSISTENCE_PERMANENT; + ;} + break; + + case 484: +#line 343 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.range) = (yyvsp[(1) - (1)].range); + (yyval.range)->relpersistence = RELPERSISTENCE_PERMANENT; + ;} + break; + + case 485: +#line 349 "third_party/libpg_query/grammar/statements/select.y" + {;} + break; + + case 486: +#line 350 "third_party/libpg_query/grammar/statements/select.y" + {;} + break; + + case 487: +#line 354 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = true; ;} + break; + + case 488: +#line 355 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = false; ;} + break; + + case 489: +#line 356 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = false; ;} + break; + + case 490: +#line 360 "third_party/libpg_query/grammar/statements/select.y" + { ;} + break; + + case 491: +#line 367 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(NIL); ;} + break; + + case 492: +#line 368 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(4) - (5)].list); ;} + break; + + case 493: +#line 372 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL;;} + break; + + case 494: +#line 373 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 495: +#line 377 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = true;;} + break; + + case 496: +#line 378 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = false;;} + break; + + case 497: +#line 379 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = false; ;} + break; + + case 498: +#line 383 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list);;} + break; + + case 499: +#line 384 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 500: +#line 388 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(3) - (3)].list); ;} + break; + + case 501: +#line 390 "third_party/libpg_query/grammar/statements/select.y" + { + PGSortBy *sort = makeNode(PGSortBy); + sort->node = (PGNode *) makeNode(PGAStar); + sort->sortby_dir = (yyvsp[(4) - (5)].sortorder); + sort->sortby_nulls = (yyvsp[(5) - (5)].nullorder); + sort->useOp = NIL; + sort->location = -1; /* no operator */ + (yyval.list) = list_make1(sort); + ;} + break; + + case 502: +#line 400 "third_party/libpg_query/grammar/statements/select.y" + { + PGSortBy *sort = makeNode(PGSortBy); + sort->node = (PGNode *) makeNode(PGAStar); + sort->sortby_dir = (yyvsp[(4) - (5)].sortorder); + sort->sortby_nulls = (yyvsp[(5) - (5)].nullorder); + sort->useOp = NIL; + sort->location = -1; /* no operator */ + (yyval.list) = list_make1(sort); + ;} + break; + + case 503: +#line 412 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].sortby)); ;} + break; + + case 504: +#line 413 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].sortby)); ;} + break; + + case 505: +#line 417 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.sortby) = makeNode(PGSortBy); + (yyval.sortby)->node = (yyvsp[(1) - (4)].node); + (yyval.sortby)->sortby_dir = SORTBY_USING; + (yyval.sortby)->sortby_nulls = (yyvsp[(4) - (4)].nullorder); + (yyval.sortby)->useOp = (yyvsp[(3) - (4)].list); + (yyval.sortby)->location = (yylsp[(3) - (4)]); + ;} + break; + + case 506: +#line 426 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.sortby) = makeNode(PGSortBy); + (yyval.sortby)->node = (yyvsp[(1) - (3)].node); + (yyval.sortby)->sortby_dir = (yyvsp[(2) - (3)].sortorder); + (yyval.sortby)->sortby_nulls = (yyvsp[(3) - (3)].nullorder); + (yyval.sortby)->useOp = NIL; + (yyval.sortby)->location = -1; /* no operator */ + ;} + break; + + case 507: +#line 436 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.sortorder) = PG_SORTBY_ASC; ;} + break; + + case 508: +#line 437 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.sortorder) = PG_SORTBY_DESC; ;} + break; + + case 509: +#line 438 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.sortorder) = PG_SORTBY_DEFAULT; ;} + break; + + case 510: +#line 441 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.nullorder) = PG_SORTBY_NULLS_FIRST; ;} + break; + + case 511: +#line 442 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.nullorder) = PG_SORTBY_NULLS_LAST; ;} + break; + + case 512: +#line 443 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.nullorder) = PG_SORTBY_NULLS_DEFAULT; ;} + break; + + case 513: +#line 447 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make2((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].node)); ;} + break; + + case 514: +#line 448 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make2((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); ;} + break; + + case 515: +#line 449 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make2(NULL, (yyvsp[(1) - (1)].node)); ;} + break; + + case 516: +#line 450 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make2((yyvsp[(1) - (1)].node), NULL); ;} + break; + + case 517: +#line 454 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 518: +#line 455 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make2(NULL,NULL); ;} + break; + + case 519: +#line 460 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + break; + + case 520: +#line 462 "third_party/libpg_query/grammar/statements/select.y" + { + /* Disabled because it was too confusing, bjm 2002-02-18 */ + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("LIMIT #,# syntax is not supported"), + errhint("Use separate LIMIT and OFFSET clauses."), + parser_errposition((yylsp[(1) - (4)])))); + ;} + break; + + case 521: +#line 478 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(3) - (5)].node); ;} + break; + + case 522: +#line 480 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeIntConst(1, -1); ;} + break; + + case 523: +#line 485 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + break; + + case 524: +#line 488 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(2) - (3)].node); ;} + break; + + case 525: +#line 496 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSampleSize(makeFloat((yyvsp[(1) - (2)].str)), true); + ;} + break; + + case 526: +#line 500 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSampleSize(makeInteger((yyvsp[(1) - (2)].ival)), true); + ;} + break; + + case 527: +#line 504 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSampleSize(makeFloat((yyvsp[(1) - (2)].str)), true); + ;} + break; + + case 528: +#line 508 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSampleSize(makeInteger((yyvsp[(1) - (2)].ival)), true); + ;} + break; + + case 529: +#line 512 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSampleSize(makeInteger((yyvsp[(1) - (1)].ival)), false); + ;} + break; + + case 530: +#line 516 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSampleSize(makeInteger((yyvsp[(1) - (2)].ival)), false); + ;} + break; + + case 531: +#line 523 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (yyvsp[(3) - (3)].node); + ;} + break; + + case 532: +#line 527 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 533: +#line 534 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 534: +#line 535 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = NULL; ;} + break; + + case 535: +#line 540 "third_party/libpg_query/grammar/statements/select.y" + { + int seed = (yyvsp[(5) - (5)].ival); + (yyval.node) = makeSampleOptions((yyvsp[(3) - (5)].node), (yyvsp[(1) - (5)].str), &seed, (yylsp[(1) - (5)])); + ;} + break; + + case 536: +#line 545 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSampleOptions((yyvsp[(1) - (1)].node), NULL, NULL, (yylsp[(1) - (1)])); + ;} + break; + + case 537: +#line 549 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSampleOptions((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].str), NULL, (yylsp[(1) - (4)])); + ;} + break; + + case 538: +#line 553 "third_party/libpg_query/grammar/statements/select.y" + { + int seed = (yyvsp[(5) - (6)].ival); + (yyval.node) = makeSampleOptions((yyvsp[(1) - (6)].node), (yyvsp[(3) - (6)].str), &seed, (yylsp[(1) - (6)])); + ;} + break; + + case 539: +#line 561 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (yyvsp[(2) - (2)].node); + ;} + break; + + case 540: +#line 567 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 541: +#line 568 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 542: +#line 573 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.ival) = (yyvsp[(3) - (4)].ival); ;} + break; + + case 543: +#line 574 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.ival) = -1; ;} + break; + + case 544: +#line 578 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 545: +#line 580 "third_party/libpg_query/grammar/statements/select.y" + { + /* LIMIT ALL is represented as a NULL constant */ + (yyval.node) = makeNullAConst((yylsp[(1) - (1)])); + ;} + break; + + case 546: +#line 585 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeLimitPercent((yyvsp[(1) - (2)].node)); ;} + break; + + case 547: +#line 587 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeLimitPercent(makeFloatConst((yyvsp[(1) - (2)].str),(yylsp[(1) - (2)]))); ;} + break; + + case 548: +#line 589 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeLimitPercent(makeIntConst((yyvsp[(1) - (2)].ival),(yylsp[(1) - (2)]))); ;} + break; + + case 549: +#line 593 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 550: +#line 613 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 551: +#line 615 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + break; + + case 552: +#line 617 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = doNegate((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + break; + + case 553: +#line 621 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeIntConst((yyvsp[(1) - (1)].ival),(yylsp[(1) - (1)])); ;} + break; + + case 554: +#line 622 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeFloatConst((yyvsp[(1) - (1)].str),(yylsp[(1) - (1)])); ;} + break; + + case 555: +#line 626 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.ival) = 0; ;} + break; + + case 556: +#line 627 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.ival) = 0; ;} + break; + + case 557: +#line 630 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.ival) = 0; ;} + break; + + case 558: +#line 631 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.ival) = 0; ;} + break; + + case 559: +#line 656 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(3) - (3)].list); ;} + break; + + case 560: +#line 658 "third_party/libpg_query/grammar/statements/select.y" + { + PGNode *node = (PGNode *) makeGroupingSet(GROUPING_SET_ALL, NIL, (yylsp[(3) - (3)])); + (yyval.list) = list_make1(node); + ;} + break; + + case 561: +#line 663 "third_party/libpg_query/grammar/statements/select.y" + { + PGNode *node = (PGNode *) makeGroupingSet(GROUPING_SET_ALL, NIL, (yylsp[(3) - (3)])); + (yyval.list) = list_make1(node); + ;} + break; + + case 562: +#line 667 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 563: +#line 671 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + break; + + case 564: +#line 672 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list),(yyvsp[(3) - (3)].node)); ;} + break; + + case 565: +#line 676 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 566: +#line 677 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + break; + + case 567: +#line 681 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 568: +#line 682 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 569: +#line 683 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 570: +#line 684 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 571: +#line 685 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 572: +#line 690 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_EMPTY, NIL, (yylsp[(1) - (2)])); + ;} + break; + + case 573: +#line 703 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_ROLLUP, (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); + ;} + break; + + case 574: +#line 710 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_CUBE, (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); + ;} + break; + + case 575: +#line 717 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_SETS, (yyvsp[(4) - (5)].list), (yylsp[(1) - (5)])); + ;} + break; + + case 576: +#line 723 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 577: +#line 724 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 578: +#line 728 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + break; + + case 579: +#line 729 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 580: +#line 733 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + break; + + case 581: +#line 734 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 582: +#line 738 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 583: +#line 739 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 584: +#line 743 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 585: +#line 744 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 586: +#line 748 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + break; + + case 587: +#line 749 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} + break; + + case 588: +#line 754 "third_party/libpg_query/grammar/statements/select.y" + { + PGLockingClause *n = makeNode(PGLockingClause); + n->lockedRels = (yyvsp[(2) - (3)].list); + n->strength = (yyvsp[(1) - (3)].lockstrength); + n->waitPolicy = (yyvsp[(3) - (3)].lockwaitpolicy); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 589: +#line 764 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.lockstrength) = LCS_FORUPDATE; ;} + break; + + case 590: +#line 765 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.lockstrength) = PG_LCS_FORNOKEYUPDATE; ;} + break; + + case 591: +#line 766 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.lockstrength) = PG_LCS_FORSHARE; ;} + break; + + case 592: +#line 767 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.lockstrength) = PG_LCS_FORKEYSHARE; ;} + break; + + case 593: +#line 771 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + break; + + case 594: +#line 772 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 595: +#line 777 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.lockwaitpolicy) = LockWaitError; ;} + break; + + case 596: +#line 778 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.lockwaitpolicy) = PGLockWaitSkip; ;} + break; + + case 597: +#line 779 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.lockwaitpolicy) = PGLockWaitBlock; ;} + break; + + case 598: +#line 789 "third_party/libpg_query/grammar/statements/select.y" + { + PGSelectStmt *n = makeNode(PGSelectStmt); + n->valuesLists = list_make1((yyvsp[(3) - (4)].list)); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 599: +#line 795 "third_party/libpg_query/grammar/statements/select.y" + { + PGSelectStmt *n = (PGSelectStmt *) (yyvsp[(1) - (5)].node); + n->valuesLists = lappend(n->valuesLists, (yyvsp[(4) - (5)].list)); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 600: +#line 803 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 601: +#line 804 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (2)].node); ;} + break; + + case 602: +#line 817 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + break; + + case 603: +#line 818 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 604: +#line 822 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + break; + + case 605: +#line 823 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} + break; + + case 606: +#line 827 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 607: +#line 828 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + break; + + case 608: +#line 835 "third_party/libpg_query/grammar/statements/select.y" + { + (yyvsp[(1) - (3)].range)->alias = (yyvsp[(2) - (3)].alias); + (yyvsp[(1) - (3)].range)->sample = (yyvsp[(3) - (3)].node); + (yyval.node) = (PGNode *) (yyvsp[(1) - (3)].range); + ;} + break; + + case 609: +#line 841 "third_party/libpg_query/grammar/statements/select.y" + { + PGRangeFunction *n = (PGRangeFunction *) (yyvsp[(1) - (3)].node); + n->alias = (PGAlias*) linitial((yyvsp[(2) - (3)].list)); + n->coldeflist = (PGList*) lsecond((yyvsp[(2) - (3)].list)); + n->sample = (yyvsp[(3) - (3)].node); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 610: +#line 849 "third_party/libpg_query/grammar/statements/select.y" + { + PGRangeSubselect *n = makeNode(PGRangeSubselect); + n->lateral = false; + n->subquery = (yyvsp[(1) - (3)].node); + n->alias = (yyvsp[(2) - (3)].alias); + n->sample = (yyvsp[(3) - (3)].node); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 611: +#line 858 "third_party/libpg_query/grammar/statements/select.y" + { + PGRangeFunction *n = (PGRangeFunction *) (yyvsp[(2) - (3)].node); + n->lateral = true; + n->alias = (PGAlias*) linitial((yyvsp[(3) - (3)].list)); + n->coldeflist = (PGList*) lsecond((yyvsp[(3) - (3)].list)); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 612: +#line 866 "third_party/libpg_query/grammar/statements/select.y" + { + PGRangeSubselect *n = makeNode(PGRangeSubselect); + n->lateral = false; + n->subquery = (yyvsp[(1) - (3)].node); + n->alias = (yyvsp[(2) - (3)].alias); + n->sample = (yyvsp[(3) - (3)].node); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 613: +#line 875 "third_party/libpg_query/grammar/statements/select.y" + { + PGRangeSubselect *n = makeNode(PGRangeSubselect); + n->lateral = true; + n->subquery = (yyvsp[(2) - (3)].node); + n->alias = (yyvsp[(3) - (3)].alias); + n->sample = NULL; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 614: +#line 884 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) (yyvsp[(1) - (1)].jexpr); + ;} + break; + + case 615: +#line 888 "third_party/libpg_query/grammar/statements/select.y" + { + (yyvsp[(2) - (4)].jexpr)->alias = (yyvsp[(4) - (4)].alias); + (yyval.node) = (PGNode *) (yyvsp[(2) - (4)].jexpr); + ;} + break; + + case 616: +#line 914 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.jexpr) = (yyvsp[(2) - (3)].jexpr); + ;} + break; + + case 617: +#line 918 "third_party/libpg_query/grammar/statements/select.y" + { + /* CROSS JOIN is same as unqualified inner join */ + PGJoinExpr *n = makeNode(PGJoinExpr); + n->jointype = PG_JOIN_INNER; + n->isNatural = false; + n->larg = (yyvsp[(1) - (4)].node); + n->rarg = (yyvsp[(4) - (4)].node); + n->usingClause = NIL; + n->quals = NULL; + n->location = (yylsp[(2) - (4)]); + (yyval.jexpr) = n; + ;} + break; + + case 618: +#line 931 "third_party/libpg_query/grammar/statements/select.y" + { + PGJoinExpr *n = makeNode(PGJoinExpr); + n->jointype = (yyvsp[(2) - (5)].jtype); + n->isNatural = false; + n->larg = (yyvsp[(1) - (5)].node); + n->rarg = (yyvsp[(4) - (5)].node); + if ((yyvsp[(5) - (5)].node) != NULL && IsA((yyvsp[(5) - (5)].node), PGList)) + n->usingClause = (PGList *) (yyvsp[(5) - (5)].node); /* USING clause */ + else + n->quals = (yyvsp[(5) - (5)].node); /* ON clause */ + n->location = (yylsp[(2) - (5)]); + (yyval.jexpr) = n; + ;} + break; + + case 619: +#line 945 "third_party/libpg_query/grammar/statements/select.y" + { + /* letting join_type reduce to empty doesn't work */ + PGJoinExpr *n = makeNode(PGJoinExpr); + n->jointype = PG_JOIN_INNER; + n->isNatural = false; + n->larg = (yyvsp[(1) - (4)].node); + n->rarg = (yyvsp[(3) - (4)].node); + if ((yyvsp[(4) - (4)].node) != NULL && IsA((yyvsp[(4) - (4)].node), PGList)) + n->usingClause = (PGList *) (yyvsp[(4) - (4)].node); /* USING clause */ + else + n->quals = (yyvsp[(4) - (4)].node); /* ON clause */ + n->location = (yylsp[(2) - (4)]); + (yyval.jexpr) = n; + ;} + break; + + case 620: +#line 960 "third_party/libpg_query/grammar/statements/select.y" + { + PGJoinExpr *n = makeNode(PGJoinExpr); + n->jointype = (yyvsp[(3) - (5)].jtype); + n->isNatural = true; + n->larg = (yyvsp[(1) - (5)].node); + n->rarg = (yyvsp[(5) - (5)].node); + n->usingClause = NIL; /* figure out which columns later... */ + n->quals = NULL; /* fill later */ + n->location = (yylsp[(2) - (5)]); + (yyval.jexpr) = n; + ;} + break; + + case 621: +#line 972 "third_party/libpg_query/grammar/statements/select.y" + { + /* letting join_type reduce to empty doesn't work */ + PGJoinExpr *n = makeNode(PGJoinExpr); + n->jointype = PG_JOIN_INNER; + n->isNatural = true; + n->larg = (yyvsp[(1) - (4)].node); + n->rarg = (yyvsp[(4) - (4)].node); + n->usingClause = NIL; /* figure out which columns later... */ + n->quals = NULL; /* fill later */ + n->location = (yylsp[(2) - (4)]); + (yyval.jexpr) = n; + ;} + break; + + case 622: +#line 988 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.alias) = makeNode(PGAlias); + (yyval.alias)->aliasname = (yyvsp[(2) - (5)].str); + (yyval.alias)->colnames = (yyvsp[(4) - (5)].list); + ;} + break; + + case 623: +#line 994 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.alias) = makeNode(PGAlias); + (yyval.alias)->aliasname = (yyvsp[(2) - (2)].str); + ;} + break; + + case 624: +#line 999 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.alias) = makeNode(PGAlias); + (yyval.alias)->aliasname = (yyvsp[(1) - (4)].str); + (yyval.alias)->colnames = (yyvsp[(3) - (4)].list); + ;} + break; + + case 625: +#line 1005 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.alias) = makeNode(PGAlias); + (yyval.alias)->aliasname = (yyvsp[(1) - (1)].str); + ;} + break; + + case 626: +#line 1011 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.alias) = (yyvsp[(1) - (1)].alias); ;} + break; + + case 627: +#line 1012 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.alias) = NULL; ;} + break; + + case 628: +#line 1021 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make2((yyvsp[(1) - (1)].alias), NIL); + ;} + break; + + case 629: +#line 1025 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make2(NULL, (yyvsp[(3) - (4)].list)); + ;} + break; + + case 630: +#line 1029 "third_party/libpg_query/grammar/statements/select.y" + { + PGAlias *a = makeNode(PGAlias); + a->aliasname = (yyvsp[(2) - (5)].str); + (yyval.list) = list_make2(a, (yyvsp[(4) - (5)].list)); + ;} + break; + + case 631: +#line 1035 "third_party/libpg_query/grammar/statements/select.y" + { + PGAlias *a = makeNode(PGAlias); + a->aliasname = (yyvsp[(1) - (4)].str); + (yyval.list) = list_make2(a, (yyvsp[(3) - (4)].list)); + ;} + break; + + case 632: +#line 1041 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make2(NULL, NIL); + ;} + break; + + case 633: +#line 1046 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.jtype) = PG_JOIN_FULL; ;} + break; + + case 634: +#line 1047 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.jtype) = PG_JOIN_LEFT; ;} + break; + + case 635: +#line 1048 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.jtype) = PG_JOIN_RIGHT; ;} + break; + + case 636: +#line 1049 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.jtype) = PG_JOIN_INNER; ;} + break; + + case 637: +#line 1053 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 638: +#line 1054 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 639: +#line 1066 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) (yyvsp[(3) - (4)].list); ;} + break; + + case 640: +#line 1067 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + break; + + case 641: +#line 1073 "third_party/libpg_query/grammar/statements/select.y" + { + /* inheritance query, implicitly */ + (yyval.range) = (yyvsp[(1) - (1)].range); + (yyval.range)->inh = true; + (yyval.range)->alias = NULL; + ;} + break; + + case 642: +#line 1080 "third_party/libpg_query/grammar/statements/select.y" + { + /* inheritance query, explicitly */ + (yyval.range) = (yyvsp[(1) - (2)].range); + (yyval.range)->inh = true; + (yyval.range)->alias = NULL; + ;} + break; + + case 643: +#line 1087 "third_party/libpg_query/grammar/statements/select.y" + { + /* no inheritance */ + (yyval.range) = (yyvsp[(2) - (2)].range); + (yyval.range)->inh = false; + (yyval.range)->alias = NULL; + ;} + break; + + case 644: +#line 1094 "third_party/libpg_query/grammar/statements/select.y" + { + /* no inheritance, SQL99-style syntax */ + (yyval.range) = (yyvsp[(3) - (4)].range); + (yyval.range)->inh = false; + (yyval.range)->alias = NULL; + ;} + break; + + case 645: +#line 1126 "third_party/libpg_query/grammar/statements/select.y" + { + PGRangeFunction *n = makeNode(PGRangeFunction); + n->lateral = false; + n->ordinality = (yyvsp[(2) - (2)].boolean); + n->is_rowsfrom = false; + n->functions = list_make1(list_make2((yyvsp[(1) - (2)].node), NIL)); + n->sample = NULL; + /* alias and coldeflist are set by table_ref production */ + (yyval.node) = (PGNode *) n; + ;} + break; + + case 646: +#line 1137 "third_party/libpg_query/grammar/statements/select.y" + { + PGRangeFunction *n = makeNode(PGRangeFunction); + n->lateral = false; + n->ordinality = (yyvsp[(6) - (6)].boolean); + n->is_rowsfrom = true; + n->functions = (yyvsp[(4) - (6)].list); + n->sample = NULL; + /* alias and coldeflist are set by table_ref production */ + (yyval.node) = (PGNode *) n; + ;} + break; + + case 647: +#line 1150 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make2((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].list)); ;} + break; + + case 648: +#line 1154 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].list)); ;} + break; + + case 649: +#line 1155 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); ;} + break; + + case 650: +#line 1158 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + break; + + case 651: +#line 1159 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 652: +#line 1162 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = true; ;} + break; + + case 653: +#line 1163 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = false; ;} + break; + + case 654: +#line 1168 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + break; + + case 655: +#line 1169 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 656: +#line 1175 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); + ;} + break; + + case 657: +#line 1179 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); + ;} + break; + + case 658: +#line 1185 "third_party/libpg_query/grammar/statements/select.y" + { + PGColumnDef *n = makeNode(PGColumnDef); + n->colname = (yyvsp[(1) - (3)].str); + n->typeName = (yyvsp[(2) - (3)].typnam); + n->inhcount = 0; + n->is_local = true; + n->is_not_null = false; + n->is_from_type = false; + n->storage = 0; + n->raw_default = NULL; + n->cooked_default = NULL; + n->collClause = (PGCollateClause *) (yyvsp[(3) - (3)].node); + n->collOid = InvalidOid; + n->constraints = NIL; + n->location = (yylsp[(1) - (3)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 659: +#line 1206 "third_party/libpg_query/grammar/statements/select.y" + { + PGCollateClause *n = makeNode(PGCollateClause); + n->arg = NULL; + n->collname = (yyvsp[(2) - (2)].list); + n->location = (yylsp[(1) - (2)]); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 660: +#line 1213 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 661: +#line 1226 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1(list_make2(makeString((yyvsp[(1) - (2)].str)), (yyvsp[(2) - (2)].typnam))); + ;} + break; + + case 662: +#line 1229 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = lappend((yyvsp[(1) - (4)].list), list_make2(makeString((yyvsp[(3) - (4)].str)), (yyvsp[(4) - (4)].typnam))); + ;} + break; + + case 665: +#line 1236 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + break; + + case 666: +#line 1237 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.typnam) = NULL; ;} + break; + + case 667: +#line 1240 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(1) - (2)].typnam); + (yyval.typnam)->arrayBounds = (yyvsp[(2) - (2)].list); + ;} + break; + + case 668: +#line 1245 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(2) - (3)].typnam); + (yyval.typnam)->arrayBounds = (yyvsp[(3) - (3)].list); + (yyval.typnam)->setof = true; + ;} + break; + + case 669: +#line 1252 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(1) - (5)].typnam); + (yyval.typnam)->arrayBounds = list_make1(makeInteger((yyvsp[(4) - (5)].ival))); + ;} + break; + + case 670: +#line 1257 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(2) - (6)].typnam); + (yyval.typnam)->arrayBounds = list_make1(makeInteger((yyvsp[(5) - (6)].ival))); + (yyval.typnam)->setof = true; + ;} + break; + + case 671: +#line 1263 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(1) - (2)].typnam); + (yyval.typnam)->arrayBounds = list_make1(makeInteger(-1)); + ;} + break; + + case 672: +#line 1268 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(2) - (3)].typnam); + (yyval.typnam)->arrayBounds = list_make1(makeInteger(-1)); + (yyval.typnam)->setof = true; + ;} + break; + + case 673: +#line 1273 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("struct"); + (yyval.typnam)->arrayBounds = (yyvsp[(5) - (5)].list); + (yyval.typnam)->typmods = (yyvsp[(3) - (5)].list); + (yyval.typnam)->location = (yylsp[(1) - (5)]); + ;} + break; + + case 674: +#line 1279 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("map"); + (yyval.typnam)->arrayBounds = (yyvsp[(5) - (5)].list); + (yyval.typnam)->typmods = (yyvsp[(3) - (5)].list); + (yyval.typnam)->location = (yylsp[(1) - (5)]); + ;} + break; + + case 675: +#line 1289 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeInteger(-1)); ;} + break; + + case 676: +#line 1291 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (4)].list), makeInteger((yyvsp[(3) - (4)].ival))); ;} + break; + + case 677: +#line 1293 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 678: +#line 1297 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + break; + + case 679: +#line 1298 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + break; + + case 680: +#line 1299 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + break; + + case 681: +#line 1300 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + break; + + case 682: +#line 1301 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + break; + + case 683: +#line 1303 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(1) - (2)].typnam); + (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); + ;} + break; + + case 684: +#line 1308 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(1) - (4)].typnam); + (yyval.typnam)->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1), + makeIntConst((yyvsp[(3) - (4)].ival), (yylsp[(3) - (4)]))); + ;} + break; + + case 685: +#line 1327 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + break; + + case 686: +#line 1328 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + break; + + case 687: +#line 1329 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + break; + + case 688: +#line 1330 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} + break; + + case 689: +#line 1342 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = makeTypeName((yyvsp[(1) - (2)].str)); + (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); + (yyval.typnam)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 690: +#line 1355 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + break; + + case 691: +#line 1356 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 692: +#line 1363 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("int4"); + (yyval.typnam)->location = (yylsp[(1) - (1)]); + ;} + break; + + case 693: +#line 1368 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("int4"); + (yyval.typnam)->location = (yylsp[(1) - (1)]); + ;} + break; + + case 694: +#line 1373 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("int2"); + (yyval.typnam)->location = (yylsp[(1) - (1)]); + ;} + break; + + case 695: +#line 1378 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("int8"); + (yyval.typnam)->location = (yylsp[(1) - (1)]); + ;} + break; + + case 696: +#line 1383 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("float4"); + (yyval.typnam)->location = (yylsp[(1) - (1)]); + ;} + break; + + case 697: +#line 1388 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(2) - (2)].typnam); + (yyval.typnam)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 698: +#line 1393 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("float8"); + (yyval.typnam)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 699: +#line 1398 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("numeric"); + (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); + (yyval.typnam)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 700: +#line 1404 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("numeric"); + (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); + (yyval.typnam)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 701: +#line 1410 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("numeric"); + (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); + (yyval.typnam)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 702: +#line 1416 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("bool"); + (yyval.typnam)->location = (yylsp[(1) - (1)]); + ;} + break; + + case 703: +#line 1423 "third_party/libpg_query/grammar/statements/select.y" + { + /* + * Check FLOAT() precision limits assuming IEEE floating + * types - thomas 1997-09-18 + */ + if ((yyvsp[(2) - (3)].ival) < 1) + ereport(ERROR, + (errcode(PG_ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("precision for type float must be at least 1 bit"), + parser_errposition((yylsp[(2) - (3)])))); + else if ((yyvsp[(2) - (3)].ival) <= 24) + (yyval.typnam) = SystemTypeName("float4"); + else if ((yyvsp[(2) - (3)].ival) <= 53) + (yyval.typnam) = SystemTypeName("float8"); + else + ereport(ERROR, + (errcode(PG_ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("precision for type float must be less than 54 bits"), + parser_errposition((yylsp[(2) - (3)])))); + ;} + break; + + case 704: +#line 1444 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("float4"); + ;} + break; + + case 705: +#line 1454 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(1) - (1)].typnam); + ;} + break; + + case 706: +#line 1458 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(1) - (1)].typnam); + ;} + break; + + case 707: +#line 1466 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(1) - (1)].typnam); + ;} + break; + + case 708: +#line 1470 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(1) - (1)].typnam); + (yyval.typnam)->typmods = NIL; + ;} + break; + + case 709: +#line 1478 "third_party/libpg_query/grammar/statements/select.y" + { + const char *typname; + + typname = (yyvsp[(2) - (5)].boolean) ? "varbit" : "bit"; + (yyval.typnam) = SystemTypeName(typname); + (yyval.typnam)->typmods = (yyvsp[(4) - (5)].list); + (yyval.typnam)->location = (yylsp[(1) - (5)]); + ;} + break; + + case 710: +#line 1490 "third_party/libpg_query/grammar/statements/select.y" + { + /* bit defaults to bit(1), varbit to no limit */ + if ((yyvsp[(2) - (2)].boolean)) + { + (yyval.typnam) = SystemTypeName("varbit"); + } + else + { + (yyval.typnam) = SystemTypeName("bit"); + (yyval.typnam)->typmods = list_make1(makeIntConst(1, -1)); + } + (yyval.typnam)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 711: +#line 1511 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(1) - (1)].typnam); + ;} + break; + + case 712: +#line 1515 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(1) - (1)].typnam); + ;} + break; + + case 713: +#line 1521 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = (yyvsp[(1) - (1)].typnam); + ;} + break; + + case 714: +#line 1525 "third_party/libpg_query/grammar/statements/select.y" + { + /* Length was not specified so allow to be unrestricted. + * This handles problems with fixed-length (bpchar) strings + * which in column definitions must default to a length + * of one, but should not be constrained if the length + * was not specified. + */ + (yyval.typnam) = (yyvsp[(1) - (1)].typnam); + (yyval.typnam)->typmods = NIL; + ;} + break; + + case 715: +#line 1538 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName((yyvsp[(1) - (4)].conststr)); + (yyval.typnam)->typmods = list_make1(makeIntConst((yyvsp[(3) - (4)].ival), (yylsp[(3) - (4)]))); + (yyval.typnam)->location = (yylsp[(1) - (4)]); + ;} + break; + + case 716: +#line 1546 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName((yyvsp[(1) - (1)].conststr)); + /* char defaults to char(1), varchar to no limit */ + if (strcmp((yyvsp[(1) - (1)].conststr), "bpchar") == 0) + (yyval.typnam)->typmods = list_make1(makeIntConst(1, -1)); + (yyval.typnam)->location = (yylsp[(1) - (1)]); + ;} + break; + + case 717: +#line 1556 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = (yyvsp[(2) - (2)].boolean) ? "varchar": "bpchar"; ;} + break; + + case 718: +#line 1558 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = (yyvsp[(2) - (2)].boolean) ? "varchar": "bpchar"; ;} + break; + + case 719: +#line 1560 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "varchar"; ;} + break; + + case 720: +#line 1562 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = (yyvsp[(3) - (3)].boolean) ? "varchar": "bpchar"; ;} + break; + + case 721: +#line 1564 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = (yyvsp[(3) - (3)].boolean) ? "varchar": "bpchar"; ;} + break; + + case 722: +#line 1566 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = (yyvsp[(2) - (2)].boolean) ? "varchar": "bpchar"; ;} + break; + + case 723: +#line 1570 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = true; ;} + break; + + case 724: +#line 1571 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = false; ;} + break; + + case 725: +#line 1579 "third_party/libpg_query/grammar/statements/select.y" + { + if ((yyvsp[(5) - (5)].boolean)) + (yyval.typnam) = SystemTypeName("timestamptz"); + else + (yyval.typnam) = SystemTypeName("timestamp"); + (yyval.typnam)->typmods = list_make1(makeIntConst((yyvsp[(3) - (5)].ival), (yylsp[(3) - (5)]))); + (yyval.typnam)->location = (yylsp[(1) - (5)]); + ;} + break; + + case 726: +#line 1588 "third_party/libpg_query/grammar/statements/select.y" + { + if ((yyvsp[(2) - (2)].boolean)) + (yyval.typnam) = SystemTypeName("timestamptz"); + else + (yyval.typnam) = SystemTypeName("timestamp"); + (yyval.typnam)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 727: +#line 1596 "third_party/libpg_query/grammar/statements/select.y" + { + if ((yyvsp[(5) - (5)].boolean)) + (yyval.typnam) = SystemTypeName("timetz"); + else + (yyval.typnam) = SystemTypeName("time"); + (yyval.typnam)->typmods = list_make1(makeIntConst((yyvsp[(3) - (5)].ival), (yylsp[(3) - (5)]))); + (yyval.typnam)->location = (yylsp[(1) - (5)]); + ;} + break; + + case 728: +#line 1605 "third_party/libpg_query/grammar/statements/select.y" + { + if ((yyvsp[(2) - (2)].boolean)) + (yyval.typnam) = SystemTypeName("timetz"); + else + (yyval.typnam) = SystemTypeName("time"); + (yyval.typnam)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 729: +#line 1616 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.typnam) = SystemTypeName("interval"); + (yyval.typnam)->location = (yylsp[(1) - (1)]); + ;} + break; + + case 730: +#line 1623 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = true; ;} + break; + + case 731: +#line 1624 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = false; ;} + break; + + case 732: +#line 1625 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = false; ;} + break; + + case 749: +#line 1654 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(YEAR), (yylsp[(1) - (1)]))); ;} + break; + + case 750: +#line 1656 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MONTH), (yylsp[(1) - (1)]))); ;} + break; + + case 751: +#line 1658 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY), (yylsp[(1) - (1)]))); ;} + break; + + case 752: +#line 1660 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(HOUR), (yylsp[(1) - (1)]))); ;} + break; + + case 753: +#line 1662 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MINUTE), (yylsp[(1) - (1)]))); ;} + break; + + case 754: +#line 1664 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(SECOND), (yylsp[(1) - (1)]))); ;} + break; + + case 755: +#line 1666 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MILLISECOND), (yylsp[(1) - (1)]))); ;} + break; + + case 756: +#line 1668 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MICROSECOND), (yylsp[(1) - (1)]))); ;} + break; + + case 757: +#line 1670 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(YEAR) | + INTERVAL_MASK(MONTH), (yylsp[(1) - (3)]))); + ;} + break; + + case 758: +#line 1675 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY) | + INTERVAL_MASK(HOUR), (yylsp[(1) - (3)]))); + ;} + break; + + case 759: +#line 1680 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY) | + INTERVAL_MASK(HOUR) | + INTERVAL_MASK(MINUTE), (yylsp[(1) - (3)]))); + ;} + break; + + case 760: +#line 1686 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY) | + INTERVAL_MASK(HOUR) | + INTERVAL_MASK(MINUTE) | + INTERVAL_MASK(SECOND), (yylsp[(1) - (3)]))); + ;} + break; + + case 761: +#line 1693 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(HOUR) | + INTERVAL_MASK(MINUTE), (yylsp[(1) - (3)]))); + ;} + break; + + case 762: +#line 1698 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(HOUR) | + INTERVAL_MASK(MINUTE) | + INTERVAL_MASK(SECOND), (yylsp[(1) - (3)]))); + ;} + break; + + case 763: +#line 1704 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MINUTE) | + INTERVAL_MASK(SECOND), (yylsp[(1) - (3)]))); + ;} + break; + + case 764: +#line 1709 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 765: +#line 1740 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 766: +#line 1743 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeTypeCast((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].typnam), 0, (yylsp[(2) - (3)])); ;} + break; + + case 767: +#line 1745 "third_party/libpg_query/grammar/statements/select.y" + { + PGCollateClause *n = makeNode(PGCollateClause); + n->arg = (yyvsp[(1) - (3)].node); + n->collname = (yyvsp[(3) - (3)].list); + n->location = (yylsp[(2) - (3)]); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 768: +#line 1753 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("timezone"), + list_make2((yyvsp[(5) - (5)].node), (yyvsp[(1) - (5)].node)), + (yylsp[(2) - (5)])); + ;} + break; + + case 769: +#line 1768 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + break; + + case 770: +#line 1770 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = doNegate((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + break; + + case 771: +#line 1772 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 772: +#line 1774 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "-", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 773: +#line 1776 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "*", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 774: +#line 1778 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "/", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 775: +#line 1780 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "%", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 776: +#line 1782 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "^", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 777: +#line 1784 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "**", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 778: +#line 1786 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 779: +#line 1788 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 780: +#line 1790 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 781: +#line 1792 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 782: +#line 1794 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 783: +#line 1796 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<>", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 784: +#line 1799 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(2) - (3)].list), (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 785: +#line 1801 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(1) - (2)].list), NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + break; + + case 786: +#line 1803 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(2) - (2)].list), (yyvsp[(1) - (2)].node), NULL, (yylsp[(2) - (2)])); ;} + break; + + case 787: +#line 1806 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeAndExpr((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 788: +#line 1808 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeOrExpr((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 789: +#line 1810 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeNotExpr((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + break; + + case 790: +#line 1812 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeNotExpr((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + break; + + case 791: +#line 1814 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_GLOB, "~~~", + (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); + ;} + break; + + case 792: +#line 1819 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_LIKE, "~~", + (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); + ;} + break; + + case 793: +#line 1824 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall(SystemFuncName("like_escape"), + list_make3((yyvsp[(1) - (5)].node), (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node)), + (yylsp[(2) - (5)])); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 794: +#line 1831 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_LIKE, "!~~", + (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node), (yylsp[(2) - (4)])); + ;} + break; + + case 795: +#line 1836 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall(SystemFuncName("not_like_escape"), + list_make3((yyvsp[(1) - (6)].node), (yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), + (yylsp[(2) - (6)])); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 796: +#line 1843 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_ILIKE, "~~*", + (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); + ;} + break; + + case 797: +#line 1848 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall(SystemFuncName("ilike_escape"), + list_make3((yyvsp[(1) - (5)].node), (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node)), + (yylsp[(2) - (5)])); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 798: +#line 1855 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_ILIKE, "!~~*", + (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node), (yylsp[(2) - (4)])); + ;} + break; + + case 799: +#line 1860 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall(SystemFuncName("not_ilike_escape"), + list_make3((yyvsp[(1) - (6)].node), (yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), + (yylsp[(2) - (6)])); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 800: +#line 1868 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall(SystemFuncName("similar_escape"), + list_make2((yyvsp[(4) - (4)].node), makeNullAConst(-1)), + (yylsp[(2) - (4)])); + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_SIMILAR, "~", + (yyvsp[(1) - (4)].node), (PGNode *) n, (yylsp[(2) - (4)])); + ;} + break; + + case 801: +#line 1876 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall(SystemFuncName("similar_escape"), + list_make2((yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), + (yylsp[(2) - (6)])); + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_SIMILAR, "~", + (yyvsp[(1) - (6)].node), (PGNode *) n, (yylsp[(2) - (6)])); + ;} + break; + + case 802: +#line 1884 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall(SystemFuncName("similar_escape"), + list_make2((yyvsp[(5) - (5)].node), makeNullAConst(-1)), + (yylsp[(2) - (5)])); + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_SIMILAR, "!~", + (yyvsp[(1) - (5)].node), (PGNode *) n, (yylsp[(2) - (5)])); + ;} + break; + + case 803: +#line 1892 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall(SystemFuncName("similar_escape"), + list_make2((yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node)), + (yylsp[(2) - (7)])); + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_SIMILAR, "!~", + (yyvsp[(1) - (7)].node), (PGNode *) n, (yylsp[(2) - (7)])); + ;} + break; + + case 804: +#line 1910 "third_party/libpg_query/grammar/statements/select.y" + { + PGNullTest *n = makeNode(PGNullTest); + n->arg = (PGExpr *) (yyvsp[(1) - (3)].node); + n->nulltesttype = PG_IS_NULL; + n->location = (yylsp[(2) - (3)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 805: +#line 1918 "third_party/libpg_query/grammar/statements/select.y" + { + PGNullTest *n = makeNode(PGNullTest); + n->arg = (PGExpr *) (yyvsp[(1) - (2)].node); + n->nulltesttype = PG_IS_NULL; + n->location = (yylsp[(2) - (2)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 806: +#line 1926 "third_party/libpg_query/grammar/statements/select.y" + { + PGNullTest *n = makeNode(PGNullTest); + n->arg = (PGExpr *) (yyvsp[(1) - (4)].node); + n->nulltesttype = IS_NOT_NULL; + n->location = (yylsp[(2) - (4)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 807: +#line 1934 "third_party/libpg_query/grammar/statements/select.y" + { + PGNullTest *n = makeNode(PGNullTest); + n->arg = (PGExpr *) (yyvsp[(1) - (3)].node); + n->nulltesttype = IS_NOT_NULL; + n->location = (yylsp[(2) - (3)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 808: +#line 1942 "third_party/libpg_query/grammar/statements/select.y" + { + PGNullTest *n = makeNode(PGNullTest); + n->arg = (PGExpr *) (yyvsp[(1) - (2)].node); + n->nulltesttype = IS_NOT_NULL; + n->location = (yylsp[(2) - (2)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 809: +#line 1949 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall(SystemFuncName("row"), (yyvsp[(1) - (1)].list), (yylsp[(1) - (1)])); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 810: +#line 1953 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall(SystemFuncName("struct_pack"), (yyvsp[(2) - (3)].list), (yylsp[(2) - (3)])); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 811: +#line 1957 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall(SystemFuncName("list_value"), (yyvsp[(2) - (3)].list), (yylsp[(2) - (3)])); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 812: +#line 1962 "third_party/libpg_query/grammar/statements/select.y" + { + PGLambdaFunction *n = makeNode(PGLambdaFunction); + n->lhs = (yyvsp[(1) - (3)].node); + n->rhs = (yyvsp[(3) - (3)].node); + n->location = (yylsp[(2) - (3)]); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 813: +#line 1970 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "->>", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); + ;} + break; + + case 814: +#line 1974 "third_party/libpg_query/grammar/statements/select.y" + { + if (list_length((yyvsp[(1) - (3)].list)) != 2) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("wrong number of parameters on left side of OVERLAPS expression"), + parser_errposition((yylsp[(1) - (3)])))); + if (list_length((yyvsp[(3) - (3)].list)) != 2) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("wrong number of parameters on right side of OVERLAPS expression"), + parser_errposition((yylsp[(3) - (3)])))); + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("overlaps"), + list_concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)), + (yylsp[(2) - (3)])); + ;} + break; + + case 815: +#line 1990 "third_party/libpg_query/grammar/statements/select.y" + { + PGBooleanTest *b = makeNode(PGBooleanTest); + b->arg = (PGExpr *) (yyvsp[(1) - (3)].node); + b->booltesttype = PG_IS_TRUE; + b->location = (yylsp[(2) - (3)]); + (yyval.node) = (PGNode *)b; + ;} + break; + + case 816: +#line 1998 "third_party/libpg_query/grammar/statements/select.y" + { + PGBooleanTest *b = makeNode(PGBooleanTest); + b->arg = (PGExpr *) (yyvsp[(1) - (4)].node); + b->booltesttype = IS_NOT_TRUE; + b->location = (yylsp[(2) - (4)]); + (yyval.node) = (PGNode *)b; + ;} + break; + + case 817: +#line 2006 "third_party/libpg_query/grammar/statements/select.y" + { + PGBooleanTest *b = makeNode(PGBooleanTest); + b->arg = (PGExpr *) (yyvsp[(1) - (3)].node); + b->booltesttype = IS_FALSE; + b->location = (yylsp[(2) - (3)]); + (yyval.node) = (PGNode *)b; + ;} + break; + + case 818: +#line 2014 "third_party/libpg_query/grammar/statements/select.y" + { + PGBooleanTest *b = makeNode(PGBooleanTest); + b->arg = (PGExpr *) (yyvsp[(1) - (4)].node); + b->booltesttype = IS_NOT_FALSE; + b->location = (yylsp[(2) - (4)]); + (yyval.node) = (PGNode *)b; + ;} + break; + + case 819: +#line 2022 "third_party/libpg_query/grammar/statements/select.y" + { + PGBooleanTest *b = makeNode(PGBooleanTest); + b->arg = (PGExpr *) (yyvsp[(1) - (3)].node); + b->booltesttype = IS_UNKNOWN; + b->location = (yylsp[(2) - (3)]); + (yyval.node) = (PGNode *)b; + ;} + break; + + case 820: +#line 2030 "third_party/libpg_query/grammar/statements/select.y" + { + PGBooleanTest *b = makeNode(PGBooleanTest); + b->arg = (PGExpr *) (yyvsp[(1) - (4)].node); + b->booltesttype = IS_NOT_UNKNOWN; + b->location = (yylsp[(2) - (4)]); + (yyval.node) = (PGNode *)b; + ;} + break; + + case 821: +#line 2038 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_DISTINCT, "=", (yyvsp[(1) - (5)].node), (yyvsp[(5) - (5)].node), (yylsp[(2) - (5)])); + ;} + break; + + case 822: +#line 2042 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_DISTINCT, "=", (yyvsp[(1) - (6)].node), (yyvsp[(6) - (6)].node), (yylsp[(2) - (6)])); + ;} + break; + + case 823: +#line 2046 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "=", (yyvsp[(1) - (6)].node), (PGNode *) (yyvsp[(5) - (6)].list), (yylsp[(2) - (6)])); + ;} + break; + + case 824: +#line 2050 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "<>", (yyvsp[(1) - (7)].node), (PGNode *) (yyvsp[(6) - (7)].list), (yylsp[(2) - (7)])); + ;} + break; + + case 825: +#line 2054 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_BETWEEN, + "BETWEEN", + (yyvsp[(1) - (6)].node), + (PGNode *) list_make2((yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), + (yylsp[(2) - (6)])); + ;} + break; + + case 826: +#line 2062 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_BETWEEN, + "NOT BETWEEN", + (yyvsp[(1) - (7)].node), + (PGNode *) list_make2((yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node)), + (yylsp[(2) - (7)])); + ;} + break; + + case 827: +#line 2070 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_BETWEEN_SYM, + "BETWEEN SYMMETRIC", + (yyvsp[(1) - (6)].node), + (PGNode *) list_make2((yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), + (yylsp[(2) - (6)])); + ;} + break; + + case 828: +#line 2078 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_BETWEEN_SYM, + "NOT BETWEEN SYMMETRIC", + (yyvsp[(1) - (7)].node), + (PGNode *) list_make2((yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node)), + (yylsp[(2) - (7)])); + ;} + break; + + case 829: +#line 2086 "third_party/libpg_query/grammar/statements/select.y" + { + /* in_expr returns a PGSubLink or a list of a_exprs */ + if (IsA((yyvsp[(3) - (3)].node), PGSubLink)) + { + /* generate foo = ANY (subquery) */ + PGSubLink *n = (PGSubLink *) (yyvsp[(3) - (3)].node); + n->subLinkType = PG_ANY_SUBLINK; + n->subLinkId = 0; + n->testexpr = (yyvsp[(1) - (3)].node); + n->operName = NIL; /* show it's IN not = ANY */ + n->location = (yylsp[(2) - (3)]); + (yyval.node) = (PGNode *)n; + } + else + { + /* generate scalar IN expression */ + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_IN, "=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); + } + ;} + break; + + case 830: +#line 2106 "third_party/libpg_query/grammar/statements/select.y" + { + /* in_expr returns a PGSubLink or a list of a_exprs */ + if (IsA((yyvsp[(4) - (4)].node), PGSubLink)) + { + /* generate NOT (foo = ANY (subquery)) */ + /* Make an = ANY node */ + PGSubLink *n = (PGSubLink *) (yyvsp[(4) - (4)].node); + n->subLinkType = PG_ANY_SUBLINK; + n->subLinkId = 0; + n->testexpr = (yyvsp[(1) - (4)].node); + n->operName = NIL; /* show it's IN not = ANY */ + n->location = (yylsp[(2) - (4)]); + /* Stick a NOT on top; must have same parse location */ + (yyval.node) = makeNotExpr((PGNode *) n, (yylsp[(2) - (4)])); + } + else + { + /* generate scalar NOT IN expression */ + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_IN, "<>", (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node), (yylsp[(2) - (4)])); + } + ;} + break; + + case 831: +#line 2128 "third_party/libpg_query/grammar/statements/select.y" + { + PGSubLink *n = makeNode(PGSubLink); + n->subLinkType = (yyvsp[(3) - (4)].subquerytype); + n->subLinkId = 0; + n->testexpr = (yyvsp[(1) - (4)].node); + n->operName = (yyvsp[(2) - (4)].list); + n->subselect = (yyvsp[(4) - (4)].node); + n->location = (yylsp[(2) - (4)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 832: +#line 2139 "third_party/libpg_query/grammar/statements/select.y" + { + if ((yyvsp[(3) - (6)].subquerytype) == PG_ANY_SUBLINK) + (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP_ANY, (yyvsp[(2) - (6)].list), (yyvsp[(1) - (6)].node), (yyvsp[(5) - (6)].node), (yylsp[(2) - (6)])); + else + (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP_ALL, (yyvsp[(2) - (6)].list), (yyvsp[(1) - (6)].node), (yyvsp[(5) - (6)].node), (yylsp[(2) - (6)])); + ;} + break; + + case 833: +#line 2146 "third_party/libpg_query/grammar/statements/select.y" + { + PGSubLink *n = makeNode(PGSubLink); + n->subLinkType = PG_ARRAY_SUBLINK; + n->subLinkId = 0; + n->testexpr = NULL; + n->operName = NULL; + n->subselect = (yyvsp[(2) - (2)].node); + n->location = (yylsp[(2) - (2)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 834: +#line 2157 "third_party/libpg_query/grammar/statements/select.y" + { + /* + * The SQL spec only allows DEFAULT in "contextually typed + * expressions", but for us, it's easier to allow it in + * any a_expr and then throw error during parse analysis + * if it's in an inappropriate context. This way also + * lets us say something smarter than "syntax error". + */ + PGSetToDefault *n = makeNode(PGSetToDefault); + /* parse analysis will fill in the rest */ + n->location = (yylsp[(1) - (1)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 835: +#line 2170 "third_party/libpg_query/grammar/statements/select.y" + { + PGList *func_name = list_make1(makeString("construct_array")); + PGFuncCall *n = makeFuncCall(func_name, (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 836: +#line 2187 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 837: +#line 2189 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeTypeCast((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].typnam), 0, (yylsp[(2) - (3)])); ;} + break; + + case 838: +#line 2191 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + break; + + case 839: +#line 2193 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = doNegate((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + break; + + case 840: +#line 2195 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 841: +#line 2197 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "-", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 842: +#line 2199 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "*", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 843: +#line 2201 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "/", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 844: +#line 2203 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "%", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 845: +#line 2205 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "^", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 846: +#line 2207 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "**", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 847: +#line 2209 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 848: +#line 2211 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 849: +#line 2213 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 850: +#line 2215 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 851: +#line 2217 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 852: +#line 2219 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<>", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 853: +#line 2221 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(2) - (3)].list), (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} + break; + + case 854: +#line 2223 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(1) - (2)].list), NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} + break; + + case 855: +#line 2225 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(2) - (2)].list), (yyvsp[(1) - (2)].node), NULL, (yylsp[(2) - (2)])); ;} + break; + + case 856: +#line 2227 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_DISTINCT, "=", (yyvsp[(1) - (5)].node), (yyvsp[(5) - (5)].node), (yylsp[(2) - (5)])); + ;} + break; + + case 857: +#line 2231 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_DISTINCT, "=", (yyvsp[(1) - (6)].node), (yyvsp[(6) - (6)].node), (yylsp[(2) - (6)])); + ;} + break; + + case 858: +#line 2235 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "=", (yyvsp[(1) - (6)].node), (PGNode *) (yyvsp[(5) - (6)].list), (yylsp[(2) - (6)])); + ;} + break; + + case 859: +#line 2239 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "<>", (yyvsp[(1) - (7)].node), (PGNode *) (yyvsp[(6) - (7)].list), (yylsp[(2) - (7)])); + ;} + break; + + case 860: +#line 2252 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 861: +#line 2253 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 862: +#line 2255 "third_party/libpg_query/grammar/statements/select.y" + { + PGPositionalReference *n = makeNode(PGPositionalReference); + n->position = (yyvsp[(2) - (2)].ival); + n->location = (yylsp[(1) - (2)]); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 863: +#line 2262 "third_party/libpg_query/grammar/statements/select.y" + { + if ((yyvsp[(2) - (2)].list)) + { + PGAIndirection *n = makeNode(PGAIndirection); + n->arg = makeParamRef(0, (yylsp[(1) - (2)])); + n->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); + (yyval.node) = (PGNode *) n; + } + else + (yyval.node) = makeParamRef(0, (yylsp[(1) - (2)])); + ;} + break; + + case 864: +#line 2274 "third_party/libpg_query/grammar/statements/select.y" + { + PGParamRef *p = makeNode(PGParamRef); + p->number = (yyvsp[(1) - (2)].ival); + p->location = (yylsp[(1) - (2)]); + if ((yyvsp[(2) - (2)].list)) + { + PGAIndirection *n = makeNode(PGAIndirection); + n->arg = (PGNode *) p; + n->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); + (yyval.node) = (PGNode *) n; + } + else + (yyval.node) = (PGNode *) p; + ;} + break; + + case 865: +#line 2289 "third_party/libpg_query/grammar/statements/select.y" + { + if ((yyvsp[(4) - (4)].list)) + { + PGAIndirection *n = makeNode(PGAIndirection); + n->arg = (yyvsp[(2) - (4)].node); + n->indirection = check_indirection((yyvsp[(4) - (4)].list), yyscanner); + (yyval.node) = (PGNode *)n; + } + else + (yyval.node) = (yyvsp[(2) - (4)].node); + ;} + break; + + case 866: +#line 2301 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 867: +#line 2303 "third_party/libpg_query/grammar/statements/select.y" + { + if ((yyvsp[(2) - (2)].list)) { + PGAIndirection *n = makeNode(PGAIndirection); + n->arg = (yyvsp[(1) - (2)].node); + n->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); + (yyval.node) = (PGNode *)n; + } + else { + (yyval.node) = (yyvsp[(1) - (2)].node); + } + ;} + break; + + case 868: +#line 2315 "third_party/libpg_query/grammar/statements/select.y" + { + PGSubLink *n = makeNode(PGSubLink); + n->subLinkType = PG_EXPR_SUBLINK; + n->subLinkId = 0; + n->testexpr = NULL; + n->operName = NIL; + n->subselect = (yyvsp[(1) - (1)].node); + n->location = (yylsp[(1) - (1)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 869: +#line 2326 "third_party/libpg_query/grammar/statements/select.y" + { + /* + * Because the select_with_parens nonterminal is designed + * to "eat" as many levels of parens as possible, the + * '(' a_expr ')' opt_indirection production above will + * fail to match a sub-SELECT with indirection decoration; + * the sub-SELECT won't be regarded as an a_expr as long + * as there are parens around it. To support applying + * subscripting or field selection to a sub-SELECT result, + * we need this redundant-looking production. + */ + PGSubLink *n = makeNode(PGSubLink); + PGAIndirection *a = makeNode(PGAIndirection); + n->subLinkType = PG_EXPR_SUBLINK; + n->subLinkId = 0; + n->testexpr = NULL; + n->operName = NIL; + n->subselect = (yyvsp[(1) - (2)].node); + n->location = (yylsp[(1) - (2)]); + a->arg = (PGNode *)n; + a->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); + (yyval.node) = (PGNode *)a; + ;} + break; + + case 870: +#line 2350 "third_party/libpg_query/grammar/statements/select.y" + { + PGSubLink *n = makeNode(PGSubLink); + n->subLinkType = PG_EXISTS_SUBLINK; + n->subLinkId = 0; + n->testexpr = NULL; + n->operName = NIL; + n->subselect = (yyvsp[(2) - (2)].node); + n->location = (yylsp[(1) - (2)]); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 871: +#line 2361 "third_party/libpg_query/grammar/statements/select.y" + { + PGGroupingFunc *g = makeNode(PGGroupingFunc); + g->args = (yyvsp[(3) - (4)].list); + g->location = (yylsp[(1) - (4)]); + (yyval.node) = (PGNode *)g; + ;} + break; + + case 872: +#line 2370 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeFuncCall((yyvsp[(1) - (3)].list), NIL, (yylsp[(1) - (3)])); + ;} + break; + + case 873: +#line 2374 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall((yyvsp[(1) - (6)].list), (yyvsp[(3) - (6)].list), (yylsp[(1) - (6)])); + n->agg_order = (yyvsp[(4) - (6)].list); + n->agg_ignore_nulls = (yyvsp[(5) - (6)].boolean); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 874: +#line 2381 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall((yyvsp[(1) - (7)].list), list_make1((yyvsp[(4) - (7)].node)), (yylsp[(1) - (7)])); + n->func_variadic = true; + n->agg_order = (yyvsp[(5) - (7)].list); + n->agg_ignore_nulls = (yyvsp[(6) - (7)].boolean); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 875: +#line 2389 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall((yyvsp[(1) - (9)].list), lappend((yyvsp[(3) - (9)].list), (yyvsp[(6) - (9)].node)), (yylsp[(1) - (9)])); + n->func_variadic = true; + n->agg_order = (yyvsp[(7) - (9)].list); + n->agg_ignore_nulls = (yyvsp[(8) - (9)].boolean); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 876: +#line 2397 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall((yyvsp[(1) - (7)].list), (yyvsp[(4) - (7)].list), (yylsp[(1) - (7)])); + n->agg_order = (yyvsp[(5) - (7)].list); + n->agg_ignore_nulls = (yyvsp[(6) - (7)].boolean); + /* Ideally we'd mark the PGFuncCall node to indicate + * "must be an aggregate", but there's no provision + * for that in PGFuncCall at the moment. + */ + (yyval.node) = (PGNode *)n; + ;} + break; + + case 877: +#line 2408 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = makeFuncCall((yyvsp[(1) - (7)].list), (yyvsp[(4) - (7)].list), (yylsp[(1) - (7)])); + n->agg_order = (yyvsp[(5) - (7)].list); + n->agg_ignore_nulls = (yyvsp[(6) - (7)].boolean); + n->agg_distinct = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 878: +#line 2416 "third_party/libpg_query/grammar/statements/select.y" + { + /* + * We consider AGGREGATE(*) to invoke a parameterless + * aggregate. This does the right thing for COUNT(*), + * and there are no other aggregates in SQL that accept + * '*' as parameter. + * + * The PGFuncCall node is also marked agg_star = true, + * so that later processing can detect what the argument + * really was. + */ + PGFuncCall *n = makeFuncCall((yyvsp[(1) - (4)].list), NIL, (yylsp[(1) - (4)])); + n->agg_star = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 879: +#line 2444 "third_party/libpg_query/grammar/statements/select.y" + { + PGFuncCall *n = (PGFuncCall *) (yyvsp[(1) - (5)].node); + /* + * The order clause for WITHIN GROUP and the one for + * plain-aggregate ORDER BY share a field, so we have to + * check here that at most one is present. We also check + * for DISTINCT and VARIADIC here to give a better error + * location. Other consistency checks are deferred to + * parse analysis. + */ + if ((yyvsp[(2) - (5)].list) != NIL) + { + if (n->agg_order != NIL) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("cannot use multiple ORDER BY clauses with WITHIN GROUP"), + parser_errposition((yylsp[(2) - (5)])))); + if (n->agg_distinct) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("cannot use DISTINCT with WITHIN GROUP"), + parser_errposition((yylsp[(2) - (5)])))); + if (n->func_variadic) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("cannot use VARIADIC with WITHIN GROUP"), + parser_errposition((yylsp[(2) - (5)])))); + n->agg_order = (yyvsp[(2) - (5)].list); + n->agg_within_group = true; + } + n->agg_filter = (yyvsp[(3) - (5)].node); + n->export_state = (yyvsp[(4) - (5)].boolean); + n->over = (yyvsp[(5) - (5)].windef); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 880: +#line 2480 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 881: +#line 2490 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 882: +#line 2491 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 883: +#line 2499 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("pg_collation_for"), + list_make1((yyvsp[(4) - (5)].node)), + (yylsp[(1) - (5)])); + ;} + break; + + case 884: +#line 2505 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_DATE, -1, (yylsp[(1) - (1)])); + ;} + break; + + case 885: +#line 2509 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_TIME, -1, (yylsp[(1) - (1)])); + ;} + break; + + case 886: +#line 2513 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_TIME_N, (yyvsp[(3) - (4)].ival), (yylsp[(1) - (4)])); + ;} + break; + + case 887: +#line 2517 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_TIMESTAMP, -1, (yylsp[(1) - (1)])); + ;} + break; + + case 888: +#line 2521 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_TIMESTAMP_N, (yyvsp[(3) - (4)].ival), (yylsp[(1) - (4)])); + ;} + break; + + case 889: +#line 2525 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_LOCALTIME, -1, (yylsp[(1) - (1)])); + ;} + break; + + case 890: +#line 2529 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_LOCALTIME_N, (yyvsp[(3) - (4)].ival), (yylsp[(1) - (4)])); + ;} + break; + + case 891: +#line 2533 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_LOCALTIMESTAMP, -1, (yylsp[(1) - (1)])); + ;} + break; + + case 892: +#line 2537 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_LOCALTIMESTAMP_N, (yyvsp[(3) - (4)].ival), (yylsp[(1) - (4)])); + ;} + break; + + case 893: +#line 2541 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_ROLE, -1, (yylsp[(1) - (1)])); + ;} + break; + + case 894: +#line 2545 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_USER, -1, (yylsp[(1) - (1)])); + ;} + break; + + case 895: +#line 2549 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_SESSION_USER, -1, (yylsp[(1) - (1)])); + ;} + break; + + case 896: +#line 2553 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_USER, -1, (yylsp[(1) - (1)])); + ;} + break; + + case 897: +#line 2557 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_CATALOG, -1, (yylsp[(1) - (1)])); + ;} + break; + + case 898: +#line 2561 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_SCHEMA, -1, (yylsp[(1) - (1)])); + ;} + break; + + case 899: +#line 2565 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeTypeCast((yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].typnam), 0, (yylsp[(1) - (6)])); ;} + break; + + case 900: +#line 2567 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = makeTypeCast((yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].typnam), 1, (yylsp[(1) - (6)])); ;} + break; + + case 901: +#line 2569 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("date_part"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); + ;} + break; + + case 902: +#line 2573 "third_party/libpg_query/grammar/statements/select.y" + { + /* overlay(A PLACING B FROM C FOR D) is converted to + * overlay(A, B, C, D) + * overlay(A PLACING B FROM C) is converted to + * overlay(A, B, C) + */ + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("overlay"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); + ;} + break; + + case 903: +#line 2582 "third_party/libpg_query/grammar/statements/select.y" + { + /* position(A in B) is converted to position(B, A) */ + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("position"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); + ;} + break; + + case 904: +#line 2587 "third_party/libpg_query/grammar/statements/select.y" + { + /* substring(A from B for C) is converted to + * substring(A, B, C) - thomas 2000-11-28 + */ + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("substring"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); + ;} + break; + + case 905: +#line 2594 "third_party/libpg_query/grammar/statements/select.y" + { + /* TREAT(expr AS target) converts expr of a particular type to target, + * which is defined to be a subtype of the original expression. + * In SQL99, this is intended for use with structured UDTs, + * but let's make this a generally useful form allowing stronger + * coercions than are handled by implicit casting. + * + * Convert SystemTypeName() to SystemFuncName() even though + * at the moment they result in the same thing. + */ + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName(((PGValue *)llast((yyvsp[(5) - (6)].typnam)->names))->val.str), + list_make1((yyvsp[(3) - (6)].node)), + (yylsp[(1) - (6)])); + ;} + break; + + case 906: +#line 2609 "third_party/libpg_query/grammar/statements/select.y" + { + /* various trim expressions are defined in SQL + * - thomas 1997-07-19 + */ + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("trim"), (yyvsp[(4) - (5)].list), (yylsp[(1) - (5)])); + ;} + break; + + case 907: +#line 2616 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("ltrim"), (yyvsp[(4) - (5)].list), (yylsp[(1) - (5)])); + ;} + break; + + case 908: +#line 2620 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("rtrim"), (yyvsp[(4) - (5)].list), (yylsp[(1) - (5)])); + ;} + break; + + case 909: +#line 2624 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("trim"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); + ;} + break; + + case 910: +#line 2628 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NULLIF, "=", (yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].node), (yylsp[(1) - (6)])); + ;} + break; + + case 911: +#line 2632 "third_party/libpg_query/grammar/statements/select.y" + { + PGCoalesceExpr *c = makeNode(PGCoalesceExpr); + c->args = (yyvsp[(3) - (4)].list); + c->location = (yylsp[(1) - (4)]); + (yyval.node) = (PGNode *)c; + ;} + break; + + case 912: +#line 2645 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(4) - (5)].list); ;} + break; + + case 913: +#line 2646 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 914: +#line 2650 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(4) - (5)].node); ;} + break; + + case 915: +#line 2651 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(3) - (4)].node); ;} + break; + + case 916: +#line 2652 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 917: +#line 2656 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = true; ;} + break; + + case 918: +#line 2657 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.boolean) = false; ;} + break; + + case 919: +#line 2664 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + break; + + case 920: +#line 2665 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 921: +#line 2669 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].windef)); ;} + break; + + case 922: +#line 2671 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].windef)); ;} + break; + + case 923: +#line 2676 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = (yyvsp[(3) - (3)].windef); + n->name = (yyvsp[(1) - (3)].str); + (yyval.windef) = n; + ;} + break; + + case 924: +#line 2684 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.windef) = (yyvsp[(2) - (2)].windef); ;} + break; + + case 925: +#line 2686 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = makeNode(PGWindowDef); + n->name = (yyvsp[(2) - (2)].str); + n->refname = NULL; + n->partitionClause = NIL; + n->orderClause = NIL; + n->frameOptions = FRAMEOPTION_DEFAULTS; + n->startOffset = NULL; + n->endOffset = NULL; + n->location = (yylsp[(2) - (2)]); + (yyval.windef) = n; + ;} + break; + + case 926: +#line 2699 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.windef) = NULL; ;} + break; + + case 927: +#line 2704 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = makeNode(PGWindowDef); + n->name = NULL; + n->refname = (yyvsp[(2) - (6)].str); + n->partitionClause = (yyvsp[(3) - (6)].list); + n->orderClause = (yyvsp[(4) - (6)].list); + /* copy relevant fields of opt_frame_clause */ + n->frameOptions = (yyvsp[(5) - (6)].windef)->frameOptions; + n->startOffset = (yyvsp[(5) - (6)].windef)->startOffset; + n->endOffset = (yyvsp[(5) - (6)].windef)->endOffset; + n->location = (yylsp[(1) - (6)]); + (yyval.windef) = n; + ;} + break; + + case 928: +#line 2729 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 929: +#line 2730 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = NULL; ;} + break; + + case 930: +#line 2733 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(3) - (3)].list); ;} + break; + + case 931: +#line 2734 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 932: +#line 2746 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = (yyvsp[(2) - (2)].windef); + n->frameOptions |= FRAMEOPTION_NONDEFAULT | FRAMEOPTION_RANGE; + (yyval.windef) = n; + ;} + break; + + case 933: +#line 2752 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = (yyvsp[(2) - (2)].windef); + n->frameOptions |= FRAMEOPTION_NONDEFAULT | FRAMEOPTION_ROWS; + (yyval.windef) = n; + ;} + break; + + case 934: +#line 2758 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = makeNode(PGWindowDef); + n->frameOptions = FRAMEOPTION_DEFAULTS; + n->startOffset = NULL; + n->endOffset = NULL; + (yyval.windef) = n; + ;} + break; + + case 935: +#line 2768 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = (yyvsp[(1) - (1)].windef); + /* reject invalid cases */ + if (n->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) + ereport(ERROR, + (errcode(PG_ERRCODE_WINDOWING_ERROR), + errmsg("frame start cannot be UNBOUNDED FOLLOWING"), + parser_errposition((yylsp[(1) - (1)])))); + if (n->frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING) + ereport(ERROR, + (errcode(PG_ERRCODE_WINDOWING_ERROR), + errmsg("frame starting from following row cannot end with current row"), + parser_errposition((yylsp[(1) - (1)])))); + n->frameOptions |= FRAMEOPTION_END_CURRENT_ROW; + (yyval.windef) = n; + ;} + break; + + case 936: +#line 2785 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n1 = (yyvsp[(2) - (4)].windef); + PGWindowDef *n2 = (yyvsp[(4) - (4)].windef); + /* form merged options */ + int frameOptions = n1->frameOptions; + /* shift converts START_ options to END_ options */ + frameOptions |= n2->frameOptions << 1; + frameOptions |= FRAMEOPTION_BETWEEN; + /* reject invalid cases */ + if (frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) + ereport(ERROR, + (errcode(PG_ERRCODE_WINDOWING_ERROR), + errmsg("frame start cannot be UNBOUNDED FOLLOWING"), + parser_errposition((yylsp[(2) - (4)])))); + if (frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING) + ereport(ERROR, + (errcode(PG_ERRCODE_WINDOWING_ERROR), + errmsg("frame end cannot be UNBOUNDED PRECEDING"), + parser_errposition((yylsp[(4) - (4)])))); + if ((frameOptions & FRAMEOPTION_START_CURRENT_ROW) && + (frameOptions & FRAMEOPTION_END_VALUE_PRECEDING)) + ereport(ERROR, + (errcode(PG_ERRCODE_WINDOWING_ERROR), + errmsg("frame starting from current row cannot have preceding rows"), + parser_errposition((yylsp[(4) - (4)])))); + if ((frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING) && + (frameOptions & (FRAMEOPTION_END_VALUE_PRECEDING | + FRAMEOPTION_END_CURRENT_ROW))) + ereport(ERROR, + (errcode(PG_ERRCODE_WINDOWING_ERROR), + errmsg("frame starting from following row cannot have preceding rows"), + parser_errposition((yylsp[(4) - (4)])))); + n1->frameOptions = frameOptions; + n1->endOffset = n2->startOffset; + (yyval.windef) = n1; + ;} + break; + + case 937: +#line 2830 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = makeNode(PGWindowDef); + n->frameOptions = FRAMEOPTION_START_UNBOUNDED_PRECEDING; + n->startOffset = NULL; + n->endOffset = NULL; + (yyval.windef) = n; + ;} + break; + + case 938: +#line 2838 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = makeNode(PGWindowDef); + n->frameOptions = FRAMEOPTION_START_UNBOUNDED_FOLLOWING; + n->startOffset = NULL; + n->endOffset = NULL; + (yyval.windef) = n; + ;} + break; + + case 939: +#line 2846 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = makeNode(PGWindowDef); + n->frameOptions = FRAMEOPTION_START_CURRENT_ROW; + n->startOffset = NULL; + n->endOffset = NULL; + (yyval.windef) = n; + ;} + break; + + case 940: +#line 2854 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = makeNode(PGWindowDef); + n->frameOptions = FRAMEOPTION_START_VALUE_PRECEDING; + n->startOffset = (yyvsp[(1) - (2)].node); + n->endOffset = NULL; + (yyval.windef) = n; + ;} + break; + + case 941: +#line 2862 "third_party/libpg_query/grammar/statements/select.y" + { + PGWindowDef *n = makeNode(PGWindowDef); + n->frameOptions = FRAMEOPTION_START_VALUE_FOLLOWING; + n->startOffset = (yyvsp[(1) - (2)].node); + n->endOffset = NULL; + (yyval.windef) = n; + ;} + break; + + case 942: +#line 2882 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + break; + + case 943: +#line 2883 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 944: +#line 2886 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list);;} + break; + + case 945: +#line 2887 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(2) - (5)].list), (yyvsp[(4) - (5)].node)); ;} + break; + + case 946: +#line 2891 "third_party/libpg_query/grammar/statements/select.y" + { + PGNamedArgExpr *na = makeNode(PGNamedArgExpr); + na->name = (yyvsp[(1) - (3)].str); + na->arg = (PGExpr *) (yyvsp[(3) - (3)].node); + na->argnumber = -1; + na->location = (yylsp[(1) - (3)]); + (yyval.node) = (PGNode *) na; + ;} + break; + + case 947: +#line 2901 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + break; + + case 948: +#line 2902 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} + break; + + case 949: +#line 2906 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 950: +#line 2907 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + break; + + case 951: +#line 2911 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.subquerytype) = PG_ANY_SUBLINK; ;} + break; + + case 952: +#line 2912 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.subquerytype) = PG_ANY_SUBLINK; ;} + break; + + case 953: +#line 2913 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.subquerytype) = PG_ALL_SUBLINK; ;} + break; + + case 954: +#line 2916 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 955: +#line 2917 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) (yyvsp[(1) - (1)].conststr); ;} + break; + + case 956: +#line 2920 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "+"; ;} + break; + + case 957: +#line 2921 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "-"; ;} + break; + + case 958: +#line 2922 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "*"; ;} + break; + + case 959: +#line 2923 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "/"; ;} + break; + + case 960: +#line 2924 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "%"; ;} + break; + + case 961: +#line 2925 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "^"; ;} + break; + + case 962: +#line 2926 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "**"; ;} + break; + + case 963: +#line 2927 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "<"; ;} + break; + + case 964: +#line 2928 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = ">"; ;} + break; + + case 965: +#line 2929 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "="; ;} + break; + + case 966: +#line 2930 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "<="; ;} + break; + + case 967: +#line 2931 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = ">="; ;} + break; + + case 968: +#line 2932 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.conststr) = "<>"; ;} + break; + + case 969: +#line 2936 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + break; + + case 970: +#line 2938 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + break; + + case 971: +#line 2943 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + break; + + case 972: +#line 2945 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + break; + + case 973: +#line 2950 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + break; + + case 974: +#line 2952 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + break; + + case 975: +#line 2954 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString("~~")); ;} + break; + + case 976: +#line 2956 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString("!~~")); ;} + break; + + case 977: +#line 2958 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString("~~~")); ;} + break; + + case 978: +#line 2960 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString("!~~~")); ;} + break; + + case 979: +#line 2962 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString("~~*")); ;} + break; + + case 980: +#line 2964 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString("!~~*")); ;} + break; + + case 981: +#line 2978 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + break; + + case 982: +#line 2980 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lcons(makeString((yyvsp[(1) - (3)].str)), (yyvsp[(3) - (3)].list)); ;} + break; + + case 983: +#line 2984 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); + ;} + break; + + case 984: +#line 2988 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); + ;} + break; + + case 985: +#line 2995 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = (yyvsp[(1) - (1)].list); + ;} + break; + + case 986: +#line 3000 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = (yyvsp[(1) - (2)].list); + ;} + break; + + case 987: +#line 3007 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = (yyvsp[(1) - (1)].list); + ;} + break; + + case 988: +#line 3011 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = NULL; + ;} + break; + + case 989: +#line 3020 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); + ;} + break; + + case 990: +#line 3024 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); + ;} + break; + + case 991: +#line 3030 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (yyvsp[(1) - (1)].node); + ;} + break; + + case 992: +#line 3034 "third_party/libpg_query/grammar/statements/select.y" + { + PGNamedArgExpr *na = makeNode(PGNamedArgExpr); + na->name = (yyvsp[(1) - (3)].str); + na->arg = (PGExpr *) (yyvsp[(3) - (3)].node); + na->argnumber = -1; /* until determined */ + na->location = (yylsp[(1) - (3)]); + (yyval.node) = (PGNode *) na; + ;} + break; + + case 993: +#line 3043 "third_party/libpg_query/grammar/statements/select.y" + { + PGNamedArgExpr *na = makeNode(PGNamedArgExpr); + na->name = (yyvsp[(1) - (3)].str); + na->arg = (PGExpr *) (yyvsp[(3) - (3)].node); + na->argnumber = -1; /* until determined */ + na->location = (yylsp[(1) - (3)]); + (yyval.node) = (PGNode *) na; + ;} + break; + + case 994: +#line 3053 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].typnam)); ;} + break; + + case 995: +#line 3054 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].typnam)); ;} + break; + + case 996: +#line 3059 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make2(makeStringConst((yyvsp[(1) - (3)].str), (yylsp[(1) - (3)])), (yyvsp[(3) - (3)].node)); + ;} + break; + + case 997: +#line 3062 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 998: +#line 3069 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 999: +#line 3070 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "year"; ;} + break; + + case 1000: +#line 3071 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "month"; ;} + break; + + case 1001: +#line 3072 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "day"; ;} + break; + + case 1002: +#line 3073 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "hour"; ;} + break; + + case 1003: +#line 3074 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "minute"; ;} + break; + + case 1004: +#line 3075 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "second"; ;} + break; + + case 1005: +#line 3076 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "millisecond"; ;} + break; + + case 1006: +#line 3077 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (char*) "microsecond"; ;} + break; + + case 1007: +#line 3078 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1008: +#line 3089 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make4((yyvsp[(1) - (4)].node), (yyvsp[(2) - (4)].node), (yyvsp[(3) - (4)].node), (yyvsp[(4) - (4)].node)); + ;} + break; + + case 1009: +#line 3093 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make3((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].node), (yyvsp[(3) - (3)].node)); + ;} + break; + + case 1010: +#line 3100 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + break; + + case 1011: +#line 3106 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make2((yyvsp[(3) - (3)].node), (yyvsp[(1) - (3)].node)); ;} + break; + + case 1012: +#line 3107 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 1013: +#line 3124 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make3((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].node), (yyvsp[(3) - (3)].node)); + ;} + break; + + case 1014: +#line 3128 "third_party/libpg_query/grammar/statements/select.y" + { + /* not legal per SQL99, but might as well allow it */ + (yyval.list) = list_make3((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yyvsp[(2) - (3)].node)); + ;} + break; + + case 1015: +#line 3133 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = list_make2((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); + ;} + break; + + case 1016: +#line 3137 "third_party/libpg_query/grammar/statements/select.y" + { + /* + * Since there are no cases where this syntax allows + * a textual FOR value, we forcibly cast the argument + * to int4. The possible matches in pg_proc are + * substring(text,int4) and substring(text,text), + * and we don't want the parser to choose the latter, + * which it is likely to do if the second argument + * is unknown or doesn't have an implicit cast to int4. + */ + (yyval.list) = list_make3((yyvsp[(1) - (2)].node), makeIntConst(1, -1), + makeTypeCast((yyvsp[(2) - (2)].node), + SystemTypeName("int4"), 0, -1)); + ;} + break; + + case 1017: +#line 3152 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = (yyvsp[(1) - (1)].list); + ;} + break; + + case 1018: +#line 3156 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 1019: +#line 3160 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + break; + + case 1020: +#line 3163 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + break; + + case 1021: +#line 3166 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(3) - (3)].list), (yyvsp[(1) - (3)].node)); ;} + break; + + case 1022: +#line 3167 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + break; + + case 1023: +#line 3168 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 1024: +#line 3172 "third_party/libpg_query/grammar/statements/select.y" + { + PGSubLink *n = makeNode(PGSubLink); + n->subselect = (yyvsp[(1) - (1)].node); + /* other fields will be filled later */ + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1025: +#line 3178 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (PGNode *)(yyvsp[(2) - (3)].list); ;} + break; + + case 1026: +#line 3189 "third_party/libpg_query/grammar/statements/select.y" + { + PGCaseExpr *c = makeNode(PGCaseExpr); + c->casetype = InvalidOid; /* not analyzed yet */ + c->arg = (PGExpr *) (yyvsp[(2) - (5)].node); + c->args = (yyvsp[(3) - (5)].list); + c->defresult = (PGExpr *) (yyvsp[(4) - (5)].node); + c->location = (yylsp[(1) - (5)]); + (yyval.node) = (PGNode *)c; + ;} + break; + + case 1027: +#line 3202 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + break; + + case 1028: +#line 3203 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} + break; + + case 1029: +#line 3208 "third_party/libpg_query/grammar/statements/select.y" + { + PGCaseWhen *w = makeNode(PGCaseWhen); + w->expr = (PGExpr *) (yyvsp[(2) - (4)].node); + w->result = (PGExpr *) (yyvsp[(4) - (4)].node); + w->location = (yylsp[(1) - (4)]); + (yyval.node) = (PGNode *)w; + ;} + break; + + case 1030: +#line 3218 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + break; + + case 1031: +#line 3219 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 1032: +#line 3222 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 1033: +#line 3223 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 1034: +#line 3227 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeColumnRef((yyvsp[(1) - (1)].str), NIL, (yylsp[(1) - (1)]), yyscanner); + ;} + break; + + case 1035: +#line 3231 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeColumnRef((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].list), (yylsp[(1) - (2)]), yyscanner); + ;} + break; + + case 1036: +#line 3238 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = (PGNode *) makeString((yyvsp[(2) - (2)].str)); + ;} + break; + + case 1037: +#line 3242 "third_party/libpg_query/grammar/statements/select.y" + { + PGAIndices *ai = makeNode(PGAIndices); + ai->is_slice = false; + ai->lidx = NULL; + ai->uidx = (yyvsp[(2) - (3)].node); + (yyval.node) = (PGNode *) ai; + ;} + break; + + case 1038: +#line 3250 "third_party/libpg_query/grammar/statements/select.y" + { + PGAIndices *ai = makeNode(PGAIndices); + ai->is_slice = true; + ai->lidx = (yyvsp[(2) - (5)].node); + ai->uidx = (yyvsp[(4) - (5)].node); + (yyval.node) = (PGNode *) ai; + ;} + break; + + case 1039: +#line 3260 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = (yyvsp[(1) - (1)].node); ;} + break; + + case 1040: +#line 3261 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.node) = NULL; ;} + break; + + case 1041: +#line 3265 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + break; + + case 1042: +#line 3266 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} + break; + + case 1043: +#line 3270 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 1044: +#line 3271 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} + break; + + case 1047: +#line 3285 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 1048: +#line 3286 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 1049: +#line 3290 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].target)); ;} + break; + + case 1050: +#line 3291 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].target)); ;} + break; + + case 1051: +#line 3295 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 1052: +#line 3296 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + break; + + case 1053: +#line 3300 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.target) = makeNode(PGResTarget); + (yyval.target)->name = (yyvsp[(3) - (3)].str); + (yyval.target)->indirection = NIL; + (yyval.target)->val = (PGNode *)(yyvsp[(1) - (3)].node); + (yyval.target)->location = (yylsp[(1) - (3)]); + ;} + break; + + case 1054: +#line 3316 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.target) = makeNode(PGResTarget); + (yyval.target)->name = (yyvsp[(2) - (2)].str); + (yyval.target)->indirection = NIL; + (yyval.target)->val = (PGNode *)(yyvsp[(1) - (2)].node); + (yyval.target)->location = (yylsp[(1) - (2)]); + ;} + break; + + case 1055: +#line 3324 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.target) = makeNode(PGResTarget); + (yyval.target)->name = NULL; + (yyval.target)->indirection = NIL; + (yyval.target)->val = (PGNode *)(yyvsp[(1) - (1)].node); + (yyval.target)->location = (yylsp[(1) - (1)]); + ;} + break; + + case 1056: +#line 3332 "third_party/libpg_query/grammar/statements/select.y" + { + PGColumnRef *n = makeNode(PGColumnRef); + PGAStar *star = makeNode(PGAStar); + n->fields = list_make1(star); + n->location = (yylsp[(1) - (3)]); + star->except_list = (yyvsp[(2) - (3)].list); + star->replace_list = (yyvsp[(3) - (3)].list); + + (yyval.target) = makeNode(PGResTarget); + (yyval.target)->name = NULL; + (yyval.target)->indirection = NIL; + (yyval.target)->val = (PGNode *)n; + (yyval.target)->location = (yylsp[(1) - (3)]); + ;} + break; + + case 1057: +#line 3347 "third_party/libpg_query/grammar/statements/select.y" + { + PGColumnRef *n = makeNode(PGColumnRef); + PGAStar *star = makeNode(PGAStar); + n->fields = list_make1(star); + n->location = (yylsp[(1) - (5)]); + star->relation = (yyvsp[(1) - (5)].str); + star->except_list = (yyvsp[(4) - (5)].list); + star->replace_list = (yyvsp[(5) - (5)].list); + + (yyval.target) = makeNode(PGResTarget); + (yyval.target)->name = NULL; + (yyval.target)->indirection = NIL; + (yyval.target)->val = (PGNode *)n; + (yyval.target)->location = (yylsp[(1) - (5)]); + ;} + break; + + case 1058: +#line 3364 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + break; + + case 1059: +#line 3365 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[(2) - (2)].str))); ;} + break; + + case 1060: +#line 3368 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 1061: +#line 3369 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NULL; ;} + break; + + case 1062: +#line 3372 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make2((yyvsp[(1) - (3)].node), makeString((yyvsp[(3) - (3)].str))); ;} + break; + + case 1063: +#line 3376 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].list)); ;} + break; + + case 1064: +#line 3377 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); ;} + break; + + case 1065: +#line 3381 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 1066: +#line 3382 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + break; + + case 1067: +#line 3385 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(3) - (4)].list); ;} + break; + + case 1068: +#line 3386 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(2) - (2)].list)); ;} + break; + + case 1069: +#line 3387 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NULL; ;} + break; + + case 1070: +#line 3397 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].range)); ;} + break; + + case 1071: +#line 3398 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].range)); ;} + break; + + case 1072: +#line 3410 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.range) = makeRangeVar(NULL, (yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); + ;} + break; + + case 1073: +#line 3414 "third_party/libpg_query/grammar/statements/select.y" + { + check_qualified_name((yyvsp[(2) - (2)].list), yyscanner); + (yyval.range) = makeRangeVar(NULL, NULL, (yylsp[(1) - (2)])); + switch (list_length((yyvsp[(2) - (2)].list))) + { + case 1: + (yyval.range)->catalogname = NULL; + (yyval.range)->schemaname = (yyvsp[(1) - (2)].str); + (yyval.range)->relname = strVal(linitial((yyvsp[(2) - (2)].list))); + break; + case 2: + (yyval.range)->catalogname = (yyvsp[(1) - (2)].str); + (yyval.range)->schemaname = strVal(linitial((yyvsp[(2) - (2)].list))); + (yyval.range)->relname = strVal(lsecond((yyvsp[(2) - (2)].list))); + break; + default: + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("improper qualified name (too many dotted names): %s", + NameListToString(lcons(makeString((yyvsp[(1) - (2)].str)), (yyvsp[(2) - (2)].list)))), + parser_errposition((yylsp[(1) - (2)])))); + break; + } + ;} + break; + + case 1074: +#line 3441 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + break; + + case 1075: +#line 3443 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeString((yyvsp[(3) - (3)].str))); ;} + break; + + case 1076: +#line 3448 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (1)].list); ;} + break; + + case 1077: +#line 3449 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(1) - (2)].list); ;} + break; + + case 1078: +#line 3452 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1079: +#line 3454 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1080: +#line 3465 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + break; + + case 1081: +#line 3468 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.list) = check_func_name(lcons(makeString((yyvsp[(1) - (2)].str)), (yyvsp[(2) - (2)].list)), + yyscanner); + ;} + break; + + case 1082: +#line 3479 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeIntConst((yyvsp[(1) - (1)].ival), (yylsp[(1) - (1)])); + ;} + break; + + case 1083: +#line 3483 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeFloatConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); + ;} + break; + + case 1084: +#line 3487 "third_party/libpg_query/grammar/statements/select.y" + { + if ((yyvsp[(2) - (2)].list)) + { + PGAIndirection *n = makeNode(PGAIndirection); + n->arg = makeStringConst((yyvsp[(1) - (2)].str), (yylsp[(1) - (2)])); + n->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); + (yyval.node) = (PGNode *) n; + } + else + (yyval.node) = makeStringConst((yyvsp[(1) - (2)].str), (yylsp[(1) - (2)])); + ;} + break; + + case 1085: +#line 3499 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeBitStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); + ;} + break; + + case 1086: +#line 3503 "third_party/libpg_query/grammar/statements/select.y" + { + /* This is a bit constant per SQL99: + * Without Feature F511, "BIT data type", + * a shall not be a + * or a . + */ + (yyval.node) = makeBitStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); + ;} + break; + + case 1087: +#line 3512 "third_party/libpg_query/grammar/statements/select.y" + { + /* generic type 'literal' syntax */ + PGTypeName *t = makeTypeNameFromNameList((yyvsp[(1) - (2)].list)); + t->location = (yylsp[(1) - (2)]); + (yyval.node) = makeStringConstCast((yyvsp[(2) - (2)].str), (yylsp[(2) - (2)]), t); + ;} + break; + + case 1088: +#line 3519 "third_party/libpg_query/grammar/statements/select.y" + { + /* generic syntax with a type modifier */ + PGTypeName *t = makeTypeNameFromNameList((yyvsp[(1) - (7)].list)); + PGListCell *lc; + + /* + * We must use func_arg_list and opt_sort_clause in the + * production to avoid reduce/reduce conflicts, but we + * don't actually wish to allow PGNamedArgExpr in this + * context, ORDER BY, nor IGNORE NULLS. + */ + foreach(lc, (yyvsp[(3) - (7)].list)) + { + PGNamedArgExpr *arg = (PGNamedArgExpr *) lfirst(lc); + + if (IsA(arg, PGNamedArgExpr)) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("type modifier cannot have parameter name"), + parser_errposition(arg->location))); + } + if ((yyvsp[(4) - (7)].list) != NIL) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("type modifier cannot have ORDER BY"), + parser_errposition((yylsp[(4) - (7)])))); + if ((yyvsp[(5) - (7)].boolean) != false) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("type modifier cannot have IGNORE NULLS"), + parser_errposition((yylsp[(5) - (7)])))); + + + t->typmods = (yyvsp[(3) - (7)].list); + t->location = (yylsp[(1) - (7)]); + (yyval.node) = makeStringConstCast((yyvsp[(7) - (7)].str), (yylsp[(7) - (7)]), t); + ;} + break; + + case 1089: +#line 3557 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeStringConstCast((yyvsp[(2) - (2)].str), (yylsp[(2) - (2)]), (yyvsp[(1) - (2)].typnam)); + ;} + break; + + case 1090: +#line 3561 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeIntervalNode((yyvsp[(3) - (5)].node), (yylsp[(3) - (5)]), (yyvsp[(5) - (5)].list)); + ;} + break; + + case 1091: +#line 3565 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeIntervalNode((yyvsp[(2) - (3)].ival), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].list)); + ;} + break; + + case 1092: +#line 3569 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeIntervalNode((yyvsp[(2) - (3)].str), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].list)); + ;} + break; + + case 1093: +#line 3573 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeBoolAConst(true, (yylsp[(1) - (1)])); + ;} + break; + + case 1094: +#line 3577 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeBoolAConst(false, (yylsp[(1) - (1)])); + ;} + break; + + case 1095: +#line 3581 "third_party/libpg_query/grammar/statements/select.y" + { + (yyval.node) = makeNullAConst((yylsp[(1) - (1)])); + ;} + break; + + case 1096: +#line 3586 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;} + break; + + case 1097: +#line 3587 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1098: +#line 3603 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1099: +#line 3604 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + break; + + case 1100: +#line 3605 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + break; + + case 1101: +#line 3608 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1102: +#line 3609 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1103: +#line 3615 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1104: +#line 3616 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + break; + + case 1105: +#line 3617 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + break; + + case 1106: +#line 3620 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1107: +#line 3621 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + break; + + case 1108: +#line 3622 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + break; + + case 1109: +#line 3625 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1110: +#line 3626 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + break; + + case 1111: +#line 3627 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + break; + + case 1112: +#line 3630 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} + break; + + case 1113: +#line 3631 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lcons(makeString((yyvsp[(1) - (2)].str)), (yyvsp[(2) - (2)].list)); ;} + break; + + case 1114: +#line 3635 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = list_make1(makeString((yyvsp[(2) - (2)].str))); ;} + break; + + case 1115: +#line 3637 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeString((yyvsp[(3) - (3)].str))); ;} + break; + + case 1116: +#line 3641 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + break; + + case 1117: +#line 3642 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.list) = NIL; ;} + break; + + case 1119: +#line 3653 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1120: +#line 3654 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + break; + + case 1121: +#line 3655 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + break; + + case 1122: +#line 3656 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + break; + + case 1123: +#line 3659 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1124: +#line 3660 "third_party/libpg_query/grammar/statements/select.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1125: +#line 8 "third_party/libpg_query/grammar/statements/prepare.y" + { + PGPrepareStmt *n = makeNode(PGPrepareStmt); + n->name = (yyvsp[(2) - (5)].str); + n->argtypes = (yyvsp[(3) - (5)].list); + n->query = (yyvsp[(5) - (5)].node); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1126: +#line 18 "third_party/libpg_query/grammar/statements/prepare.y" + { (yyval.list) = (yyvsp[(2) - (3)].list); ;} + break; + + case 1127: +#line 19 "third_party/libpg_query/grammar/statements/prepare.y" + { (yyval.list) = NIL; ;} + break; + + case 1132: +#line 8 "third_party/libpg_query/grammar/statements/create_schema.y" + { + PGCreateSchemaStmt *n = makeNode(PGCreateSchemaStmt); + /* ...but not both */ + n->schemaname = (yyvsp[(3) - (4)].str); + n->schemaElts = (yyvsp[(4) - (4)].list); + n->onconflict = PG_ERROR_ON_CONFLICT; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1133: +#line 17 "third_party/libpg_query/grammar/statements/create_schema.y" + { + PGCreateSchemaStmt *n = makeNode(PGCreateSchemaStmt); + /* ...but not here */ + n->schemaname = (yyvsp[(6) - (7)].str); + if ((yyvsp[(7) - (7)].list) != NIL) + ereport(ERROR, + (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("CREATE SCHEMA IF NOT EXISTS cannot include schema elements"), + parser_errposition((yylsp[(7) - (7)])))); + n->schemaElts = (yyvsp[(7) - (7)].list); + n->onconflict = PG_IGNORE_ON_CONFLICT; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1134: +#line 35 "third_party/libpg_query/grammar/statements/create_schema.y" + { + if ((yyloc) < 0) /* see comments for YYLLOC_DEFAULT */ + (yyloc) = (yylsp[(2) - (2)]); + (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); + ;} + break; + + case 1135: +#line 41 "third_party/libpg_query/grammar/statements/create_schema.y" + { (yyval.list) = NIL; ;} + break; + + case 1140: +#line 11 "third_party/libpg_query/grammar/statements/index.y" + { + PGIndexStmt *n = makeNode(PGIndexStmt); + n->unique = (yyvsp[(2) - (13)].boolean); + n->concurrent = (yyvsp[(4) - (13)].boolean); + n->idxname = (yyvsp[(5) - (13)].str); + n->relation = (yyvsp[(7) - (13)].range); + n->accessMethod = (yyvsp[(8) - (13)].str); + n->indexParams = (yyvsp[(10) - (13)].list); + n->options = (yyvsp[(12) - (13)].list); + n->whereClause = (yyvsp[(13) - (13)].node); + n->excludeOpNames = NIL; + n->idxcomment = NULL; + n->indexOid = InvalidOid; + n->oldNode = InvalidOid; + n->primary = false; + n->isconstraint = false; + n->deferrable = false; + n->initdeferred = false; + n->transformed = false; + n->onconflict = PG_ERROR_ON_CONFLICT; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1141: +#line 36 "third_party/libpg_query/grammar/statements/index.y" + { + PGIndexStmt *n = makeNode(PGIndexStmt); + n->unique = (yyvsp[(2) - (16)].boolean); + n->concurrent = (yyvsp[(4) - (16)].boolean); + n->idxname = (yyvsp[(8) - (16)].str); + n->relation = (yyvsp[(10) - (16)].range); + n->accessMethod = (yyvsp[(11) - (16)].str); + n->indexParams = (yyvsp[(13) - (16)].list); + n->options = (yyvsp[(15) - (16)].list); + n->whereClause = (yyvsp[(16) - (16)].node); + n->excludeOpNames = NIL; + n->idxcomment = NULL; + n->indexOid = InvalidOid; + n->oldNode = InvalidOid; + n->primary = false; + n->isconstraint = false; + n->deferrable = false; + n->initdeferred = false; + n->transformed = false; + n->onconflict = PG_IGNORE_ON_CONFLICT; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1142: +#line 62 "third_party/libpg_query/grammar/statements/index.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1143: +#line 66 "third_party/libpg_query/grammar/statements/index.y" + { (yyval.str) = (yyvsp[(2) - (2)].str); ;} + break; + + case 1144: +#line 67 "third_party/libpg_query/grammar/statements/index.y" + { (yyval.str) = (char*) DEFAULT_INDEX_TYPE; ;} + break; + + case 1145: +#line 72 "third_party/libpg_query/grammar/statements/index.y" + { (yyval.boolean) = true; ;} + break; + + case 1146: +#line 73 "third_party/libpg_query/grammar/statements/index.y" + { (yyval.boolean) = false; ;} + break; + + case 1147: +#line 78 "third_party/libpg_query/grammar/statements/index.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1148: +#line 79 "third_party/libpg_query/grammar/statements/index.y" + { (yyval.str) = NULL; ;} + break; + + case 1149: +#line 83 "third_party/libpg_query/grammar/statements/index.y" + { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + break; + + case 1150: +#line 84 "third_party/libpg_query/grammar/statements/index.y" + { (yyval.list) = NIL; ;} + break; + + case 1151: +#line 89 "third_party/libpg_query/grammar/statements/index.y" + { (yyval.boolean) = true; ;} + break; + + case 1152: +#line 90 "third_party/libpg_query/grammar/statements/index.y" + { (yyval.boolean) = false; ;} + break; + + case 1153: +#line 8 "third_party/libpg_query/grammar/statements/alter_schema.y" + { + PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); + n->objectType = PG_OBJECT_TABLE; + n->relation = (yyvsp[(3) - (6)].range); + n->newschema = (yyvsp[(6) - (6)].str); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1154: +#line 17 "third_party/libpg_query/grammar/statements/alter_schema.y" + { + PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); + n->objectType = PG_OBJECT_TABLE; + n->relation = (yyvsp[(5) - (8)].range); + n->newschema = (yyvsp[(8) - (8)].str); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1155: +#line 26 "third_party/libpg_query/grammar/statements/alter_schema.y" + { + PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); + n->objectType = PG_OBJECT_SEQUENCE; + n->relation = (yyvsp[(3) - (6)].range); + n->newschema = (yyvsp[(6) - (6)].str); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1156: +#line 35 "third_party/libpg_query/grammar/statements/alter_schema.y" + { + PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); + n->objectType = PG_OBJECT_SEQUENCE; + n->relation = (yyvsp[(5) - (8)].range); + n->newschema = (yyvsp[(8) - (8)].str); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1157: +#line 44 "third_party/libpg_query/grammar/statements/alter_schema.y" + { + PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); + n->objectType = PG_OBJECT_VIEW; + n->relation = (yyvsp[(3) - (6)].range); + n->newschema = (yyvsp[(6) - (6)].str); + n->missing_ok = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1158: +#line 53 "third_party/libpg_query/grammar/statements/alter_schema.y" + { + PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); + n->objectType = PG_OBJECT_VIEW; + n->relation = (yyvsp[(5) - (8)].range); + n->newschema = (yyvsp[(8) - (8)].str); + n->missing_ok = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1159: +#line 6 "third_party/libpg_query/grammar/statements/checkpoint.y" + { + PGCheckPointStmt *n = makeNode(PGCheckPointStmt); + n->force = true; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1160: +#line 12 "third_party/libpg_query/grammar/statements/checkpoint.y" + { + PGCheckPointStmt *n = makeNode(PGCheckPointStmt); + n->force = false; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1161: +#line 8 "third_party/libpg_query/grammar/statements/export.y" + { + PGExportStmt *n = makeNode(PGExportStmt); + n->filename = (yyvsp[(3) - (4)].str); + n->options = NIL; + if ((yyvsp[(4) - (4)].list)) { + n->options = list_concat(n->options, (yyvsp[(4) - (4)].list)); + } + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1162: +#line 21 "third_party/libpg_query/grammar/statements/export.y" + { + PGImportStmt *n = makeNode(PGImportStmt); + n->filename = (yyvsp[(3) - (3)].str); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1163: +#line 10 "third_party/libpg_query/grammar/statements/explain.y" + { + PGExplainStmt *n = makeNode(PGExplainStmt); + n->query = (yyvsp[(2) - (2)].node); + n->options = NIL; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1164: +#line 17 "third_party/libpg_query/grammar/statements/explain.y" + { + PGExplainStmt *n = makeNode(PGExplainStmt); + n->query = (yyvsp[(4) - (4)].node); + n->options = list_make1(makeDefElem("analyze", NULL, (yylsp[(2) - (4)]))); + if ((yyvsp[(3) - (4)].boolean)) + n->options = lappend(n->options, + makeDefElem("verbose", NULL, (yylsp[(3) - (4)]))); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1165: +#line 27 "third_party/libpg_query/grammar/statements/explain.y" + { + PGExplainStmt *n = makeNode(PGExplainStmt); + n->query = (yyvsp[(3) - (3)].node); + n->options = list_make1(makeDefElem("verbose", NULL, (yylsp[(2) - (3)]))); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1166: +#line 34 "third_party/libpg_query/grammar/statements/explain.y" + { + PGExplainStmt *n = makeNode(PGExplainStmt); + n->query = (yyvsp[(5) - (5)].node); + n->options = (yyvsp[(3) - (5)].list); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1167: +#line 44 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.boolean) = true; ;} + break; + + case 1168: +#line 45 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.boolean) = false; ;} + break; + + case 1169: +#line 50 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); ;} + break; + + case 1170: +#line 51 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.node) = (PGNode *) (yyvsp[(1) - (1)].value); ;} + break; + + case 1171: +#line 52 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.node) = NULL; ;} + break; + + case 1202: +#line 90 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1203: +#line 91 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + break; + + case 1204: +#line 92 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} + break; + + case 1205: +#line 97 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1206: +#line 98 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1207: +#line 104 "third_party/libpg_query/grammar/statements/explain.y" + { + (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); + ;} + break; + + case 1208: +#line 108 "third_party/libpg_query/grammar/statements/explain.y" + { + (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); + ;} + break; + + case 1209: +#line 115 "third_party/libpg_query/grammar/statements/explain.y" + {;} + break; + + case 1210: +#line 116 "third_party/libpg_query/grammar/statements/explain.y" + {;} + break; + + case 1211: +#line 121 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = (char*) "true"; ;} + break; + + case 1212: +#line 122 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = (char*) "false"; ;} + break; + + case 1213: +#line 123 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = (char*) "on"; ;} + break; + + case 1214: +#line 129 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1215: +#line 135 "third_party/libpg_query/grammar/statements/explain.y" + { + (yyval.defelt) = makeDefElem((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); + ;} + break; + + case 1216: +#line 142 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1217: +#line 143 "third_party/libpg_query/grammar/statements/explain.y" + { (yyval.str) = (char*) "analyze"; ;} + break; + + case 1218: +#line 11 "third_party/libpg_query/grammar/statements/variable_set.y" + { + PGVariableSetStmt *n = (yyvsp[(2) - (2)].vsetstmt); + n->scope = VAR_SET_SCOPE_DEFAULT; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1219: +#line 17 "third_party/libpg_query/grammar/statements/variable_set.y" + { + PGVariableSetStmt *n = (yyvsp[(3) - (3)].vsetstmt); + n->scope = VAR_SET_SCOPE_LOCAL; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1220: +#line 23 "third_party/libpg_query/grammar/statements/variable_set.y" + { + PGVariableSetStmt *n = (yyvsp[(3) - (3)].vsetstmt); + n->scope = VAR_SET_SCOPE_SESSION; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1221: +#line 29 "third_party/libpg_query/grammar/statements/variable_set.y" + { + PGVariableSetStmt *n = (yyvsp[(3) - (3)].vsetstmt); + n->scope = VAR_SET_SCOPE_GLOBAL; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1222: +#line 38 "third_party/libpg_query/grammar/statements/variable_set.y" + {(yyval.vsetstmt) = (yyvsp[(1) - (1)].vsetstmt);;} + break; + + case 1223: +#line 40 "third_party/libpg_query/grammar/statements/variable_set.y" + { + PGVariableSetStmt *n = makeNode(PGVariableSetStmt); + n->kind = VAR_SET_CURRENT; + n->name = (yyvsp[(1) - (3)].str); + (yyval.vsetstmt) = n; + ;} + break; + + case 1224: +#line 48 "third_party/libpg_query/grammar/statements/variable_set.y" + { + PGVariableSetStmt *n = makeNode(PGVariableSetStmt); + n->kind = VAR_SET_VALUE; + n->name = (char*) "timezone"; + if ((yyvsp[(3) - (3)].node) != NULL) + n->args = list_make1((yyvsp[(3) - (3)].node)); + else + n->kind = VAR_SET_DEFAULT; + (yyval.vsetstmt) = n; + ;} + break; + + case 1225: +#line 59 "third_party/libpg_query/grammar/statements/variable_set.y" + { + PGVariableSetStmt *n = makeNode(PGVariableSetStmt); + n->kind = VAR_SET_VALUE; + n->name = (char*) "search_path"; + n->args = list_make1(makeStringConst((yyvsp[(2) - (2)].str), (yylsp[(2) - (2)]))); + (yyval.vsetstmt) = n; + ;} + break; + + case 1226: +#line 71 "third_party/libpg_query/grammar/statements/variable_set.y" + { + PGVariableSetStmt *n = makeNode(PGVariableSetStmt); + n->kind = VAR_SET_VALUE; + n->name = (yyvsp[(1) - (3)].str); + n->args = (yyvsp[(3) - (3)].list); + (yyval.vsetstmt) = n; + ;} + break; + + case 1227: +#line 79 "third_party/libpg_query/grammar/statements/variable_set.y" + { + PGVariableSetStmt *n = makeNode(PGVariableSetStmt); + n->kind = VAR_SET_VALUE; + n->name = (yyvsp[(1) - (3)].str); + n->args = (yyvsp[(3) - (3)].list); + (yyval.vsetstmt) = n; + ;} + break; + + case 1228: +#line 87 "third_party/libpg_query/grammar/statements/variable_set.y" + { + PGVariableSetStmt *n = makeNode(PGVariableSetStmt); + n->kind = VAR_SET_DEFAULT; + n->name = (yyvsp[(1) - (3)].str); + (yyval.vsetstmt) = n; + ;} + break; + + case 1229: +#line 94 "third_party/libpg_query/grammar/statements/variable_set.y" + { + PGVariableSetStmt *n = makeNode(PGVariableSetStmt); + n->kind = VAR_SET_DEFAULT; + n->name = (yyvsp[(1) - (3)].str); + (yyval.vsetstmt) = n; + ;} + break; + + case 1230: +#line 104 "third_party/libpg_query/grammar/statements/variable_set.y" + { (yyval.node) = makeStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); ;} + break; + + case 1231: +#line 106 "third_party/libpg_query/grammar/statements/variable_set.y" + { (yyval.node) = makeAConst((yyvsp[(1) - (1)].value), (yylsp[(1) - (1)])); ;} + break; + + case 1232: +#line 112 "third_party/libpg_query/grammar/statements/variable_set.y" + { + (yyval.node) = makeStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); + ;} + break; + + case 1233: +#line 116 "third_party/libpg_query/grammar/statements/variable_set.y" + { + (yyval.node) = makeStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); + ;} + break; + + case 1234: +#line 120 "third_party/libpg_query/grammar/statements/variable_set.y" + { + PGTypeName *t = (yyvsp[(1) - (3)].typnam); + if ((yyvsp[(3) - (3)].list) != NIL) + { + PGAConst *n = (PGAConst *) linitial((yyvsp[(3) - (3)].list)); + if ((n->val.val.ival & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("time zone interval must be HOUR or HOUR TO MINUTE"), + parser_errposition((yylsp[(3) - (3)])))); + } + t->typmods = (yyvsp[(3) - (3)].list); + (yyval.node) = makeStringConstCast((yyvsp[(2) - (3)].str), (yylsp[(2) - (3)]), t); + ;} + break; + + case 1235: +#line 135 "third_party/libpg_query/grammar/statements/variable_set.y" + { + PGTypeName *t = (yyvsp[(1) - (5)].typnam); + t->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1), + makeIntConst((yyvsp[(3) - (5)].ival), (yylsp[(3) - (5)]))); + (yyval.node) = makeStringConstCast((yyvsp[(5) - (5)].str), (yylsp[(5) - (5)]), t); + ;} + break; + + case 1236: +#line 141 "third_party/libpg_query/grammar/statements/variable_set.y" + { (yyval.node) = makeAConst((yyvsp[(1) - (1)].value), (yylsp[(1) - (1)])); ;} + break; + + case 1237: +#line 142 "third_party/libpg_query/grammar/statements/variable_set.y" + { (yyval.node) = NULL; ;} + break; + + case 1238: +#line 143 "third_party/libpg_query/grammar/statements/variable_set.y" + { (yyval.node) = NULL; ;} + break; + + case 1239: +#line 147 "third_party/libpg_query/grammar/statements/variable_set.y" + { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} + break; + + case 1240: +#line 148 "third_party/libpg_query/grammar/statements/variable_set.y" + { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} + break; + + case 1241: +#line 8 "third_party/libpg_query/grammar/statements/load.y" + { + PGLoadStmt *n = makeNode(PGLoadStmt); + n->filename = (yyvsp[(2) - (2)].str); + n->load_type = PG_LOAD_TYPE_LOAD; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1242: +#line 14 "third_party/libpg_query/grammar/statements/load.y" + { + PGLoadStmt *n = makeNode(PGLoadStmt); + n->filename = (yyvsp[(2) - (2)].str); + n->load_type = PG_LOAD_TYPE_INSTALL; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1243: +#line 20 "third_party/libpg_query/grammar/statements/load.y" + { + PGLoadStmt *n = makeNode(PGLoadStmt); + n->filename = (yyvsp[(3) - (3)].str); + n->load_type = PG_LOAD_TYPE_FORCE_INSTALL; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1244: +#line 28 "third_party/libpg_query/grammar/statements/load.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1245: +#line 29 "third_party/libpg_query/grammar/statements/load.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1246: +#line 9 "third_party/libpg_query/grammar/statements/vacuum.y" + { + PGVacuumStmt *n = makeNode(PGVacuumStmt); + n->options = PG_VACOPT_VACUUM; + if ((yyvsp[(2) - (4)].boolean)) + n->options |= PG_VACOPT_FULL; + if ((yyvsp[(3) - (4)].boolean)) + n->options |= PG_VACOPT_FREEZE; + if ((yyvsp[(4) - (4)].boolean)) + n->options |= PG_VACOPT_VERBOSE; + n->relation = NULL; + n->va_cols = NIL; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1247: +#line 23 "third_party/libpg_query/grammar/statements/vacuum.y" + { + PGVacuumStmt *n = makeNode(PGVacuumStmt); + n->options = PG_VACOPT_VACUUM; + if ((yyvsp[(2) - (5)].boolean)) + n->options |= PG_VACOPT_FULL; + if ((yyvsp[(3) - (5)].boolean)) + n->options |= PG_VACOPT_FREEZE; + if ((yyvsp[(4) - (5)].boolean)) + n->options |= PG_VACOPT_VERBOSE; + n->relation = (yyvsp[(5) - (5)].range); + n->va_cols = NIL; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1248: +#line 37 "third_party/libpg_query/grammar/statements/vacuum.y" + { + PGVacuumStmt *n = (PGVacuumStmt *) (yyvsp[(5) - (5)].node); + n->options |= PG_VACOPT_VACUUM; + if ((yyvsp[(2) - (5)].boolean)) + n->options |= PG_VACOPT_FULL; + if ((yyvsp[(3) - (5)].boolean)) + n->options |= PG_VACOPT_FREEZE; + if ((yyvsp[(4) - (5)].boolean)) + n->options |= PG_VACOPT_VERBOSE; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1249: +#line 49 "third_party/libpg_query/grammar/statements/vacuum.y" + { + PGVacuumStmt *n = makeNode(PGVacuumStmt); + n->options = PG_VACOPT_VACUUM | (yyvsp[(3) - (4)].ival); + n->relation = NULL; + n->va_cols = NIL; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1250: +#line 57 "third_party/libpg_query/grammar/statements/vacuum.y" + { + PGVacuumStmt *n = makeNode(PGVacuumStmt); + n->options = PG_VACOPT_VACUUM | (yyvsp[(3) - (6)].ival); + n->relation = (yyvsp[(5) - (6)].range); + n->va_cols = (yyvsp[(6) - (6)].list); + if (n->va_cols != NIL) /* implies analyze */ + n->options |= PG_VACOPT_ANALYZE; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1251: +#line 70 "third_party/libpg_query/grammar/statements/vacuum.y" + { (yyval.ival) = PG_VACOPT_ANALYZE; ;} + break; + + case 1252: +#line 71 "third_party/libpg_query/grammar/statements/vacuum.y" + { (yyval.ival) = PG_VACOPT_VERBOSE; ;} + break; + + case 1253: +#line 72 "third_party/libpg_query/grammar/statements/vacuum.y" + { (yyval.ival) = PG_VACOPT_FREEZE; ;} + break; + + case 1254: +#line 73 "third_party/libpg_query/grammar/statements/vacuum.y" + { (yyval.ival) = PG_VACOPT_FULL; ;} + break; + + case 1255: +#line 75 "third_party/libpg_query/grammar/statements/vacuum.y" + { + if (strcmp((yyvsp[(1) - (1)].str), "disable_page_skipping") == 0) + (yyval.ival) = PG_VACOPT_DISABLE_PAGE_SKIPPING; + else + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("unrecognized VACUUM option \"%s\"", (yyvsp[(1) - (1)].str)), + parser_errposition((yylsp[(1) - (1)])))); + ;} + break; + + case 1256: +#line 87 "third_party/libpg_query/grammar/statements/vacuum.y" + { (yyval.boolean) = true; ;} + break; + + case 1257: +#line 88 "third_party/libpg_query/grammar/statements/vacuum.y" + { (yyval.boolean) = false; ;} + break; + + case 1258: +#line 93 "third_party/libpg_query/grammar/statements/vacuum.y" + { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;} + break; + + case 1259: +#line 94 "third_party/libpg_query/grammar/statements/vacuum.y" + { (yyval.ival) = (yyvsp[(1) - (3)].ival) | (yyvsp[(3) - (3)].ival); ;} + break; + + case 1260: +#line 98 "third_party/libpg_query/grammar/statements/vacuum.y" + { (yyval.boolean) = true; ;} + break; + + case 1261: +#line 99 "third_party/libpg_query/grammar/statements/vacuum.y" + { (yyval.boolean) = false; ;} + break; + + case 1262: +#line 9 "third_party/libpg_query/grammar/statements/delete.y" + { + PGDeleteStmt *n = makeNode(PGDeleteStmt); + n->relation = (yyvsp[(4) - (7)].range); + n->usingClause = (yyvsp[(5) - (7)].list); + n->whereClause = (yyvsp[(6) - (7)].node); + n->returningList = (yyvsp[(7) - (7)].list); + n->withClause = (yyvsp[(1) - (7)].with); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1263: +#line 22 "third_party/libpg_query/grammar/statements/delete.y" + { + (yyval.range) = (yyvsp[(1) - (1)].range); + ;} + break; + + case 1264: +#line 26 "third_party/libpg_query/grammar/statements/delete.y" + { + PGAlias *alias = makeNode(PGAlias); + alias->aliasname = (yyvsp[(2) - (2)].str); + (yyvsp[(1) - (2)].range)->alias = alias; + (yyval.range) = (yyvsp[(1) - (2)].range); + ;} + break; + + case 1265: +#line 33 "third_party/libpg_query/grammar/statements/delete.y" + { + PGAlias *alias = makeNode(PGAlias); + alias->aliasname = (yyvsp[(3) - (3)].str); + (yyvsp[(1) - (3)].range)->alias = alias; + (yyval.range) = (yyvsp[(1) - (3)].range); + ;} + break; + + case 1266: +#line 43 "third_party/libpg_query/grammar/statements/delete.y" + { (yyval.node) = (yyvsp[(2) - (2)].node); ;} + break; + + case 1267: +#line 44 "third_party/libpg_query/grammar/statements/delete.y" + { (yyval.node) = NULL; ;} + break; + + case 1268: +#line 50 "third_party/libpg_query/grammar/statements/delete.y" + { (yyval.list) = (yyvsp[(2) - (2)].list); ;} + break; + + case 1269: +#line 51 "third_party/libpg_query/grammar/statements/delete.y" + { (yyval.list) = NIL; ;} + break; + + case 1270: +#line 10 "third_party/libpg_query/grammar/statements/analyze.y" + { + PGVacuumStmt *n = makeNode(PGVacuumStmt); + n->options = PG_VACOPT_ANALYZE; + if ((yyvsp[(2) - (2)].boolean)) + n->options |= PG_VACOPT_VERBOSE; + n->relation = NULL; + n->va_cols = NIL; + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1271: +#line 20 "third_party/libpg_query/grammar/statements/analyze.y" + { + PGVacuumStmt *n = makeNode(PGVacuumStmt); + n->options = PG_VACOPT_ANALYZE; + if ((yyvsp[(2) - (4)].boolean)) + n->options |= PG_VACOPT_VERBOSE; + n->relation = (yyvsp[(3) - (4)].range); + n->va_cols = (yyvsp[(4) - (4)].list); + (yyval.node) = (PGNode *)n; + ;} + break; + + case 1272: +#line 2 "third_party/libpg_query/grammar/statements/variable_reset.y" + { (yyval.node) = (PGNode *) (yyvsp[(2) - (2)].vsetstmt); ;} + break; + + case 1273: +#line 8 "third_party/libpg_query/grammar/statements/variable_reset.y" + { + PGVariableSetStmt *n = makeNode(PGVariableSetStmt); + n->kind = VAR_RESET; + n->name = (yyvsp[(1) - (1)].str); + (yyval.vsetstmt) = n; + ;} + break; + + case 1274: +#line 15 "third_party/libpg_query/grammar/statements/variable_reset.y" + { + PGVariableSetStmt *n = makeNode(PGVariableSetStmt); + n->kind = VAR_RESET_ALL; + (yyval.vsetstmt) = n; + ;} + break; + + case 1275: +#line 24 "third_party/libpg_query/grammar/statements/variable_reset.y" + { (yyval.vsetstmt) = (yyvsp[(1) - (1)].vsetstmt); ;} + break; + + case 1276: +#line 26 "third_party/libpg_query/grammar/statements/variable_reset.y" + { + PGVariableSetStmt *n = makeNode(PGVariableSetStmt); + n->kind = VAR_RESET; + n->name = (char*) "timezone"; + (yyval.vsetstmt) = n; + ;} + break; + + case 1277: +#line 33 "third_party/libpg_query/grammar/statements/variable_reset.y" + { + PGVariableSetStmt *n = makeNode(PGVariableSetStmt); + n->kind = VAR_RESET; + n->name = (char*) "transaction_isolation"; + (yyval.vsetstmt) = n; + ;} + break; + + case 1278: +#line 3 "third_party/libpg_query/grammar/statements/variable_show.y" + { + PGVariableShowSelectStmt *n = makeNode(PGVariableShowSelectStmt); + n->stmt = (yyvsp[(2) - (2)].node); + n->name = (char*) "select"; + n->is_summary = 0; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1279: +#line 10 "third_party/libpg_query/grammar/statements/variable_show.y" + { + PGVariableShowSelectStmt *n = makeNode(PGVariableShowSelectStmt); + n->stmt = (yyvsp[(2) - (2)].node); + n->name = (char*) "select"; + n->is_summary = 1; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1280: +#line 18 "third_party/libpg_query/grammar/statements/variable_show.y" + { + PGVariableShowStmt *n = makeNode(PGVariableShowStmt); + n->name = (yyvsp[(2) - (2)].str); + n->is_summary = 1; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1281: +#line 25 "third_party/libpg_query/grammar/statements/variable_show.y" + { + PGVariableShowStmt *n = makeNode(PGVariableShowStmt); + n->name = (yyvsp[(2) - (2)].str); + n->is_summary = 0; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1282: +#line 32 "third_party/libpg_query/grammar/statements/variable_show.y" + { + PGVariableShowStmt *n = makeNode(PGVariableShowStmt); + n->name = (char*) "timezone"; + n->is_summary = 0; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1283: +#line 39 "third_party/libpg_query/grammar/statements/variable_show.y" + { + PGVariableShowStmt *n = makeNode(PGVariableShowStmt); + n->name = (char*) "transaction_isolation"; + n->is_summary = 0; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1284: +#line 46 "third_party/libpg_query/grammar/statements/variable_show.y" + { + PGVariableShowStmt *n = makeNode(PGVariableShowStmt); + n->name = (char*) "__show_tables_expanded"; + n->is_summary = 0; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1285: +#line 53 "third_party/libpg_query/grammar/statements/variable_show.y" + { + PGVariableShowStmt *n = makeNode(PGVariableShowStmt); + n->name = (char*) "__show_tables_expanded"; + n->is_summary = 0; + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1288: +#line 63 "third_party/libpg_query/grammar/statements/variable_show.y" + { (yyval.str) = (yyvsp[(1) - (1)].str); ;} + break; + + case 1289: +#line 65 "third_party/libpg_query/grammar/statements/variable_show.y" + { (yyval.str) = psprintf("%s.%s", (yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str)); ;} + break; + + case 1290: +#line 7 "third_party/libpg_query/grammar/statements/call.y" + { + PGCallStmt *n = makeNode(PGCallStmt); + n->func = (yyvsp[(2) - (2)].node); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1291: +#line 10 "third_party/libpg_query/grammar/statements/view.y" + { + PGViewStmt *n = makeNode(PGViewStmt); + n->view = (yyvsp[(4) - (9)].range); + n->view->relpersistence = (yyvsp[(2) - (9)].ival); + n->aliases = (yyvsp[(5) - (9)].list); + n->query = (yyvsp[(8) - (9)].node); + n->onconflict = PG_ERROR_ON_CONFLICT; + n->options = (yyvsp[(6) - (9)].list); + n->withCheckOption = (yyvsp[(9) - (9)].viewcheckoption); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1292: +#line 23 "third_party/libpg_query/grammar/statements/view.y" + { + PGViewStmt *n = makeNode(PGViewStmt); + n->view = (yyvsp[(6) - (11)].range); + n->view->relpersistence = (yyvsp[(4) - (11)].ival); + n->aliases = (yyvsp[(7) - (11)].list); + n->query = (yyvsp[(10) - (11)].node); + n->onconflict = PG_REPLACE_ON_CONFLICT; + n->options = (yyvsp[(8) - (11)].list); + n->withCheckOption = (yyvsp[(11) - (11)].viewcheckoption); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1293: +#line 36 "third_party/libpg_query/grammar/statements/view.y" + { + PGViewStmt *n = makeNode(PGViewStmt); + n->view = (yyvsp[(5) - (12)].range); + n->view->relpersistence = (yyvsp[(2) - (12)].ival); + n->aliases = (yyvsp[(7) - (12)].list); + n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, (yyvsp[(11) - (12)].node)); + n->onconflict = PG_ERROR_ON_CONFLICT; + n->options = (yyvsp[(9) - (12)].list); + n->withCheckOption = (yyvsp[(12) - (12)].viewcheckoption); + if (n->withCheckOption != PG_NO_CHECK_OPTION) + ereport(ERROR, + (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("WITH CHECK OPTION not supported on recursive views"), + parser_errposition((yylsp[(12) - (12)])))); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1294: +#line 54 "third_party/libpg_query/grammar/statements/view.y" + { + PGViewStmt *n = makeNode(PGViewStmt); + n->view = (yyvsp[(7) - (14)].range); + n->view->relpersistence = (yyvsp[(4) - (14)].ival); + n->aliases = (yyvsp[(9) - (14)].list); + n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, (yyvsp[(13) - (14)].node)); + n->onconflict = PG_REPLACE_ON_CONFLICT; + n->options = (yyvsp[(11) - (14)].list); + n->withCheckOption = (yyvsp[(14) - (14)].viewcheckoption); + if (n->withCheckOption != PG_NO_CHECK_OPTION) + ereport(ERROR, + (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("WITH CHECK OPTION not supported on recursive views"), + parser_errposition((yylsp[(14) - (14)])))); + (yyval.node) = (PGNode *) n; + ;} + break; + + case 1295: +#line 74 "third_party/libpg_query/grammar/statements/view.y" + { (yyval.viewcheckoption) = CASCADED_CHECK_OPTION; ;} + break; + + case 1296: +#line 75 "third_party/libpg_query/grammar/statements/view.y" + { (yyval.viewcheckoption) = CASCADED_CHECK_OPTION; ;} + break; + + case 1297: +#line 76 "third_party/libpg_query/grammar/statements/view.y" + { (yyval.viewcheckoption) = PG_LOCAL_CHECK_OPTION; ;} + break; + + case 1298: +#line 77 "third_party/libpg_query/grammar/statements/view.y" + { (yyval.viewcheckoption) = PG_NO_CHECK_OPTION; ;} + break; + + case 1299: +#line 12 "third_party/libpg_query/grammar/statements/create_as.y" + { + PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); + ctas->query = (yyvsp[(6) - (7)].node); + ctas->into = (yyvsp[(4) - (7)].into); + ctas->relkind = PG_OBJECT_TABLE; + ctas->is_select_into = false; + ctas->onconflict = PG_ERROR_ON_CONFLICT; + /* cram additional flags into the PGIntoClause */ + (yyvsp[(4) - (7)].into)->rel->relpersistence = (yyvsp[(2) - (7)].ival); + (yyvsp[(4) - (7)].into)->skipData = !((yyvsp[(7) - (7)].boolean)); + (yyval.node) = (PGNode *) ctas; + ;} + break; + + case 1300: +#line 25 "third_party/libpg_query/grammar/statements/create_as.y" + { + PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); + ctas->query = (yyvsp[(9) - (10)].node); + ctas->into = (yyvsp[(7) - (10)].into); + ctas->relkind = PG_OBJECT_TABLE; + ctas->is_select_into = false; + ctas->onconflict = PG_IGNORE_ON_CONFLICT; + /* cram additional flags into the PGIntoClause */ + (yyvsp[(7) - (10)].into)->rel->relpersistence = (yyvsp[(2) - (10)].ival); + (yyvsp[(7) - (10)].into)->skipData = !((yyvsp[(10) - (10)].boolean)); + (yyval.node) = (PGNode *) ctas; + ;} + break; + + case 1301: +#line 38 "third_party/libpg_query/grammar/statements/create_as.y" + { + PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); + ctas->query = (yyvsp[(8) - (9)].node); + ctas->into = (yyvsp[(6) - (9)].into); + ctas->relkind = PG_OBJECT_TABLE; + ctas->is_select_into = false; + ctas->onconflict = PG_REPLACE_ON_CONFLICT; + /* cram additional flags into the PGIntoClause */ + (yyvsp[(6) - (9)].into)->rel->relpersistence = (yyvsp[(4) - (9)].ival); + (yyvsp[(6) - (9)].into)->skipData = !((yyvsp[(9) - (9)].boolean)); + (yyval.node) = (PGNode *) ctas; + ;} + break; + + case 1302: +#line 54 "third_party/libpg_query/grammar/statements/create_as.y" + { (yyval.boolean) = true; ;} + break; + + case 1303: +#line 55 "third_party/libpg_query/grammar/statements/create_as.y" + { (yyval.boolean) = false; ;} + break; + + case 1304: +#line 56 "third_party/libpg_query/grammar/statements/create_as.y" + { (yyval.boolean) = true; ;} + break; + + case 1305: +#line 62 "third_party/libpg_query/grammar/statements/create_as.y" + { + (yyval.into) = makeNode(PGIntoClause); + (yyval.into)->rel = (yyvsp[(1) - (4)].range); + (yyval.into)->colNames = (yyvsp[(2) - (4)].list); + (yyval.into)->options = (yyvsp[(3) - (4)].list); + (yyval.into)->onCommit = (yyvsp[(4) - (4)].oncommit); + (yyval.into)->viewQuery = NULL; + (yyval.into)->skipData = false; /* might get changed later */ + ;} + break; + + +/* Line 1267 of yacc.c. */ +#line 25801 "third_party/libpg_query/grammar/grammar_out.cpp" + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + *++yylsp = yyloc; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (&yylloc, yyscanner, YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (&yylloc, yyscanner, yymsg); + } + else + { + yyerror (&yylloc, yyscanner, YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + yyerror_range[0] = yylloc; + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse look-ahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval, &yylloc, yyscanner); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse look-ahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + yyerror_range[0] = yylsp[1-yylen]; + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + yyerror_range[0] = *yylsp; + yydestruct ("Error: popping", + yystos[yystate], yyvsp, yylsp, yyscanner); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + if (yyn == YYFINAL) + YYACCEPT; + + *++yyvsp = yylval; + + yyerror_range[1] = yylloc; + /* Using YYLLOC is tempting, but would change the location of + the look-ahead. YYLOC is available though. */ + YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2); + *++yylsp = yyloc; + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#ifndef yyoverflow +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (&yylloc, yyscanner, YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, &yylloc, yyscanner); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp, yylsp, yyscanner); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + +#line 83 "third_party/libpg_query/grammar/statements/create_as.y" + + +#line 1 "third_party/libpg_query/grammar/grammar.cpp" +/* + * The signature of this function is required by bison. However, we + * ignore the passed yylloc and instead use the last token position + * available from the scanner. + */ +static void +base_yyerror(YYLTYPE *yylloc, core_yyscan_t yyscanner, const char *msg) +{ + parser_yyerror(msg); +} + +static PGRawStmt * +makeRawStmt(PGNode *stmt, int stmt_location) +{ + PGRawStmt *rs = makeNode(PGRawStmt); + + rs->stmt = stmt; + rs->stmt_location = stmt_location; + rs->stmt_len = 0; /* might get changed later */ + return rs; +} + +/* Adjust a PGRawStmt to reflect that it doesn't run to the end of the string */ +static void +updateRawStmtEnd(PGRawStmt *rs, int end_location) +{ + /* + * If we already set the length, don't change it. This is for situations + * like "select foo ;; select bar" where the same statement will be last + * in the string for more than one semicolon. + */ + if (rs->stmt_len > 0) + return; + + /* OK, update length of PGRawStmt */ + rs->stmt_len = end_location - rs->stmt_location; +} + +static PGNode * +makeColumnRef(char *colname, PGList *indirection, + int location, core_yyscan_t yyscanner) +{ + /* + * Generate a PGColumnRef node, with an PGAIndirection node added if there + * is any subscripting in the specified indirection list. However, + * any field selection at the start of the indirection list must be + * transposed into the "fields" part of the PGColumnRef node. + */ + PGColumnRef *c = makeNode(PGColumnRef); + int nfields = 0; + PGListCell *l; + + c->location = location; + foreach(l, indirection) + { + if (IsA(lfirst(l), PGAIndices)) + { + PGAIndirection *i = makeNode(PGAIndirection); + + if (nfields == 0) + { + /* easy case - all indirection goes to PGAIndirection */ + c->fields = list_make1(makeString(colname)); + i->indirection = check_indirection(indirection, yyscanner); + } + else + { + /* got to split the list in two */ + i->indirection = check_indirection(list_copy_tail(indirection, + nfields), + yyscanner); + indirection = list_truncate(indirection, nfields); + c->fields = lcons(makeString(colname), indirection); + } + i->arg = (PGNode *) c; + return (PGNode *) i; + } + else if (IsA(lfirst(l), PGAStar)) + { + /* We only allow '*' at the end of a PGColumnRef */ + if (lnext(l) != NULL) + parser_yyerror("improper use of \"*\""); + } + nfields++; + } + /* No subscripting, so all indirection gets added to field list */ + c->fields = lcons(makeString(colname), indirection); + return (PGNode *) c; +} + +static PGNode * +makeTypeCast(PGNode *arg, PGTypeName *tpname, int trycast, int location) +{ + PGTypeCast *n = makeNode(PGTypeCast); + n->arg = arg; + n->typeName = tpname; + n->tryCast = trycast; + n->location = location; + return (PGNode *) n; +} + +static PGNode * +makeStringConst(char *str, int location) +{ + PGAConst *n = makeNode(PGAConst); + + n->val.type = T_PGString; + n->val.val.str = str; + n->location = location; + + return (PGNode *)n; +} + +static PGNode * +makeStringConstCast(char *str, int location, PGTypeName *tpname) +{ + PGNode *s = makeStringConst(str, location); + + return makeTypeCast(s, tpname, 0, -1); +} + +static PGNode * +makeIntervalNode(char *str, int location, PGList *typmods) { + PGIntervalConstant *n = makeNode(PGIntervalConstant); + + n->val_type = T_PGString; + n->sval = str; + n->location = location; + n->typmods = typmods; + + return (PGNode *)n; + +} + +static PGNode * +makeIntervalNode(int val, int location, PGList *typmods) { + PGIntervalConstant *n = makeNode(PGIntervalConstant); + + n->val_type = T_PGInteger; + n->ival = val; + n->location = location; + n->typmods = typmods; + + return (PGNode *)n; +} + +static PGNode * +makeIntervalNode(PGNode *arg, int location, PGList *typmods) { + PGIntervalConstant *n = makeNode(PGIntervalConstant); + + n->val_type = T_PGAExpr; + n->eval = arg; + n->location = location; + n->typmods = typmods; + + return (PGNode *)n; +} + +static PGNode * +makeSampleSize(PGValue *sample_size, bool is_percentage) { + PGSampleSize *n = makeNode(PGSampleSize); + + n->sample_size = *sample_size; + n->is_percentage = is_percentage; + + return (PGNode *)n; +} + +static PGNode * +makeSampleOptions(PGNode *sample_size, char *method, int *seed, int location) { + PGSampleOptions *n = makeNode(PGSampleOptions); + + n->sample_size = sample_size; + n->method = method; + if (seed) { + n->has_seed = true; + n->seed = *seed; + } + n->location = location; + + return (PGNode *)n; +} + +/* makeLimitPercent() + * Make limit percent node + */ +static PGNode * +makeLimitPercent(PGNode *limit_percent) { + PGLimitPercent *n = makeNode(PGLimitPercent); + + n->limit_percent = limit_percent; + + return (PGNode *)n; +} + +static PGNode * +makeIntConst(int val, int location) +{ + PGAConst *n = makeNode(PGAConst); + + n->val.type = T_PGInteger; + n->val.val.ival = val; + n->location = location; + + return (PGNode *)n; +} + +static PGNode * +makeFloatConst(char *str, int location) +{ + PGAConst *n = makeNode(PGAConst); + + n->val.type = T_PGFloat; + n->val.val.str = str; + n->location = location; + + return (PGNode *)n; +} + +static PGNode * +makeBitStringConst(char *str, int location) +{ + PGAConst *n = makeNode(PGAConst); + + n->val.type = T_PGBitString; + n->val.val.str = str; + n->location = location; + + return (PGNode *)n; +} + +static PGNode * +makeNullAConst(int location) +{ + PGAConst *n = makeNode(PGAConst); + + n->val.type = T_PGNull; + n->location = location; + + return (PGNode *)n; +} + +static PGNode * +makeAConst(PGValue *v, int location) +{ + PGNode *n; + + switch (v->type) + { + case T_PGFloat: + n = makeFloatConst(v->val.str, location); + break; + + case T_PGInteger: + n = makeIntConst(v->val.ival, location); + break; + + case T_PGString: + default: + n = makeStringConst(v->val.str, location); + break; + } + + return n; +} + +/* makeBoolAConst() + * Create an PGAConst string node and put it inside a boolean cast. + */ +static PGNode * +makeBoolAConst(bool state, int location) +{ + PGAConst *n = makeNode(PGAConst); + + n->val.type = T_PGString; + n->val.val.str = (state ? (char*) "t" : (char*) "f"); + n->location = location; + + return makeTypeCast((PGNode *)n, SystemTypeName("bool"), 0, -1); +} + +/* check_qualified_name --- check the result of qualified_name production + * + * It's easiest to let the grammar production for qualified_name allow + * subscripts and '*', which we then must reject here. + */ +static void +check_qualified_name(PGList *names, core_yyscan_t yyscanner) +{ + PGListCell *i; + + foreach(i, names) + { + if (!IsA(lfirst(i), PGString)) + parser_yyerror("syntax error"); + } +} + +/* check_func_name --- check the result of func_name production + * + * It's easiest to let the grammar production for func_name allow subscripts + * and '*', which we then must reject here. + */ +static PGList * +check_func_name(PGList *names, core_yyscan_t yyscanner) +{ + PGListCell *i; + + foreach(i, names) + { + if (!IsA(lfirst(i), PGString)) + parser_yyerror("syntax error"); + } + return names; +} + +/* check_indirection --- check the result of indirection production + * + * We only allow '*' at the end of the list, but it's hard to enforce that + * in the grammar, so do it here. + */ +static PGList * +check_indirection(PGList *indirection, core_yyscan_t yyscanner) +{ + PGListCell *l; + + foreach(l, indirection) + { + if (IsA(lfirst(l), PGAStar)) + { + if (lnext(l) != NULL) + parser_yyerror("improper use of \"*\""); + } + } + return indirection; +} + +/* makeParamRef + * Creates a new PGParamRef node + */ +static PGNode* makeParamRef(int number, int location) +{ + PGParamRef *p = makeNode(PGParamRef); + p->number = number; + p->location = location; + return (PGNode *) p; +} + + +/* insertSelectOptions() + * Insert ORDER BY, etc into an already-constructed SelectStmt. + * + * This routine is just to avoid duplicating code in PGSelectStmt productions. + */ +static void +insertSelectOptions(PGSelectStmt *stmt, + PGList *sortClause, PGList *lockingClause, + PGNode *limitOffset, PGNode *limitCount, + PGWithClause *withClause, + core_yyscan_t yyscanner) +{ + Assert(IsA(stmt, PGSelectStmt)); + + /* + * Tests here are to reject constructs like + * (SELECT foo ORDER BY bar) ORDER BY baz + */ + if (sortClause) + { + if (stmt->sortClause) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("multiple ORDER BY clauses not allowed"), + parser_errposition(exprLocation((PGNode *) sortClause)))); + stmt->sortClause = sortClause; + } + /* We can handle multiple locking clauses, though */ + stmt->lockingClause = list_concat(stmt->lockingClause, lockingClause); + if (limitOffset) + { + if (stmt->limitOffset) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("multiple OFFSET clauses not allowed"), + parser_errposition(exprLocation(limitOffset)))); + stmt->limitOffset = limitOffset; + } + if (limitCount) + { + if (stmt->limitCount) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("multiple LIMIT clauses not allowed"), + parser_errposition(exprLocation(limitCount)))); + stmt->limitCount = limitCount; + } + if (withClause) + { + if (stmt->withClause) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("multiple WITH clauses not allowed"), + parser_errposition(exprLocation((PGNode *) withClause)))); + stmt->withClause = withClause; + } +} + +static PGNode * +makeSetOp(PGSetOperation op, bool all, PGNode *larg, PGNode *rarg) +{ + PGSelectStmt *n = makeNode(PGSelectStmt); + + n->op = op; + n->all = all; + n->larg = (PGSelectStmt *) larg; + n->rarg = (PGSelectStmt *) rarg; + return (PGNode *) n; +} + +/* SystemFuncName() + * Build a properly-qualified reference to a built-in function. + */ +PGList * +SystemFuncName(const char *name) +{ + return list_make2(makeString(DEFAULT_SCHEMA), makeString(name)); +} + +/* SystemTypeName() + * Build a properly-qualified reference to a built-in type. + * + * typmod is defaulted, but may be changed afterwards by caller. + * Likewise for the location. + */ +PGTypeName * +SystemTypeName(const char *name) +{ + return makeTypeNameFromNameList(list_make2(makeString(DEFAULT_SCHEMA), + makeString(name))); +} + +/* doNegate() + * Handle negation of a numeric constant. + * + * Formerly, we did this here because the optimizer couldn't cope with + * indexquals that looked like "var = -4" --- it wants "var = const" + * and a unary minus operator applied to a constant didn't qualify. + * As of Postgres 7.0, that problem doesn't exist anymore because there + * is a constant-subexpression simplifier in the optimizer. However, + * there's still a good reason for doing this here, which is that we can + * postpone committing to a particular internal representation for simple + * negative constants. It's better to leave "-123.456" in string form + * until we know what the desired type is. + */ +static PGNode * +doNegate(PGNode *n, int location) +{ + if (IsA(n, PGAConst)) + { + PGAConst *con = (PGAConst *)n; + + /* report the constant's location as that of the '-' sign */ + con->location = location; + + if (con->val.type == T_PGInteger) + { + con->val.val.ival = -con->val.val.ival; + return n; + } + if (con->val.type == T_PGFloat) + { + doNegateFloat(&con->val); + return n; + } + } + + return (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "-", NULL, n, location); +} + +static void +doNegateFloat(PGValue *v) +{ + char *oldval = v->val.str; + + Assert(IsA(v, PGFloat)); + if (*oldval == '+') + oldval++; + if (*oldval == '-') + v->val.str = oldval+1; /* just strip the '-' */ + else + v->val.str = psprintf("-%s", oldval); +} + +static PGNode * +makeAndExpr(PGNode *lexpr, PGNode *rexpr, int location) +{ + PGNode *lexp = lexpr; + + /* Look through AEXPR_PAREN nodes so they don't affect flattening */ + while (IsA(lexp, PGAExpr) && + ((PGAExpr *) lexp)->kind == AEXPR_PAREN) + lexp = ((PGAExpr *) lexp)->lexpr; + /* Flatten "a AND b AND c ..." to a single PGBoolExpr on sight */ + if (IsA(lexp, PGBoolExpr)) + { + PGBoolExpr *blexpr = (PGBoolExpr *) lexp; + + if (blexpr->boolop == PG_AND_EXPR) + { + blexpr->args = lappend(blexpr->args, rexpr); + return (PGNode *) blexpr; + } + } + return (PGNode *) makeBoolExpr(PG_AND_EXPR, list_make2(lexpr, rexpr), location); +} + +static PGNode * +makeOrExpr(PGNode *lexpr, PGNode *rexpr, int location) +{ + PGNode *lexp = lexpr; + + /* Look through AEXPR_PAREN nodes so they don't affect flattening */ + while (IsA(lexp, PGAExpr) && + ((PGAExpr *) lexp)->kind == AEXPR_PAREN) + lexp = ((PGAExpr *) lexp)->lexpr; + /* Flatten "a OR b OR c ..." to a single PGBoolExpr on sight */ + if (IsA(lexp, PGBoolExpr)) + { + PGBoolExpr *blexpr = (PGBoolExpr *) lexp; + + if (blexpr->boolop == PG_OR_EXPR) + { + blexpr->args = lappend(blexpr->args, rexpr); + return (PGNode *) blexpr; + } + } + return (PGNode *) makeBoolExpr(PG_OR_EXPR, list_make2(lexpr, rexpr), location); +} + +static PGNode * +makeNotExpr(PGNode *expr, int location) +{ + return (PGNode *) makeBoolExpr(PG_NOT_EXPR, list_make1(expr), location); +} + +static PGNode * +makeSQLValueFunction(PGSQLValueFunctionOp op, int32_t typmod, int location) +{ + PGSQLValueFunction *svf = makeNode(PGSQLValueFunction); + + svf->op = op; + /* svf->type will be filled during parse analysis */ + svf->typmod = typmod; + svf->location = location; + return (PGNode *) svf; +} + +/* Separate PGConstraint nodes from COLLATE clauses in a */ +static void +SplitColQualList(PGList *qualList, + PGList **constraintList, PGCollateClause **collClause, + core_yyscan_t yyscanner) +{ + PGListCell *cell; + PGListCell *prev; + PGListCell *next; + + *collClause = NULL; + prev = NULL; + for (cell = list_head(qualList); cell; cell = next) + { + PGNode *n = (PGNode *) lfirst(cell); + + next = lnext(cell); + if (IsA(n, PGConstraint)) + { + /* keep it in list */ + prev = cell; + continue; + } + if (IsA(n, PGCollateClause)) + { + PGCollateClause *c = (PGCollateClause *) n; + + if (*collClause) + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + errmsg("multiple COLLATE clauses not allowed"), + parser_errposition(c->location))); + *collClause = c; + } + else + elog(ERROR, "unexpected node type %d", (int) n->type); + /* remove non-Constraint nodes from qualList */ + qualList = list_delete_cell(qualList, cell, prev); + } + *constraintList = qualList; +} + +/* + * Process result of ConstraintAttributeSpec, and set appropriate bool flags + * in the output command node. Pass NULL for any flags the particular + * command doesn't support. + */ +static void +processCASbits(int cas_bits, int location, const char *constrType, + bool *deferrable, bool *initdeferred, bool *not_valid, + bool *no_inherit, core_yyscan_t yyscanner) +{ + /* defaults */ + if (deferrable) + *deferrable = false; + if (initdeferred) + *initdeferred = false; + if (not_valid) + *not_valid = false; + + if (cas_bits & (CAS_DEFERRABLE | CAS_INITIALLY_DEFERRED)) + { + if (deferrable) + *deferrable = true; + else + ereport(ERROR, + (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is CHECK, UNIQUE, or similar */ + errmsg("%s constraints cannot be marked DEFERRABLE", + constrType), + parser_errposition(location))); + } + + if (cas_bits & CAS_INITIALLY_DEFERRED) + { + if (initdeferred) + *initdeferred = true; + else + ereport(ERROR, + (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is CHECK, UNIQUE, or similar */ + errmsg("%s constraints cannot be marked DEFERRABLE", + constrType), + parser_errposition(location))); + } + + if (cas_bits & CAS_NOT_VALID) + { + if (not_valid) + *not_valid = true; + else + ereport(ERROR, + (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is CHECK, UNIQUE, or similar */ + errmsg("%s constraints cannot be marked NOT VALID", + constrType), + parser_errposition(location))); + } + + if (cas_bits & CAS_NO_INHERIT) + { + if (no_inherit) + *no_inherit = true; + else + ereport(ERROR, + (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is CHECK, UNIQUE, or similar */ + errmsg("%s constraints cannot be marked NO INHERIT", + constrType), + parser_errposition(location))); + } +} + +/*---------- + * Recursive view transformation + * + * Convert + * + * CREATE RECURSIVE VIEW relname (aliases) AS query + * + * to + * + * CREATE VIEW relname (aliases) AS + * WITH RECURSIVE relname (aliases) AS (query) + * SELECT aliases FROM relname + * + * Actually, just the WITH ... part, which is then inserted into the original + * view as the query. + * ---------- + */ +static PGNode * +makeRecursiveViewSelect(char *relname, PGList *aliases, PGNode *query) +{ + PGSelectStmt *s = makeNode(PGSelectStmt); + PGWithClause *w = makeNode(PGWithClause); + PGCommonTableExpr *cte = makeNode(PGCommonTableExpr); + PGList *tl = NIL; + PGListCell *lc; + + /* create common table expression */ + cte->ctename = relname; + cte->aliascolnames = aliases; + cte->ctequery = query; + cte->location = -1; + + /* create WITH clause and attach CTE */ + w->recursive = true; + w->ctes = list_make1(cte); + w->location = -1; + + /* create target list for the new SELECT from the alias list of the + * recursive view specification */ + foreach (lc, aliases) + { + PGResTarget *rt = makeNode(PGResTarget); + + rt->name = NULL; + rt->indirection = NIL; + rt->val = makeColumnRef(strVal(lfirst(lc)), NIL, -1, 0); + rt->location = -1; + + tl = lappend(tl, rt); + } + + /* create new SELECT combining WITH clause, target list, and fake FROM + * clause */ + s->withClause = w; + s->targetList = tl; + s->fromClause = list_make1(makeRangeVar(NULL, relname, -1)); + + return (PGNode *) s; +} + +/* parser_init() + * Initialize to parse one query string + */ +void +parser_init(base_yy_extra_type *yyext) +{ + yyext->parsetree = NIL; /* in case grammar forgets to set it */ +} + +#undef yyparse +#undef yylex +#undef yyerror +#undef yylval +#undef yychar +#undef yydebug +#undef yynerrs +#undef yylloc + +} // namespace duckdb_libpgquery + + + +// LICENSE_CHANGE_END + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 +// See the end of this file for a list + +/*-------------------------------------------------------------------- + * Symbols referenced in this file: + * - raw_parser + * - base_yylex + * - raw_parser + *-------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------- + * + * parser.c + * Main entry point/driver for PostgreSQL grammar + * + * Note that the grammar is not allowed to perform any table access + * (since we need to be able to do basic parsing even while inside an + * aborted transaction). Therefore, the data structures returned by + * the grammar are "raw" parsetrees that still need to be analyzed by + * analyze.c and related files. + * + * + * Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/parser/parser.c + * + *------------------------------------------------------------------------- + */ + + + + + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 +// See the end of this file for a list + + +namespace duckdb_libpgquery { +#define PG_KEYWORD(a,b,c) {a,b,c}, + +const PGScanKeyword ScanKeywords[] = { +PG_KEYWORD("abort", ABORT_P, UNRESERVED_KEYWORD) +PG_KEYWORD("absolute", ABSOLUTE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("access", ACCESS, UNRESERVED_KEYWORD) +PG_KEYWORD("action", ACTION, UNRESERVED_KEYWORD) +PG_KEYWORD("add", ADD_P, UNRESERVED_KEYWORD) +PG_KEYWORD("admin", ADMIN, UNRESERVED_KEYWORD) +PG_KEYWORD("after", AFTER, UNRESERVED_KEYWORD) +PG_KEYWORD("aggregate", AGGREGATE, UNRESERVED_KEYWORD) +PG_KEYWORD("all", ALL, RESERVED_KEYWORD) +PG_KEYWORD("also", ALSO, UNRESERVED_KEYWORD) +PG_KEYWORD("alter", ALTER, UNRESERVED_KEYWORD) +PG_KEYWORD("always", ALWAYS, UNRESERVED_KEYWORD) +PG_KEYWORD("analyse", ANALYSE, RESERVED_KEYWORD) +PG_KEYWORD("analyze", ANALYZE, RESERVED_KEYWORD) +PG_KEYWORD("and", AND, RESERVED_KEYWORD) +PG_KEYWORD("any", ANY, RESERVED_KEYWORD) +PG_KEYWORD("array", ARRAY, RESERVED_KEYWORD) +PG_KEYWORD("as", AS, RESERVED_KEYWORD) +PG_KEYWORD("asc", ASC_P, RESERVED_KEYWORD) +PG_KEYWORD("assertion", ASSERTION, UNRESERVED_KEYWORD) +PG_KEYWORD("assignment", ASSIGNMENT, UNRESERVED_KEYWORD) +PG_KEYWORD("asymmetric", ASYMMETRIC, RESERVED_KEYWORD) +PG_KEYWORD("at", AT, UNRESERVED_KEYWORD) +PG_KEYWORD("attach", ATTACH, UNRESERVED_KEYWORD) +PG_KEYWORD("attribute", ATTRIBUTE, UNRESERVED_KEYWORD) +PG_KEYWORD("authorization", AUTHORIZATION, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("backward", BACKWARD, UNRESERVED_KEYWORD) +PG_KEYWORD("before", BEFORE, UNRESERVED_KEYWORD) +PG_KEYWORD("begin", BEGIN_P, UNRESERVED_KEYWORD) +PG_KEYWORD("between", BETWEEN, COL_NAME_KEYWORD) +PG_KEYWORD("bigint", BIGINT, COL_NAME_KEYWORD) +PG_KEYWORD("binary", BINARY, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("bit", BIT, COL_NAME_KEYWORD) +PG_KEYWORD("boolean", BOOLEAN_P, COL_NAME_KEYWORD) +PG_KEYWORD("both", BOTH, RESERVED_KEYWORD) +PG_KEYWORD("by", BY, UNRESERVED_KEYWORD) +PG_KEYWORD("cache", CACHE, UNRESERVED_KEYWORD) +PG_KEYWORD("call", CALL_P, UNRESERVED_KEYWORD) +PG_KEYWORD("called", CALLED, UNRESERVED_KEYWORD) +PG_KEYWORD("cascade", CASCADE, UNRESERVED_KEYWORD) +PG_KEYWORD("cascaded", CASCADED, UNRESERVED_KEYWORD) +PG_KEYWORD("case", CASE, RESERVED_KEYWORD) +PG_KEYWORD("cast", CAST, RESERVED_KEYWORD) +PG_KEYWORD("catalog", CATALOG_P, UNRESERVED_KEYWORD) +PG_KEYWORD("chain", CHAIN, UNRESERVED_KEYWORD) +PG_KEYWORD("char", CHAR_P, COL_NAME_KEYWORD) +PG_KEYWORD("character", CHARACTER, COL_NAME_KEYWORD) +PG_KEYWORD("characteristics", CHARACTERISTICS, UNRESERVED_KEYWORD) +PG_KEYWORD("check", CHECK_P, RESERVED_KEYWORD) +PG_KEYWORD("checkpoint", CHECKPOINT, UNRESERVED_KEYWORD) +PG_KEYWORD("class", CLASS, UNRESERVED_KEYWORD) +PG_KEYWORD("close", CLOSE, UNRESERVED_KEYWORD) +PG_KEYWORD("cluster", CLUSTER, UNRESERVED_KEYWORD) +PG_KEYWORD("coalesce", COALESCE, COL_NAME_KEYWORD) +PG_KEYWORD("collate", COLLATE, RESERVED_KEYWORD) +PG_KEYWORD("collation", COLLATION, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("column", COLUMN, RESERVED_KEYWORD) +PG_KEYWORD("columns", COLUMNS, UNRESERVED_KEYWORD) +PG_KEYWORD("comment", COMMENT, UNRESERVED_KEYWORD) +PG_KEYWORD("comments", COMMENTS, UNRESERVED_KEYWORD) +PG_KEYWORD("commit", COMMIT, UNRESERVED_KEYWORD) +PG_KEYWORD("committed", COMMITTED, UNRESERVED_KEYWORD) +PG_KEYWORD("compression", COMPRESSION, UNRESERVED_KEYWORD) +PG_KEYWORD("concurrently", CONCURRENTLY, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("configuration", CONFIGURATION, UNRESERVED_KEYWORD) +PG_KEYWORD("conflict", CONFLICT, UNRESERVED_KEYWORD) +PG_KEYWORD("connection", CONNECTION, UNRESERVED_KEYWORD) +PG_KEYWORD("constraint", CONSTRAINT, RESERVED_KEYWORD) +PG_KEYWORD("constraints", CONSTRAINTS, UNRESERVED_KEYWORD) +PG_KEYWORD("content", CONTENT_P, UNRESERVED_KEYWORD) +PG_KEYWORD("continue", CONTINUE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("conversion", CONVERSION_P, UNRESERVED_KEYWORD) +PG_KEYWORD("copy", COPY, UNRESERVED_KEYWORD) +PG_KEYWORD("cost", COST, UNRESERVED_KEYWORD) +PG_KEYWORD("create", CREATE_P, RESERVED_KEYWORD) +PG_KEYWORD("cross", CROSS, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("csv", CSV, UNRESERVED_KEYWORD) +PG_KEYWORD("cube", CUBE, UNRESERVED_KEYWORD) +PG_KEYWORD("current", CURRENT_P, UNRESERVED_KEYWORD) +PG_KEYWORD("current_catalog", CURRENT_CATALOG, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("current_date", CURRENT_DATE, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("current_role", CURRENT_ROLE, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("current_schema", CURRENT_SCHEMA, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("current_time", CURRENT_TIME, RESERVED_KEYWORD) +PG_KEYWORD("current_timestamp", CURRENT_TIMESTAMP, RESERVED_KEYWORD) +PG_KEYWORD("current_user", CURRENT_USER, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("cursor", CURSOR, UNRESERVED_KEYWORD) +PG_KEYWORD("cycle", CYCLE, UNRESERVED_KEYWORD) +PG_KEYWORD("data", DATA_P, UNRESERVED_KEYWORD) +PG_KEYWORD("database", DATABASE, UNRESERVED_KEYWORD) +PG_KEYWORD("day", DAY_P, UNRESERVED_KEYWORD) +PG_KEYWORD("days", DAYS_P, UNRESERVED_KEYWORD) +PG_KEYWORD("deallocate", DEALLOCATE, UNRESERVED_KEYWORD) +PG_KEYWORD("dec", DEC, COL_NAME_KEYWORD) +PG_KEYWORD("decimal", DECIMAL_P, COL_NAME_KEYWORD) +PG_KEYWORD("declare", DECLARE, UNRESERVED_KEYWORD) +PG_KEYWORD("default", DEFAULT, RESERVED_KEYWORD) +PG_KEYWORD("defaults", DEFAULTS, UNRESERVED_KEYWORD) +PG_KEYWORD("deferrable", DEFERRABLE, RESERVED_KEYWORD) +PG_KEYWORD("deferred", DEFERRED, UNRESERVED_KEYWORD) +PG_KEYWORD("definer", DEFINER, UNRESERVED_KEYWORD) +PG_KEYWORD("delete", DELETE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("delimiter", DELIMITER, UNRESERVED_KEYWORD) +PG_KEYWORD("delimiters", DELIMITERS, UNRESERVED_KEYWORD) +PG_KEYWORD("depends", DEPENDS, UNRESERVED_KEYWORD) +PG_KEYWORD("desc", DESC_P, RESERVED_KEYWORD) +PG_KEYWORD("describe", DESCRIBE, UNRESERVED_KEYWORD) +PG_KEYWORD("detach", DETACH, UNRESERVED_KEYWORD) +PG_KEYWORD("dictionary", DICTIONARY, UNRESERVED_KEYWORD) +PG_KEYWORD("disable", DISABLE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("discard", DISCARD, UNRESERVED_KEYWORD) +PG_KEYWORD("distinct", DISTINCT, RESERVED_KEYWORD) +PG_KEYWORD("do", DO, RESERVED_KEYWORD) +PG_KEYWORD("document", DOCUMENT_P, UNRESERVED_KEYWORD) +PG_KEYWORD("domain", DOMAIN_P, UNRESERVED_KEYWORD) +PG_KEYWORD("double", DOUBLE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("drop", DROP, UNRESERVED_KEYWORD) +PG_KEYWORD("each", EACH, UNRESERVED_KEYWORD) +PG_KEYWORD("else", ELSE, RESERVED_KEYWORD) +PG_KEYWORD("enable", ENABLE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("encoding", ENCODING, UNRESERVED_KEYWORD) +PG_KEYWORD("encrypted", ENCRYPTED, UNRESERVED_KEYWORD) +PG_KEYWORD("end", END_P, RESERVED_KEYWORD) +PG_KEYWORD("enum", ENUM_P, UNRESERVED_KEYWORD) +PG_KEYWORD("escape", ESCAPE, UNRESERVED_KEYWORD) +PG_KEYWORD("event", EVENT, UNRESERVED_KEYWORD) +PG_KEYWORD("except", EXCEPT, RESERVED_KEYWORD) +PG_KEYWORD("exclude", EXCLUDE, UNRESERVED_KEYWORD) +PG_KEYWORD("excluding", EXCLUDING, UNRESERVED_KEYWORD) +PG_KEYWORD("exclusive", EXCLUSIVE, UNRESERVED_KEYWORD) +PG_KEYWORD("execute", EXECUTE, UNRESERVED_KEYWORD) +PG_KEYWORD("exists", EXISTS, COL_NAME_KEYWORD) +PG_KEYWORD("explain", EXPLAIN, UNRESERVED_KEYWORD) +PG_KEYWORD("export", EXPORT_P, UNRESERVED_KEYWORD) +PG_KEYWORD("export_state", EXPORT_STATE, UNRESERVED_KEYWORD) +PG_KEYWORD("extension", EXTENSION, UNRESERVED_KEYWORD) +PG_KEYWORD("external", EXTERNAL, UNRESERVED_KEYWORD) +PG_KEYWORD("extract", EXTRACT, COL_NAME_KEYWORD) +PG_KEYWORD("false", FALSE_P, RESERVED_KEYWORD) +PG_KEYWORD("family", FAMILY, UNRESERVED_KEYWORD) +PG_KEYWORD("fetch", FETCH, RESERVED_KEYWORD) +PG_KEYWORD("filter", FILTER, UNRESERVED_KEYWORD) +PG_KEYWORD("first", FIRST_P, UNRESERVED_KEYWORD) +PG_KEYWORD("float", FLOAT_P, COL_NAME_KEYWORD) +PG_KEYWORD("following", FOLLOWING, UNRESERVED_KEYWORD) +PG_KEYWORD("for", FOR, RESERVED_KEYWORD) +PG_KEYWORD("force", FORCE, UNRESERVED_KEYWORD) +PG_KEYWORD("foreign", FOREIGN, RESERVED_KEYWORD) +PG_KEYWORD("forward", FORWARD, UNRESERVED_KEYWORD) +PG_KEYWORD("freeze", FREEZE, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("from", FROM, RESERVED_KEYWORD) +PG_KEYWORD("full", FULL, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("function", FUNCTION, UNRESERVED_KEYWORD) +PG_KEYWORD("functions", FUNCTIONS, UNRESERVED_KEYWORD) +PG_KEYWORD("generated", GENERATED, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("glob", GLOB, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("global", GLOBAL, UNRESERVED_KEYWORD) +PG_KEYWORD("grant", GRANT, RESERVED_KEYWORD) +PG_KEYWORD("granted", GRANTED, UNRESERVED_KEYWORD) +PG_KEYWORD("group", GROUP_P, RESERVED_KEYWORD) +PG_KEYWORD("grouping", GROUPING, COL_NAME_KEYWORD) +PG_KEYWORD("grouping_id", GROUPING_ID, COL_NAME_KEYWORD) +PG_KEYWORD("handler", HANDLER, UNRESERVED_KEYWORD) +PG_KEYWORD("having", HAVING, RESERVED_KEYWORD) +PG_KEYWORD("header", HEADER_P, UNRESERVED_KEYWORD) +PG_KEYWORD("hold", HOLD, UNRESERVED_KEYWORD) +PG_KEYWORD("hour", HOUR_P, UNRESERVED_KEYWORD) +PG_KEYWORD("hours", HOURS_P, UNRESERVED_KEYWORD) +PG_KEYWORD("identity", IDENTITY_P, UNRESERVED_KEYWORD) +PG_KEYWORD("if", IF_P, UNRESERVED_KEYWORD) +PG_KEYWORD("ignore", IGNORE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("ilike", ILIKE, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("immediate", IMMEDIATE, UNRESERVED_KEYWORD) +PG_KEYWORD("immutable", IMMUTABLE, UNRESERVED_KEYWORD) +PG_KEYWORD("implicit", IMPLICIT_P, UNRESERVED_KEYWORD) +PG_KEYWORD("import", IMPORT_P, UNRESERVED_KEYWORD) +PG_KEYWORD("in", IN_P, RESERVED_KEYWORD) +PG_KEYWORD("including", INCLUDING, UNRESERVED_KEYWORD) +PG_KEYWORD("increment", INCREMENT, UNRESERVED_KEYWORD) +PG_KEYWORD("index", INDEX, UNRESERVED_KEYWORD) +PG_KEYWORD("indexes", INDEXES, UNRESERVED_KEYWORD) +PG_KEYWORD("inherit", INHERIT, UNRESERVED_KEYWORD) +PG_KEYWORD("inherits", INHERITS, UNRESERVED_KEYWORD) +PG_KEYWORD("initially", INITIALLY, RESERVED_KEYWORD) +PG_KEYWORD("inline", INLINE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("inner", INNER_P, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("inout", INOUT, COL_NAME_KEYWORD) +PG_KEYWORD("input", INPUT_P, UNRESERVED_KEYWORD) +PG_KEYWORD("insensitive", INSENSITIVE, UNRESERVED_KEYWORD) +PG_KEYWORD("insert", INSERT, UNRESERVED_KEYWORD) +PG_KEYWORD("install", INSTALL, UNRESERVED_KEYWORD) +PG_KEYWORD("instead", INSTEAD, UNRESERVED_KEYWORD) +PG_KEYWORD("int", INT_P, COL_NAME_KEYWORD) +PG_KEYWORD("integer", INTEGER, COL_NAME_KEYWORD) +PG_KEYWORD("intersect", INTERSECT, RESERVED_KEYWORD) +PG_KEYWORD("interval", INTERVAL, COL_NAME_KEYWORD) +PG_KEYWORD("into", INTO, RESERVED_KEYWORD) +PG_KEYWORD("invoker", INVOKER, UNRESERVED_KEYWORD) +PG_KEYWORD("is", IS, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("isnull", ISNULL, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("isolation", ISOLATION, UNRESERVED_KEYWORD) +PG_KEYWORD("join", JOIN, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("json", JSON, UNRESERVED_KEYWORD) +PG_KEYWORD("key", KEY, UNRESERVED_KEYWORD) +PG_KEYWORD("label", LABEL, UNRESERVED_KEYWORD) +PG_KEYWORD("language", LANGUAGE, UNRESERVED_KEYWORD) +PG_KEYWORD("large", LARGE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("last", LAST_P, UNRESERVED_KEYWORD) +PG_KEYWORD("lateral", LATERAL_P, RESERVED_KEYWORD) +PG_KEYWORD("leading", LEADING, RESERVED_KEYWORD) +PG_KEYWORD("leakproof", LEAKPROOF, UNRESERVED_KEYWORD) +PG_KEYWORD("left", LEFT, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("level", LEVEL, UNRESERVED_KEYWORD) +PG_KEYWORD("like", LIKE, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("limit", LIMIT, RESERVED_KEYWORD) +PG_KEYWORD("listen", LISTEN, UNRESERVED_KEYWORD) +PG_KEYWORD("load", LOAD, UNRESERVED_KEYWORD) +PG_KEYWORD("local", LOCAL, UNRESERVED_KEYWORD) +PG_KEYWORD("localtime", LOCALTIME, RESERVED_KEYWORD) +PG_KEYWORD("localtimestamp", LOCALTIMESTAMP, RESERVED_KEYWORD) +PG_KEYWORD("location", LOCATION, UNRESERVED_KEYWORD) +PG_KEYWORD("lock", LOCK_P, UNRESERVED_KEYWORD) +PG_KEYWORD("locked", LOCKED, UNRESERVED_KEYWORD) +PG_KEYWORD("logged", LOGGED, UNRESERVED_KEYWORD) +PG_KEYWORD("macro", MACRO, UNRESERVED_KEYWORD) +PG_KEYWORD("map", MAP, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("mapping", MAPPING, UNRESERVED_KEYWORD) +PG_KEYWORD("match", MATCH, UNRESERVED_KEYWORD) +PG_KEYWORD("materialized", MATERIALIZED, UNRESERVED_KEYWORD) +PG_KEYWORD("maxvalue", MAXVALUE, UNRESERVED_KEYWORD) +PG_KEYWORD("method", METHOD, UNRESERVED_KEYWORD) +PG_KEYWORD("microsecond", MICROSECOND_P, UNRESERVED_KEYWORD) +PG_KEYWORD("microseconds", MICROSECONDS_P, UNRESERVED_KEYWORD) +PG_KEYWORD("millisecond", MILLISECOND_P, UNRESERVED_KEYWORD) +PG_KEYWORD("milliseconds", MILLISECONDS_P, UNRESERVED_KEYWORD) +PG_KEYWORD("minute", MINUTE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("minutes", MINUTES_P, UNRESERVED_KEYWORD) +PG_KEYWORD("minvalue", MINVALUE, UNRESERVED_KEYWORD) +PG_KEYWORD("mode", MODE, UNRESERVED_KEYWORD) +PG_KEYWORD("month", MONTH_P, UNRESERVED_KEYWORD) +PG_KEYWORD("months", MONTHS_P, UNRESERVED_KEYWORD) +PG_KEYWORD("move", MOVE, UNRESERVED_KEYWORD) +PG_KEYWORD("name", NAME_P, UNRESERVED_KEYWORD) +PG_KEYWORD("names", NAMES, UNRESERVED_KEYWORD) +PG_KEYWORD("national", NATIONAL, COL_NAME_KEYWORD) +PG_KEYWORD("natural", NATURAL, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("nchar", NCHAR, COL_NAME_KEYWORD) +PG_KEYWORD("new", NEW, UNRESERVED_KEYWORD) +PG_KEYWORD("next", NEXT, UNRESERVED_KEYWORD) +PG_KEYWORD("no", NO, UNRESERVED_KEYWORD) +PG_KEYWORD("none", NONE, COL_NAME_KEYWORD) +PG_KEYWORD("not", NOT, RESERVED_KEYWORD) +PG_KEYWORD("nothing", NOTHING, UNRESERVED_KEYWORD) +PG_KEYWORD("notify", NOTIFY, UNRESERVED_KEYWORD) +PG_KEYWORD("notnull", NOTNULL, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("nowait", NOWAIT, UNRESERVED_KEYWORD) +PG_KEYWORD("null", NULL_P, RESERVED_KEYWORD) +PG_KEYWORD("nullif", NULLIF, COL_NAME_KEYWORD) +PG_KEYWORD("nulls", NULLS_P, UNRESERVED_KEYWORD) +PG_KEYWORD("numeric", NUMERIC, COL_NAME_KEYWORD) +PG_KEYWORD("object", OBJECT_P, UNRESERVED_KEYWORD) +PG_KEYWORD("of", OF, UNRESERVED_KEYWORD) +PG_KEYWORD("off", OFF, UNRESERVED_KEYWORD) +PG_KEYWORD("offset", OFFSET, RESERVED_KEYWORD) +PG_KEYWORD("oids", OIDS, UNRESERVED_KEYWORD) +PG_KEYWORD("old", OLD, UNRESERVED_KEYWORD) +PG_KEYWORD("on", ON, RESERVED_KEYWORD) +PG_KEYWORD("only", ONLY, RESERVED_KEYWORD) +PG_KEYWORD("operator", OPERATOR, UNRESERVED_KEYWORD) +PG_KEYWORD("option", OPTION, UNRESERVED_KEYWORD) +PG_KEYWORD("options", OPTIONS, UNRESERVED_KEYWORD) +PG_KEYWORD("or", OR, RESERVED_KEYWORD) +PG_KEYWORD("order", ORDER, RESERVED_KEYWORD) +PG_KEYWORD("ordinality", ORDINALITY, UNRESERVED_KEYWORD) +PG_KEYWORD("out", OUT_P, COL_NAME_KEYWORD) +PG_KEYWORD("outer", OUTER_P, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("over", OVER, UNRESERVED_KEYWORD) +PG_KEYWORD("overlaps", OVERLAPS, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("overlay", OVERLAY, COL_NAME_KEYWORD) +PG_KEYWORD("overriding", OVERRIDING, UNRESERVED_KEYWORD) +PG_KEYWORD("owned", OWNED, UNRESERVED_KEYWORD) +PG_KEYWORD("owner", OWNER, UNRESERVED_KEYWORD) +PG_KEYWORD("parallel", PARALLEL, UNRESERVED_KEYWORD) +PG_KEYWORD("parser", PARSER, UNRESERVED_KEYWORD) +PG_KEYWORD("partial", PARTIAL, UNRESERVED_KEYWORD) +PG_KEYWORD("partition", PARTITION, UNRESERVED_KEYWORD) +PG_KEYWORD("passing", PASSING, UNRESERVED_KEYWORD) +PG_KEYWORD("password", PASSWORD, UNRESERVED_KEYWORD) +PG_KEYWORD("percent", PERCENT, UNRESERVED_KEYWORD) +PG_KEYWORD("placing", PLACING, RESERVED_KEYWORD) +PG_KEYWORD("plans", PLANS, UNRESERVED_KEYWORD) +PG_KEYWORD("policy", POLICY, UNRESERVED_KEYWORD) +PG_KEYWORD("position", POSITION, COL_NAME_KEYWORD) +PG_KEYWORD("pragma", PRAGMA_P, UNRESERVED_KEYWORD) +PG_KEYWORD("preceding", PRECEDING, UNRESERVED_KEYWORD) +PG_KEYWORD("precision", PRECISION, COL_NAME_KEYWORD) +PG_KEYWORD("prepare", PREPARE, UNRESERVED_KEYWORD) +PG_KEYWORD("prepared", PREPARED, UNRESERVED_KEYWORD) +PG_KEYWORD("preserve", PRESERVE, UNRESERVED_KEYWORD) +PG_KEYWORD("primary", PRIMARY, RESERVED_KEYWORD) +PG_KEYWORD("prior", PRIOR, UNRESERVED_KEYWORD) +PG_KEYWORD("privileges", PRIVILEGES, UNRESERVED_KEYWORD) +PG_KEYWORD("procedural", PROCEDURAL, UNRESERVED_KEYWORD) +PG_KEYWORD("procedure", PROCEDURE, UNRESERVED_KEYWORD) +PG_KEYWORD("program", PROGRAM, UNRESERVED_KEYWORD) +PG_KEYWORD("publication", PUBLICATION, UNRESERVED_KEYWORD) +PG_KEYWORD("qualify", QUALIFY, RESERVED_KEYWORD) +PG_KEYWORD("quote", QUOTE, UNRESERVED_KEYWORD) +PG_KEYWORD("range", RANGE, UNRESERVED_KEYWORD) +PG_KEYWORD("read", READ_P, UNRESERVED_KEYWORD) +PG_KEYWORD("real", REAL, COL_NAME_KEYWORD) +PG_KEYWORD("reassign", REASSIGN, UNRESERVED_KEYWORD) +PG_KEYWORD("recheck", RECHECK, UNRESERVED_KEYWORD) +PG_KEYWORD("recursive", RECURSIVE, UNRESERVED_KEYWORD) +PG_KEYWORD("ref", REF, UNRESERVED_KEYWORD) +PG_KEYWORD("references", REFERENCES, RESERVED_KEYWORD) +PG_KEYWORD("referencing", REFERENCING, UNRESERVED_KEYWORD) +PG_KEYWORD("refresh", REFRESH, UNRESERVED_KEYWORD) +PG_KEYWORD("reindex", REINDEX, UNRESERVED_KEYWORD) +PG_KEYWORD("relative", RELATIVE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("release", RELEASE, UNRESERVED_KEYWORD) +PG_KEYWORD("rename", RENAME, UNRESERVED_KEYWORD) +PG_KEYWORD("repeatable", REPEATABLE, UNRESERVED_KEYWORD) +PG_KEYWORD("replace", REPLACE, UNRESERVED_KEYWORD) +PG_KEYWORD("replica", REPLICA, UNRESERVED_KEYWORD) +PG_KEYWORD("reset", RESET, UNRESERVED_KEYWORD) +PG_KEYWORD("respect", RESPECT_P, UNRESERVED_KEYWORD) +PG_KEYWORD("restart", RESTART, UNRESERVED_KEYWORD) +PG_KEYWORD("restrict", RESTRICT, UNRESERVED_KEYWORD) +PG_KEYWORD("returning", RETURNING, RESERVED_KEYWORD) +PG_KEYWORD("returns", RETURNS, UNRESERVED_KEYWORD) +PG_KEYWORD("revoke", REVOKE, UNRESERVED_KEYWORD) +PG_KEYWORD("right", RIGHT, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("role", ROLE, UNRESERVED_KEYWORD) +PG_KEYWORD("rollback", ROLLBACK, UNRESERVED_KEYWORD) +PG_KEYWORD("rollup", ROLLUP, UNRESERVED_KEYWORD) +PG_KEYWORD("row", ROW, COL_NAME_KEYWORD) +PG_KEYWORD("rows", ROWS, UNRESERVED_KEYWORD) +PG_KEYWORD("rule", RULE, UNRESERVED_KEYWORD) +PG_KEYWORD("sample", SAMPLE, UNRESERVED_KEYWORD) +PG_KEYWORD("savepoint", SAVEPOINT, UNRESERVED_KEYWORD) +PG_KEYWORD("schema", SCHEMA, UNRESERVED_KEYWORD) +PG_KEYWORD("schemas", SCHEMAS, UNRESERVED_KEYWORD) +PG_KEYWORD("scroll", SCROLL, UNRESERVED_KEYWORD) +PG_KEYWORD("search", SEARCH, UNRESERVED_KEYWORD) +PG_KEYWORD("second", SECOND_P, UNRESERVED_KEYWORD) +PG_KEYWORD("seconds", SECONDS_P, UNRESERVED_KEYWORD) +PG_KEYWORD("security", SECURITY, UNRESERVED_KEYWORD) +PG_KEYWORD("select", SELECT, RESERVED_KEYWORD) +PG_KEYWORD("sequence", SEQUENCE, UNRESERVED_KEYWORD) +PG_KEYWORD("sequences", SEQUENCES, UNRESERVED_KEYWORD) +PG_KEYWORD("serializable", SERIALIZABLE, UNRESERVED_KEYWORD) +PG_KEYWORD("server", SERVER, UNRESERVED_KEYWORD) +PG_KEYWORD("session", SESSION, UNRESERVED_KEYWORD) +PG_KEYWORD("session_user", SESSION_USER, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("set", SET, UNRESERVED_KEYWORD) +PG_KEYWORD("setof", SETOF, COL_NAME_KEYWORD) +PG_KEYWORD("sets", SETS, UNRESERVED_KEYWORD) +PG_KEYWORD("share", SHARE, UNRESERVED_KEYWORD) +PG_KEYWORD("show", SHOW, UNRESERVED_KEYWORD) +PG_KEYWORD("similar", SIMILAR, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("simple", SIMPLE, UNRESERVED_KEYWORD) +PG_KEYWORD("skip", SKIP, UNRESERVED_KEYWORD) +PG_KEYWORD("smallint", SMALLINT, COL_NAME_KEYWORD) +PG_KEYWORD("snapshot", SNAPSHOT, UNRESERVED_KEYWORD) +PG_KEYWORD("some", SOME, RESERVED_KEYWORD) +PG_KEYWORD("sql", SQL_P, UNRESERVED_KEYWORD) +PG_KEYWORD("stable", STABLE, UNRESERVED_KEYWORD) +PG_KEYWORD("standalone", STANDALONE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("start", START, UNRESERVED_KEYWORD) +PG_KEYWORD("statement", STATEMENT, UNRESERVED_KEYWORD) +PG_KEYWORD("statistics", STATISTICS, UNRESERVED_KEYWORD) +PG_KEYWORD("stdin", STDIN, UNRESERVED_KEYWORD) +PG_KEYWORD("stdout", STDOUT, UNRESERVED_KEYWORD) +PG_KEYWORD("storage", STORAGE, UNRESERVED_KEYWORD) +PG_KEYWORD("stored", STORED, UNRESERVED_KEYWORD) +PG_KEYWORD("strict", STRICT_P, UNRESERVED_KEYWORD) +PG_KEYWORD("strip", STRIP_P, UNRESERVED_KEYWORD) +PG_KEYWORD("struct", STRUCT, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("subscription", SUBSCRIPTION, UNRESERVED_KEYWORD) +PG_KEYWORD("substring", SUBSTRING, COL_NAME_KEYWORD) +PG_KEYWORD("summarize", SUMMARIZE, UNRESERVED_KEYWORD) +PG_KEYWORD("symmetric", SYMMETRIC, RESERVED_KEYWORD) +PG_KEYWORD("sysid", SYSID, UNRESERVED_KEYWORD) +PG_KEYWORD("system", SYSTEM_P, UNRESERVED_KEYWORD) +PG_KEYWORD("table", TABLE, RESERVED_KEYWORD) +PG_KEYWORD("tables", TABLES, UNRESERVED_KEYWORD) +PG_KEYWORD("tablesample", TABLESAMPLE, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("tablespace", TABLESPACE, UNRESERVED_KEYWORD) +PG_KEYWORD("temp", TEMP, UNRESERVED_KEYWORD) +PG_KEYWORD("template", TEMPLATE, UNRESERVED_KEYWORD) +PG_KEYWORD("temporary", TEMPORARY, UNRESERVED_KEYWORD) +PG_KEYWORD("text", TEXT_P, UNRESERVED_KEYWORD) +PG_KEYWORD("then", THEN, RESERVED_KEYWORD) +PG_KEYWORD("time", TIME, COL_NAME_KEYWORD) +PG_KEYWORD("timestamp", TIMESTAMP, COL_NAME_KEYWORD) +PG_KEYWORD("to", TO, RESERVED_KEYWORD) +PG_KEYWORD("trailing", TRAILING, RESERVED_KEYWORD) +PG_KEYWORD("transaction", TRANSACTION, UNRESERVED_KEYWORD) +PG_KEYWORD("transform", TRANSFORM, UNRESERVED_KEYWORD) +PG_KEYWORD("treat", TREAT, COL_NAME_KEYWORD) +PG_KEYWORD("trigger", TRIGGER, UNRESERVED_KEYWORD) +PG_KEYWORD("trim", TRIM, COL_NAME_KEYWORD) +PG_KEYWORD("true", TRUE_P, RESERVED_KEYWORD) +PG_KEYWORD("truncate", TRUNCATE, UNRESERVED_KEYWORD) +PG_KEYWORD("trusted", TRUSTED, UNRESERVED_KEYWORD) +PG_KEYWORD("try_cast", TRY_CAST, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("type", TYPE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("types", TYPES_P, UNRESERVED_KEYWORD) +PG_KEYWORD("unbounded", UNBOUNDED, UNRESERVED_KEYWORD) +PG_KEYWORD("uncommitted", UNCOMMITTED, UNRESERVED_KEYWORD) +PG_KEYWORD("unencrypted", UNENCRYPTED, UNRESERVED_KEYWORD) +PG_KEYWORD("union", UNION, RESERVED_KEYWORD) +PG_KEYWORD("unique", UNIQUE, RESERVED_KEYWORD) +PG_KEYWORD("unknown", UNKNOWN, UNRESERVED_KEYWORD) +PG_KEYWORD("unlisten", UNLISTEN, UNRESERVED_KEYWORD) +PG_KEYWORD("unlogged", UNLOGGED, UNRESERVED_KEYWORD) +PG_KEYWORD("until", UNTIL, UNRESERVED_KEYWORD) +PG_KEYWORD("update", UPDATE, UNRESERVED_KEYWORD) +PG_KEYWORD("user", USER, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("using", USING, RESERVED_KEYWORD) +PG_KEYWORD("vacuum", VACUUM, UNRESERVED_KEYWORD) +PG_KEYWORD("valid", VALID, UNRESERVED_KEYWORD) +PG_KEYWORD("validate", VALIDATE, UNRESERVED_KEYWORD) +PG_KEYWORD("validator", VALIDATOR, UNRESERVED_KEYWORD) +PG_KEYWORD("value", VALUE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("values", VALUES, COL_NAME_KEYWORD) +PG_KEYWORD("varchar", VARCHAR, COL_NAME_KEYWORD) +PG_KEYWORD("variadic", VARIADIC, RESERVED_KEYWORD) +PG_KEYWORD("varying", VARYING, UNRESERVED_KEYWORD) +PG_KEYWORD("verbose", VERBOSE, TYPE_FUNC_NAME_KEYWORD) +PG_KEYWORD("version", VERSION_P, UNRESERVED_KEYWORD) +PG_KEYWORD("view", VIEW, UNRESERVED_KEYWORD) +PG_KEYWORD("views", VIEWS, UNRESERVED_KEYWORD) +PG_KEYWORD("virtual", VIRTUAL, UNRESERVED_KEYWORD) +PG_KEYWORD("volatile", VOLATILE, UNRESERVED_KEYWORD) +PG_KEYWORD("when", WHEN, RESERVED_KEYWORD) +PG_KEYWORD("where", WHERE, RESERVED_KEYWORD) +PG_KEYWORD("whitespace", WHITESPACE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("window", WINDOW, RESERVED_KEYWORD) +PG_KEYWORD("with", WITH, RESERVED_KEYWORD) +PG_KEYWORD("within", WITHIN, UNRESERVED_KEYWORD) +PG_KEYWORD("without", WITHOUT, UNRESERVED_KEYWORD) +PG_KEYWORD("work", WORK, UNRESERVED_KEYWORD) +PG_KEYWORD("wrapper", WRAPPER, UNRESERVED_KEYWORD) +PG_KEYWORD("write", WRITE_P, UNRESERVED_KEYWORD) +PG_KEYWORD("xml", XML_P, UNRESERVED_KEYWORD) +PG_KEYWORD("xmlattributes", XMLATTRIBUTES, COL_NAME_KEYWORD) +PG_KEYWORD("xmlconcat", XMLCONCAT, COL_NAME_KEYWORD) +PG_KEYWORD("xmlelement", XMLELEMENT, COL_NAME_KEYWORD) +PG_KEYWORD("xmlexists", XMLEXISTS, COL_NAME_KEYWORD) +PG_KEYWORD("xmlforest", XMLFOREST, COL_NAME_KEYWORD) +PG_KEYWORD("xmlnamespaces", XMLNAMESPACES, COL_NAME_KEYWORD) +PG_KEYWORD("xmlparse", XMLPARSE, COL_NAME_KEYWORD) +PG_KEYWORD("xmlpi", XMLPI, COL_NAME_KEYWORD) +PG_KEYWORD("xmlroot", XMLROOT, COL_NAME_KEYWORD) +PG_KEYWORD("xmlserialize", XMLSERIALIZE, COL_NAME_KEYWORD) +PG_KEYWORD("xmltable", XMLTABLE, COL_NAME_KEYWORD) +PG_KEYWORD("year", YEAR_P, UNRESERVED_KEYWORD) +PG_KEYWORD("years", YEARS_P, UNRESERVED_KEYWORD) +PG_KEYWORD("yes", YES_P, UNRESERVED_KEYWORD) +PG_KEYWORD("zone", ZONE, UNRESERVED_KEYWORD) + +}; + +const int NumScanKeywords = lengthof(ScanKeywords); +} // namespace duckdb_libpgquery + + +// LICENSE_CHANGE_END + + +namespace duckdb_libpgquery { + +/* + * raw_parser + * Given a query in string form, do lexical and grammatical analysis. + * + * Returns a list of raw (un-analyzed) parse trees. The immediate elements + * of the list are always PGRawStmt nodes. + */ +PGList *raw_parser(const char *str) { + core_yyscan_t yyscanner; + base_yy_extra_type yyextra; + int yyresult; + + /* initialize the flex scanner */ + yyscanner = scanner_init(str, &yyextra.core_yy_extra, ScanKeywords, NumScanKeywords); + + /* base_yylex() only needs this much initialization */ + yyextra.have_lookahead = false; + + /* initialize the bison parser */ + parser_init(&yyextra); + + /* Parse! */ + yyresult = base_yyparse(yyscanner); + + /* Clean up (release memory) */ + scanner_finish(yyscanner); + + if (yyresult) /* error */ + return NIL; + + return yyextra.parsetree; +} + +bool is_keyword(const char *text) { + return ScanKeywordLookup(text, ScanKeywords, NumScanKeywords) != NULL; +} + +std::vector keyword_list() { + std::vector result; + for(size_t i = 0; i < NumScanKeywords; i++) { + PGKeyword keyword; + keyword.text = ScanKeywords[i].name; + switch(ScanKeywords[i].category) { + case UNRESERVED_KEYWORD: + keyword.category = PGKeywordCategory::PG_KEYWORD_UNRESERVED; + break; + case RESERVED_KEYWORD: + keyword.category = PGKeywordCategory::PG_KEYWORD_RESERVED; + break; + case TYPE_FUNC_NAME_KEYWORD: + keyword.category = PGKeywordCategory::PG_KEYWORD_TYPE_FUNC; + break; + case COL_NAME_KEYWORD: + keyword.category = PGKeywordCategory::PG_KEYWORD_COL_NAME; + break; + } + result.push_back(keyword); + } + return result; +} + +std::vector tokenize(const char *str) { + core_yyscan_t yyscanner; + base_yy_extra_type yyextra; + + std::vector result; + yyscanner = scanner_init(str, &yyextra.core_yy_extra, ScanKeywords, NumScanKeywords); + yyextra.have_lookahead = false; + + while(true) { + YYSTYPE type; + YYLTYPE loc; + int token; + try { + token = base_yylex(&type, &loc, yyscanner); + } catch(...) { + token = 0; + } + if (token == 0) { + break; + } + PGSimplifiedToken current_token; + switch(token) { + case IDENT: + current_token.type = PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_IDENTIFIER; + break; + case ICONST: + case FCONST: + current_token.type = PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_NUMERIC_CONSTANT; + break; + case SCONST: + case BCONST: + case XCONST: + current_token.type = PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_STRING_CONSTANT; + break; + case Op: + case PARAM: + case COLON_EQUALS: + case EQUALS_GREATER: + case LESS_EQUALS: + case GREATER_EQUALS: + case NOT_EQUALS: + current_token.type = PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_OPERATOR; + break; + default: + if (token >= 255) { + // non-ascii value, probably a keyword + current_token.type = PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_KEYWORD; + } else { + // ascii value, probably an operator + current_token.type = PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_OPERATOR; + } + break; + } + current_token.start = loc; + result.push_back(current_token); + } + + scanner_finish(yyscanner); + return result; +} + + + +/* + * Intermediate filter between parser and core lexer (core_yylex in scan.l). + * + * This filter is needed because in some cases the standard SQL grammar + * requires more than one token lookahead. We reduce these cases to one-token + * lookahead by replacing tokens here, in order to keep the grammar LALR(1). + * + * Using a filter is simpler than trying to recognize multiword tokens + * directly in scan.l, because we'd have to allow for comments between the + * words. Furthermore it's not clear how to do that without re-introducing + * scanner backtrack, which would cost more performance than this filter + * layer does. + * + * The filter also provides a convenient place to translate between + * the core_YYSTYPE and YYSTYPE representations (which are really the + * same thing anyway, but notationally they're different). + */ +int base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner) { + base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); + int cur_token; + int next_token; + int cur_token_length; + YYLTYPE cur_yylloc; + + /* Get next token --- we might already have it */ + if (yyextra->have_lookahead) { + cur_token = yyextra->lookahead_token; + lvalp->core_yystype = yyextra->lookahead_yylval; + *llocp = yyextra->lookahead_yylloc; + *(yyextra->lookahead_end) = yyextra->lookahead_hold_char; + yyextra->have_lookahead = false; + } else + cur_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner); + + /* + * If this token isn't one that requires lookahead, just return it. If it + * does, determine the token length. (We could get that via strlen(), but + * since we have such a small set of possibilities, hardwiring seems + * feasible and more efficient.) + */ + switch (cur_token) { + case NOT: + cur_token_length = 3; + break; + case NULLS_P: + cur_token_length = 5; + break; + case WITH: + cur_token_length = 4; + break; + default: + return cur_token; + } + + /* + * Identify end+1 of current token. core_yylex() has temporarily stored a + * '\0' here, and will undo that when we call it again. We need to redo + * it to fully revert the lookahead call for error reporting purposes. + */ + yyextra->lookahead_end = yyextra->core_yy_extra.scanbuf + *llocp + cur_token_length; + Assert(*(yyextra->lookahead_end) == '\0'); + + /* + * Save and restore *llocp around the call. It might look like we could + * avoid this by just passing &lookahead_yylloc to core_yylex(), but that + * does not work because flex actually holds onto the last-passed pointer + * internally, and will use that for error reporting. We need any error + * reports to point to the current token, not the next one. + */ + cur_yylloc = *llocp; + + /* Get next token, saving outputs into lookahead variables */ + next_token = core_yylex(&(yyextra->lookahead_yylval), llocp, yyscanner); + yyextra->lookahead_token = next_token; + yyextra->lookahead_yylloc = *llocp; + + *llocp = cur_yylloc; + + /* Now revert the un-truncation of the current token */ + yyextra->lookahead_hold_char = *(yyextra->lookahead_end); + *(yyextra->lookahead_end) = '\0'; + + yyextra->have_lookahead = true; + + /* Replace cur_token if needed, based on lookahead */ + switch (cur_token) { + case NOT: + /* Replace NOT by NOT_LA if it's followed by BETWEEN, IN, etc */ + switch (next_token) { + case BETWEEN: + case IN_P: + case LIKE: + case ILIKE: + case SIMILAR: + cur_token = NOT_LA; + break; + } + break; + + case NULLS_P: + /* Replace NULLS_P by NULLS_LA if it's followed by FIRST or LAST */ + switch (next_token) { + case FIRST_P: + case LAST_P: + cur_token = NULLS_LA; + break; + } + break; + + case WITH: + /* Replace WITH by WITH_LA if it's followed by TIME or ORDINALITY */ + switch (next_token) { + case TIME: + case ORDINALITY: + cur_token = WITH_LA; + break; + } + break; + } + + return cur_token; +} + +} + +// LICENSE_CHANGE_END + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 +// See the end of this file for a list + +#line 1 "third_party/libpg_query/src_backend_parser_scan.cpp" +/*------------------------------------------------------------------------- + * + * scan.l + * lexical scanner for PostgreSQL + * + * NOTE NOTE NOTE: + * + * The rules in this file must be kept in sync with src/fe_utils/psqlscan.l! + * + * The rules are designed so that the scanner never has to backtrack, + * in the sense that there is always a rule that can match the input + * consumed so far (the rule action may internally throw back some input + * with yyless(), however). As explained in the flex manual, this makes + * for a useful speed increase --- about a third faster than a plain -CF + * lexer, in simple testing. The extra complexity is mostly in the rules + * for handling float numbers and continued string literals. If you change + * the lexical rules, verify that you haven't broken the no-backtrack ' + * property by running flex with the "-b" option and checking that the + * resulting "lex.backup" file says that no backing up is needed. (As of + * Postgres 9.2, this check is made automatically by the Makefile.) + * + * + * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/backend/parser/scan.l + * + *------------------------------------------------------------------------- + */ +#include +//#include + + + + /* only needed for GUC variables */ + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 +// See the end of this file for a list + +/*------------------------------------------------------------------------- + * + * pg_wchar.h + * multibyte-character support + * + * Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/mb/pg_wchar.h + * + * NOTES + * This is used both by the backend and by libpq, but should not be + * included by libpq client programs. In particular, a libpq client + * should not assume that the encoding IDs used by the version of libpq + * it's linked to match up with the IDs declared here. + * + *------------------------------------------------------------------------- + */ + + +#include + +/* + * The pg_wchar type + */ +namespace duckdb_libpgquery { +typedef unsigned int pg_wchar; +} + +// LICENSE_CHANGE_END + + +#include + +#line 43 "third_party/libpg_query/src_backend_parser_scan.cpp" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 6 +#define YY_FLEX_SUBMINOR_VERSION 4 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +#ifdef yy_create_buffer +#define core_yy_create_buffer_ALREADY_DEFINED +#else +#define yy_create_buffer core_yy_create_buffer +#endif + +#ifdef yy_delete_buffer +#define core_yy_delete_buffer_ALREADY_DEFINED +#else +#define yy_delete_buffer core_yy_delete_buffer +#endif + +#ifdef yy_scan_buffer +#define core_yy_scan_buffer_ALREADY_DEFINED +#else +#define yy_scan_buffer core_yy_scan_buffer +#endif + +#ifdef yy_scan_string +#define core_yy_scan_string_ALREADY_DEFINED +#else +#define yy_scan_string core_yy_scan_string +#endif + +#ifdef yy_scan_bytes +#define core_yy_scan_bytes_ALREADY_DEFINED +#else +#define yy_scan_bytes core_yy_scan_bytes +#endif + +#ifdef yy_init_buffer +#define core_yy_init_buffer_ALREADY_DEFINED +#else +#define yy_init_buffer core_yy_init_buffer +#endif + +#ifdef yy_flush_buffer +#define core_yy_flush_buffer_ALREADY_DEFINED +#else +#define yy_flush_buffer core_yy_flush_buffer +#endif + +#ifdef yy_load_buffer_state +#define core_yy_load_buffer_state_ALREADY_DEFINED +#else +#define yy_load_buffer_state core_yy_load_buffer_state +#endif + +#ifdef yy_switch_to_buffer +#define core_yy_switch_to_buffer_ALREADY_DEFINED +#else +#define yy_switch_to_buffer core_yy_switch_to_buffer +#endif + +#ifdef yypush_buffer_state +#define core_yypush_buffer_state_ALREADY_DEFINED +#else +#define yypush_buffer_state core_yypush_buffer_state +#endif + +#ifdef yypop_buffer_state +#define core_yypop_buffer_state_ALREADY_DEFINED +#else +#define yypop_buffer_state core_yypop_buffer_state +#endif + +#ifdef yyensure_buffer_stack +#define core_yyensure_buffer_stack_ALREADY_DEFINED +#else +#define yyensure_buffer_stack core_yyensure_buffer_stack +#endif + +#ifdef yylex +#define core_yylex_ALREADY_DEFINED +#else +#define yylex core_yylex +#endif + +#ifdef yyrestart +#define core_yyrestart_ALREADY_DEFINED +#else +#define yyrestart core_yyrestart +#endif + +#ifdef yylex_init +#define core_yylex_init_ALREADY_DEFINED +#else +#define yylex_init core_yylex_init +#endif + +#ifdef yylex_init_extra +#define core_yylex_init_extra_ALREADY_DEFINED +#else +#define yylex_init_extra core_yylex_init_extra +#endif + +#ifdef yylex_destroy +#define core_yylex_destroy_ALREADY_DEFINED +#else +#define yylex_destroy core_yylex_destroy +#endif + +#ifdef yyget_debug +#define core_yyget_debug_ALREADY_DEFINED +#else +#define yyget_debug core_yyget_debug +#endif + +#ifdef yyset_debug +#define core_yyset_debug_ALREADY_DEFINED +#else +#define yyset_debug core_yyset_debug +#endif + +#ifdef yyget_extra +#define core_yyget_extra_ALREADY_DEFINED +#else +#define yyget_extra core_yyget_extra +#endif + +#ifdef yyset_extra +#define core_yyset_extra_ALREADY_DEFINED +#else +#define yyset_extra core_yyset_extra +#endif + +#ifdef yyget_in +#define core_yyget_in_ALREADY_DEFINED +#else +#define yyget_in core_yyget_in +#endif + +#ifdef yyset_in +#define core_yyset_in_ALREADY_DEFINED +#else +#define yyset_in core_yyset_in +#endif + +#ifdef yyget_out +#define core_yyget_out_ALREADY_DEFINED +#else +#define yyget_out core_yyget_out +#endif + +#ifdef yyset_out +#define core_yyset_out_ALREADY_DEFINED +#else +#define yyset_out core_yyset_out +#endif + +#ifdef yyget_leng +#define core_yyget_leng_ALREADY_DEFINED +#else +#define yyget_leng core_yyget_leng +#endif + +#ifdef yyget_text +#define core_yyget_text_ALREADY_DEFINED +#else +#define yyget_text core_yyget_text +#endif + +#ifdef yyget_lineno +#define core_yyget_lineno_ALREADY_DEFINED +#else +#define yyget_lineno core_yyget_lineno +#endif + +#ifdef yyset_lineno +#define core_yyset_lineno_ALREADY_DEFINED +#else +#define yyset_lineno core_yyset_lineno +#endif + +#ifdef yyget_column +#define core_yyget_column_ALREADY_DEFINED +#else +#define yyget_column core_yyget_column +#endif + +#ifdef yyset_column +#define core_yyset_column_ALREADY_DEFINED +#else +#define yyset_column core_yyset_column +#endif + +#ifdef yywrap +#define core_yywrap_ALREADY_DEFINED +#else +#define yywrap core_yywrap +#endif + +#ifdef yyget_lval +#define core_yyget_lval_ALREADY_DEFINED +#else +#define yyget_lval core_yyget_lval +#endif + +#ifdef yyset_lval +#define core_yyset_lval_ALREADY_DEFINED +#else +#define yyset_lval core_yyset_lval +#endif + +#ifdef yyget_lloc +#define core_yyget_lloc_ALREADY_DEFINED +#else +#define yyget_lloc core_yyget_lloc +#endif + +#ifdef yyset_lloc +#define core_yyset_lloc_ALREADY_DEFINED +#else +#define yyset_lloc core_yyset_lloc +#endif + +#ifdef yyalloc +#define core_yyalloc_ALREADY_DEFINED +#else +#define yyalloc core_yyalloc +#endif + +#ifdef yyrealloc +#define core_yyrealloc_ALREADY_DEFINED +#else +#define yyrealloc core_yyrealloc +#endif + +#ifdef yyfree +#define core_yyfree_ALREADY_DEFINED +#else +#define yyfree core_yyfree +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include +#include +#include +#include + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H +namespace duckdb_libpgquery { + +/* C99 systems have . Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +typedef uint64_t flex_uint64_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef SIZE_MAX +#define SIZE_MAX (~(size_t)0) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +/* begin standard C++ headers. */ + +/* TODO: this is always defined, so inline it */ +#define yyconst const + +#if defined(__GNUC__) && __GNUC__ >= 3 +#define yynoreturn __attribute__((__noreturn__)) +#else +#define yynoreturn +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an + * integer in range [0..255] for use as an array index. + */ +#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin , yyscanner ) +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + #define YY_LESS_LINENO(n) + #define YY_LINENO_REWIND_TO(ptr) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + int yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + yy_size_t yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ + ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ + : NULL) +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +void yyrestart ( FILE *input_file , yyscan_t yyscanner ); +void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); +void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); +void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); +void yypop_buffer_state ( yyscan_t yyscanner ); + +static void yyensure_buffer_stack ( yyscan_t yyscanner ); +static void yy_load_buffer_state ( yyscan_t yyscanner ); +static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner ); +#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner) + +YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); +YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, yy_size_t len , yyscan_t yyscanner ); + +void *yyalloc ( yy_size_t , yyscan_t yyscanner ); +void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); +void yyfree ( void * , yyscan_t yyscanner ); + +#define yy_new_buffer yy_create_buffer +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +/* Begin user sect3 */ + +#define core_yywrap(yyscanner) (/*CONSTCOND*/1) +#define YY_SKIP_YYWRAP +typedef flex_uint8_t YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +static yy_state_type yy_get_previous_state ( yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner); +static int yy_get_next_buffer ( yyscan_t yyscanner ); +static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ + yyleng = (yy_size_t) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yyg->yy_c_buf_p = yy_cp; +#define YY_NUM_RULES 83 +#define YY_END_OF_BUFFER 84 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static const flex_int16_t yy_accept[296] = + { 0, + 0, 0, 12, 12, 0, 0, 0, 0, 11, 11, + 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, + 0, 0, 28, 28, 0, 0, 84, 82, 1, 1, + 72, 49, 82, 71, 72, 19, 71, 71, 71, 71, + 71, 75, 71, 71, 71, 71, 82, 81, 81, 81, + 81, 81, 81, 12, 9, 5, 5, 6, 6, 58, + 51, 11, 16, 32, 32, 22, 42, 31, 22, 46, + 46, 48, 52, 54, 53, 53, 54, 54, 24, 27, + 26, 26, 27, 27, 35, 36, 35, 1, 72, 70, + 43, 73, 44, 65, 1, 63, 61, 76, 2, 76, + + 75, 79, 60, 62, 67, 69, 66, 68, 74, 81, + 8, 20, 18, 59, 15, 12, 9, 9, 10, 5, + 7, 4, 3, 58, 57, 11, 16, 16, 17, 32, + 22, 22, 30, 23, 38, 39, 37, 37, 38, 31, + 46, 45, 47, 53, 53, 55, 24, 24, 25, 26, + 26, 28, 37, 37, 44, 1, 1, 64, 2, 77, + 76, 80, 78, 50, 21, 9, 14, 10, 9, 3, + 16, 13, 17, 16, 22, 41, 23, 22, 39, 37, + 37, 40, 47, 53, 55, 24, 25, 24, 26, 28, + 37, 37, 9, 9, 9, 9, 16, 16, 16, 16, + + 22, 22, 22, 22, 39, 37, 37, 40, 55, 24, + 24, 24, 24, 28, 37, 37, 9, 9, 9, 9, + 9, 16, 16, 16, 16, 16, 22, 22, 22, 22, + 22, 37, 37, 55, 24, 24, 24, 24, 24, 28, + 37, 37, 9, 16, 22, 37, 33, 55, 24, 28, + 37, 34, 37, 55, 28, 37, 37, 55, 55, 55, + 28, 28, 28, 37, 37, 55, 55, 28, 28, 37, + 56, 55, 55, 55, 55, 29, 28, 28, 28, 28, + 55, 55, 55, 55, 55, 28, 28, 28, 28, 28, + 55, 55, 28, 28, 0 + + } ; + +static const YY_CHAR yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 2, 4, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 5, 6, 1, 7, 8, 9, 10, 11, + 11, 12, 13, 11, 14, 15, 16, 17, 17, 17, + 17, 17, 17, 17, 17, 18, 18, 19, 11, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 28, + 30, 30, 30, 30, 30, 30, 30, 31, 30, 32, + 30, 30, 33, 30, 34, 30, 30, 35, 30, 30, + 11, 36, 11, 8, 30, 24, 25, 26, 27, 28, + + 29, 28, 30, 30, 30, 30, 30, 30, 30, 31, + 30, 32, 30, 30, 33, 30, 37, 30, 30, 38, + 30, 30, 1, 24, 1, 24, 1, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + 30, 30, 30, 30, 30 + } ; + +static const YY_CHAR yy_meta[39] = + { 0, + 1, 1, 2, 2, 3, 4, 5, 3, 3, 6, + 1, 7, 3, 3, 1, 7, 8, 8, 1, 3, + 3, 3, 1, 3, 9, 9, 9, 9, 9, 10, + 10, 10, 10, 10, 10, 11, 10, 10 + } ; + +static const flex_int16_t yy_base[363] = + { 0, + 0, 0, 431, 430, 34, 54, 428, 419, 414, 409, + 41, 50, 408, 402, 38, 54, 405, 393, 85, 121, + 388, 386, 157, 193, 37, 46, 395, 1208, 77, 81, + 362, 1208, 83, 0, 0, 1208, 1208, 370, 50, 76, + 365, 80, 50, 81, 354, 349, 87, 0, 359, 347, + 346, 345, 343, 0, 104, 0, 0, 80, 329, 0, + 334, 0, 112, 0, 0, 126, 100, 0, 129, 0, + 0, 328, 328, 1208, 108, 142, 313, 291, 160, 1208, + 145, 148, 300, 283, 1208, 1208, 119, 163, 0, 0, + 1208, 103, 304, 0, 226, 282, 1208, 151, 0, 158, + + 164, 171, 1208, 1208, 0, 0, 0, 0, 124, 0, + 1208, 1208, 1208, 180, 1208, 0, 196, 199, 283, 0, + 192, 1208, 0, 0, 1208, 0, 212, 215, 276, 0, + 218, 241, 1208, 268, 1208, 261, 0, 0, 0, 0, + 0, 1208, 270, 250, 0, 241, 254, 257, 259, 260, + 0, 237, 0, 0, 262, 0, 267, 0, 0, 1208, + 194, 160, 188, 1208, 1208, 282, 1208, 252, 291, 0, + 296, 1208, 251, 299, 305, 1208, 235, 314, 224, 0, + 0, 0, 230, 0, 209, 319, 219, 322, 0, 201, + 0, 0, 328, 335, 341, 344, 348, 357, 361, 364, + + 370, 377, 383, 386, 1208, 0, 0, 1208, 199, 390, + 399, 403, 406, 167, 0, 0, 412, 419, 425, 428, + 434, 441, 447, 450, 454, 463, 467, 470, 476, 485, + 489, 0, 0, 151, 492, 498, 505, 514, 518, 140, + 0, 0, 521, 527, 534, 0, 1208, 128, 540, 125, + 0, 1208, 0, 543, 548, 0, 0, 557, 0, 113, + 562, 0, 99, 0, 0, 55, 571, 42, 576, 0, + 1208, 585, 590, 599, 604, 1208, 613, 618, 627, 632, + 641, 646, 655, 660, 669, 674, 683, 688, 697, 702, + 711, 0, 716, 0, 1208, 730, 741, 752, 763, 774, + + 785, 796, 807, 818, 829, 838, 841, 847, 857, 868, + 879, 890, 901, 911, 922, 933, 940, 946, 956, 965, + 970, 970, 972, 974, 979, 989, 1000, 1004, 1006, 1015, + 1026, 1037, 1041, 1043, 1045, 1054, 1058, 1060, 1069, 1080, + 1091, 1095, 1097, 1106, 1110, 1112, 1114, 1116, 1118, 1120, + 1122, 1124, 1126, 1128, 1130, 1139, 1150, 1154, 1163, 1174, + 1185, 1196 + } ; + +static const flex_int16_t yy_def[363] = + { 0, + 295, 1, 296, 296, 297, 297, 298, 298, 299, 299, + 300, 300, 301, 301, 302, 302, 298, 298, 303, 303, + 301, 301, 304, 304, 305, 305, 295, 295, 295, 295, + 306, 295, 307, 306, 306, 295, 295, 306, 306, 295, + 306, 295, 295, 306, 306, 306, 295, 308, 308, 308, + 308, 308, 308, 309, 295, 310, 310, 295, 295, 311, + 295, 312, 295, 313, 313, 295, 314, 315, 295, 316, + 316, 317, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 306, 306, + 295, 295, 318, 306, 319, 306, 295, 295, 320, 295, + + 295, 295, 295, 295, 306, 306, 306, 306, 295, 308, + 295, 295, 295, 295, 295, 309, 295, 295, 295, 310, + 295, 295, 321, 311, 295, 312, 295, 295, 295, 313, + 295, 295, 295, 295, 295, 295, 322, 323, 324, 315, + 316, 295, 325, 295, 326, 295, 295, 295, 295, 295, + 327, 295, 328, 329, 318, 319, 319, 306, 320, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 330, 321, + 295, 295, 295, 331, 295, 295, 295, 332, 295, 333, + 334, 335, 325, 326, 295, 295, 295, 336, 327, 295, + 337, 338, 339, 330, 330, 330, 340, 331, 331, 331, + + 341, 332, 332, 332, 295, 342, 343, 295, 295, 344, + 336, 336, 336, 295, 345, 346, 339, 339, 295, 339, + 330, 340, 340, 295, 340, 331, 341, 341, 295, 341, + 332, 347, 348, 295, 344, 344, 295, 344, 336, 295, + 349, 350, 339, 340, 341, 351, 295, 295, 344, 295, + 352, 295, 353, 295, 295, 354, 355, 295, 356, 295, + 295, 357, 295, 358, 348, 295, 359, 295, 360, 350, + 295, 359, 359, 361, 359, 295, 360, 360, 362, 360, + 359, 359, 295, 359, 359, 360, 360, 295, 360, 360, + 361, 356, 362, 357, 0, 295, 295, 295, 295, 295, + + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295 + } ; + +static const flex_int16_t yy_nxt[1247] = + { 0, + 28, 29, 30, 29, 31, 32, 33, 34, 35, 36, + 37, 38, 34, 39, 40, 41, 42, 42, 43, 44, + 45, 46, 47, 35, 48, 49, 48, 48, 50, 48, + 51, 48, 48, 52, 53, 28, 52, 53, 57, 86, + 71, 57, 57, 65, 72, 58, 57, 57, 86, 59, + 66, 276, 65, 57, 57, 57, 71, 57, 57, 66, + 72, 57, 57, 95, 271, 58, 57, 57, 103, 59, + 104, 96, 87, 57, 57, 57, 67, 57, 88, 88, + 88, 87, 88, 88, 88, 67, 75, 76, 75, 91, + 97, 121, 98, 98, 100, 122, 101, 101, 77, 92, + + 92, 105, 106, 109, 109, 117, 118, 118, 102, 144, + 144, 144, 269, 127, 128, 128, 136, 119, 78, 92, + 92, 78, 75, 76, 75, 129, 267, 131, 132, 132, + 131, 132, 132, 137, 77, 133, 138, 139, 133, 134, + 109, 109, 134, 144, 144, 144, 150, 150, 150, 150, + 150, 150, 153, 255, 78, 154, 254, 78, 81, 82, + 81, 147, 148, 148, 88, 88, 88, 98, 98, 133, + 83, 250, 160, 149, 161, 161, 163, 163, 100, 102, + 101, 101, 248, 162, 162, 164, 102, 163, 163, 165, + 84, 240, 102, 84, 81, 82, 81, 117, 118, 118, + + 166, 166, 166, 121, 163, 163, 83, 122, 167, 119, + 161, 161, 168, 127, 128, 128, 171, 171, 171, 131, + 132, 132, 102, 234, 172, 129, 84, 214, 173, 84, + 157, 134, 210, 157, 157, 209, 142, 157, 157, 157, + 205, 157, 175, 175, 175, 157, 157, 157, 201, 157, + 176, 144, 144, 144, 177, 147, 148, 148, 186, 186, + 186, 150, 150, 150, 197, 193, 176, 149, 91, 190, + 187, 157, 188, 185, 157, 157, 142, 179, 157, 157, + 157, 178, 157, 166, 166, 166, 157, 157, 157, 174, + 157, 167, 195, 118, 118, 168, 169, 171, 171, 171, + + 199, 128, 128, 158, 196, 172, 175, 175, 175, 173, + 91, 152, 200, 151, 176, 203, 132, 132, 177, 146, + 186, 186, 186, 212, 148, 148, 145, 204, 176, 218, + 219, 219, 187, 125, 142, 213, 195, 118, 118, 125, + 123, 220, 195, 118, 118, 195, 118, 118, 196, 223, + 224, 224, 115, 114, 196, 113, 112, 221, 199, 128, + 128, 225, 199, 128, 128, 199, 128, 128, 111, 108, + 200, 228, 229, 229, 200, 107, 99, 226, 203, 132, + 132, 94, 90, 230, 203, 132, 132, 203, 132, 132, + 204, 236, 237, 237, 295, 79, 204, 79, 73, 231, + + 212, 148, 148, 238, 212, 148, 148, 212, 148, 148, + 73, 69, 213, 218, 219, 219, 213, 69, 63, 239, + 218, 219, 219, 63, 61, 220, 166, 166, 166, 218, + 219, 219, 220, 61, 167, 195, 118, 118, 168, 55, + 55, 243, 223, 224, 224, 295, 295, 221, 223, 224, + 224, 171, 171, 171, 225, 223, 224, 224, 295, 172, + 225, 295, 295, 173, 199, 128, 128, 244, 228, 229, + 229, 228, 229, 229, 295, 295, 226, 175, 175, 175, + 230, 295, 295, 230, 295, 176, 228, 229, 229, 177, + 203, 132, 132, 236, 237, 237, 295, 295, 245, 236, + + 237, 237, 231, 295, 295, 238, 186, 186, 186, 295, + 295, 238, 295, 295, 176, 236, 237, 237, 187, 212, + 148, 148, 218, 219, 219, 295, 295, 249, 223, 224, + 224, 239, 295, 295, 243, 228, 229, 229, 295, 295, + 244, 236, 237, 237, 258, 258, 258, 245, 295, 261, + 261, 261, 259, 249, 295, 295, 260, 262, 258, 258, + 258, 263, 295, 261, 261, 261, 259, 295, 295, 295, + 260, 262, 273, 258, 258, 263, 295, 278, 261, 261, + 274, 295, 295, 295, 275, 279, 273, 258, 258, 280, + 295, 273, 258, 258, 274, 295, 295, 295, 275, 274, + + 282, 283, 283, 275, 295, 273, 258, 258, 274, 295, + 295, 295, 284, 274, 278, 261, 261, 285, 295, 278, + 261, 261, 279, 295, 295, 295, 280, 279, 287, 288, + 288, 280, 295, 278, 261, 261, 279, 295, 295, 295, + 289, 279, 273, 258, 258, 290, 295, 273, 258, 258, + 291, 295, 295, 295, 275, 291, 258, 258, 258, 275, + 295, 273, 258, 258, 292, 295, 295, 295, 260, 291, + 273, 258, 258, 285, 295, 278, 261, 261, 274, 295, + 295, 295, 285, 293, 278, 261, 261, 280, 295, 261, + 261, 261, 293, 295, 295, 295, 280, 294, 278, 261, + + 261, 263, 295, 278, 261, 261, 293, 295, 295, 295, + 290, 279, 282, 283, 283, 290, 295, 287, 288, 288, + 274, 295, 295, 295, 284, 279, 295, 295, 295, 289, + 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, + 54, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 60, 60, 60, 60, 60, 60, 60, 60, + 60, 60, 60, 62, 62, 62, 62, 62, 62, 62, + 62, 62, 62, 62, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 68, 68, 68, 68, 68, + 68, 68, 68, 68, 68, 68, 70, 70, 70, 70, + + 70, 70, 70, 70, 70, 70, 70, 74, 74, 74, + 74, 74, 74, 74, 74, 74, 74, 74, 80, 80, + 80, 80, 80, 80, 80, 80, 80, 80, 80, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 89, 295, 295, 295, 89, 93, 295, 295, 93, 93, + 93, 110, 295, 295, 110, 110, 110, 116, 116, 116, + 116, 116, 295, 116, 116, 116, 116, 116, 120, 120, + 120, 120, 120, 120, 295, 120, 120, 120, 120, 124, + 124, 124, 295, 124, 124, 124, 124, 124, 124, 124, + 126, 126, 126, 126, 126, 295, 126, 126, 126, 126, + + 126, 130, 130, 130, 130, 130, 295, 130, 130, 130, + 130, 135, 135, 135, 135, 135, 135, 135, 135, 135, + 135, 135, 140, 140, 140, 140, 140, 295, 140, 140, + 140, 140, 140, 141, 141, 141, 141, 295, 141, 141, + 141, 141, 141, 141, 143, 295, 295, 295, 143, 143, + 155, 295, 295, 155, 155, 155, 156, 295, 156, 156, + 156, 156, 156, 156, 156, 156, 156, 159, 295, 295, + 295, 159, 170, 295, 295, 295, 170, 180, 180, 181, + 181, 182, 182, 183, 295, 295, 183, 183, 183, 184, + 295, 184, 184, 184, 184, 184, 184, 184, 184, 184, + + 189, 295, 189, 189, 189, 189, 189, 189, 189, 189, + 189, 191, 191, 192, 192, 194, 194, 194, 194, 194, + 194, 194, 194, 194, 194, 194, 198, 198, 198, 198, + 198, 198, 198, 198, 198, 198, 198, 202, 202, 202, + 202, 202, 202, 202, 202, 202, 202, 202, 206, 206, + 207, 207, 208, 208, 211, 211, 211, 211, 211, 211, + 211, 211, 211, 211, 211, 215, 215, 216, 216, 217, + 217, 217, 217, 217, 217, 217, 217, 217, 217, 217, + 222, 222, 222, 222, 222, 222, 222, 222, 222, 222, + 222, 227, 227, 227, 227, 227, 227, 227, 227, 227, + + 227, 227, 232, 232, 233, 233, 235, 235, 235, 235, + 235, 235, 235, 235, 235, 235, 235, 241, 241, 242, + 242, 246, 246, 247, 247, 251, 251, 252, 252, 253, + 253, 256, 256, 257, 257, 264, 264, 265, 265, 266, + 266, 266, 266, 266, 295, 266, 266, 266, 266, 266, + 268, 268, 268, 268, 268, 295, 268, 268, 268, 268, + 268, 270, 270, 272, 272, 272, 272, 272, 272, 272, + 272, 272, 272, 272, 277, 277, 277, 277, 277, 277, + 277, 277, 277, 277, 277, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 286, 286, 286, 286, + + 286, 286, 286, 286, 286, 286, 286, 27, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295 + } ; + +static const flex_int16_t yy_chk[1247] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 5, 25, + 15, 5, 5, 11, 15, 5, 5, 5, 26, 5, + 11, 268, 12, 5, 5, 5, 16, 5, 6, 12, + 16, 6, 6, 39, 266, 6, 6, 6, 43, 6, + 43, 39, 25, 6, 6, 6, 11, 6, 29, 29, + 29, 26, 30, 30, 30, 12, 19, 19, 19, 33, + 40, 58, 40, 40, 42, 58, 42, 42, 19, 33, + + 33, 44, 44, 47, 47, 55, 55, 55, 42, 75, + 75, 75, 263, 63, 63, 63, 67, 55, 19, 92, + 92, 19, 20, 20, 20, 63, 260, 66, 66, 66, + 69, 69, 69, 67, 20, 66, 67, 67, 69, 66, + 109, 109, 69, 76, 76, 76, 81, 81, 81, 82, + 82, 82, 87, 250, 20, 87, 248, 20, 23, 23, + 23, 79, 79, 79, 88, 88, 88, 98, 98, 79, + 23, 240, 100, 79, 100, 100, 162, 162, 101, 98, + 101, 101, 234, 102, 102, 114, 100, 102, 102, 114, + 23, 214, 101, 23, 24, 24, 24, 117, 117, 117, + + 118, 118, 118, 121, 163, 163, 24, 121, 118, 117, + 161, 161, 118, 127, 127, 127, 128, 128, 128, 131, + 131, 131, 161, 209, 128, 127, 24, 190, 128, 24, + 95, 131, 187, 95, 95, 185, 183, 95, 95, 95, + 179, 95, 132, 132, 132, 95, 95, 95, 177, 95, + 132, 144, 144, 144, 132, 147, 147, 147, 148, 148, + 148, 150, 150, 150, 173, 168, 148, 147, 155, 152, + 148, 157, 149, 146, 157, 157, 143, 136, 157, 157, + 157, 134, 157, 166, 166, 166, 157, 157, 157, 129, + 157, 166, 169, 169, 169, 166, 119, 171, 171, 171, + + 174, 174, 174, 96, 169, 171, 175, 175, 175, 171, + 93, 84, 174, 83, 175, 178, 178, 178, 175, 78, + 186, 186, 186, 188, 188, 188, 77, 178, 186, 193, + 193, 193, 186, 73, 72, 188, 194, 194, 194, 61, + 59, 193, 195, 195, 195, 196, 196, 196, 194, 197, + 197, 197, 53, 52, 195, 51, 50, 196, 198, 198, + 198, 197, 199, 199, 199, 200, 200, 200, 49, 46, + 198, 201, 201, 201, 199, 45, 41, 200, 202, 202, + 202, 38, 31, 201, 203, 203, 203, 204, 204, 204, + 202, 210, 210, 210, 27, 22, 203, 21, 18, 204, + + 211, 211, 211, 210, 212, 212, 212, 213, 213, 213, + 17, 14, 211, 217, 217, 217, 212, 13, 10, 213, + 218, 218, 218, 9, 8, 217, 219, 219, 219, 220, + 220, 220, 218, 7, 219, 221, 221, 221, 219, 4, + 3, 220, 222, 222, 222, 0, 0, 221, 223, 223, + 223, 224, 224, 224, 222, 225, 225, 225, 0, 224, + 223, 0, 0, 224, 226, 226, 226, 225, 227, 227, + 227, 228, 228, 228, 0, 0, 226, 229, 229, 229, + 227, 0, 0, 228, 0, 229, 230, 230, 230, 229, + 231, 231, 231, 235, 235, 235, 0, 0, 230, 236, + + 236, 236, 231, 0, 0, 235, 237, 237, 237, 0, + 0, 236, 0, 0, 237, 238, 238, 238, 237, 239, + 239, 239, 243, 243, 243, 0, 0, 238, 244, 244, + 244, 239, 0, 0, 243, 245, 245, 245, 0, 0, + 244, 249, 249, 249, 254, 254, 254, 245, 0, 255, + 255, 255, 254, 249, 0, 0, 254, 255, 258, 258, + 258, 255, 0, 261, 261, 261, 258, 0, 0, 0, + 258, 261, 267, 267, 267, 261, 0, 269, 269, 269, + 267, 0, 0, 0, 267, 269, 272, 272, 272, 269, + 0, 273, 273, 273, 272, 0, 0, 0, 272, 273, + + 274, 274, 274, 273, 0, 275, 275, 275, 274, 0, + 0, 0, 274, 275, 277, 277, 277, 275, 0, 278, + 278, 278, 277, 0, 0, 0, 277, 278, 279, 279, + 279, 278, 0, 280, 280, 280, 279, 0, 0, 0, + 279, 280, 281, 281, 281, 280, 0, 282, 282, 282, + 281, 0, 0, 0, 281, 282, 283, 283, 283, 282, + 0, 284, 284, 284, 283, 0, 0, 0, 283, 284, + 285, 285, 285, 284, 0, 286, 286, 286, 285, 0, + 0, 0, 285, 286, 287, 287, 287, 286, 0, 288, + 288, 288, 287, 0, 0, 0, 287, 288, 289, 289, + + 289, 288, 0, 290, 290, 290, 289, 0, 0, 0, + 289, 290, 291, 291, 291, 290, 0, 293, 293, 293, + 291, 0, 0, 0, 291, 293, 0, 0, 0, 293, + 296, 296, 296, 296, 296, 296, 296, 296, 296, 296, + 296, 297, 297, 297, 297, 297, 297, 297, 297, 297, + 297, 297, 298, 298, 298, 298, 298, 298, 298, 298, + 298, 298, 298, 299, 299, 299, 299, 299, 299, 299, + 299, 299, 299, 299, 300, 300, 300, 300, 300, 300, + 300, 300, 300, 300, 300, 301, 301, 301, 301, 301, + 301, 301, 301, 301, 301, 301, 302, 302, 302, 302, + + 302, 302, 302, 302, 302, 302, 302, 303, 303, 303, + 303, 303, 303, 303, 303, 303, 303, 303, 304, 304, + 304, 304, 304, 304, 304, 304, 304, 304, 304, 305, + 305, 305, 305, 305, 305, 305, 305, 305, 305, 305, + 306, 0, 0, 0, 306, 307, 0, 0, 307, 307, + 307, 308, 0, 0, 308, 308, 308, 309, 309, 309, + 309, 309, 0, 309, 309, 309, 309, 309, 310, 310, + 310, 310, 310, 310, 0, 310, 310, 310, 310, 311, + 311, 311, 0, 311, 311, 311, 311, 311, 311, 311, + 312, 312, 312, 312, 312, 0, 312, 312, 312, 312, + + 312, 313, 313, 313, 313, 313, 0, 313, 313, 313, + 313, 314, 314, 314, 314, 314, 314, 314, 314, 314, + 314, 314, 315, 315, 315, 315, 315, 0, 315, 315, + 315, 315, 315, 316, 316, 316, 316, 0, 316, 316, + 316, 316, 316, 316, 317, 0, 0, 0, 317, 317, + 318, 0, 0, 318, 318, 318, 319, 0, 319, 319, + 319, 319, 319, 319, 319, 319, 319, 320, 0, 0, + 0, 320, 321, 0, 0, 0, 321, 322, 322, 323, + 323, 324, 324, 325, 0, 0, 325, 325, 325, 326, + 0, 326, 326, 326, 326, 326, 326, 326, 326, 326, + + 327, 0, 327, 327, 327, 327, 327, 327, 327, 327, + 327, 328, 328, 329, 329, 330, 330, 330, 330, 330, + 330, 330, 330, 330, 330, 330, 331, 331, 331, 331, + 331, 331, 331, 331, 331, 331, 331, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 333, 333, + 334, 334, 335, 335, 336, 336, 336, 336, 336, 336, + 336, 336, 336, 336, 336, 337, 337, 338, 338, 339, + 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, + 340, 340, 340, 340, 340, 340, 340, 340, 340, 340, + 340, 341, 341, 341, 341, 341, 341, 341, 341, 341, + + 341, 341, 342, 342, 343, 343, 344, 344, 344, 344, + 344, 344, 344, 344, 344, 344, 344, 345, 345, 346, + 346, 347, 347, 348, 348, 349, 349, 350, 350, 351, + 351, 352, 352, 353, 353, 354, 354, 355, 355, 356, + 356, 356, 356, 356, 0, 356, 356, 356, 356, 356, + 357, 357, 357, 357, 357, 0, 357, 357, 357, 357, + 357, 358, 358, 359, 359, 359, 359, 359, 359, 359, + 359, 359, 359, 359, 360, 360, 360, 360, 360, 360, + 360, 360, 360, 360, 360, 361, 361, 361, 361, 361, + 361, 361, 361, 361, 361, 361, 362, 362, 362, 362, + + 362, 362, 362, 362, 362, 362, 362, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, + 295, 295, 295, 295, 295, 295 + } ; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "third_party/libpg_query/scan.l" + +#line 46 "third_party/libpg_query/scan.l" + +/* LCOV_EXCL_START */ + +/* + * GUC variables. This is a DIRECT violation of the warning given at the + * head of gram.y, ie flex/bison code must not depend on any GUC variables; + * as such, changing their values can induce very unintuitive behavior. + * But we shall have to live with it until we can remove these variables. + */ + +int backslash_quote = PG_BACKSLASH_QUOTE_SAFE_ENCODING; +bool escape_string_warning = true; +bool standard_conforming_strings = true; + +/* + * Set the type of YYSTYPE. + */ +#define YYSTYPE core_YYSTYPE + +/* + * Set the type of yyextra. All state variables used by the scanner should + * be in yyextra, *not* statically allocated. + */ +#define YY_EXTRA_TYPE core_yy_extra_type * + +/* + * Each call to yylex must set yylloc to the location of the found token + * (expressed as a byte offset from the start of the input text). + * When we parse a token that requires multiple lexer rules to process, + * this should be done in the first such rule, else yylloc will point + * into the middle of the token. + */ +#define SET_YYLLOC() (*(yylloc) = yytext - yyextra->scanbuf) + +/* + * Advance yylloc by the given number of bytes. + */ +#define ADVANCE_YYLLOC(delta) ( *(yylloc) += (delta) ) + +#define startlit() ( yyextra->literallen = 0 ) +static void addlit(char *ytext, int yleng, core_yyscan_t yyscanner); +static void addlitchar(unsigned char ychar, core_yyscan_t yyscanner); +static char *litbufdup(core_yyscan_t yyscanner); +static char *litbuf_udeescape(unsigned char escape, core_yyscan_t yyscanner); +static unsigned char unescape_single_char(unsigned char c, core_yyscan_t yyscanner); +static int process_integer_literal(const char *token, YYSTYPE *lval); +static bool is_utf16_surrogate_first(pg_wchar c); +static bool is_utf16_surrogate_second(pg_wchar c); +static pg_wchar surrogate_pair_to_codepoint(pg_wchar first, pg_wchar second); +static void addunicode(pg_wchar c, yyscan_t yyscanner); +static bool check_uescapechar(unsigned char escape); + +#define yyerror(msg) scanner_yyerror(msg, yyscanner) + +#define lexer_errposition() scanner_errposition(*(yylloc), yyscanner) + +static void check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner); +static void check_escape_warning(core_yyscan_t yyscanner); + +/* + * Work around a bug in flex 2.5.35: it emits a couple of functions that + * it forgets to emit declarations for. Since we use -Wmissing-prototypes, + * this would cause warnings. Providing our own declarations should be + * harmless even when the bug gets fixed. + */ +extern int core_yyget_column(yyscan_t yyscanner); +extern void core_yyset_column(int column_no, yyscan_t yyscanner); + +#line 1151 "third_party/libpg_query/src_backend_parser_scan.cpp" +#define YY_NO_INPUT 1 +/* + * OK, here is a short description of lex/flex rules behavior. + * The longest pattern which matches an input string is always chosen. + * For equal-length patterns, the first occurring in the rules list is chosen. + * INITIAL is the starting state, to which all non-conditional rules apply. + * Exclusive states change parsing rules while the state is active. When in + * an exclusive state, only those rules defined for that state apply. + * + * We use exclusive states for quoted strings, extended comments, + * and to eliminate parsing troubles for numeric strings. + * Exclusive states: + * bit string literal + * extended C-style comments + * delimited identifiers (double-quoted identifiers) + * hexadecimal numeric string + * standard quoted strings + * extended quoted strings (support backslash escape sequences) + * $foo$ quoted strings + * quoted identifier with Unicode escapes + * end of a quoted identifier with Unicode escapes, UESCAPE can follow + * quoted string with Unicode escapes + * end of a quoted string with Unicode escapes, UESCAPE can follow + * Unicode surrogate pair in extended quoted string + * + * Remember to add an <> case whenever you add a new exclusive state! + * The default one is probably not the right thing. + */ + +/* + * In order to make the world safe for Windows and Mac clients as well as + * Unix ones, we accept either \n or \r as a newline. A DOS-style \r\n + * sequence will be seen as two successive newlines, but that doesn't cause ' + * any problems. Comments that start with -- and extend to the next + * newline are treated as equivalent to a single whitespace character. + * + * NOTE a fine point: if there is no newline following --, we will absorb + * everything to the end of the input as a comment. This is correct. Older + * versions of Postgres failed to recognize -- as a comment if the input + * did not end with a newline. + * + * XXX perhaps \f (formfeed) should be treated as a newline as well? + * + * XXX if you change the set of whitespace characters, fix scanner_isspace() + * to agree, and see also the plpgsql lexer. + */ +/* + * SQL requires at least one newline in the whitespace separating + * string literals that are to be concatenated. Silly, but who are we + * to argue? Note that {whitespace_with_newline} should not have * after + * it, whereas {whitespace} should generally have a * after it... + */ +/* + * To ensure that {quotecontinue} can be scanned without having to back up + * if the full pattern isn't matched, we include trailing whitespace in + * {quotestop}. This matches all cases where {quotecontinue} fails to match, + * except for {quote} followed by whitespace and just one "-" (not two, + * which would start a {comment}). To cover that we have {quotefail}. + * The actions for {quotestop} and {quotefail} must throw back characters + * beyond the quote proper. + */ +/* Bit string + * It is tempting to scan the string for only those characters + * which are allowed. However, this leads to silently swallowed + * characters if illegal characters are included in the string. + * For example, if xbinside is [01] then B'ABCD' is interpreted + * as a zero-length string, and the ABCD' is lost! + * Better to pass the string forward and let the input routines + * validate the contents. + */ +/* Hexadecimal number */ +/* National character */ +/* Quoted string that allows backslash escapes */ +/* Extended quote + * xqdouble implements embedded quote, '''' + */ +/* $foo$ style quotes ("dollar quoting") + * The quoted string starts with $foo$ where "foo" is an optional string + * in the form of an identifier, except that it may not contain "$", + * and extends to the first occurrence of an identical string. + * There is *no* processing of the quoted text. + * + * {dolqfailed} is an error rule to avoid scanner backup when {dolqdelim} + * fails to match its trailing "$". + */ +/* Double quote + * Allows embedded spaces and other special characters into identifiers. + */ +/* Unicode escapes */ +/* error rule to avoid backup */ +/* Quoted identifier with Unicode escapes */ +/* Quoted string with Unicode escapes */ +/* Optional UESCAPE after a quoted string or identifier with Unicode escapes. */ +/* error rule to avoid backup */ +/* C-style comments + * + * The "extended comment" syntax closely resembles allowable operator syntax. + * The tricky part here is to get lex to recognize a string starting with + * slash-star as a comment, when interpreting it as an operator would produce + * a longer match --- remember lex will prefer a longer match! Also, if we + * have something like plus-slash-star, lex will think this is a 3-character + * operator whereas we want to see it as a + operator and a comment start. + * The solution is two-fold: + * 1. append {op_chars}* to xcstart so that it matches as much text as + * {operator} would. Then the tie-breaker (first matching rule of same + * length) ensures xcstart wins. We put back the extra stuff with yyless() + * in case it contains a star-slash that should terminate the comment. + * 2. In the operator rule, check for slash-star within the operator, and + * if found throw it back with yyless(). This handles the plus-slash-star + * problem. + * Dash-dash comments have similar interactions with the operator rule. + */ +/* Assorted special-case operators and operator-like tokens */ +/* " */ +/* + * These operator-like tokens (unlike the above ones) also match the {operator} + * rule, which means that they might be overridden by a longer match if they + * are followed by a comment start or a + or - character. Accordingly, if you + * add to this list, you must also add corresponding code to the {operator} + * block to return the correct token in such cases. (This is not needed in + * psqlscan.l since the token value is ignored there.) + */ +/* + * "self" is the set of chars that should be returned as single-character + * tokens. "op_chars" is the set of chars that can make up "Op" tokens, + * which can be one or more characters long (but if a single-char token + * appears in the "self" set, it is not to be returned as an Op). Note + * that the sets overlap, but each has some chars that are not in the other. + * + * If you change either set, adjust the character lists appearing in the + * rule for "operator"! + */ +/* we no longer allow unary minus in numbers. + * instead we pass it separately to parser. there it gets + * coerced via doNegate() -- Leon aug 20 1999 + * + * {decimalfail} is used because we would like "1..10" to lex as 1, dot_dot, 10. + * + * {realfail1} and {realfail2} are added to prevent the need for scanner + * backup when the {real} rule fails to match completely. + */ +/* + * Dollar quoted strings are totally opaque, and no escaping is done on them. + * Other quoted strings must allow some special characters such as single-quote + * and newline. + * Embedded single-quotes are implemented both in the SQL standard + * style of two adjacent single quotes "''" and in the Postgres/Java style + * of escaped-quote "\'". + * Other embedded escaped characters are matched explicitly and the leading + * backslash is dropped from the string. + * Note that xcstart must appear before operator, as explained above! + * Also whitespace (comment) must appear before operator. + */ +#line 1305 "third_party/libpg_query/src_backend_parser_scan.cpp" + +#define INITIAL 0 +#define xb 1 +#define xc 2 +#define xd 3 +#define xh 4 +#define xe 5 +#define xq 6 +#define xdolq 7 +#define xui 8 +#define xuiend 9 +#define xus 10 +#define xusend 11 +#define xeu 12 + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t + { + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + yy_size_t yy_n_chars; + yy_size_t yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + YYSTYPE * yylval_r; + + YYLTYPE * yylloc_r; + + }; /* end struct yyguts_t */ + +static int yy_init_globals ( yyscan_t yyscanner ); + + /* This must go here because YYSTYPE and YYLTYPE are included + * from bison output in section 1.*/ + # define yylval yyg->yylval_r + + # define yylloc yyg->yylloc_r + +int yylex_init (yyscan_t* scanner); + +int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int yylex_destroy ( yyscan_t yyscanner ); + +int yyget_debug ( yyscan_t yyscanner ); + +void yyset_debug ( int debug_flag , yyscan_t yyscanner ); + +YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); + +void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); + +FILE *yyget_in ( yyscan_t yyscanner ); + +void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); + +FILE *yyget_out ( yyscan_t yyscanner ); + +void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); + + yy_size_t yyget_leng ( yyscan_t yyscanner ); + +char *yyget_text ( yyscan_t yyscanner ); + +int yyget_lineno ( yyscan_t yyscanner ); + +void yyset_lineno ( int _line_number , yyscan_t yyscanner ); + +int yyget_column ( yyscan_t yyscanner ); + +void yyset_column ( int _column_no , yyscan_t yyscanner ); + +YYSTYPE * yyget_lval ( yyscan_t yyscanner ); + +void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner ); + + YYLTYPE *yyget_lloc ( yyscan_t yyscanner ); + + void yyset_lloc ( YYLTYPE * yylloc_param , yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap ( yyscan_t yyscanner ); +#else +extern int yywrap ( yyscan_t yyscanner ); +#endif +#endif + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen ( const char * , yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput ( yyscan_t yyscanner ); +#else +static int input ( yyscan_t yyscanner ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + yy_size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int yylex \ + (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner); + +#define YY_DECL int yylex \ + (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK /*LINTED*/break; +#endif + +#define YY_RULE_SETUP \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + yy_state_type yy_current_state; + char *yy_cp, *yy_bp; + int yy_act; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yylval = yylval_param; + + yylloc = yylloc_param; + + if ( !yyg->yy_init ) + { + yyg->yy_init = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yyg->yy_start ) + yyg->yy_start = 1; /* first start state */ + if ( ! YY_CURRENT_BUFFER ) { + yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); + } + + yy_load_buffer_state( yyscanner ); + } + + { +#line 403 "third_party/libpg_query/scan.l" + + +#line 1594 "third_party/libpg_query/src_backend_parser_scan.cpp" + + while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ + { + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yyg->yy_start; +yy_match: + do + { + YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 296 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + ++yy_cp; + } + while ( yy_current_state != 295 ); + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + + YY_DO_BEFORE_ACTION; + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + +case 1: +/* rule 1 can match eol */ +YY_RULE_SETUP +#line 405 "third_party/libpg_query/scan.l" +{ + /* ignore */ + } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 409 "third_party/libpg_query/scan.l" +{ + /* Set location in case of syntax error in comment */ + SET_YYLLOC(); + yyextra->xcdepth = 0; + BEGIN(xc); + /* Put back any characters past slash-star; see above */ + yyless(2); + } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 418 "third_party/libpg_query/scan.l" +{ + (yyextra->xcdepth)++; + /* Put back any characters past slash-star; see above */ + yyless(2); + } + YY_BREAK +case 4: +YY_RULE_SETUP +#line 424 "third_party/libpg_query/scan.l" +{ + if (yyextra->xcdepth <= 0) + BEGIN(INITIAL); + else + (yyextra->xcdepth)--; + } + YY_BREAK +case 5: +/* rule 5 can match eol */ +YY_RULE_SETUP +#line 431 "third_party/libpg_query/scan.l" +{ + /* ignore */ + } + YY_BREAK +case 6: +YY_RULE_SETUP +#line 435 "third_party/libpg_query/scan.l" +{ + /* ignore */ + } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 439 "third_party/libpg_query/scan.l" +{ + /* ignore */ + } + YY_BREAK +case YY_STATE_EOF(xc): +#line 443 "third_party/libpg_query/scan.l" +{ yyerror("unterminated /* comment"); } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 445 "third_party/libpg_query/scan.l" +{ + /* Binary bit type. + * At some point we should simply pass the string + * forward to the parser and label it there. + * In the meantime, place a leading "b" on the string + * to mark it for the input routine as a binary string. + */ + SET_YYLLOC(); + BEGIN(xb); + startlit(); + addlitchar('b', yyscanner); + } + YY_BREAK +case 9: +/* rule 9 can match eol */ +#line 458 "third_party/libpg_query/scan.l" +case 10: +/* rule 10 can match eol */ +YY_RULE_SETUP +#line 458 "third_party/libpg_query/scan.l" +{ + yyless(1); + BEGIN(INITIAL); + yylval->str = litbufdup(yyscanner); + return BCONST; + } + YY_BREAK +case 11: +/* rule 11 can match eol */ +#line 465 "third_party/libpg_query/scan.l" +case 12: +/* rule 12 can match eol */ +YY_RULE_SETUP +#line 465 "third_party/libpg_query/scan.l" +{ + addlit(yytext, yyleng, yyscanner); + } + YY_BREAK +case 13: +/* rule 13 can match eol */ +#line 469 "third_party/libpg_query/scan.l" +case 14: +/* rule 14 can match eol */ +YY_RULE_SETUP +#line 469 "third_party/libpg_query/scan.l" +{ + /* ignore */ + } + YY_BREAK +case YY_STATE_EOF(xb): +#line 472 "third_party/libpg_query/scan.l" +{ yyerror("unterminated bit string literal"); } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 474 "third_party/libpg_query/scan.l" +{ + /* Hexadecimal bit type. + * At some point we should simply pass the string + * forward to the parser and label it there. + * In the meantime, place a leading "x" on the string + * to mark it for the input routine as a hex string. + */ + SET_YYLLOC(); + BEGIN(xh); + startlit(); + addlitchar('x', yyscanner); + } + YY_BREAK +case 16: +/* rule 16 can match eol */ +#line 487 "third_party/libpg_query/scan.l" +case 17: +/* rule 17 can match eol */ +YY_RULE_SETUP +#line 487 "third_party/libpg_query/scan.l" +{ + yyless(1); + BEGIN(INITIAL); + yylval->str = litbufdup(yyscanner); + return XCONST; + } + YY_BREAK +case YY_STATE_EOF(xh): +#line 493 "third_party/libpg_query/scan.l" +{ yyerror("unterminated hexadecimal string literal"); } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 495 "third_party/libpg_query/scan.l" +{ + /* National character. + * We will pass this along as a normal character string, + * but preceded with an internally-generated "NCHAR". + */ + const PGScanKeyword *keyword; + + SET_YYLLOC(); + yyless(1); /* eat only 'n' this time */ + + keyword = ScanKeywordLookup("nchar", + yyextra->keywords, + yyextra->num_keywords); + if (keyword != NULL) + { + yylval->keyword = keyword->name; + return keyword->value; + } + else + { + /* If NCHAR isn't a keyword, just return "n" */ + yylval->str = pstrdup("n"); + return IDENT; + } + } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 521 "third_party/libpg_query/scan.l" +{ + yyextra->warn_on_first_escape = true; + yyextra->saw_non_ascii = false; + SET_YYLLOC(); + if (yyextra->standard_conforming_strings) + BEGIN(xq); + else + BEGIN(xe); + startlit(); + } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 531 "third_party/libpg_query/scan.l" +{ + yyextra->warn_on_first_escape = false; + yyextra->saw_non_ascii = false; + SET_YYLLOC(); + BEGIN(xe); + startlit(); + } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 538 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + if (!yyextra->standard_conforming_strings) + ereport(ERROR, + (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("unsafe use of string constant with Unicode escapes"), + errdetail("String constants with Unicode escapes cannot be used when standard_conforming_strings is off."), + lexer_errposition())); + BEGIN(xus); + startlit(); + } + YY_BREAK +case 22: +/* rule 22 can match eol */ +#line 550 "third_party/libpg_query/scan.l" +case 23: +/* rule 23 can match eol */ +YY_RULE_SETUP +#line 550 "third_party/libpg_query/scan.l" +{ + yyless(1); + BEGIN(INITIAL); + /* + * check that the data remains valid if it might have been + * made invalid by unescaping any chars. + */ + if (yyextra->saw_non_ascii) + pg_verifymbstr(yyextra->literalbuf, + yyextra->literallen, + false); + yylval->str = litbufdup(yyscanner); + return SCONST; + } + YY_BREAK +case 24: +/* rule 24 can match eol */ +#line 565 "third_party/libpg_query/scan.l" +case 25: +/* rule 25 can match eol */ +YY_RULE_SETUP +#line 565 "third_party/libpg_query/scan.l" +{ + /* throw back all but the quote */ + yyless(1); + /* xusend state looks for possible UESCAPE */ + BEGIN(xusend); + } + YY_BREAK +case 26: +/* rule 26 can match eol */ +YY_RULE_SETUP +#line 571 "third_party/libpg_query/scan.l" +{ + /* stay in xusend state over whitespace */ + } + YY_BREAK +case YY_STATE_EOF(xusend): +#line 574 "third_party/libpg_query/scan.l" +case 27: +/* rule 27 can match eol */ +#line 576 "third_party/libpg_query/scan.l" +case 28: +/* rule 28 can match eol */ +YY_RULE_SETUP +#line 576 "third_party/libpg_query/scan.l" +{ + /* no UESCAPE after the quote, throw back everything */ + yyless(0); + BEGIN(INITIAL); + yylval->str = litbuf_udeescape('\\', yyscanner); + return SCONST; + } + YY_BREAK +case 29: +/* rule 29 can match eol */ +YY_RULE_SETUP +#line 583 "third_party/libpg_query/scan.l" +{ + /* found UESCAPE after the end quote */ + BEGIN(INITIAL); + if (!check_uescapechar(yytext[yyleng - 2])) + { + SET_YYLLOC(); + ADVANCE_YYLLOC(yyleng - 2); + yyerror("invalid Unicode escape character"); + } + yylval->str = litbuf_udeescape(yytext[yyleng - 2], + yyscanner); + return SCONST; + } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 596 "third_party/libpg_query/scan.l" +{ + addlitchar('\'', yyscanner); + } + YY_BREAK +case 31: +/* rule 31 can match eol */ +YY_RULE_SETUP +#line 599 "third_party/libpg_query/scan.l" +{ + addlit(yytext, yyleng, yyscanner); + } + YY_BREAK +case 32: +/* rule 32 can match eol */ +YY_RULE_SETUP +#line 602 "third_party/libpg_query/scan.l" +{ + addlit(yytext, yyleng, yyscanner); + } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 605 "third_party/libpg_query/scan.l" +{ + pg_wchar c = strtoul(yytext + 2, NULL, 16); + + check_escape_warning(yyscanner); + + if (is_utf16_surrogate_first(c)) + { + yyextra->utf16_first_part = c; + BEGIN(xeu); + } + else if (is_utf16_surrogate_second(c)) + yyerror("invalid Unicode surrogate pair"); + else + addunicode(c, yyscanner); + } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 620 "third_party/libpg_query/scan.l" +{ + pg_wchar c = strtoul(yytext + 2, NULL, 16); + + if (!is_utf16_surrogate_second(c)) + yyerror("invalid Unicode surrogate pair"); + + c = surrogate_pair_to_codepoint(yyextra->utf16_first_part, c); + + addunicode(c, yyscanner); + + BEGIN(xe); + } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 632 "third_party/libpg_query/scan.l" +{ yyerror("invalid Unicode surrogate pair"); } + YY_BREAK +case 36: +/* rule 36 can match eol */ +YY_RULE_SETUP +#line 633 "third_party/libpg_query/scan.l" +{ yyerror("invalid Unicode surrogate pair"); } + YY_BREAK +case YY_STATE_EOF(xeu): +#line 634 "third_party/libpg_query/scan.l" +{ yyerror("invalid Unicode surrogate pair"); } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 635 "third_party/libpg_query/scan.l" +{ + ereport(ERROR, + (errcode(PG_ERRCODE_INVALID_ESCAPE_SEQUENCE), + errmsg("invalid Unicode escape"), + errhint("Unicode escapes must be \\uXXXX or \\UXXXXXXXX."), + lexer_errposition())); + } + YY_BREAK +case 38: +/* rule 38 can match eol */ +YY_RULE_SETUP +#line 642 "third_party/libpg_query/scan.l" +{ + // if (yytext[1] == '\'') + // { + // if (yyextra->backslash_quote == PG_BACKSLASH_QUOTE_OFF || + // (yyextra->backslash_quote == PG_BACKSLASH_QUOTE_SAFE_ENCODING && + // PG_ENCODING_IS_CLIENT_ONLY(pg_get_client_encoding()))) + // ereport(ERROR, + // (errcode(PG_ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), + // errmsg("unsafe use of \\' in a string literal"), + // errhint("Use '' to write quotes in strings. \\' is insecure in client-only encodings."), + // lexer_errposition())); + // } + check_string_escape_warning(yytext[1], yyscanner); + addlitchar(unescape_single_char(yytext[1], yyscanner), + yyscanner); + } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 658 "third_party/libpg_query/scan.l" +{ + unsigned char c = strtoul(yytext + 1, NULL, 8); + + check_escape_warning(yyscanner); + addlitchar(c, yyscanner); + if (c == '\0' || IS_HIGHBIT_SET(c)) + yyextra->saw_non_ascii = true; + } + YY_BREAK +case 40: +YY_RULE_SETUP +#line 666 "third_party/libpg_query/scan.l" +{ + unsigned char c = strtoul(yytext + 2, NULL, 16); + + check_escape_warning(yyscanner); + addlitchar(c, yyscanner); + if (c == '\0' || IS_HIGHBIT_SET(c)) + yyextra->saw_non_ascii = true; + } + YY_BREAK +case 41: +/* rule 41 can match eol */ +YY_RULE_SETUP +#line 674 "third_party/libpg_query/scan.l" +{ + /* ignore */ + } + YY_BREAK +case 42: +YY_RULE_SETUP +#line 677 "third_party/libpg_query/scan.l" +{ + /* This is only needed for \ just before EOF */ + addlitchar(yytext[0], yyscanner); + } + YY_BREAK +case YY_STATE_EOF(xq): +case YY_STATE_EOF(xe): +case YY_STATE_EOF(xus): +#line 681 "third_party/libpg_query/scan.l" +{ yyerror("unterminated quoted string"); } + YY_BREAK +case 43: +YY_RULE_SETUP +#line 683 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + yyextra->dolqstart = pstrdup(yytext); + BEGIN(xdolq); + startlit(); + } + YY_BREAK +case 44: +YY_RULE_SETUP +#line 689 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + /* throw back all but the initial "$" */ + yyless(1); + /* and treat it as {other} */ + return yytext[0]; + } + YY_BREAK +case 45: +YY_RULE_SETUP +#line 696 "third_party/libpg_query/scan.l" +{ + if (strcmp(yytext, yyextra->dolqstart) == 0) + { + pfree(yyextra->dolqstart); + yyextra->dolqstart = NULL; + BEGIN(INITIAL); + yylval->str = litbufdup(yyscanner); + return SCONST; + } + else + { + /* + * When we fail to match $...$ to dolqstart, transfer + * the $... part to the output, but put back the final + * $ for rescanning. Consider $delim$...$junk$delim$ + */ + addlit(yytext, yyleng - 1, yyscanner); + yyless(yyleng - 1); + } + } + YY_BREAK +case 46: +/* rule 46 can match eol */ +YY_RULE_SETUP +#line 716 "third_party/libpg_query/scan.l" +{ + addlit(yytext, yyleng, yyscanner); + } + YY_BREAK +case 47: +YY_RULE_SETUP +#line 719 "third_party/libpg_query/scan.l" +{ + addlit(yytext, yyleng, yyscanner); + } + YY_BREAK +case 48: +YY_RULE_SETUP +#line 722 "third_party/libpg_query/scan.l" +{ + /* This is only needed for $ inside the quoted text */ + addlitchar(yytext[0], yyscanner); + } + YY_BREAK +case YY_STATE_EOF(xdolq): +#line 726 "third_party/libpg_query/scan.l" +{ yyerror("unterminated dollar-quoted string"); } + YY_BREAK +case 49: +YY_RULE_SETUP +#line 728 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + BEGIN(xd); + startlit(); + } + YY_BREAK +case 50: +YY_RULE_SETUP +#line 733 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + BEGIN(xui); + startlit(); + } + YY_BREAK +case 51: +YY_RULE_SETUP +#line 738 "third_party/libpg_query/scan.l" +{ + char *ident; + + BEGIN(INITIAL); + if (yyextra->literallen == 0) + yyerror("zero-length delimited identifier"); + ident = litbufdup(yyscanner); + yylval->str = ident; + return IDENT; + } + YY_BREAK +case 52: +YY_RULE_SETUP +#line 748 "third_party/libpg_query/scan.l" +{ + yyless(1); + /* xuiend state looks for possible UESCAPE */ + BEGIN(xuiend); + } + YY_BREAK +case 53: +/* rule 53 can match eol */ +YY_RULE_SETUP +#line 753 "third_party/libpg_query/scan.l" +{ + /* stay in xuiend state over whitespace */ + } + YY_BREAK +case YY_STATE_EOF(xuiend): +#line 756 "third_party/libpg_query/scan.l" +case 54: +/* rule 54 can match eol */ +#line 758 "third_party/libpg_query/scan.l" +case 55: +/* rule 55 can match eol */ +YY_RULE_SETUP +#line 758 "third_party/libpg_query/scan.l" +{ + /* no UESCAPE after the quote, throw back everything */ + char *ident; + int identlen; + + yyless(0); + + BEGIN(INITIAL); + if (yyextra->literallen == 0) + yyerror("zero-length delimited identifier"); + ident = litbuf_udeescape('\\', yyscanner); + identlen = strlen(ident); + yylval->str = ident; + return IDENT; + } + YY_BREAK +case 56: +/* rule 56 can match eol */ +YY_RULE_SETUP +#line 773 "third_party/libpg_query/scan.l" +{ + /* found UESCAPE after the end quote */ + char *ident; + int identlen; + + BEGIN(INITIAL); + if (yyextra->literallen == 0) + yyerror("zero-length delimited identifier"); + if (!check_uescapechar(yytext[yyleng - 2])) + { + SET_YYLLOC(); + ADVANCE_YYLLOC(yyleng - 2); + yyerror("invalid Unicode escape character"); + } + ident = litbuf_udeescape(yytext[yyleng - 2], yyscanner); + identlen = strlen(ident); + yylval->str = ident; + return IDENT; + } + YY_BREAK +case 57: +YY_RULE_SETUP +#line 792 "third_party/libpg_query/scan.l" +{ + addlitchar('"', yyscanner); + } + YY_BREAK +case 58: +/* rule 58 can match eol */ +YY_RULE_SETUP +#line 795 "third_party/libpg_query/scan.l" +{ + addlit(yytext, yyleng, yyscanner); + } + YY_BREAK +case YY_STATE_EOF(xd): +case YY_STATE_EOF(xui): +#line 798 "third_party/libpg_query/scan.l" +{ yyerror("unterminated quoted identifier"); } + YY_BREAK +case 59: +YY_RULE_SETUP +#line 800 "third_party/libpg_query/scan.l" +{ + char *ident; + + SET_YYLLOC(); + /* throw back all but the initial u/U */ + yyless(1); + /* and treat it as {identifier} */ + ident = downcase_truncate_identifier(yytext, yyleng, true); + yylval->str = ident; + return IDENT; + } + YY_BREAK +case 60: +YY_RULE_SETUP +#line 812 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + return TYPECAST; + } + YY_BREAK +case 61: +YY_RULE_SETUP +#line 817 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + return DOT_DOT; + } + YY_BREAK +case 62: +YY_RULE_SETUP +#line 822 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + return COLON_EQUALS; + } + YY_BREAK +case 63: +YY_RULE_SETUP +#line 827 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + return LAMBDA_ARROW; + } + YY_BREAK +case 64: +YY_RULE_SETUP +#line 832 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + return DOUBLE_ARROW; + } + YY_BREAK +case 65: +YY_RULE_SETUP +#line 837 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + return POWER_OF; + } + YY_BREAK +case 66: +YY_RULE_SETUP +#line 842 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + return EQUALS_GREATER; + } + YY_BREAK +case 67: +YY_RULE_SETUP +#line 847 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + return LESS_EQUALS; + } + YY_BREAK +case 68: +YY_RULE_SETUP +#line 852 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + return GREATER_EQUALS; + } + YY_BREAK +case 69: +YY_RULE_SETUP +#line 857 "third_party/libpg_query/scan.l" +{ + /* We accept both "<>" and "!=" as meaning NOT_EQUALS */ + SET_YYLLOC(); + return NOT_EQUALS; + } + YY_BREAK +case 70: +YY_RULE_SETUP +#line 863 "third_party/libpg_query/scan.l" +{ + /* We accept both "<>" and "!=" as meaning NOT_EQUALS */ + SET_YYLLOC(); + return NOT_EQUALS; + } + YY_BREAK +case 71: +YY_RULE_SETUP +#line 869 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + return yytext[0]; + } + YY_BREAK +case 72: +YY_RULE_SETUP +#line 874 "third_party/libpg_query/scan.l" +{ + /* + * Check for embedded slash-star or dash-dash; those + * are comment starts, so operator must stop there. + * Note that slash-star or dash-dash at the first + * character will match a prior rule, not this one. + */ + int nchars = yyleng; + char *slashstar = strstr(yytext, "/*"); /* slash star */ + char *dashdash = strstr(yytext, "--"); + + if (slashstar && dashdash) { + /* if both appear, take the first one */ + if (slashstar > dashdash) + slashstar = dashdash; + } else if (!slashstar) { + slashstar = dashdash; + } + if (slashstar) { + nchars = slashstar - yytext; + } + + /* + * For SQL compatibility, '+' and '-' cannot be the + * last char of a multi-char operator unless the operator + * contains chars that are not in SQL operators. + * The idea is to lex '=-' as two operators, but not + * to forbid operator names like '?-' that could not be + * sequences of SQL operators. + */ + while (nchars > 1 && + (yytext[nchars - 1] == '+' || + yytext[nchars - 1] == '-')) + { + int ic; + + for (ic = nchars - 2; ic >= 0; ic--) + { + if (strchr("~!@^&|`?%", yytext[ic])) + break; + } + if (ic >= 0) + break; /* found a char that makes it OK */ + nchars--; /* else remove the +/-, and check again */ + } + + /* We don't accept leading ? in any multi-character operators + * except for those in use by hstore, JSON and geometric operators. + * + * We don't accept contained or trailing ? in any + * multi-character operators. + * + * This is necessary in order to support normalized queries without + * spacing between ? as a substition character and a simple operator (e.g. "?=?") + */ + if (yytext[0] == '?' && + strcmp(yytext, "?|") != 0 && strcmp(yytext, "?&") != 0 && + strcmp(yytext, "?-") != 0 && + strcmp(yytext, "?-|") != 0 && strcmp(yytext, "?||") != 0) { + nchars = 1; + } + + if (yytext[0] != '?' && strchr(yytext, '?')) { + /* Lex up to just before the ? character */ + nchars = strchr(yytext, '?') - yytext; + } + + SET_YYLLOC(); + + if ((yy_size_t) nchars < yyleng) + { + /* Strip the unwanted chars from the token */ + yyless(nchars); + /* + * If what we have left is only one char, and it's + * one of the characters matching "self", then + * return it as a character token the same way + * that the "self" rule would have. + */ + if (nchars == 1 && + strchr(",()[].;:+-*/%^<>=?", yytext[0])) { + return yytext[0]; + } + /* + * Likewise, if what we have left is two chars, and + * those match the tokens ">=", "<=", "=>", "<>" or + * "!=", then we must return the appropriate token + * rather than the generic Op. + */ + if (nchars == 2) + { + if (yytext[0] == '=' && yytext[1] == '>') + return EQUALS_GREATER; + if (yytext[0] == '>' && yytext[1] == '=') + return GREATER_EQUALS; + if (yytext[0] == '<' && yytext[1] == '=') + return LESS_EQUALS; + if (yytext[0] == '<' && yytext[1] == '>') + return NOT_EQUALS; + if (yytext[0] == '!' && yytext[1] == '=') + return NOT_EQUALS; + } + } + + /* + * Complain if operator is too long. Unlike the case + * for identifiers, we make this an error not a notice- + * and-truncate, because the odds are we are looking at + * a syntactic mistake anyway. NAMEDDATALEN + */ + if (nchars >= 64) + yyerror("operator too long: operators longer than 64 bytes are not supported"); + + yylval->str = pstrdup(yytext); + return Op; + } + YY_BREAK +case 73: +YY_RULE_SETUP +#line 991 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + yylval->ival = atol(yytext + 1); + return PARAM; + } + YY_BREAK +case 74: +YY_RULE_SETUP +#line 997 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + yylval->ival = atol(yytext + 1); + return PARAM; + } + YY_BREAK +case 75: +YY_RULE_SETUP +#line 1003 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + return process_integer_literal(yytext, yylval); + } + YY_BREAK +case 76: +YY_RULE_SETUP +#line 1007 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + yylval->str = pstrdup(yytext); + return FCONST; + } + YY_BREAK +case 77: +YY_RULE_SETUP +#line 1012 "third_party/libpg_query/scan.l" +{ + /* throw back the .., and treat as integer */ + yyless(yyleng - 2); + SET_YYLLOC(); + return process_integer_literal(yytext, yylval); + } + YY_BREAK +case 78: +YY_RULE_SETUP +#line 1018 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + yylval->str = pstrdup(yytext); + return FCONST; + } + YY_BREAK +case 79: +YY_RULE_SETUP +#line 1023 "third_party/libpg_query/scan.l" +{ + /* + * throw back the [Ee], and treat as {decimal}. Note + * that it is possible the input is actually {integer}, + * but since this case will almost certainly lead to a + * syntax error anyway, we don't bother to distinguish. + */ + yyless(yyleng - 1); + SET_YYLLOC(); + yylval->str = pstrdup(yytext); + return FCONST; + } + YY_BREAK +case 80: +YY_RULE_SETUP +#line 1035 "third_party/libpg_query/scan.l" +{ + /* throw back the [Ee][+-], and proceed as above */ + yyless(yyleng - 2); + SET_YYLLOC(); + yylval->str = pstrdup(yytext); + return FCONST; + } + YY_BREAK +case 81: +YY_RULE_SETUP +#line 1044 "third_party/libpg_query/scan.l" +{ + const PGScanKeyword *keyword; + char *ident; + char *keyword_text = pstrdup(yytext); + + SET_YYLLOC(); + + if (yytext[yyleng - 1] == '?') { + keyword_text[yyleng - 1] = '\0'; + } + + /* Is it a keyword? */ + keyword = ScanKeywordLookup(keyword_text, + yyextra->keywords, + yyextra->num_keywords); + if (keyword != NULL) + { + if (keyword_text[yyleng - 1] == '\0') { + yyless(yyleng - 1); + } + yylval->keyword = keyword->name; + return keyword->value; + } + + /* + * No. Convert the identifier to lower case, and truncate + * if necessary. + */ + ident = downcase_truncate_identifier(yytext, yyleng, true); + yylval->str = ident; + return IDENT; + } + YY_BREAK +case 82: +YY_RULE_SETUP +#line 1077 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + return yytext[0]; + } + YY_BREAK +case YY_STATE_EOF(INITIAL): +#line 1082 "third_party/libpg_query/scan.l" +{ + SET_YYLLOC(); + yyterminate(); + } + YY_BREAK +case 83: +YY_RULE_SETUP +#line 1087 "third_party/libpg_query/scan.l" +YY_FATAL_ERROR( "flex scanner jammed" ); + YY_BREAK +#line 2661 "third_party/libpg_query/src_backend_parser_scan.cpp" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_END_OF_FILE: + { + yyg->yy_did_buffer_switch_on_eof = 0; + + if ( yywrap( yyscanner ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = + yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of user's declarations */ +} /* end of yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + char *source = yyg->yytext_ptr; + int number_to_move, i; + int ret_val; + + if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1); + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else + { + yy_size_t num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + + int yy_c_buf_p_offset = + (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + yy_size_t new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yyrealloc( (void *) b->yy_ch_buf, + (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = NULL; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + yyg->yy_n_chars, num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if ( yyg->yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin , yyscanner); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( + (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + /* "- 2" to take care of EOB's */ + YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); + } + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +{ + yy_state_type yy_current_state; + char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_current_state = yyg->yy_start; + + for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) + { + YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 296 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) +{ + int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ + char *yy_cp = yyg->yy_c_buf_p; + + YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 296 ) + yy_c = yy_meta[yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; + yy_is_jam = (yy_current_state == 295); + + (void)yyg; + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_UNPUT + +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (yyscan_t yyscanner) +#else + static int input (yyscan_t yyscanner) +#endif + +{ + int c; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else + { /* need more input */ + yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr; + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin , yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap( yyscanner ) ) + return 0; + + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(yyscanner); +#else + return input(yyscanner); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ + void yyrestart (FILE * input_file , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! YY_CURRENT_BUFFER ){ + yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); + } + + yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner); + yy_load_buffer_state( yyscanner ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ + void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * yypop_buffer_state(); + * yypush_buffer_state(new_buffer); + */ + yyensure_buffer_stack (yyscanner); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + yy_load_buffer_state( yyscanner ); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +static void yy_load_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ + YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file , yyscanner); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with yy_create_buffer() + * @param yyscanner The scanner object. + */ + void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yyfree( (void *) b->yy_ch_buf , yyscanner ); + + yyfree( (void *) b , yyscanner ); +} + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a yyrestart() or at EOF. + */ + static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + +{ + int oerrno = errno; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_flush_buffer( b , yyscanner); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then yy_init_buffer was _probably_ + * called from yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ + void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + yy_load_buffer_state( yyscanner ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (new_buffer == NULL) + return; + + yyensure_buffer_stack(yyscanner); + + /* This block is copied from yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from yy_switch_to_buffer. */ + yy_load_buffer_state( yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +void yypop_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) { + yy_load_buffer_state( yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void yyensure_buffer_stack (yyscan_t yyscanner) +{ + yy_size_t num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + yy_size_t grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc + (yyg->yy_buffer_stack, + num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return NULL; + + b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = NULL; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b , yyscanner ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * yy_scan_bytes() instead. + */ +YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner) +{ + + return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner); +} + +/** Setup the input buffer state to scan the given bytes. The next call to yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + yy_size_t i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = (yy_size_t) (_yybytes_len + 2); + buf = (char *) yyalloc( n , yyscanner ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n , yyscanner); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + //( stderr, "%s\n", msg ); + throw std::runtime_error(msg); // YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yy_size_t yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyextra; +} + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int yyget_lineno (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int yyget_column (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_in (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *yyget_out (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +yy_size_t yyget_leng (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *yyget_text (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yytext; +} + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyextra = user_defined ; +} + +/** Set the current line number. + * @param _line_number line number + * @param yyscanner The scanner object. + */ +void yyset_lineno (int _line_number , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + YY_FATAL_ERROR( "yyset_lineno called with no buffer" ); + + yylineno = _line_number; +} + +/** Set the current column. + * @param _column_no column number + * @param yyscanner The scanner object. + */ +void yyset_column (int _column_no , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + YY_FATAL_ERROR( "yyset_column called with no buffer" ); + + yycolumn = _column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param _in_str A readable stream. + * @param yyscanner The scanner object. + * @see yy_switch_to_buffer + */ +void yyset_in (FILE * _in_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyin = _in_str ; +} + +void yyset_out (FILE * _out_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyout = _out_str ; +} + +int yyget_debug (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yy_flex_debug; +} + +void yyset_debug (int _bdebug , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yy_flex_debug = _bdebug ; +} + +/* Accessor methods for yylval and yylloc */ + +YYSTYPE * yyget_lval (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylval; +} + +void yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylval = yylval_param; +} + +YYLTYPE *yyget_lloc (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylloc; +} + +void yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylloc = yylloc_param; +} + +/* User-visible API */ + +/* yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ +int yylex_init(yyscan_t* ptr_yy_globals) +{ + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* yylex_init_extra has the same functionality as yylex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to yyalloc in + * the yyextra field. + */ +int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals ) +{ + struct yyguts_t dummy_yyguts; + + yyset_extra (yy_user_defined, &dummy_yyguts); + + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in + yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + yyset_extra (yy_user_defined, *ptr_yy_globals); + + return yy_init_globals ( *ptr_yy_globals ); +} + +static int yy_init_globals (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from yylex_destroy(), so don't allocate here. + */ + + yyg->yy_buffer_stack = NULL; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = NULL; + yyg->yy_init = 0; + yyg->yy_start = 0; + + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = NULL; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = NULL; + yyout = NULL; +#endif + + /* For future reference: Set errno on error, since we are called by + * yylex_init() + */ + return 0; +} + +/* yylex_destroy is for both reentrant and non-reentrant scanners. */ +int yylex_destroy (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner ); + YY_CURRENT_BUFFER_LVALUE = NULL; + yypop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + yyfree(yyg->yy_buffer_stack , yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + yyfree( yyg->yy_start_stack , yyscanner ); + yyg->yy_start_stack = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * yylex() is called, initialization will occur. */ + yy_init_globals( yyscanner); + + /* Destroy the main struct (reentrant only). */ + yyfree ( yyscanner , yyscanner ); + yyscanner = NULL; + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + (void)yyg; + + int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (const char * s , yyscan_t yyscanner) +{ + int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +#define YYTABLES_NAME "yytables" + +#line 1087 "third_party/libpg_query/scan.l" + + +/* LCOV_EXCL_STOP */ + +/* + * Arrange access to yyextra for subroutines of the main yylex() function. + * We expect each subroutine to have a yyscanner parameter. Rather than + * use the yyget_xxx functions, which might or might not get inlined by the + * compiler, we cheat just a bit and cast yyscanner to the right type. + */ +#undef yyextra +#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r) + +/* Likewise for a couple of other things we need. */ +#undef yylloc +#define yylloc (((struct yyguts_t *) yyscanner)->yylloc_r) +#undef yyleng +#define yyleng (((struct yyguts_t *) yyscanner)->yyleng_r) + + +/* + * scanner_errposition + * Report a lexer or grammar error cursor position, if possible. + * + * This is expected to be used within an ereport() call. The return value + * is a dummy (always 0, in fact). + * + * Note that this can only be used for messages emitted during raw parsing + * (essentially, scan.l and gram.y), since it requires the yyscanner struct + * to still be available. + */ +int +scanner_errposition(int location, core_yyscan_t yyscanner) +{ + int pos; + + if (location < 0) + return 0; /* no-op if location is unknown */ + + /* Convert byte offset to character number */ + pos = pg_mbstrlen_with_len(yyextra->scanbuf, location) + 1; + /* And pass it to the ereport mechanism */ + return errposition(pos); +} + +/* + * scanner_yyerror + * Report a lexer or grammar error. + * + * The message's cursor position is whatever YYLLOC was last set to, + * ie, the start of the current token if called within yylex(), or the + * most recently lexed token if called from the grammar. + * This is OK for syntax error messages from the Bison parser, because Bison + * parsers report error as soon as the first unparsable token is reached. + * Beware of using yyerror for other purposes, as the cursor position might + * be misleading! + */ +void +scanner_yyerror(const char *message, core_yyscan_t yyscanner) +{ + const char *loc = yyextra->scanbuf + *yylloc; + + if (*loc == YY_END_OF_BUFFER_CHAR) + { + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + /* translator: %s is typically the translation of "syntax error" */ + errmsg("%s at end of input", _(message)), + lexer_errposition())); + } + else + { + ereport(ERROR, + (errcode(PG_ERRCODE_SYNTAX_ERROR), + /* translator: first %s is typically the translation of "syntax error" */ + errmsg("%s at or near \"%s\"", _(message), loc), + lexer_errposition())); + } +} + + +/* + * Called before any actual parsing is done + */ +core_yyscan_t +scanner_init(const char *str, + core_yy_extra_type *yyext, + const PGScanKeyword *keywords, + int num_keywords) +{ + PGSize slen = strlen(str); + yyscan_t scanner; + + if (yylex_init(&scanner) != 0) + elog(ERROR, "yylex_init() failed: %m"); + + core_yyset_extra(yyext, scanner); + + yyext->keywords = keywords; + yyext->num_keywords = num_keywords; + + yyext->backslash_quote = backslash_quote; + yyext->escape_string_warning = escape_string_warning; + yyext->standard_conforming_strings = standard_conforming_strings; + + /* + * Make a scan buffer with special termination needed by flex. + */ + yyext->scanbuf = (char *) palloc(slen + 2); + yyext->scanbuflen = slen; + memcpy(yyext->scanbuf, str, slen); + yyext->scanbuf[slen] = yyext->scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; + yy_scan_buffer(yyext->scanbuf, slen + 2, scanner); + + /* initialize literal buffer to a reasonable but expansible size */ + yyext->literalalloc = 1024; + yyext->literalbuf = (char *) palloc(yyext->literalalloc); + yyext->literallen = 0; + + return scanner; +} + + +/* + * Called after parsing is done to clean up after scanner_init() + */ +void +scanner_finish(core_yyscan_t yyscanner) +{ + /* + * We don't bother to call yylex_destroy(), because all it would do is + * pfree a small amount of control storage. It's cheaper to leak the + * storage until the parsing context is destroyed. The amount of space + * involved is usually negligible compared to the output parse tree + * anyway. + * + * We do bother to pfree the scanbuf and literal buffer, but only if they + * represent a nontrivial amount of space. The 8K cutoff is arbitrary. + */ + if (yyextra->scanbuflen >= 8192) + pfree(yyextra->scanbuf); + if (yyextra->literalalloc >= 8192) + pfree(yyextra->literalbuf); +} + + +static void +addlit(char *ytext, int yleng, core_yyscan_t yyscanner) +{ + /* enlarge buffer if needed */ + if ((yyextra->literallen + yleng) >= yyextra->literalalloc) + { + do + { + yyextra->literalalloc *= 2; + } while ((yyextra->literallen + yleng) >= yyextra->literalalloc); + yyextra->literalbuf = (char *) repalloc(yyextra->literalbuf, + yyextra->literalalloc); + } + /* append new data */ + memcpy(yyextra->literalbuf + yyextra->literallen, ytext, yleng); + yyextra->literallen += yleng; +} + + +static void +addlitchar(unsigned char ychar, core_yyscan_t yyscanner) +{ + /* enlarge buffer if needed */ + if ((yyextra->literallen + 1) >= yyextra->literalalloc) + { + yyextra->literalalloc *= 2; + yyextra->literalbuf = (char *) repalloc(yyextra->literalbuf, + yyextra->literalalloc); + } + /* append new data */ + yyextra->literalbuf[yyextra->literallen] = ychar; + yyextra->literallen += 1; +} + + +/* + * Create a palloc'd copy of literalbuf, adding a trailing null. + */ +static char * +litbufdup(core_yyscan_t yyscanner) +{ + int llen = yyextra->literallen; + char *newbuf; + + newbuf = (char*) palloc(llen + 1); + memcpy(newbuf, yyextra->literalbuf, llen); + newbuf[llen] = '\0'; + return newbuf; +} + +static int +process_integer_literal(const char *token, YYSTYPE *lval) +{ + long val; + char *endptr; + + errno = 0; + val = strtol(token, &endptr, 10); + if (*endptr != '\0' || errno == ERANGE + /* if long > 32 bits, check for overflow of int4_t */ + || val != (long) ((int32_t) val) ) + { + /* integer too large, treat it as a float */ + lval->str = pstrdup(token); + return FCONST; + } + lval->ival = val; + return ICONST; +} + +static unsigned int +hexval(unsigned char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 0xA; + if (c >= 'A' && c <= 'F') + return c - 'A' + 0xA; + elog(ERROR, "invalid hexadecimal digit"); + return 0; /* not reached */ +} + +static void +check_unicode_value(pg_wchar c, char *loc, core_yyscan_t yyscanner) +{ + // database encoding is always UTF8 + // if (GetDatabaseEncoding() == PG_UTF8) + // return; + + // if (c > 0x7F) + // { + // ADVANCE_YYLLOC(loc - yyextra->literalbuf + 3); /* 3 for U&" */ + // yyerror("Unicode escape values cannot be used for code point values above 007F when the server encoding is not UTF8"); + // } +} + +static bool +is_utf16_surrogate_first(pg_wchar c) +{ + return (c >= 0xD800 && c <= 0xDBFF); +} + +static bool +is_utf16_surrogate_second(pg_wchar c) +{ + return (c >= 0xDC00 && c <= 0xDFFF); +} + +static pg_wchar +surrogate_pair_to_codepoint(pg_wchar first, pg_wchar second) +{ + return ((first & 0x3FF) << 10) + 0x10000 + (second & 0x3FF); +} + +static void +addunicode(pg_wchar c, core_yyscan_t yyscanner) +{ + char buf[8]; + + if (c == 0 || c > 0x10FFFF) + yyerror("invalid Unicode escape value"); + if (c > 0x7F) + { + // if (GetDatabaseEncoding() != PG_UTF8) + // yyerror("Unicode escape values cannot be used for code point values above 007F when the server encoding is not UTF8"); + yyextra->saw_non_ascii = true; + } + unicode_to_utf8(c, (unsigned char *) buf); + addlit(buf, pg_mblen(buf), yyscanner); +} + +/* is 'escape' acceptable as Unicode escape character (UESCAPE syntax) ? */ +static bool +check_uescapechar(unsigned char escape) +{ + if (isxdigit(escape) + || escape == '+' + || escape == '\'' + || escape == '"' + || scanner_isspace(escape)) + { + return false; + } + else + return true; +} + +/* like litbufdup, but handle unicode escapes */ +static char * +litbuf_udeescape(unsigned char escape, core_yyscan_t yyscanner) +{ + char *newbuf; + char *litbuf, + *in, + *out; + pg_wchar pair_first = 0; + + /* Make literalbuf null-terminated to simplify the scanning loop */ + litbuf = yyextra->literalbuf; + litbuf[yyextra->literallen] = '\0'; + + /* + * This relies on the subtle assumption that a UTF-8 expansion cannot be + * longer than its escaped representation. + */ + newbuf = (char*) palloc(yyextra->literallen + 1); + + in = litbuf; + out = newbuf; + while (*in) + { + if (in[0] == escape) + { + if (in[1] == escape) + { + if (pair_first) + { + ADVANCE_YYLLOC(in - litbuf + 3); /* 3 for U&" */ + yyerror("invalid Unicode surrogate pair"); + } + *out++ = escape; + in += 2; + } + else if (isxdigit((unsigned char) in[1]) && + isxdigit((unsigned char) in[2]) && + isxdigit((unsigned char) in[3]) && + isxdigit((unsigned char) in[4])) + { + pg_wchar unicode; + + unicode = (hexval(in[1]) << 12) + + (hexval(in[2]) << 8) + + (hexval(in[3]) << 4) + + hexval(in[4]); + check_unicode_value(unicode, in, yyscanner); + if (pair_first) + { + if (is_utf16_surrogate_second(unicode)) + { + unicode = surrogate_pair_to_codepoint(pair_first, unicode); + pair_first = 0; + } + else + { + ADVANCE_YYLLOC(in - litbuf + 3); /* 3 for U&" */ + yyerror("invalid Unicode surrogate pair"); + } + } + else if (is_utf16_surrogate_second(unicode)) + yyerror("invalid Unicode surrogate pair"); + + if (is_utf16_surrogate_first(unicode)) + pair_first = unicode; + else + { + unicode_to_utf8(unicode, (unsigned char *) out); + out += pg_mblen(out); + } + in += 5; + } + else if (in[1] == '+' && + isxdigit((unsigned char) in[2]) && + isxdigit((unsigned char) in[3]) && + isxdigit((unsigned char) in[4]) && + isxdigit((unsigned char) in[5]) && + isxdigit((unsigned char) in[6]) && + isxdigit((unsigned char) in[7])) + { + pg_wchar unicode; + + unicode = (hexval(in[2]) << 20) + + (hexval(in[3]) << 16) + + (hexval(in[4]) << 12) + + (hexval(in[5]) << 8) + + (hexval(in[6]) << 4) + + hexval(in[7]); + check_unicode_value(unicode, in, yyscanner); + if (pair_first) + { + if (is_utf16_surrogate_second(unicode)) + { + unicode = surrogate_pair_to_codepoint(pair_first, unicode); + pair_first = 0; + } + else + { + ADVANCE_YYLLOC(in - litbuf + 3); /* 3 for U&" */ + yyerror("invalid Unicode surrogate pair"); + } + } + else if (is_utf16_surrogate_second(unicode)) + yyerror("invalid Unicode surrogate pair"); + + if (is_utf16_surrogate_first(unicode)) + pair_first = unicode; + else + { + unicode_to_utf8(unicode, (unsigned char *) out); + out += pg_mblen(out); + } + in += 8; + } + else + { + ADVANCE_YYLLOC(in - litbuf + 3); /* 3 for U&" */ + yyerror("invalid Unicode escape value"); + } + } + else + { + if (pair_first) + { + ADVANCE_YYLLOC(in - litbuf + 3); /* 3 for U&" */ + yyerror("invalid Unicode surrogate pair"); + } + *out++ = *in++; + } + } + + /* unfinished surrogate pair? */ + if (pair_first) + { + ADVANCE_YYLLOC(in - litbuf + 3); /* 3 for U&" */ + yyerror("invalid Unicode surrogate pair"); + } + + *out = '\0'; + + /* + * We could skip pg_verifymbstr if we didn't process any non-7-bit-ASCII + * codes; but it's probably not worth the trouble, since this isn't likely + * to be a performance-critical path. + */ + pg_verifymbstr(newbuf, out - newbuf, false); + return newbuf; +} + +static unsigned char +unescape_single_char(unsigned char c, core_yyscan_t yyscanner) +{ + switch (c) + { + case 'b': + return '\b'; + case 'f': + return '\f'; + case 'n': + return '\n'; + case 'r': + return '\r'; + case 't': + return '\t'; + default: + /* check for backslash followed by non-7-bit-ASCII */ + if (c == '\0' || IS_HIGHBIT_SET(c)) + yyextra->saw_non_ascii = true; + + return c; + } +} + +static void +check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner) +{ + if (ychar == '\'') + { + if (yyextra->warn_on_first_escape && yyextra->escape_string_warning) + ereport(PGWARNING, + (errcode(PG_ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), + errmsg("nonstandard use of \\' in a string literal"), + errhint("Use '' to write quotes in strings, or use the escape string syntax (E'...')."), + lexer_errposition())); + yyextra->warn_on_first_escape = false; /* warn only once per string */ + } + else if (ychar == '\\') + { + if (yyextra->warn_on_first_escape && yyextra->escape_string_warning) + ereport(PGWARNING, + (errcode(PG_ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), + errmsg("nonstandard use of \\\\ in a string literal"), + errhint("Use the escape string syntax for backslashes, e.g., E'\\\\'."), + lexer_errposition())); + yyextra->warn_on_first_escape = false; /* warn only once per string */ + } + else + check_escape_warning(yyscanner); +} + +static void +check_escape_warning(core_yyscan_t yyscanner) +{ + if (yyextra->warn_on_first_escape && yyextra->escape_string_warning) + ereport(PGWARNING, + (errcode(PG_ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), + errmsg("nonstandard use of escape in a string literal"), + errhint("Use the escape string syntax for escapes, e.g., E'\\r\\n'."), + lexer_errposition())); + yyextra->warn_on_first_escape = false; /* warn only once per string */ +} + +/* + * Interface functions to make flex use palloc() instead of malloc(). + * It'd be better to make these static, but flex insists otherwise. + */ + +void * +core_yyalloc(yy_size_t bytes, core_yyscan_t yyscanner) +{ + return palloc(bytes); +} + +void * +core_yyrealloc(void *ptr, yy_size_t bytes, core_yyscan_t yyscanner) +{ + if (ptr) + return repalloc(ptr, bytes); + else + return palloc(bytes); +} + +void +core_yyfree(void *ptr, core_yyscan_t yyscanner) +{ + if (ptr) + pfree(ptr); +} + +#undef yyerror +#undef yylloc +#undef yylval +#undef yyin +#undef yyout +#undef yyextra +#undef yyleng +#undef yytext +#undef yylineno +#undef yycolumn +#undef yy_flex_debug +#undef yyless +#undef YYSTYPE +#undef YY_EXTRA_TYPE +#undef SET_YYLLOC +#undef ADVANCE_YYLLOC +#undef BEGIN +#undef REJECT +#undef INITIAL +#undef xb +#undef xc +#undef xd +#undef xh +#undef xe +#undef xq +#undef xdolq +#undef xui +#undef xuiend +#undef xus +#undef xusend +#undef xeu +#undef ECHO + + +} /* duckdb_libpgquery */ + + +// LICENSE_CHANGE_END + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 +// See the end of this file for a list + +/*-------------------------------------------------------------------- + * Symbols referenced in this file: + * - truncate_identifier + * - downcase_truncate_identifier + * - downcase_identifier + * - scanner_isspace + *-------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------- + * + * scansup.c + * support routines for the lex/flex scanner, used by both the normal + * backend as well as the bootstrap backend + * + * Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/parser/scansup.c + * + *------------------------------------------------------------------------- + */ + +#include + +#include + + + + +namespace duckdb_libpgquery { + +/* ---------------- + * scanstr + * + * if the string passed in has escaped codes, map the escape codes to actual + * chars + * + * the string returned is palloc'd and should eventually be pfree'd by the + * caller! + * ---------------- + */ + +/* + * downcase_truncate_identifier() --- do appropriate downcasing and + * truncation of an unquoted identifier. Optionally warn of truncation. + * + * Returns a palloc'd string containing the adjusted identifier. + * + * Note: in some usages the passed string is not null-terminated. + * + * Note: the API of this function is designed to allow for downcasing + * transformations that increase the string length, but we don't yet + * support that. If you want to implement it, you'll need to fix + * SplitIdentifierString() in utils/adt/varlena.c. + */ +char *downcase_truncate_identifier(const char *ident, int len, bool warn) { + return downcase_identifier(ident, len, warn, true); +} + +static __thread bool pg_preserve_identifier_case = false; + +void set_preserve_identifier_case(bool preserve) { + pg_preserve_identifier_case = preserve; +} + +bool get_preserve_identifier_case() { + return pg_preserve_identifier_case; +} + +/* + * a workhorse for downcase_truncate_identifier + */ +char *downcase_identifier(const char *ident, int len, bool warn, bool truncate) { + char *result; + int i; + bool enc_is_single_byte; + + result = (char *)palloc(len + 1); + enc_is_single_byte = pg_database_encoding_max_length() == 1; + + /* + * SQL99 specifies Unicode-aware case normalization, which we don't yet + * have the infrastructure for. Instead we use tolower() to provide a + * locale-aware translation. However, there are some locales where this + * is not right either (eg, Turkish may do strange things with 'i' and + * 'I'). Our current compromise is to use tolower() for characters with + * the high bit set, as long as they aren't part of a multi-byte + * character, and use an ASCII-only downcasing for 7-bit characters. + */ + for (i = 0; i < len; i++) { + unsigned char ch = (unsigned char)ident[i]; + + if (!get_preserve_identifier_case()) { + if (ch >= 'A' && ch <= 'Z') + ch += 'a' - 'A'; + else if (enc_is_single_byte && IS_HIGHBIT_SET(ch) && isupper(ch)) + ch = tolower(ch); + } + result[i] = (char)ch; + } + result[i] = '\0'; + + return result; +} + +/* + * scanner_isspace() --- return true if flex scanner considers char whitespace + * + * This should be used instead of the potentially locale-dependent isspace() + * function when it's important to match the lexer's behavior. + * + * In principle we might need similar functions for isalnum etc, but for the + * moment only isspace seems needed. + */ +bool scanner_isspace(char ch) { + /* This must match scan.l's list of {space} characters */ + if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '\f') + return true; + return false; +} +} + +// LICENSE_CHANGE_END + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #13 +// See the end of this file for a list + +/*-------------------------------------------------------------------- + * Symbols referenced in this file: + * - ScanKeywords + * - NumScanKeywords + * - ScanKeywordLookup + *-------------------------------------------------------------------- + */ + +/*------------------------------------------------------------------------- + * + * keywords.c + * lexical token lookup for key words in PostgreSQL + * + * + * Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/common/keywords.c + * + *------------------------------------------------------------------------- + */ + +#include +#include +#include + + + + + +namespace duckdb_libpgquery { + +/* + * ScanKeywordLookup - see if a given word is a keyword + * + * The table to be searched is passed explicitly, so that this can be used + * to search keyword lists other than the standard list appearing above. + * + * Returns a pointer to the PGScanKeyword table entry, or NULL if no match. + * + * The match is done case-insensitively. Note that we deliberately use a + * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z', + * even if we are in a locale where tolower() would produce more or different + * translations. This is to conform to the SQL99 spec, which says that + * keywords are to be matched in this way even though non-keyword identifiers + * receive a different case-normalization mapping. + */ +const PGScanKeyword *ScanKeywordLookup(const char *text, const PGScanKeyword *keywords, int num_keywords) { + int len, i; + const PGScanKeyword *low; + const PGScanKeyword *high; + + len = strlen(text); + auto data = std::unique_ptr(new char[len + 1]); + auto word = data.get(); + /* We assume all keywords are shorter than NAMEDATALEN. */ + + /* + * Apply an ASCII-only downcasing. We must not use tolower() since it may + * produce the wrong translation in some locales (eg, Turkish). + */ + for (i = 0; i < len; i++) { + char ch = text[i]; + + if (ch >= 'A' && ch <= 'Z') + ch += 'a' - 'A'; + word[i] = ch; + } + word[len] = '\0'; + + /* + * Now do a binary search using plain strcmp() comparison. + */ + low = keywords; + high = keywords + (num_keywords - 1); + while (low <= high) { + const PGScanKeyword *middle; + int difference; + + middle = low + (high - low) / 2; + difference = strcmp(middle->name, word); + if (difference == 0) + return middle; + else if (difference < 0) + low = middle + 1; + else + high = middle - 1; + } + + return NULL; +} +} + +// LICENSE_CHANGE_END + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/* + * Generic ASN.1 parsing + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/** + * \file common.h + * + * \brief Utility macros for internal use in the library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_LIBRARY_COMMON_H +#define MBEDTLS_LIBRARY_COMMON_H + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/** + * \file build_info.h + * + * \brief Build-time configuration info + * + * Include this file if you need to depend on the + * configuration options defined in mbedtls_config.h or MBEDTLS_CONFIG_FILE + */ + /* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_BUILD_INFO_H +#define MBEDTLS_BUILD_INFO_H + +/* + * This set of compile-time defines can be used to determine the version number + * of the Mbed TLS library used. Run-time variables for the same can be found in + * version.h + */ + +/** + * The version number x.y.z is split into three parts. + * Major, Minor, Patchlevel + */ +#define MBEDTLS_VERSION_MAJOR 3 +#define MBEDTLS_VERSION_MINOR 1 +#define MBEDTLS_VERSION_PATCH 0 + +/** + * The single version number has the following structure: + * MMNNPP00 + * Major version | Minor version | Patch version + */ +#define MBEDTLS_VERSION_NUMBER 0x03010000 +#define MBEDTLS_VERSION_STRING "3.1.0" +#define MBEDTLS_VERSION_STRING_FULL "mbed TLS 3.1.0" + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +#if !defined(MBEDTLS_CONFIG_FILE) + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +#define MBEDTLS_SHA256_C +#define MBEDTLS_SHA224_C +#define MBEDTLS_RSA_C +#define MBEDTLS_PKCS1_V15 +#define MBEDTLS_BIGNUM_C +#define MBEDTLS_OID_C +#define MBEDTLS_MD_C +#define MBEDTLS_BASE64_C +#define MBEDTLS_PK_PARSE_C +#define MBEDTLS_ASN1_PARSE_C +#define MBEDTLS_PK_C +#define MBEDTLS_PEM_PARSE_C +#define MBEDTLS_PLATFORM_C + + +// LICENSE_CHANGE_END + +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CONFIG_VERSION) && ( \ + MBEDTLS_CONFIG_VERSION < 0x03000000 || \ + MBEDTLS_CONFIG_VERSION > MBEDTLS_VERSION_NUMBER ) +#error "Invalid config version, defined value of MBEDTLS_CONFIG_VERSION is unsupported" +#endif + +/* Target and application specific configurations + * + * Allow user to override any previous default. + * + */ +#if defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_CONFIG) + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +// dummy file to make amalgamantion happy + +// LICENSE_CHANGE_END + +#endif + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/** + * \file check_config.h + * + * \brief Consistency checks for configuration options + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_CHECK_CONFIG_H +#define MBEDTLS_CHECK_CONFIG_H + +/* + * We assume CHAR_BIT is 8 in many places. In practice, this is true on our + * target platforms, so not an issue, but let's just be extra sure. + */ +#include +#if CHAR_BIT != 8 +#error "mbed TLS requires a platform with 8-bit chars" +#endif + +#if defined(_WIN32) +#if !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_C is required on Windows" +#endif + +/* Fix the config here. Not convenient to put an #ifdef _WIN32 in mbedtls_config.h as + * it would confuse config.py. */ +#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif + +#if !defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_VSNPRINTF_ALT +#endif +#endif /* _WIN32 */ + +#if defined(TARGET_LIKE_MBED) && defined(MBEDTLS_NET_C) +#error "The NET module is not available for mbed OS - please use the network functions provided by Mbed OS" +#endif + +#if defined(MBEDTLS_DEPRECATED_WARNING) && \ + !defined(__GNUC__) && !defined(__clang__) +#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) +#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" +#endif + +#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) +#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) +#error "MBEDTLS_DHM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CMAC_C) && \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) +#error "MBEDTLS_CMAC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_NIST_KW_C) && \ + ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) ) +#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + ( !defined(MBEDTLS_ECP_C) || \ + !( defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) ) || \ + !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_ASN1_WRITE_C) ) +#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECJPAKE_C) && \ + ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) && \ + ( defined(MBEDTLS_USE_PSA_CRYPTO) || \ + defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) || \ + defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) || \ + defined(MBEDTLS_ECDSA_SIGN_ALT) || \ + defined(MBEDTLS_ECDSA_VERIFY_ALT) || \ + defined(MBEDTLS_ECDSA_GENKEY_ALT) || \ + defined(MBEDTLS_ECP_INTERNAL_ALT) || \ + defined(MBEDTLS_ECP_ALT) ) +#error "MBEDTLS_ECP_RESTARTABLE defined, but it cannot coexist with an alternative or PSA-based ECP implementation" +#endif + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) +#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ + !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) ) ) +#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_ASN1_PARSE_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA256_C)) +#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ + defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ + && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) +#define MBEDTLS_HAS_MEMSAN +#endif +#endif +#if defined(MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN) && !defined(MBEDTLS_HAS_MEMSAN) +#error "MBEDTLS_TEST_CONSTANT_FLOW_MEMSAN requires building with MemorySanitizer" +#endif +#undef MBEDTLS_HAS_MEMSAN + +#if defined(MBEDTLS_GCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) && !defined(MBEDTLS_ARIA_C) ) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NO_FALLBACK) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NO_FALLBACK defined, but no alternative implementation enabled" +#endif + +#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HKDF_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) +#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(MBEDTLS_ECDH_C) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + ( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) +#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_WITH_CERT_ENABLED) && \ + !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) && \ + ( !defined(MBEDTLS_SHA256_C) && \ + !defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA1_C) ) +#error "!MBEDTLS_SSL_KEEP_PEER_CERTIFICATE requires MBEDTLS_SHA512_C, MBEDTLS_SHA256_C or MBEDTLS_SHA1_C" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_BACKTRACE) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_BACKTRACE defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_MEMORY_DEBUG) && !defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequesites" +#endif + +#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_C) && \ + ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) +#error "MBEDTLS_PK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ + defined(MBEDTLS_PLATFORM_EXIT_ALT) ) +#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ + defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_FREE) +#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_CALLOC) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) +#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ + defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ + defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ + !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ + !defined(MBEDTLS_PLATFORM_EXIT_ALT) +#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ + ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ + !defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) +#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ + !defined(MBEDTLS_ENTROPY_NV_SEED) +#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) && \ + !( ( ( defined(MBEDTLS_CTR_DRBG_C) || defined(MBEDTLS_HMAC_DRBG_C) ) && \ + defined(MBEDTLS_ENTROPY_C) ) || \ + defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) ) +#error "MBEDTLS_PSA_CRYPTO_C defined, but not all prerequisites (missing RNG)" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_SPM) && !defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_PSA_CRYPTO_SPM defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_SE_C) && \ + ! ( defined(MBEDTLS_PSA_CRYPTO_C) && \ + defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) ) +#error "MBEDTLS_PSA_CRYPTO_SE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ + ! defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_PSA_CRYPTO_STORAGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + !( defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) && \ + defined(MBEDTLS_ENTROPY_NV_SEED) ) +#error "MBEDTLS_PSA_INJECT_ENTROPY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with actual entropy sources" +#endif + +#if defined(MBEDTLS_PSA_INJECT_ENTROPY) && \ + defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +#error "MBEDTLS_PSA_INJECT_ENTROPY is not compatible with MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG" +#endif + +#if defined(MBEDTLS_PSA_ITS_FILE_C) && \ + !defined(MBEDTLS_FS_IO) +#error "MBEDTLS_PSA_ITS_FILE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) +#error "MBEDTLS_PSA_CRYPTO_KEY_ID_ENCODES_OWNER defined, but it cannot coexist with MBEDTLS_USE_PSA_CRYPTO." +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) ) +#error "MBEDTLS_RSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" +#endif + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) +#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SHA384_C) && !defined(MBEDTLS_SHA512_C) +#error "MBEDTLS_SHA384_C defined without MBEDTLS_SHA512_C" +#endif + +#if defined(MBEDTLS_SHA224_C) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_SHA224_C defined without MBEDTLS_SHA256_C" +#endif + +#if defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA224_C) +#error "MBEDTLS_SHA256_C defined without MBEDTLS_SHA224_C" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \ + !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +/* + * HKDF is mandatory for TLS 1.3. + * Otherwise support for at least one ciphersuite mandates either SHA_256 or + * SHA_384. + */ +#if defined(MBEDTLS_SSL_PROTO_TLS1_3) && \ + ( ( !defined(MBEDTLS_HKDF_C) ) || \ + ( !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA384_C) ) || \ + ( !defined(MBEDTLS_PSA_CRYPTO_C) ) ) +#error "MBEDTLS_SSL_PROTO_TLS1_3 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && \ + !(defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) || \ + defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) ) +#error "One or more versions of the TLS protocol are enabled " \ + "but no key exchange methods defined with MBEDTLS_KEY_EXCHANGE_xxxx" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ + !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) +#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ + !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_CONNECTION_ID defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + defined(MBEDTLS_SSL_CID_IN_LEN_MAX) && \ + MBEDTLS_SSL_CID_IN_LEN_MAX > 255 +#error "MBEDTLS_SSL_CID_IN_LEN_MAX too large (max 255)" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CONNECTION_ID) && \ + defined(MBEDTLS_SSL_CID_OUT_LEN_MAX) && \ + MBEDTLS_SSL_CID_OUT_LEN_MAX > 255 +#error "MBEDTLS_SSL_CID_OUT_LEN_MAX too large (max 255)" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + !defined(MBEDTLS_X509_CRT_PARSE_C) +#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_THREADING_PTHREAD) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_ALT) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_C defined, single threading implementation required" +#endif +#undef MBEDTLS_THREADING_IMPL + +#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_PSA_CRYPTO_C) +#error "MBEDTLS_USE_PSA_CRYPTO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) +#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_PK_PARSE_C) ) +#error "MBEDTLS_X509_USE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ + !defined(MBEDTLS_PK_WRITE_C) ) +#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) +#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" +#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ + +#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ + defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" +#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ + +#if defined(MBEDTLS_SSL_DTLS_SRTP) && ( !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_SRTP defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH) && ( !defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) ) +#error "MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH defined, but not all prerequisites" +#endif + + + +/* Reject attempts to enable options that have been removed and that could + * cause a build to succeed but with features removed. */ + +#if defined(MBEDTLS_HAVEGE_C) //no-check-names +#error "MBEDTLS_HAVEGE_C was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/2599" +#endif + +#if defined(MBEDTLS_SSL_HW_RECORD_ACCEL) //no-check-names +#error "MBEDTLS_SSL_HW_RECORD_ACCEL was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) //no-check-names +#error "MBEDTLS_SSL_PROTO_SSL3 (SSL v3.0 support) was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO) //no-check-names +#error "MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO (SSL v2 ClientHello support) was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) //no-check-names +#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT (compatibility with the buggy implementation of truncated HMAC in Mbed TLS up to 2.7) was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) //no-check-names +#error "MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES was removed in Mbed TLS 3.0. See the ChangeLog entry if you really need SHA-1-signed certificates." +#endif + +#if defined(MBEDTLS_ZLIB_SUPPORT) //no-check-names +#error "MBEDTLS_ZLIB_SUPPORT was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4031" +#endif + +#if defined(MBEDTLS_CHECK_PARAMS) //no-check-names +#error "MBEDTLS_CHECK_PARAMS was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4313" +#endif + +#if defined(MBEDTLS_SSL_CID_PADDING_GRANULARITY) //no-check-names +#error "MBEDTLS_SSL_CID_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4335" +#endif + +#if defined(MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY) //no-check-names +#error "MBEDTLS_SSL_TLS1_3_PADDING_GRANULARITY was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4335" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) //no-check-names +#error "MBEDTLS_SSL_TRUNCATED_HMAC was removed in Mbed TLS 3.0. See https://github.com/ARMmbed/mbedtls/issues/4341" +#endif + +/* + * Avoid warning from -pedantic. This is a convenient place for this + * workaround since this is included by every single file before the + * #if defined(MBEDTLS_xxx_C) that results in empty translation units. + */ +typedef int mbedtls_iso_c_forbids_empty_translation_units; + +#endif /* MBEDTLS_CHECK_CONFIG_H */ + + +// LICENSE_CHANGE_END + + +#endif /* MBEDTLS_BUILD_INFO_H */ + + +// LICENSE_CHANGE_END + + +#include + +/** Helper to define a function as static except when building invasive tests. + * + * If a function is only used inside its own source file and should be + * declared `static` to allow the compiler to optimize for code size, + * but that function has unit tests, define it with + * ``` + * MBEDTLS_STATIC_TESTABLE int mbedtls_foo(...) { ... } + * ``` + * and declare it in a header in the `library/` directory with + * ``` + * #if defined(MBEDTLS_TEST_HOOKS) + * int mbedtls_foo(...); + * #endif + * ``` + */ +#if defined(MBEDTLS_TEST_HOOKS) +#define MBEDTLS_STATIC_TESTABLE +#else +#define MBEDTLS_STATIC_TESTABLE static +#endif + +#if defined(MBEDTLS_TEST_HOOKS) +extern void (*mbedtls_test_hook_test_fail)( const char * test, int line, const char * file ); +#define MBEDTLS_TEST_HOOK_TEST_ASSERT( TEST ) \ + do { \ + if( ( ! ( TEST ) ) && ( ( *mbedtls_test_hook_test_fail ) != NULL ) ) \ + { \ + ( *mbedtls_test_hook_test_fail )( #TEST, __LINE__, __FILE__ ); \ + } \ + } while( 0 ) +#else +#define MBEDTLS_TEST_HOOK_TEST_ASSERT( TEST ) +#endif /* defined(MBEDTLS_TEST_HOOKS) */ + +/** Allow library to access its structs' private members. + * + * Although structs defined in header files are publicly available, + * their members are private and should not be accessed by the user. + */ +#define MBEDTLS_ALLOW_PRIVATE_ACCESS + +/** Byte Reading Macros + * + * Given a multi-byte integer \p x, MBEDTLS_BYTE_n retrieves the n-th + * byte from x, where byte 0 is the least significant byte. + */ +#define MBEDTLS_BYTE_0( x ) ( (uint8_t) ( ( x ) & 0xff ) ) +#define MBEDTLS_BYTE_1( x ) ( (uint8_t) ( ( ( x ) >> 8 ) & 0xff ) ) +#define MBEDTLS_BYTE_2( x ) ( (uint8_t) ( ( ( x ) >> 16 ) & 0xff ) ) +#define MBEDTLS_BYTE_3( x ) ( (uint8_t) ( ( ( x ) >> 24 ) & 0xff ) ) +#define MBEDTLS_BYTE_4( x ) ( (uint8_t) ( ( ( x ) >> 32 ) & 0xff ) ) +#define MBEDTLS_BYTE_5( x ) ( (uint8_t) ( ( ( x ) >> 40 ) & 0xff ) ) +#define MBEDTLS_BYTE_6( x ) ( (uint8_t) ( ( ( x ) >> 48 ) & 0xff ) ) +#define MBEDTLS_BYTE_7( x ) ( (uint8_t) ( ( ( x ) >> 56 ) & 0xff ) ) + +/** + * Get the unsigned 32 bits integer corresponding to four bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the four bytes from. + * \param offset Offset from \p data of the first and most significant + * byte of the four bytes to build the 32 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT32_BE +#define MBEDTLS_GET_UINT32_BE( data , offset ) \ + ( \ + ( (uint32_t) ( data )[( offset ) ] << 24 ) \ + | ( (uint32_t) ( data )[( offset ) + 1] << 16 ) \ + | ( (uint32_t) ( data )[( offset ) + 2] << 8 ) \ + | ( (uint32_t) ( data )[( offset ) + 3] ) \ + ) +#endif + +/** + * Put in memory a 32 bits unsigned integer in big-endian order. + * + * \param n 32 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 32 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the most significant + * byte of the 32 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT32_BE +#define MBEDTLS_PUT_UINT32_BE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_3( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 3] = MBEDTLS_BYTE_0( n ); \ +} +#endif + +/** + * Get the unsigned 32 bits integer corresponding to four bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the four bytes from. + * \param offset Offset from \p data of the first and least significant + * byte of the four bytes to build the 32 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT32_LE +#define MBEDTLS_GET_UINT32_LE( data, offset ) \ + ( \ + ( (uint32_t) ( data )[( offset ) ] ) \ + | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \ + | ( (uint32_t) ( data )[( offset ) + 2] << 16 ) \ + | ( (uint32_t) ( data )[( offset ) + 3] << 24 ) \ + ) +#endif + +/** + * Put in memory a 32 bits unsigned integer in little-endian order. + * + * \param n 32 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 32 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the least significant + * byte of the 32 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT32_LE +#define MBEDTLS_PUT_UINT32_LE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n ); \ +} +#endif + +/** + * Get the unsigned 16 bits integer corresponding to two bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the two bytes from. + * \param offset Offset from \p data of the first and least significant + * byte of the two bytes to build the 16 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT16_LE +#define MBEDTLS_GET_UINT16_LE( data, offset ) \ + ( \ + ( (uint16_t) ( data )[( offset ) ] ) \ + | ( (uint16_t) ( data )[( offset ) + 1] << 8 ) \ + ) +#endif + +/** + * Put in memory a 16 bits unsigned integer in little-endian order. + * + * \param n 16 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 16 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the least significant + * byte of the 16 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT16_LE +#define MBEDTLS_PUT_UINT16_LE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \ +} +#endif + +/** + * Get the unsigned 16 bits integer corresponding to two bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the two bytes from. + * \param offset Offset from \p data of the first and most significant + * byte of the two bytes to build the 16 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT16_BE +#define MBEDTLS_GET_UINT16_BE( data, offset ) \ + ( \ + ( (uint16_t) ( data )[( offset ) ] << 8 ) \ + | ( (uint16_t) ( data )[( offset ) + 1] ) \ + ) +#endif + +/** + * Put in memory a 16 bits unsigned integer in big-endian order. + * + * \param n 16 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 16 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the most significant + * byte of the 16 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT16_BE +#define MBEDTLS_PUT_UINT16_BE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_0( n ); \ +} +#endif + +/** + * Get the unsigned 24 bits integer corresponding to three bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the three bytes from. + * \param offset Offset from \p data of the first and most significant + * byte of the three bytes to build the 24 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT24_BE +#define MBEDTLS_GET_UINT24_BE( data , offset ) \ + ( \ + ( (uint32_t) ( data )[( offset ) ] << 16 ) \ + | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \ + | ( (uint32_t) ( data )[( offset ) + 2] ) \ + ) +#endif + +/** + * Put in memory a 24 bits unsigned integer in big-endian order. + * + * \param n 24 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 24 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the most significant + * byte of the 24 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT24_BE +#define MBEDTLS_PUT_UINT24_BE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_0( n ); \ +} +#endif + +/** + * Get the unsigned 24 bits integer corresponding to three bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the three bytes from. + * \param offset Offset from \p data of the first and least significant + * byte of the three bytes to build the 24 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT24_LE +#define MBEDTLS_GET_UINT24_LE( data, offset ) \ + ( \ + ( (uint32_t) ( data )[( offset ) ] ) \ + | ( (uint32_t) ( data )[( offset ) + 1] << 8 ) \ + | ( (uint32_t) ( data )[( offset ) + 2] << 16 ) \ + ) +#endif + +/** + * Put in memory a 24 bits unsigned integer in little-endian order. + * + * \param n 24 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 24 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the least significant + * byte of the 24 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT24_LE +#define MBEDTLS_PUT_UINT24_LE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \ +} +#endif + +/** + * Get the unsigned 64 bits integer corresponding to eight bytes in + * big-endian order (MSB first). + * + * \param data Base address of the memory to get the eight bytes from. + * \param offset Offset from \p data of the first and most significant + * byte of the eight bytes to build the 64 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT64_BE +#define MBEDTLS_GET_UINT64_BE( data, offset ) \ + ( \ + ( (uint64_t) ( data )[( offset ) ] << 56 ) \ + | ( (uint64_t) ( data )[( offset ) + 1] << 48 ) \ + | ( (uint64_t) ( data )[( offset ) + 2] << 40 ) \ + | ( (uint64_t) ( data )[( offset ) + 3] << 32 ) \ + | ( (uint64_t) ( data )[( offset ) + 4] << 24 ) \ + | ( (uint64_t) ( data )[( offset ) + 5] << 16 ) \ + | ( (uint64_t) ( data )[( offset ) + 6] << 8 ) \ + | ( (uint64_t) ( data )[( offset ) + 7] ) \ + ) +#endif + +/** + * Put in memory a 64 bits unsigned integer in big-endian order. + * + * \param n 64 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 64 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the most significant + * byte of the 64 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT64_BE +#define MBEDTLS_PUT_UINT64_BE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_7( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_6( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_5( n ); \ + ( data )[( offset ) + 3] = MBEDTLS_BYTE_4( n ); \ + ( data )[( offset ) + 4] = MBEDTLS_BYTE_3( n ); \ + ( data )[( offset ) + 5] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 6] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 7] = MBEDTLS_BYTE_0( n ); \ +} +#endif + +/** + * Get the unsigned 64 bits integer corresponding to eight bytes in + * little-endian order (LSB first). + * + * \param data Base address of the memory to get the eight bytes from. + * \param offset Offset from \p data of the first and least significant + * byte of the eight bytes to build the 64 bits unsigned + * integer from. + */ +#ifndef MBEDTLS_GET_UINT64_LE +#define MBEDTLS_GET_UINT64_LE( data, offset ) \ + ( \ + ( (uint64_t) ( data )[( offset ) + 7] << 56 ) \ + | ( (uint64_t) ( data )[( offset ) + 6] << 48 ) \ + | ( (uint64_t) ( data )[( offset ) + 5] << 40 ) \ + | ( (uint64_t) ( data )[( offset ) + 4] << 32 ) \ + | ( (uint64_t) ( data )[( offset ) + 3] << 24 ) \ + | ( (uint64_t) ( data )[( offset ) + 2] << 16 ) \ + | ( (uint64_t) ( data )[( offset ) + 1] << 8 ) \ + | ( (uint64_t) ( data )[( offset ) ] ) \ + ) +#endif + +/** + * Put in memory a 64 bits unsigned integer in little-endian order. + * + * \param n 64 bits unsigned integer to put in memory. + * \param data Base address of the memory where to put the 64 + * bits unsigned integer in. + * \param offset Offset from \p data where to put the least significant + * byte of the 64 bits unsigned integer \p n. + */ +#ifndef MBEDTLS_PUT_UINT64_LE +#define MBEDTLS_PUT_UINT64_LE( n, data, offset ) \ +{ \ + ( data )[( offset ) ] = MBEDTLS_BYTE_0( n ); \ + ( data )[( offset ) + 1] = MBEDTLS_BYTE_1( n ); \ + ( data )[( offset ) + 2] = MBEDTLS_BYTE_2( n ); \ + ( data )[( offset ) + 3] = MBEDTLS_BYTE_3( n ); \ + ( data )[( offset ) + 4] = MBEDTLS_BYTE_4( n ); \ + ( data )[( offset ) + 5] = MBEDTLS_BYTE_5( n ); \ + ( data )[( offset ) + 6] = MBEDTLS_BYTE_6( n ); \ + ( data )[( offset ) + 7] = MBEDTLS_BYTE_7( n ); \ +} +#endif + +/* Fix MSVC C99 compatible issue + * MSVC support __func__ from visual studio 2015( 1900 ) + * Use MSVC predefine macro to avoid name check fail. + */ +#if (defined(_MSC_VER) && ( _MSC_VER <= 1900 )) +#define /*no-check-names*/ __func__ __FUNCTION__ +#endif + +#endif /* MBEDTLS_LIBRARY_COMMON_H */ + + +// LICENSE_CHANGE_END + + +#if defined(MBEDTLS_ASN1_PARSE_C) + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/** + * \file asn1.h + * + * \brief Generic ASN.1 parsing + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_ASN1_H +#define MBEDTLS_ASN1_H + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + + /** + * \file private_access.h + * + * \brief Macro wrapper for struct's memebrs. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_PRIVATE_ACCESS_H +#define MBEDTLS_PRIVATE_ACCESS_H + +#ifndef MBEDTLS_ALLOW_PRIVATE_ACCESS +#define MBEDTLS_PRIVATE(member) private_##member +#else +#define MBEDTLS_PRIVATE(member) member +#endif + +#endif /* MBEDTLS_PRIVATE_ACCESS_H */ + + +// LICENSE_CHANGE_END + + + + +#include + +#if defined(MBEDTLS_BIGNUM_C) + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/** + * \file bignum.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_BIGNUM_H +#define MBEDTLS_BIGNUM_H + + + + +#include +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +/** An error occurred while reading from or writing to a file. */ +#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 +/** There is an invalid character in the digit string. */ +#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 +/** The buffer is too small to write to. */ +#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 +/** The input arguments are negative or result in illegal output. */ +#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A +/** The input argument for division is zero, which is not allowed. */ +#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C +/** The input arguments are not acceptable. */ +#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E +/** Memory allocation failed. */ +#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 + +#define MBEDTLS_MPI_CHK(f) \ + do \ + { \ + if( ( ret = (f) ) != 0 ) \ + goto cleanup; \ + } while( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define MBEDTLS_MPI_MAX_LIMBS 10000 + +#if !defined(MBEDTLS_MPI_WINDOW_SIZE) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 ** MBEDTLS_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum window size used. */ +#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ + +#if !defined(MBEDTLS_MPI_MAX_SIZE) +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can temporarily result in larger MPIs. So the number + * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. + */ +#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ +#endif /* !MBEDTLS_MPI_MAX_SIZE */ + +#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mbedtls_mpi_read_file() and writing to files with + * mbedtls_mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) +#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 +#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise. + * + * 32 or 64-bit integer types can be forced regardless of the underlying + * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 + * respectively and undefining MBEDTLS_HAVE_ASM. + * + * Double-width integers (e.g. 128-bit in 64-bit architectures) can be + * disabled by defining MBEDTLS_NO_UDBL_DIVISION. + */ +#if !defined(MBEDTLS_HAVE_INT32) + #if defined(_MSC_VER) && defined(_M_AMD64) + /* Always choose 64-bit when using MSC */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #elif defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + ( defined(__sparc__) && defined(__arch64__) ) || \ + defined(__s390x__) || defined(__mips64) || \ + defined(__aarch64__) ) + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(__ARMCC_VERSION) && defined(__aarch64__) + /* + * __ARMCC_VERSION is defined for both armcc and armclang and + * __aarch64__ is only defined by armclang when compiling 64-bit code + */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef __uint128_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(MBEDTLS_HAVE_INT64) + /* Force 64-bit integers with unknown compiler */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #endif +#endif /* !MBEDTLS_HAVE_INT32 */ + +#if !defined(MBEDTLS_HAVE_INT64) + /* Default to 32-bit compilation */ + #if !defined(MBEDTLS_HAVE_INT32) + #define MBEDTLS_HAVE_INT32 + #endif /* !MBEDTLS_HAVE_INT32 */ + typedef int32_t mbedtls_mpi_sint; + typedef uint32_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + typedef uint64_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ +#endif /* !MBEDTLS_HAVE_INT64 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct mbedtls_mpi +{ + int MBEDTLS_PRIVATE(s); /*!< Sign: -1 if the mpi is negative, 1 otherwise */ + size_t MBEDTLS_PRIVATE(n); /*!< total # of limbs */ + mbedtls_mpi_uint *MBEDTLS_PRIVATE(p); /*!< pointer to limbs */ +} +mbedtls_mpi; + +/** + * \brief Initialize an MPI context. + * + * This makes the MPI ready to be set or freed, + * but does not define a value for the MPI. + * + * \param X The MPI context to initialize. This must not be \c NULL. + */ +void mbedtls_mpi_init( mbedtls_mpi *X ); + +/** + * \brief This function frees the components of an MPI context. + * + * \param X The MPI context to be cleared. This may be \c NULL, + * in which case this function is a no-op. If it is + * not \c NULL, it must point to an initialized MPI. + */ +void mbedtls_mpi_free( mbedtls_mpi *X ); + +/** + * \brief Enlarge an MPI to the specified number of limbs. + * + * \note This function does nothing if the MPI is + * already large enough. + * + * \param X The MPI to grow. It must be initialized. + * \param nblimbs The target number of limbs. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief This function resizes an MPI downwards, keeping at least the + * specified number of limbs. + * + * If \c X is smaller than \c nblimbs, it is resized up + * instead. + * + * \param X The MPI to shrink. This must point to an initialized MPI. + * \param nblimbs The minimum number of limbs to keep. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * (this can only happen when resizing up). + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Make a copy of an MPI. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param Y The source MPI. This must point to an initialized MPI. + * + * \note The limb-buffer in the destination MPI is enlarged + * if necessary to hold the value in the source MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Swap the contents of two MPIs. + * + * \param X The first MPI. It must be initialized. + * \param Y The second MPI. It must be initialized. + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); + +/** + * \brief Perform a safe conditional copy of MPI which doesn't + * reveal whether the condition was true or not. + * + * \param X The MPI to conditionally assign to. This must point + * to an initialized MPI. + * \param Y The MPI to be assigned from. This must point to an + * initialized MPI. + * \param assign The condition deciding whether to perform the + * assignment or not. Possible values: + * * \c 1: Perform the assignment `X = Y`. + * * \c 0: Keep the original value of \p X. + * + * \note This function is equivalent to + * `if( assign ) mbedtls_mpi_copy( X, Y );` + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Perform a safe conditional swap which doesn't + * reveal whether the condition was true or not. + * + * \param X The first MPI. This must be initialized. + * \param Y The second MPI. This must be initialized. + * \param assign The condition deciding whether to perform + * the swap or not. Possible values: + * * \c 1: Swap the values of \p X and \p Y. + * * \c 0: Keep the original values of \p X and \p Y. + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + * + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Store integer value in MPI. + * + * \param X The MPI to set. This must be initialized. + * \param z The value to use. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Get a specific bit from an MPI. + * + * \param X The MPI to query. This must be initialized. + * \param pos Zero-based index of the bit to query. + * + * \return \c 0 or \c 1 on success, depending on whether bit \c pos + * of \c X is unset or set. + * \return A negative error code on failure. + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); + +/** + * \brief Modify a specific bit in an MPI. + * + * \note This function will grow the target MPI if necessary to set a + * bit to \c 1 in a not yet existing limb. It will not grow if + * the bit should be set to \c 0. + * + * \param X The MPI to modify. This must be initialized. + * \param pos Zero-based index of the bit to modify. + * \param val The desired value of bit \c pos: \c 0 or \c 1. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of bits of value \c 0 before the + * least significant bit of value \c 1. + * + * \note This is the same as the zero-based index of + * the least significant bit of value \c 1. + * + * \param X The MPI to query. + * + * \return The number of bits of value \c 0 before the least significant + * bit of value \c 1 in \p X. + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant bit of value \c 1. + * + * * \note This is same as the one-based index of the most + * significant bit of value \c 1. + * + * \param X The MPI to query. This must point to an initialized MPI. + * + * \return The number of bits up to and including the most + * significant bit of value \c 1. + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); + +/** + * \brief Return the total size of an MPI value in bytes. + * + * \param X The MPI to use. This must point to an initialized MPI. + * + * \note The value returned by this function may be less than + * the number of bytes used to store \p X internally. + * This happens if and only if there are trailing bytes + * of value zero. + * + * \return The least number of bytes capable of storing + * the absolute value of \p X. + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ); + +/** + * \brief Import an MPI from an ASCII string. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the input string. + * \param s Null-terminated string buffer. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); + +/** + * \brief Export an MPI to an ASCII string. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base of the output string. + * \param buf The buffer to write the string to. This must be writable + * buffer of length \p buflen Bytes. + * \param buflen The available size in Bytes of \p buf. + * \param olen The address at which to store the length of the string + * written, including the final \c NULL byte. This must + * not be \c NULL. + * + * \note You can call this function with `buflen == 0` to obtain the + * minimum required buffer size in `*olen`. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the target buffer \p buf + * is too small to hold the value of \p X in the desired base. + * In this case, `*olen` is nonetheless updated to contain the + * size of \p buf required for a successful call. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Read an MPI from a line in an opened file. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param radix The numeric base of the string representation used + * in the source line. + * \param fin The input file handle to use. This must not be \c NULL. + * + * \note On success, this function advances the file stream + * to the end of the current line or to EOF. + * + * The function returns \c 0 on an empty line. + * + * Leading whitespaces are ignored, as is a + * '0x' prefix for radix \c 16. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if the file read buffer + * is too small. + * \return Another negative error code on failure. + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); + +/** + * \brief Export an MPI into an opened file. + * + * \param p A string prefix to emit prior to the MPI data. + * For example, this might be a label, or "0x" when + * printing in base \c 16. This may be \c NULL if no prefix + * is needed. + * \param X The source MPI. This must point to an initialized MPI. + * \param radix The numeric base to be used in the emitted string. + * \param fout The output file handle. This may be \c NULL, in which case + * the output is written to \c stdout. + * + * \return \c 0 if successful. + * \return A negative error code on failure. + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, + int radix, FILE *fout ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Import an MPI from unsigned big endian binary data. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param buf The input buffer. This must be a readable buffer of length + * \p buflen Bytes. + * \param buflen The length of the input buffer \p p in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Import X from unsigned binary data, little endian + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param buf The input buffer. This must be a readable buffer of length + * \p buflen Bytes. + * \param buflen The length of the input buffer \p p in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_read_binary_le( mbedtls_mpi *X, + const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian. + * Always fills the whole buffer, which will start with zeros + * if the number is smaller. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, + size_t buflen ); + +/** + * \brief Export X into unsigned binary data, little endian. + * Always fills the whole buffer, which will end with zeros + * if the number is smaller. + * + * \param X The source MPI. This must point to an initialized MPI. + * \param buf The output buffer. This must be a writable buffer of length + * \p buflen Bytes. + * \param buflen The size of the output buffer \p buf in Bytes. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if \p buf isn't + * large enough to hold the value of \p X. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ); + +/** + * \brief Perform a left-shift on an MPI: X <<= count + * + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); + +/** + * \brief Perform a right-shift on an MPI: X >>= count + * + * \param X The MPI to shift. This must point to an initialized MPI. + * \param count The number of bits to shift by. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); + +/** + * \brief Compare the absolute values of two MPIs. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. + * + * \return \c 1 if `|X|` is greater than `|Y|`. + * \return \c -1 if `|X|` is lesser than `|Y|`. + * \return \c 0 if `|X|` is equal to `|Y|`. + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare two MPIs. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param Y The right-hand MPI. This must point to an initialized MPI. + * + * \return \c 1 if \p X is greater than \p Y. + * \return \c -1 if \p X is lesser than \p Y. + * \return \c 0 if \p X is equal to \p Y. + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Check if an MPI is less than the other in constant time. + * + * \param X The left-hand MPI. This must point to an initialized MPI + * with the same allocated length as Y. + * \param Y The right-hand MPI. This must point to an initialized MPI + * with the same allocated length as X. + * \param ret The result of the comparison: + * \c 1 if \p X is less than \p Y. + * \c 0 if \p X is greater than or equal to \p Y. + * + * \return 0 on success. + * \return MBEDTLS_ERR_MPI_BAD_INPUT_DATA if the allocated length of + * the two input MPIs is not the same. + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, const mbedtls_mpi *Y, + unsigned *ret ); + +/** + * \brief Compare an MPI with an integer. + * + * \param X The left-hand MPI. This must point to an initialized MPI. + * \param z The integer value to compare \p X to. + * + * \return \c 1 if \p X is greater than \p z. + * \return \c -1 if \p X is lesser than \p z. + * \return \c 0 if \p X is equal to \p z. + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Perform an unsigned addition of MPIs: X = |A| + |B| + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform an unsigned subtraction of MPIs: X = |A| - |B| + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is greater than \p A. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed addition of MPIs: X = A + B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param B The second summand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed subtraction of MPIs: X = A - B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param B The subtrahend. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a signed addition of an MPI and an integer: X = A + b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first summand. This must point to an initialized MPI. + * \param b The second summand. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a signed subtraction of an MPI and an integer: + * X = A - b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The minuend. This must point to an initialized MPI. + * \param b The subtrahend. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a multiplication of two MPIs: X = A * B + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param B The second factor. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a multiplication of an MPI with an unsigned integer: + * X = A * b + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The first factor. This must point to an initialized MPI. + * \param b The second factor. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, + mbedtls_mpi_uint b ); + +/** + * \brief Perform a division with remainder of two MPIs: + * A = Q * B + R + * + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param B The divisor. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a division with remainder of an MPI by an integer: + * A = Q * b + R + * + * \param Q The destination MPI for the quotient. + * This may be \c NULL if the value of the + * quotient is not needed. + * \param R The destination MPI for the remainder value. + * This may be \c NULL if the value of the + * remainder is not needed. + * \param A The dividend. This must point to an initialized MPi. + * \param b The divisor. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a modular reduction. R = A mod B + * + * \param R The destination MPI for the residue value. + * This must point to an initialized MPI. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPI. + * \param B The base of the modular reduction. + * This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p B equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p B is negative. + * \return Another negative error code on different kinds of failure. + * + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Perform a modular reduction with respect to an integer. + * r = A mod b + * + * \param r The address at which to store the residue. + * This must not be \c NULL. + * \param A The MPI to compute the residue of. + * This must point to an initialized MPi. + * \param b The integer base of the modular reduction. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if \p b equals zero. + * \return #MBEDTLS_ERR_MPI_NEGATIVE_VALUE if \p b is negative. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, + mbedtls_mpi_sint b ); + +/** + * \brief Perform a sliding-window exponentiation: X = A^E mod N + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The base of the exponentiation. + * This must point to an initialized MPI. + * \param E The exponent MPI. This must point to an initialized MPI. + * \param N The base for the modular reduction. This must point to an + * initialized MPI. + * \param prec_RR A helper MPI depending solely on \p N which can be used to + * speed-up multiple modular exponentiations for the same value + * of \p N. This may be \c NULL. If it is not \c NULL, it must + * point to an initialized MPI. If it hasn't been used after + * the call to mbedtls_mpi_init(), this function will compute + * the helper value and store it in \p prec_RR for reuse on + * subsequent calls to this function. Otherwise, the function + * will assume that \p prec_RR holds the helper value set by a + * previous call to mbedtls_mpi_exp_mod(), and reuse it. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \c N is negative or + * even, or if \c E is negative. + * \return Another negative error code on different kinds of failures. + * + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *prec_RR ); + +/** + * \brief Fill an MPI with a number of random bytes. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param size The number of random bytes to generate. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context argument. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on failure. + * + * \note The bytes obtained from the RNG are interpreted + * as a big-endian representation of an MPI; this can + * be relevant in applications like deterministic ECDSA. + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** Generate a random number uniformly in a range. + * + * This function generates a random number between \p min inclusive and + * \p N exclusive. + * + * The procedure complies with RFC 6979 §3.3 (deterministic ECDSA) + * when the RNG is a suitably parametrized instance of HMAC_DRBG + * and \p min is \c 1. + * + * \note There are `N - min` possible outputs. The lower bound + * \p min can be reached, but the upper bound \p N cannot. + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param min The minimum value to return. + * It must be nonnegative. + * \param N The upper bound of the range, exclusive. + * In other words, this is one plus the maximum value to return. + * \p N must be strictly larger than \p min. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p min or \p N is invalid + * or if they are incompatible. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if the implementation was + * unable to find a suitable value within a limited number + * of attempts. This has a negligible probability if \p N + * is significantly larger than \p min, which is the case + * for all usual cryptographic applications. + * \return Another negative error code on failure. + */ +int mbedtls_mpi_random( mbedtls_mpi *X, + mbedtls_mpi_sint min, + const mbedtls_mpi *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Compute the greatest common divisor: G = gcd(A, B) + * + * \param G The destination MPI. This must point to an initialized MPI. + * \param A The first operand. This must point to an initialized MPI. + * \param B The second operand. This must point to an initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return Another negative error code on different kinds of failure. + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, + const mbedtls_mpi *B ); + +/** + * \brief Compute the modular inverse: X = A^-1 mod N + * + * \param X The destination MPI. This must point to an initialized MPI. + * \param A The MPI to calculate the modular inverse of. This must point + * to an initialized MPI. + * \param N The base of the modular inversion. This must point to an + * initialized MPI. + * + * \return \c 0 if successful. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if \p N is less than + * or equal to one. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p has no modular inverse + * with respect to \p N. + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *N ); + +/** + * \brief Miller-Rabin primality test. + * + * \warning If \p X is potentially generated by an adversary, for example + * when validating cryptographic parameters that you didn't + * generate yourself and that are supposed to be prime, then + * \p rounds should be at least the half of the security + * strength of the cryptographic algorithm. On the other hand, + * if \p X is chosen uniformly or non-adversially (as is the + * case when mbedtls_mpi_gen_prime calls this function), then + * \p rounds can be much lower. + * + * \param X The MPI to check for primality. + * This must point to an initialized MPI. + * \param rounds The number of bases to perform the Miller-Rabin primality + * test for. The probability of returning 0 on a composite is + * at most 2-2*\p rounds. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, i.e. \p X is probably prime. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if \p X is not prime. + * \return Another negative error code on other kinds of failure. + */ +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +/** + * \brief Flags for mbedtls_mpi_gen_prime() + * + * Each of these flags is a constraint on the result X returned by + * mbedtls_mpi_gen_prime(). + */ +typedef enum { + MBEDTLS_MPI_GEN_PRIME_FLAG_DH = 0x0001, /**< (X-1)/2 is prime too */ + MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR = 0x0002, /**< lower error rate from 2-80 to 2-128 */ +} mbedtls_mpi_gen_prime_flag_t; + +/** + * \brief Generate a prime number. + * + * \param X The destination MPI to store the generated prime in. + * This must point to an initialized MPi. + * \param nbits The required size of the destination MPI in bits. + * This must be between \c 3 and #MBEDTLS_MPI_MAX_BITS. + * \param flags A mask of flags of type #mbedtls_mpi_gen_prime_flag_t. + * \param f_rng The RNG function to use. This must not be \c NULL. + * \param p_rng The RNG parameter to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't use + * a context parameter. + * + * \return \c 0 if successful, in which case \p X holds a + * probably prime number. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED if a memory allocation failed. + * \return #MBEDTLS_ERR_MPI_BAD_INPUT_DATA if `nbits` is not between + * \c 3 and #MBEDTLS_MPI_MAX_BITS. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_mpi_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ + + +// LICENSE_CHANGE_END + +#endif + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \name ASN1 Error codes + * These error codes are OR'ed to X509 error codes for + * higher error granularity. + * ASN1 is a standard to specify data structures. + * \{ + */ +/** Out of data when parsing an ASN1 data structure. */ +#define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 +/** ASN1 tag was of an unexpected value. */ +#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 +/** Error when trying to determine the length or invalid length. */ +#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 +/** Actual length differs from expected length. */ +#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 +/** Data is invalid. */ +#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 +/** Memory allocation failed */ +#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A +/** Buffer too small when writing ASN.1 data structure. */ +#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C + +/* \} name */ + +/** + * \name DER constants + * These constants comply with the DER encoded ASN.1 type tags. + * DER encoding uses hexadecimal representation. + * An example DER sequence is:\n + * - 0x02 -- tag indicating INTEGER + * - 0x01 -- length in octets + * - 0x05 -- value + * Such sequences are typically read into \c ::mbedtls_x509_buf. + * \{ + */ +#define MBEDTLS_ASN1_BOOLEAN 0x01 +#define MBEDTLS_ASN1_INTEGER 0x02 +#define MBEDTLS_ASN1_BIT_STRING 0x03 +#define MBEDTLS_ASN1_OCTET_STRING 0x04 +#define MBEDTLS_ASN1_NULL 0x05 +#define MBEDTLS_ASN1_OID 0x06 +#define MBEDTLS_ASN1_ENUMERATED 0x0A +#define MBEDTLS_ASN1_UTF8_STRING 0x0C +#define MBEDTLS_ASN1_SEQUENCE 0x10 +#define MBEDTLS_ASN1_SET 0x11 +#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 +#define MBEDTLS_ASN1_T61_STRING 0x14 +#define MBEDTLS_ASN1_IA5_STRING 0x16 +#define MBEDTLS_ASN1_UTC_TIME 0x17 +#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 +#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C +#define MBEDTLS_ASN1_BMP_STRING 0x1E +#define MBEDTLS_ASN1_PRIMITIVE 0x00 +#define MBEDTLS_ASN1_CONSTRUCTED 0x20 +#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 + +/* Slightly smaller way to check if tag is a string tag + * compared to canonical implementation. */ +#define MBEDTLS_ASN1_IS_STRING_TAG( tag ) \ + ( ( tag ) < 32u && ( \ + ( ( 1u << ( tag ) ) & ( ( 1u << MBEDTLS_ASN1_BMP_STRING ) | \ + ( 1u << MBEDTLS_ASN1_UTF8_STRING ) | \ + ( 1u << MBEDTLS_ASN1_T61_STRING ) | \ + ( 1u << MBEDTLS_ASN1_IA5_STRING ) | \ + ( 1u << MBEDTLS_ASN1_UNIVERSAL_STRING ) | \ + ( 1u << MBEDTLS_ASN1_PRINTABLE_STRING ) | \ + ( 1u << MBEDTLS_ASN1_BIT_STRING ) ) ) != 0 ) ) + +/* + * Bit masks for each of the components of an ASN.1 tag as specified in + * ITU X.690 (08/2015), section 8.1 "General rules for encoding", + * paragraph 8.1.2.2: + * + * Bit 8 7 6 5 1 + * +-------+-----+------------+ + * | Class | P/C | Tag number | + * +-------+-----+------------+ + */ +#define MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 +#define MBEDTLS_ASN1_TAG_PC_MASK 0x20 +#define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F + +/* \} name */ +/* \} addtogroup asn1_module */ + +/** Returns the size of the binary string, without the trailing \\0 */ +#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) + +/** + * Compares an mbedtls_asn1_buf structure to a reference OID. + * + * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a + * 'unsigned char *oid' here! + */ +#define MBEDTLS_OID_CMP(oid_str, oid_buf) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ + memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) + +#define MBEDTLS_OID_CMP_RAW(oid_str, oid_buf, oid_buf_len) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf_len) ) || \ + memcmp( (oid_str), (oid_buf), (oid_buf_len) ) != 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Functions to parse ASN.1 data structures + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef struct mbedtls_asn1_buf +{ + int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ + size_t len; /**< ASN1 length, in octets. */ + unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ +} +mbedtls_asn1_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef struct mbedtls_asn1_bitstring +{ + size_t len; /**< ASN1 length, in octets. */ + unsigned char unused_bits; /**< Number of unused bits at the end of the string */ + unsigned char *p; /**< Raw ASN1 data for the bit string */ +} +mbedtls_asn1_bitstring; + +/** + * Container for a sequence of ASN.1 items + */ +typedef struct mbedtls_asn1_sequence +{ + mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ + + /** The next entry in the sequence. + * + * The details of memory management for sequences are not documented and + * may change in future versions. Set this field to \p NULL when + * initializing a structure, and do not modify it except via Mbed TLS + * library functions. + */ + struct mbedtls_asn1_sequence *next; +} +mbedtls_asn1_sequence; + +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +typedef struct mbedtls_asn1_named_data +{ + mbedtls_asn1_buf oid; /**< The object identifier. */ + mbedtls_asn1_buf val; /**< The named value. */ + + /** The next entry in the sequence. + * + * The details of memory management for named data sequences are not + * documented and may change in future versions. Set this field to \p NULL + * when initializing a structure, and do not modify it except via Mbed TLS + * library functions. + */ + struct mbedtls_asn1_named_data *next; + + /** Merge next item into the current one? + * + * This field exists for the sake of Mbed TLS's X.509 certificate parsing + * code and may change in future versions of the library. + */ + unsigned char MBEDTLS_PRIVATE(next_merged); +} +mbedtls_asn1_named_data; + +/** + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. + * + * \param p On entry, \c *p points to the first byte of the length, + * i.e. immediately after the tag. + * On successful completion, \c *p points to the first byte + * after the length, i.e. the first byte of the content. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On successful completion, \c *len contains the length + * read from the ASN.1 input. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element + * would end beyond \p end. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable. + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Get the tag and length of the element. + * Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * after the length, i.e. the first byte of the content. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On successful completion, \c *len contains the length + * read from the ASN.1 input. + * \param tag The expected tag. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the data does not start + * with the requested tag. + * \return #MBEDTLS_ERR_ASN1_OUT_OF_DATA if the ASN.1 element + * would end beyond \p end. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the length is unparseable. + */ +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ); + +/** + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value (\c 0 or \c 1). + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BOOLEAN. + */ +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 INTEGER. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + */ +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an enumerated ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param val On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 ENUMERATED. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + */ +int mbedtls_asn1_get_enum( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p is equal to \p end. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param bs On success, ::mbedtls_asn1_bitstring information about + * the parsed value. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains + * extra data after a valid BIT STRING. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BIT STRING. + */ +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs ); + +/** + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * of the content of the BIT STRING. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param len On success, \c *len is the length of the content in bytes. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_INVALID_DATA if the input starts with + * a valid BIT STRING with a nonzero number of unused bits. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 BIT STRING. + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Parses and splits an ASN.1 "SEQUENCE OF ". + * Updates the pointer to immediately behind the full sequence tag. + * + * This function allocates memory for the sequence elements. You can free + * the allocated memory with mbedtls_asn1_sequence_free(). + * + * \note On error, this function may return a partial list in \p cur. + * You must set `cur->next = NULL` before calling this function! + * Otherwise it is impossible to distinguish a previously non-null + * pointer from a pointer to an object allocated by this function. + * + * \note If the sequence is empty, this function does not modify + * \c *cur. If the sequence is valid and non-empty, this + * function sets `cur->buf.tag` to \p tag. This allows + * callers to distinguish between an empty sequence and + * a one-element sequence. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p is equal to \p end. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param cur A ::mbedtls_asn1_sequence which this function fills. + * When this function returns, \c *cur is the head of a linked + * list. Each node in this list is allocated with + * mbedtls_calloc() apart from \p cur itself, and should + * therefore be freed with mbedtls_free(). + * The list describes the content of the sequence. + * The head of the list (i.e. \c *cur itself) describes the + * first element, `*cur->next` describes the second element, etc. + * For each element, `buf.tag == tag`, `buf.len` is the length + * of the content of the content of the element, and `buf.p` + * points to the first byte of the content (i.e. immediately + * past the length of the element). + * Note that list elements may be allocated even on error. + * \param tag Each element of the sequence must have this tag. + * + * \return 0 if successful. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input contains + * extra data after a valid SEQUENCE OF \p tag. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts with + * an ASN.1 SEQUENCE in which an element has a tag that + * is different from \p tag. + * \return #MBEDTLS_ERR_ASN1_ALLOC_FAILED if a memory allocation failed. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 SEQUENCE. + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag ); +/** + * \brief Free a heap-allocated linked list presentation of + * an ASN.1 sequence, including the first element. + * + * There are two common ways to manage the memory used for the representation + * of a parsed ASN.1 sequence: + * - Allocate a head node `mbedtls_asn1_sequence *head` with mbedtls_calloc(). + * Pass this node as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head`. + * - Allocate a head node `mbedtls_asn1_sequence *head` in any manner, + * for example on the stack. Make sure that `head->next == NULL`. + * Pass `head` as the `cur` argument to mbedtls_asn1_get_sequence_of(). + * When you have finished processing the sequence, + * call mbedtls_asn1_sequence_free() on `head->cur`, + * then free `head` itself in the appropriate manner. + * + * \param seq The address of the first sequence component. This may + * be \c NULL, in which case this functions returns + * immediately. + */ +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ); + +/** + * \brief Traverse an ASN.1 SEQUENCE container and + * call a callback for each entry. + * + * This function checks that the input is a SEQUENCE of elements that + * each have a "must" tag, and calls a callback function on the elements + * that have a "may" tag. + * + * For example, to validate that the input is a SEQUENCE of `tag1` and call + * `cb` on each element, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0xff, tag1, 0, 0, cb, ctx); + * ``` + * + * To validate that the input is a SEQUENCE of ANY and call `cb` on + * each element, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0, 0, 0, 0, cb, ctx); + * ``` + * + * To validate that the input is a SEQUENCE of CHOICE {NULL, OCTET STRING} + * and call `cb` on each element that is an OCTET STRING, use + * ``` + * mbedtls_asn1_traverse_sequence_of(&p, end, 0xfe, 0x04, 0xff, 0x04, cb, ctx); + * ``` + * + * The callback is called on the elements with a "may" tag from left to + * right. If the input is not a valid SEQUENCE of elements with a "must" tag, + * the callback is called on the elements up to the leftmost point where + * the input is invalid. + * + * \warning This function is still experimental and may change + * at any time. + * + * \param p The address of the pointer to the beginning of + * the ASN.1 SEQUENCE header. This is updated to + * point to the end of the ASN.1 SEQUENCE container + * on a successful invocation. + * \param end The end of the ASN.1 SEQUENCE container. + * \param tag_must_mask A mask to be applied to the ASN.1 tags found within + * the SEQUENCE before comparing to \p tag_must_value. + * \param tag_must_val The required value of each ASN.1 tag found in the + * SEQUENCE, after masking with \p tag_must_mask. + * Mismatching tags lead to an error. + * For example, a value of \c 0 for both \p tag_must_mask + * and \p tag_must_val means that every tag is allowed, + * while a value of \c 0xFF for \p tag_must_mask means + * that \p tag_must_val is the only allowed tag. + * \param tag_may_mask A mask to be applied to the ASN.1 tags found within + * the SEQUENCE before comparing to \p tag_may_value. + * \param tag_may_val The desired value of each ASN.1 tag found in the + * SEQUENCE, after masking with \p tag_may_mask. + * Mismatching tags will be silently ignored. + * For example, a value of \c 0 for \p tag_may_mask and + * \p tag_may_val means that any tag will be considered, + * while a value of \c 0xFF for \p tag_may_mask means + * that all tags with value different from \p tag_may_val + * will be ignored. + * \param cb The callback to trigger for each component + * in the ASN.1 SEQUENCE that matches \p tag_may_val. + * The callback function is called with the following + * parameters: + * - \p ctx. + * - The tag of the current element. + * - A pointer to the start of the current element's + * content inside the input. + * - The length of the content of the current element. + * If the callback returns a non-zero value, + * the function stops immediately, + * forwarding the callback's return value. + * \param ctx The context to be passed to the callback \p cb. + * + * \return \c 0 if successful the entire ASN.1 SEQUENCE + * was traversed without parsing or callback errors. + * \return #MBEDTLS_ERR_ASN1_LENGTH_MISMATCH if the input + * contains extra data after a valid SEQUENCE + * of elements with an accepted tag. + * \return #MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if the input starts + * with an ASN.1 SEQUENCE in which an element has a tag + * that is not accepted. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 SEQUENCE. + * \return A non-zero error code forwarded from the callback + * \p cb in case the latter returns a non-zero value. + */ +int mbedtls_asn1_traverse_sequence_of( + unsigned char **p, + const unsigned char *end, + unsigned char tag_must_mask, unsigned char tag_must_val, + unsigned char tag_may_mask, unsigned char tag_may_val, + int (*cb)( void *ctx, int tag, + unsigned char* start, size_t len ), + void *ctx ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the ASN.1 element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param X On success, the parsed value. + * + * \return 0 if successful. + * \return An ASN.1 error code if the input does not start with + * a valid ASN.1 INTEGER. + * \return #MBEDTLS_ERR_ASN1_INVALID_LENGTH if the parsed value does + * not fit in an \c int. + * \return An MPI error code if the parsed value is too large. + */ +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the AlgorithmIdentifier element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param alg The buffer to receive the OID. + * \param params The buffer to receive the parameters. + * This is zeroized if there are no parameters. + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p On entry, \c *p points to the start of the ASN.1 element. + * On successful completion, \c *p points to the first byte + * beyond the AlgorithmIdentifier element. + * On error, the value of \c *p is undefined. + * \param end End of data. + * \param alg The buffer to receive the OID. + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ); + +/** + * \brief Find a specific named_data entry in a sequence or list based on + * the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( const mbedtls_asn1_named_data *list, + const char *oid, size_t len ); + +/** + * \brief Free a mbedtls_asn1_named_data entry + * + * \param entry The named data entry to free. + * This function calls mbedtls_free() on + * `entry->oid.p` and `entry->val.p`. + */ +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); + +/** + * \brief Free all entries in a mbedtls_asn1_named_data list. + * + * \param head Pointer to the head of the list of named data entries to free. + * This function calls mbedtls_asn1_free_named_data() and + * mbedtls_free() on each list element and + * sets \c *head to \c NULL. + */ +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); + +#ifdef __cplusplus +} +#endif + +#endif /* asn1.h */ + + +// LICENSE_CHANGE_END + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/** + * \file platform_util.h + * + * \brief Common and shared functions used by multiple modules in the Mbed TLS + * library. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_PLATFORM_UTIL_H +#define MBEDTLS_PLATFORM_UTIL_H + + + +#include +#if defined(MBEDTLS_HAVE_TIME_DATE) + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/** + * \file platform_time.h + * + * \brief mbed TLS Platform time abstraction + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_PLATFORM_TIME_H +#define MBEDTLS_PLATFORM_TIME_H + + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_config.h or define them on the compiler command line. + * \{ + */ + +/* + * The time_t datatype + */ +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) +typedef MBEDTLS_PLATFORM_TIME_TYPE_MACRO mbedtls_time_t; +#else +/* For time_t */ +#include +typedef time_t mbedtls_time_t; +#endif /* MBEDTLS_PLATFORM_TIME_TYPE_MACRO */ + +/* + * The function pointers for time + */ +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +extern mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* time ); + +/** + * \brief Set your own time function pointer + * + * \param time_func the time function implementation + * + * \return 0 + */ +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* time ) ); +#else +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) +#define mbedtls_time MBEDTLS_PLATFORM_TIME_MACRO +#else +#define mbedtls_time time +#endif /* MBEDTLS_PLATFORM_TIME_MACRO */ +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif /* platform_time.h */ + + +// LICENSE_CHANGE_END + +#include +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Internal macros meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 ) +#define MBEDTLS_INTERNAL_VALIDATE( cond ) do { } while( 0 ) + +/* Internal helper macros for deprecating API constants. */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +MBEDTLS_DEPRECATED typedef char const * mbedtls_deprecated_string_constant_t; +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_string_constant_t) ( VAL ) ) +MBEDTLS_DEPRECATED typedef int mbedtls_deprecated_numeric_constant_t; +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) \ + ( (mbedtls_deprecated_numeric_constant_t) ( VAL ) ) +#else /* MBEDTLS_DEPRECATED_WARNING */ +#define MBEDTLS_DEPRECATED +#define MBEDTLS_DEPRECATED_STRING_CONSTANT( VAL ) VAL +#define MBEDTLS_DEPRECATED_NUMERIC_CONSTANT( VAL ) VAL +#endif /* MBEDTLS_DEPRECATED_WARNING */ +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/* Implementation of the check-return facility. + * See the user documentation in mbedtls_config.h. + * + * Do not use this macro directly to annotate function: instead, + * use one of MBEDTLS_CHECK_RETURN_CRITICAL or MBEDTLS_CHECK_RETURN_TYPICAL + * depending on how important it is to check the return value. + */ +#if !defined(MBEDTLS_CHECK_RETURN) +#if defined(__GNUC__) +#define MBEDTLS_CHECK_RETURN __attribute__((__warn_unused_result__)) +#elif defined(_MSC_VER) && _MSC_VER >= 1700 +#include +#define MBEDTLS_CHECK_RETURN _Check_return_ +#else +#define MBEDTLS_CHECK_RETURN +#endif +#endif + +/** Critical-failure function + * + * This macro appearing at the beginning of the declaration of a function + * indicates that its return value should be checked in all applications. + * Omitting the check is very likely to indicate a bug in the application + * and will result in a compile-time warning if #MBEDTLS_CHECK_RETURN + * is implemented for the compiler in use. + * + * \note The use of this macro is a work in progress. + * This macro may be added to more functions in the future. + * Such an extension is not considered an API break, provided that + * there are near-unavoidable circumstances under which the function + * can fail. For example, signature/MAC/AEAD verification functions, + * and functions that require a random generator, are considered + * return-check-critical. + */ +#define MBEDTLS_CHECK_RETURN_CRITICAL MBEDTLS_CHECK_RETURN + +/** Ordinary-failure function + * + * This macro appearing at the beginning of the declaration of a function + * indicates that its return value should be generally be checked in portable + * applications. Omitting the check will result in a compile-time warning if + * #MBEDTLS_CHECK_RETURN is implemented for the compiler in use and + * #MBEDTLS_CHECK_RETURN_WARNING is enabled in the compile-time configuration. + * + * You can use #MBEDTLS_IGNORE_RETURN to explicitly ignore the return value + * of a function that is annotated with #MBEDTLS_CHECK_RETURN. + * + * \note The use of this macro is a work in progress. + * This macro will be added to more functions in the future. + * Eventually this should appear before most functions returning + * an error code (as \c int in the \c mbedtls_xxx API or + * as ::psa_status_t in the \c psa_xxx API). + */ +#if defined(MBEDTLS_CHECK_RETURN_WARNING) +#define MBEDTLS_CHECK_RETURN_TYPICAL MBEDTLS_CHECK_RETURN +#else +#define MBEDTLS_CHECK_RETURN_TYPICAL +#endif + +/** Benign-failure function + * + * This macro appearing at the beginning of the declaration of a function + * indicates that it is rarely useful to check its return value. + * + * This macro has an empty expansion. It exists for documentation purposes: + * a #MBEDTLS_CHECK_RETURN_OPTIONAL annotation indicates that the function + * has been analyzed for return-check usefuless, whereas the lack of + * an annotation indicates that the function has not been analyzed and its + * return-check usefulness is unknown. + */ +#define MBEDTLS_CHECK_RETURN_OPTIONAL + +/** \def MBEDTLS_IGNORE_RETURN + * + * Call this macro with one argument, a function call, to suppress a warning + * from #MBEDTLS_CHECK_RETURN due to that function call. + */ +#if !defined(MBEDTLS_IGNORE_RETURN) +/* GCC doesn't silence the warning with just (void)(result). + * (void)!(result) is known to work up at least up to GCC 10, as well + * as with Clang and MSVC. + * + * https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Non_002dbugs.html + * https://stackoverflow.com/questions/40576003/ignoring-warning-wunused-result + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425#c34 + */ +#define MBEDTLS_IGNORE_RETURN(result) ( (void) !( result ) ) +#endif + +/** + * \brief Securely zeroize a buffer + * + * The function is meant to wipe the data contained in a buffer so + * that it can no longer be recovered even if the program memory + * is later compromised. Call this function on sensitive data + * stored on the stack before returning from a function, and on + * sensitive data stored on the heap before freeing the heap + * object. + * + * It is extremely difficult to guarantee that calls to + * mbedtls_platform_zeroize() are not removed by aggressive + * compiler optimizations in a portable way. For this reason, Mbed + * TLS provides the configuration option + * MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for + * their platform and needs + * + * \param buf Buffer to be zeroized + * \param len Length of the buffer in bytes + * + */ +void mbedtls_platform_zeroize( void *buf, size_t len ); + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/** + * \brief Platform-specific implementation of gmtime_r() + * + * The function is a thread-safe abstraction that behaves + * similarly to the gmtime_r() function from Unix/POSIX. + * + * Mbed TLS will try to identify the underlying platform and + * make use of an appropriate underlying implementation (e.g. + * gmtime_r() for POSIX and gmtime_s() for Windows). If this is + * not possible, then gmtime() will be used. In this case, calls + * from the library to gmtime() will be guarded by the mutex + * mbedtls_threading_gmtime_mutex if MBEDTLS_THREADING_C is + * enabled. It is recommended that calls from outside the library + * are also guarded by this mutex. + * + * If MBEDTLS_PLATFORM_GMTIME_R_ALT is defined, then Mbed TLS will + * unconditionally use the alternative implementation for + * mbedtls_platform_gmtime_r() supplied by the user at compile time. + * + * \param tt Pointer to an object containing time (in seconds) since the + * epoch to be converted + * \param tm_buf Pointer to an object where the results will be stored + * + * \return Pointer to an object of type struct tm on success, otherwise + * NULL + */ +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ); +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PLATFORM_UTIL_H */ + + +// LICENSE_CHANGE_END + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/** + * \file error.h + * + * \brief Error to string translation + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_ERROR_H +#define MBEDTLS_ERROR_H + + + +#include + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/** + * Error code layout. + * + * Currently we try to keep all error codes within the negative space of 16 + * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In + * addition we'd like to give two layers of information on the error if + * possible. + * + * For that purpose the error codes are segmented in the following manner: + * + * 16 bit error code bit-segmentation + * + * 1 bit - Unused (sign bit) + * 3 bits - High level module ID + * 5 bits - Module-dependent error code + * 7 bits - Low level module errors + * + * For historical reasons, low-level error codes are divided in even and odd, + * even codes were assigned first, and -1 is reserved for other errors. + * + * Low-level module errors (0x0002-0x007E, 0x0001-0x007F) + * + * Module Nr Codes assigned + * ERROR 2 0x006E 0x0001 + * MPI 7 0x0002-0x0010 + * GCM 3 0x0012-0x0016 0x0013-0x0013 + * THREADING 3 0x001A-0x001E + * AES 5 0x0020-0x0022 0x0021-0x0025 + * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 2 0x0032-0x0032 0x0033-0x0033 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 0x003D-0x003F + * NET 13 0x0042-0x0052 0x0043-0x0049 + * ARIA 4 0x0058-0x005E + * ASN1 7 0x0060-0x006C + * CMAC 1 0x007A-0x007A + * PBKDF2 1 0x007C-0x007C + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 3 0x000D-0x0011 + * MD5 1 0x002F-0x002F + * RIPEMD160 1 0x0031-0x0031 + * SHA1 1 0x0035-0x0035 0x0073-0x0073 + * SHA256 1 0x0037-0x0037 0x0074-0x0074 + * SHA512 1 0x0039-0x0039 0x0075-0x0075 + * CHACHA20 3 0x0051-0x0055 + * POLY1305 3 0x0057-0x005B + * CHACHAPOLY 2 0x0054-0x0056 + * PLATFORM 2 0x0070-0x0072 + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 20 + * PKCS5 2 4 (Started from top) + * DHM 3 11 + * PK 3 15 (Started from top) + * RSA 4 11 + * ECP 4 10 (Started from top) + * MD 5 5 + * HKDF 5 1 (Started from top) + * SSL 5 2 (Started from 0x5F00) + * CIPHER 6 8 (Started from 0x6080) + * SSL 6 22 (Started from top, plus 0x6000) + * SSL 7 20 (Started from 0x7000, gaps at + * 0x7380, 0x7900-0x7980, 0x7A80-0x7E80) + * + * Module dependent error code (5 bits 0x.00.-0x.F8.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** Generic error */ +#define MBEDTLS_ERR_ERROR_GENERIC_ERROR -0x0001 +/** This is a bug in the library */ +#define MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED -0x006E + +/** Hardware accelerator failed */ +#define MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED -0x0070 +/** The requested feature is not supported by the platform */ +#define MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED -0x0072 + +/** + * \brief Combines a high-level and low-level error code together. + * + * Wrapper macro for mbedtls_error_add(). See that function for + * more details. + */ +#define MBEDTLS_ERROR_ADD( high, low ) \ + mbedtls_error_add( high, low, __FILE__, __LINE__ ) + +#if defined(MBEDTLS_TEST_HOOKS) +/** + * \brief Testing hook called before adding/combining two error codes together. + * Only used when invasive testing is enabled via MBEDTLS_TEST_HOOKS. + */ +extern void (*mbedtls_test_hook_error_add)( int, int, const char *, int ); +#endif + +/** + * \brief Combines a high-level and low-level error code together. + * + * This function can be called directly however it is usually + * called via the #MBEDTLS_ERROR_ADD macro. + * + * While a value of zero is not a negative error code, it is still an + * error code (that denotes success) and can be combined with both a + * negative error code or another value of zero. + * + * \note When invasive testing is enabled via #MBEDTLS_TEST_HOOKS, also try to + * call \link mbedtls_test_hook_error_add \endlink. + * + * \param high high-level error code. See error.h for more details. + * \param low low-level error code. See error.h for more details. + * \param file file where this error code addition occurred. + * \param line line where this error code addition occurred. + */ +static inline int mbedtls_error_add( int high, int low, + const char *file, int line ) +{ +#if defined(MBEDTLS_TEST_HOOKS) + if( *mbedtls_test_hook_error_add != NULL ) + ( *mbedtls_test_hook_error_add )( high, low, file, line ); +#endif + (void)file; + (void)line; + + return( high + low ); +} + +/** + * \brief Translate a mbed TLS error code into a string representation, + * Result is truncated if necessary and always includes a terminating + * null byte. + * + * \param errnum error code + * \param buffer buffer to place representation in + * \param buflen length of the buffer + */ +void mbedtls_strerror( int errnum, char *buffer, size_t buflen ); + +/** + * \brief Translate the high-level part of an Mbed TLS error code into a string + * representation. + * + * This function returns a const pointer to an un-modifiable string. The caller + * must not try to modify the string. It is intended to be used mostly for + * logging purposes. + * + * \param error_code error code + * + * \return The string representation of the error code, or \c NULL if the error + * code is unknown. + */ +const char * mbedtls_high_level_strerr( int error_code ); + +/** + * \brief Translate the low-level part of an Mbed TLS error code into a string + * representation. + * + * This function returns a const pointer to an un-modifiable string. The caller + * must not try to modify the string. It is intended to be used mostly for + * logging purposes. + * + * \param error_code error code + * + * \return The string representation of the error code, or \c NULL if the error + * code is unknown. + */ +const char * mbedtls_low_level_strerr( int error_code ); + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ + + +// LICENSE_CHANGE_END + + +#include + +#if defined(MBEDTLS_BIGNUM_C) + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/** + * \file platform.h + * + * \brief This file contains the definitions and functions of the + * Mbed TLS platform abstraction layer. + * + * The platform abstraction layer removes the need for the library + * to directly link to standard C library functions or operating + * system services, making the library easier to port and embed. + * Application developers and users of the library can provide their own + * implementations of these functions, or implementations specific to + * their platform, which can be statically linked to the library or + * dynamically configured at runtime. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_PLATFORM_H +#define MBEDTLS_PLATFORM_H + + + + +#if defined(MBEDTLS_HAVE_TIME) + +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name SECTION: Module settings + * + * The configuration options you can set for this module are in this section. + * Either change them in mbedtls_config.h or define them on the compiler command line. + * \{ + */ + +/* The older Microsoft Windows common runtime provides non-conforming + * implementations of some standard library functions, including snprintf + * and vsnprintf. This affects MSVC and MinGW builds. + */ +#if defined(__MINGW32__) || (defined(_MSC_VER) && _MSC_VER <= 1900) +#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF +#define MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF +#endif + +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#include +#include +#include +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#define MBEDTLS_PLATFORM_STD_VSNPRINTF mbedtls_platform_win32_vsnprintf /**< The default \c vsnprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_VSNPRINTF vsnprintf /**< The default \c vsnprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +#define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +#define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +#define MBEDTLS_PLATFORM_STD_TIME time /**< The default \c time function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The default exit value to use. */ +#endif +#if defined(MBEDTLS_FS_IO) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" +#endif +#endif /* MBEDTLS_FS_IO */ +#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) +#include MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + + +/* \} name SECTION: Module settings */ + +/* + * The function pointers for calloc and free. + */ +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ + defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO +#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO +#else +/* For size_t */ +#include +extern void *mbedtls_calloc( size_t n, size_t size ); +extern void mbedtls_free( void *ptr ); + +/** + * \brief This function dynamically sets the memory-management + * functions used by the library, during runtime. + * + * \param calloc_func The \c calloc function implementation. + * \param free_func The \c free function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ); +#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ +#else /* !MBEDTLS_PLATFORM_MEMORY */ +#define mbedtls_free free +#define mbedtls_calloc calloc +#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ + +/* + * The function pointers for fprintf + */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +/* We need FILE * */ +#include +extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); + +/** + * \brief This function dynamically configures the fprintf + * function that is called when the + * mbedtls_fprintf() function is invoked by the library. + * + * \param fprintf_func The \c fprintf function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, + ... ) ); +#else +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) +#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO +#else +#define mbedtls_fprintf fprintf +#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +/* + * The function pointers for printf + */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +extern int (*mbedtls_printf)( const char *format, ... ); + +/** + * \brief This function dynamically configures the snprintf + * function that is called when the mbedtls_snprintf() + * function is invoked by the library. + * + * \param printf_func The \c printf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); +#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) +#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO +#else +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +/* + * The function pointers for snprintf + * + * The snprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) +/* For Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); + +/** + * \brief This function allows configuring a custom + * \c snprintf function pointer. + * + * \param snprintf_func The \c snprintf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, ... ) ); +#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO +#else +#define mbedtls_snprintf MBEDTLS_PLATFORM_STD_SNPRINTF +#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +/* + * The function pointers for vsnprintf + * + * The vsnprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) +#include +/* For Older Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_vsnprintf( char *s, size_t n, const char *fmt, va_list arg ); +#endif + +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) +#include +extern int (*mbedtls_vsnprintf)( char * s, size_t n, const char * format, va_list arg ); + +/** + * \brief Set your own snprintf function pointer + * + * \param vsnprintf_func The \c vsnprintf function implementation + * + * \return \c 0 + */ +int mbedtls_platform_set_vsnprintf( int (*vsnprintf_func)( char * s, size_t n, + const char * format, va_list arg ) ); +#else /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_VSNPRINTF_MACRO) +#define mbedtls_vsnprintf MBEDTLS_PLATFORM_VSNPRINTF_MACRO +#else +#define mbedtls_vsnprintf vsnprintf +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ + +/* + * The function pointers for exit + */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +extern void (*mbedtls_exit)( int status ); + +/** + * \brief This function dynamically configures the exit + * function that is called when the mbedtls_exit() + * function is invoked by the library. + * + * \param exit_func The \c exit function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); +#else +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) +#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO +#else +#define mbedtls_exit exit +#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +/* + * The default exit values + */ +#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS +#else +#define MBEDTLS_EXIT_SUCCESS 0 +#endif +#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE +#else +#define MBEDTLS_EXIT_FAILURE 1 +#endif + +/* + * The function pointers for reading from and writing a seed file to + * Non-Volatile storage (NV) in a platform-independent way + * + * Only enabled when the NV seed entropy source is enabled + */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Internal standard platform definitions */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ); +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ); +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); +extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); + +/** + * \brief This function allows configuring custom seed file writing and + * reading functions. + * + * \param nv_seed_read_func The seed reading function implementation. + * \param nv_seed_write_func The seed writing function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) + ); +#else +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ + defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) +#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO +#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO +#else +#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read +#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write +#endif +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + +/** + * \brief The platform context structure. + * + * \note This structure may be used to assist platform-specific + * setup or teardown operations. + */ +typedef struct mbedtls_platform_context +{ + char MBEDTLS_PRIVATE(dummy); /**< A placeholder member, as empty structs are not portable. */ +} +mbedtls_platform_context; + +#else + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +// dummy file to make amalgamantion happy + +// LICENSE_CHANGE_END + +#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +/** + * \brief This function performs any platform-specific initialization + * operations. + * + * \note This function should be called before any other library functions. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + * \return \c 0 on success. + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ); +/** + * \brief This function performs any platform teardown operations. + * + * \note This function should be called after every other Mbed TLS module + * has been correctly freed using the appropriate free function. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ + + +// LICENSE_CHANGE_END + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* + * ASN.1 DER decoding routines + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( **p & 0x80 ) == 0 ) + *len = *(*p)++; + else + { + switch( **p & 0x7F ) + { + case 1: + if( ( end - *p ) < 2 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = (*p)[1]; + (*p) += 2; + break; + + case 2: + if( ( end - *p ) < 3 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2]; + (*p) += 3; + break; + + case 3: + if( ( end - *p ) < 4 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 16 ) | + ( (size_t)(*p)[2] << 8 ) | (*p)[3]; + (*p) += 4; + break; + + case 4: + if( ( end - *p ) < 5 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) | + ( (size_t)(*p)[3] << 8 ) | (*p)[4]; + (*p) += 5; + break; + + default: + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + } + } + + if( *len > (size_t) ( end - *p ) ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + return( 0 ); +} + +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != tag ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + + return( mbedtls_asn1_get_len( p, end, len ) ); +} + +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 ) + return( ret ); + + if( len != 1 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = ( **p != 0 ) ? 1 : 0; + (*p)++; + + return( 0 ); +} + +static int asn1_get_tagged_int( unsigned char **p, + const unsigned char *end, + int tag, int *val ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, tag ) ) != 0 ) + return( ret ); + + /* + * len==0 is malformed (0 must be represented as 020100 for INTEGER, + * or 0A0100 for ENUMERATED tags + */ + if( len == 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + /* This is a cryptography library. Reject negative integers. */ + if( ( **p & 0x80 ) != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Skip leading zeros. */ + while( len > 0 && **p == 0 ) + { + ++( *p ); + --len; + } + + /* Reject integers that don't fit in an int. This code assumes that + * the int type has no padding bit. */ + if( len > sizeof( int ) ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + if( len == sizeof( int ) && ( **p & 0x80 ) != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = 0; + while( len-- > 0 ) + { + *val = ( *val << 8 ) | **p; + (*p)++; + } + + return( 0 ); +} + +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ) +{ + return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_INTEGER, val) ); +} + +int mbedtls_asn1_get_enum( unsigned char **p, + const unsigned char *end, + int *val ) +{ + return( asn1_get_tagged_int( p, end, MBEDTLS_ASN1_ENUMERATED, val) ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + ret = mbedtls_mpi_read_binary( X, *p, len ); + + *p += len; + + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + /* Certificate type is a single byte bitstring */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + /* Check length, subtract one for actual bit string length */ + if( bs->len < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + bs->len -= 1; + + /* Get number of unused bits, ensure unused bits <= 7 */ + bs->unused_bits = **p; + if( bs->unused_bits > 7 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + (*p)++; + + /* Get actual bitstring */ + bs->p = *p; + *p += bs->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Traverse an ASN.1 "SEQUENCE OF " + * and call a callback for each entry found. + */ +int mbedtls_asn1_traverse_sequence_of( + unsigned char **p, + const unsigned char *end, + unsigned char tag_must_mask, unsigned char tag_must_val, + unsigned char tag_may_mask, unsigned char tag_may_val, + int (*cb)( void *ctx, int tag, + unsigned char *start, size_t len ), + void *ctx ) +{ + int ret; + size_t len; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( ret ); + } + + if( *p + len != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + unsigned char const tag = *(*p)++; + + if( ( tag & tag_must_mask ) != tag_must_val ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_len( p, end, &len ) ) != 0 ) + return( ret ); + + if( ( tag & tag_may_mask ) == tag_may_val ) + { + if( cb != NULL ) + { + ret = cb( ctx, tag, *p, len ); + if( ret != 0 ) + return( ret ); + } + } + + *p += len; + } + + return( 0 ); +} + +/* + * Get a bit string without unused bits + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + if( *len == 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + --( *len ); + + if( **p != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + ++( *p ); + + return( 0 ); +} + +void mbedtls_asn1_sequence_free( mbedtls_asn1_sequence *seq ) +{ + while( seq != NULL ) + { + mbedtls_asn1_sequence *next = seq->next; + mbedtls_platform_zeroize( seq, sizeof( *seq ) ); + mbedtls_free( seq ); + seq = next; + } +} + +typedef struct +{ + int tag; + mbedtls_asn1_sequence *cur; +} asn1_get_sequence_of_cb_ctx_t; + +static int asn1_get_sequence_of_cb( void *ctx, + int tag, + unsigned char *start, + size_t len ) +{ + asn1_get_sequence_of_cb_ctx_t *cb_ctx = + (asn1_get_sequence_of_cb_ctx_t *) ctx; + mbedtls_asn1_sequence *cur = + cb_ctx->cur; + + if( cur->buf.p != NULL ) + { + cur->next = + (struct mbedtls_asn1_sequence *) mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + + cur->buf.p = start; + cur->buf.len = len; + cur->buf.tag = tag; + + cb_ctx->cur = cur; + return( 0 ); +} + +/* + * Parses and splits an ASN.1 "SEQUENCE OF " + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag) +{ + asn1_get_sequence_of_cb_ctx_t cb_ctx = { tag, cur }; + memset( cur, 0, sizeof( mbedtls_asn1_sequence ) ); + return( mbedtls_asn1_traverse_sequence_of( + p, end, 0xFF, tag, 0, 0, + asn1_get_sequence_of_cb, &cb_ctx ) ); +} + +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + alg->tag = **p; + end = *p + len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + alg->p = *p; + *p += alg->len; + + if( *p == end ) + { + mbedtls_platform_zeroize( params, sizeof(mbedtls_asn1_buf) ); + return( 0 ); + } + + params->tag = **p; + (*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, ¶ms->len ) ) != 0 ) + return( ret ); + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_asn1_buf params; + + memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) + return( ret ); + + if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) +{ + if( cur == NULL ) + return; + + mbedtls_free( cur->oid.p ); + mbedtls_free( cur->val.p ); + + mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); +} + +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) +{ + mbedtls_asn1_named_data *cur; + + while( ( cur = *head ) != NULL ) + { + *head = cur->next; + mbedtls_asn1_free_named_data( cur ); + mbedtls_free( cur ); + } +} + +const mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( const mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ + + +// LICENSE_CHANGE_END + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/* + * RFC 1521 base64 encoding/decoding + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + + +#if defined(MBEDTLS_BASE64_C) + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/** + * \file base64.h + * + * \brief RFC 1521 base64 encoding/decoding + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_BASE64_H +#define MBEDTLS_BASE64_H + + + +#include + +/** Output buffer too small. */ +#define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL -0x002A +/** Invalid character in input. */ +#define MBEDTLS_ERR_BASE64_INVALID_CHARACTER -0x002C + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Encode a buffer into base64 format + * + * \param dst destination buffer + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be encoded + * + * \return 0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * If that length cannot be represented, then no data is + * written to the buffer and *olen is set to the maximum + * length representable as a size_t. + * + * \note Call this function with dlen = 0 to obtain the + * required buffer size in *olen + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +/** + * \brief Decode a base64-formatted buffer + * + * \param dst destination buffer (can be NULL for checking size) + * \param dlen size of the destination buffer + * \param olen number of bytes written + * \param src source buffer + * \param slen amount of data to be decoded + * + * \return 0 if successful, MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL, or + * MBEDTLS_ERR_BASE64_INVALID_CHARACTER if the input data is + * not correct. *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with *dst = NULL or dlen = 0 to obtain + * the required buffer size in *olen + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_base64_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* base64.h */ + + +// LICENSE_CHANGE_END + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/** + * Constant-time functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_CONSTANT_TIME_INTERNAL_H +#define MBEDTLS_CONSTANT_TIME_INTERNAL_H + + + +#if defined(MBEDTLS_BIGNUM_C) + +#endif + +#if defined(MBEDTLS_SSL_TLS_C) + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +// dummy file to make amalgamantion happy + +// LICENSE_CHANGE_END + +#endif + +#include + + +/** Turn a value into a mask: + * - if \p value == 0, return the all-bits 0 mask, aka 0 + * - otherwise, return the all-bits 1 mask, aka (unsigned) -1 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param value The value to analyze. + * + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +unsigned mbedtls_ct_uint_mask( unsigned value ); + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +/** Turn a value into a mask: + * - if \p value == 0, return the all-bits 0 mask, aka 0 + * - otherwise, return the all-bits 1 mask, aka (size_t) -1 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param value The value to analyze. + * + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +size_t mbedtls_ct_size_mask( size_t value ); + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#if defined(MBEDTLS_BIGNUM_C) + +/** Turn a value into a mask: + * - if \p value == 0, return the all-bits 0 mask, aka 0 + * - otherwise, return the all-bits 1 mask, aka (mbedtls_mpi_uint) -1 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param value The value to analyze. + * + * \return Zero if \p value is zero, otherwise all-bits-one. + */ +mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask( mbedtls_mpi_uint value ); + +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +/** Constant-flow mask generation for "greater or equal" comparison: + * - if \p x >= \p y, return all-bits 1, that is (size_t) -1 + * - otherwise, return all bits 0, that is 0 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return All-bits-one if \p x is greater or equal than \p y, + * otherwise zero. + */ +size_t mbedtls_ct_size_mask_ge( size_t x, + size_t y ); + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +/** Constant-flow boolean "equal" comparison: + * return x == y + * + * This is equivalent to \p x == \p y, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return 1 if \p x equals to \p y, otherwise 0. + */ +unsigned mbedtls_ct_size_bool_eq( size_t x, + size_t y ); + +#if defined(MBEDTLS_BIGNUM_C) + +/** Decide if an integer is less than the other, without branches. + * + * This is equivalent to \p x < \p y, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return 1 if \p x is less than \p y, otherwise 0. + */ +unsigned mbedtls_ct_mpi_uint_lt( const mbedtls_mpi_uint x, + const mbedtls_mpi_uint y ); + +#endif /* MBEDTLS_BIGNUM_C */ + +/** Choose between two integer values without branches. + * + * This is equivalent to `condition ? if1 : if0`, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition is nonzero. + * \param if0 Value to use if \p condition is zero. + * + * \return \c if1 if \p condition is nonzero, otherwise \c if0. + */ +unsigned mbedtls_ct_uint_if( unsigned condition, + unsigned if1, + unsigned if0 ); + +#if defined(MBEDTLS_BIGNUM_C) + +/** Conditionally assign a value without branches. + * + * This is equivalent to `if ( condition ) dest = src`, but is likely + * to be compiled to code using bitwise operation rather than a branch. + * + * \param n \p dest and \p src must be arrays of limbs of size n. + * \param dest The MPI to conditionally assign to. This must point + * to an initialized MPI. + * \param src The MPI to be assigned from. This must point to an + * initialized MPI. + * \param condition Condition to test, must be 0 or 1. + */ +void mbedtls_ct_mpi_uint_cond_assign( size_t n, + mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *src, + unsigned char condition ); + +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_BASE64_C) + +/** Given a value in the range 0..63, return the corresponding Base64 digit. + * + * The implementation assumes that letters are consecutive (e.g. ASCII + * but not EBCDIC). + * + * \param value A value in the range 0..63. + * + * \return A base64 digit converted from \p value. + */ +unsigned char mbedtls_ct_base64_enc_char( unsigned char value ); + +/** Given a Base64 digit, return its value. + * + * If c is not a Base64 digit ('A'..'Z', 'a'..'z', '0'..'9', '+' or '/'), + * return -1. + * + * The implementation assumes that letters are consecutive (e.g. ASCII + * but not EBCDIC). + * + * \param c A base64 digit. + * + * \return The value of the base64 digit \p c. + */ +signed char mbedtls_ct_base64_dec_value( unsigned char c ); + +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) + +/** Conditional memcpy without branches. + * + * This is equivalent to `if ( c1 == c2 ) memcpy(dest, src, len)`, but is likely + * to be compiled to code using bitwise operation rather than a branch. + * + * \param dest The pointer to conditionally copy to. + * \param src The pointer to copy from. Shouldn't overlap with \p dest. + * \param len The number of bytes to copy. + * \param c1 The first value to analyze in the condition. + * \param c2 The second value to analyze in the condition. + */ +void mbedtls_ct_memcpy_if_eq( unsigned char *dest, + const unsigned char *src, + size_t len, + size_t c1, size_t c2 ); + +/** Copy data from a secret position with constant flow. + * + * This function copies \p len bytes from \p src_base + \p offset_secret to \p + * dst, with a code flow and memory access pattern that does not depend on \p + * offset_secret, but only on \p offset_min, \p offset_max and \p len. + * Functionally equivalent to `memcpy(dst, src + offset_secret, len)`. + * + * \param dest The destination buffer. This must point to a writable + * buffer of at least \p len bytes. + * \param src The base of the source buffer. This must point to a + * readable buffer of at least \p offset_max + \p len + * bytes. Shouldn't overlap with \p dest. + * \param offset The offset in the source buffer from which to copy. + * This must be no less than \p offset_min and no greater + * than \p offset_max. + * \param offset_min The minimal value of \p offset. + * \param offset_max The maximal value of \p offset. + * \param len The number of bytes to copy. + */ +void mbedtls_ct_memcpy_offset( unsigned char *dest, + const unsigned char *src, + size_t offset, + size_t offset_min, + size_t offset_max, + size_t len ); + +/** Compute the HMAC of variable-length data with constant flow. + * + * This function computes the HMAC of the concatenation of \p add_data and \p + * data, and does with a code flow and memory access pattern that does not + * depend on \p data_len_secret, but only on \p min_data_len and \p + * max_data_len. In particular, this function always reads exactly \p + * max_data_len bytes from \p data. + * + * \param ctx The HMAC context. It must have keys configured + * with mbedtls_md_hmac_starts() and use one of the + * following hashes: SHA-384, SHA-256, SHA-1 or MD-5. + * It is reset using mbedtls_md_hmac_reset() after + * the computation is complete to prepare for the + * next computation. + * \param add_data The first part of the message whose HMAC is being + * calculated. This must point to a readable buffer + * of \p add_data_len bytes. + * \param add_data_len The length of \p add_data in bytes. + * \param data The buffer containing the second part of the + * message. This must point to a readable buffer + * of \p max_data_len bytes. + * \param data_len_secret The length of the data to process in \p data. + * This must be no less than \p min_data_len and no + * greater than \p max_data_len. + * \param min_data_len The minimal length of the second part of the + * message, read from \p data. + * \param max_data_len The maximal length of the second part of the + * message, read from \p data. + * \param output The HMAC will be written here. This must point to + * a writable buffer of sufficient size to hold the + * HMAC value. + * + * \retval 0 on success. + * \retval #MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED + * The hardware accelerator failed. + */ +int mbedtls_ct_hmac( mbedtls_md_context_t *ctx, + const unsigned char *add_data, + size_t add_data_len, + const unsigned char *data, + size_t data_len_secret, + size_t min_data_len, + size_t max_data_len, + unsigned char *output ); + +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ + +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) + +/** This function performs the unpadding part of a PKCS#1 v1.5 decryption + * operation (EME-PKCS1-v1_5 decoding). + * + * \note The return value from this function is a sensitive value + * (this is unusual). #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE shouldn't happen + * in a well-written application, but 0 vs #MBEDTLS_ERR_RSA_INVALID_PADDING + * is often a situation that an attacker can provoke and leaking which + * one is the result is precisely the information the attacker wants. + * + * \param input The input buffer which is the payload inside PKCS#1v1.5 + * encryption padding, called the "encoded message EM" + * by the terminology. + * \param ilen The length of the payload in the \p input buffer. + * \param output The buffer for the payload, called "message M" by the + * PKCS#1 terminology. This must be a writable buffer of + * length \p output_max_len bytes. + * \param olen The address at which to store the length of + * the payload. This must not be \c NULL. + * \param output_max_len The length in bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE + * The output buffer is too small for the unpadded payload. + * \return #MBEDTLS_ERR_RSA_INVALID_PADDING + * The input doesn't contain properly formatted padding. + */ +int mbedtls_ct_rsaes_pkcs1_v15_unpadding( unsigned char *input, + size_t ilen, + unsigned char *output, + size_t output_max_len, + size_t *olen ); + +#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ + +#endif /* MBEDTLS_CONSTANT_TIME_INTERNAL_H */ + + +// LICENSE_CHANGE_END + + +#include + +#if defined(MBEDTLS_SELF_TEST) +#include +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#define BASE64_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Encode a buffer into base64 format + */ +int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i, n; + int C1, C2, C3; + unsigned char *p; + + if( slen == 0 ) + { + *olen = 0; + return( 0 ); + } + + n = slen / 3 + ( slen % 3 != 0 ); + + if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 ) + { + *olen = BASE64_SIZE_T_MAX; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n *= 4; + + if( ( dlen < n + 1 ) || ( NULL == dst ) ) + { + *olen = n + 1; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + n = ( slen / 3 ) * 3; + + for( i = 0, p = dst; i < n; i += 3 ) + { + C1 = *src++; + C2 = *src++; + C3 = *src++; + + *p++ = mbedtls_ct_base64_enc_char( ( C1 >> 2 ) & 0x3F ); + *p++ = mbedtls_ct_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) + & 0x3F ); + *p++ = mbedtls_ct_base64_enc_char( ( ( ( C2 & 15 ) << 2 ) + ( C3 >> 6 ) ) + & 0x3F ); + *p++ = mbedtls_ct_base64_enc_char( C3 & 0x3F ); + } + + if( i < slen ) + { + C1 = *src++; + C2 = ( ( i + 1 ) < slen ) ? *src++ : 0; + + *p++ = mbedtls_ct_base64_enc_char( ( C1 >> 2 ) & 0x3F ); + *p++ = mbedtls_ct_base64_enc_char( ( ( ( C1 & 3 ) << 4 ) + ( C2 >> 4 ) ) + & 0x3F ); + + if( ( i + 1 ) < slen ) + *p++ = mbedtls_ct_base64_enc_char( ( ( C2 & 15 ) << 2 ) & 0x3F ); + else *p++ = '='; + + *p++ = '='; + } + + *olen = p - dst; + *p = 0; + + return( 0 ); +} + +/* + * Decode a base64-formatted buffer + */ +int mbedtls_base64_decode( unsigned char *dst, size_t dlen, size_t *olen, + const unsigned char *src, size_t slen ) +{ + size_t i; /* index in source */ + size_t n; /* number of digits or trailing = in source */ + uint32_t x; /* value accumulator */ + unsigned accumulated_digits = 0; + unsigned equals = 0; + int spaces_present = 0; + unsigned char *p; + + /* First pass: check for validity and get output length */ + for( i = n = 0; i < slen; i++ ) + { + /* Skip spaces before checking for EOL */ + spaces_present = 0; + while( i < slen && src[i] == ' ' ) + { + ++i; + spaces_present = 1; + } + + /* Spaces at end of buffer are OK */ + if( i == slen ) + break; + + if( ( slen - i ) >= 2 && + src[i] == '\r' && src[i + 1] == '\n' ) + continue; + + if( src[i] == '\n' ) + continue; + + /* Space inside a line is an error */ + if( spaces_present ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] > 127 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + + if( src[i] == '=' ) + { + if( ++equals > 2 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + } + else + { + if( equals != 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + if( mbedtls_ct_base64_dec_value( src[i] ) < 0 ) + return( MBEDTLS_ERR_BASE64_INVALID_CHARACTER ); + } + n++; + } + + if( n == 0 ) + { + *olen = 0; + return( 0 ); + } + + /* The following expression is to calculate the following formula without + * risk of integer overflow in n: + * n = ( ( n * 6 ) + 7 ) >> 3; + */ + n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 ); + n -= equals; + + if( dst == NULL || dlen < n ) + { + *olen = n; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + equals = 0; + for( x = 0, p = dst; i > 0; i--, src++ ) + { + if( *src == '\r' || *src == '\n' || *src == ' ' ) + continue; + + x = x << 6; + if( *src == '=' ) + ++equals; + else + x |= mbedtls_ct_base64_dec_value( *src ); + + if( ++accumulated_digits == 4 ) + { + accumulated_digits = 0; + *p++ = MBEDTLS_BYTE_2( x ); + if( equals <= 1 ) *p++ = MBEDTLS_BYTE_1( x ); + if( equals <= 0 ) *p++ = MBEDTLS_BYTE_0( x ); + } + } + + *olen = p - dst; + + return( 0 ); +} + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char base64_test_dec[64] = +{ + 0x24, 0x48, 0x6E, 0x56, 0x87, 0x62, 0x5A, 0xBD, + 0xBF, 0x17, 0xD9, 0xA2, 0xC4, 0x17, 0x1A, 0x01, + 0x94, 0xED, 0x8F, 0x1E, 0x11, 0xB3, 0xD7, 0x09, + 0x0C, 0xB6, 0xE9, 0x10, 0x6F, 0x22, 0xEE, 0x13, + 0xCA, 0xB3, 0x07, 0x05, 0x76, 0xC9, 0xFA, 0x31, + 0x6C, 0x08, 0x34, 0xFF, 0x8D, 0xC2, 0x6C, 0x38, + 0x00, 0x43, 0xE9, 0x54, 0x97, 0xAF, 0x50, 0x4B, + 0xD1, 0x41, 0xBA, 0x95, 0x31, 0x5A, 0x0B, 0x97 +}; + +static const unsigned char base64_test_enc[] = + "JEhuVodiWr2/F9mixBcaAZTtjx4Rs9cJDLbpEG8i7hPK" + "swcFdsn6MWwINP+Nwmw4AEPpVJevUEvRQbqVMVoLlw=="; + +/* + * Checkup routine + */ +int mbedtls_base64_self_test( int verbose ) +{ + size_t len; + const unsigned char *src; + unsigned char buffer[128]; + + if( verbose != 0 ) + mbedtls_printf( " Base64 encoding test: " ); + + src = base64_test_dec; + + if( mbedtls_base64_encode( buffer, sizeof( buffer ), &len, src, 64 ) != 0 || + memcmp( base64_test_enc, buffer, 88 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n Base64 decoding test: " ); + + src = base64_test_enc; + + if( mbedtls_base64_decode( buffer, sizeof( buffer ), &len, src, 88 ) != 0 || + memcmp( base64_test_dec, buffer, 64 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BASE64_C */ + + +// LICENSE_CHANGE_END + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/* + * Multi-precision integer library + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * The following sources were referenced in the design of this Multi-precision + * Integer library: + * + * [1] Handbook of Applied Cryptography - 1997 + * Menezes, van Oorschot and Vanstone + * + * [2] Multi-Precision Math + * Tom St Denis + * https://github.com/libtom/libtommath/blob/develop/tommath.pdf + * + * [3] GNU Multi-Precision Arithmetic Library + * https://gmplib.org/manual/index.html + * + */ + + + +#if defined(MBEDTLS_BIGNUM_C) + + + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef MBEDTLS_BN_MUL_H +#define MBEDTLS_BN_MUL_H + + + + + + +/* + * Conversion macros for embedded constants: + * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 + */ +#if defined(MBEDTLS_HAVE_INT32) + +#define MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d ) \ + ( (mbedtls_mpi_uint) (a) << 0 ) | \ + ( (mbedtls_mpi_uint) (b) << 8 ) | \ + ( (mbedtls_mpi_uint) (c) << 16 ) | \ + ( (mbedtls_mpi_uint) (d) << 24 ) + +#define MBEDTLS_BYTES_TO_T_UINT_2( a, b ) \ + MBEDTLS_BYTES_TO_T_UINT_4( a, b, 0, 0 ) -#define YYFAIL goto yyerrlab +#define MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d ), \ + MBEDTLS_BYTES_TO_T_UINT_4( e, f, g, h ) -#define YYRECOVERING() (!!yyerrstatus) +#else /* 64-bits */ -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ - YYPOPSTACK (1); \ - goto yybackup; \ - } \ - else \ - { \ - yyerror (&yylloc, yyscanner, YY_("syntax error: cannot back up")); \ - YYERROR; \ - } \ -while (YYID (0)) +#define MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + ( (mbedtls_mpi_uint) (a) << 0 ) | \ + ( (mbedtls_mpi_uint) (b) << 8 ) | \ + ( (mbedtls_mpi_uint) (c) << 16 ) | \ + ( (mbedtls_mpi_uint) (d) << 24 ) | \ + ( (mbedtls_mpi_uint) (e) << 32 ) | \ + ( (mbedtls_mpi_uint) (f) << 40 ) | \ + ( (mbedtls_mpi_uint) (g) << 48 ) | \ + ( (mbedtls_mpi_uint) (h) << 56 ) +#define MBEDTLS_BYTES_TO_T_UINT_4( a, b, c, d ) \ + MBEDTLS_BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 ) -#define YYTERROR 1 -#define YYERRCODE 256 +#define MBEDTLS_BYTES_TO_T_UINT_2( a, b ) \ + MBEDTLS_BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 ) +#endif /* bits in mbedtls_mpi_uint */ -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ +#if defined(MBEDTLS_HAVE_ASM) -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (YYID (N)) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (YYID (0)) +#ifndef asm +#define asm __asm #endif +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ +/* + * Disable use of the i386 assembly code below if option -O0, to disable all + * compiler optimisations, is passed, detected with __OPTIMIZE__ + * This is done as the number of registers used in the assembly code doesn't + * work with the -O0 option. + */ +#if defined(__i386__) && defined(__OPTIMIZE__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(MBEDTLS_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); -#ifndef YY_LOCATION_PRINT -# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "xorq %%r8, %%r8\n" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax\n" \ + "mulq %%rbx\n" \ + "addq $8, %%rsi\n" \ + "addq %%rcx, %%rax\n" \ + "movq %%r8, %%rcx\n" \ + "adcq $0, %%rdx\n" \ + "nop \n" \ + "addq %%rax, (%%rdi)\n" \ + "adcq %%rdx, %%rcx\n" \ + "addq $8, %%rdi\n" + +#define MULADDC_STOP \ + : "+c" (c), "+D" (d), "+S" (s), "+m" (*(uint64_t (*)[16]) d) \ + : "b" (b), "m" (*(const uint64_t (*)[16]) s) \ + : "rax", "rdx", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__aarch64__) + +#define MULADDC_INIT \ + asm( + +#define MULADDC_CORE \ + "ldr x4, [%2], #8 \n\t" \ + "ldr x5, [%1] \n\t" \ + "mul x6, x4, %4 \n\t" \ + "umulh x7, x4, %4 \n\t" \ + "adds x5, x5, x6 \n\t" \ + "adc x7, x7, xzr \n\t" \ + "adds x5, x5, %0 \n\t" \ + "adc %0, x7, xzr \n\t" \ + "str x5, [%1], #8 \n\t" + +#define MULADDC_STOP \ + : "+r" (c), "+r" (d), "+r" (s), "+m" (*(uint64_t (*)[16]) d) \ + : "r" (b), "m" (*(const uint64_t (*)[16]) s) \ + : "x4", "x5", "x6", "x7", "cc" \ + ); + +#endif /* Aarch64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc(64) assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) +#if defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#else /* __sparc64__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* __sparc64__ */ +#endif /* __sparc__ */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +/* + * Note, gcc -O0 by default uses r7 for the frame pointer, so it complains about + * our use of r7 below, unless -fomit-frame-pointer is passed. + * + * On the other hand, -fomit-frame-pointer is implied by any -Ox options with + * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by + * clang and armcc5 under the same conditions). + * + * So, only use the optimized assembly below for optimized build, which avoids + * the build error and is pretty reasonable anyway. + */ +#if defined(__GNUC__) && !defined(__OPTIMIZE__) +#define MULADDC_CANNOT_USE_R7 #endif +#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#elif (__ARM_ARCH >= 6) && \ + defined (__ARM_FEATURE_DSP) && (__ARM_FEATURE_DSP == 1) + +#define MULADDC_INIT \ + asm( + +#define MULADDC_CORE \ + "ldr r0, [%0], #4 \n\t" \ + "ldr r1, [%1] \n\t" \ + "umaal r1, %2, %3, r0 \n\t" \ + "str r1, [%1], #4 \n\t" + +#define MULADDC_STOP \ + : "=r" (s), "=r" (d), "=r" (c) \ + : "r" (b), "0" (s), "1" (d), "2" (c) \ + : "r0", "r1", "memory" \ + ); -/* YYLEX -- calling `yylex' with the right arguments. */ +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15", "lo", "hi" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(MBEDTLS_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ -#ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) #else -# define YYLEX yylex (&yylval, &yylloc, yyscanner) -#endif -/* Enable debugging if requested. */ -#if YYDEBUG +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif +#endif /* SSE2 */ +#endif /* MSVC */ -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (YYID (0)) +#endif /* MBEDTLS_HAVE_ASM */ -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yy_symbol_print (stderr, \ - Type, Value, Location, yyscanner); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (YYID (0)) +#if !defined(MULADDC_CORE) +#if defined(MBEDTLS_HAVE_UDBL) +#define MULADDC_INIT \ +{ \ + mbedtls_t_udbl r; \ + mbedtls_mpi_uint r0, r1; -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +#define MULADDC_CORE \ + r = *(s++) * (mbedtls_t_udbl) b; \ + r0 = (mbedtls_mpi_uint) r; \ + r1 = (mbedtls_mpi_uint)( r >> biL ); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, core_yyscan_t yyscanner) #else -static void -yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, yyscanner) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; - YYLTYPE const * const yylocationp; - core_yyscan_t yyscanner; +#define MULADDC_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ + + +// LICENSE_CHANGE_END + + + + + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free #endif + +#define MPI_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) +#define MPI_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows + */ +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) { - if (!yyvaluep) - return; - YYUSE (yylocationp); - YYUSE (yyscanner); -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# else - YYUSE (yyoutput); -# endif - switch (yytype) + mbedtls_platform_zeroize( v, ciL * n ); +} + +/* + * Initialize one MPI + */ +void mbedtls_mpi_init( mbedtls_mpi *X ) +{ + MPI_VALIDATE( X != NULL ); + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mbedtls_mpi_free( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) { - default: - break; + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); } + + X->s = 1; + X->n = 0; + X->p = NULL; } +/* + * Enlarge to the specified number of limbs + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + MPI_VALIDATE_RET( X != NULL ); -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp, core_yyscan_t yyscanner) -#else -static void -yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp, yyscanner) - FILE *yyoutput; - int yytype; - YYSTYPE const * const yyvaluep; - YYLTYPE const * const yylocationp; - core_yyscan_t yyscanner; -#endif + if( X->n < nblimbs ) + { + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) { - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + mbedtls_mpi_uint *p; + size_t i; + MPI_VALIDATE_RET( X != NULL ); - YY_LOCATION_PRINT (yyoutput, *yylocationp); - YYFPRINTF (yyoutput, ": "); - yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp, yyscanner); - YYFPRINTF (yyoutput, ")"); + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + /* Actually resize up if there are currently fewer than nblimbs limbs. */ + if( X->n <= nblimbs ) + return( mbedtls_mpi_grow( X, nblimbs ) ); + /* After this point, then X->n > nblimbs and in particular X->n > 0. */ + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + i++; + + if( i < nblimbs ) + i = nblimbs; + + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); } -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ +/* Resize X to have exactly n limbs and set it to 0. */ +static int mbedtls_mpi_resize_clear( mbedtls_mpi *X, size_t limbs ) +{ + if( limbs == 0 ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + else if( X->n == limbs ) + { + memset( X->p, 0, limbs * ciL ); + X->s = 1; + return( 0 ); + } + else + { + mbedtls_mpi_free( X ); + return( mbedtls_mpi_grow( X, limbs ) ); + } +} -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_stack_print (yytype_int16 *bottom, yytype_int16 *top) -#else -static void -yy_stack_print (bottom, top) - yytype_int16 *bottom; - yytype_int16 *top; -#endif +/* + * Copy the contents of Y into X. + * + * This function is not constant-time. Leading zeros in Y may be removed. + * + * Ensure that X does not shrink. This is not guaranteed by the public API, + * but some code in the bignum module relies on this property, for example + * in mbedtls_mpi_exp_mod(). + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) { - YYFPRINTF (stderr, "Stack now"); - for (; bottom <= top; ++bottom) - YYFPRINTF (stderr, " %d", *bottom); - YYFPRINTF (stderr, "\n"); + int ret = 0; + size_t i; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + if( X == Y ) + return( 0 ); + + if( Y->n == 0 ) + { + if( X->n != 0 ) + { + X->s = 1; + memset( X->p, 0, X->n * ciL ); + } + return( 0 ); + } + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + if( X->n < i ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + } + else + { + memset( X->p + i, 0, ( X->n - i ) * ciL ); + } + + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); } -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (YYID (0)) +/* + * Swap the contents of X and Y + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) +{ + mbedtls_mpi T; + MPI_VALIDATE( X != NULL ); + MPI_VALIDATE( Y != NULL ); + memcpy( &T, X, sizeof( mbedtls_mpi ) ); + memcpy( X, Y, sizeof( mbedtls_mpi ) ); + memcpy( Y, &T, sizeof( mbedtls_mpi ) ); +} -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ +/* + * Set value from integer + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MPI_VALIDATE_RET( X != NULL ); -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule, core_yyscan_t yyscanner) -#else -static void -yy_reduce_print (yyvsp, yylsp, yyrule, yyscanner) - YYSTYPE *yyvsp; - YYLTYPE *yylsp; - int yyrule; - core_yyscan_t yyscanner; -#endif + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) { - int yynrhs = yyr2[yyrule]; - int yyi; - unsigned long int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", - yyrule - 1, yylno); - /* The symbols being reduced. */ - for (yyi = 0; yyi < yynrhs; yyi++) + MPI_VALIDATE_RET( X != NULL ); + + if( X->n * biL <= pos ) + return( 0 ); + + return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); +} + +/* Get a specific byte, without range checks. */ +#define GET_BYTE( X, i ) \ + ( ( ( X )->p[( i ) / ciL] >> ( ( ( i ) % ciL ) * 8 ) ) & 0xff ) + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + MPI_VALIDATE_RET( X != NULL ); + + if( val != 0 && val != 1 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( X->n * biL <= pos ) { - fprintf (stderr, " $%d = ", yyi + 1); - yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], - &(yyvsp[(yyi + 1) - (yynrhs)]) - , &(yylsp[(yyi + 1) - (yynrhs)]) , yyscanner); - fprintf (stderr, "\n"); + if( val == 0 ) + return( 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); } + + X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); + X->p[off] |= (mbedtls_mpi_uint) val << idx; + +cleanup: + + return( ret ); } -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (yyvsp, yylsp, Rule, yyscanner); \ -} while (YYID (0)) +/* + * Return the number of less significant zero-bits + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) +{ + size_t i, j, count = 0; + MBEDTLS_INTERNAL_VALIDATE_RET( X != NULL, 0 ); -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ + for( i = 0; i < X->n; i++ ) + for( j = 0; j < biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + return( 0 ); +} -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif +/* + * Count leading zero bits in a given integer + */ +static size_t mbedtls_clz( const mbedtls_mpi_uint x ) +{ + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). + for( j = 0; j < biL; j++ ) + { + if( x & mask ) break; - Do not make this value too large; the results are undefined if - YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ + mask >>= 1; + } -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif + return j; +} - +/* + * Return the number of bits + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) +{ + size_t i, j; -#if YYERROR_VERBOSE + if( X->n == 0 ) + return( 0 ); -# ifndef yystrlen -# if defined __GLIBC__ && defined _STRING_H -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static YYSIZE_T -yystrlen (const char *yystr) -#else -static YYSIZE_T -yystrlen (yystr) - const char *yystr; + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + j = biL - mbedtls_clz( X->p[i] ); + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ) +{ + return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (mbedtls_mpi_uint) radix ) + return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j, slen, n; + int sign = 1; + mbedtls_mpi_uint d; + mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( s != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + + if( s[0] == 0 ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + + if( s[0] == '-' ) + { + ++s; + sign = -1; + } + + slen = strlen( s ); + + if( radix == 16 ) + { + if( slen > MPI_SIZE_T_MAX >> 2 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = BITS_TO_LIMBS( slen << 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); + } + } + + if( sign < 0 && mbedtls_mpi_bitlen( X ) != 0 ) + X->s = -1; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first. + */ +static int mpi_write_hlp( mbedtls_mpi *X, int radix, + char **p, const size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi_uint r; + size_t length = 0; + char *p_end = *p + buflen; + + do + { + if( length >= buflen ) + { + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + /* + * Write the residue in the current position, as an ASCII character. + */ + if( r < 0xA ) + *(--p_end) = (char)( '0' + r ); + else + *(--p_end) = (char)( 'A' + ( r - 0xA ) ); + + length++; + } while( mbedtls_mpi_cmp_int( X, 0 ) != 0 ); + + memmove( *p, p_end, length ); + *p += length; + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ) +{ + int ret = 0; + size_t n; + char *p; + mbedtls_mpi T; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( olen != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = mbedtls_mpi_bitlen( X ); /* Number of bits necessary to present `n`. */ + if( radix >= 4 ) n >>= 1; /* Number of 4-adic digits necessary to present + * `n`. If radix > 4, this might be a strict + * overapproximation of the number of + * radix-adic digits needed to present `n`. */ + if( radix >= 16 ) n >>= 1; /* Number of hexadecimal digits necessary to + * present `n`. */ + + n += 1; /* Terminating null byte */ + n += 1; /* Compensate for the divisions above, which round down `n` + * in case it's not even. */ + n += 1; /* Potential '-'-sign. */ + n += ( n & 1 ); /* Make n even to have enough space for hexadecimal writing, + * which always uses an even number of hex-digits. */ + + if( buflen < n ) + { + *olen = n; + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = buf; + mbedtls_mpi_init( &T ); + + if( X->s == -1 ) + { + *p++ = '-'; + buflen--; + } + + if( radix == 16 ) + { + int c; + size_t i, j, k; + + for( i = X->n, k = 0; i > 0; i-- ) + { + for( j = ciL; j > 0; j-- ) + { + c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; + + if( c == 0 && k == 0 && ( i + j ) != 2 ) + continue; + + *(p++) = "0123456789ABCDEF" [c / 16]; + *(p++) = "0123456789ABCDEF" [c % 16]; + k = 1; + } + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); + + if( T.s == -1 ) + T.s = 1; + + MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p, buflen ) ); + } + + *p++ = '\0'; + *olen = p - buf; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Read X from an opened file + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) +{ + mbedtls_mpi_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( fin != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( slen == sizeof( s ) - 2 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while( p-- > s ) + if( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n, slen, plen; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + MPI_VALIDATE_RET( X != NULL ); + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( s, 0, sizeof( s ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); + + if( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if( fout != NULL ) + { + if( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + } + else + mbedtls_printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + + +/* Convert a big-endian byte array aligned to the size of mbedtls_mpi_uint + * into the storage form used by mbedtls_mpi. */ + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host_c( mbedtls_mpi_uint x ) +{ + uint8_t i; + unsigned char *x_ptr; + mbedtls_mpi_uint tmp = 0; + + for( i = 0, x_ptr = (unsigned char*) &x; i < ciL; i++, x_ptr++ ) + { + tmp <<= CHAR_BIT; + tmp |= (mbedtls_mpi_uint) *x_ptr; + } + + return( tmp ); +} + +static mbedtls_mpi_uint mpi_uint_bigendian_to_host( mbedtls_mpi_uint x ) +{ +#if defined(__BYTE_ORDER__) + +/* Nothing to do on bigendian systems. */ +#if ( __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ) + return( x ); +#endif /* __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ */ + +#if ( __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ) + +/* For GCC and Clang, have builtins for byte swapping. */ +#if defined(__GNUC__) && defined(__GNUC_PREREQ) +#if __GNUC_PREREQ(4,3) +#define have_bswap +#endif +#endif + +#if defined(__clang__) && defined(__has_builtin) +#if __has_builtin(__builtin_bswap32) && \ + __has_builtin(__builtin_bswap64) +#define have_bswap +#endif +#endif + +#if defined(have_bswap) + /* The compiler is hopefully able to statically evaluate this! */ + switch( sizeof(mbedtls_mpi_uint) ) + { + case 4: + return( __builtin_bswap32(x) ); + case 8: + return( __builtin_bswap64(x) ); + } #endif +#endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */ +#endif /* __BYTE_ORDER__ */ + + /* Fall back to C-based reordering if we don't know the byte order + * or we couldn't use a compiler-specific builtin. */ + return( mpi_uint_bigendian_to_host_c( x ) ); +} + +static void mpi_bigendian_to_host( mbedtls_mpi_uint * const p, size_t limbs ) { - YYSIZE_T yylen; - for (yylen = 0; yystr[yylen]; yylen++) - continue; - return yylen; + mbedtls_mpi_uint *cur_limb_left; + mbedtls_mpi_uint *cur_limb_right; + if( limbs == 0 ) + return; + + /* + * Traverse limbs and + * - adapt byte-order in each limb + * - swap the limbs themselves. + * For that, simultaneously traverse the limbs from left to right + * and from right to left, as long as the left index is not bigger + * than the right index (it's not a problem if limbs is odd and the + * indices coincide in the last iteration). + */ + for( cur_limb_left = p, cur_limb_right = p + ( limbs - 1 ); + cur_limb_left <= cur_limb_right; + cur_limb_left++, cur_limb_right-- ) + { + mbedtls_mpi_uint tmp; + /* Note that if cur_limb_left == cur_limb_right, + * this code effectively swaps the bytes only once. */ + tmp = mpi_uint_bigendian_to_host( *cur_limb_left ); + *cur_limb_left = mpi_uint_bigendian_to_host( *cur_limb_right ); + *cur_limb_right = tmp; + } } -# endif -# endif -# ifndef yystpcpy -# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static char * -yystpcpy (char *yydest, const char *yysrc) -#else -static char * -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; +/* + * Import X from unsigned binary data, little endian + */ +int mbedtls_mpi_read_binary_le( mbedtls_mpi *X, + const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) ); + + for( i = 0; i < buflen; i++ ) + X->p[i / ciL] |= ((mbedtls_mpi_uint) buf[i]) << ((i % ciL) << 3); + +cleanup: + + /* + * This function is also used to import keys. However, wiping the buffers + * upon failure is not necessary because failure only can happen before any + * input is copied. + */ + return( ret ); +} + +/* + * Import X from unsigned binary data, big endian + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + size_t const overhead = ( limbs * ciL ) - buflen; + unsigned char *Xp; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) ); + + /* Avoid calling `memcpy` with NULL source or destination argument, + * even if buflen is 0. */ + if( buflen != 0 ) + { + Xp = (unsigned char*) X->p; + memcpy( Xp + overhead, buf, buflen ); + + mpi_bigendian_to_host( X->p, limbs ); + } + +cleanup: + + /* + * This function is also used to import keys. However, wiping the buffers + * upon failure is not necessary because failure only can happen before any + * input is copied. + */ + return( ret ); +} + +/* + * Export X into unsigned binary data, little endian + */ +int mbedtls_mpi_write_binary_le( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) +{ + size_t stored_bytes = X->n * ciL; + size_t bytes_to_copy; + size_t i; + + if( stored_bytes < buflen ) + { + bytes_to_copy = stored_bytes; + } + else + { + bytes_to_copy = buflen; + + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } + + for( i = 0; i < bytes_to_copy; i++ ) + buf[i] = GET_BYTE( X, i ); + + if( stored_bytes < buflen ) + { + /* Write trailing 0 bytes */ + memset( buf + stored_bytes, 0, buflen - stored_bytes ); + } + + return( 0 ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, + unsigned char *buf, size_t buflen ) +{ + size_t stored_bytes; + size_t bytes_to_copy; + unsigned char *p; + size_t i; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( buflen == 0 || buf != NULL ); + + stored_bytes = X->n * ciL; + + if( stored_bytes < buflen ) + { + /* There is enough space in the output buffer. Write initial + * null bytes and record the position at which to start + * writing the significant bytes. In this case, the execution + * trace of this function does not depend on the value of the + * number. */ + bytes_to_copy = stored_bytes; + p = buf + buflen - stored_bytes; + memset( buf, 0, buflen - stored_bytes ); + } + else + { + /* The output buffer is smaller than the allocated size of X. + * However X may fit if its leading bytes are zero. */ + bytes_to_copy = buflen; + p = buf; + for( i = bytes_to_copy; i < stored_bytes; i++ ) + { + if( GET_BYTE( X, i ) != 0 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + } + + for( i = 0; i < bytes_to_copy; i++ ) + p[bytes_to_copy - i - 1] = GET_BYTE( X, i ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, v0, t1; + mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mbedtls_mpi_bitlen( X ) + count; + + if( X->n * biL < i ) + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if( t1 > 0 ) + { + for( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) +{ + size_t i, v0, v1; + mbedtls_mpi_uint r0 = 0, r1; + MPI_VALIDATE_RET( X != NULL ); + + v0 = count / biL; + v1 = count & (biL - 1); + + if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return mbedtls_mpi_lset( X, 0 ); + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if( v1 > 0 ) + { + for( i = X->n; i > 0; i-- ) + { + r1 = X->p[i - 1] << (biL - v1); + X->p[i - 1] >>= v1; + X->p[i - 1] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( 1 ); + if( j > i ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( X->s ); + if( j > i ) return( -Y->s ); + + if( X->s > 0 && Y->s < 0 ) return( 1 ); + if( Y->s > 0 && X->s < 0 ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + mbedtls_mpi Y; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mbedtls_mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j; + mbedtls_mpi_uint *o, *p, c, tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( X == B ) + { + const mbedtls_mpi *T = A; A = X; B = T; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned additions. + */ + X->s = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + + o = B->p; p = X->p; c = 0; + + /* + * tmp is used because it might happen that p == o + */ + for( i = 0; i < j; i++, o++, p++ ) + { + tmp= *o; + *p += c; c = ( *p < c ); + *p += tmp; c += ( *p < tmp ); + } + + while( c != 0 ) + { + if( i >= X->n ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/** + * Helper for mbedtls_mpi subtraction. + * + * Calculate l - r where l and r have the same size. + * This function operates modulo (2^ciL)^n and returns the carry + * (1 if there was a wraparound, i.e. if `l < r`, and 0 otherwise). + * + * d may be aliased to l or r. + * + * \param n Number of limbs of \p d, \p l and \p r. + * \param[out] d The result of the subtraction. + * \param[in] l The left operand. + * \param[in] r The right operand. + * + * \return 1 if `l < r`. + * 0 if `l >= r`. + */ +static mbedtls_mpi_uint mpi_sub_hlp( size_t n, + mbedtls_mpi_uint *d, + const mbedtls_mpi_uint *l, + const mbedtls_mpi_uint *r ) +{ + size_t i; + mbedtls_mpi_uint c = 0, t, z; + + for( i = 0; i < n; i++ ) + { + z = ( l[i] < c ); t = l[i] - c; + c = ( t < r[i] ) + z; d[i] = t - r[i]; + } + + return( c ); +} + +/* + * Unsigned subtraction: X = |A| - |B| (HAC 14.9, 14.10) + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + mbedtls_mpi_uint carry; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + for( n = B->n; n > 0; n-- ) + if( B->p[n - 1] != 0 ) + break; + if( n > A->n ) + { + /* B >= (2^ciL)^n > A */ + ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, A->n ) ); + + /* Set the high limbs of X to match A. Don't touch the lower limbs + * because X might be aliased to B, and we must not overwrite the + * significant digits of B. */ + if( A->n > n ) + memcpy( X->p + n, A->p + n, ( A->n - n ) * ciL ); + if( X->n > A->n ) + memset( X->p + A->n, 0, ( X->n - A->n ) * ciL ); + + carry = mpi_sub_hlp( n, X->p, A->p, B->p ); + if( carry != 0 ) + { + /* Propagate the carry to the first nonzero limb of X. */ + for( ; n < X->n && X->p[n] == 0; n++ ) + --X->p[n]; + /* If we ran out of space for the carry, it means that the result + * is negative. */ + if( n == X->n ) + { + ret = MBEDTLS_ERR_MPI_NEGATIVE_VALUE; + goto cleanup; + } + --X->p[n]; + } + + /* X should always be positive as a result of unsigned subtractions. */ + X->s = 1; + +cleanup: + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + s = A->s; + if( A->s * B->s < 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed subtraction: X = A - B + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + s = A->s; + if( A->s * B->s > 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + B.s = ( b < 0 ) ? -1 : 1; + B.n = 1; + B.p = p; + + return( mbedtls_mpi_add_mpi( X, A, &B ) ); +} + +/* + * Signed subtraction: X = A - b + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + p[0] = ( b < 0 ) ? -b : b; + B.s = ( b < 0 ) ? -1 : 1; + B.n = 1; + B.p = p; + + return( mbedtls_mpi_sub_mpi( X, A, &B ) ); +} + +/** Helper for mbedtls_mpi multiplication. + * + * Add \p b * \p s to \p d. + * + * \param i The number of limbs of \p s. + * \param[in] s A bignum to multiply, of size \p i. + * It may overlap with \p d, but only if + * \p d <= \p s. + * Its leading limb must not be \c 0. + * \param[in,out] d The bignum to add to. + * It must be sufficiently large to store the + * result of the multiplication. This means + * \p i + 1 limbs if \p d[\p i - 1] started as 0 and \p b + * is not known a priori. + * \param b A scalar to multiply. + */ +static +#if defined(__APPLE__) && defined(__arm__) +/* + * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) + * appears to need this to prevent bad ARM code generation at -O3. + */ +__attribute__ ((noinline)) #endif +void mpi_mul_hlp( size_t i, + const mbedtls_mpi_uint *s, + mbedtls_mpi_uint *d, + mbedtls_mpi_uint b ) { - char *yyd = yydest; - const char *yys = yysrc; + mbedtls_mpi_uint c = 0, t = 0; - while ((*yyd++ = *yys++) != '\0') - continue; +#if defined(MULADDC_HUIT) + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } - return yyd - 1; + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else /* MULADDC_HUIT */ + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif /* MULADDC_HUIT */ + + t++; + + while( c != 0 ) + { + *d += c; c = ( *d < c ); d++; + } } -# endif -# endif -# ifndef yytnamerr -/* Copy to YYRES the contents of YYSTR after stripping away unnecessary - quotes and backslashes, so that it's suitable for yyerror. The - heuristic is that double-quoting is unnecessary unless the string - contains an apostrophe, a comma, or backslash (other than - backslash-backslash). YYSTR is taken from yytname. If YYRES is - null, do not copy; instead, return the length of what the result - would have been. */ -static YYSIZE_T -yytnamerr (char *yyres, const char *yystr) +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) { - if (*yystr == '"') + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, j; + mbedtls_mpi TA, TB; + int result_is_zero = 0; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } + + for( i = A->n; i > 0; i-- ) + if( A->p[i - 1] != 0 ) + break; + if( i == 0 ) + result_is_zero = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + if( j == 0 ) + result_is_zero = 1; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( ; j > 0; j-- ) + mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] ); + + /* If the result is 0, we don't shortcut the operation, which reduces + * but does not eliminate side channels leaking the zero-ness. We do + * need to take care to set the sign bit properly since the library does + * not fully support an MPI object with a value of 0 and s == -1. */ + if( result_is_zero ) + X->s = 1; + else + X->s = A->s * B->s; + +cleanup: + + mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) +{ + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + + /* mpi_mul_hlp can't deal with a leading 0. */ + size_t n = A->n; + while( n > 0 && A->p[n - 1] == 0 ) + --n; + + /* The general method below doesn't work if n==0 or b==0. By chance + * calculating the result is trivial in those cases. */ + if( b == 0 || n == 0 ) { - YYSIZE_T yyn = 0; - char const *yyp = yystr; + return( mbedtls_mpi_lset( X, 0 ) ); + } - for (;;) - switch (*++yyp) - { - case '\'': - case ',': - goto do_not_strip_quotes; + /* Calculate A*b as A + A*(b-1) to take advantage of mpi_mul_hlp */ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + /* In general, A * b requires 1 limb more than b. If + * A->p[n - 1] * b / b == A->p[n - 1], then A * b fits in the same + * number of limbs as A and the call to grow() is not required since + * copy() will take care of the growth if needed. However, experimentally, + * making the call to grow() unconditional causes slightly fewer + * calls to calloc() in ECP code, presumably because it reuses the + * same mpi for a while and this way the mpi is more likely to directly + * grow to its final size. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + mpi_mul_hlp( n, A->p, X->p, b - 1 ); - case '\\': - if (*++yyp != '\\') - goto do_not_strip_quotes; - /* Fall through. */ - default: - if (yyres) - yyres[yyn] = *yyp; - yyn++; - break; +cleanup: + return( ret ); +} - case '"': - if (yyres) - yyres[yyn] = '\0'; - return yyn; - } - do_not_strip_quotes: ; +/* + * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and + * mbedtls_mpi_uint divisor, d + */ +static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, + mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) +{ +#if defined(MBEDTLS_HAVE_UDBL) + mbedtls_t_udbl dividend, quotient; +#else + const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; + const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; + mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; + mbedtls_mpi_uint u0_msw, u0_lsw; + size_t s; +#endif + + /* + * Check for overflow + */ + if( 0 == d || u1 >= d ) + { + if (r != NULL) *r = ~0; + + return ( ~0 ); } - if (! yyres) - return yystrlen (yystr); +#if defined(MBEDTLS_HAVE_UDBL) + dividend = (mbedtls_t_udbl) u1 << biL; + dividend |= (mbedtls_t_udbl) u0; + quotient = dividend / d; + if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) + quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; - return yystpcpy (yyres, yystr) - yyres; + if( r != NULL ) + *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); + + return (mbedtls_mpi_uint) quotient; +#else + + /* + * Algorithm D, Section 4.3.1 - The Art of Computer Programming + * Vol. 2 - Seminumerical Algorithms, Knuth + */ + + /* + * Normalize the divisor, d, and dividend, u0, u1 + */ + s = mbedtls_clz( d ); + d = d << s; + + u1 = u1 << s; + u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); + u0 = u0 << s; + + d1 = d >> biH; + d0 = d & uint_halfword_mask; + + u0_msw = u0 >> biH; + u0_lsw = u0 & uint_halfword_mask; + + /* + * Find the first quotient and remainder + */ + q1 = u1 / d1; + r0 = u1 - d1 * q1; + + while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) + { + q1 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); + q0 = rAX / d1; + r0 = rAX - q0 * d1; + + while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) + { + q0 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + if (r != NULL) + *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; + + quotient = q1 * radix + q0; + + return quotient; +#endif } -# endif -/* Copy into YYRESULT an error message about the unexpected token - YYCHAR while in state YYSTATE. Return the number of bytes copied, - including the terminating null byte. If YYRESULT is null, do not - copy anything; just return the number of bytes that would be - copied. As a special case, return 0 if an ordinary "syntax error" - message will do. Return YYSIZE_MAXIMUM if overflow occurs during - size calculation. */ -static YYSIZE_T -yysyntax_error (char *yyresult, int yystate, int yychar) +/* + * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, + const mbedtls_mpi *B ) { - int yyn = yypact[yystate]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, n, t, k; + mbedtls_mpi X, Y, Z, T1, T2; + mbedtls_mpi_uint TP2[3]; + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + mbedtls_mpi_init( &T1 ); + /* + * Avoid dynamic memory allocations for constant-size T2. + * + * T2 is used for comparison only and the 3 limbs are assigned explicitly, + * so nobody increase the size of the MPI and we're safe to use an on-stack + * buffer. + */ + T2.s = 1; + T2.n = sizeof( TP2 ) / sizeof( *TP2 ); + T2.p = TP2; - if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) - return 0; - else + if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) { - int yytype = YYTRANSLATE (yychar); - YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); - YYSIZE_T yysize = yysize0; - YYSIZE_T yysize1; - int yysize_overflow = 0; - enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; - char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; - int yyx; + if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); + if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); + return( 0 ); + } -# if 0 - /* This is so xgettext sees the translatable formats that are - constructed on the fly. */ - YY_("syntax error, unexpected %s"); - YY_("syntax error, unexpected %s, expecting %s"); - YY_("syntax error, unexpected %s, expecting %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s"); - YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); -# endif - char *yyfmt; - char const *yyf; - static char const yyunexpected[] = "syntax error, unexpected %s"; - static char const yyexpecting[] = ", expecting %s"; - static char const yyor[] = " or %s"; - char yyformat[sizeof yyunexpected - + sizeof yyexpecting - 1 - + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) - * (sizeof yyor - 1))]; - char const *yyprefix = yyexpecting; + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); + X.s = Y.s = 1; - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, A->n + 2 ) ); + + k = mbedtls_mpi_bitlen( &Y ) % biL; + if( k < biL - 1 ) + { + k = biL - 1 - k; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); + + while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); + + for( i = n; i > t ; i-- ) + { + if( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { + Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], + Y.p[t], NULL); + } + + T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; + T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); + T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + } + while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); + + if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if( Q != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); + Q->s = A->s * B->s; + } + + if( R != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); + X.s = A->s; + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); + + if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn + 1; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 1; +cleanup: - yyarg[0] = yytname[yytype]; - yyfmt = yystpcpy (yyformat, yyunexpected); + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + mbedtls_mpi_free( &T1 ); + mbedtls_platform_zeroize( TP2, sizeof( TP2 ) ); - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) - { - yycount = 1; - yysize = yysize0; - yyformat[sizeof yyunexpected - 1] = '\0'; - break; - } - yyarg[yycount++] = yytname[yyx]; - yysize1 = yysize + yytnamerr (0, yytname[yyx]); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; - yyfmt = yystpcpy (yyfmt, yyprefix); - yyprefix = yyor; - } + return( ret ); +} - yyf = YY_(yyformat); - yysize1 = yysize + yystrlen (yyf); - yysize_overflow |= (yysize1 < yysize); - yysize = yysize1; +/* + * Division by int: A = Q * b + R + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, + const mbedtls_mpi *A, + mbedtls_mpi_sint b ) +{ + mbedtls_mpi B; + mbedtls_mpi_uint p[1]; + MPI_VALIDATE_RET( A != NULL ); - if (yysize_overflow) - return YYSIZE_MAXIMUM; + p[0] = ( b < 0 ) ? -b : b; + B.s = ( b < 0 ) ? -1 : 1; + B.n = 1; + B.p = p; - if (yyresult) - { - /* Avoid sprintf, as that infringes on the user's name space. - Don't have undefined behavior even if the translation - produced a string with the wrong number of "%s"s. */ - char *yyp = yyresult; - int yyi = 0; - while ((*yyp = *yyf) != '\0') - { - if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) - { - yyp += yytnamerr (yyp, yyarg[yyi++]); - yyf += 2; - } - else - { - yyp++; - yyf++; - } - } - } - return yysize; - } + return( mbedtls_mpi_div_mpi( Q, R, A, &B ) ); } -#endif /* YYERROR_VERBOSE */ - -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ +/* + * Modulo: R = A mod B + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + MPI_VALIDATE_RET( R != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); -/*ARGSUSED*/ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp, core_yyscan_t yyscanner) -#else -static void -yydestruct (yymsg, yytype, yyvaluep, yylocationp, yyscanner) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; - YYLTYPE *yylocationp; - core_yyscan_t yyscanner; -#endif + if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); + + while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); + + while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) { - YYUSE (yyvaluep); - YYUSE (yylocationp); - YYUSE (yyscanner); + size_t i; + mbedtls_mpi_uint x, y, z; + MPI_VALIDATE_RET( r != NULL ); + MPI_VALIDATE_RET( A != NULL ); - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + if( b == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); - switch (yytype) + if( b < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + /* + * handle trivial cases + */ + if( b == 1 ) { + *r = 0; + return( 0 ); + } - default: - break; + if( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); } -} - -/* Prevent warnings from -Wmissing-prototypes. */ + /* + * general case + */ + for( i = A->n, y = 0; i > 0; i-- ) + { + x = A->p[i - 1]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } -#ifdef YYPARSE_PARAM -#if defined __STDC__ || defined __cplusplus -int yyparse (void *YYPARSE_PARAM); -#else -int yyparse (); -#endif -#else /* ! YYPARSE_PARAM */ -#if defined __STDC__ || defined __cplusplus -int yyparse (core_yyscan_t yyscanner); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ + /* + * If A is negative, then the current y represents a negative value. + * Flipping it to the positive side. + */ + if( A->s < 0 && y != 0 ) + y = b - y; + *r = y; + return( 0 ); +} +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +{ + mbedtls_mpi_uint x, m0 = N->p[0]; + unsigned int i; + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + for( i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( m0 * x ) ); -/*----------. -| yyparse. | -`----------*/ + *mm = ~x + 1; +} -#ifdef YYPARSE_PARAM -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (void *YYPARSE_PARAM) -#else -int -yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -#endif -#else /* ! YYPARSE_PARAM */ -#if (defined __STDC__ || defined __C99__FUNC__ \ - || defined __cplusplus || defined _MSC_VER) -int -yyparse (core_yyscan_t yyscanner) -#else -int -yyparse (yyscanner) - core_yyscan_t yyscanner; -#endif -#endif +/** Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + * + * \param[in,out] A One of the numbers to multiply. + * It must have at least as many limbs as N + * (A->n >= N->n), and any limbs beyond n are ignored. + * On successful completion, A contains the result of + * the multiplication A * B * R^-1 mod N where + * R = (2^ciL)^n. + * \param[in] B One of the numbers to multiply. + * It must be nonzero and must not have more limbs than N + * (B->n <= N->n). + * \param[in] N The modulo. N must be odd. + * \param mm The value calculated by `mpi_montg_init(&mm, N)`. + * This is -N^-1 mod 2^ciL. + * \param[in,out] T A bignum for temporary storage. + * It must be at least twice the limb size of N plus 2 + * (T->n >= 2 * (N->n + 1)). + * Its initial content is unused and + * its final content is indeterminate. + * Note that unlike the usual convention in the library + * for `const mbedtls_mpi*`, the content of T can change. + */ +static void mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ) { - /* The look-ahead symbol. */ -int yychar; + size_t i, n, m; + mbedtls_mpi_uint u0, u1, *d; -/* The semantic value of the look-ahead symbol. */ -YYSTYPE yylval; + memset( T->p, 0, T->n * ciL ); -/* Number of syntax errors so far. */ -int yynerrs; -/* Location data for the look-ahead symbol. */ -YYLTYPE yylloc; + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; - int yystate; - int yyn; - int yyresult; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - /* Look-ahead token as an internal (translated) token number. */ - int yytoken = 0; -#if YYERROR_VERBOSE - /* Buffer for error messages, and its allocated size. */ - char yymsgbuf[128]; - char *yymsg = yymsgbuf; - YYSIZE_T yymsg_alloc = sizeof yymsgbuf; -#endif + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; - /* Three stacks and their tools: - `yyss': related to states, - `yyvs': related to semantic values, - `yyls': related to locations. + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ + *d++ = u0; d[n + 1] = 0; + } - /* The state stack. */ - yytype_int16 yyssa[YYINITDEPTH]; - yytype_int16 *yyss = yyssa; - yytype_int16 *yyssp; + /* At this point, d is either the desired result or the desired result + * plus N. We now potentially subtract N, avoiding leaking whether the + * subtraction is performed through side channels. */ + + /* Copy the n least significant limbs of d to A, so that + * A = d if d < N (recall that N has n limbs). */ + memcpy( A->p, d, n * ciL ); + /* If d >= N then we want to set A to d - N. To prevent timing attacks, + * do the calculation without using conditional tests. */ + /* Set d to d0 + (2^biL)^n - N where d0 is the current value of d. */ + d[n] += 1; + d[n] -= mpi_sub_hlp( n, d, d, N->p ); + /* If d0 < N then d < (2^biL)^n + * so d[n] == 0 and we want to keep A as it is. + * If d0 >= N then d >= (2^biL)^n, and d <= (2^biL)^n + N < 2 * (2^biL)^n + * so d[n] == 1 and we want to set A to the result of the subtraction + * which is d - (2^biL)^n, i.e. the n least significant limbs of d. + * This exactly corresponds to a conditional assignment. */ + mbedtls_ct_mpi_uint_cond_assign( n, A->p, d, (unsigned char) d[n] ); +} - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - YYSTYPE *yyvsp; +/* + * Montgomery reduction: A = A * R^-1 mod N + * + * See mpi_montmul() regarding constraints and guarantees on the parameters. + */ +static void mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, + mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +{ + mbedtls_mpi_uint z = 1; + mbedtls_mpi U; - /* The location stack. */ - YYLTYPE yylsa[YYINITDEPTH]; - YYLTYPE *yyls = yylsa; - YYLTYPE *yylsp; - /* The locations where the error started and ended. */ - YYLTYPE yyerror_range[2]; + U.n = U.s = (int) z; + U.p = &z; -#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N)) + mpi_montmul( A, &U, N, mm, T ); +} - YYSIZE_T yystacksize = YYINITDEPTH; +/** + * Select an MPI from a table without leaking the index. + * + * This is functionally equivalent to mbedtls_mpi_copy(R, T[idx]) except it + * reads the entire table in order to avoid leaking the value of idx to an + * attacker able to observe memory access patterns. + * + * \param[out] R Where to write the selected MPI. + * \param[in] T The table to read from. + * \param[in] T_size The number of elements in the table. + * \param[in] idx The index of the element to select; + * this must satisfy 0 <= idx < T_size. + * + * \return \c 0 on success, or a negative error code. + */ +static int mpi_select( mbedtls_mpi *R, const mbedtls_mpi *T, size_t T_size, size_t idx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; - YYLTYPE yyloc; + for( size_t i = 0; i < T_size; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( R, &T[i], + (unsigned char) mbedtls_ct_size_bool_eq( i, idx ) ) ); + } - /* The number of symbols on the RHS of the reduced rule. - Keep to zero when no symbol should be popped. */ - int yylen = 0; +cleanup: + return( ret ); +} - YYDPRINTF ((stderr, "Starting parse\n")); +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, + const mbedtls_mpi *E, const mbedtls_mpi *N, + mbedtls_mpi *prec_RR ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + mbedtls_mpi_uint ei, mm, state; + mbedtls_mpi RR, T, W[ 1 << MBEDTLS_MPI_WINDOW_SIZE ], WW, Apos; + int neg; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( E != NULL ); + MPI_VALIDATE_RET( N != NULL ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_bitlen( E ) > MBEDTLS_MPI_MAX_BITS || + mbedtls_mpi_bitlen( N ) > MBEDTLS_MPI_MAX_BITS ) + return ( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); + mbedtls_mpi_init( &Apos ); + mbedtls_mpi_init( &WW ); + memset( W, 0, sizeof( W ) ); - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ + i = mbedtls_mpi_bitlen( E ); - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; - yyssp = yyss; - yyvsp = yyvs; - yylsp = yyls; -#if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL - /* Initialize the default location before parsing starts. */ - yylloc.first_line = yylloc.last_line = 1; - yylloc.first_column = yylloc.last_column = 0; +#if( MBEDTLS_MPI_WINDOW_SIZE < 6 ) + if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; #endif - goto yysetstate; + j = N->n + 1; + /* All W[i] and X must have at least N->n limbs for the mpi_montmul() + * and mpi_montred() calls later. Here we ensure that W[1] and X are + * large enough, and later we'll grow other W[i] to the same length. + * They must not be shrunk midway through this function! + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. So pushing a state here evens the stacks. */ - yyssp++; + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if( neg ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } - yysetstate: - *yyssp = yystate; + /* + * If 1st call, pre-compute R^2 mod N + */ + if( prec_RR == NULL || prec_RR->p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); - if (yyss + yystacksize - 1 <= yyssp) + if( prec_RR != NULL ) + memcpy( prec_RR, &RR, sizeof( mbedtls_mpi ) ); + } + else + memcpy( &RR, prec_RR, sizeof( mbedtls_mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); + /* This should be a no-op because W[1] is already that large before + * mbedtls_mpi_mod_mpi(), but it's necessary to avoid an overflow + * in mpi_montmul() below, so let's make sure. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], N->n + 1 ) ); + } + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - yytype_int16 *yyss1 = yyss; - YYLTYPE *yyls1 = yyls; + /* Note that this is safe because W[1] always has at least N->n limbs + * (it grew above and was preserved by mbedtls_mpi_copy()). */ + mpi_montmul( &W[1], &RR, N, mm, &T ); - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow (YY_("memory exhausted"), - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yyls1, yysize * sizeof (*yylsp), - &yystacksize); - yyls = yyls1; - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyexhaustedlab; -# else - /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyexhaustedlab; - yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) - yystacksize = YYMAXDEPTH; + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); + mpi_montred( X, N, mm, &T ); - { - yytype_int16 *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyexhaustedlab; - YYSTACK_RELOCATE (yyss); - YYSTACK_RELOCATE (yyvs); - YYSTACK_RELOCATE (yyls); -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << ( wsize - 1 ); - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - yylsp = yyls + yysize - 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + for( i = 0; i < wsize - 1; i++ ) + mpi_montmul( &W[j], &W[j], N, mm, &T ); - if (yyss + yystacksize - 1 <= yyssp) - YYABORT; + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < ( one << wsize ); i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); + + mpi_montmul( &W[i], &W[1], N, mm, &T ); + } } - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; - goto yybackup; + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs == 0 ) + break; -/*-----------. -| yybackup. | -`-----------*/ -yybackup: + nblimbs--; - /* Do appropriate processing given the current state. Read a - look-ahead token if we need one and don't already have one. */ + bufsize = sizeof( mbedtls_mpi_uint ) << 3; + } - /* First try to decide what to do without reference to look-ahead token. */ - yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) - goto yydefault; + bufsize--; - /* Not known => get a look-ahead token if don't already have one. */ + ei = (E->p[nblimbs] >> bufsize) & 1; - /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ - if (yychar == YYEMPTY) + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + mpi_montmul( X, X, N, mm, &T ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= ( ei << ( wsize - nbits ) ); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + mpi_montmul( X, X, N, mm, &T ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + MBEDTLS_MPI_CHK( mpi_select( &WW, W, (size_t) 1 << wsize, wbits ) ); + mpi_montmul( X, &WW, N, mm, &T ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; + mpi_montmul( X, X, N, mm, &T ); + + wbits <<= 1; + + if( ( wbits & ( one << wsize ) ) != 0 ) + mpi_montmul( X, &W[1], N, mm, &T ); } - if (yychar <= YYEOF) + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + mpi_montred( X, N, mm, &T ); + + if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); + X->s = -1; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); } - else + +cleanup: + + for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mbedtls_mpi_free( &W[i] ); + + mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); + mbedtls_mpi_free( &WW ); + + if( prec_RR == NULL || prec_RR->p == NULL ) + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t lz, lzt; + mbedtls_mpi TA, TB; + + MPI_VALIDATE_RET( G != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( B != NULL ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + + lz = mbedtls_mpi_lsb( &TA ); + lzt = mbedtls_mpi_lsb( &TB ); + + /* The loop below gives the correct result when A==0 but not when B==0. + * So have a special case for B==0. Leverage the fact that we just + * calculated the lsb and lsb(B)==0 iff B is odd or 0 to make the test + * slightly more efficient than cmp_int(). */ + if( lzt == 0 && mbedtls_mpi_get_bit( &TB, 0 ) == 0 ) { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + ret = mbedtls_mpi_copy( G, A ); + goto cleanup; } - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) - goto yydefault; - yyn = yytable[yyn]; - if (yyn <= 0) + if( lzt < lz ) + lz = lzt; + + TA.s = TB.s = 1; + + /* We mostly follow the procedure described in HAC 14.54, but with some + * minor differences: + * - Sequences of multiplications or divisions by 2 are grouped into a + * single shift operation. + * - The procedure in HAC assumes that 0 < TB <= TA. + * - The condition TB <= TA is not actually necessary for correctness. + * TA and TB have symmetric roles except for the loop termination + * condition, and the shifts at the beginning of the loop body + * remove any significance from the ordering of TA vs TB before + * the shifts. + * - If TA = 0, the loop goes through 0 iterations and the result is + * correctly TB. + * - The case TB = 0 was short-circuited above. + * + * For the correctness proof below, decompose the original values of + * A and B as + * A = sa * 2^a * A' with A'=0 or A' odd, and sa = +-1 + * B = sb * 2^b * B' with B'=0 or B' odd, and sb = +-1 + * Then gcd(A, B) = 2^{min(a,b)} * gcd(A',B'), + * and gcd(A',B') is odd or 0. + * + * At the beginning, we have TA = |A| and TB = |B| so gcd(A,B) = gcd(TA,TB). + * The code maintains the following invariant: + * gcd(A,B) = 2^k * gcd(TA,TB) for some k (I) + */ + + /* Proof that the loop terminates: + * At each iteration, either the right-shift by 1 is made on a nonzero + * value and the nonnegative integer bitlen(TA) + bitlen(TB) decreases + * by at least 1, or the right-shift by 1 is made on zero and then + * TA becomes 0 which ends the loop (TB cannot be 0 if it is right-shifted + * since in that case TB is calculated from TB-TA with the condition TB>TA). + */ + while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) { - if (yyn == 0 || yyn == YYTABLE_NINF) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; + /* Divisions by 2 preserve the invariant (I). */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); + + /* Set either TA or TB to |TA-TB|/2. Since TA and TB are both odd, + * TA-TB is even so the division by 2 has an integer result. + * Invariant (I) is preserved since any odd divisor of both TA and TB + * also divides |TA-TB|/2, and any odd divisor of both TA and |TA-TB|/2 + * also divides TB, and any odd divisior of both TB and |TA-TB|/2 also + * divides TA. + */ + if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); + } + /* Note that one of TA or TB is still odd. */ } - if (yyn == YYFINAL) - YYACCEPT; + /* By invariant (I), gcd(A,B) = 2^k * gcd(TA,TB) for some k. + * At the loop exit, TA = 0, so gcd(TA,TB) = TB. + * - If there was at least one loop iteration, then one of TA or TB is odd, + * and TA = 0, so TB is odd and gcd(TA,TB) = gcd(A',B'). In this case, + * lz = min(a,b) so gcd(A,B) = 2^lz * TB. + * - If there was no loop iteration, then A was 0, and gcd(A,B) = B. + * In this case, lz = 0 and B = TB so gcd(A,B) = B = 2^lz * TB as well. + */ - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); - /* Shift the look-ahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); +cleanup: - /* Discard the shifted token unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); - yystate = yyn; - *++yyvsp = yylval; - *++yylsp = yylloc; - goto yynewstate; + return( ret ); +} +/* Fill X with n_bytes random bytes. + * X must already have room for those bytes. + * The ordering of the bytes returned from the RNG is suitable for + * deterministic ECDSA (see RFC 6979 §3.3 and mbedtls_mpi_random()). + * The size and sign of X are unchanged. + * n_bytes must not be 0. + */ +static int mpi_fill_random_internal( + mbedtls_mpi *X, size_t n_bytes, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const size_t limbs = CHARS_TO_LIMBS( n_bytes ); + const size_t overhead = ( limbs * ciL ) - n_bytes; -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; + if( X->n < limbs ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + memset( X->p, 0, overhead ); + memset( (unsigned char *) X->p + limbs * ciL, 0, ( X->n - limbs ) * ciL ); + MBEDTLS_MPI_CHK( f_rng( p_rng, (unsigned char *) X->p + overhead, n_bytes ) ); + mpi_bigendian_to_host( X->p, limbs ); -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; +cleanup: + return( ret ); +} - /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. +/* + * Fill X with size bytes of random. + * + * Use a temporary bytes representation to make sure the result is the same + * regardless of the platform endianness (useful when f_rng is actually + * deterministic, eg for tests). + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t const limbs = CHARS_TO_LIMBS( size ); - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); - /* Default location. */ - YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); - YY_REDUCE_PRINT (yyn); - switch (yyn) - { - case 2: -#line 468 "third_party/libpg_query/grammar/grammar.y" - { - pg_yyget_extra(yyscanner)->parsetree = (yyvsp[(1) - (1)].list); - ;} - break; + /* Ensure that target MPI has exactly the necessary number of limbs */ + MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, limbs ) ); + if( size == 0 ) + return( 0 ); - case 3: -#line 484 "third_party/libpg_query/grammar/grammar.y" - { - if ((yyvsp[(1) - (3)].list) != NIL) - { - /* update length of previous stmt */ - updateRawStmtEnd(llast_node(PGRawStmt, (yyvsp[(1) - (3)].list)), (yylsp[(2) - (3)])); - } - if ((yyvsp[(3) - (3)].node) != NULL) - (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeRawStmt((yyvsp[(3) - (3)].node), (yylsp[(2) - (3)]) + 1)); - else - (yyval.list) = (yyvsp[(1) - (3)].list); - ;} - break; + ret = mpi_fill_random_internal( X, size, f_rng, p_rng ); - case 4: -#line 496 "third_party/libpg_query/grammar/grammar.y" +cleanup: + return( ret ); +} + +int mbedtls_mpi_random( mbedtls_mpi *X, + mbedtls_mpi_sint min, + const mbedtls_mpi *N, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + int count; + unsigned lt_lower = 1, lt_upper = 0; + size_t n_bits = mbedtls_mpi_bitlen( N ); + size_t n_bytes = ( n_bits + 7 ) / 8; + mbedtls_mpi lower_bound; + + if( min < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + if( mbedtls_mpi_cmp_int( N, min ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * When min == 0, each try has at worst a probability 1/2 of failing + * (the msb has a probability 1/2 of being 0, and then the result will + * be < N), so after 30 tries failure probability is a most 2**(-30). + * + * When N is just below a power of 2, as is the case when generating + * a random scalar on most elliptic curves, 1 try is enough with + * overwhelming probability. When N is just above a power of 2, + * as when generating a random scalar on secp224k1, each try has + * a probability of failing that is almost 1/2. + * + * The probabilities are almost the same if min is nonzero but negligible + * compared to N. This is always the case when N is crypto-sized, but + * it's convenient to support small N for testing purposes. When N + * is small, use a higher repeat count, otherwise the probability of + * failure is macroscopic. + */ + count = ( n_bytes > 4 ? 30 : 250 ); + + mbedtls_mpi_init( &lower_bound ); + + /* Ensure that target MPI has exactly the same number of limbs + * as the upper bound, even if the upper bound has leading zeros. + * This is necessary for the mbedtls_mpi_lt_mpi_ct() check. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_resize_clear( X, N->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &lower_bound, N->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &lower_bound, min ) ); + + /* + * Match the procedure given in RFC 6979 §3.3 (deterministic ECDSA) + * when f_rng is a suitably parametrized instance of HMAC_DRBG: + * - use the same byte ordering; + * - keep the leftmost n_bits bits of the generated octet string; + * - try until result is in the desired range. + * This also avoids any bias, which is especially important for ECDSA. + */ + do { - if ((yyvsp[(1) - (1)].node) != NULL) - (yyval.list) = list_make1(makeRawStmt((yyvsp[(1) - (1)].node), 0)); - else - (yyval.list) = NIL; - ;} - break; + MBEDTLS_MPI_CHK( mpi_fill_random_internal( X, n_bytes, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, 8 * n_bytes - n_bits ) ); - case 39: -#line 539 "third_party/libpg_query/grammar/grammar.y" - { (yyval.node) = NULL; ;} - break; + if( --count == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } - case 40: -#line 10 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(3) - (4)].range); - n->cmds = (yyvsp[(4) - (4)].list); - n->relkind = PG_OBJECT_TABLE; - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; + MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, &lower_bound, <_lower ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lt_mpi_ct( X, N, <_upper ) ); + } + while( lt_lower != 0 || lt_upper == 0 ); - case 41: -#line 19 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(5) - (6)].range); - n->cmds = (yyvsp[(6) - (6)].list); - n->relkind = PG_OBJECT_TABLE; - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; +cleanup: + mbedtls_mpi_free( &lower_bound ); + return( ret ); +} - case 42: -#line 28 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(3) - (4)].range); - n->cmds = (yyvsp[(4) - (4)].list); - n->relkind = PG_OBJECT_INDEX; - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( A != NULL ); + MPI_VALIDATE_RET( N != NULL ); - case 43: -#line 37 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(5) - (6)].range); - n->cmds = (yyvsp[(6) - (6)].list); - n->relkind = PG_OBJECT_INDEX; - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - case 44: -#line 46 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(3) - (4)].range); - n->cmds = (yyvsp[(4) - (4)].list); - n->relkind = PG_OBJECT_SEQUENCE; - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); + mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); + mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); - case 45: -#line 55 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(5) - (6)].range); - n->cmds = (yyvsp[(6) - (6)].list); - n->relkind = PG_OBJECT_SEQUENCE; - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); - case 46: -#line 64 "third_party/libpg_query/grammar/statements/alter_table.y" + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) { - PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(3) - (4)].range); - n->cmds = (yyvsp[(4) - (4)].list); - n->relkind = PG_OBJECT_VIEW; - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } - case 47: -#line 73 "third_party/libpg_query/grammar/statements/alter_table.y" + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); + + do { - PGAlterTableStmt *n = makeNode(PGAlterTableStmt); - n->relation = (yyvsp[(5) - (6)].range); - n->cmds = (yyvsp[(6) - (6)].list); - n->relkind = PG_OBJECT_VIEW; - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; + while( ( TU.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); - case 48: -#line 86 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); ;} - break; + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); + } - case 49: -#line 88 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].defelt)); ;} - break; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); + } - case 50: -#line 93 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.node) = (yyvsp[(3) - (3)].node); ;} - break; + while( ( TV.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); - case 51: -#line 94 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.node) = NULL; ;} - break; + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); + } - case 52: -#line 100 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.defelt) = makeDefElem("restart", NULL, (yylsp[(1) - (1)])); - ;} - break; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); + } - case 53: -#line 104 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.defelt) = makeDefElem("restart", (PGNode *)(yyvsp[(3) - (3)].value), (yylsp[(1) - (3)])); - ;} - break; + if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); - case 54: -#line 108 "third_party/libpg_query/grammar/statements/alter_table.y" - { - if (strcmp((yyvsp[(2) - (2)].defelt)->defname, "as") == 0 || - strcmp((yyvsp[(2) - (2)].defelt)->defname, "restart") == 0 || - strcmp((yyvsp[(2) - (2)].defelt)->defname, "owned_by") == 0) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("sequence option \"%s\" not supported here", (yyvsp[(2) - (2)].defelt)->defname), - parser_errposition((yylsp[(2) - (2)])))); - (yyval.defelt) = (yyvsp[(2) - (2)].defelt); - ;} - break; + while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); - case 55: -#line 119 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.defelt) = makeDefElem("generated", (PGNode *) makeInteger((yyvsp[(3) - (3)].ival)), (yylsp[(1) - (3)])); - ;} - break; + while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); - case 56: -#line 127 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); - ;} - break; + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); - case 57: -#line 131 "third_party/libpg_query/grammar/statements/alter_table.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); - ;} - break; +cleanup: - case 58: -#line 140 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_AddColumn; - n->def = (yyvsp[(2) - (2)].node); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); + mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); + mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); - case 59: -#line 149 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_AddColumn; - n->def = (yyvsp[(5) - (5)].node); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; + return( ret ); +} - case 60: -#line 158 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_AddColumn; - n->def = (yyvsp[(3) - (3)].node); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(MBEDTLS_GENPRIME) - case 61: -#line 167 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_AddColumn; - n->def = (yyvsp[(6) - (6)].node); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; - case 62: -#line 176 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_ColumnDefault; - n->name = (yyvsp[(3) - (4)].str); - n->def = (yyvsp[(4) - (4)].node); - (yyval.node) = (PGNode *)n; - ;} - break; +/* + * Small divisors test (X must be positive) + * + * Return values: + * 0: no small factor (possible prime, more tests needed) + * 1: certain prime + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime + * other negative: error + */ +static int mpi_check_small_factors( const mbedtls_mpi *X ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint r; - case 63: -#line 185 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_DropNotNull; - n->name = (yyvsp[(3) - (6)].str); - (yyval.node) = (PGNode *)n; - ;} - break; + if( ( X->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - case 64: -#line 193 "third_party/libpg_query/grammar/statements/alter_table.y" + for( i = 0; small_prime[i] > 0; i++ ) { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_SetNotNull; - n->name = (yyvsp[(3) - (6)].str); - (yyval.node) = (PGNode *)n; - ;} - break; + if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 1 ); - case 65: -#line 201 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_SetStatistics; - n->name = (yyvsp[(3) - (6)].str); - n->def = (PGNode *) makeInteger((yyvsp[(6) - (6)].ival)); - (yyval.node) = (PGNode *)n; - ;} - break; + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); - case 66: -#line 210 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_SetOptions; - n->name = (yyvsp[(3) - (5)].str); - n->def = (PGNode *) (yyvsp[(5) - (5)].list); - (yyval.node) = (PGNode *)n; - ;} - break; + if( r == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } - case 67: -#line 219 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_ResetOptions; - n->name = (yyvsp[(3) - (5)].str); - n->def = (PGNode *) (yyvsp[(5) - (5)].list); - (yyval.node) = (PGNode *)n; - ;} - break; +cleanup: + return( ret ); +} - case 68: -#line 228 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_SetStorage; - n->name = (yyvsp[(3) - (6)].str); - n->def = (PGNode *) makeString((yyvsp[(6) - (6)].str)); - (yyval.node) = (PGNode *)n; - ;} - break; +/* + * Miller-Rabin pseudo-primality test (HAC 4.24) + */ +static int mpi_miller_rabin( const mbedtls_mpi *X, size_t rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count; + size_t i, j, k, s; + mbedtls_mpi W, R, T, A, RR; - case 69: -#line 237 "third_party/libpg_query/grammar/statements/alter_table.y" + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); + mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); + mbedtls_mpi_init( &RR ); + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); + s = mbedtls_mpi_lsb( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); + + for( i = 0; i < rounds; i++ ) { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - PGConstraint *c = makeNode(PGConstraint); + /* + * pick a random A, 1 < A < |X| - 1 + */ + count = 0; + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + j = mbedtls_mpi_bitlen( &A ); + k = mbedtls_mpi_bitlen( &W ); + if (j > k) { + A.p[A.n - 1] &= ( (mbedtls_mpi_uint) 1 << ( k - ( A.n - 1 ) * biL - 1 ) ) - 1; + } - c->contype = PG_CONSTR_IDENTITY; - c->generated_when = (yyvsp[(6) - (9)].ival); - c->options = (yyvsp[(9) - (9)].list); - c->location = (yylsp[(5) - (9)]); + if (count++ > 30) { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } - n->subtype = PG_AT_AddIdentity; - n->name = (yyvsp[(3) - (9)].str); - n->def = (PGNode *) c; + } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || + mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); - (yyval.node) = (PGNode *)n; - ;} - break; + /* + * A = A^R mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); - case 70: -#line 254 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_SetIdentity; - n->name = (yyvsp[(3) - (4)].str); - n->def = (PGNode *) (yyvsp[(4) - (4)].list); - (yyval.node) = (PGNode *)n; - ;} - break; + if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + continue; - case 71: -#line 263 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = AT_DropIdentity; - n->name = (yyvsp[(3) - (5)].str); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; + j = 1; + while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); - case 72: -#line 272 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = AT_DropIdentity; - n->name = (yyvsp[(3) - (7)].str); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; + if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + break; - case 73: -#line 281 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_DropColumn; - n->name = (yyvsp[(5) - (6)].str); - n->behavior = (yyvsp[(6) - (6)].dbehavior); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; + j++; + } - case 74: -#line 291 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_DropColumn; - n->name = (yyvsp[(3) - (4)].str); - n->behavior = (yyvsp[(4) - (4)].dbehavior); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } - case 75: -#line 304 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - PGColumnDef *def = makeNode(PGColumnDef); - n->subtype = PG_AT_AlterColumnType; - n->name = (yyvsp[(3) - (8)].str); - n->def = (PGNode *) def; - /* We only use these fields of the PGColumnDef node */ - def->typeName = (yyvsp[(6) - (8)].typnam); - def->collClause = (PGCollateClause *) (yyvsp[(7) - (8)].node); - def->raw_default = (yyvsp[(8) - (8)].node); - def->location = (yylsp[(3) - (8)]); - (yyval.node) = (PGNode *)n; - ;} - break; +cleanup: + mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); + mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &RR ); - case 76: -#line 319 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_AlterColumnGenericOptions; - n->name = (yyvsp[(3) - (4)].str); - n->def = (PGNode *) (yyvsp[(4) - (4)].list); - (yyval.node) = (PGNode *)n; - ;} - break; + return( ret ); +} - case 77: -#line 328 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_AddConstraint; - n->def = (yyvsp[(2) - (2)].node); - (yyval.node) = (PGNode *)n; - ;} - break; +/* + * Pseudo-primality test: small factors, then Miller-Rabin + */ +int mbedtls_mpi_is_prime_ext( const mbedtls_mpi *X, int rounds, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi XX; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); - case 78: -#line 336 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - PGConstraint *c = makeNode(PGConstraint); - n->subtype = PG_AT_AlterConstraint; - n->def = (PGNode *) c; - c->contype = PG_CONSTR_FOREIGN; /* others not supported, yet */ - c->conname = (yyvsp[(3) - (4)].str); - processCASbits((yyvsp[(4) - (4)].ival), (yylsp[(4) - (4)]), "ALTER CONSTRAINT statement", - &c->deferrable, - &c->initdeferred, - NULL, NULL, yyscanner); - (yyval.node) = (PGNode *)n; - ;} - break; + XX.s = 1; + XX.n = X->n; + XX.p = X->p; - case 79: -#line 351 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_ValidateConstraint; - n->name = (yyvsp[(3) - (3)].str); - (yyval.node) = (PGNode *)n; - ;} - break; + if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || + mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); - case 80: -#line 359 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_DropConstraint; - n->name = (yyvsp[(5) - (6)].str); - n->behavior = (yyvsp[(6) - (6)].dbehavior); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; + if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) + return( 0 ); - case 81: -#line 369 "third_party/libpg_query/grammar/statements/alter_table.y" + if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_DropConstraint; - n->name = (yyvsp[(3) - (4)].str); - n->behavior = (yyvsp[(4) - (4)].dbehavior); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; + if( ret == 1 ) + return( 0 ); - case 82: -#line 379 "third_party/libpg_query/grammar/statements/alter_table.y" + return( ret ); + } + + return( mpi_miller_rabin( &XX, rounds, f_rng, p_rng ) ); +} + +/* + * Prime number generation + * + * To generate an RSA key in a way recommended by FIPS 186-4, both primes must + * be either 1024 bits or 1536 bits long, and flags must contain + * MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int flags, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ +#ifdef MBEDTLS_HAVE_INT64 +// ceil(2^63.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL +#else +// ceil(2^31.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U +#endif + int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + size_t k, n; + int rounds; + mbedtls_mpi_uint r; + mbedtls_mpi Y; + + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( f_rng != NULL ); + + if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR ) == 0 ) { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_SetLogged; - (yyval.node) = (PGNode *)n; - ;} - break; + /* + * 2^-80 error probability, number of rounds chosen per HAC, table 4.4 + */ + rounds = ( ( nbits >= 1300 ) ? 2 : ( nbits >= 850 ) ? 3 : + ( nbits >= 650 ) ? 4 : ( nbits >= 350 ) ? 8 : + ( nbits >= 250 ) ? 12 : ( nbits >= 150 ) ? 18 : 27 ); + } + else + { + /* + * 2^-100 error probability, number of rounds computed based on HAC, + * fact 4.48 + */ + rounds = ( ( nbits >= 1450 ) ? 4 : ( nbits >= 1150 ) ? 5 : + ( nbits >= 1000 ) ? 6 : ( nbits >= 850 ) ? 7 : + ( nbits >= 750 ) ? 8 : ( nbits >= 500 ) ? 13 : + ( nbits >= 250 ) ? 28 : ( nbits >= 150 ) ? 40 : 51 ); + } - case 83: -#line 386 "third_party/libpg_query/grammar/statements/alter_table.y" + while( 1 ) { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_SetUnLogged; - (yyval.node) = (PGNode *)n; - ;} - break; + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ + if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue; + + k = n * biL; + if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); + X->p[0] |= 1; + + if( ( flags & MBEDTLS_MPI_GEN_PRIME_FLAG_DH ) == 0 ) + { + ret = mbedtls_mpi_is_prime_ext( X, rounds, f_rng, p_rng ); + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + } + else + { + /* + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 + */ + + X->p[0] |= 2; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, rounds, f_rng, p_rng ) ) + == 0 && + ( ret = mpi_miller_rabin( &Y, rounds, f_rng, p_rng ) ) + == 0 ) + goto cleanup; + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &Y ); + + return( ret ); +} + +#endif /* MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_SELF_TEST) + +#define GCD_PAIR_COUNT 3 + +static const int gcd_pairs[GCD_PAIR_COUNT][3] = +{ + { 693, 609, 21 }, + { 1764, 868, 28 }, + { 768454923, 542167814, 1 } +}; - case 84: -#line 393 "third_party/libpg_query/grammar/statements/alter_table.y" +/* + * Checkup routine + */ +int mbedtls_mpi_self_test( int verbose ) +{ + int ret, i; + mbedtls_mpi A, E, N, X, Y, U, V; + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); + mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #1 (mul_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_SetRelOptions; - n->def = (PGNode *)(yyvsp[(2) - (2)].list); - (yyval.node) = (PGNode *)n; - ;} - break; + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); - case 85: -#line 401 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_ResetRelOptions; - n->def = (PGNode *)(yyvsp[(2) - (2)].list); - (yyval.node) = (PGNode *)n; - ;} - break; + ret = 1; + goto cleanup; + } - case 86: -#line 408 "third_party/libpg_query/grammar/statements/alter_table.y" - { - PGAlterTableCmd *n = makeNode(PGAlterTableCmd); - n->subtype = PG_AT_GenericOptions; - n->def = (PGNode *)(yyvsp[(1) - (1)].list); - (yyval.node) = (PGNode *) n; - ;} - break; + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); - case 87: -#line 418 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} - break; + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); - case 88: -#line 419 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.node) = NULL; ;} - break; + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); - case 89: -#line 425 "third_party/libpg_query/grammar/statements/alter_table.y" + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #2 (div_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || + mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) { - (yyval.defelt) = (yyvsp[(1) - (1)].defelt); - ;} - break; + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); - case 90: -#line 429 "third_party/libpg_query/grammar/statements/alter_table.y" + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #3 (exp_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) { - (yyval.defelt) = (yyvsp[(2) - (2)].defelt); - (yyval.defelt)->defaction = PG_DEFELEM_SET; - ;} - break; + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); - case 91: -#line 434 "third_party/libpg_query/grammar/statements/alter_table.y" + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #4 (inv_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) { - (yyval.defelt) = (yyvsp[(2) - (2)].defelt); - (yyval.defelt)->defaction = PG_DEFELEM_ADD; - ;} - break; + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); - case 92: -#line 439 "third_party/libpg_query/grammar/statements/alter_table.y" + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #5 (simple gcd): " ); + + for( i = 0; i < GCD_PAIR_COUNT; i++ ) { - (yyval.defelt) = makeDefElemExtended(NULL, (yyvsp[(2) - (2)].str), NULL, DEFELEM_DROP, (yylsp[(2) - (2)])); - ;} - break; + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); - case 93: -#line 446 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} - break; + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); - case 94: -#line 447 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} - break; + if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed at %d\n", i ); - case 95: -#line 452 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} - break; + ret = 1; + goto cleanup; + } + } - case 96: -#line 456 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.ival) = 1; ;} - break; + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); - case 97: -#line 457 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.ival) = 0; ;} - break; +cleanup: - case 98: -#line 458 "third_party/libpg_query/grammar/statements/alter_table.y" - { (yyval.ival) = 0; ;} - break; + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", (unsigned int) ret ); - case 99: -#line 8 "third_party/libpg_query/grammar/statements/deallocate.y" - { - PGDeallocateStmt *n = makeNode(PGDeallocateStmt); - n->name = (yyvsp[(2) - (2)].str); - (yyval.node) = (PGNode *) n; - ;} - break; + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); + mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); - case 100: -#line 14 "third_party/libpg_query/grammar/statements/deallocate.y" - { - PGDeallocateStmt *n = makeNode(PGDeallocateStmt); - n->name = (yyvsp[(3) - (3)].str); - (yyval.node) = (PGNode *) n; - ;} - break; + if( verbose != 0 ) + mbedtls_printf( "\n" ); - case 101: -#line 20 "third_party/libpg_query/grammar/statements/deallocate.y" - { - PGDeallocateStmt *n = makeNode(PGDeallocateStmt); - n->name = NULL; - (yyval.node) = (PGNode *) n; - ;} - break; + return( ret ); +} - case 102: -#line 26 "third_party/libpg_query/grammar/statements/deallocate.y" - { - PGDeallocateStmt *n = makeNode(PGDeallocateStmt); - n->name = NULL; - (yyval.node) = (PGNode *) n; - ;} - break; +#endif /* MBEDTLS_SELF_TEST */ - case 103: -#line 7 "third_party/libpg_query/grammar/statements/rename.y" - { - PGRenameStmt *n = makeNode(PGRenameStmt); - n->renameType = PG_OBJECT_SCHEMA; - n->subname = (yyvsp[(3) - (6)].str); - n->newname = (yyvsp[(6) - (6)].str); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; +#endif /* MBEDTLS_BIGNUM_C */ - case 104: -#line 16 "third_party/libpg_query/grammar/statements/rename.y" - { - PGRenameStmt *n = makeNode(PGRenameStmt); - n->renameType = PG_OBJECT_TABLE; - n->relation = (yyvsp[(3) - (6)].range); - n->subname = NULL; - n->newname = (yyvsp[(6) - (6)].str); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; - case 105: -#line 26 "third_party/libpg_query/grammar/statements/rename.y" - { - PGRenameStmt *n = makeNode(PGRenameStmt); - n->renameType = PG_OBJECT_TABLE; - n->relation = (yyvsp[(5) - (8)].range); - n->subname = NULL; - n->newname = (yyvsp[(8) - (8)].str); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; +// LICENSE_CHANGE_END - case 106: -#line 36 "third_party/libpg_query/grammar/statements/rename.y" - { - PGRenameStmt *n = makeNode(PGRenameStmt); - n->renameType = PG_OBJECT_SEQUENCE; - n->relation = (yyvsp[(3) - (6)].range); - n->subname = NULL; - n->newname = (yyvsp[(6) - (6)].str); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; - case 107: -#line 46 "third_party/libpg_query/grammar/statements/rename.y" - { - PGRenameStmt *n = makeNode(PGRenameStmt); - n->renameType = PG_OBJECT_SEQUENCE; - n->relation = (yyvsp[(5) - (8)].range); - n->subname = NULL; - n->newname = (yyvsp[(8) - (8)].str); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 108: -#line 56 "third_party/libpg_query/grammar/statements/rename.y" - { - PGRenameStmt *n = makeNode(PGRenameStmt); - n->renameType = PG_OBJECT_VIEW; - n->relation = (yyvsp[(3) - (6)].range); - n->subname = NULL; - n->newname = (yyvsp[(6) - (6)].str); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * Constant-time functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - case 109: -#line 66 "third_party/libpg_query/grammar/statements/rename.y" - { - PGRenameStmt *n = makeNode(PGRenameStmt); - n->renameType = PG_OBJECT_VIEW; - n->relation = (yyvsp[(5) - (8)].range); - n->subname = NULL; - n->newname = (yyvsp[(8) - (8)].str); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; + /* + * The following functions are implemented without using comparison operators, as those + * might be translated to branches by some compilers on some platforms. + */ - case 110: -#line 76 "third_party/libpg_query/grammar/statements/rename.y" - { - PGRenameStmt *n = makeNode(PGRenameStmt); - n->renameType = PG_OBJECT_INDEX; - n->relation = (yyvsp[(3) - (6)].range); - n->subname = NULL; - n->newname = (yyvsp[(6) - (6)].str); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; - case 111: -#line 86 "third_party/libpg_query/grammar/statements/rename.y" - { - PGRenameStmt *n = makeNode(PGRenameStmt); - n->renameType = PG_OBJECT_INDEX; - n->relation = (yyvsp[(5) - (8)].range); - n->subname = NULL; - n->newname = (yyvsp[(8) - (8)].str); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; - case 112: -#line 96 "third_party/libpg_query/grammar/statements/rename.y" - { - PGRenameStmt *n = makeNode(PGRenameStmt); - n->renameType = PG_OBJECT_COLUMN; - n->relationType = PG_OBJECT_TABLE; - n->relation = (yyvsp[(3) - (8)].range); - n->subname = (yyvsp[(6) - (8)].str); - n->newname = (yyvsp[(8) - (8)].str); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; - case 113: -#line 107 "third_party/libpg_query/grammar/statements/rename.y" - { - PGRenameStmt *n = makeNode(PGRenameStmt); - n->renameType = PG_OBJECT_COLUMN; - n->relationType = PG_OBJECT_TABLE; - n->relation = (yyvsp[(5) - (10)].range); - n->subname = (yyvsp[(8) - (10)].str); - n->newname = (yyvsp[(10) - (10)].str); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; - case 114: -#line 118 "third_party/libpg_query/grammar/statements/rename.y" - { - PGRenameStmt *n = makeNode(PGRenameStmt); - n->renameType = PG_OBJECT_TABCONSTRAINT; - n->relation = (yyvsp[(3) - (8)].range); - n->subname = (yyvsp[(6) - (8)].str); - n->newname = (yyvsp[(8) - (8)].str); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 115: -#line 128 "third_party/libpg_query/grammar/statements/rename.y" - { - PGRenameStmt *n = makeNode(PGRenameStmt); - n->renameType = PG_OBJECT_TABCONSTRAINT; - n->relation = (yyvsp[(5) - (10)].range); - n->subname = (yyvsp[(8) - (10)].str); - n->newname = (yyvsp[(10) - (10)].str); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * Constant-time functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - case 116: -#line 140 "third_party/libpg_query/grammar/statements/rename.y" - { (yyval.ival) = COLUMN; ;} - break; +#ifndef MBEDTLS_CONSTANT_TIME_H +#define MBEDTLS_CONSTANT_TIME_H - case 117: -#line 141 "third_party/libpg_query/grammar/statements/rename.y" - { (yyval.ival) = 0; ;} - break; +#include - case 118: -#line 10 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyvsp[(5) - (7)].istmt)->relation = (yyvsp[(4) - (7)].range); - (yyvsp[(5) - (7)].istmt)->onConflictClause = (yyvsp[(6) - (7)].onconflict); - (yyvsp[(5) - (7)].istmt)->returningList = (yyvsp[(7) - (7)].list); - (yyvsp[(5) - (7)].istmt)->withClause = (yyvsp[(1) - (7)].with); - (yyval.node) = (PGNode *) (yyvsp[(5) - (7)].istmt); - ;} - break; - case 119: -#line 22 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.istmt) = makeNode(PGInsertStmt); - (yyval.istmt)->cols = NIL; - (yyval.istmt)->selectStmt = (yyvsp[(1) - (1)].node); - ;} - break; +/** Constant-time buffer comparison without branches. + * + * This is equivalent to the standard memcmp function, but is likely to be + * compiled to code using bitwise operation rather than a branch. + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param a Pointer to the first buffer. + * \param b Pointer to the second buffer. + * \param n The number of bytes to compare in the buffer. + * + * \return Zero if the content of the two buffer is the same, + * otherwise non-zero. + */ +int mbedtls_ct_memcmp( const void *a, + const void *b, + size_t n ); - case 120: -#line 28 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.istmt) = makeNode(PGInsertStmt); - (yyval.istmt)->cols = NIL; - (yyval.istmt)->override = (yyvsp[(2) - (4)].override); - (yyval.istmt)->selectStmt = (yyvsp[(4) - (4)].node); - ;} - break; +#endif /* MBEDTLS_CONSTANT_TIME_H */ - case 121: -#line 35 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.istmt) = makeNode(PGInsertStmt); - (yyval.istmt)->cols = (yyvsp[(2) - (4)].list); - (yyval.istmt)->selectStmt = (yyvsp[(4) - (4)].node); - ;} - break; - case 122: -#line 41 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.istmt) = makeNode(PGInsertStmt); - (yyval.istmt)->cols = (yyvsp[(2) - (7)].list); - (yyval.istmt)->override = (yyvsp[(5) - (7)].override); - (yyval.istmt)->selectStmt = (yyvsp[(7) - (7)].node); - ;} - break; +// LICENSE_CHANGE_END - case 123: -#line 48 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.istmt) = makeNode(PGInsertStmt); - (yyval.istmt)->cols = NIL; - (yyval.istmt)->selectStmt = NULL; - ;} - break; - case 124: -#line 58 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.range) = (yyvsp[(1) - (1)].range); - ;} - break; - case 125: -#line 62 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyvsp[(1) - (3)].range)->alias = makeAlias((yyvsp[(3) - (3)].str), NIL); - (yyval.range) = (yyvsp[(1) - (3)].range); - ;} - break; - case 126: -#line 71 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.infer) = makeNode(PGInferClause); - (yyval.infer)->indexElems = (yyvsp[(2) - (4)].list); - (yyval.infer)->whereClause = (yyvsp[(4) - (4)].node); - (yyval.infer)->conname = NULL; - (yyval.infer)->location = (yylsp[(1) - (4)]); - ;} - break; +#if defined(MBEDTLS_BIGNUM_C) - case 127: -#line 80 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.infer) = makeNode(PGInferClause); - (yyval.infer)->indexElems = NIL; - (yyval.infer)->whereClause = NULL; - (yyval.infer)->conname = (yyvsp[(3) - (3)].str); - (yyval.infer)->location = (yylsp[(1) - (3)]); - ;} - break; +#endif - case 128: -#line 88 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.infer) = NULL; - ;} - break; +#if defined(MBEDTLS_SSL_TLS_C) - case 129: -#line 95 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.with) = (yyvsp[(1) - (1)].with); ;} - break; +#endif - case 130: -#line 96 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.with) = NULL; ;} - break; +#if defined(MBEDTLS_RSA_C) - case 131: -#line 102 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.target) = makeNode(PGResTarget); - (yyval.target)->name = (yyvsp[(1) - (2)].str); - (yyval.target)->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); - (yyval.target)->val = NULL; - (yyval.target)->location = (yylsp[(1) - (2)]); - ;} - break; - case 132: -#line 114 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyvsp[(1) - (3)].target)->val = (PGNode *) (yyvsp[(3) - (3)].node); - (yyval.list) = list_make1((yyvsp[(1) - (3)].target)); - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 133: -#line 119 "third_party/libpg_query/grammar/statements/insert.y" - { - int ncolumns = list_length((yyvsp[(2) - (5)].list)); - int i = 1; - PGListCell *col_cell; +/** + * \file rsa.h + * + * \brief This file provides an API for the RSA public-key cryptosystem. + * + * The RSA public-key cryptosystem is defined in Public-Key + * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption + * and Public-Key Cryptography Standards (PKCS) #1 v2.1: + * RSA Cryptography Specifications. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_RSA_H +#define MBEDTLS_RSA_H - /* Create a PGMultiAssignRef source for each target */ - foreach(col_cell, (yyvsp[(2) - (5)].list)) - { - PGResTarget *res_col = (PGResTarget *) lfirst(col_cell); - PGMultiAssignRef *r = makeNode(PGMultiAssignRef); - r->source = (PGNode *) (yyvsp[(5) - (5)].node); - r->colno = i; - r->ncolumns = ncolumns; - res_col->val = (PGNode *) r; - i++; - } - (yyval.list) = (yyvsp[(2) - (5)].list); - ;} - break; - case 134: -#line 144 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.onconflict) = makeNode(PGOnConflictClause); - (yyval.onconflict)->action = PG_ONCONFLICT_UPDATE; - (yyval.onconflict)->infer = (yyvsp[(3) - (8)].infer); - (yyval.onconflict)->targetList = (yyvsp[(7) - (8)].list); - (yyval.onconflict)->whereClause = (yyvsp[(8) - (8)].node); - (yyval.onconflict)->location = (yylsp[(1) - (8)]); - ;} - break; - case 135: -#line 154 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.onconflict) = makeNode(PGOnConflictClause); - (yyval.onconflict)->action = PG_ONCONFLICT_NOTHING; - (yyval.onconflict)->infer = (yyvsp[(3) - (5)].infer); - (yyval.onconflict)->targetList = NIL; - (yyval.onconflict)->whereClause = NULL; - (yyval.onconflict)->location = (yylsp[(1) - (5)]); - ;} - break; - case 136: -#line 163 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.onconflict) = NULL; - ;} - break; - case 137: -#line 170 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.ielem) = makeNode(PGIndexElem); - (yyval.ielem)->name = (yyvsp[(1) - (5)].str); - (yyval.ielem)->expr = NULL; - (yyval.ielem)->indexcolname = NULL; - (yyval.ielem)->collation = (yyvsp[(2) - (5)].list); - (yyval.ielem)->opclass = (yyvsp[(3) - (5)].list); - (yyval.ielem)->ordering = (yyvsp[(4) - (5)].sortorder); - (yyval.ielem)->nulls_ordering = (yyvsp[(5) - (5)].nullorder); - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 138: -#line 181 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.ielem) = makeNode(PGIndexElem); - (yyval.ielem)->name = NULL; - (yyval.ielem)->expr = (yyvsp[(1) - (5)].node); - (yyval.ielem)->indexcolname = NULL; - (yyval.ielem)->collation = (yyvsp[(2) - (5)].list); - (yyval.ielem)->opclass = (yyvsp[(3) - (5)].list); - (yyval.ielem)->ordering = (yyvsp[(4) - (5)].sortorder); - (yyval.ielem)->nulls_ordering = (yyvsp[(5) - (5)].nullorder); - ;} - break; + /** + * \file md.h + * + * \brief This file contains the generic message-digest wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - case 139: -#line 192 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.ielem) = makeNode(PGIndexElem); - (yyval.ielem)->name = NULL; - (yyval.ielem)->expr = (yyvsp[(2) - (7)].node); - (yyval.ielem)->indexcolname = NULL; - (yyval.ielem)->collation = (yyvsp[(4) - (7)].list); - (yyval.ielem)->opclass = (yyvsp[(5) - (7)].list); - (yyval.ielem)->ordering = (yyvsp[(6) - (7)].sortorder); - (yyval.ielem)->nulls_ordering = (yyvsp[(7) - (7)].nullorder); - ;} - break; +#ifndef MBEDTLS_MD_H +#define MBEDTLS_MD_H - case 140: -#line 206 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} - break; - case 141: -#line 207 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = NIL; ;} - break; +#include - case 142: -#line 213 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.override) = PG_OVERRIDING_USER_VALUE; ;} - break; - case 143: -#line 214 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.override) = OVERRIDING_SYSTEM_VALUE; ;} - break; - case 144: -#line 219 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].target)); ;} - break; - case 145: -#line 220 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list),(yyvsp[(3) - (3)].target)); ;} - break; +/** The selected feature is not available. */ +#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 +/** Failed to allocate memory. */ +#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 +/** Opening or reading of file failed. */ +#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 - case 146: -#line 226 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} - break; +#ifdef __cplusplus +extern "C" { +#endif - case 147: -#line 227 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = NIL; ;} - break; +/** + * \brief Supported message digests. + * + * \warning MD5 and SHA-1 are considered weak message digests and + * their use constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef enum { + MBEDTLS_MD_NONE=0, /**< None. */ + MBEDTLS_MD_MD5, /**< The MD5 message digest. */ + MBEDTLS_MD_SHA1, /**< The SHA-1 message digest. */ + MBEDTLS_MD_SHA224, /**< The SHA-224 message digest. */ + MBEDTLS_MD_SHA256, /**< The SHA-256 message digest. */ + MBEDTLS_MD_SHA384, /**< The SHA-384 message digest. */ + MBEDTLS_MD_SHA512, /**< The SHA-512 message digest. */ + MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */ +} mbedtls_md_type_t; + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#else +#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#endif - case 148: -#line 231 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_BLOCK_SIZE 128 +#else +#define MBEDTLS_MD_MAX_BLOCK_SIZE 64 +#endif - case 149: -#line 232 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = NIL; ;} - break; +/** + * Opaque struct. + * + * Constructed using either #mbedtls_md_info_from_string or + * #mbedtls_md_info_from_type. + * + * Fields can be accessed with #mbedtls_md_get_size, + * #mbedtls_md_get_type and #mbedtls_md_get_name. + */ +/* Defined internally in library/md_wrap.h. */ +typedef struct mbedtls_md_info_t mbedtls_md_info_t; - case 150: -#line 238 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].target)); ;} - break; +/** + * The generic message-digest context. + */ +typedef struct mbedtls_md_context_t +{ + /** Information about the associated message digest. */ + const mbedtls_md_info_t *MBEDTLS_PRIVATE(md_info); - case 151: -#line 240 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].target)); ;} - break; + /** The digest-specific context. */ + void *MBEDTLS_PRIVATE(md_ctx); - case 152: -#line 245 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; + /** The HMAC part of the context. */ + void *MBEDTLS_PRIVATE(hmac_ctx); +} mbedtls_md_context_t; - case 153: -#line 246 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = list_concat((yyvsp[(1) - (3)].list),(yyvsp[(3) - (3)].list)); ;} - break; +/** + * \brief This function returns the list of digests supported by the + * generic digest module. + * + * \note The list starts with the strongest available hashes. + * + * \return A statically allocated array of digests. Each element + * in the returned list is an integer belonging to the + * message-digest enumeration #mbedtls_md_type_t. + * The last entry is 0. + */ +const int *mbedtls_md_list( void ); - case 154: -#line 250 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; +/** + * \brief This function returns the message-digest information + * associated with the given digest name. + * + * \param md_name The name of the digest to search for. + * + * \return The message-digest information associated with \p md_name. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); - case 155: -#line 251 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} - break; +/** + * \brief This function returns the message-digest information + * associated with the given digest type. + * + * \param md_type The type of digest to search for. + * + * \return The message-digest information associated with \p md_type. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); - case 156: -#line 254 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].ielem)); ;} - break; +/** + * \brief This function initializes a message-digest context without + * binding it to a particular message-digest algorithm. + * + * This function should always be called first. It prepares the + * context for mbedtls_md_setup() for binding it to a + * message-digest algorithm. + */ +void mbedtls_md_init( mbedtls_md_context_t *ctx ); - case 157: -#line 255 "third_party/libpg_query/grammar/statements/insert.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].ielem)); ;} - break; +/** + * \brief This function clears the internal structure of \p ctx and + * frees any embedded internal structure, but does not free + * \p ctx itself. + * + * If you have called mbedtls_md_setup() on \p ctx, you must + * call mbedtls_md_free() when you are no longer using the + * context. + * Calling this function if you have previously + * called mbedtls_md_init() and nothing else is optional. + * You must not call this function if you have not called + * mbedtls_md_init(). + */ +void mbedtls_md_free( mbedtls_md_context_t *ctx ); - case 158: -#line 261 "third_party/libpg_query/grammar/statements/insert.y" - { - (yyval.target) = makeNode(PGResTarget); - (yyval.target)->name = (yyvsp[(1) - (2)].str); - (yyval.target)->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); - (yyval.target)->val = NULL; /* upper production sets this */ - (yyval.target)->location = (yylsp[(1) - (2)]); - ;} - break; - case 159: -#line 8 "third_party/libpg_query/grammar/statements/create_type.y" - { - PGCreateTypeStmt *n = makeNode(PGCreateTypeStmt); - n->kind = PG_NEWTYPE_ENUM; - n->typeName = (yyvsp[(3) - (8)].list); - n->vals = (yyvsp[(7) - (8)].list); - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or + * mbedtls_md_free(). Makes it necessary to call + * mbedtls_md_free() later. + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param hmac Defines if HMAC is used. 0: HMAC is not used (saves some memory), + * or non-zero: HMAC is used with this context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); - case 160: -#line 16 "third_party/libpg_query/grammar/statements/create_type.y" - { - PGCreateTypeStmt *n = makeNode(PGCreateTypeStmt); - n->kind = PG_NEWTYPE_ALIAS; - n->typeName = (yyvsp[(3) - (5)].list); - n->ofType = (yyvsp[(5) - (5)].typnam); - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief This function clones the state of an message-digest + * context. + * + * \note You must call mbedtls_md_setup() on \c dst before calling + * this function. + * + * \note The two contexts must have the same type, + * for example, both are SHA-256. + * + * \warning This function clones the message-digest state, not the + * HMAC state. + * + * \param dst The destination context. + * \param src The context to be cloned. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ); - case 161: -#line 26 "third_party/libpg_query/grammar/statements/create_type.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; +/** + * \brief This function extracts the message-digest size from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The size of the message-digest output in Bytes. + */ +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); - case 162: -#line 27 "third_party/libpg_query/grammar/statements/create_type.y" - { (yyval.list) = NIL; ;} - break; +/** + * \brief This function extracts the message-digest type from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The type of the message digest. + */ +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); - case 163: -#line 31 "third_party/libpg_query/grammar/statements/create_type.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} - break; +/** + * \brief This function extracts the message-digest name from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The name of the message digest. + */ +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); - case 164: -#line 33 "third_party/libpg_query/grammar/statements/create_type.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeString((yyvsp[(3) - (3)].str))); ;} - break; +/** + * \brief This function starts a message-digest computation. + * + * You must call this function after setting up the context + * with mbedtls_md_setup(), and before passing data with + * mbedtls_md_update(). + * + * \param ctx The generic message-digest context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_starts( mbedtls_md_context_t *ctx ); - case 165: -#line 8 "third_party/libpg_query/grammar/statements/pragma.y" - { - PGPragmaStmt *n = makeNode(PGPragmaStmt); - n->kind = PG_PRAGMA_TYPE_NOTHING; - n->name = (yyvsp[(2) - (2)].str); - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief This function feeds an input buffer into an ongoing + * message-digest computation. + * + * You must call mbedtls_md_starts() before calling this + * function. You may call this function multiple times. + * Afterwards, call mbedtls_md_finish(). + * + * \param ctx The generic message-digest context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); - case 166: -#line 15 "third_party/libpg_query/grammar/statements/pragma.y" - { - PGPragmaStmt *n = makeNode(PGPragmaStmt); - n->kind = PG_PRAGMA_TYPE_ASSIGNMENT; - n->name = (yyvsp[(2) - (4)].str); - n->args = (yyvsp[(4) - (4)].list); - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief This function finishes the digest operation, + * and writes the result to the output buffer. + * + * Call this function after a call to mbedtls_md_starts(), + * followed by any number of calls to mbedtls_md_update(). + * Afterwards, you may either clear the context with + * mbedtls_md_free(), or call mbedtls_md_starts() to reuse + * the context for another digest operation with the same + * algorithm. + * + * \param ctx The generic message-digest context. + * \param output The buffer for the generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); - case 167: -#line 23 "third_party/libpg_query/grammar/statements/pragma.y" - { - PGPragmaStmt *n = makeNode(PGPragmaStmt); - n->kind = PG_PRAGMA_TYPE_CALL; - n->name = (yyvsp[(2) - (5)].str); - n->args = (yyvsp[(4) - (5)].list); - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief This function calculates the message-digest of a buffer, + * with respect to a configurable message-digest algorithm + * in a single call. + * + * The result is calculated as + * Output = message_digest(input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ); - case 168: -#line 10 "third_party/libpg_query/grammar/statements/create_sequence.y" - { - PGCreateSeqStmt *n = makeNode(PGCreateSeqStmt); - (yyvsp[(4) - (5)].range)->relpersistence = (yyvsp[(2) - (5)].ival); - n->sequence = (yyvsp[(4) - (5)].range); - n->options = (yyvsp[(5) - (5)].list); - n->ownerId = InvalidOid; - n->onconflict = PG_ERROR_ON_CONFLICT; - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function calculates the message-digest checksum + * result of the contents of the provided file. + * + * The result is calculated as + * Output = message_digest(file contents). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param path The input file name. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_FILE_IO_ERROR on an I/O error accessing + * the file pointed by \p path. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, + unsigned char *output ); +#endif /* MBEDTLS_FS_IO */ - case 169: -#line 20 "third_party/libpg_query/grammar/statements/create_sequence.y" - { - PGCreateSeqStmt *n = makeNode(PGCreateSeqStmt); - (yyvsp[(7) - (8)].range)->relpersistence = (yyvsp[(2) - (8)].ival); - n->sequence = (yyvsp[(7) - (8)].range); - n->options = (yyvsp[(8) - (8)].list); - n->ownerId = InvalidOid; - n->onconflict = PG_IGNORE_ON_CONFLICT; - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief This function sets the HMAC key and prepares to + * authenticate a new message. + * + * Call this function after mbedtls_md_setup(), to use + * the MD context for an HMAC calculation, then call + * mbedtls_md_hmac_update() to provide the input data, and + * mbedtls_md_hmac_finish() to get the HMAC value. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC key in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, + size_t keylen ); - case 170: -#line 32 "third_party/libpg_query/grammar/statements/create_sequence.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; +/** + * \brief This function feeds an input buffer into an ongoing HMAC + * computation. + * + * Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() + * before calling this function. + * You may call this function multiple times to pass the + * input piecewise. + * Afterwards, call mbedtls_md_hmac_finish(). + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, + size_t ilen ); - case 171: -#line 33 "third_party/libpg_query/grammar/statements/create_sequence.y" - { (yyval.list) = NIL; ;} - break; +/** + * \brief This function finishes the HMAC operation, and writes + * the result to the output buffer. + * + * Call this function after mbedtls_md_hmac_starts() and + * mbedtls_md_hmac_update() to get the HMAC value. Afterwards + * you may either call mbedtls_md_free() to clear the context, + * or call mbedtls_md_hmac_reset() to reuse the context with + * the same HMAC key. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param output The generic HMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); - case 172: -#line 8 "third_party/libpg_query/grammar/statements/execute.y" - { - PGExecuteStmt *n = makeNode(PGExecuteStmt); - n->name = (yyvsp[(2) - (3)].str); - n->params = (yyvsp[(3) - (3)].list); - (yyval.node) = (PGNode *) n; - ;} - break; +/** + * \brief This function prepares to authenticate a new message with + * the same key as the previous HMAC operation. + * + * You may call this function after mbedtls_md_hmac_finish(). + * Afterwards call mbedtls_md_hmac_update() to pass the new + * input. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); - case 173: -#line 16 "third_party/libpg_query/grammar/statements/execute.y" - { - PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); - PGExecuteStmt *n = makeNode(PGExecuteStmt); - n->name = (yyvsp[(7) - (9)].str); - n->params = (yyvsp[(8) - (9)].list); - ctas->query = (PGNode *) n; - ctas->into = (yyvsp[(4) - (9)].into); - ctas->relkind = PG_OBJECT_TABLE; - ctas->is_select_into = false; - ctas->onconflict = PG_ERROR_ON_CONFLICT; - /* cram additional flags into the PGIntoClause */ - (yyvsp[(4) - (9)].into)->rel->relpersistence = (yyvsp[(2) - (9)].ival); - (yyvsp[(4) - (9)].into)->skipData = !((yyvsp[(9) - (9)].boolean)); - (yyval.node) = (PGNode *) ctas; - ;} - break; +/** + * \brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The HMAC result is calculated as + * output = generic HMAC(hmac key, input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC secret key in Bytes. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The generic HMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); - case 174: -#line 33 "third_party/libpg_query/grammar/statements/execute.y" - { - PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); - PGExecuteStmt *n = makeNode(PGExecuteStmt); - n->name = (yyvsp[(10) - (12)].str); - n->params = (yyvsp[(11) - (12)].list); - ctas->query = (PGNode *) n; - ctas->into = (yyvsp[(7) - (12)].into); - ctas->relkind = PG_OBJECT_TABLE; - ctas->is_select_into = false; - ctas->onconflict = PG_IGNORE_ON_CONFLICT; - /* cram additional flags into the PGIntoClause */ - (yyvsp[(7) - (12)].into)->rel->relpersistence = (yyvsp[(2) - (12)].ival); - (yyvsp[(7) - (12)].into)->skipData = !((yyvsp[(12) - (12)].boolean)); - (yyval.node) = (PGNode *) ctas; - ;} - break; +/* Internal use */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); - case 175: -#line 51 "third_party/libpg_query/grammar/statements/execute.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} - break; +#ifdef __cplusplus +} +#endif - case 176: -#line 52 "third_party/libpg_query/grammar/statements/execute.y" - { (yyval.list) = NIL; ;} - break; +#endif /* MBEDTLS_MD_H */ - case 177: -#line 10 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - PGAlterSeqStmt *n = makeNode(PGAlterSeqStmt); - n->sequence = (yyvsp[(3) - (4)].range); - n->options = (yyvsp[(4) - (4)].list); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; - case 178: -#line 18 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - PGAlterSeqStmt *n = makeNode(PGAlterSeqStmt); - n->sequence = (yyvsp[(5) - (6)].range); - n->options = (yyvsp[(6) - (6)].list); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; +// LICENSE_CHANGE_END - case 179: -#line 29 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); ;} - break; - case 180: -#line 30 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].defelt)); ;} - break; +#if defined(MBEDTLS_THREADING_C) - case 181: -#line 34 "third_party/libpg_query/grammar/statements/alter_sequence.y" - {;} - break; - case 182: -#line 35 "third_party/libpg_query/grammar/statements/alter_sequence.y" - {;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 183: -#line 36 "third_party/libpg_query/grammar/statements/alter_sequence.y" - {;} - break; +// dummy file to make amalgamantion happy - case 184: -#line 41 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.value) = makeFloat((yyvsp[(1) - (1)].str)); ;} - break; +// LICENSE_CHANGE_END - case 185: -#line 42 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.value) = makeFloat((yyvsp[(2) - (2)].str)); ;} - break; +#endif - case 186: -#line 44 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.value) = makeFloat((yyvsp[(2) - (2)].str)); - doNegateFloat((yyval.value)); - ;} - break; +/* + * RSA Error codes + */ +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 +/** Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 +/** Something failed during generation of a key. */ +#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 +/** Key failed to pass the validity check of the library. */ +#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 +/** The public key operation failed. */ +#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 +/** The private key operation failed. */ +#define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 +/** The PKCS#1 verification failed. */ +#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 +/** The output buffer for decryption is not large enough. */ +#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 +/** The random generator failed to generate non-zeros. */ +#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 - case 187: -#line 48 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.value) = makeInteger((yyvsp[(1) - (1)].ival)); ;} - break; +/* + * RSA constants + */ - case 188: -#line 53 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("as", (PGNode *)(yyvsp[(2) - (2)].typnam), (yylsp[(1) - (2)])); - ;} - break; +#define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS#1 v1.5 encoding. */ +#define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS#1 v2.1 encoding. */ + +#define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ +#define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ + +#define MBEDTLS_RSA_SALT_LEN_ANY -1 + +/* + * The above constants may be used even if the RSA module is compile out, + * eg for alternative (PKCS#11) RSA implemenations in the PK layers. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_RSA_ALT) +// Regular implementation +// + +/** + * \brief The RSA context structure. + */ +typedef struct mbedtls_rsa_context +{ + int MBEDTLS_PRIVATE(ver); /*!< Reserved for internal purposes. + * Do not set this field in application + * code. Its meaning might change without + * notice. */ + size_t MBEDTLS_PRIVATE(len); /*!< The size of \p N in Bytes. */ + + mbedtls_mpi MBEDTLS_PRIVATE(N); /*!< The public modulus. */ + mbedtls_mpi MBEDTLS_PRIVATE(E); /*!< The public exponent. */ + + mbedtls_mpi MBEDTLS_PRIVATE(D); /*!< The private exponent. */ + mbedtls_mpi MBEDTLS_PRIVATE(P); /*!< The first prime factor. */ + mbedtls_mpi MBEDTLS_PRIVATE(Q); /*!< The second prime factor. */ + + mbedtls_mpi MBEDTLS_PRIVATE(DP); /*!< D % (P - 1). */ + mbedtls_mpi MBEDTLS_PRIVATE(DQ); /*!< D % (Q - 1). */ + mbedtls_mpi MBEDTLS_PRIVATE(QP); /*!< 1 / (Q % P). */ + + mbedtls_mpi MBEDTLS_PRIVATE(RN); /*!< cached R^2 mod N. */ + + mbedtls_mpi MBEDTLS_PRIVATE(RP); /*!< cached R^2 mod P. */ + mbedtls_mpi MBEDTLS_PRIVATE(RQ); /*!< cached R^2 mod Q. */ + + mbedtls_mpi MBEDTLS_PRIVATE(Vi); /*!< The cached blinding value. */ + mbedtls_mpi MBEDTLS_PRIVATE(Vf); /*!< The cached un-blinding value. */ + + int MBEDTLS_PRIVATE(padding); /*!< Selects padding mode: + #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ + int MBEDTLS_PRIVATE(hash_id); /*!< Hash identifier of mbedtls_md_type_t type, + as specified in md.h for use in the MGF + mask generating function used in the + EME-OAEP and EMSA-PSS encodings. */ +#if defined(MBEDTLS_THREADING_C) + /* Invariant: the mutex is initialized iff ver != 0. */ + mbedtls_threading_mutex_t MBEDTLS_PRIVATE(mutex); /*!< Thread-safety mutex. */ +#endif +} +mbedtls_rsa_context; + +#else /* MBEDTLS_RSA_ALT */ + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +// dummy file to make amalgamantion happy + +// LICENSE_CHANGE_END + +#endif /* MBEDTLS_RSA_ALT */ + +/** + * \brief This function initializes an RSA context. + * + * \note This function initializes the padding and the hash + * identifier to respectively #MBEDTLS_RSA_PKCS_V15 and + * #MBEDTLS_MD_NONE. See mbedtls_rsa_set_padding() for more + * information about those parameters. + * + * \param ctx The RSA context to initialize. This must not be \c NULL. + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx ); + +/** + * \brief This function sets padding for an already initialized RSA + * context. + * + * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \note The \p hash_id parameter is ignored when using + * #MBEDTLS_RSA_PKCS_V15 padding. + * + * \note The choice of padding mode is strictly enforced for private + * key operations, since there might be security concerns in + * mixing padding modes. For public key operations it is + * a default value, which can be overridden by calling specific + * \c mbedtls_rsa_rsaes_xxx or \c mbedtls_rsa_rsassa_xxx + * functions. + * + * \note The hash selected in \p hash_id is always used for OEAP + * encryption. For PSS signatures, it is always used for + * making signatures, but can be overridden for verifying them. + * If set to #MBEDTLS_MD_NONE, it is always overridden. + * + * \param ctx The initialized RSA context to be configured. + * \param padding The padding mode to use. This must be either + * #MBEDTLS_RSA_PKCS_V15 or #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The hash identifier for PSS or OAEP, if \p padding is + * #MBEDTLS_RSA_PKCS_V21. #MBEDTLS_MD_NONE is accepted by this + * function but may be not suitable for some operations. + * Ignored if \p padding is #MBEDTLS_RSA_PKCS_V15. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_INVALID_PADDING failure: + * \p padding or \p hash_id is invalid. + */ +int mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + mbedtls_md_type_t hash_id ); + +/** + * \brief This function imports a set of core parameters into an + * RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param D The private exponent. This may be \c NULL. + * \param E The public exponent. This may be \c NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ); - case 189: -#line 57 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("cache", (PGNode *)(yyvsp[(2) - (2)].value), (yylsp[(1) - (2)])); - ;} - break; +/** + * \brief This function imports core RSA parameters, in raw big-endian + * binary format, into an RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus. This may be \c NULL. + * \param N_len The Byte length of \p N; it is ignored if \p N == NULL. + * \param P The first prime factor of \p N. This may be \c NULL. + * \param P_len The Byte length of \p P; it ns ignored if \p P == NULL. + * \param Q The second prime factor of \p N. This may be \c NULL. + * \param Q_len The Byte length of \p Q; it is ignored if \p Q == NULL. + * \param D The private exponent. This may be \c NULL. + * \param D_len The Byte length of \p D; it is ignored if \p D == NULL. + * \param E The public exponent. This may be \c NULL. + * \param E_len The Byte length of \p E; it is ignored if \p E == NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ); - case 190: -#line 61 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("cycle", (PGNode *)makeInteger(true), (yylsp[(1) - (1)])); - ;} - break; +/** + * \brief This function completes an RSA context from + * a set of imported core parameters. + * + * To setup an RSA public key, precisely \p N and \p E + * must have been imported. + * + * To setup an RSA private key, sufficient information must + * be present for the other parameters to be derivable. + * + * The default implementation supports the following: + *

  • Derive \p P, \p Q from \p N, \p D, \p E.
  • + *
  • Derive \p N, \p D from \p P, \p Q, \p E.
+ * Alternative implementations need not support these. + * + * If this function runs successfully, it guarantees that + * the RSA context can be used for RSA operations without + * the risk of failure or crash. + * + * \warning This function need not perform consistency checks + * for the imported parameters. In particular, parameters that + * are not needed by the implementation might be silently + * discarded and left unchecked. To check the consistency + * of the key material, see mbedtls_rsa_check_privkey(). + * + * \param ctx The initialized RSA context holding imported parameters. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the attempted derivations + * failed. + * + */ +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); - case 191: -#line 65 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("cycle", (PGNode *)makeInteger(false), (yylsp[(1) - (2)])); - ;} - break; +/** + * \brief This function exports the core parameters of an RSA key. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * + * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The MPI to hold the RSA modulus. + * This may be \c NULL if this field need not be exported. + * \param P The MPI to hold the first prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param Q The MPI to hold the second prime factor of \p N. + * This may be \c NULL if this field need not be exported. + * \param D The MPI to hold the private exponent. + * This may be \c NULL if this field need not be exported. + * \param E The MPI to hold the public exponent. + * This may be \c NULL if this field need not be exported. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + * + */ +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ); - case 192: -#line 69 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("increment", (PGNode *)(yyvsp[(3) - (3)].value), (yylsp[(1) - (3)])); - ;} - break; +/** + * \brief This function exports core parameters of an RSA key + * in raw big-endian binary format. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \note The length parameters are ignored if the corresponding + * buffer pointers are NULL. + * + * \param ctx The initialized RSA context. + * \param N The Byte array to store the RSA modulus, + * or \c NULL if this field need not be exported. + * \param N_len The size of the buffer for the modulus. + * \param P The Byte array to hold the first prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param P_len The size of the buffer for the first prime factor. + * \param Q The Byte array to hold the second prime factor of \p N, + * or \c NULL if this field need not be exported. + * \param Q_len The size of the buffer for the second prime factor. + * \param D The Byte array to hold the private exponent, + * or \c NULL if this field need not be exported. + * \param D_len The size of the buffer for the private exponent. + * \param E The Byte array to hold the public exponent, + * or \c NULL if this field need not be exported. + * \param E_len The size of the buffer for the public exponent. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + */ +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ); - case 193: -#line 73 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("maxvalue", (PGNode *)(yyvsp[(2) - (2)].value), (yylsp[(1) - (2)])); - ;} - break; +/** + * \brief This function exports CRT parameters of a private RSA key. + * + * \note Alternative RSA implementations not using CRT-parameters + * internally can implement this function based on + * mbedtls_rsa_deduce_opt(). + * + * \param ctx The initialized RSA context. + * \param DP The MPI to hold \c D modulo `P-1`, + * or \c NULL if it need not be exported. + * \param DQ The MPI to hold \c D modulo `Q-1`, + * or \c NULL if it need not be exported. + * \param QP The MPI to hold modular inverse of \c Q modulo \c P, + * or \c NULL if it need not be exported. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + * + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ); - case 194: -#line 77 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("minvalue", (PGNode *)(yyvsp[(2) - (2)].value), (yylsp[(1) - (2)])); - ;} - break; +/** + * \brief This function retrieves the length of RSA modulus in Bytes. + * + * \param ctx The initialized RSA context. + * + * \return The length of the RSA modulus in Bytes. + * + */ +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ); - case 195: -#line 81 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("maxvalue", NULL, (yylsp[(1) - (2)])); - ;} - break; +/** + * \brief This function generates an RSA keypair. + * + * \note mbedtls_rsa_init() must be called before this function, + * to set up the RSA context. + * + * \param ctx The initialized RSA context used to hold the key. + * \param f_rng The RNG function to be used for key generation. + * This is mandatory and must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. + * This may be \c NULL if \p f_rng doesn't need a context. + * \param nbits The size of the public key in bits. + * \param exponent The public exponent to use. For example, \c 65537. + * This must be odd and greater than \c 1. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); - case 196: -#line 85 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("minvalue", NULL, (yylsp[(1) - (2)])); - ;} - break; +/** + * \brief This function checks if a context contains at least an RSA + * public key. + * + * If the function runs successfully, it is guaranteed that + * enough information is present to perform an RSA public key + * operation using mbedtls_rsa_public(). + * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); - case 197: -#line 89 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("owned_by", (PGNode *)(yyvsp[(3) - (3)].list), (yylsp[(1) - (3)])); - ;} - break; +/** + * \brief This function checks if a context contains an RSA private key + * and perform basic consistency checks. + * + * \note The consistency checks performed by this function not only + * ensure that mbedtls_rsa_private() can be called successfully + * on the given context, but that the various parameters are + * mutually consistent with high probability, in the sense that + * mbedtls_rsa_public() and mbedtls_rsa_private() are inverses. + * + * \warning This function should catch accidental misconfigurations + * like swapping of parameters, but it cannot establish full + * trust in neither the quality nor the consistency of the key + * material that was used to setup the given RSA context: + *
  • Consistency: Imported parameters that are irrelevant + * for the implementation might be silently dropped. If dropped, + * the current function does not have access to them, + * and therefore cannot check them. See mbedtls_rsa_complete(). + * If you want to check the consistency of the entire + * content of an PKCS1-encoded RSA private key, for example, you + * should use mbedtls_rsa_validate_params() before setting + * up the RSA context. + * Additionally, if the implementation performs empirical checks, + * these checks substantiate but do not guarantee consistency.
  • + *
  • Quality: This function is not expected to perform + * extended quality assessments like checking that the prime + * factors are safe. Additionally, it is the responsibility of the + * user to ensure the trustworthiness of the source of his RSA + * parameters, which goes beyond what is effectively checkable + * by the library.
+ * + * \param ctx The initialized RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); - case 198: -#line 93 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - /* not documented, only used by pg_dump */ - (yyval.defelt) = makeDefElem("sequence_name", (PGNode *)(yyvsp[(3) - (3)].list), (yylsp[(1) - (3)])); - ;} - break; +/** + * \brief This function checks a public-private RSA key pair. + * + * It checks each of the contexts, and makes sure they match. + * + * \param pub The initialized RSA context holding the public key. + * \param prv The initialized RSA context holding the private key. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ); - case 199: -#line 98 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("start", (PGNode *)(yyvsp[(3) - (3)].value), (yylsp[(1) - (3)])); - ;} - break; +/** + * \brief This function performs an RSA public key operation. + * + * \param ctx The initialized RSA context to use. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \note This function does not handle message padding. + * + * \note Make sure to set \p input[0] = 0 or ensure that + * input is smaller than \p N. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); - case 200: -#line 102 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("restart", NULL, (yylsp[(1) - (1)])); - ;} - break; +/** + * \brief This function performs an RSA private key operation. + * + * \note Blinding is used if and only if a PRNG is provided. + * + * \note If blinding is used, both the base of exponentation + * and the exponent are blinded, providing protection + * against some side-channel attacks. + * + * \warning It is deprecated and a security risk to not provide + * a PRNG here and thereby prevent the use of blinding. + * Future versions of the library may enforce the presence + * of a PRNG. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function, used for blinding. It is mandatory. + * \param p_rng The RNG context to pass to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context. + * \param input The input buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ); - case 201: -#line 106 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { - (yyval.defelt) = makeDefElem("restart", (PGNode *)(yyvsp[(3) - (3)].value), (yylsp[(1) - (3)])); - ;} - break; +/** + * \brief This function adds the message padding, then performs an RSA + * operation. + * + * It is the generic wrapper for performing a PKCS#1 encryption + * operation. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG to use. It is used for padding generation + * and it is mandatory. + * \param p_rng The RNG context to be passed to \p f_rng. May be + * \c NULL if \p f_rng doesn't need a context argument. + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t ilen, + const unsigned char *input, + unsigned char *output ); - case 202: -#line 112 "third_party/libpg_query/grammar/statements/alter_sequence.y" - {;} - break; +/** + * \brief This function performs a PKCS#1 v1.5 encryption operation + * (RSAES-PKCS1-v1_5-ENCRYPT). + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. It is mandatory and used for + * padding generation. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * \param ilen The length of the plaintext in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t ilen, + const unsigned char *input, + unsigned char *output ); - case 203: -#line 113 "third_party/libpg_query/grammar/statements/alter_sequence.y" - {;} - break; +/** + * \brief This function performs a PKCS#1 v2.1 OAEP encryption + * operation (RSAES-OAEP-ENCRYPT). + * + * \note The output buffer must be as large as the size + * of ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \param ctx The initnialized RSA context to use. + * \param f_rng The RNG function to use. This is needed for padding + * generation and is mandatory. + * \param p_rng The RNG context to be passed to \p f_rng. This may + * be \c NULL if \p f_rng doesn't need a context argument. + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param ilen The length of the plaintext buffer \p input in Bytes. + * \param input The input data to encrypt. This must be a readable + * buffer of size \p ilen Bytes. It may be \c NULL if + * `ilen == 0`. + * \param output The output buffer. This must be a writable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ); - case 204: -#line 117 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;} - break; +/** + * \brief This function performs an RSA operation, then removes the + * message padding. + * + * It is the generic wrapper for performing a PKCS#1 decryption + * operation. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N (for example, + * 128 Bytes if RSA-1024 is used) to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory; see mbedtls_rsa_private() for more. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context. + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); - case 205: -#line 118 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.ival) = + (yyvsp[(2) - (2)].ival); ;} - break; +/** + * \brief This function performs a PKCS#1 v1.5 decryption + * operation (RSAES-PKCS1-v1_5-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for example, + * 128 Bytes if RSA-1024 is used, to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory; see mbedtls_rsa_private() for more. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context. + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); - case 206: -#line 119 "third_party/libpg_query/grammar/statements/alter_sequence.y" - { (yyval.ival) = - (yyvsp[(2) - (2)].ival); ;} - break; +/** + * \brief This function performs a PKCS#1 v2.1 OAEP decryption + * operation (RSAES-OAEP-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for + * example, 128 Bytes if RSA-1024 is used, to be able to + * hold an arbitrary decrypted message. If it is not + * large enough to hold the decryption of the particular + * ciphertext provided, the function returns + * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory. + * \param p_rng The RNG context to be passed to \p f_rng. This may be + * \c NULL if \p f_rng doesn't need a context. + * \param label The buffer holding the custom label to use. + * This must be a readable buffer of length \p label_len + * Bytes. It may be \c NULL if \p label_len is \c 0. + * \param label_len The length of the label in Bytes. + * \param olen The address at which to store the length of + * the plaintext. This must not be \c NULL. + * \param input The ciphertext buffer. This must be a readable buffer + * of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * \param output The buffer used to hold the plaintext. This must + * be a writable buffer of length \p output_max_len Bytes. + * \param output_max_len The length in Bytes of the output buffer \p output. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); - case 207: -#line 3 "third_party/libpg_query/grammar/statements/transaction.y" - { - PGTransactionStmt *n = makeNode(PGTransactionStmt); - n->kind = PG_TRANS_STMT_ROLLBACK; - n->options = NIL; - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief This function performs a private RSA operation to sign + * a message digest using PKCS#1. + * + * It is the generic wrapper for performing a PKCS#1 + * signature. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_sign() for details on + * \p md_alg and \p hash_id. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function to use. This is mandatory and + * must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); - case 208: -#line 10 "third_party/libpg_query/grammar/statements/transaction.y" - { - PGTransactionStmt *n = makeNode(PGTransactionStmt); - n->kind = PG_TRANS_STMT_BEGIN; - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief This function performs a PKCS#1 v1.5 signature + * operation (RSASSA-PKCS1-v1_5-SIGN). + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. This is used for blinding and is + * mandatory; see mbedtls_rsa_private() for more. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); - case 209: -#line 16 "third_party/libpg_query/grammar/statements/transaction.y" - { - PGTransactionStmt *n = makeNode(PGTransactionStmt); - n->kind = PG_TRANS_STMT_START; - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). + * + * \note The \c hash_id set in \p ctx by calling + * mbedtls_rsa_set_padding() selects the hash used for the + * encoding operation and for the mask generation function + * (MGF1). For more details on the encoding operation and the + * mask generation function, consult RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications. + * + * \note This function enforces that the provided salt length complies + * with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 v2.2) §9.1.1 + * step 3. The constraint is that the hash length plus the salt + * length plus 2 bytes must be at most the key length. If this + * constraint is not met, this function returns + * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. It is mandatory and must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param saltlen The length of the salt that should be used. + * If passed #MBEDTLS_RSA_SALT_LEN_ANY, the function will use + * the largest possible salt length up to the hash length, + * which is the largest permitted by some standards including + * FIPS 186-4 §5.5. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_sign_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + int saltlen, + unsigned char *sig ); - case 210: -#line 22 "third_party/libpg_query/grammar/statements/transaction.y" - { - PGTransactionStmt *n = makeNode(PGTransactionStmt); - n->kind = PG_TRANS_STMT_COMMIT; - n->options = NIL; - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). + * + * \note The \c hash_id set in \p ctx by calling + * mbedtls_rsa_set_padding() selects the hash used for the + * encoding operation and for the mask generation function + * (MGF1). For more details on the encoding operation and the + * mask generation function, consult RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications. + * + * \note This function always uses the maximum possible salt size, + * up to the length of the payload hash. This choice of salt + * size complies with FIPS 186-4 §5.5 (e) and RFC 8017 (PKCS#1 + * v2.2) §9.1.1 step 3. Furthermore this function enforces a + * minimum salt size which is the hash size minus 2 bytes. If + * this minimum size is too large given the key size (the salt + * size, plus the hash size, plus 2 bytes must be no more than + * the key size in bytes), this function returns + * #MBEDTLS_ERR_RSA_BAD_INPUT_DATA. + * + * \param ctx The initialized RSA context to use. + * \param f_rng The RNG function. It is mandatory and must not be \c NULL. + * \param p_rng The RNG context to be passed to \p f_rng. This may be \c NULL + * if \p f_rng doesn't need a context argument. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param sig The buffer to hold the signature. This must be a writable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. A buffer length of + * #MBEDTLS_MPI_MAX_SIZE is always safe. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); - case 211: -#line 29 "third_party/libpg_query/grammar/statements/transaction.y" - { - PGTransactionStmt *n = makeNode(PGTransactionStmt); - n->kind = PG_TRANS_STMT_COMMIT; - n->options = NIL; - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief This function performs a public RSA operation and checks + * the message digest. + * + * This is the generic wrapper for performing a PKCS#1 + * verification. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and + * \p hash_id. + * + * \param ctx The initialized RSA public key context to use. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); - case 212: -#line 36 "third_party/libpg_query/grammar/statements/transaction.y" - { - PGTransactionStmt *n = makeNode(PGTransactionStmt); - n->kind = PG_TRANS_STMT_ROLLBACK; - n->options = NIL; - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief This function performs a PKCS#1 v1.5 verification + * operation (RSASSA-PKCS1-v1_5-VERIFY). + * + * \param ctx The initialized RSA public key context to use. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); - case 213: -#line 45 "third_party/libpg_query/grammar/statements/transaction.y" - {;} - break; +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * \note The \c hash_id set in \p ctx by calling + * mbedtls_rsa_set_padding() selects the hash used for the + * encoding operation and for the mask generation function + * (MGF1). For more details on the encoding operation and the + * mask generation function, consult RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications. If the \c hash_id set in \p ctx by + * mbedtls_rsa_set_padding() is #MBEDTLS_MD_NONE, the \p md_alg + * parameter is used. + * + * \param ctx The initialized RSA public key context to use. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); - case 214: -#line 46 "third_party/libpg_query/grammar/statements/transaction.y" - {;} - break; +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \c hash_id set in \p ctx by mbedtls_rsa_set_padding() is + * ignored. + * + * \param ctx The initialized RSA public key context to use. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest or raw data in Bytes. + * If \p md_alg is not #MBEDTLS_MD_NONE, this must match the + * output length of the corresponding hash algorithm. + * \param hash The buffer holding the message digest or raw data. + * This must be a readable buffer of at least \p hashlen Bytes. + * \param mgf1_hash_id The message digest algorithm used for the + * verification operation and the mask generation + * function (MGF1). For more details on the encoding + * operation and the mask generation function, consult + * RFC-3447: Public-Key Cryptography Standards + * (PKCS) #1 v2.1: RSA Cryptography + * Specifications. + * \param expected_salt_len The length of the salt used in padding. Use + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * \param sig The buffer holding the signature. This must be a readable + * buffer of length \c ctx->len Bytes. For example, \c 256 Bytes + * for an 2048-bit RSA modulus. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ); - case 215: -#line 47 "third_party/libpg_query/grammar/statements/transaction.y" - {;} - break; +/** + * \brief This function copies the components of an RSA context. + * + * \param dst The destination context. This must be initialized. + * \param src The source context. This must be initialized. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); - case 216: -#line 9 "third_party/libpg_query/grammar/statements/create.y" - { - PGCreateStmt *n = makeNode(PGCreateStmt); - (yyvsp[(4) - (9)].range)->relpersistence = (yyvsp[(2) - (9)].ival); - n->relation = (yyvsp[(4) - (9)].range); - n->tableElts = (yyvsp[(6) - (9)].list); - n->ofTypename = NULL; - n->constraints = NIL; - n->options = (yyvsp[(8) - (9)].list); - n->oncommit = (yyvsp[(9) - (9)].oncommit); - n->onconflict = PG_ERROR_ON_CONFLICT; - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief This function frees the components of an RSA key. + * + * \param ctx The RSA context to free. May be \c NULL, in which case + * this function is a no-op. If it is not \c NULL, it must + * point to an initialized RSA context. + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); - case 217: -#line 24 "third_party/libpg_query/grammar/statements/create.y" - { - PGCreateStmt *n = makeNode(PGCreateStmt); - (yyvsp[(7) - (12)].range)->relpersistence = (yyvsp[(2) - (12)].ival); - n->relation = (yyvsp[(7) - (12)].range); - n->tableElts = (yyvsp[(9) - (12)].list); - n->ofTypename = NULL; - n->constraints = NIL; - n->options = (yyvsp[(11) - (12)].list); - n->oncommit = (yyvsp[(12) - (12)].oncommit); - n->onconflict = PG_IGNORE_ON_CONFLICT; - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(MBEDTLS_SELF_TEST) - case 218: -#line 39 "third_party/libpg_query/grammar/statements/create.y" - { - PGCreateStmt *n = makeNode(PGCreateStmt); - (yyvsp[(6) - (11)].range)->relpersistence = (yyvsp[(4) - (11)].ival); - n->relation = (yyvsp[(6) - (11)].range); - n->tableElts = (yyvsp[(8) - (11)].list); - n->ofTypename = NULL; - n->constraints = NIL; - n->options = (yyvsp[(10) - (11)].list); - n->oncommit = (yyvsp[(11) - (11)].oncommit); - n->onconflict = PG_REPLACE_ON_CONFLICT; - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief The RSA checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_rsa_self_test( int verbose ); - case 219: -#line 56 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = 0; ;} - break; +#endif /* MBEDTLS_SELF_TEST */ - case 220: -#line 58 "third_party/libpg_query/grammar/statements/create.y" - { - /* - * We must complain about conflicting options. - * We could, but choose not to, complain about redundant - * options (ie, where $2's bit is already set in $1). - */ - int newspec = (yyvsp[(1) - (2)].ival) | (yyvsp[(2) - (2)].ival); +#ifdef __cplusplus +} +#endif - /* special message for this case */ - if ((newspec & (CAS_NOT_DEFERRABLE | CAS_INITIALLY_DEFERRED)) == (CAS_NOT_DEFERRABLE | CAS_INITIALLY_DEFERRED)) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("constraint declared INITIALLY DEFERRED must be DEFERRABLE"), - parser_errposition((yylsp[(2) - (2)])))); - /* generic message for other conflicts */ - if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE) || - (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("conflicting constraint properties"), - parser_errposition((yylsp[(2) - (2)])))); - (yyval.ival) = newspec; - ;} - break; +#endif /* rsa.h */ - case 221: -#line 84 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *)(yyvsp[(1) - (1)].typnam); ;} - break; - case 222: -#line 85 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *)makeString(pstrdup((yyvsp[(1) - (1)].keyword))); ;} - break; +// LICENSE_CHANGE_END - case 223: -#line 86 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *)(yyvsp[(1) - (1)].list); ;} - break; +#endif - case 224: -#line 87 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *)(yyvsp[(1) - (1)].value); ;} - break; +#if defined(MBEDTLS_BASE64_C) - case 225: -#line 88 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *)makeString((yyvsp[(1) - (1)].str)); ;} - break; - case 226: -#line 89 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *)makeString(pstrdup((yyvsp[(1) - (1)].keyword))); ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 227: -#line 93 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} - break; +/** + * \file constant_time_invasive.h + * + * \brief Constant-time module: interfaces for invasive testing only. + * + * The interfaces in this file are intended for testing purposes only. + * They SHOULD NOT be made available in library integrations except when + * building the library for testing. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - case 228: -#line 94 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = NIL; ;} - break; +#ifndef MBEDTLS_CONSTANT_TIME_INVASIVE_H +#define MBEDTLS_CONSTANT_TIME_INVASIVE_H - case 229: -#line 99 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); ;} - break; - case 230: -#line 104 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_FKCONSTR_ACTION_NOACTION; ;} - break; - case 231: -#line 105 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_FKCONSTR_ACTION_RESTRICT; ;} - break; +#if defined(MBEDTLS_TEST_HOOKS) - case 232: -#line 106 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_FKCONSTR_ACTION_CASCADE; ;} - break; +/** Turn a value into a mask: + * - if \p low <= \p c <= \p high, + * return the all-bits 1 mask, aka (unsigned) -1 + * - otherwise, return the all-bits 0 mask, aka 0 + * + * \param low The value to analyze. + * \param high The value to analyze. + * \param c The value to analyze. + * + * \return All-bits-one if \p low <= \p c <= \p high, otherwise zero. + */ +unsigned char mbedtls_ct_uchar_mask_of_range( unsigned char low, + unsigned char high, + unsigned char c ); - case 233: -#line 107 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_FKCONSTR_ACTION_SETNULL; ;} - break; +#endif /* MBEDTLS_TEST_HOOKS */ - case 234: -#line 108 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_FKCONSTR_ACTION_SETDEFAULT; ;} - break; +#endif /* MBEDTLS_CONSTANT_TIME_INVASIVE_H */ - case 235: -#line 114 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = castNode(PGConstraint, (yyvsp[(3) - (3)].node)); - n->conname = (yyvsp[(2) - (3)].str); - n->location = (yylsp[(1) - (3)]); - (yyval.node) = (PGNode *) n; - ;} - break; - case 236: -#line 120 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +// LICENSE_CHANGE_END - case 237: -#line 121 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +#endif - case 238: -#line 123 "third_party/libpg_query/grammar/statements/create.y" - { - /* - * Note: the PGCollateClause is momentarily included in - * the list built by ColQualList, but we split it out - * again in SplitColQualList. - */ - PGCollateClause *n = makeNode(PGCollateClause); - n->arg = NULL; - n->collname = (yyvsp[(2) - (2)].list); - n->location = (yylsp[(1) - (2)]); - (yyval.node) = (PGNode *) n; - ;} - break; +#include - case 239: -#line 140 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_NOTNULL; - n->location = (yylsp[(1) - (2)]); - (yyval.node) = (PGNode *)n; - ;} - break; +int mbedtls_ct_memcmp( const void *a, + const void *b, + size_t n ) +{ + size_t i; + volatile const unsigned char *A = (volatile const unsigned char *) a; + volatile const unsigned char *B = (volatile const unsigned char *) b; + volatile unsigned char diff = 0; - case 240: -#line 147 "third_party/libpg_query/grammar/statements/create.y" + for( i = 0; i < n; i++ ) { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_NULL; - n->location = (yylsp[(1) - (1)]); - (yyval.node) = (PGNode *)n; - ;} - break; + /* Read volatile data in order before computing diff. + * This avoids IAR compiler warning: + * 'the order of volatile accesses is undefined ..' */ + unsigned char x = A[i], y = B[i]; + diff |= x ^ y; + } - case 241: -#line 154 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_UNIQUE; - n->location = (yylsp[(1) - (2)]); - n->keys = NULL; - n->options = (yyvsp[(2) - (2)].list); - n->indexname = NULL; - (yyval.node) = (PGNode *)n; - ;} - break; + return( (int)diff ); +} - case 242: -#line 164 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_PRIMARY; - n->location = (yylsp[(1) - (3)]); - n->keys = NULL; - n->options = (yyvsp[(3) - (3)].list); - n->indexname = NULL; - (yyval.node) = (PGNode *)n; - ;} - break; +unsigned mbedtls_ct_uint_mask( unsigned value ) +{ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} - case 243: -#line 174 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_CHECK; - n->location = (yylsp[(1) - (5)]); - n->is_no_inherit = (yyvsp[(5) - (5)].boolean); - n->raw_expr = (yyvsp[(3) - (5)].node); - n->cooked_expr = NULL; - n->skip_validation = false; - n->initially_valid = true; - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) - case 244: -#line 186 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_COMPRESSION; - n->location = (yylsp[(1) - (3)]); - n->compression_name = (yyvsp[(3) - (3)].str); - (yyval.node) = (PGNode *)n; - ;} - break; +size_t mbedtls_ct_size_mask( size_t value ) +{ + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} - case 245: -#line 194 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_DEFAULT; - n->location = (yylsp[(1) - (2)]); - n->raw_expr = (yyvsp[(2) - (2)].node); - n->cooked_expr = NULL; - (yyval.node) = (PGNode *)n; - ;} - break; +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ - case 246: -#line 203 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_FOREIGN; - n->location = (yylsp[(1) - (5)]); - n->pktable = (yyvsp[(2) - (5)].range); - n->fk_attrs = NIL; - n->pk_attrs = (yyvsp[(3) - (5)].list); - n->fk_matchtype = (yyvsp[(4) - (5)].ival); - n->fk_upd_action = (char) ((yyvsp[(5) - (5)].ival) >> 8); - n->fk_del_action = (char) ((yyvsp[(5) - (5)].ival) & 0xFF); - n->skip_validation = false; - n->initially_valid = true; - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(MBEDTLS_BIGNUM_C) - case 247: -#line 220 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.constr) = PG_CONSTR_GENERATED_VIRTUAL; ;} - break; +mbedtls_mpi_uint mbedtls_ct_mpi_uint_mask( mbedtls_mpi_uint value ) +{ + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + return( - ( ( value | - value ) >> ( sizeof( value ) * 8 - 1 ) ) ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif +} - case 248: -#line 221 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.constr) = PG_CONSTR_GENERATED_STORED; ;} - break; +#endif /* MBEDTLS_BIGNUM_C */ - case 249: -#line 225 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.constr) = (yyvsp[(1) - (1)].constr) ;} - break; +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) - case 250: -#line 226 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.constr) = PG_CONSTR_GENERATED_VIRTUAL; ;} - break; +/** Constant-flow mask generation for "less than" comparison: + * - if \p x < \p y, return all-bits 1, that is (size_t) -1 + * - otherwise, return all bits 0, that is 0 + * + * This function can be used to write constant-time code by replacing branches + * with bit operations using masks. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return All-bits-one if \p x is less than \p y, otherwise zero. + */ +static size_t mbedtls_ct_size_mask_lt( size_t x, + size_t y ) +{ + /* This has the most significant bit set if and only if x < y */ + const size_t sub = x - y; - case 251: -#line 231 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_IDENTITY; - n->generated_when = (yyvsp[(2) - (5)].ival); - n->options = (yyvsp[(5) - (5)].list); - n->location = (yylsp[(1) - (5)]); - (yyval.node) = (PGNode *)n; - ;} - break; + /* sub1 = (x < y) ? 1 : 0 */ + const size_t sub1 = sub >> ( sizeof( sub ) * 8 - 1 ); - case 252: -#line 240 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = (yyvsp[(7) - (7)].constr); - n->generated_when = (yyvsp[(2) - (7)].ival); - n->raw_expr = (yyvsp[(5) - (7)].node); - n->cooked_expr = NULL; - n->location = (yylsp[(1) - (7)]); + /* mask = (x < y) ? 0xff... : 0x00... */ + const size_t mask = mbedtls_ct_size_mask( sub1 ); - /* - * Can't do this in the grammar because of shift/reduce - * conflicts. (IDENTITY allows both ALWAYS and BY - * DEFAULT, but generated columns only allow ALWAYS.) We - * can also give a more useful error message and location. - */ - if ((yyvsp[(2) - (7)].ival) != PG_ATTRIBUTE_IDENTITY_ALWAYS) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("for a generated column, GENERATED ALWAYS must be specified"), - parser_errposition((yylsp[(2) - (7)])))); + return( mask ); +} - (yyval.node) = (PGNode *)n; - ;} - break; +size_t mbedtls_ct_size_mask_ge( size_t x, + size_t y ) +{ + return( ~mbedtls_ct_size_mask_lt( x, y ) ); +} - case 253: -#line 263 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = (yyvsp[(5) - (5)].constr); - n->generated_when = PG_ATTRIBUTE_IDENTITY_ALWAYS; - n->raw_expr = (yyvsp[(3) - (5)].node); - n->cooked_expr = NULL; - n->location = (yylsp[(1) - (5)]); - (yyval.node) = (PGNode *)n; - ;} - break; +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ - case 254: -#line 277 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); - ;} - break; +#if defined(MBEDTLS_BASE64_C) - case 255: -#line 283 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = (yyvsp[(3) - (3)].ival); ;} - break; +/* Return 0xff if low <= c <= high, 0 otherwise. + * + * Constant flow with respect to c. + */ +MBEDTLS_STATIC_TESTABLE +unsigned char mbedtls_ct_uchar_mask_of_range( unsigned char low, + unsigned char high, + unsigned char c ) +{ + /* low_mask is: 0 if low <= c, 0x...ff if low > c */ + unsigned low_mask = ( (unsigned) c - low ) >> 8; + /* high_mask is: 0 if c <= high, 0x...ff if c > high */ + unsigned high_mask = ( (unsigned) high - c ) >> 8; + return( ~( low_mask | high_mask ) & 0xff ); +} - case 256: -#line 289 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = ((yyvsp[(1) - (1)].ival) << 8) | (PG_FKCONSTR_ACTION_NOACTION & 0xFF); ;} - break; +#endif /* MBEDTLS_BASE64_C */ - case 257: -#line 291 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = (PG_FKCONSTR_ACTION_NOACTION << 8) | ((yyvsp[(1) - (1)].ival) & 0xFF); ;} - break; +unsigned mbedtls_ct_size_bool_eq( size_t x, + size_t y ) +{ + /* diff = 0 if x == y, non-zero otherwise */ + const size_t diff = x ^ y; - case 258: -#line 293 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = ((yyvsp[(1) - (2)].ival) << 8) | ((yyvsp[(2) - (2)].ival) & 0xFF); ;} - break; + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif - case 259: -#line 295 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = ((yyvsp[(2) - (2)].ival) << 8) | ((yyvsp[(1) - (2)].ival) & 0xFF); ;} - break; + /* diff_msb's most significant bit is equal to x != y */ + const size_t diff_msb = ( diff | (size_t) -diff ); - case 260: -#line 297 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = (PG_FKCONSTR_ACTION_NOACTION << 8) | (PG_FKCONSTR_ACTION_NOACTION & 0xFF); ;} - break; +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif - case 261: -#line 300 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.oncommit) = ONCOMMIT_DROP; ;} - break; + /* diff1 = (x != y) ? 1 : 0 */ + const unsigned diff1 = diff_msb >> ( sizeof( diff_msb ) * 8 - 1 ); - case 262: -#line 301 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.oncommit) = PG_ONCOMMIT_DELETE_ROWS; ;} - break; + return( 1 ^ diff1 ); +} - case 263: -#line 302 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.oncommit) = PG_ONCOMMIT_PRESERVE_ROWS; ;} - break; +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) - case 264: -#line 303 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.oncommit) = PG_ONCOMMIT_NOOP; ;} - break; +/** Constant-flow "greater than" comparison: + * return x > y + * + * This is equivalent to \p x > \p y, but is likely to be compiled + * to code using bitwise operation rather than a branch. + * + * \param x The first value to analyze. + * \param y The second value to analyze. + * + * \return 1 if \p x greater than \p y, otherwise 0. + */ +static unsigned mbedtls_ct_size_gt( size_t x, + size_t y ) +{ + /* Return the sign bit (1 for negative) of (y - x). */ + return( ( y - x ) >> ( sizeof( size_t ) * 8 - 1 ) ); +} - case 265: -#line 308 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} - break; +#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ - case 266: -#line 312 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.boolean) = true; ;} - break; +#if defined(MBEDTLS_BIGNUM_C) - case 267: -#line 313 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.boolean) = false; ;} - break; +unsigned mbedtls_ct_mpi_uint_lt( const mbedtls_mpi_uint x, + const mbedtls_mpi_uint y ) +{ + mbedtls_mpi_uint ret; + mbedtls_mpi_uint cond; - case 268: -#line 319 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = castNode(PGConstraint, (yyvsp[(3) - (3)].node)); - n->conname = (yyvsp[(2) - (3)].str); - n->location = (yylsp[(1) - (3)]); - (yyval.node) = (PGNode *) n; - ;} - break; + /* + * Check if the most significant bits (MSB) of the operands are different. + */ + cond = ( x ^ y ); + /* + * If the MSB are the same then the difference x-y will be negative (and + * have its MSB set to 1 during conversion to unsigned) if and only if x> ( sizeof( mbedtls_mpi_uint ) * 8 - 1 ); - case 271: -#line 331 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_CONSTRAINTS; ;} - break; + return (unsigned) ret; +} - case 272: -#line 332 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_DEFAULTS; ;} - break; +#endif /* MBEDTLS_BIGNUM_C */ - case 273: -#line 333 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_IDENTITY; ;} - break; +unsigned mbedtls_ct_uint_if( unsigned condition, + unsigned if1, + unsigned if0 ) +{ + unsigned mask = mbedtls_ct_uint_mask( condition ); + return( ( mask & if1 ) | (~mask & if0 ) ); +} - case 274: -#line 334 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_INDEXES; ;} - break; +#if defined(MBEDTLS_BIGNUM_C) - case 275: -#line 335 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_STATISTICS; ;} - break; +/** Select between two sign values without branches. + * + * This is functionally equivalent to `condition ? if1 : if0` but uses only bit + * operations in order to avoid branches. + * + * \note if1 and if0 must be either 1 or -1, otherwise the result + * is undefined. + * + * \param condition Condition to test. + * \param if1 The first sign; must be either +1 or -1. + * \param if0 The second sign; must be either +1 or -1. + * + * \return \c if1 if \p condition is nonzero, otherwise \c if0. + * */ +static int mbedtls_ct_cond_select_sign( unsigned char condition, + int if1, + int if0 ) +{ + /* In order to avoid questions about what we can reasonably assume about + * the representations of signed integers, move everything to unsigned + * by taking advantage of the fact that if1 and if0 are either +1 or -1. */ + unsigned uif1 = if1 + 1; + unsigned uif0 = if0 + 1; - case 276: -#line 336 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_STORAGE; ;} - break; + /* condition was 0 or 1, mask is 0 or 2 as are uif1 and uif0 */ + const unsigned mask = condition << 1; - case 277: -#line 337 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_CREATE_TABLE_LIKE_ALL; ;} - break; + /* select uif1 or uif0 */ + unsigned ur = ( uif0 & ~mask ) | ( uif1 & mask ); - case 278: -#line 343 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); ;} - break; + /* ur is now 0 or 2, convert back to -1 or +1 */ + return( (int) ur - 1 ); +} - case 279: -#line 344 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); ;} - break; +void mbedtls_ct_mpi_uint_cond_assign( size_t n, + mbedtls_mpi_uint *dest, + const mbedtls_mpi_uint *src, + unsigned char condition ) +{ + size_t i; - case 280: -#line 348 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.str) = (yyvsp[(3) - (3)].str); ;} - break; + /* MSVC has a warning about unary minus on unsigned integer types, + * but this is well-defined and precisely what we want to do here. */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif - case 281: -#line 354 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_ATTR_DEFERRABLE; - n->location = (yylsp[(1) - (1)]); - (yyval.node) = (PGNode *)n; - ;} - break; + /* all-bits 1 if condition is 1, all-bits 0 if condition is 0 */ + const mbedtls_mpi_uint mask = -condition; - case 282: -#line 361 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_ATTR_NOT_DEFERRABLE; - n->location = (yylsp[(1) - (2)]); - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif - case 283: -#line 368 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_ATTR_DEFERRED; - n->location = (yylsp[(1) - (2)]); - (yyval.node) = (PGNode *)n; - ;} - break; + for( i = 0; i < n; i++ ) + dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask ); +} - case 284: -#line 375 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_ATTR_IMMEDIATE; - n->location = (yylsp[(1) - (2)]); - (yyval.node) = (PGNode *)n; - ;} - break; +#endif /* MBEDTLS_BIGNUM_C */ - case 285: -#line 386 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} - break; +#if defined(MBEDTLS_BASE64_C) - case 286: -#line 387 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = list_make1(makeDefElem("oids", (PGNode *) makeInteger(true), (yylsp[(1) - (2)]))); ;} - break; +unsigned char mbedtls_ct_base64_enc_char( unsigned char value ) +{ + unsigned char digit = 0; + /* For each range of values, if value is in that range, mask digit with + * the corresponding value. Since value can only be in a single range, + * only at most one masking will change digit. */ + digit |= mbedtls_ct_uchar_mask_of_range( 0, 25, value ) & ( 'A' + value ); + digit |= mbedtls_ct_uchar_mask_of_range( 26, 51, value ) & ( 'a' + value - 26 ); + digit |= mbedtls_ct_uchar_mask_of_range( 52, 61, value ) & ( '0' + value - 52 ); + digit |= mbedtls_ct_uchar_mask_of_range( 62, 62, value ) & '+'; + digit |= mbedtls_ct_uchar_mask_of_range( 63, 63, value ) & '/'; + return( digit ); +} + +signed char mbedtls_ct_base64_dec_value( unsigned char c ) +{ + unsigned char val = 0; + /* For each range of digits, if c is in that range, mask val with + * the corresponding value. Since c can only be in a single range, + * only at most one masking will change val. Set val to one plus + * the desired value so that it stays 0 if c is in none of the ranges. */ + val |= mbedtls_ct_uchar_mask_of_range( 'A', 'Z', c ) & ( c - 'A' + 0 + 1 ); + val |= mbedtls_ct_uchar_mask_of_range( 'a', 'z', c ) & ( c - 'a' + 26 + 1 ); + val |= mbedtls_ct_uchar_mask_of_range( '0', '9', c ) & ( c - '0' + 52 + 1 ); + val |= mbedtls_ct_uchar_mask_of_range( '+', '+', c ) & ( c - '+' + 62 + 1 ); + val |= mbedtls_ct_uchar_mask_of_range( '/', '/', c ) & ( c - '/' + 63 + 1 ); + /* At this point, val is 0 if c is an invalid digit and v+1 if c is + * a digit with the value v. */ + return( val - 1 ); +} + +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) + +/** Shift some data towards the left inside a buffer. + * + * `mbedtls_ct_mem_move_to_left(start, total, offset)` is functionally + * equivalent to + * ``` + * memmove(start, start + offset, total - offset); + * memset(start + offset, 0, total - offset); + * ``` + * but it strives to use a memory access pattern (and thus total timing) + * that does not depend on \p offset. This timing independence comes at + * the expense of performance. + * + * \param start Pointer to the start of the buffer. + * \param total Total size of the buffer. + * \param offset Offset from which to copy \p total - \p offset bytes. + */ +static void mbedtls_ct_mem_move_to_left( void *start, + size_t total, + size_t offset ) +{ + volatile unsigned char *buf = (volatile unsigned char *) start; + size_t i, n; + if( total == 0 ) + return; + for( i = 0; i < total; i++ ) + { + unsigned no_op = mbedtls_ct_size_gt( total - offset, i ); + /* The first `total - offset` passes are a no-op. The last + * `offset` passes shift the data one byte to the left and + * zero out the last byte. */ + for( n = 0; n < total - 1; n++ ) + { + unsigned char current = buf[n]; + unsigned char next = buf[n+1]; + buf[n] = mbedtls_ct_uint_if( no_op, current, next ); + } + buf[total-1] = mbedtls_ct_uint_if( no_op, buf[total-1], 0 ); + } +} - case 287: -#line 388 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = list_make1(makeDefElem("oids", (PGNode *) makeInteger(false), (yylsp[(1) - (2)]))); ;} - break; +#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ - case 288: -#line 389 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = NIL; ;} - break; +#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) - case 289: -#line 393 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} - break; +void mbedtls_ct_memcpy_if_eq( unsigned char *dest, + const unsigned char *src, + size_t len, + size_t c1, + size_t c2 ) +{ + /* mask = c1 == c2 ? 0xff : 0x00 */ + const size_t equal = mbedtls_ct_size_bool_eq( c1, c2 ); + const unsigned char mask = (unsigned char) mbedtls_ct_size_mask( equal ); - case 290: -#line 398 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = (yyvsp[(1) - (3)].ival) | (yyvsp[(3) - (3)].ival); ;} - break; + /* dest[i] = c1 == c2 ? src[i] : dest[i] */ + for( size_t i = 0; i < len; i++ ) + dest[i] = ( src[i] & mask ) | ( dest[i] & ~mask ); +} - case 291: -#line 399 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = (yyvsp[(1) - (3)].ival) & ~(yyvsp[(3) - (3)].ival); ;} - break; +void mbedtls_ct_memcpy_offset( unsigned char *dest, + const unsigned char *src, + size_t offset, + size_t offset_min, + size_t offset_max, + size_t len ) +{ + size_t offsetval; - case 292: -#line 400 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = 0; ;} - break; + for( offsetval = offset_min; offsetval <= offset_max; offsetval++ ) + { + mbedtls_ct_memcpy_if_eq( dest, src + offsetval, len, + offsetval, offset ); + } +} - case 293: -#line 405 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; +int mbedtls_ct_hmac( mbedtls_md_context_t *ctx, + const unsigned char *add_data, + size_t add_data_len, + const unsigned char *data, + size_t data_len_secret, + size_t min_data_len, + size_t max_data_len, + unsigned char *output ) +{ + /* + * This function breaks the HMAC abstraction and uses the md_clone() + * extension to the MD API in order to get constant-flow behaviour. + * + * HMAC(msg) is defined as HASH(okey + HASH(ikey + msg)) where + means + * concatenation, and okey/ikey are the XOR of the key with some fixed bit + * patterns (see RFC 2104, sec. 2), which are stored in ctx->hmac_ctx. + * + * We'll first compute inner_hash = HASH(ikey + msg) by hashing up to + * minlen, then cloning the context, and for each byte up to maxlen + * finishing up the hash computation, keeping only the correct result. + * + * Then we only need to compute HASH(okey + inner_hash) and we're done. + */ + const mbedtls_md_type_t md_alg = mbedtls_md_get_type( ctx->md_info ); + /* TLS 1.2 only supports SHA-384, SHA-256, SHA-1, MD-5, + * all of which have the same block size except SHA-384. */ + const size_t block_size = md_alg == MBEDTLS_MD_SHA384 ? 128 : 64; + const unsigned char * const ikey = ctx->hmac_ctx; + const unsigned char * const okey = ikey + block_size; + const size_t hash_size = mbedtls_md_get_size( ctx->md_info ); + + unsigned char aux_out[MBEDTLS_MD_MAX_SIZE]; + mbedtls_md_context_t aux; + size_t offset; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + mbedtls_md_init( &aux ); + +#define MD_CHK( func_call ) \ + do { \ + ret = (func_call); \ + if( ret != 0 ) \ + goto cleanup; \ + } while( 0 ) + + MD_CHK( mbedtls_md_setup( &aux, ctx->md_info, 0 ) ); + + /* After hmac_start() of hmac_reset(), ikey has already been hashed, + * so we can start directly with the message */ + MD_CHK( mbedtls_md_update( ctx, add_data, add_data_len ) ); + MD_CHK( mbedtls_md_update( ctx, data, min_data_len ) ); + + /* For each possible length, compute the hash up to that point */ + for( offset = min_data_len; offset <= max_data_len; offset++ ) + { + MD_CHK( mbedtls_md_clone( &aux, ctx ) ); + MD_CHK( mbedtls_md_finish( &aux, aux_out ) ); + /* Keep only the correct inner_hash in the output buffer */ + mbedtls_ct_memcpy_if_eq( output, aux_out, hash_size, + offset, data_len_secret ); + + if( offset < max_data_len ) + MD_CHK( mbedtls_md_update( ctx, data + offset, 1 ) ); + } - case 294: -#line 410 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = CAS_NOT_DEFERRABLE; ;} - break; + /* The context needs to finish() before it starts() again */ + MD_CHK( mbedtls_md_finish( ctx, aux_out ) ); - case 295: -#line 411 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = CAS_DEFERRABLE; ;} - break; + /* Now compute HASH(okey + inner_hash) */ + MD_CHK( mbedtls_md_starts( ctx ) ); + MD_CHK( mbedtls_md_update( ctx, okey, block_size ) ); + MD_CHK( mbedtls_md_update( ctx, output, hash_size ) ); + MD_CHK( mbedtls_md_finish( ctx, output ) ); - case 296: -#line 412 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = CAS_INITIALLY_IMMEDIATE; ;} - break; + /* Done, get ready for next time */ + MD_CHK( mbedtls_md_hmac_reset( ctx ) ); - case 297: -#line 413 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = CAS_INITIALLY_DEFERRED; ;} - break; +#undef MD_CHK - case 298: -#line 414 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = CAS_NOT_VALID; ;} - break; +cleanup: + mbedtls_md_free( &aux ); + return( ret ); +} - case 299: -#line 415 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = CAS_NO_INHERIT; ;} - break; +#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */ - case 300: -#line 421 "third_party/libpg_query/grammar/statements/create.y" - { - PGColumnDef *n = makeNode(PGColumnDef); - n->category = COL_STANDARD; - n->colname = (yyvsp[(1) - (3)].str); - n->typeName = (yyvsp[(2) - (3)].typnam); - n->inhcount = 0; - n->is_local = true; - n->is_not_null = false; - n->is_from_type = false; - n->storage = 0; - n->raw_default = NULL; - n->cooked_default = NULL; - n->collOid = InvalidOid; - SplitColQualList((yyvsp[(3) - (3)].list), &n->constraints, &n->collClause, - yyscanner); - n->location = (yylsp[(1) - (3)]); - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(MBEDTLS_BIGNUM_C) - case 301: -#line 441 "third_party/libpg_query/grammar/statements/create.y" - { - PGColumnDef *n = makeNode(PGColumnDef); - n->category = COL_GENERATED; - n->colname = (yyvsp[(1) - (4)].str); - n->typeName = (yyvsp[(2) - (4)].typnam); - n->inhcount = 0; - n->is_local = true; - n->is_not_null = false; - n->is_from_type = false; - n->storage = 0; - n->raw_default = NULL; - n->cooked_default = NULL; - n->collOid = InvalidOid; - // merge the constraints with the generated column constraint - auto constraints = (yyvsp[(4) - (4)].list); - if (constraints) { - constraints = lappend(constraints, (yyvsp[(3) - (4)].node)); - } else { - constraints = list_make1((yyvsp[(3) - (4)].node)); - } - SplitColQualList(constraints, &n->constraints, &n->collClause, - yyscanner); - n->location = (yylsp[(1) - (4)]); - (yyval.node) = (PGNode *)n; - ;} - break; +#define MPI_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MPI_BAD_INPUT_DATA ) - case 302: -#line 469 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); ;} - break; +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, + const mbedtls_mpi *Y, + unsigned char assign ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint limb_mask; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); - case 303: -#line 470 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); ;} - break; + /* all-bits 1 if assign is 1, all-bits 0 if assign is 0 */ + limb_mask = mbedtls_ct_mpi_uint_mask( assign );; - case 304: -#line 474 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); - case 305: -#line 478 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; + X->s = mbedtls_ct_cond_select_sign( assign, Y->s, X->s ); - case 306: -#line 479 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; + mbedtls_ct_mpi_uint_cond_assign( Y->n, X->p, Y->p, assign ); - case 307: -#line 480 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; + for( i = Y->n; i < X->n; i++ ) + X->p[i] &= ~limb_mask; - case 308: -#line 485 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (3)].str), (PGNode *) (yyvsp[(3) - (3)].node), (yylsp[(1) - (3)])); - ;} - break; +cleanup: + return( ret ); +} - case 309: -#line 489 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (1)].str), NULL, (yylsp[(1) - (1)])); - ;} - break; +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which whould lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, + mbedtls_mpi *Y, + unsigned char swap ) +{ + int ret, s; + size_t i; + mbedtls_mpi_uint limb_mask; + mbedtls_mpi_uint tmp; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); - case 310: -#line 496 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} - break; + if( X == Y ) + return( 0 ); - case 311: -#line 497 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = NIL; ;} - break; + /* all-bits 1 if swap is 1, all-bits 0 if swap is 0 */ + limb_mask = mbedtls_ct_mpi_uint_mask( swap ); - case 312: -#line 502 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); - case 313: -#line 503 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} - break; + s = X->s; + X->s = mbedtls_ct_cond_select_sign( swap, Y->s, X->s ); + Y->s = mbedtls_ct_cond_select_sign( swap, s, Y->s ); - case 314: -#line 504 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = NIL; ;} - break; - case 315: -#line 509 "third_party/libpg_query/grammar/statements/create.y" + for( i = 0; i < X->n; i++ ) { - (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); - ;} - break; + tmp = X->p[i]; + X->p[i] = ( X->p[i] & ~limb_mask ) | ( Y->p[i] & limb_mask ); + Y->p[i] = ( Y->p[i] & ~limb_mask ) | ( tmp & limb_mask ); + } - case 316: -#line 516 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} - break; +cleanup: + return( ret ); +} - case 317: -#line 517 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = NIL; ;} - break; +/* + * Compare signed values in constant time + */ +int mbedtls_mpi_lt_mpi_ct( const mbedtls_mpi *X, + const mbedtls_mpi *Y, + unsigned *ret ) +{ + size_t i; + /* The value of any of these variables is either 0 or 1 at all times. */ + unsigned cond, done, X_is_negative, Y_is_negative; - case 318: -#line 522 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} - break; + MPI_VALIDATE_RET( X != NULL ); + MPI_VALIDATE_RET( Y != NULL ); + MPI_VALIDATE_RET( ret != NULL ); - case 319: -#line 523 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = NIL; ;} - break; + if( X->n != Y->n ) + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; - case 320: -#line 527 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = (yyvsp[(3) - (3)].ival); ;} - break; + /* + * Set sign_N to 1 if N >= 0, 0 if N < 0. + * We know that N->s == 1 if N >= 0 and N->s == -1 if N < 0. + */ + X_is_negative = ( X->s & 2 ) >> 1; + Y_is_negative = ( Y->s & 2 ) >> 1; - case 321: -#line 533 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (3)].str), (PGNode *) (yyvsp[(3) - (3)].node), (yylsp[(1) - (3)])); - ;} - break; + /* + * If the signs are different, then the positive operand is the bigger. + * That is if X is negative (X_is_negative == 1), then X < Y is true and it + * is false if X is positive (X_is_negative == 0). + */ + cond = ( X_is_negative ^ Y_is_negative ); + *ret = cond & X_is_negative; - case 322: -#line 537 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (1)].str), NULL, (yylsp[(1) - (1)])); - ;} - break; + /* + * This is a constant-time function. We might have the result, but we still + * need to go through the loop. Record if we have the result already. + */ + done = cond; - case 323: -#line 541 "third_party/libpg_query/grammar/statements/create.y" + for( i = X->n; i > 0; i-- ) { - (yyval.defelt) = makeDefElemExtended((yyvsp[(1) - (5)].str), (yyvsp[(3) - (5)].str), (PGNode *) (yyvsp[(5) - (5)].node), - PG_DEFELEM_UNSPEC, (yylsp[(1) - (5)])); - ;} - break; + /* + * If Y->p[i - 1] < X->p[i - 1] then X < Y is true if and only if both + * X and Y are negative. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = mbedtls_ct_mpi_uint_lt( Y->p[i - 1], X->p[i - 1] ); + *ret |= cond & ( 1 - done ) & X_is_negative; + done |= cond; - case 324: -#line 546 "third_party/libpg_query/grammar/statements/create.y" + /* + * If X->p[i - 1] < Y->p[i - 1] then X < Y is true if and only if both + * X and Y are positive. + * + * Again even if we can make a decision, we just mark the result and + * the fact that we are done and continue looping. + */ + cond = mbedtls_ct_mpi_uint_lt( X->p[i - 1], Y->p[i - 1] ); + *ret |= cond & ( 1 - done ) & ( 1 - X_is_negative ); + done |= cond; + } + + return( 0 ); +} + +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT) + +int mbedtls_ct_rsaes_pkcs1_v15_unpadding( unsigned char *input, + size_t ilen, + unsigned char *output, + size_t output_max_len, + size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t i, plaintext_max_size; + + /* The following variables take sensitive values: their value must + * not leak into the observable behavior of the function other than + * the designated outputs (output, olen, return value). Otherwise + * this would open the execution of the function to + * side-channel-based variants of the Bleichenbacher padding oracle + * attack. Potential side channels include overall timing, memory + * access patterns (especially visible to an adversary who has access + * to a shared memory cache), and branches (especially visible to + * an adversary who has access to a shared code cache or to a shared + * branch predictor). */ + size_t pad_count = 0; + unsigned bad = 0; + unsigned char pad_done = 0; + size_t plaintext_size = 0; + unsigned output_too_large; + + plaintext_max_size = ( output_max_len > ilen - 11 ) ? ilen - 11 + : output_max_len; + + /* Check and get padding length in constant time and constant + * memory trace. The first byte must be 0. */ + bad |= input[0]; + + + /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00 + * where PS must be at least 8 nonzero bytes. */ + bad |= input[1] ^ MBEDTLS_RSA_CRYPT; + + /* Read the whole buffer. Set pad_done to nonzero if we find + * the 0x00 byte and remember the padding length in pad_count. */ + for( i = 2; i < ilen; i++ ) { - (yyval.defelt) = makeDefElemExtended((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str), NULL, PG_DEFELEM_UNSPEC, (yylsp[(1) - (3)])); - ;} - break; + pad_done |= ((input[i] | (unsigned char)-input[i]) >> 7) ^ 1; + pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } - case 325: -#line 553 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} - break; - case 326: -#line 554 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} - break; + /* If pad_done is still zero, there's no data, only unfinished padding. */ + bad |= mbedtls_ct_uint_if( pad_done, 0, 1 ); + + /* There must be at least 8 bytes of padding. */ + bad |= mbedtls_ct_size_gt( 8, pad_count ); + + /* If the padding is valid, set plaintext_size to the number of + * remaining bytes after stripping the padding. If the padding + * is invalid, avoid leaking this fact through the size of the + * output: use the maximum message size that fits in the output + * buffer. Do it without branches to avoid leaking the padding + * validity through timing. RSA keys are small enough that all the + * size_t values involved fit in unsigned int. */ + plaintext_size = mbedtls_ct_uint_if( + bad, (unsigned) plaintext_max_size, + (unsigned) ( ilen - pad_count - 3 ) ); + + /* Set output_too_large to 0 if the plaintext fits in the output + * buffer and to 1 otherwise. */ + output_too_large = mbedtls_ct_size_gt( plaintext_size, + plaintext_max_size ); + + /* Set ret without branches to avoid timing attacks. Return: + * - INVALID_PADDING if the padding is bad (bad != 0). + * - OUTPUT_TOO_LARGE if the padding is good but the decrypted + * plaintext does not fit in the output buffer. + * - 0 if the padding is correct. */ + ret = - (int) mbedtls_ct_uint_if( + bad, - MBEDTLS_ERR_RSA_INVALID_PADDING, + mbedtls_ct_uint_if( output_too_large, + - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE, + 0 ) ); + + /* If the padding is bad or the plaintext is too large, zero the + * data that we're about to copy to the output buffer. + * We need to copy the same amount of data + * from the same buffer whether the padding is good or not to + * avoid leaking the padding validity through overall timing or + * through memory or cache access patterns. */ + bad = mbedtls_ct_uint_mask( bad | output_too_large ); + for( i = 11; i < ilen; i++ ) + input[i] &= ~bad; + + /* If the plaintext is too large, truncate it to the buffer size. + * Copy anyway to avoid revealing the length through timing, because + * revealing the length is as bad as revealing the padding validity + * for a Bleichenbacher attack. */ + plaintext_size = mbedtls_ct_uint_if( output_too_large, + (unsigned) plaintext_max_size, + (unsigned) plaintext_size ); + + /* Move the plaintext to the leftmost position where it can start in + * the working buffer, i.e. make it start plaintext_max_size from + * the end of the buffer. Do this with a memory access trace that + * does not depend on the plaintext size. After this move, the + * starting location of the plaintext is no longer sensitive + * information. */ + mbedtls_ct_mem_move_to_left( input + ilen - plaintext_max_size, + plaintext_max_size, + plaintext_max_size - plaintext_size ); + + /* Finally copy the decrypted plaintext plus trailing zeros into the output + * buffer. If output_max_len is 0, then output may be an invalid pointer + * and the result of memcpy() would be undefined; prevent undefined + * behavior making sure to depend only on output_max_len (the size of the + * user-provided output buffer), which is independent from plaintext + * length, validity of padding, success of the decryption, and other + * secrets. */ + if( output_max_len != 0 ) + memcpy( output, input + ilen - plaintext_max_size, plaintext_max_size ); + + /* Report the amount of data we copied to the output buffer. In case + * of errors (bad padding or output too large), the value of *olen + * when this function returns is not specified. Making it equivalent + * to the good case limits the risks of leaking the padding validity. */ + *olen = plaintext_size; + + return( ret ); +} + +#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */ - case 327: -#line 558 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; - case 328: -#line 559 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} - break; +// LICENSE_CHANGE_END - case 329: -#line 563 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} - break; - case 330: -#line 565 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.typnam) = makeTypeNameFromNameList(lcons(makeString((yyvsp[(1) - (4)].str)), (yyvsp[(2) - (4)].list))); - (yyval.typnam)->pct_type = true; - (yyval.typnam)->location = (yylsp[(1) - (4)]); - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 331: -#line 571 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.typnam) = makeTypeNameFromNameList(lcons(makeString((yyvsp[(2) - (5)].str)), (yyvsp[(3) - (5)].list))); - (yyval.typnam)->pct_type = true; - (yyval.typnam)->setof = true; - (yyval.typnam)->location = (yylsp[(2) - (5)]); - ;} - break; +/** + * \file md.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - case 332: -#line 582 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_CHECK; - n->location = (yylsp[(1) - (5)]); - n->raw_expr = (yyvsp[(3) - (5)].node); - n->cooked_expr = NULL; - processCASbits((yyvsp[(5) - (5)].ival), (yylsp[(5) - (5)]), "CHECK", - NULL, NULL, &n->skip_validation, - &n->is_no_inherit, yyscanner); - n->initially_valid = !n->skip_validation; - (yyval.node) = (PGNode *)n; - ;} - break; - case 333: -#line 596 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_UNIQUE; - n->location = (yylsp[(1) - (6)]); - n->keys = (yyvsp[(3) - (6)].list); - n->options = (yyvsp[(5) - (6)].list); - n->indexname = NULL; - processCASbits((yyvsp[(6) - (6)].ival), (yylsp[(6) - (6)]), "UNIQUE", - &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); - (yyval.node) = (PGNode *)n; - ;} - break; - case 334: -#line 609 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_UNIQUE; - n->location = (yylsp[(1) - (3)]); - n->keys = NIL; - n->options = NIL; - n->indexname = (yyvsp[(2) - (3)].str); - n->indexspace = NULL; - processCASbits((yyvsp[(3) - (3)].ival), (yylsp[(3) - (3)]), "UNIQUE", - &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(MBEDTLS_MD_C) - case 335: -#line 624 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_PRIMARY; - n->location = (yylsp[(1) - (7)]); - n->keys = (yyvsp[(4) - (7)].list); - n->options = (yyvsp[(6) - (7)].list); - n->indexname = NULL; - processCASbits((yyvsp[(7) - (7)].ival), (yylsp[(7) - (7)]), "PRIMARY KEY", - &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); - (yyval.node) = (PGNode *)n; - ;} - break; - case 336: -#line 637 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_PRIMARY; - n->location = (yylsp[(1) - (4)]); - n->keys = NIL; - n->options = NIL; - n->indexname = (yyvsp[(3) - (4)].str); - n->indexspace = NULL; - processCASbits((yyvsp[(4) - (4)].ival), (yylsp[(4) - (4)]), "PRIMARY KEY", - &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); - (yyval.node) = (PGNode *)n; - ;} - break; - case 337: -#line 652 "third_party/libpg_query/grammar/statements/create.y" - { - PGConstraint *n = makeNode(PGConstraint); - n->contype = PG_CONSTR_FOREIGN; - n->location = (yylsp[(1) - (11)]); - n->pktable = (yyvsp[(7) - (11)].range); - n->fk_attrs = (yyvsp[(4) - (11)].list); - n->pk_attrs = (yyvsp[(8) - (11)].list); - n->fk_matchtype = (yyvsp[(9) - (11)].ival); - n->fk_upd_action = (char) ((yyvsp[(10) - (11)].ival) >> 8); - n->fk_del_action = (char) ((yyvsp[(10) - (11)].ival) & 0xFF); - processCASbits((yyvsp[(11) - (11)].ival), (yylsp[(11) - (11)]), "FOREIGN KEY", - &n->deferrable, &n->initdeferred, - &n->skip_validation, NULL, - yyscanner); - n->initially_valid = !n->skip_validation; - (yyval.node) = (PGNode *)n; - ;} - break; - case 338: -#line 674 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 339: -#line 678 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); - ;} - break; +/** + * \file md_wrap.h + * + * \brief Message digest wrappers. + * + * \warning This in an internal header. Do not include directly. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_MD_WRAP_H +#define MBEDTLS_MD_WRAP_H - case 340: -#line 685 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.ival) = PG_FKCONSTR_MATCH_FULL; - ;} - break; - case 341: -#line 689 "third_party/libpg_query/grammar/statements/create.y" - { - ereport(ERROR, - (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("MATCH PARTIAL not yet implemented"), - parser_errposition((yylsp[(1) - (2)])))); - (yyval.ival) = PG_FKCONSTR_MATCH_PARTIAL; - ;} - break; - case 342: -#line 697 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.ival) = PG_FKCONSTR_MATCH_SIMPLE; - ;} - break; - case 343: -#line 701 "third_party/libpg_query/grammar/statements/create.y" - { - (yyval.ival) = PG_FKCONSTR_MATCH_SIMPLE; - ;} - break; - case 344: -#line 709 "third_party/libpg_query/grammar/statements/create.y" - { - PGTableLikeClause *n = makeNode(PGTableLikeClause); - n->relation = (yyvsp[(2) - (3)].range); - n->options = (yyvsp[(3) - (3)].ival); - (yyval.node) = (PGNode *)n; - ;} - break; +#ifdef __cplusplus +extern "C" { +#endif - case 345: -#line 718 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_RELPERSISTENCE_TEMP; ;} - break; +/** + * Message digest information. + * Allows message digest functions to be called in a generic way. + */ +struct mbedtls_md_info_t +{ + /** Name of the message digest */ + const char * name; - case 346: -#line 719 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_RELPERSISTENCE_TEMP; ;} - break; + /** Digest identifier */ + mbedtls_md_type_t type; - case 347: -#line 720 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_RELPERSISTENCE_TEMP; ;} - break; + /** Output length of the digest function in bytes */ + unsigned char size; - case 348: -#line 721 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_RELPERSISTENCE_TEMP; ;} - break; + /** Block length of the digest function in bytes */ + unsigned char block_size; +}; - case 349: -#line 723 "third_party/libpg_query/grammar/statements/create.y" - { - ereport(PGWARNING, - (errmsg("GLOBAL is deprecated in temporary table creation"), - parser_errposition((yylsp[(1) - (2)])))); - (yyval.ival) = PG_RELPERSISTENCE_TEMP; - ;} - break; +#if defined(MBEDTLS_MD5_C) +extern const mbedtls_md_info_t mbedtls_md5_info; +#endif +#if defined(MBEDTLS_RIPEMD160_C) +extern const mbedtls_md_info_t mbedtls_ripemd160_info; +#endif +#if defined(MBEDTLS_SHA1_C) +extern const mbedtls_md_info_t mbedtls_sha1_info; +#endif +#if defined(MBEDTLS_SHA224_C) +extern const mbedtls_md_info_t mbedtls_sha224_info; +#endif +#if defined(MBEDTLS_SHA256_C) +extern const mbedtls_md_info_t mbedtls_sha256_info; +#endif +#if defined(MBEDTLS_SHA384_C) +extern const mbedtls_md_info_t mbedtls_sha384_info; +#endif +#if defined(MBEDTLS_SHA512_C) +extern const mbedtls_md_info_t mbedtls_sha512_info; +#endif - case 350: -#line 730 "third_party/libpg_query/grammar/statements/create.y" - { - ereport(PGWARNING, - (errmsg("GLOBAL is deprecated in temporary table creation"), - parser_errposition((yylsp[(1) - (2)])))); - (yyval.ival) = PG_RELPERSISTENCE_TEMP; - ;} - break; +#ifdef __cplusplus +} +#endif - case 351: -#line 736 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_RELPERSISTENCE_UNLOGGED; ;} - break; +#endif /* MBEDTLS_MD_WRAP_H */ - case 352: -#line 737 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = RELPERSISTENCE_PERMANENT; ;} - break; - case 353: -#line 742 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = PG_ATTRIBUTE_IDENTITY_ALWAYS; ;} - break; +// LICENSE_CHANGE_END - case 354: -#line 743 "third_party/libpg_query/grammar/statements/create.y" - { (yyval.ival) = ATTRIBUTE_IDENTITY_BY_DEFAULT; ;} - break; - case 355: -#line 10 "third_party/libpg_query/grammar/statements/drop.y" - { - PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = (yyvsp[(2) - (6)].objtype); - n->missing_ok = true; - n->objects = (yyvsp[(5) - (6)].list); - n->behavior = (yyvsp[(6) - (6)].dbehavior); - n->concurrent = false; - (yyval.node) = (PGNode *)n; - ;} - break; - case 356: -#line 20 "third_party/libpg_query/grammar/statements/drop.y" - { - PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = (yyvsp[(2) - (4)].objtype); - n->missing_ok = false; - n->objects = (yyvsp[(3) - (4)].list); - n->behavior = (yyvsp[(4) - (4)].dbehavior); - n->concurrent = false; - (yyval.node) = (PGNode *)n; - ;} - break; - case 357: -#line 30 "third_party/libpg_query/grammar/statements/drop.y" - { - PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = (yyvsp[(2) - (6)].objtype); - n->missing_ok = true; - n->objects = (yyvsp[(5) - (6)].list); - n->behavior = (yyvsp[(6) - (6)].dbehavior); - n->concurrent = false; - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(MBEDTLS_MD5_C) - case 358: -#line 40 "third_party/libpg_query/grammar/statements/drop.y" - { - PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = (yyvsp[(2) - (4)].objtype); - n->missing_ok = false; - n->objects = (yyvsp[(3) - (4)].list); - n->behavior = (yyvsp[(4) - (4)].dbehavior); - n->concurrent = false; - (yyval.node) = (PGNode *)n; - ;} - break; - case 359: -#line 50 "third_party/libpg_query/grammar/statements/drop.y" - { - PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = (yyvsp[(2) - (6)].objtype); - n->objects = list_make1(lappend((yyvsp[(5) - (6)].list), makeString((yyvsp[(3) - (6)].str)))); - n->behavior = (yyvsp[(6) - (6)].dbehavior); - n->missing_ok = false; - n->concurrent = false; - (yyval.node) = (PGNode *) n; - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 360: -#line 60 "third_party/libpg_query/grammar/statements/drop.y" - { - PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = (yyvsp[(2) - (8)].objtype); - n->objects = list_make1(lappend((yyvsp[(7) - (8)].list), makeString((yyvsp[(5) - (8)].str)))); - n->behavior = (yyvsp[(8) - (8)].dbehavior); - n->missing_ok = true; - n->concurrent = false; - (yyval.node) = (PGNode *) n; - ;} - break; +// dummy file to make amalgamantion happy - case 361: -#line 70 "third_party/libpg_query/grammar/statements/drop.y" - { - PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = PG_OBJECT_TYPE; - n->missing_ok = false; - n->objects = (yyvsp[(3) - (4)].list); - n->behavior = (yyvsp[(4) - (4)].dbehavior); - n->concurrent = false; - (yyval.node) = (PGNode *) n; - ;} - break; +// LICENSE_CHANGE_END - case 362: -#line 80 "third_party/libpg_query/grammar/statements/drop.y" - { - PGDropStmt *n = makeNode(PGDropStmt); - n->removeType = PG_OBJECT_TYPE; - n->missing_ok = true; - n->objects = (yyvsp[(5) - (6)].list); - n->behavior = (yyvsp[(6) - (6)].dbehavior); - n->concurrent = false; - (yyval.node) = (PGNode *) n; - ;} - break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) - case 363: -#line 93 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TABLE; ;} - break; - case 364: -#line 94 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_SEQUENCE; ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 365: -#line 95 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_FUNCTION; ;} - break; +// dummy file to make amalgamantion happy - case 366: -#line 96 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_FUNCTION; ;} - break; +// LICENSE_CHANGE_END - case 367: -#line 97 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TABLE_MACRO; ;} - break; +#endif +#if defined(MBEDTLS_SHA1_C) - case 368: -#line 98 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_VIEW; ;} - break; - case 369: -#line 99 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_MATVIEW; ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 370: -#line 100 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_INDEX; ;} - break; +/** + * \file sha1.h + * + * \brief This file contains SHA-1 definitions and functions. + * + * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in + * FIPS 180-4: Secure Hash Standard (SHS). + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_SHA1_H +#define MBEDTLS_SHA1_H - case 371: -#line 101 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_FOREIGN_TABLE; ;} - break; - case 372: -#line 102 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_COLLATION; ;} - break; - case 373: -#line 103 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_CONVERSION; ;} - break; - case 374: -#line 104 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_STATISTIC_EXT; ;} - break; +#include +#include - case 375: -#line 105 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TSPARSER; ;} - break; +/** SHA-1 input data was malformed. */ +#define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA -0x0073 - case 376: -#line 106 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TSDICTIONARY; ;} - break; +#ifdef __cplusplus +extern "C" { +#endif - case 377: -#line 107 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TSTEMPLATE; ;} - break; +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// - case 378: -#line 108 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TSCONFIGURATION; ;} - break; +/** + * \brief The SHA-1 context structure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_sha1_context +{ + uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ + uint32_t MBEDTLS_PRIVATE(state)[5]; /*!< The intermediate digest state. */ + unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< The data block being processed. */ +} +mbedtls_sha1_context; - case 379: -#line 113 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_ACCESS_METHOD; ;} - break; +#else /* MBEDTLS_SHA1_ALT */ - case 380: -#line 114 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_EVENT_TRIGGER; ;} - break; - case 381: -#line 115 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_EXTENSION; ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 382: -#line 116 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_FDW; ;} - break; +// dummy file to make amalgamantion happy - case 383: -#line 117 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_PUBLICATION; ;} - break; +// LICENSE_CHANGE_END - case 384: -#line 118 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_SCHEMA; ;} - break; +#endif /* MBEDTLS_SHA1_ALT */ - case 385: -#line 119 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_FOREIGN_SERVER; ;} - break; +/** + * \brief This function initializes a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. + * This must not be \c NULL. + * + */ +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); - case 386: -#line 124 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].list)); ;} - break; +/** + * \brief This function clears a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to clear. This may be \c NULL, + * in which case this function does nothing. If it is + * not \c NULL, it must point to an initialized + * SHA-1 context. + * + */ +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); - case 387: -#line 125 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); ;} - break; +/** + * \brief This function clones the state of a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param dst The SHA-1 context to clone to. This must be initialized. + * \param src The SHA-1 context to clone from. This must be initialized. + * + */ +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ); - case 388: -#line 130 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.dbehavior) = PG_DROP_CASCADE; ;} - break; +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); - case 389: -#line 131 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.dbehavior) = PG_DROP_RESTRICT; ;} - break; +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); - case 390: -#line 132 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.dbehavior) = PG_DROP_RESTRICT; /* default */ ;} - break; +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ); - case 391: -#line 137 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_POLICY; ;} - break; +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized. + * \param data The data block being processed. This must be a + * readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); - case 392: -#line 138 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_RULE; ;} - break; +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); - case 393: -#line 139 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.objtype) = PG_OBJECT_TRIGGER; ;} - break; +#if defined(MBEDTLS_SELF_TEST) - case 394: -#line 142 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].typnam)); ;} - break; +/** + * \brief The SHA-1 checkup routine. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \return \c 0 on success. + * \return \c 1 on failure. + * + */ +int mbedtls_sha1_self_test( int verbose ); - case 395: -#line 143 "third_party/libpg_query/grammar/statements/drop.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].typnam)); ;} - break; +#endif /* MBEDTLS_SELF_TEST */ - case 396: -#line 9 "third_party/libpg_query/grammar/statements/create_function.y" - { - PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt); - n->relpersistence=(yyvsp[(2) - (8)].ival); - n->name = (yyvsp[(4) - (8)].range); - n->params = (yyvsp[(5) - (8)].list); - n->function = NULL; - n->query = (yyvsp[(8) - (8)].node); - (yyval.node) = (PGNode *)n; - - ;} - break; +#ifdef __cplusplus +} +#endif - case 397: -#line 21 "third_party/libpg_query/grammar/statements/create_function.y" - { - PGCreateFunctionStmt *n = makeNode(PGCreateFunctionStmt); - n->relpersistence=(yyvsp[(2) - (7)].ival); - n->name = (yyvsp[(4) - (7)].range); - n->params = (yyvsp[(5) - (7)].list); - n->function = (yyvsp[(7) - (7)].node); - n->query = NULL; - (yyval.node) = (PGNode *)n; - ;} - break; +#endif /* mbedtls_sha1.h */ - case 400: -#line 42 "third_party/libpg_query/grammar/statements/create_function.y" - { - (yyval.list) = NIL; - ;} - break; - case 401: -#line 46 "third_party/libpg_query/grammar/statements/create_function.y" - { - (yyval.list) = (yyvsp[(2) - (3)].list); - ;} - break; +// LICENSE_CHANGE_END - case 402: -#line 12 "third_party/libpg_query/grammar/statements/update.y" - { - PGUpdateStmt *n = makeNode(PGUpdateStmt); - n->relation = (yyvsp[(3) - (8)].range); - n->targetList = (yyvsp[(5) - (8)].list); - n->fromClause = (yyvsp[(6) - (8)].list); - n->whereClause = (yyvsp[(7) - (8)].node); - n->returningList = (yyvsp[(8) - (8)].list); - n->withClause = (yyvsp[(1) - (8)].with); - (yyval.node) = (PGNode *)n; - ;} - break; +#endif +#if defined(MBEDTLS_SHA256_C) - case 403: -#line 3 "third_party/libpg_query/grammar/statements/copy.y" - { - PGCopyStmt *n = makeNode(PGCopyStmt); - n->relation = (yyvsp[(3) - (11)].range); - n->query = NULL; - n->attlist = (yyvsp[(4) - (11)].list); - n->is_from = (yyvsp[(6) - (11)].boolean); - n->is_program = (yyvsp[(7) - (11)].boolean); - n->filename = (yyvsp[(8) - (11)].str); - if (n->is_program && n->filename == NULL) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("STDIN/STDOUT not allowed with PROGRAM"), - parser_errposition((yylsp[(8) - (11)])))); +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - n->options = NIL; - /* Concatenate user-supplied flags */ - if ((yyvsp[(2) - (11)].defelt)) - n->options = lappend(n->options, (yyvsp[(2) - (11)].defelt)); - if ((yyvsp[(5) - (11)].defelt)) - n->options = lappend(n->options, (yyvsp[(5) - (11)].defelt)); - if ((yyvsp[(9) - (11)].defelt)) - n->options = lappend(n->options, (yyvsp[(9) - (11)].defelt)); - if ((yyvsp[(11) - (11)].list)) - n->options = list_concat(n->options, (yyvsp[(11) - (11)].list)); - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \file sha256.h + * + * \brief This file contains SHA-224 and SHA-256 definitions and functions. + * + * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_SHA256_H +#define MBEDTLS_SHA256_H - case 404: -#line 31 "third_party/libpg_query/grammar/statements/copy.y" - { - PGCopyStmt *n = makeNode(PGCopyStmt); - n->relation = NULL; - n->query = (yyvsp[(3) - (9)].node); - n->attlist = NIL; - n->is_from = false; - n->is_program = (yyvsp[(6) - (9)].boolean); - n->filename = (yyvsp[(7) - (9)].str); - n->options = (yyvsp[(9) - (9)].list); - if (n->is_program && n->filename == NULL) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("STDIN/STDOUT not allowed with PROGRAM"), - parser_errposition((yylsp[(5) - (9)])))); - (yyval.node) = (PGNode *)n; - ;} - break; - case 405: -#line 53 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.boolean) = true; ;} - break; +#include +#include - case 406: -#line 54 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.boolean) = false; ;} - break; +/** SHA-256 input data was malformed. */ +#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 - case 407: -#line 60 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("delimiter", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(2) - (3)])); - ;} - break; +#ifdef __cplusplus +extern "C" { +#endif - case 408: -#line 63 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.defelt) = NULL; ;} - break; +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// - case 409: -#line 69 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} - break; +/** + * \brief The SHA-256 context structure. + * + * The structure is used both for SHA-256 and for SHA-224 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha256_starts(). + */ +typedef struct mbedtls_sha256_context +{ + uint32_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ + uint32_t MBEDTLS_PRIVATE(state)[8]; /*!< The intermediate digest state. */ + unsigned char MBEDTLS_PRIVATE(buffer)[64]; /*!< The data block being processed. */ + int MBEDTLS_PRIVATE(is224); /*!< Determines which function to use: + 0: Use SHA-256, or 1: Use SHA-224. */ +} +mbedtls_sha256_context; - case 410: -#line 73 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); - ;} - break; +#else /* MBEDTLS_SHA256_ALT */ - case 411: -#line 80 "third_party/libpg_query/grammar/statements/copy.y" - {;} - break; - case 412: -#line 81 "third_party/libpg_query/grammar/statements/copy.y" - {;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 413: -#line 85 "third_party/libpg_query/grammar/statements/copy.y" - {;} - break; +// dummy file to make amalgamantion happy - case 414: -#line 86 "third_party/libpg_query/grammar/statements/copy.y" - {;} - break; +// LICENSE_CHANGE_END - case 415: -#line 91 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.boolean) = true; ;} - break; +#endif /* MBEDTLS_SHA256_ALT */ - case 416: -#line 92 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.boolean) = false; ;} - break; +/** + * \brief This function initializes a SHA-256 context. + * + * \param ctx The SHA-256 context to initialize. This must not be \c NULL. + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); - case 417: -#line 96 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; +/** + * \brief This function clears a SHA-256 context. + * + * \param ctx The SHA-256 context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized SHA-256 context. + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); - case 418: -#line 97 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} - break; +/** + * \brief This function clones the state of a SHA-256 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); - case 419: -#line 102 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); ;} - break; +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \param ctx The context to use. This must be initialized. + * \param is224 This determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); - case 420: -#line 103 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = (PGNode *) (yyvsp[(1) - (1)].value); ;} - break; +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); - case 421: -#line 104 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = (PGNode *) makeNode(PGAStar); ;} - break; +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. + * This must be a writable buffer of length \c 32 bytes + * for SHA-256, \c 28 bytes for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char *output ); - case 422: -#line 105 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = (PGNode *) (yyvsp[(2) - (3)].list); ;} - break; +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must + * be a readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); - case 423: -#line 106 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = NULL; ;} - break; +/** + * \brief This function calculates the SHA-224 or SHA-256 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. + * This must be a writable buffer of length \c 32 bytes + * for SHA-256, \c 28 bytes for SHA-224. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char *output, + int is224 ); - case 424: -#line 112 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); - ;} - break; +#if defined(MBEDTLS_SELF_TEST) - case 425: -#line 120 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("oids", (PGNode *)makeInteger(true), (yylsp[(1) - (2)])); - ;} - break; +/** + * \brief The SHA-224 and SHA-256 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha256_self_test( int verbose ); - case 426: -#line 123 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.defelt) = NULL; ;} - break; +#endif /* MBEDTLS_SELF_TEST */ - case 427: -#line 128 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].defelt)); ;} - break; +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ + + +// LICENSE_CHANGE_END + +#endif +#if defined(MBEDTLS_SHA512_C) + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/** + * \file sha512.h + * \brief This file contains SHA-384 and SHA-512 definitions and functions. + * + * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_SHA512_H +#define MBEDTLS_SHA512_H + + + + +#include +#include + +/** SHA-512 input data was malformed. */ +#define MBEDTLS_ERR_SHA512_BAD_INPUT_DATA -0x0075 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA512_ALT) +// Regular implementation +// + +/** + * \brief The SHA-512 context structure. + * + * The structure is used both for SHA-384 and for SHA-512 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha512_starts(). + */ +typedef struct mbedtls_sha512_context +{ + uint64_t MBEDTLS_PRIVATE(total)[2]; /*!< The number of Bytes processed. */ + uint64_t MBEDTLS_PRIVATE(state)[8]; /*!< The intermediate digest state. */ + unsigned char MBEDTLS_PRIVATE(buffer)[128]; /*!< The data block being processed. */ +#if defined(MBEDTLS_SHA384_C) + int MBEDTLS_PRIVATE(is384); /*!< Determines which function to use: + 0: Use SHA-512, or 1: Use SHA-384. */ +#endif +} +mbedtls_sha512_context; - case 428: -#line 129 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.list) = NIL; ;} - break; +#else /* MBEDTLS_SHA512_ALT */ - case 429: -#line 135 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("format", (PGNode *)makeString("binary"), (yylsp[(1) - (1)])); - ;} - break; - case 430: -#line 138 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.defelt) = NULL; ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 431: -#line 144 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("format", (PGNode *)makeString("binary"), (yylsp[(1) - (1)])); - ;} - break; +// dummy file to make amalgamantion happy - case 432: -#line 148 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("oids", (PGNode *)makeInteger(true), (yylsp[(1) - (1)])); - ;} - break; +// LICENSE_CHANGE_END - case 433: -#line 152 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("freeze", (PGNode *)makeInteger(true), (yylsp[(1) - (1)])); - ;} - break; +#endif /* MBEDTLS_SHA512_ALT */ - case 434: -#line 156 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("delimiter", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(1) - (3)])); - ;} - break; +/** + * \brief This function initializes a SHA-512 context. + * + * \param ctx The SHA-512 context to initialize. This must + * not be \c NULL. + */ +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); - case 435: -#line 160 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("null", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(1) - (3)])); - ;} - break; +/** + * \brief This function clears a SHA-512 context. + * + * \param ctx The SHA-512 context to clear. This may be \c NULL, + * in which case this function does nothing. If it + * is not \c NULL, it must point to an initialized + * SHA-512 context. + */ +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); - case 436: -#line 164 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("format", (PGNode *)makeString("csv"), (yylsp[(1) - (1)])); - ;} - break; +/** + * \brief This function clones the state of a SHA-512 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ); - case 437: -#line 168 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("header", (PGNode *)makeInteger(true), (yylsp[(1) - (1)])); - ;} - break; +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \param ctx The SHA-512 context to use. This must be initialized. + * \param is384 Determines which function to use. This must be + * either \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA384_C is not defined, + * \p is384 must be \c 0, or the function will return + * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ); - case 438: -#line 172 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("quote", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(1) - (3)])); - ;} - break; +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. This must + * be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); - case 439: -#line 176 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("escape", (PGNode *)makeString((yyvsp[(3) - (3)].str)), (yylsp[(1) - (3)])); - ;} - break; +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-512 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 bytes + * for SHA-512, \c 48 bytes for SHA-384. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char *output ); - case 440: -#line 180 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("force_quote", (PGNode *)(yyvsp[(3) - (3)].list), (yylsp[(1) - (3)])); - ;} - break; +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. + * This function is for internal use only. + * + * \param ctx The SHA-512 context. This must be initialized. + * \param data The buffer holding one block of data. This + * must be a readable buffer of length \c 128 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ); - case 441: -#line 184 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("force_quote", (PGNode *)makeNode(PGAStar), (yylsp[(1) - (3)])); - ;} - break; +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \param input The buffer holding the input data. This must be + * a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-384 or SHA-512 checksum result. + * This must be a writable buffer of length \c 64 bytes + * for SHA-512, \c 48 bytes for SHA-384. + * \param is384 Determines which function to use. This must be either + * \c 0 for SHA-512, or \c 1 for SHA-384. + * + * \note When \c MBEDTLS_SHA384_C is not defined, \p is384 must + * be \c 0, or the function will return + * #MBEDTLS_ERR_SHA512_BAD_INPUT_DATA. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char *output, + int is384 ); - case 442: -#line 188 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("force_not_null", (PGNode *)(yyvsp[(4) - (4)].list), (yylsp[(1) - (4)])); - ;} - break; +#if defined(MBEDTLS_SELF_TEST) - case 443: -#line 192 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("force_null", (PGNode *)(yyvsp[(3) - (3)].list), (yylsp[(1) - (3)])); - ;} - break; + /** + * \brief The SHA-384 or SHA-512 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha512_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST */ - case 444: -#line 196 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.defelt) = makeDefElem("encoding", (PGNode *)makeString((yyvsp[(2) - (2)].str)), (yylsp[(1) - (2)])); - ;} - break; +#ifdef __cplusplus +} +#endif - case 445: -#line 203 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); ;} - break; +#endif /* mbedtls_sha512.h */ - case 446: -#line 209 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; - case 447: -#line 210 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.str) = NULL; ;} - break; +// LICENSE_CHANGE_END - case 448: -#line 211 "third_party/libpg_query/grammar/statements/copy.y" - { (yyval.str) = NULL; ;} - break; +#endif - case 449: -#line 217 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); - ;} - break; +#if defined(MBEDTLS_PLATFORM_C) - case 450: -#line 221 "third_party/libpg_query/grammar/statements/copy.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); - ;} - break; +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif - case 453: -#line 52 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (3)].node); ;} - break; +#include - case 454: -#line 53 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (3)].node); ;} - break; +#if defined(MBEDTLS_FS_IO) +#include +#endif - case 455: -#line 68 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +#if defined(MBEDTLS_MD5_C) +const mbedtls_md_info_t mbedtls_md5_info = { + "MD5", + MBEDTLS_MD_MD5, + 16, + 64, +}; +#endif - case 456: -#line 70 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].list), NIL, - NULL, NULL, NULL, - yyscanner); - (yyval.node) = (yyvsp[(1) - (2)].node); - ;} - break; +#if defined(MBEDTLS_RIPEMD160_C) +const mbedtls_md_info_t mbedtls_ripemd160_info = { + "RIPEMD160", + MBEDTLS_MD_RIPEMD160, + 20, + 64, +}; +#endif - case 457: -#line 77 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(1) - (4)].node), (yyvsp[(2) - (4)].list), (yyvsp[(3) - (4)].list), - (PGNode*) list_nth((yyvsp[(4) - (4)].list), 0), (PGNode*) list_nth((yyvsp[(4) - (4)].list), 1), - NULL, - yyscanner); - (yyval.node) = (yyvsp[(1) - (4)].node); - ;} - break; +#if defined(MBEDTLS_SHA1_C) +const mbedtls_md_info_t mbedtls_sha1_info = { + "SHA1", + MBEDTLS_MD_SHA1, + 20, + 64, +}; +#endif - case 458: -#line 85 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(1) - (4)].node), (yyvsp[(2) - (4)].list), (yyvsp[(4) - (4)].list), - (PGNode*) list_nth((yyvsp[(3) - (4)].list), 0), (PGNode*) list_nth((yyvsp[(3) - (4)].list), 1), - NULL, - yyscanner); - (yyval.node) = (yyvsp[(1) - (4)].node); - ;} - break; +#if defined(MBEDTLS_SHA224_C) +const mbedtls_md_info_t mbedtls_sha224_info = { + "SHA224", + MBEDTLS_MD_SHA224, + 28, + 64, +}; +#endif - case 459: -#line 93 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(2) - (2)].node), NULL, NIL, - NULL, NULL, - (yyvsp[(1) - (2)].with), - yyscanner); - (yyval.node) = (yyvsp[(2) - (2)].node); - ;} - break; +#if defined(MBEDTLS_SHA256_C) +const mbedtls_md_info_t mbedtls_sha256_info = { + "SHA256", + MBEDTLS_MD_SHA256, + 32, + 64, +}; +#endif - case 460: -#line 101 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(2) - (3)].node), (yyvsp[(3) - (3)].list), NIL, - NULL, NULL, - (yyvsp[(1) - (3)].with), - yyscanner); - (yyval.node) = (yyvsp[(2) - (3)].node); - ;} - break; +#if defined(MBEDTLS_SHA384_C) +const mbedtls_md_info_t mbedtls_sha384_info = { + "SHA384", + MBEDTLS_MD_SHA384, + 48, + 128, +}; +#endif - case 461: -#line 109 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(2) - (5)].node), (yyvsp[(3) - (5)].list), (yyvsp[(4) - (5)].list), - (PGNode*) list_nth((yyvsp[(5) - (5)].list), 0), (PGNode*) list_nth((yyvsp[(5) - (5)].list), 1), - (yyvsp[(1) - (5)].with), - yyscanner); - (yyval.node) = (yyvsp[(2) - (5)].node); - ;} - break; +#if defined(MBEDTLS_SHA512_C) +const mbedtls_md_info_t mbedtls_sha512_info = { + "SHA512", + MBEDTLS_MD_SHA512, + 64, + 128, +}; +#endif - case 462: -#line 117 "third_party/libpg_query/grammar/statements/select.y" - { - insertSelectOptions((PGSelectStmt *) (yyvsp[(2) - (5)].node), (yyvsp[(3) - (5)].list), (yyvsp[(5) - (5)].list), - (PGNode*) list_nth((yyvsp[(4) - (5)].list), 0), (PGNode*) list_nth((yyvsp[(4) - (5)].list), 1), - (yyvsp[(1) - (5)].with), - yyscanner); - (yyval.node) = (yyvsp[(2) - (5)].node); - ;} - break; +/* + * Reminder: update profiles in x509_crt.c when adding a new hash! + */ +static const int supported_digests[] = { - case 463: -#line 127 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, +#endif - case 464: -#line 128 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +#if defined(MBEDTLS_SHA384_C) + MBEDTLS_MD_SHA384, +#endif - case 465: -#line 158 "third_party/libpg_query/grammar/statements/select.y" - { - PGSelectStmt *n = makeNode(PGSelectStmt); - n->targetList = (yyvsp[(3) - (11)].list); - n->intoClause = (yyvsp[(4) - (11)].into); - n->fromClause = (yyvsp[(5) - (11)].list); - n->whereClause = (yyvsp[(6) - (11)].node); - n->groupClause = (yyvsp[(7) - (11)].list); - n->havingClause = (yyvsp[(8) - (11)].node); - n->windowClause = (yyvsp[(9) - (11)].list); - n->qualifyClause = (yyvsp[(10) - (11)].node); - n->sampleOptions = (yyvsp[(11) - (11)].node); - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, +#endif +#if defined(MBEDTLS_SHA224_C) + MBEDTLS_MD_SHA224, +#endif - case 466: -#line 174 "third_party/libpg_query/grammar/statements/select.y" - { - PGSelectStmt *n = makeNode(PGSelectStmt); - n->distinctClause = (yyvsp[(2) - (11)].list); - n->targetList = (yyvsp[(3) - (11)].list); - n->intoClause = (yyvsp[(4) - (11)].into); - n->fromClause = (yyvsp[(5) - (11)].list); - n->whereClause = (yyvsp[(6) - (11)].node); - n->groupClause = (yyvsp[(7) - (11)].list); - n->havingClause = (yyvsp[(8) - (11)].node); - n->windowClause = (yyvsp[(9) - (11)].list); - n->qualifyClause = (yyvsp[(10) - (11)].node); - n->sampleOptions = (yyvsp[(11) - (11)].node); - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_MD_SHA1, +#endif - case 467: -#line 188 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +#if defined(MBEDTLS_RIPEMD160_C) + MBEDTLS_MD_RIPEMD160, +#endif - case 468: -#line 190 "third_party/libpg_query/grammar/statements/select.y" - { - /* same as SELECT * FROM relation_expr */ - PGColumnRef *cr = makeNode(PGColumnRef); - PGResTarget *rt = makeNode(PGResTarget); - PGSelectStmt *n = makeNode(PGSelectStmt); +#if defined(MBEDTLS_MD5_C) + MBEDTLS_MD_MD5, +#endif - cr->fields = list_make1(makeNode(PGAStar)); - cr->location = -1; + MBEDTLS_MD_NONE +}; - rt->name = NULL; - rt->indirection = NIL; - rt->val = (PGNode *)cr; - rt->location = -1; +const int *mbedtls_md_list( void ) +{ + return( supported_digests ); +} - n->targetList = list_make1(rt); - n->fromClause = list_make1((yyvsp[(2) - (2)].range)); - (yyval.node) = (PGNode *)n; - ;} - break; +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) +{ + if( NULL == md_name ) + return( NULL ); - case 469: -#line 209 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSetOp(PG_SETOP_UNION, (yyvsp[(3) - (4)].boolean), (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node)); - ;} - break; + /* Get the appropriate digest information */ +#if defined(MBEDTLS_MD5_C) + if( !strcmp( "MD5", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + if( !strcmp( "RIPEMD160", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); +#endif +#if defined(MBEDTLS_SHA1_C) + if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA224_C) + if( !strcmp( "SHA224", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); +#endif +#if defined(MBEDTLS_SHA256_C) + if( !strcmp( "SHA256", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA384_C) + if( !strcmp( "SHA384", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); +#endif +#if defined(MBEDTLS_SHA512_C) + if( !strcmp( "SHA512", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); +#endif + return( NULL ); +} - case 470: -#line 213 "third_party/libpg_query/grammar/statements/select.y" +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) +{ + switch( md_type ) { - (yyval.node) = makeSetOp(PG_SETOP_INTERSECT, (yyvsp[(3) - (4)].boolean), (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node)); - ;} - break; +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( &mbedtls_md5_info ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( &mbedtls_ripemd160_info ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( &mbedtls_sha1_info ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( &mbedtls_sha224_info ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( &mbedtls_sha256_info ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( &mbedtls_sha384_info ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( &mbedtls_sha512_info ); +#endif + default: + return( NULL ); + } +} - case 471: -#line 217 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSetOp(PG_SETOP_EXCEPT, (yyvsp[(3) - (4)].boolean), (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node)); - ;} - break; +void mbedtls_md_init( mbedtls_md_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); +} - case 472: -#line 234 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.with) = makeNode(PGWithClause); - (yyval.with)->ctes = (yyvsp[(2) - (2)].list); - (yyval.with)->recursive = false; - (yyval.with)->location = (yylsp[(1) - (2)]); - ;} - break; +void mbedtls_md_free( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return; - case 473: -#line 241 "third_party/libpg_query/grammar/statements/select.y" + if( ctx->md_ctx != NULL ) { - (yyval.with) = makeNode(PGWithClause); - (yyval.with)->ctes = (yyvsp[(2) - (2)].list); - (yyval.with)->recursive = false; - (yyval.with)->location = (yylsp[(1) - (2)]); - ;} - break; + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + mbedtls_md5_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + mbedtls_ripemd160_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + mbedtls_sha1_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + mbedtls_sha256_free((mbedtls_sha256_context *) ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + mbedtls_sha256_free((mbedtls_sha256_context *) ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + mbedtls_sha512_free( ctx->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + mbedtls_sha512_free( ctx->md_ctx ); + break; +#endif + default: + /* Shouldn't happen */ + break; + } + mbedtls_free( ctx->md_ctx ); + } - case 474: -#line 248 "third_party/libpg_query/grammar/statements/select.y" + if( ctx->hmac_ctx != NULL ) { - (yyval.with) = makeNode(PGWithClause); - (yyval.with)->ctes = (yyvsp[(3) - (3)].list); - (yyval.with)->recursive = true; - (yyval.with)->location = (yylsp[(1) - (3)]); - ;} - break; - - case 475: -#line 257 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} - break; + mbedtls_platform_zeroize( ctx->hmac_ctx, + 2 * ctx->md_info->block_size ); + mbedtls_free( ctx->hmac_ctx ); + } - case 476: -#line 258 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} - break; + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); +} - case 477: -#line 262 "third_party/libpg_query/grammar/statements/select.y" +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ) +{ + if( dst == NULL || dst->md_info == NULL || + src == NULL || src->md_info == NULL || + dst->md_info != src->md_info ) { - PGCommonTableExpr *n = makeNode(PGCommonTableExpr); - n->ctename = (yyvsp[(1) - (6)].str); - n->aliascolnames = (yyvsp[(2) - (6)].list); - n->ctequery = (yyvsp[(5) - (6)].node); - n->location = (yylsp[(1) - (6)]); - (yyval.node) = (PGNode *) n; - ;} - break; + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } - case 478: -#line 274 "third_party/libpg_query/grammar/statements/select.y" + switch( src->md_info->type ) { - (yyval.into) = makeNode(PGIntoClause); - (yyval.into)->rel = (yyvsp[(2) - (2)].range); - (yyval.into)->colNames = NIL; - (yyval.into)->options = NIL; - (yyval.into)->onCommit = PG_ONCOMMIT_NOOP; - (yyval.into)->viewQuery = NULL; - (yyval.into)->skipData = false; - ;} - break; +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + mbedtls_md5_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + mbedtls_ripemd160_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + mbedtls_sha1_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + mbedtls_sha256_clone((mbedtls_sha256_context *) dst->md_ctx, (mbedtls_sha256_context *) src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + mbedtls_sha256_clone((mbedtls_sha256_context *) dst->md_ctx, (mbedtls_sha256_context *)src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + mbedtls_sha512_clone( dst->md_ctx, src->md_ctx ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + mbedtls_sha512_clone( dst->md_ctx, src->md_ctx ); + break; +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } - case 479: -#line 284 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.into) = NULL; ;} - break; + return( 0 ); +} - case 480: -#line 293 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.range) = (yyvsp[(3) - (3)].range); - (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; - ;} - break; +#define ALLOC( type ) \ + do { \ + ctx->md_ctx = (mbedtls_##type##_context*) mbedtls_calloc( 1, sizeof( mbedtls_##type##_context ) ); \ + if( ctx->md_ctx == NULL ) \ + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); \ + mbedtls_##type##_init((mbedtls_##type##_context*) ctx->md_ctx ); \ + } \ + while( 0 ) - case 481: -#line 298 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.range) = (yyvsp[(3) - (3)].range); - (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; - ;} - break; +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) +{ + if( md_info == NULL || ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - case 482: -#line 303 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.range) = (yyvsp[(4) - (4)].range); - (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; - ;} - break; + ctx->md_info = md_info; + ctx->md_ctx = NULL; + ctx->hmac_ctx = NULL; - case 483: -#line 308 "third_party/libpg_query/grammar/statements/select.y" + switch( md_info->type ) { - (yyval.range) = (yyvsp[(4) - (4)].range); - (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; - ;} - break; +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + ALLOC( md5 ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + ALLOC( ripemd160 ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + ALLOC( sha1 ); + break; +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + ALLOC( sha256 ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + ALLOC( sha256 ); + break; +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + ALLOC( sha512 ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + ALLOC( sha512 ); + break; +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } - case 484: -#line 313 "third_party/libpg_query/grammar/statements/select.y" + if( hmac != 0 ) { - ereport(PGWARNING, - (errmsg("GLOBAL is deprecated in temporary table creation"), - parser_errposition((yylsp[(1) - (4)])))); - (yyval.range) = (yyvsp[(4) - (4)].range); - (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; - ;} - break; + ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); + if( ctx->hmac_ctx == NULL ) + { + mbedtls_md_free( ctx ); + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + } + } - case 485: -#line 321 "third_party/libpg_query/grammar/statements/select.y" - { - ereport(PGWARNING, - (errmsg("GLOBAL is deprecated in temporary table creation"), - parser_errposition((yylsp[(1) - (4)])))); - (yyval.range) = (yyvsp[(4) - (4)].range); - (yyval.range)->relpersistence = PG_RELPERSISTENCE_TEMP; - ;} - break; + return( 0 ); +} +#undef ALLOC - case 486: -#line 329 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.range) = (yyvsp[(3) - (3)].range); - (yyval.range)->relpersistence = PG_RELPERSISTENCE_UNLOGGED; - ;} - break; +int mbedtls_md_starts( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - case 487: -#line 334 "third_party/libpg_query/grammar/statements/select.y" + switch( ctx->md_info->type ) { - (yyval.range) = (yyvsp[(2) - (2)].range); - (yyval.range)->relpersistence = RELPERSISTENCE_PERMANENT; - ;} - break; +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_starts( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_starts( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_starts( ctx->md_ctx ) ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256_starts( (mbedtls_sha256_context *)ctx->md_ctx, 1 ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_starts( (mbedtls_sha256_context *) ctx->md_ctx, 0 ) ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512_starts( ctx->md_ctx, 1 ) ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_starts( ctx->md_ctx, 0 ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} - case 488: -#line 339 "third_party/libpg_query/grammar/statements/select.y" +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + switch( ctx->md_info->type ) { - (yyval.range) = (yyvsp[(1) - (1)].range); - (yyval.range)->relpersistence = RELPERSISTENCE_PERMANENT; - ;} - break; +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_update( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_update( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_update( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256_update( (mbedtls_sha256_context *)ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_update( (mbedtls_sha256_context *)ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512_update( ctx->md_ctx, input, ilen ) ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_update( ctx->md_ctx, input, ilen ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} - case 489: -#line 345 "third_party/libpg_query/grammar/statements/select.y" - {;} - break; +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - case 490: -#line 346 "third_party/libpg_query/grammar/statements/select.y" - {;} - break; + switch( ctx->md_info->type ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5_finish( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160_finish( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1_finish( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256_finish((mbedtls_sha256_context *) ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256_finish((mbedtls_sha256_context *) (mbedtls_sha256_context *)ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512_finish( ctx->md_ctx, output ) ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512_finish( ctx->md_ctx, output ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} - case 491: -#line 350 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = true; ;} - break; +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - case 492: -#line 351 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} - break; + switch( md_info->type ) + { +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_md5( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_ripemd160( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_sha1( input, ilen, output ) ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_sha256( input, ilen, output, 1 ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( mbedtls_sha256( input, ilen, output, 0 ) ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( mbedtls_sha512( input, ilen, output, 1 ) ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( mbedtls_sha512( input, ilen, output, 0 ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} - case 493: -#line 352 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} - break; +#if defined(MBEDTLS_FS_IO) +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + FILE *f; + size_t n; + mbedtls_md_context_t ctx; + unsigned char buf[1024]; - case 494: -#line 359 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(NIL); ;} - break; + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - case 495: -#line 360 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(4) - (5)].list); ;} - break; + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); - case 496: -#line 364 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL;;} - break; + mbedtls_md_init( &ctx ); - case 497: -#line 365 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + goto cleanup; - case 498: -#line 369 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = true;;} - break; + if( ( ret = mbedtls_md_starts( &ctx ) ) != 0 ) + goto cleanup; - case 499: -#line 370 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false;;} - break; + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + if( ( ret = mbedtls_md_update( &ctx, buf, n ) ) != 0 ) + goto cleanup; - case 500: -#line 371 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} - break; + if( ferror( f ) != 0 ) + ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; + else + ret = mbedtls_md_finish( &ctx, output ); - case 501: -#line 375 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list);;} - break; +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + fclose( f ); + mbedtls_md_free( &ctx ); - case 502: -#line 376 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ - case 503: -#line 380 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (3)].list); ;} - break; +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char sum[MBEDTLS_MD_MAX_SIZE]; + unsigned char *ipad, *opad; + size_t i; - case 504: -#line 382 "third_party/libpg_query/grammar/statements/select.y" - { - PGSortBy *sort = makeNode(PGSortBy); - sort->node = (PGNode *) makeNode(PGAStar); - sort->sortby_dir = (yyvsp[(4) - (5)].sortorder); - sort->sortby_nulls = (yyvsp[(5) - (5)].nullorder); - sort->useOp = NIL; - sort->location = -1; /* no operator */ - (yyval.list) = list_make1(sort); - ;} - break; + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - case 505: -#line 392 "third_party/libpg_query/grammar/statements/select.y" + if( keylen > (size_t) ctx->md_info->block_size ) { - PGSortBy *sort = makeNode(PGSortBy); - sort->node = (PGNode *) makeNode(PGAStar); - sort->sortby_dir = (yyvsp[(4) - (5)].sortorder); - sort->sortby_nulls = (yyvsp[(5) - (5)].nullorder); - sort->useOp = NIL; - sort->location = -1; /* no operator */ - (yyval.list) = list_make1(sort); - ;} - break; - - case 506: -#line 404 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].sortby)); ;} - break; + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_update( ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_finish( ctx, sum ) ) != 0 ) + goto cleanup; + + keylen = ctx->md_info->size; + key = sum; + } - case 507: -#line 405 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].sortby)); ;} - break; + ipad = (unsigned char *) ctx->hmac_ctx; + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; - case 508: -#line 409 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.sortby) = makeNode(PGSortBy); - (yyval.sortby)->node = (yyvsp[(1) - (4)].node); - (yyval.sortby)->sortby_dir = SORTBY_USING; - (yyval.sortby)->sortby_nulls = (yyvsp[(4) - (4)].nullorder); - (yyval.sortby)->useOp = (yyvsp[(3) - (4)].list); - (yyval.sortby)->location = (yylsp[(3) - (4)]); - ;} - break; + memset( ipad, 0x36, ctx->md_info->block_size ); + memset( opad, 0x5C, ctx->md_info->block_size ); - case 509: -#line 418 "third_party/libpg_query/grammar/statements/select.y" + for( i = 0; i < keylen; i++ ) { - (yyval.sortby) = makeNode(PGSortBy); - (yyval.sortby)->node = (yyvsp[(1) - (3)].node); - (yyval.sortby)->sortby_dir = (yyvsp[(2) - (3)].sortorder); - (yyval.sortby)->sortby_nulls = (yyvsp[(3) - (3)].nullorder); - (yyval.sortby)->useOp = NIL; - (yyval.sortby)->location = -1; /* no operator */ - ;} - break; + ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); + opad[i] = (unsigned char)( opad[i] ^ key[i] ); + } - case 510: -#line 428 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.sortorder) = PG_SORTBY_ASC; ;} - break; + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_update( ctx, ipad, + ctx->md_info->block_size ) ) != 0 ) + goto cleanup; - case 511: -#line 429 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.sortorder) = PG_SORTBY_DESC; ;} - break; +cleanup: + mbedtls_platform_zeroize( sum, sizeof( sum ) ); - case 512: -#line 430 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.sortorder) = PG_SORTBY_DEFAULT; ;} - break; + return( ret ); +} - case 513: -#line 433 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.nullorder) = PG_SORTBY_NULLS_FIRST; ;} - break; +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - case 514: -#line 434 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.nullorder) = PG_SORTBY_NULLS_LAST; ;} - break; + return( mbedtls_md_update( ctx, input, ilen ) ); +} - case 515: -#line 435 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.nullorder) = PG_SORTBY_NULLS_DEFAULT; ;} - break; +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; + unsigned char *opad; - case 516: -#line 439 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2((yyvsp[(2) - (2)].node), (yyvsp[(1) - (2)].node)); ;} - break; + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - case 517: -#line 440 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); ;} - break; + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; - case 518: -#line 441 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2(NULL, (yyvsp[(1) - (1)].node)); ;} - break; + if( ( ret = mbedtls_md_finish( ctx, tmp ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_update( ctx, opad, + ctx->md_info->block_size ) ) != 0 ) + return( ret ); + if( ( ret = mbedtls_md_update( ctx, tmp, + ctx->md_info->size ) ) != 0 ) + return( ret ); + return( mbedtls_md_finish( ctx, output ) ); +} - case 519: -#line 442 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2((yyvsp[(1) - (1)].node), NULL); ;} - break; +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *ipad; - case 520: -#line 446 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - case 521: -#line 447 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2(NULL,NULL); ;} - break; + ipad = (unsigned char *) ctx->hmac_ctx; - case 522: -#line 452 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} - break; + if( ( ret = mbedtls_md_starts( ctx ) ) != 0 ) + return( ret ); + return( mbedtls_md_update( ctx, ipad, ctx->md_info->block_size ) ); +} - case 523: -#line 454 "third_party/libpg_query/grammar/statements/select.y" - { - /* Disabled because it was too confusing, bjm 2002-02-18 */ - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("LIMIT #,# syntax is not supported"), - errhint("Use separate LIMIT and OFFSET clauses."), - parser_errposition((yylsp[(1) - (4)])))); - ;} - break; +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_md_context_t ctx; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - case 524: -#line 470 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(3) - (5)].node); ;} - break; + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - case 525: -#line 472 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeIntConst(1, -1); ;} - break; + mbedtls_md_init( &ctx ); - case 526: -#line 477 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} - break; + if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) + goto cleanup; - case 527: -#line 480 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (3)].node); ;} - break; + if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 ) + goto cleanup; - case 528: -#line 488 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleSize(makeFloat((yyvsp[(1) - (2)].str)), true); - ;} - break; +cleanup: + mbedtls_md_free( &ctx ); - case 529: -#line 492 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleSize(makeInteger((yyvsp[(1) - (2)].ival)), true); - ;} - break; + return( ret ); +} - case 530: -#line 496 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleSize(makeFloat((yyvsp[(1) - (2)].str)), true); - ;} - break; +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); - case 531: -#line 500 "third_party/libpg_query/grammar/statements/select.y" + switch( ctx->md_info->type ) { - (yyval.node) = makeSampleSize(makeInteger((yyvsp[(1) - (2)].ival)), true); - ;} - break; +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( mbedtls_internal_md5_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( mbedtls_internal_ripemd160_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( mbedtls_internal_sha1_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA224_C) + case MBEDTLS_MD_SHA224: + return( mbedtls_internal_sha256_process((mbedtls_sha256_context *) ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA256: + return( mbedtls_internal_sha256_process((mbedtls_sha256_context *) ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA384_C) + case MBEDTLS_MD_SHA384: + return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA512: + return( mbedtls_internal_sha512_process( ctx->md_ctx, data ) ); +#endif + default: + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } +} - case 532: -#line 504 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleSize(makeInteger((yyvsp[(1) - (1)].ival)), false); - ;} - break; +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( 0 ); - case 533: -#line 508 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleSize(makeInteger((yyvsp[(1) - (2)].ival)), false); - ;} - break; + return md_info->size; +} - case 534: -#line 515 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (yyvsp[(3) - (3)].node); - ;} - break; +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( MBEDTLS_MD_NONE ); - case 535: -#line 519 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; + return md_info->type; +} - case 536: -#line 526 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( NULL ); - case 537: -#line 527 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = NULL; ;} - break; + return md_info->name; +} - case 538: -#line 532 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleOptions((yyvsp[(3) - (5)].node), (yyvsp[(1) - (5)].str), (yyvsp[(5) - (5)].ival), (yylsp[(1) - (5)])); - ;} - break; +#endif /* MBEDTLS_MD_C */ - case 539: -#line 536 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleOptions((yyvsp[(1) - (1)].node), NULL, -1, (yylsp[(1) - (1)])); - ;} - break; - case 540: -#line 540 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleOptions((yyvsp[(1) - (4)].node), (yyvsp[(3) - (4)].str), -1, (yylsp[(1) - (4)])); - ;} - break; +// LICENSE_CHANGE_END - case 541: -#line 544 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSampleOptions((yyvsp[(1) - (6)].node), (yyvsp[(3) - (6)].str), (yyvsp[(5) - (6)].ival), (yylsp[(1) - (6)])); - ;} - break; - case 542: -#line 551 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (yyvsp[(2) - (2)].node); - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 543: -#line 557 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +/** + * \file oid.c + * + * \brief Object Identifier (OID) database + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - case 544: -#line 558 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; - case 545: -#line 563 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = (yyvsp[(3) - (4)].ival); ;} - break; - case 546: -#line 564 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = -1; ;} - break; +#if defined(MBEDTLS_OID_C) - case 547: -#line 568 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; - case 548: -#line 570 "third_party/libpg_query/grammar/statements/select.y" - { - /* LIMIT ALL is represented as a NULL constant */ - (yyval.node) = makeNullAConst((yylsp[(1) - (1)])); - ;} - break; - case 549: -#line 575 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeLimitPercent((yyvsp[(1) - (2)].node)); ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 550: -#line 577 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeLimitPercent(makeFloatConst((yyvsp[(1) - (2)].str),(yylsp[(1) - (2)]))); ;} - break; +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_OID_H +#define MBEDTLS_OID_H - case 551: -#line 579 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeLimitPercent(makeIntConst((yyvsp[(1) - (2)].ival),(yylsp[(1) - (2)]))); ;} - break; - case 552: -#line 583 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; - case 553: -#line 603 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; - case 554: -#line 605 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} - break; - case 555: -#line 607 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = doNegate((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} - break; - case 556: -#line 611 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeIntConst((yyvsp[(1) - (1)].ival),(yylsp[(1) - (1)])); ;} - break; - case 557: -#line 612 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeFloatConst((yyvsp[(1) - (1)].str),(yylsp[(1) - (1)])); ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 558: -#line 616 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = 0; ;} - break; +/** + * \file pk.h + * + * \brief Public Key abstraction layer + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - case 559: -#line 617 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = 0; ;} - break; +#ifndef MBEDTLS_PK_H +#define MBEDTLS_PK_H - case 560: -#line 620 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = 0; ;} - break; - case 561: -#line 621 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = 0; ;} - break; - case 562: -#line 646 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (3)].list); ;} - break; - case 563: -#line 648 "third_party/libpg_query/grammar/statements/select.y" - { - PGNode *node = (PGNode *) makeGroupingSet(GROUPING_SET_ALL, NIL, (yylsp[(3) - (3)])); - (yyval.list) = list_make1(node); - ;} - break; - case 564: -#line 653 "third_party/libpg_query/grammar/statements/select.y" - { - PGNode *node = (PGNode *) makeGroupingSet(GROUPING_SET_ALL, NIL, (yylsp[(3) - (3)])); - (yyval.list) = list_make1(node); - ;} - break; - case 565: -#line 657 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +#if defined(MBEDTLS_RSA_C) - case 566: -#line 661 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} - break; +#endif - case 567: -#line 662 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list),(yyvsp[(3) - (3)].node)); ;} - break; +#if defined(MBEDTLS_ECP_C) - case 568: -#line 666 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; - case 569: -#line 667 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 570: -#line 671 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +// dummy file to make amalgamantion happy - case 571: -#line 672 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +// LICENSE_CHANGE_END - case 572: -#line 673 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +#endif - case 573: -#line 674 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +#if defined(MBEDTLS_ECDSA_C) - case 574: -#line 675 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; - case 575: -#line 680 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_EMPTY, NIL, (yylsp[(1) - (2)])); - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 576: -#line 693 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_ROLLUP, (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} - break; +// dummy file to make amalgamantion happy - case 577: -#line 700 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_CUBE, (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} - break; +// LICENSE_CHANGE_END - case 578: -#line 707 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeGroupingSet(GROUPING_SET_SETS, (yyvsp[(4) - (5)].list), (yylsp[(1) - (5)])); - ;} - break; +#endif - case 579: -#line 713 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; +#if defined(MBEDTLS_USE_PSA_CRYPTO) - case 580: -#line 714 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; - case 581: -#line 718 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 582: -#line 719 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; +// dummy file to make amalgamantion happy - case 583: -#line 723 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} - break; +// LICENSE_CHANGE_END - case 584: -#line 724 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; +#endif - case 585: -#line 728 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif - case 586: -#line 729 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +/** Memory allocation failed. */ +#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 +/** Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 +/** Read/write of file failed. */ +#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 +/** Unsupported key version */ +#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 +/** Invalid key tag or value. */ +#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 +/** Key algorithm is unsupported (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 +/** Private key password can't be empty. */ +#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 +/** Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 +/** The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 +/** The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 +/** Elliptic curve is unsupported (only NIST curves are supported). */ +#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 +/** Unavailable feature, e.g. RSA disabled for RSA key. */ +#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 +/** The buffer contains a valid signature followed by more data. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 +/** The output buffer is too small. */ +#define MBEDTLS_ERR_PK_BUFFER_TOO_SMALL -0x3880 - case 587: -#line 733 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; +#ifdef __cplusplus +extern "C" { +#endif - case 588: -#line 734 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +/** + * \brief Public key types + */ +typedef enum { + MBEDTLS_PK_NONE=0, + MBEDTLS_PK_RSA, + MBEDTLS_PK_ECKEY, + MBEDTLS_PK_ECKEY_DH, + MBEDTLS_PK_ECDSA, + MBEDTLS_PK_RSA_ALT, + MBEDTLS_PK_RSASSA_PSS, + MBEDTLS_PK_OPAQUE, +} mbedtls_pk_type_t; - case 589: -#line 738 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} - break; +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c mbedtls_rsa_rsassa_pss_verify_ext() + */ +typedef struct mbedtls_pk_rsassa_pss_options +{ + mbedtls_md_type_t MBEDTLS_PRIVATE(mgf1_hash_id); + int MBEDTLS_PRIVATE(expected_salt_len); - case 590: -#line 739 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} - break; +} mbedtls_pk_rsassa_pss_options; - case 591: -#line 744 "third_party/libpg_query/grammar/statements/select.y" - { - PGLockingClause *n = makeNode(PGLockingClause); - n->lockedRels = (yyvsp[(2) - (3)].list); - n->strength = (yyvsp[(1) - (3)].lockstrength); - n->waitPolicy = (yyvsp[(3) - (3)].lockwaitpolicy); - (yyval.node) = (PGNode *) n; - ;} - break; +/** + * \brief Maximum size of a signature made by mbedtls_pk_sign(). + */ +/* We need to set MBEDTLS_PK_SIGNATURE_MAX_SIZE to the maximum signature + * size among the supported signature types. Do it by starting at 0, + * then incrementally increasing to be large enough for each supported + * signature mechanism. + * + * The resulting value can be 0, for example if MBEDTLS_ECDH_C is enabled + * (which allows the pk module to be included) but neither MBEDTLS_ECDSA_C + * nor MBEDTLS_RSA_C nor any opaque signature mechanism (PSA or RSA_ALT). + */ +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE 0 + +#if ( defined(MBEDTLS_RSA_C) || defined(MBEDTLS_PK_RSA_ALT_SUPPORT) ) && \ + MBEDTLS_MPI_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For RSA, the signature can be as large as the bignum module allows. + * For RSA_ALT, the signature size is not necessarily tied to what the + * bignum module can do, but in the absence of any specific setting, + * we use that (rsa_alt_sign_wrap in library/pk_wrap.h will check). */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_MPI_MAX_SIZE +#endif - case 592: -#line 754 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockstrength) = LCS_FORUPDATE; ;} - break; +#if defined(MBEDTLS_ECDSA_C) && \ + MBEDTLS_ECDSA_MAX_LEN > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* For ECDSA, the ecdsa module exports a constant for the maximum + * signature size. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE MBEDTLS_ECDSA_MAX_LEN +#endif - case 593: -#line 755 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockstrength) = PG_LCS_FORNOKEYUPDATE; ;} - break; +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#if PSA_SIGNATURE_MAX_SIZE > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* PSA_SIGNATURE_MAX_SIZE is the maximum size of a signature made + * through the PSA API in the PSA representation. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE PSA_SIGNATURE_MAX_SIZE +#endif - case 594: -#line 756 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockstrength) = PG_LCS_FORSHARE; ;} - break; +#if PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 > MBEDTLS_PK_SIGNATURE_MAX_SIZE +/* The Mbed TLS representation is different for ECDSA signatures: + * PSA uses the raw concatenation of r and s, + * whereas Mbed TLS uses the ASN.1 representation (SEQUENCE of two INTEGERs). + * Add the overhead of ASN.1: up to (1+2) + 2 * (1+2+1) for the + * types, lengths (represented by up to 2 bytes), and potential leading + * zeros of the INTEGERs and the SEQUENCE. */ +#undef MBEDTLS_PK_SIGNATURE_MAX_SIZE +#define MBEDTLS_PK_SIGNATURE_MAX_SIZE ( PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE + 11 ) +#endif +#endif /* defined(MBEDTLS_USE_PSA_CRYPTO) */ - case 595: -#line 757 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockstrength) = PG_LCS_FORKEYSHARE; ;} - break; +/** + * \brief Types for interfacing with the debug module + */ +typedef enum +{ + MBEDTLS_PK_DEBUG_NONE = 0, + MBEDTLS_PK_DEBUG_MPI, + MBEDTLS_PK_DEBUG_ECP, +} mbedtls_pk_debug_type; - case 596: -#line 761 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} - break; +/** + * \brief Item to send to the debug module + */ +typedef struct mbedtls_pk_debug_item +{ + mbedtls_pk_debug_type MBEDTLS_PRIVATE(type); + const char *MBEDTLS_PRIVATE(name); + void *MBEDTLS_PRIVATE(value); +} mbedtls_pk_debug_item; - case 597: -#line 762 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +/** Maximum number of item send for debugging, plus 1 */ +#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 - case 598: -#line 767 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockwaitpolicy) = LockWaitError; ;} - break; +/** + * \brief Public key information and operations + * + * \note The library does not support custom pk info structures, + * only built-in structures returned by + * mbedtls_cipher_info_from_type(). + */ +typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; - case 599: -#line 768 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockwaitpolicy) = PGLockWaitSkip; ;} - break; +/** + * \brief Public key container + */ +typedef struct mbedtls_pk_context +{ + const mbedtls_pk_info_t * MBEDTLS_PRIVATE(pk_info); /**< Public key information */ + void * MBEDTLS_PRIVATE(pk_ctx); /**< Underlying public key context */ +} mbedtls_pk_context; - case 600: -#line 769 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.lockwaitpolicy) = PGLockWaitBlock; ;} - break; +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Context for resuming operations + */ +typedef struct +{ + const mbedtls_pk_info_t * MBEDTLS_PRIVATE(pk_info); /**< Public key information */ + void * MBEDTLS_PRIVATE(rs_ctx); /**< Underlying restart context */ +} mbedtls_pk_restart_ctx; +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ +/* Now we can declare functions that take a pointer to that */ +typedef void mbedtls_pk_restart_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + +#if defined(MBEDTLS_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning You must make sure the PK context actually holds an RSA context + * before using this function! + */ +static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) +{ + return( (mbedtls_rsa_context *) (pk).MBEDTLS_PRIVATE(pk_ctx) ); +} +#endif /* MBEDTLS_RSA_C */ - case 601: -#line 779 "third_party/libpg_query/grammar/statements/select.y" - { - PGSelectStmt *n = makeNode(PGSelectStmt); - n->valuesLists = list_make1((yyvsp[(3) - (4)].list)); - (yyval.node) = (PGNode *) n; - ;} - break; +#if defined(MBEDTLS_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning You must make sure the PK context actually holds an EC context + * before using this function! + */ +static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) +{ + return( (mbedtls_ecp_keypair *) (pk).MBEDTLS_PRIVATE(pk_ctx) ); +} +#endif /* MBEDTLS_ECP_C */ - case 602: -#line 785 "third_party/libpg_query/grammar/statements/select.y" - { - PGSelectStmt *n = (PGSelectStmt *) (yyvsp[(1) - (5)].node); - n->valuesLists = lappend(n->valuesLists, (yyvsp[(4) - (5)].list)); - (yyval.node) = (PGNode *) n; - ;} - break; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - case 603: -#line 793 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \return The PK info associated with the type or NULL if not found. + */ +const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); - case 604: -#line 794 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (2)].node); ;} - break; +/** + * \brief Initialize a #mbedtls_pk_context (as NONE). + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ); - case 605: -#line 807 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} - break; +/** + * \brief Free the components of a #mbedtls_pk_context. + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + * + * \note For contexts that have been set up with + * mbedtls_pk_setup_opaque(), this does not free the underlying + * PSA key and you still need to call psa_destroy_key() + * independently if you want to destroy that key. + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ); - case 606: -#line 808 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/** + * \brief Initialize a restart context + * + * \param ctx The context to initialize. + * This must not be \c NULL. + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ); - case 607: -#line 812 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} - break; +/** + * \brief Free the components of a restart context + * + * \param ctx The context to clear. It must have been initialized. + * If this is \c NULL, this function does nothing. + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - case 608: -#line 813 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} - break; +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param info Information to use + * + * \return 0 on success, + * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, + * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c mbedtls_pk_setup_rsa_alt() instead. + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); - case 609: -#line 817 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Initialize a PK context to wrap a PSA key. + * + * \note This function replaces mbedtls_pk_setup() for contexts + * that wrap a (possibly opaque) PSA key instead of + * storing and manipulating the key material directly. + * + * \param ctx The context to initialize. It must be empty (type NONE). + * \param key The PSA key to wrap, which must hold an ECC key pair + * (see notes below). + * + * \note The wrapped key must remain valid as long as the + * wrapping PK context is in use, that is at least between + * the point this function is called and the point + * mbedtls_pk_free() is called on this context. The wrapped + * key might then be independently used or destroyed. + * + * \note This function is currently only available for ECC key + * pairs (that is, ECC keys containing private key material). + * Support for other key types may be added later. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input + * (context already used, invalid key identifier). + * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the key is not an + * ECC key pair. + * \return #MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + */ +int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, + const psa_key_id_t key ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ - case 610: -#line 818 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} - break; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. It must not have been set + * up yet (type #MBEDTLS_PK_NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - case 611: -#line 825 "third_party/libpg_query/grammar/statements/select.y" - { - (yyvsp[(1) - (3)].range)->alias = (yyvsp[(2) - (3)].alias); - (yyvsp[(1) - (3)].range)->sample = (yyvsp[(3) - (3)].node); - (yyval.node) = (PGNode *) (yyvsp[(1) - (3)].range); - ;} - break; +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx The context to query. It must have been initialized. + * + * \return Key size in bits, or 0 on error + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); + +///** +// * \brief Get the length in bytes of the underlying key +// * +// * \param ctx The context to query. It must have been initialized. +// * +// * \return Key length in bytes, or 0 on error +// */ +//static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) +//{ +// return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 ); +//} - case 612: -#line 831 "third_party/libpg_query/grammar/statements/select.y" - { - PGRangeFunction *n = (PGRangeFunction *) (yyvsp[(1) - (3)].node); - n->alias = (PGAlias*) linitial((yyvsp[(2) - (3)].list)); - n->coldeflist = (PGList*) lsecond((yyvsp[(2) - (3)].list)); - n->sample = (yyvsp[(3) - (3)].node); - (yyval.node) = (PGNode *) n; - ;} - break; +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx The context to query. It must have been initialized. + * \param type The desired type. + * + * \return 1 if the context can do operations on the given type. + * \return 0 if the context cannot do the operations on the given + * type. This is always the case for a context that has + * been initialized but not set up, or that has been + * cleared with mbedtls_pk_free(). + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); - case 613: -#line 839 "third_party/libpg_query/grammar/statements/select.y" - { - PGRangeFunction *n = (PGRangeFunction *) (yyvsp[(2) - (3)].node); - n->lateral = true; - n->alias = (PGAlias*) linitial((yyvsp[(3) - (3)].list)); - n->coldeflist = (PGList*) lsecond((yyvsp[(3) - (3)].list)); - (yyval.node) = (PGNode *) n; - ;} - break; +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used. + * This can be #MBEDTLS_MD_NONE if the signature algorithm + * does not rely on a hash algorithm (non-deterministic + * ECDSA, RSA PKCS#1 v1.5). + * For PKCS#1 v1.5, if \p md_alg is #MBEDTLS_MD_NONE, then + * \p hash is the DigestInfo structure used by RFC 8017 + * §9.2 steps 3–6. If \p md_alg is a valid hash + * algorithm then \p hash is the digest itself, and this + * function calculates the DigestInfo encoding internally. + * \param hash Hash of the message to sign + * \param hash_len Hash length + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); - case 614: -#line 847 "third_party/libpg_query/grammar/statements/select.y" - { - PGRangeSubselect *n = makeNode(PGRangeSubselect); - n->lateral = false; - n->subquery = (yyvsp[(1) - (3)].node); - n->alias = (yyvsp[(2) - (3)].alias); - n->sample = (yyvsp[(3) - (3)].node); - (yyval.node) = (PGNode *) n; - ;} - break; +/** + * \brief Restartable version of \c mbedtls_pk_verify() + * + * \note Performs the same job as \c mbedtls_pk_verify(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_verify(). + * + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_verify(), or + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ); - case 615: -#line 856 "third_party/libpg_query/grammar/statements/select.y" - { - PGRangeSubselect *n = makeNode(PGRangeSubselect); - n->lateral = true; - n->subquery = (yyvsp[(2) - (3)].node); - n->alias = (yyvsp[(3) - (3)].alias); - n->sample = NULL; - (yyval.node) = (PGNode *) n; - ;} - break; +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx The PK context to use. It must have been set up. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + * + * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point + * to a mbedtls_pk_rsassa_pss_options structure, + * otherwise it must be NULL. + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); - case 616: -#line 865 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) (yyvsp[(1) - (1)].jexpr); - ;} - break; +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_size The size of the \p sig buffer in bytes. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. + * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - case 617: -#line 869 "third_party/libpg_query/grammar/statements/select.y" - { - (yyvsp[(2) - (4)].jexpr)->alias = (yyvsp[(4) - (4)].alias); - (yyval.node) = (PGNode *) (yyvsp[(2) - (4)].jexpr); - ;} - break; +/** + * \brief Restartable version of \c mbedtls_pk_sign() + * + * \note Performs the same job as \c mbedtls_pk_sign(), but can + * return early and restart according to the limit set with + * \c mbedtls_ecp_set_max_ops() to reduce blocking for ECC + * operations. For RSA, same as \c mbedtls_pk_sign(). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param md_alg Hash algorithm used (see notes for mbedtls_pk_sign()) + * \param hash Hash of the message to sign + * \param hash_len Hash length + * \param sig Place to write the signature. + * It must have enough room for the signature. + * #MBEDTLS_PK_SIGNATURE_MAX_SIZE is always enough. + * You may use a smaller buffer if it is large enough + * given the key type. + * \param sig_size The size of the \p sig buffer in bytes. + * \param sig_len On successful return, + * the number of bytes written to \p sig. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * \param rs_ctx Restart context (NULL to disable restart) + * + * \return See \c mbedtls_pk_sign(). + * \return #MBEDTLS_ERR_ECP_IN_PROGRESS if maximum number of + * operations was reached: see \c mbedtls_ecp_set_max_ops(). + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ); - case 618: -#line 895 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.jexpr) = (yyvsp[(2) - (3)].jexpr); - ;} - break; +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up + * with a private key. + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - case 619: -#line 899 "third_party/libpg_query/grammar/statements/select.y" - { - /* CROSS JOIN is same as unqualified inner join */ - PGJoinExpr *n = makeNode(PGJoinExpr); - n->jointype = PG_JOIN_INNER; - n->isNatural = false; - n->larg = (yyvsp[(1) - (4)].node); - n->rarg = (yyvsp[(4) - (4)].node); - n->usingClause = NIL; - n->quals = NULL; - n->location = (yylsp[(2) - (4)]); - (yyval.jexpr) = n; - ;} - break; +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx The PK context to use. It must have been set up. + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \note \p f_rng is used for padding generation. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - case 620: -#line 912 "third_party/libpg_query/grammar/statements/select.y" - { - PGJoinExpr *n = makeNode(PGJoinExpr); - n->jointype = (yyvsp[(2) - (5)].jtype); - n->isNatural = false; - n->larg = (yyvsp[(1) - (5)].node); - n->rarg = (yyvsp[(4) - (5)].node); - if ((yyvsp[(5) - (5)].node) != NULL && IsA((yyvsp[(5) - (5)].node), PGList)) - n->usingClause = (PGList *) (yyvsp[(5) - (5)].node); /* USING clause */ - else - n->quals = (yyvsp[(5) - (5)].node); /* ON clause */ - n->location = (yylsp[(2) - (5)]); - (yyval.jexpr) = n; - ;} - break; +/** + * \brief Check if a public-private pair of keys matches. + * + * \param pub Context holding a public key. + * \param prv Context holding a private (and public) key. + * \param f_rng RNG function, must not be \c NULL. + * \param p_rng RNG parameter + * + * \return \c 0 on success (keys were checked and match each other). + * \return #MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE if the keys could not + * be checked - in that case they may or may not match. + * \return #MBEDTLS_ERR_PK_BAD_INPUT_DATA if a context is invalid. + * \return Another non-zero value if the keys do not match. + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, + const mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); - case 621: -#line 926 "third_party/libpg_query/grammar/statements/select.y" - { - /* letting join_type reduce to empty doesn't work */ - PGJoinExpr *n = makeNode(PGJoinExpr); - n->jointype = PG_JOIN_INNER; - n->isNatural = false; - n->larg = (yyvsp[(1) - (4)].node); - n->rarg = (yyvsp[(3) - (4)].node); - if ((yyvsp[(4) - (4)].node) != NULL && IsA((yyvsp[(4) - (4)].node), PGList)) - n->usingClause = (PGList *) (yyvsp[(4) - (4)].node); /* USING clause */ - else - n->quals = (yyvsp[(4) - (4)].node); /* ON clause */ - n->location = (yylsp[(2) - (4)]); - (yyval.jexpr) = n; - ;} - break; +/** + * \brief Export debug information + * + * \param ctx The PK context to use. It must have been initialized. + * \param items Place to write debug items + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ); - case 622: -#line 941 "third_party/libpg_query/grammar/statements/select.y" - { - PGJoinExpr *n = makeNode(PGJoinExpr); - n->jointype = (yyvsp[(3) - (5)].jtype); - n->isNatural = true; - n->larg = (yyvsp[(1) - (5)].node); - n->rarg = (yyvsp[(5) - (5)].node); - n->usingClause = NIL; /* figure out which columns later... */ - n->quals = NULL; /* fill later */ - n->location = (yylsp[(2) - (5)]); - (yyval.jexpr) = n; - ;} - break; +/** + * \brief Access the type name + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type name on success, or "invalid PK" + */ +const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); - case 623: -#line 953 "third_party/libpg_query/grammar/statements/select.y" - { - /* letting join_type reduce to empty doesn't work */ - PGJoinExpr *n = makeNode(PGJoinExpr); - n->jointype = PG_JOIN_INNER; - n->isNatural = true; - n->larg = (yyvsp[(1) - (4)].node); - n->rarg = (yyvsp[(4) - (4)].node); - n->usingClause = NIL; /* figure out which columns later... */ - n->quals = NULL; /* fill later */ - n->location = (yylsp[(2) - (4)]); - (yyval.jexpr) = n; - ;} - break; +/** + * \brief Get the key type + * + * \param ctx The PK context to use. It must have been initialized. + * + * \return Type on success. + * \return #MBEDTLS_PK_NONE for a context that has not been set up. + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); - case 624: -#line 969 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.alias) = makeNode(PGAlias); - (yyval.alias)->aliasname = (yyvsp[(2) - (5)].str); - (yyval.alias)->colnames = (yyvsp[(4) - (5)].list); - ;} - break; +#if defined(MBEDTLS_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key in PEM or DER format + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * \param pwd Optional password for decryption. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a string of \p pwdlen bytes if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * \param pwdlen Size of the password in bytes. + * Ignored if \p pwd is \c NULL. + * \param f_rng RNG function, must not be \c NULL. Used for blinding. + * \param p_rng RNG parameter + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - case 625: -#line 975 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.alias) = makeNode(PGAlias); - (yyval.alias)->aliasname = (yyvsp[(2) - (2)].str); - ;} - break; +/** \ingroup pk_module */ +/** + * \brief Parse a public key in PEM or DER format + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param key Input buffer to parse. + * The buffer must contain the input exactly, with no + * extra trailing material. For PEM, the buffer must + * contain a null-terminated string. + * \param keylen Size of \b key in bytes. + * For PEM data, this includes the terminating null byte, + * so \p keylen must be equal to `strlen(key) + 1`. + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ); - case 626: -#line 980 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.alias) = makeNode(PGAlias); - (yyval.alias)->aliasname = (yyvsp[(1) - (4)].str); - (yyval.alias)->colnames = (yyvsp[(3) - (4)].list); - ;} - break; +#if defined(MBEDTLS_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the private key from + * \param password Optional password to decrypt the file. + * Pass \c NULL if expecting a non-encrypted key. + * Pass a null-terminated string if expecting an encrypted + * key; a non-encrypted key will also be accepted. + * The empty password is not supported. + * \param f_rng RNG function, must not be \c NULL. Used for blinding. + * \param p_rng RNG parameter + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *password, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); - case 627: -#line 986 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.alias) = makeNode(PGAlias); - (yyval.alias)->aliasname = (yyvsp[(1) - (1)].str); - ;} - break; +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx The PK context to fill. It must have been initialized + * but not set up. + * \param path filename to read the public key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If + * you need a specific key type, check the result with + * mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_PK_PARSE_C */ - case 628: -#line 992 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.alias) = (yyvsp[(1) - (1)].alias); ;} - break; +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_key_der( const mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); - case 629: -#line 993 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.alias) = NULL; ;} - break; +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_pubkey_der( const mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); - case 630: -#line 1002 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make2((yyvsp[(1) - (1)].alias), NIL); - ;} - break; +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx PK context which must contain a valid public or private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_pubkey_pem( const mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); - case 631: -#line 1006 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make2(NULL, (yyvsp[(3) - (4)].list)); - ;} - break; +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx PK context which must contain a valid private key. + * \param buf Buffer to write to. The output includes a + * terminating null byte. + * \param size Size of the buffer in bytes. + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_key_pem( const mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PK_WRITE_C */ - case 632: -#line 1010 "third_party/libpg_query/grammar/statements/select.y" - { - PGAlias *a = makeNode(PGAlias); - a->aliasname = (yyvsp[(2) - (5)].str); - (yyval.list) = list_make2(a, (yyvsp[(4) - (5)].list)); - ;} - break; +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ - case 633: -#line 1016 "third_party/libpg_query/grammar/statements/select.y" - { - PGAlias *a = makeNode(PGAlias); - a->aliasname = (yyvsp[(1) - (4)].str); - (yyval.list) = list_make2(a, (yyvsp[(3) - (4)].list)); - ;} - break; +#if defined(MBEDTLS_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk The PK context to fill. It must have been initialized + * but not set up. + * + * \return 0 if successful, or a specific PK error code + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ); +#endif /* MBEDTLS_PK_PARSE_C */ - case 634: -#line 1022 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make2(NULL, NIL); - ;} - break; +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key PK context which must contain a valid public or private key. + * + * \return the length written or a negative error code + */ +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ); +#endif /* MBEDTLS_PK_WRITE_C */ - case 635: -#line 1027 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.jtype) = PG_JOIN_FULL; ;} - break; +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +#if defined(MBEDTLS_FS_IO) +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); +#endif - case 636: -#line 1028 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.jtype) = PG_JOIN_LEFT; ;} - break; +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief Turn an EC key into an opaque one. + * + * \warning This is a temporary utility function for tests. It might + * change or be removed at any time without notice. + * + * \note Only ECDSA keys are supported so far. Signing with the + * specified hash is the only allowed use of that key. + * + * \param pk Input: the EC key to import to a PSA key. + * Output: a PK context wrapping that PSA key. + * \param key Output: a PSA key identifier. + * It's the caller's responsibility to call + * psa_destroy_key() on that key identifier after calling + * mbedtls_pk_free() on the PK context. + * \param hash_alg The hash algorithm to allow for use with that key. + * + * \return \c 0 if successful. + * \return An Mbed TLS error code otherwise. + */ +int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk, + psa_key_id_t *key, + psa_algorithm_t hash_alg ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ - case 637: -#line 1029 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.jtype) = PG_JOIN_RIGHT; ;} - break; +#ifdef __cplusplus +} +#endif - case 638: -#line 1030 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.jtype) = PG_JOIN_INNER; ;} - break; +#endif /* MBEDTLS_PK_H */ - case 639: -#line 1034 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; - case 640: -#line 1035 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; +// LICENSE_CHANGE_END - case 641: -#line 1047 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) (yyvsp[(3) - (4)].list); ;} - break; - case 642: -#line 1048 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} - break; +#include - case 643: -#line 1054 "third_party/libpg_query/grammar/statements/select.y" - { - /* inheritance query, implicitly */ - (yyval.range) = (yyvsp[(1) - (1)].range); - (yyval.range)->inh = true; - (yyval.range)->alias = NULL; - ;} - break; +#if defined(MBEDTLS_CIPHER_C) - case 644: -#line 1061 "third_party/libpg_query/grammar/statements/select.y" - { - /* inheritance query, explicitly */ - (yyval.range) = (yyvsp[(1) - (2)].range); - (yyval.range)->inh = true; - (yyval.range)->alias = NULL; - ;} - break; - case 645: -#line 1068 "third_party/libpg_query/grammar/statements/select.y" - { - /* no inheritance */ - (yyval.range) = (yyvsp[(2) - (2)].range); - (yyval.range)->inh = false; - (yyval.range)->alias = NULL; - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 646: -#line 1075 "third_party/libpg_query/grammar/statements/select.y" - { - /* no inheritance, SQL99-style syntax */ - (yyval.range) = (yyvsp[(3) - (4)].range); - (yyval.range)->inh = false; - (yyval.range)->alias = NULL; - ;} - break; +/** + * \file cipher.h + * + * \brief This file contains an abstraction interface for use with the cipher + * primitives provided by the library. It provides a common interface to all of + * the available cipher operations. + * + * \author Adriaan de Jong + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - case 647: -#line 1107 "third_party/libpg_query/grammar/statements/select.y" - { - PGRangeFunction *n = makeNode(PGRangeFunction); - n->lateral = false; - n->ordinality = (yyvsp[(2) - (2)].boolean); - n->is_rowsfrom = false; - n->functions = list_make1(list_make2((yyvsp[(1) - (2)].node), NIL)); - n->sample = NULL; - /* alias and coldeflist are set by table_ref production */ - (yyval.node) = (PGNode *) n; - ;} - break; +#ifndef MBEDTLS_CIPHER_H +#define MBEDTLS_CIPHER_H - case 648: -#line 1118 "third_party/libpg_query/grammar/statements/select.y" - { - PGRangeFunction *n = makeNode(PGRangeFunction); - n->lateral = false; - n->ordinality = (yyvsp[(6) - (6)].boolean); - n->is_rowsfrom = true; - n->functions = (yyvsp[(4) - (6)].list); - n->sample = NULL; - /* alias and coldeflist are set by table_ref production */ - (yyval.node) = (PGNode *) n; - ;} - break; - case 649: -#line 1131 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].list)); ;} - break; - case 650: -#line 1135 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].list)); ;} - break; - case 651: -#line 1136 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); ;} - break; +#include - case 652: -#line 1139 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} - break; - case 653: -#line 1140 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +#define MBEDTLS_CIPHER_MODE_AEAD +#endif - case 654: -#line 1143 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = true; ;} - break; +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_CIPHER_MODE_WITH_PADDING +#endif - case 655: -#line 1144 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} - break; +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + defined(MBEDTLS_CHACHA20_C) +#define MBEDTLS_CIPHER_MODE_STREAM +#endif - case 656: -#line 1149 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} - break; +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif - case 657: -#line 1150 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; +/** The selected feature is not available. */ +#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 +/** Bad input parameters. */ +#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 +/** Failed to allocate memory. */ +#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 +/** Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 +/** Decryption of block requires a full block. */ +#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 +/** Authentication failed (for AEAD modes). */ +#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 +/** The context is invalid. For example, because it was freed. */ +#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 + +#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ +#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */ - case 658: -#line 1156 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} - break; +#ifdef __cplusplus +extern "C" { +#endif - case 659: -#line 1160 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); - ;} - break; +/** + * \brief Supported cipher types. + * + * \warning DES is considered weak cipher and its use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */ + MBEDTLS_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */ + MBEDTLS_CIPHER_ID_AES, /**< The AES cipher. */ + MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. */ + MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. */ + MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ + MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */ + MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */ +} mbedtls_cipher_id_t; - case 660: -#line 1166 "third_party/libpg_query/grammar/statements/select.y" - { - PGColumnDef *n = makeNode(PGColumnDef); - n->colname = (yyvsp[(1) - (3)].str); - n->typeName = (yyvsp[(2) - (3)].typnam); - n->inhcount = 0; - n->is_local = true; - n->is_not_null = false; - n->is_from_type = false; - n->storage = 0; - n->raw_default = NULL; - n->cooked_default = NULL; - n->collClause = (PGCollateClause *) (yyvsp[(3) - (3)].node); - n->collOid = InvalidOid; - n->constraints = NIL; - n->location = (yylsp[(1) - (3)]); - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief Supported {cipher type, cipher mode} pairs. + * + * \warning DES is considered weak cipher and its use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_NONE = 0, /**< Placeholder to mark the end of cipher-pair lists. */ + MBEDTLS_CIPHER_NULL, /**< The identity stream cipher. */ + MBEDTLS_CIPHER_AES_128_ECB, /**< AES cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_AES_192_ECB, /**< AES cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_AES_256_ECB, /**< AES cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_AES_128_CBC, /**< AES cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_AES_192_CBC, /**< AES cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_AES_256_CBC, /**< AES cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_AES_128_CFB128, /**< AES cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_192_CFB128, /**< AES cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_256_CFB128, /**< AES cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_128_CTR, /**< AES cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_AES_192_CTR, /**< AES cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_AES_256_CTR, /**< AES cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_AES_128_GCM, /**< AES cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_AES_192_GCM, /**< AES cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_AES_256_GCM, /**< AES cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_ECB, /**< Camellia cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_ECB, /**< Camellia cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_ECB, /**< Camellia cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CBC, /**< Camellia cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CBC, /**< Camellia cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CBC, /**< Camellia cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, /**< Camellia cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, /**< Camellia cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, /**< Camellia cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CTR, /**< Camellia cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CTR, /**< Camellia cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CTR, /**< Camellia cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. */ + MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. */ + MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. */ + MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. */ + MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. */ + MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. */ + MBEDTLS_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_AES_128_CCM_STAR_NO_TAG, /**< AES cipher with 128-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_AES_192_CCM_STAR_NO_TAG, /**< AES cipher with 192-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_AES_256_CCM_STAR_NO_TAG, /**< AES cipher with 256-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CCM_STAR_NO_TAG, /**< Camellia cipher with 128-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CCM_STAR_NO_TAG, /**< Camellia cipher with 192-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CCM_STAR_NO_TAG, /**< Camellia cipher with 256-bit CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_128_CBC, /**< Aria cipher with 128-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_192_CBC, /**< Aria cipher with 192-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_256_CBC, /**< Aria cipher with 256-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_128_CFB128, /**< Aria cipher with 128-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_192_CFB128, /**< Aria cipher with 192-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_256_CFB128, /**< Aria cipher with 256-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_128_CTR, /**< Aria cipher with 128-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_192_CTR, /**< Aria cipher with 192-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_256_CTR, /**< Aria cipher with 256-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_128_GCM, /**< Aria cipher with 128-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_192_GCM, /**< Aria cipher with 192-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_256_GCM, /**< Aria cipher with 256-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_128_CCM_STAR_NO_TAG, /**< Aria cipher with 128-bit key and CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_ARIA_192_CCM_STAR_NO_TAG, /**< Aria cipher with 192-bit key and CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_ARIA_256_CCM_STAR_NO_TAG, /**< Aria cipher with 256-bit key and CCM_STAR_NO_TAG mode. */ + MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */ + MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */ + MBEDTLS_CIPHER_AES_128_KW, /**< AES cipher with 128-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_192_KW, /**< AES cipher with 192-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_256_KW, /**< AES cipher with 256-bit NIST KW mode. */ + MBEDTLS_CIPHER_AES_128_KWP, /**< AES cipher with 128-bit NIST KWP mode. */ + MBEDTLS_CIPHER_AES_192_KWP, /**< AES cipher with 192-bit NIST KWP mode. */ + MBEDTLS_CIPHER_AES_256_KWP, /**< AES cipher with 256-bit NIST KWP mode. */ +} mbedtls_cipher_type_t; + +/** Supported cipher modes. */ +typedef enum { + MBEDTLS_MODE_NONE = 0, /**< None. */ + MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */ + MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */ + MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */ + MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */ + MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */ + MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ + MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ + MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ + MBEDTLS_MODE_CCM_STAR_NO_TAG, /**< The CCM*-no-tag cipher mode. */ + MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ + MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ + MBEDTLS_MODE_KW, /**< The SP800-38F KW mode */ + MBEDTLS_MODE_KWP, /**< The SP800-38F KWP mode */ +} mbedtls_cipher_mode_t; + +/** Supported cipher padding types. */ +typedef enum { + MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */ + MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */ + MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */ + MBEDTLS_PADDING_ZEROS, /**< Zero padding (not reversible). */ + MBEDTLS_PADDING_NONE, /**< Never pad (full blocks only). */ +} mbedtls_cipher_padding_t; + +/** Type of operation. */ +typedef enum { + MBEDTLS_OPERATION_NONE = -1, + MBEDTLS_DECRYPT = 0, + MBEDTLS_ENCRYPT, +} mbedtls_operation_t; - case 661: -#line 1187 "third_party/libpg_query/grammar/statements/select.y" - { - PGCollateClause *n = makeNode(PGCollateClause); - n->arg = NULL; - n->collname = (yyvsp[(2) - (2)].list); - n->location = (yylsp[(1) - (2)]); - (yyval.node) = (PGNode *) n; - ;} - break; +enum { + /** Undefined key length. */ + MBEDTLS_KEY_LENGTH_NONE = 0, + /** Key length, in bits (including parity), for DES keys. */ + MBEDTLS_KEY_LENGTH_DES = 64, + /** Key length in bits, including parity, for DES in two-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE = 128, + /** Key length in bits, including parity, for DES in three-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, +}; + +/** Maximum length of any IV, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * This should be kept in sync with MBEDTLS_SSL_MAX_IV_LENGTH defined + * in library/ssl_misc.h. */ +#define MBEDTLS_MAX_IV_LENGTH 16 + +/** Maximum block size of any cipher, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined + * in library/ssl_misc.h. */ +#define MBEDTLS_MAX_BLOCK_LENGTH 16 + +/** Maximum key length, in Bytes. */ +/* This should ideally be derived automatically from list of ciphers. + * For now, only check whether XTS is enabled which uses 64 Byte keys, + * and use 32 Bytes as an upper bound for the maximum key length otherwise. + * This should be kept in sync with MBEDTLS_SSL_MAX_BLOCK_LENGTH defined + * in library/ssl_misc.h, which however deliberately ignores the case of XTS + * since the latter isn't used in SSL/TLS. */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +#define MBEDTLS_MAX_KEY_LENGTH 64 +#else +#define MBEDTLS_MAX_KEY_LENGTH 32 +#endif /* MBEDTLS_CIPHER_MODE_XTS */ - case 662: -#line 1194 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; +/** + * Base cipher information (opaque struct). + */ +typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; - case 663: -#line 1207 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1(list_make2(makeString((yyvsp[(1) - (2)].str)), (yyvsp[(2) - (2)].typnam))); - ;} - break; +/** + * CMAC context (opaque struct). + */ +typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; - case 664: -#line 1210 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = lappend((yyvsp[(1) - (4)].list), list_make2(makeString((yyvsp[(3) - (4)].str)), (yyvsp[(4) - (4)].typnam))); - ;} - break; +/** + * Cipher information. Allows calling cipher functions + * in a generic way. + * + * \note The library does not support custom cipher info structures, + * only built-in structures returned by the functions + * mbedtls_cipher_info_from_string(), + * mbedtls_cipher_info_from_type(), + * mbedtls_cipher_info_from_values(), + * mbedtls_cipher_info_from_psa(). + */ +typedef struct mbedtls_cipher_info_t +{ + /** Full cipher identifier. For example, + * MBEDTLS_CIPHER_AES_256_CBC. + */ + mbedtls_cipher_type_t MBEDTLS_PRIVATE(type); - case 667: -#line 1217 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} - break; + /** The cipher mode. For example, MBEDTLS_MODE_CBC. */ + mbedtls_cipher_mode_t MBEDTLS_PRIVATE(mode); - case 668: -#line 1218 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = NULL; ;} - break; + /** The cipher key length, in bits. This is the + * default length for variable sized ciphers. + * Includes parity bits for ciphers like DES. + */ + unsigned int MBEDTLS_PRIVATE(key_bitlen); - case 669: -#line 1221 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (2)].typnam); - (yyval.typnam)->arrayBounds = (yyvsp[(2) - (2)].list); - ;} - break; + /** Name of the cipher. */ + const char * MBEDTLS_PRIVATE(name); - case 670: -#line 1226 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(2) - (3)].typnam); - (yyval.typnam)->arrayBounds = (yyvsp[(3) - (3)].list); - (yyval.typnam)->setof = true; - ;} - break; + /** IV or nonce size, in Bytes. + * For ciphers that accept variable IV sizes, + * this is the recommended size. + */ + unsigned int MBEDTLS_PRIVATE(iv_size); - case 671: -#line 1233 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (5)].typnam); - (yyval.typnam)->arrayBounds = list_make1(makeInteger((yyvsp[(4) - (5)].ival))); - ;} - break; + /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and + * MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the + * cipher supports variable IV or variable key sizes, respectively. + */ + int MBEDTLS_PRIVATE(flags); - case 672: -#line 1238 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(2) - (6)].typnam); - (yyval.typnam)->arrayBounds = list_make1(makeInteger((yyvsp[(5) - (6)].ival))); - (yyval.typnam)->setof = true; - ;} - break; + /** The block size, in Bytes. */ + unsigned int MBEDTLS_PRIVATE(block_size); - case 673: -#line 1244 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (2)].typnam); - (yyval.typnam)->arrayBounds = list_make1(makeInteger(-1)); - ;} - break; + /** Struct for base cipher information and functions. */ + const mbedtls_cipher_base_t *MBEDTLS_PRIVATE(base); - case 674: -#line 1249 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(2) - (3)].typnam); - (yyval.typnam)->arrayBounds = list_make1(makeInteger(-1)); - (yyval.typnam)->setof = true; - ;} - break; +} mbedtls_cipher_info_t; - case 675: -#line 1254 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("struct"); - (yyval.typnam)->arrayBounds = (yyvsp[(5) - (5)].list); - (yyval.typnam)->typmods = (yyvsp[(3) - (5)].list); - (yyval.typnam)->location = (yylsp[(1) - (5)]); - ;} - break; +/** + * Generic cipher context. + */ +typedef struct mbedtls_cipher_context_t +{ + /** Information about the associated cipher. */ + const mbedtls_cipher_info_t *MBEDTLS_PRIVATE(cipher_info); - case 676: -#line 1260 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("map"); - (yyval.typnam)->arrayBounds = (yyvsp[(5) - (5)].list); - (yyval.typnam)->typmods = (yyvsp[(3) - (5)].list); - (yyval.typnam)->location = (yylsp[(1) - (5)]); - ;} - break; + /** Key length to use. */ + int MBEDTLS_PRIVATE(key_bitlen); - case 677: -#line 1270 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeInteger(-1)); ;} - break; + /** Operation that the key of the context has been + * initialized for. + */ + mbedtls_operation_t MBEDTLS_PRIVATE(operation); - case 678: -#line 1272 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (4)].list), makeInteger((yyvsp[(3) - (4)].ival))); ;} - break; +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /** Padding functions to use, if relevant for + * the specific cipher mode. + */ + void (*MBEDTLS_PRIVATE(add_padding))( unsigned char *output, size_t olen, size_t data_len ); + int (*MBEDTLS_PRIVATE(get_padding))( unsigned char *input, size_t ilen, size_t *data_len ); +#endif - case 679: -#line 1274 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; + /** Buffer for input that has not been processed yet. */ + unsigned char MBEDTLS_PRIVATE(unprocessed_data)[MBEDTLS_MAX_BLOCK_LENGTH]; - case 680: -#line 1278 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} - break; + /** Number of Bytes that have not been processed yet. */ + size_t MBEDTLS_PRIVATE(unprocessed_len); - case 681: -#line 1279 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} - break; + /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number + * for XTS-mode. */ + unsigned char MBEDTLS_PRIVATE(iv)[MBEDTLS_MAX_IV_LENGTH]; - case 682: -#line 1280 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} - break; + /** IV size in Bytes, for ciphers with variable-length IVs. */ + size_t MBEDTLS_PRIVATE(iv_size); - case 683: -#line 1281 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} - break; + /** The cipher-specific context. */ + void *MBEDTLS_PRIVATE(cipher_ctx); - case 684: -#line 1282 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} - break; +#if defined(MBEDTLS_CMAC_C) + /** CMAC-specific context. */ + mbedtls_cmac_context_t *MBEDTLS_PRIVATE(cmac_ctx); +#endif - case 685: -#line 1284 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (2)].typnam); - (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); - ;} - break; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + /** Indicates whether the cipher operations should be performed + * by Mbed TLS' own crypto library or an external implementation + * of the PSA Crypto API. + * This is unset if the cipher context was established through + * mbedtls_cipher_setup(), and set if it was established through + * mbedtls_cipher_setup_psa(). + */ + unsigned char MBEDTLS_PRIVATE(psa_enabled); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ - case 686: -#line 1289 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (4)].typnam); - (yyval.typnam)->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1), - makeIntConst((yyvsp[(3) - (4)].ival), (yylsp[(3) - (4)]))); - ;} - break; +} mbedtls_cipher_context_t; - case 687: -#line 1308 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} - break; +/** + * \brief This function retrieves the list of ciphers supported + * by the generic cipher module. + * + * For any cipher identifier in the returned list, you can + * obtain the corresponding generic cipher information structure + * via mbedtls_cipher_info_from_type(), which can then be used + * to prepare a cipher context via mbedtls_cipher_setup(). + * + * + * \return A statically-allocated array of cipher identifiers + * of type cipher_type_t. The last entry is zero. + */ +const int *mbedtls_cipher_list( void ); - case 688: -#line 1309 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} - break; +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher name. + * + * \param cipher_name Name of the cipher to search for. This must not be + * \c NULL. + * + * \return The cipher information structure associated with the + * given \p cipher_name. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); - case 689: -#line 1310 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} - break; +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher type. + * + * \param cipher_type Type of the cipher to search for. + * + * \return The cipher information structure associated with the + * given \p cipher_type. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); - case 690: -#line 1311 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.typnam) = (yyvsp[(1) - (1)].typnam); ;} - break; +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher ID, + * key size and mode. + * + * \param cipher_id The ID of the cipher to search for. For example, + * #MBEDTLS_CIPHER_ID_AES. + * \param key_bitlen The length of the key in bits. + * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. + * + * \return The cipher information structure associated with the + * given \p cipher_id. + * \return \c NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ); - case 691: -#line 1323 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = makeTypeName((yyvsp[(1) - (2)].str)); - (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} - break; +/** + * \brief Retrieve the identifier for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The full cipher identifier (\c MBEDTLS_CIPHER_xxx). + * \return #MBEDTLS_CIPHER_NONE if \p info is \c NULL. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_info_get_type( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( MBEDTLS_CIPHER_NONE ); + else + return( info->MBEDTLS_PRIVATE(type) ); +} - case 692: -#line 1336 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} - break; +/** + * \brief Retrieve the operation mode for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The cipher mode (\c MBEDTLS_MODE_xxx). + * \return #MBEDTLS_MODE_NONE if \p info is \c NULL. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_info_get_mode( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( MBEDTLS_MODE_NONE ); + else + return( info->MBEDTLS_PRIVATE(mode) ); +} - case 693: -#line 1337 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +/** + * \brief Retrieve the key size for a cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The key length in bits. + * For variable-sized ciphers, this is the default length. + * For DES, this includes the parity bits. + * \return \c 0 if \p info is \c NULL. + */ +static inline size_t mbedtls_cipher_info_get_key_bitlen( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( 0 ); + else + return( info->MBEDTLS_PRIVATE(key_bitlen) ); +} - case 694: -#line 1344 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("int4"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} - break; +/** + * \brief Retrieve the human-readable name for a + * cipher info structure. + * + * \param[in] info The cipher info structure to query. + * This may be \c NULL. + * + * \return The cipher name, which is a human readable string, + * with static storage duration. + * \return \c NULL if \c info is \p NULL. + */ +static inline const char *mbedtls_cipher_info_get_name( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( NULL ); + else + return( info->MBEDTLS_PRIVATE(name) ); +} - case 695: -#line 1349 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("int4"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} - break; +/** + * \brief This function returns the size of the IV or nonce + * for the cipher info structure, in bytes. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return The recommended IV size. + * \return \c 0 for ciphers not using an IV or a nonce. + * \return \c 0 if \p info is \c NULL. + */ +static inline size_t mbedtls_cipher_info_get_iv_size( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( 0 ); - case 696: -#line 1354 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("int2"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} - break; + return( (size_t) info->MBEDTLS_PRIVATE(iv_size) ); +} - case 697: -#line 1359 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("int8"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} - break; +/** + * \brief This function returns the block size of the given + * cipher info structure in bytes. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return The block size of the cipher. + * \return \c 1 if the cipher is a stream cipher. + * \return \c 0 if \p info is \c NULL. + */ +static inline size_t mbedtls_cipher_info_get_block_size( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( 0 ); - case 698: -#line 1364 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("float4"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} - break; + return( (size_t) info->MBEDTLS_PRIVATE(block_size) ); +} - case 699: -#line 1369 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(2) - (2)].typnam); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} - break; +/** + * \brief This function returns a non-zero value if the key length for + * the given cipher is variable. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return Non-zero if the key length is variable, \c 0 otherwise. + * \return \c 0 if the given pointer is \c NULL. + */ +static inline int mbedtls_cipher_info_has_variable_key_bitlen( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( 0 ); - case 700: -#line 1374 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("float8"); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} - break; + return( info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ); +} - case 701: -#line 1379 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("numeric"); - (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} - break; +/** + * \brief This function returns a non-zero value if the IV size for + * the given cipher is variable. + * + * \param info The cipher info structure. This may be \c NULL. + * + * \return Non-zero if the IV size is variable, \c 0 otherwise. + * \return \c 0 if the given pointer is \c NULL. + */ +static inline int mbedtls_cipher_info_has_variable_iv_size( + const mbedtls_cipher_info_t *info ) +{ + if( info == NULL ) + return( 0 ); - case 702: -#line 1385 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("numeric"); - (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} - break; + return( info->MBEDTLS_PRIVATE(flags) & MBEDTLS_CIPHER_VARIABLE_IV_LEN ); +} + +/** + * \brief This function initializes a \p cipher_context as NONE. + * + * \param ctx The context to be initialized. This must not be \c NULL. + */ +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function frees and clears the cipher-specific + * context of \p ctx. Freeing \p ctx itself remains the + * responsibility of the caller. + * + * \param ctx The context to be freed. If this is \c NULL, the + * function has no effect, otherwise this must point to an + * initialized context. + */ +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); - case 703: -#line 1391 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("numeric"); - (yyval.typnam)->typmods = (yyvsp[(2) - (2)].list); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} - break; - case 704: -#line 1397 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("bool"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} - break; +/** + * \brief This function prepares a cipher context for + * use with the given cipher primitive. + * + * \note After calling this function, you should call + * mbedtls_cipher_setkey() and, if the mode uses padding, + * mbedtls_cipher_set_padding_mode(), then for each + * message to encrypt or decrypt with this key, either: + * - mbedtls_cipher_crypt() for one-shot processing with + * non-AEAD modes; + * - mbedtls_cipher_auth_encrypt_ext() or + * mbedtls_cipher_auth_decrypt_ext() for one-shot + * processing with AEAD modes or NIST_KW; + * - for multi-part processing, see the documentation of + * mbedtls_cipher_reset(). + * + * \param ctx The context to prepare. This must be initialized by + * a call to mbedtls_cipher_init() first. + * \param cipher_info The cipher to use. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. + */ +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info ); - case 705: -#line 1404 "third_party/libpg_query/grammar/statements/select.y" - { - /* - * Check FLOAT() precision limits assuming IEEE floating - * types - thomas 1997-09-18 - */ - if ((yyvsp[(2) - (3)].ival) < 1) - ereport(ERROR, - (errcode(PG_ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("precision for type float must be at least 1 bit"), - parser_errposition((yylsp[(2) - (3)])))); - else if ((yyvsp[(2) - (3)].ival) <= 24) - (yyval.typnam) = SystemTypeName("float4"); - else if ((yyvsp[(2) - (3)].ival) <= 53) - (yyval.typnam) = SystemTypeName("float8"); - else - ereport(ERROR, - (errcode(PG_ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("precision for type float must be less than 54 bits"), - parser_errposition((yylsp[(2) - (3)])))); - ;} - break; +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/** + * \brief This function initializes a cipher context for + * PSA-based use with the given cipher primitive. + * + * \note See #MBEDTLS_USE_PSA_CRYPTO for information on PSA. + * + * \param ctx The context to initialize. May not be \c NULL. + * \param cipher_info The cipher to use. + * \param taglen For AEAD ciphers, the length in bytes of the + * authentication tag to use. Subsequent uses of + * mbedtls_cipher_auth_encrypt_ext() or + * mbedtls_cipher_auth_decrypt_ext() must provide + * the same tag length. + * For non-AEAD ciphers, the value must be \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. + */ +int mbedtls_cipher_setup_psa( mbedtls_cipher_context_t *ctx, + const mbedtls_cipher_info_t *cipher_info, + size_t taglen ); +#endif /* MBEDTLS_USE_PSA_CRYPTO */ - case 706: -#line 1425 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("float4"); - ;} - break; +/** + * \brief This function returns the block size of the given cipher + * in bytes. + * + * \param ctx The context of the cipher. + * + * \return The block size of the underlying cipher. + * \return \c 1 if the cipher is a stream cipher. + * \return \c 0 if \p ctx has not been initialized. + */ +static inline unsigned int mbedtls_cipher_get_block_size( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return 0; - case 707: -#line 1435 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - ;} - break; + return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(block_size); +} - case 708: -#line 1439 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - ;} - break; +/** + * \brief This function returns the mode of operation for + * the cipher. For example, MBEDTLS_MODE_CBC. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The mode of operation. + * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, MBEDTLS_MODE_NONE ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return MBEDTLS_MODE_NONE; - case 709: -#line 1447 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - ;} - break; + return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(mode); +} - case 710: -#line 1451 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - (yyval.typnam)->typmods = NIL; - ;} - break; +/** + * \brief This function returns the size of the IV or nonce + * of the cipher, in Bytes. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The recommended IV size if no IV has been set. + * \return \c 0 for ciphers not using an IV or a nonce. + * \return The actual size if an IV has been set. + */ +static inline int mbedtls_cipher_get_iv_size( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return 0; - case 711: -#line 1459 "third_party/libpg_query/grammar/statements/select.y" - { - const char *typname; + if( ctx->MBEDTLS_PRIVATE(iv_size) != 0 ) + return (int) ctx->MBEDTLS_PRIVATE(iv_size); - typname = (yyvsp[(2) - (5)].boolean) ? "varbit" : "bit"; - (yyval.typnam) = SystemTypeName(typname); - (yyval.typnam)->typmods = (yyvsp[(4) - (5)].list); - (yyval.typnam)->location = (yylsp[(1) - (5)]); - ;} - break; + return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(iv_size); +} - case 712: -#line 1471 "third_party/libpg_query/grammar/statements/select.y" - { - /* bit defaults to bit(1), varbit to no limit */ - if ((yyvsp[(2) - (2)].boolean)) - { - (yyval.typnam) = SystemTypeName("varbit"); - } - else - { - (yyval.typnam) = SystemTypeName("bit"); - (yyval.typnam)->typmods = list_make1(makeIntConst(1, -1)); - } - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} - break; +/** + * \brief This function returns the type of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The type of the cipher. + * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_CIPHER_NONE ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return MBEDTLS_CIPHER_NONE; - case 713: -#line 1492 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - ;} - break; + return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(type); +} - case 714: -#line 1496 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - ;} - break; +/** + * \brief This function returns the name of the given cipher + * as a string. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The name of the cipher. + * \return NULL if \p ctx has not been not initialized. + */ +static inline const char *mbedtls_cipher_get_name( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( ctx != NULL, 0 ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return 0; - case 715: -#line 1502 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - ;} - break; + return ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(name); +} - case 716: -#line 1506 "third_party/libpg_query/grammar/statements/select.y" - { - /* Length was not specified so allow to be unrestricted. - * This handles problems with fixed-length (bpchar) strings - * which in column definitions must default to a length - * of one, but should not be constrained if the length - * was not specified. - */ - (yyval.typnam) = (yyvsp[(1) - (1)].typnam); - (yyval.typnam)->typmods = NIL; - ;} - break; +/** + * \brief This function returns the key length of the cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The key length of the cipher in bits. + * \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been + * initialized. + */ +static inline int mbedtls_cipher_get_key_bitlen( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_KEY_LENGTH_NONE ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return MBEDTLS_KEY_LENGTH_NONE; - case 717: -#line 1519 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName((yyvsp[(1) - (4)].conststr)); - (yyval.typnam)->typmods = list_make1(makeIntConst((yyvsp[(3) - (4)].ival), (yylsp[(3) - (4)]))); - (yyval.typnam)->location = (yylsp[(1) - (4)]); - ;} - break; + return (int) ctx->MBEDTLS_PRIVATE(cipher_info)->MBEDTLS_PRIVATE(key_bitlen); +} - case 718: -#line 1527 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName((yyvsp[(1) - (1)].conststr)); - /* char defaults to char(1), varchar to no limit */ - if (strcmp((yyvsp[(1) - (1)].conststr), "bpchar") == 0) - (yyval.typnam)->typmods = list_make1(makeIntConst(1, -1)); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} - break; +/** + * \brief This function returns the operation of the given cipher. + * + * \param ctx The context of the cipher. This must be initialized. + * + * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_operation_t mbedtls_cipher_get_operation( + const mbedtls_cipher_context_t *ctx ) +{ + MBEDTLS_INTERNAL_VALIDATE_RET( + ctx != NULL, MBEDTLS_OPERATION_NONE ); + if( ctx->MBEDTLS_PRIVATE(cipher_info) == NULL ) + return MBEDTLS_OPERATION_NONE; - case 719: -#line 1537 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = (yyvsp[(2) - (2)].boolean) ? "varchar": "bpchar"; ;} - break; + return ctx->MBEDTLS_PRIVATE(operation); +} - case 720: -#line 1539 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = (yyvsp[(2) - (2)].boolean) ? "varchar": "bpchar"; ;} - break; +/** + * \brief This function sets the key to use with the given context. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param key The key to use. This must be a readable buffer of at + * least \p key_bitlen Bits. + * \param key_bitlen The key length to use, in Bits. + * \param operation The operation that the key will be used for: + * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, + const unsigned char *key, + int key_bitlen, + const mbedtls_operation_t operation ); - case 721: -#line 1541 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "varchar"; ;} - break; +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +/** + * \brief This function sets the padding mode, for cipher modes + * that use padding. + * + * The default passing mode is PKCS7 padding. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param mode The padding mode. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if the selected padding mode is not supported. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * does not support padding. + */ +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, + mbedtls_cipher_padding_t mode ); +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ - case 722: -#line 1543 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = (yyvsp[(3) - (3)].boolean) ? "varchar": "bpchar"; ;} - break; +/** + * \brief This function sets the initialization vector (IV) + * or nonce. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, this function has no effect. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a cipher information structure. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. This + * must be a readable buffer of at least \p iv_len Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, + size_t iv_len ); - case 723: -#line 1545 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = (yyvsp[(3) - (3)].boolean) ? "varchar": "bpchar"; ;} - break; +/** + * \brief This function resets the cipher state. + * + * \note With non-AEAD ciphers, the order of calls for each message + * is as follows: + * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce. + * 2. mbedtls_cipher_reset() + * 3. mbedtls_cipher_update() one or more times + * 4. mbedtls_cipher_finish() + * . + * This sequence can be repeated to encrypt or decrypt multiple + * messages with the same key. + * + * \note With AEAD ciphers, the order of calls for each message + * is as follows: + * 1. mbedtls_cipher_set_iv() if the mode uses an IV/nonce. + * 2. mbedtls_cipher_reset() + * 3. mbedtls_cipher_update_ad() + * 4. mbedtls_cipher_update() one or more times + * 5. mbedtls_cipher_finish() + * 6. mbedtls_cipher_check_tag() (for decryption) or + * mbedtls_cipher_write_tag() (for encryption). + * . + * This sequence can be repeated to encrypt or decrypt multiple + * messages with the same key. + * + * \param ctx The generic cipher context. This must be bound to a key. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); - case 724: -#line 1547 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = (yyvsp[(2) - (2)].boolean) ? "varchar": "bpchar"; ;} - break; +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function adds additional data for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * + * \param ctx The generic cipher context. This must be initialized. + * \param ad The additional data to use. This must be a readable + * buffer of at least \p ad_len Bytes. + * \param ad_len The length of \p ad in Bytes. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ - case 725: -#line 1551 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = true; ;} - break; +/** + * \brief The generic cipher update function. It encrypts or + * decrypts using the given cipher context. Writes as + * many block-sized blocks of data as possible to output. + * Any data that cannot be written immediately is either + * added to the next block, or flushed when + * mbedtls_cipher_finish() is called. + * Exception: For MBEDTLS_MODE_ECB, expects a single block + * in size. For example, 16 Bytes for AES. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, + size_t ilen, unsigned char *output, + size_t *olen ); - case 726: -#line 1552 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} - break; +/** + * \brief The generic cipher finalization function. If data still + * needs to be flushed from an incomplete block, the data + * contained in it is padded to the size of + * the last block, and written to the \p output buffer. + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key. + * \param output The buffer to write data to. This needs to be a writable + * buffer of at least \p block_size Bytes. + * \param olen The length of the data written to the \p output buffer. + * This may not be \c NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ); - case 727: -#line 1560 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(5) - (5)].boolean)) - (yyval.typnam) = SystemTypeName("timestamptz"); - else - (yyval.typnam) = SystemTypeName("timestamp"); - (yyval.typnam)->typmods = list_make1(makeIntConst((yyvsp[(3) - (5)].ival), (yylsp[(3) - (5)]))); - (yyval.typnam)->location = (yylsp[(1) - (5)]); - ;} - break; +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function writes a tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized, + * bound to a key, and have just completed a cipher + * operation through mbedtls_cipher_finish() the tag for + * which should be written. + * \param tag The buffer to write the tag to. This must be a writable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to write. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); - case 728: -#line 1569 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(2) - (2)].boolean)) - (yyval.typnam) = SystemTypeName("timestamptz"); - else - (yyval.typnam) = SystemTypeName("timestamp"); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} - break; +/** + * \brief This function checks the tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * This must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. This must be initialized. + * \param tag The buffer holding the tag. This must be a readable + * buffer of at least \p tag_len Bytes. + * \param tag_len The length of the tag to check. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ - case 729: -#line 1577 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(5) - (5)].boolean)) - (yyval.typnam) = SystemTypeName("timetz"); - else - (yyval.typnam) = SystemTypeName("time"); - (yyval.typnam)->typmods = list_make1(makeIntConst((yyvsp[(3) - (5)].ival), (yylsp[(3) - (5)]))); - (yyval.typnam)->location = (yylsp[(1) - (5)]); - ;} - break; +/** + * \brief The generic all-in-one encryption/decryption function, + * for all ciphers except AEAD constructs. + * + * \param ctx The generic cipher context. This must be initialized. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * This must be a readable buffer of at least \p iv_len + * Bytes. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size + * IV. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The buffer for the output data. This must be able to + * hold at least `ilen + block_size`. This must not be the + * same buffer as \p input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. This must not be + * \c NULL. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, use \p iv = NULL and \p iv_len = 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ); - case 730: -#line 1586 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(2) - (2)].boolean)) - (yyval.typnam) = SystemTypeName("timetz"); - else - (yyval.typnam) = SystemTypeName("time"); - (yyval.typnam)->location = (yylsp[(1) - (2)]); - ;} - break; +#if defined(MBEDTLS_CIPHER_MODE_AEAD) || defined(MBEDTLS_NIST_KW_C) +/** + * \brief The authenticated encryption (AEAD/NIST_KW) function. + * + * \note For AEAD modes, the tag will be appended to the + * ciphertext, as recommended by RFC 5116. + * (NIST_KW doesn't have a separate tag.) + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key, with an AEAD algorithm or NIST_KW. + * \param iv The nonce to use. This must be a readable buffer of + * at least \p iv_len Bytes and may be \c NULL if \p + * iv_len is \c 0. + * \param iv_len The length of the nonce. For AEAD ciphers, this must + * satisfy the constraints imposed by the cipher used. + * For NIST_KW, this must be \c 0. + * \param ad The additional data to authenticate. This must be a + * readable buffer of at least \p ad_len Bytes, and may + * be \c NULL is \p ad_len is \c 0. + * \param ad_len The length of \p ad. For NIST_KW, this must be \c 0. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes, and may be + * \c NULL if \p ilen is \c 0. + * \param ilen The length of the input data. + * \param output The buffer for the output data. This must be a + * writable buffer of at least \p output_len Bytes, and + * must not be \c NULL. + * \param output_len The length of the \p output buffer in Bytes. For AEAD + * ciphers, this must be at least \p ilen + \p tag_len. + * For NIST_KW, this must be at least \p ilen + 8 + * (rounded up to a multiple of 8 if KWP is used); + * \p ilen + 15 is always a safe value. + * \param olen This will be filled with the actual number of Bytes + * written to the \p output buffer. This must point to a + * writable object of type \c size_t. + * \param tag_len The desired length of the authentication tag. For AEAD + * ciphers, this must match the constraints imposed by + * the cipher used, and in particular must not be \c 0. + * For NIST_KW, this must be \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_encrypt_ext( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t output_len, + size_t *olen, size_t tag_len ); - case 731: -#line 1597 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.typnam) = SystemTypeName("interval"); - (yyval.typnam)->location = (yylsp[(1) - (1)]); - ;} - break; +/** + * \brief The authenticated encryption (AEAD/NIST_KW) function. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext being + * used, making this interface safer. + * + * \note For AEAD modes, the tag must be appended to the + * ciphertext, as recommended by RFC 5116. + * (NIST_KW doesn't have a separate tag.) + * + * \param ctx The generic cipher context. This must be initialized and + * bound to a key, with an AEAD algorithm or NIST_KW. + * \param iv The nonce to use. This must be a readable buffer of + * at least \p iv_len Bytes and may be \c NULL if \p + * iv_len is \c 0. + * \param iv_len The length of the nonce. For AEAD ciphers, this must + * satisfy the constraints imposed by the cipher used. + * For NIST_KW, this must be \c 0. + * \param ad The additional data to authenticate. This must be a + * readable buffer of at least \p ad_len Bytes, and may + * be \c NULL is \p ad_len is \c 0. + * \param ad_len The length of \p ad. For NIST_KW, this must be \c 0. + * \param input The buffer holding the input data. This must be a + * readable buffer of at least \p ilen Bytes, and may be + * \c NULL if \p ilen is \c 0. + * \param ilen The length of the input data. For AEAD ciphers this + * must be at least \p tag_len. For NIST_KW this must be + * at least \c 8. + * \param output The buffer for the output data. This must be a + * writable buffer of at least \p output_len Bytes, and + * may be \c NULL if \p output_len is \c 0. + * \param output_len The length of the \p output buffer in Bytes. For AEAD + * ciphers, this must be at least \p ilen - \p tag_len. + * For NIST_KW, this must be at least \p ilen - 8. + * \param olen This will be filled with the actual number of Bytes + * written to the \p output buffer. This must point to a + * writable object of type \c size_t. + * \param tag_len The actual length of the authentication tag. For AEAD + * ciphers, this must match the constraints imposed by + * the cipher used, and in particular must not be \c 0. + * For NIST_KW, this must be \c 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_decrypt_ext( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t output_len, + size_t *olen, size_t tag_len ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD || MBEDTLS_NIST_KW_C */ +#ifdef __cplusplus +} +#endif - case 732: -#line 1604 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = true; ;} - break; +#endif /* MBEDTLS_CIPHER_H */ - case 733: -#line 1605 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} - break; - case 734: -#line 1606 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} - break; +// LICENSE_CHANGE_END - case 751: -#line 1635 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(YEAR), (yylsp[(1) - (1)]))); ;} - break; +#endif - case 752: -#line 1637 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MONTH), (yylsp[(1) - (1)]))); ;} - break; +#if defined(MBEDTLS_MD_C) - case 753: -#line 1639 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY), (yylsp[(1) - (1)]))); ;} - break; +#endif - case 754: -#line 1641 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(HOUR), (yylsp[(1) - (1)]))); ;} - break; +/** OID is not found. */ +#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E +/** output buffer is too small */ +#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B - case 755: -#line 1643 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MINUTE), (yylsp[(1) - (1)]))); ;} - break; +/* This is for the benefit of X.509, but defined here in order to avoid + * having a "backwards" include of x.509.h here */ +/* + * X.509 extension types (internal, arbitrary values for bitsets) + */ +#define MBEDTLS_OID_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define MBEDTLS_OID_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define MBEDTLS_OID_X509_EXT_KEY_USAGE (1 << 2) +#define MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES (1 << 3) +#define MBEDTLS_OID_X509_EXT_POLICY_MAPPINGS (1 << 4) +#define MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME (1 << 5) +#define MBEDTLS_OID_X509_EXT_ISSUER_ALT_NAME (1 << 6) +#define MBEDTLS_OID_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS (1 << 8) +#define MBEDTLS_OID_X509_EXT_NAME_CONSTRAINTS (1 << 9) +#define MBEDTLS_OID_X509_EXT_POLICY_CONSTRAINTS (1 << 10) +#define MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) +#define MBEDTLS_OID_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define MBEDTLS_OID_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define MBEDTLS_OID_X509_EXT_FRESHEST_CRL (1 << 14) +#define MBEDTLS_OID_X509_EXT_NS_CERT_TYPE (1 << 16) - case 756: -#line 1645 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(SECOND), (yylsp[(1) - (1)]))); ;} - break; +/* + * Top level OID tuples + */ +#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ - case 757: -#line 1647 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MILLISECOND), (yylsp[(1) - (1)]))); ;} - break; +/* + * ISO Member bodies OID parts + */ +#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ +#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ +#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_ANSI_X9_62 - case 758: -#line 1649 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MICROSECOND), (yylsp[(1) - (1)]))); ;} - break; +/* + * ISO Identified organization OID parts + */ +#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ +#define MBEDTLS_OID_ORG_OIW "\x0e" +#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" +#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" +#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" +#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM +#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST - case 759: -#line 1651 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(YEAR) | - INTERVAL_MASK(MONTH), (yylsp[(1) - (3)]))); - ;} - break; +/* + * ISO ITU OID parts + */ +#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ - case 760: -#line 1656 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY) | - INTERVAL_MASK(HOUR), (yylsp[(1) - (3)]))); - ;} - break; +#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ +#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ - case 761: -#line 1661 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY) | - INTERVAL_MASK(HOUR) | - INTERVAL_MASK(MINUTE), (yylsp[(1) - (3)]))); - ;} - break; +#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ - case 762: -#line 1667 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(DAY) | - INTERVAL_MASK(HOUR) | - INTERVAL_MASK(MINUTE) | - INTERVAL_MASK(SECOND), (yylsp[(1) - (3)]))); - ;} - break; +/* ISO arc for standard certificate and CRL extensions */ +#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ - case 763: -#line 1674 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(HOUR) | - INTERVAL_MASK(MINUTE), (yylsp[(1) - (3)]))); - ;} - break; +#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ - case 764: -#line 1679 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(HOUR) | - INTERVAL_MASK(MINUTE) | - INTERVAL_MASK(SECOND), (yylsp[(1) - (3)]))); - ;} - break; +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define MBEDTLS_OID_INTERNET MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01" +#define MBEDTLS_OID_PKIX MBEDTLS_OID_INTERNET "\x05\x05\x07" - case 765: -#line 1685 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1(makeIntConst(INTERVAL_MASK(MINUTE) | - INTERVAL_MASK(SECOND), (yylsp[(1) - (3)]))); - ;} - break; +/* + * Arc for standard naming attributes + */ +#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ +#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define MBEDTLS_OID_UID "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x01" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) uid(1)} */ +#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ - case 766: -#line 1690 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +/* + * OIDs for standard certificate extensions + */ +#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ - case 767: -#line 1721 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +/* + * Certificate policies + */ +#define MBEDTLS_OID_ANY_POLICY MBEDTLS_OID_CERTIFICATE_POLICIES "\x00" /**< anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } */ - case 768: -#line 1724 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeTypeCast((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].typnam), 0, (yylsp[(2) - (3)])); ;} - break; +/* + * Netscape certificate extensions + */ +#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" +#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" +#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" +#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" +#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" +#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" +#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" +#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" +#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" +#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" +#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" - case 769: -#line 1726 "third_party/libpg_query/grammar/statements/select.y" - { - PGCollateClause *n = makeNode(PGCollateClause); - n->arg = (yyvsp[(1) - (3)].node); - n->collname = (yyvsp[(3) - (3)].list); - n->location = (yylsp[(2) - (3)]); - (yyval.node) = (PGNode *) n; - ;} - break; +/* + * OIDs for CRL extensions + */ +#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" +#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ - case 770: -#line 1734 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("timezone"), - list_make2((yyvsp[(5) - (5)].node), (yyvsp[(1) - (5)].node)), - (yylsp[(2) - (5)])); - ;} - break; +/* + * X.509 v3 Extended key usage OIDs + */ +#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ - case 771: -#line 1749 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} - break; +#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ - case 772: -#line 1751 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = doNegate((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} - break; +/** + * Wi-SUN Alliance Field Area Network + * { iso(1) identified-organization(3) dod(6) internet(1) + * private(4) enterprise(1) WiSUN(45605) FieldAreaNetwork(1) } + */ +#define MBEDTLS_OID_WISUN_FAN MBEDTLS_OID_INTERNET "\x04\x01\x82\xe4\x25\x01" - case 773: -#line 1753 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#define MBEDTLS_OID_ON MBEDTLS_OID_PKIX "\x08" /**< id-on OBJECT IDENTIFIER ::= { id-pkix 8 } */ +#define MBEDTLS_OID_ON_HW_MODULE_NAME MBEDTLS_OID_ON "\x04" /**< id-on-hardwareModuleName OBJECT IDENTIFIER ::= { id-on 4 } */ - case 774: -#line 1755 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "-", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +/* + * PKCS definition OIDs + */ - case 775: -#line 1757 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "*", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ - case 776: -#line 1759 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "/", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +/* + * PKCS#1 OIDs + */ +#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ - case 777: -#line 1761 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "%", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" - case 778: -#line 1763 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "^", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ - case 779: -#line 1765 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "**", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +/* RFC 4055 */ +#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ - case 780: -#line 1767 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +/* + * Digest algorithms + */ +#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ - case 781: -#line 1769 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ - case 782: -#line 1771 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ - case 783: -#line 1773 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#define MBEDTLS_OID_DIGEST_ALG_RIPEMD160 MBEDTLS_OID_TELETRUST "\x03\x02\x01" /**< id-ripemd160 OBJECT IDENTIFIER :: { iso(1) identified-organization(3) teletrust(36) algorithm(3) hashAlgorithm(2) ripemd160(1) } */ - case 784: -#line 1775 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ - case 785: -#line 1777 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<>", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ - case 786: -#line 1780 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(2) - (3)].list), (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ - case 787: -#line 1782 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(1) - (2)].list), NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} - break; +#define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ - case 788: -#line 1784 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(2) - (2)].list), (yyvsp[(1) - (2)].node), NULL, (yylsp[(2) - (2)])); ;} - break; +#define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ - case 789: -#line 1787 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeAndExpr((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +/* + * Encryption algorithms + */ +#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ +#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ - case 790: -#line 1789 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeOrExpr((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +/* + * Key Wrapping algorithms + */ +/* + * RFC 5649 + */ +#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ +#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ +#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ +#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ +#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ +#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ +/* + * PKCS#5 OIDs + */ +#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ - case 791: -#line 1791 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeNotExpr((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} - break; +/* + * PKCS#5 PBES1 algorithms + */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ - case 792: -#line 1793 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeNotExpr((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} - break; +/* + * PKCS#8 OIDs + */ +#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ - case 793: -#line 1796 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_GLOB, "~~~", - (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); - ;} - break; +/* + * PKCS#12 PBE OIDs + */ +#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ - case 794: -#line 1801 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_LIKE, "~~", - (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); - ;} - break; +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ - case 795: -#line 1806 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall(SystemFuncName("like_escape"), - list_make3((yyvsp[(1) - (5)].node), (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node)), - (yylsp[(2) - (5)])); - (yyval.node) = (PGNode *) n; - ;} - break; +/* + * EC key algorithms from RFC 5480 + */ - case 796: -#line 1813 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_LIKE, "!~~", - (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node), (yylsp[(2) - (4)])); - ;} - break; +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" - case 797: -#line 1818 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall(SystemFuncName("not_like_escape"), - list_make3((yyvsp[(1) - (6)].node), (yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), - (yylsp[(2) - (6)])); - (yyval.node) = (PGNode *) n; - ;} - break; +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" - case 798: -#line 1825 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_ILIKE, "~~*", - (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); - ;} - break; +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ - case 799: -#line 1830 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall(SystemFuncName("ilike_escape"), - list_make3((yyvsp[(1) - (5)].node), (yyvsp[(3) - (5)].node), (yyvsp[(5) - (5)].node)), - (yylsp[(2) - (5)])); - (yyval.node) = (PGNode *) n; - ;} - break; +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" - case 800: -#line 1837 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_ILIKE, "!~~*", - (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node), (yylsp[(2) - (4)])); - ;} - break; +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" - case 801: -#line 1842 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall(SystemFuncName("not_ilike_escape"), - list_make3((yyvsp[(1) - (6)].node), (yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), - (yylsp[(2) - (6)])); - (yyval.node) = (PGNode *) n; - ;} - break; +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" - case 802: -#line 1850 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall(SystemFuncName("similar_escape"), - list_make2((yyvsp[(4) - (4)].node), makeNullAConst(-1)), - (yylsp[(2) - (4)])); - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_SIMILAR, "~", - (yyvsp[(1) - (4)].node), (PGNode *) n, (yylsp[(2) - (4)])); - ;} - break; +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" - case 803: -#line 1858 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall(SystemFuncName("similar_escape"), - list_make2((yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), - (yylsp[(2) - (6)])); - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_SIMILAR, "~", - (yyvsp[(1) - (6)].node), (PGNode *) n, (yylsp[(2) - (6)])); - ;} - break; +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" - case 804: -#line 1866 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall(SystemFuncName("similar_escape"), - list_make2((yyvsp[(5) - (5)].node), makeNullAConst(-1)), - (yylsp[(2) - (5)])); - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_SIMILAR, "!~", - (yyvsp[(1) - (5)].node), (PGNode *) n, (yylsp[(2) - (5)])); - ;} - break; +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" - case 805: -#line 1874 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall(SystemFuncName("similar_escape"), - list_make2((yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node)), - (yylsp[(2) - (7)])); - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_SIMILAR, "!~", - (yyvsp[(1) - (7)].node), (PGNode *) n, (yylsp[(2) - (7)])); - ;} - break; +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" - case 806: -#line 1892 "third_party/libpg_query/grammar/statements/select.y" - { - PGNullTest *n = makeNode(PGNullTest); - n->arg = (PGExpr *) (yyvsp[(1) - (3)].node); - n->nulltesttype = PG_IS_NULL; - n->location = (yylsp[(2) - (3)]); - (yyval.node) = (PGNode *)n; - ;} - break; +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" - case 807: -#line 1900 "third_party/libpg_query/grammar/statements/select.y" - { - PGNullTest *n = makeNode(PGNullTest); - n->arg = (PGExpr *) (yyvsp[(1) - (2)].node); - n->nulltesttype = PG_IS_NULL; - n->location = (yylsp[(2) - (2)]); - (yyval.node) = (PGNode *)n; - ;} - break; +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" - case 808: -#line 1908 "third_party/libpg_query/grammar/statements/select.y" - { - PGNullTest *n = makeNode(PGNullTest); - n->arg = (PGExpr *) (yyvsp[(1) - (4)].node); - n->nulltesttype = IS_NOT_NULL; - n->location = (yylsp[(2) - (4)]); - (yyval.node) = (PGNode *)n; - ;} - break; +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" - case 809: -#line 1916 "third_party/libpg_query/grammar/statements/select.y" - { - PGNullTest *n = makeNode(PGNullTest); - n->arg = (PGExpr *) (yyvsp[(1) - (3)].node); - n->nulltesttype = IS_NOT_NULL; - n->location = (yylsp[(2) - (3)]); - (yyval.node) = (PGNode *)n; - ;} - break; +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" - case 810: -#line 1924 "third_party/libpg_query/grammar/statements/select.y" - { - PGNullTest *n = makeNode(PGNullTest); - n->arg = (PGExpr *) (yyvsp[(1) - (2)].node); - n->nulltesttype = IS_NOT_NULL; - n->location = (yylsp[(2) - (2)]); - (yyval.node) = (PGNode *)n; - ;} - break; +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" - case 811: -#line 1931 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall(SystemFuncName("row"), (yyvsp[(1) - (1)].list), (yylsp[(1) - (1)])); - (yyval.node) = (PGNode *) n; - ;} - break; +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" +#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" - case 812: -#line 1935 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall(SystemFuncName("struct_pack"), (yyvsp[(2) - (3)].list), (yylsp[(2) - (3)])); - (yyval.node) = (PGNode *) n; - ;} - break; +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ - case 813: -#line 1939 "third_party/libpg_query/grammar/statements/select.y" - { - PGFuncCall *n = makeFuncCall(SystemFuncName("list_value"), (yyvsp[(2) - (3)].list), (yylsp[(2) - (3)])); - (yyval.node) = (PGNode *) n; - ;} - break; +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" - case 814: -#line 1944 "third_party/libpg_query/grammar/statements/select.y" - { - PGLambdaFunction *n = makeNode(PGLambdaFunction); - n->lhs = (yyvsp[(1) - (3)].node); - n->rhs = (yyvsp[(3) - (3)].node); - n->location = (yylsp[(2) - (3)]); - (yyval.node) = (PGNode *) n; - ;} - break; +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" - case 815: -#line 1952 "third_party/libpg_query/grammar/statements/select.y" - { - if (list_length((yyvsp[(1) - (3)].list)) != 2) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("wrong number of parameters on left side of OVERLAPS expression"), - parser_errposition((yylsp[(1) - (3)])))); - if (list_length((yyvsp[(3) - (3)].list)) != 2) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("wrong number of parameters on right side of OVERLAPS expression"), - parser_errposition((yylsp[(3) - (3)])))); - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("overlaps"), - list_concat((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)), - (yylsp[(2) - (3)])); - ;} - break; +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" - case 816: -#line 1968 "third_party/libpg_query/grammar/statements/select.y" - { - PGBooleanTest *b = makeNode(PGBooleanTest); - b->arg = (PGExpr *) (yyvsp[(1) - (3)].node); - b->booltesttype = PG_IS_TRUE; - b->location = (yylsp[(2) - (3)]); - (yyval.node) = (PGNode *)b; - ;} - break; +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" - case 817: -#line 1976 "third_party/libpg_query/grammar/statements/select.y" - { - PGBooleanTest *b = makeNode(PGBooleanTest); - b->arg = (PGExpr *) (yyvsp[(1) - (4)].node); - b->booltesttype = IS_NOT_TRUE; - b->location = (yylsp[(2) - (4)]); - (yyval.node) = (PGNode *)b; - ;} - break; +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" - case 818: -#line 1984 "third_party/libpg_query/grammar/statements/select.y" - { - PGBooleanTest *b = makeNode(PGBooleanTest); - b->arg = (PGExpr *) (yyvsp[(1) - (3)].node); - b->booltesttype = IS_FALSE; - b->location = (yylsp[(2) - (3)]); - (yyval.node) = (PGNode *)b; - ;} - break; +#ifdef __cplusplus +extern "C" { +#endif - case 819: -#line 1992 "third_party/libpg_query/grammar/statements/select.y" - { - PGBooleanTest *b = makeNode(PGBooleanTest); - b->arg = (PGExpr *) (yyvsp[(1) - (4)].node); - b->booltesttype = IS_NOT_FALSE; - b->location = (yylsp[(2) - (4)]); - (yyval.node) = (PGNode *)b; - ;} - break; +/** + * \brief Base OID descriptor structure + */ +typedef struct mbedtls_oid_descriptor_t +{ + const char *MBEDTLS_PRIVATE(asn1); /*!< OID ASN.1 representation */ + size_t MBEDTLS_PRIVATE(asn1_len); /*!< length of asn1 */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) + const char *MBEDTLS_PRIVATE(name); /*!< official name (e.g. from RFC) */ + const char *MBEDTLS_PRIVATE(description); /*!< human friendly description */ +#endif +} mbedtls_oid_descriptor_t; - case 820: -#line 2000 "third_party/libpg_query/grammar/statements/select.y" - { - PGBooleanTest *b = makeNode(PGBooleanTest); - b->arg = (PGExpr *) (yyvsp[(1) - (3)].node); - b->booltesttype = IS_UNKNOWN; - b->location = (yylsp[(2) - (3)]); - (yyval.node) = (PGNode *)b; - ;} - break; +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \return Length of the string written (excluding final NULL) or + * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error + */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid ); - case 821: -#line 2008 "third_party/libpg_query/grammar/statements/select.y" - { - PGBooleanTest *b = makeNode(PGBooleanTest); - b->arg = (PGExpr *) (yyvsp[(1) - (4)].node); - b->booltesttype = IS_NOT_UNKNOWN; - b->location = (yylsp[(2) - (4)]); - (yyval.node) = (PGNode *)b; - ;} - break; +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); - case 822: -#line 2016 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_DISTINCT, "=", (yyvsp[(1) - (5)].node), (yyvsp[(5) - (5)].node), (yylsp[(2) - (5)])); - ;} - break; +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name ); - case 823: -#line 2020 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_DISTINCT, "=", (yyvsp[(1) - (6)].node), (yyvsp[(6) - (6)].node), (yylsp[(2) - (6)])); - ;} - break; +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); - case 824: -#line 2024 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "=", (yyvsp[(1) - (6)].node), (PGNode *) (yyvsp[(5) - (6)].list), (yylsp[(2) - (6)])); - ;} - break; +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, + const char **oid, size_t *olen ); - case 825: -#line 2028 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "<>", (yyvsp[(1) - (7)].node), (PGNode *) (yyvsp[(6) - (7)].list), (yylsp[(2) - (7)])); - ;} - break; +#if defined(MBEDTLS_ECP_C) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); - case 826: -#line 2032 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_BETWEEN, - "BETWEEN", - (yyvsp[(1) - (6)].node), - (PGNode *) list_make2((yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), - (yylsp[(2) - (6)])); - ;} - break; +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* MBEDTLS_ECP_C */ - case 827: -#line 2040 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_BETWEEN, - "NOT BETWEEN", - (yyvsp[(1) - (7)].node), - (PGNode *) list_make2((yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node)), - (yylsp[(2) - (7)])); - ;} - break; +#if defined(MBEDTLS_MD_C) +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); - case 828: -#line 2048 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_BETWEEN_SYM, - "BETWEEN SYMMETRIC", - (yyvsp[(1) - (6)].node), - (PGNode *) list_make2((yyvsp[(4) - (6)].node), (yyvsp[(6) - (6)].node)), - (yylsp[(2) - (6)])); - ;} - break; +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc ); - case 829: -#line 2056 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_BETWEEN_SYM, - "NOT BETWEEN SYMMETRIC", - (yyvsp[(1) - (7)].node), - (PGNode *) list_make2((yyvsp[(5) - (7)].node), (yyvsp[(7) - (7)].node)), - (yylsp[(2) - (7)])); - ;} - break; +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const char **oid, size_t *olen ); - case 830: -#line 2064 "third_party/libpg_query/grammar/statements/select.y" - { - /* in_expr returns a PGSubLink or a list of a_exprs */ - if (IsA((yyvsp[(3) - (3)].node), PGSubLink)) - { - /* generate foo = ANY (subquery) */ - PGSubLink *n = (PGSubLink *) (yyvsp[(3) - (3)].node); - n->subLinkType = PG_ANY_SUBLINK; - n->subLinkId = 0; - n->testexpr = (yyvsp[(1) - (3)].node); - n->operName = NIL; /* show it's IN not = ANY */ - n->location = (yylsp[(2) - (3)]); - (yyval.node) = (PGNode *)n; - } - else - { - /* generate scalar IN expression */ - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_IN, "=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); - } - ;} - break; +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); - case 831: -#line 2084 "third_party/libpg_query/grammar/statements/select.y" - { - /* in_expr returns a PGSubLink or a list of a_exprs */ - if (IsA((yyvsp[(4) - (4)].node), PGSubLink)) - { - /* generate NOT (foo = ANY (subquery)) */ - /* Make an = ANY node */ - PGSubLink *n = (PGSubLink *) (yyvsp[(4) - (4)].node); - n->subLinkType = PG_ANY_SUBLINK; - n->subLinkId = 0; - n->testexpr = (yyvsp[(1) - (4)].node); - n->operName = NIL; /* show it's IN not = ANY */ - n->location = (yylsp[(2) - (4)]); - /* Stick a NOT on top; must have same parse location */ - (yyval.node) = makeNotExpr((PGNode *) n, (yylsp[(2) - (4)])); - } - else - { - /* generate scalar NOT IN expression */ - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_IN, "<>", (yyvsp[(1) - (4)].node), (yyvsp[(4) - (4)].node), (yylsp[(2) - (4)])); - } - ;} - break; +/** + * \brief Translate hmac algorithm OID into md_type + * + * \param oid OID to use + * \param md_hmac place to store message hmac algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_hmac( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac ); +#endif /* MBEDTLS_MD_C */ - case 832: -#line 2106 "third_party/libpg_query/grammar/statements/select.y" - { - PGSubLink *n = makeNode(PGSubLink); - n->subLinkType = (yyvsp[(3) - (4)].subquerytype); - n->subLinkId = 0; - n->testexpr = (yyvsp[(1) - (4)].node); - n->operName = (yyvsp[(2) - (4)].list); - n->subselect = (yyvsp[(4) - (4)].node); - n->location = (yylsp[(2) - (4)]); - (yyval.node) = (PGNode *)n; - ;} - break; +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc ); +#endif - case 833: -#line 2117 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(3) - (6)].subquerytype) == PG_ANY_SUBLINK) - (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP_ANY, (yyvsp[(2) - (6)].list), (yyvsp[(1) - (6)].node), (yyvsp[(5) - (6)].node), (yylsp[(2) - (6)])); - else - (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP_ALL, (yyvsp[(2) - (6)].list), (yyvsp[(1) - (6)].node), (yyvsp[(5) - (6)].node), (yylsp[(2) - (6)])); - ;} - break; +/** + * \brief Translate certificate policies OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_certificate_policies( const mbedtls_asn1_buf *oid, const char **desc ); - case 834: -#line 2124 "third_party/libpg_query/grammar/statements/select.y" - { - /* - * The SQL spec only allows DEFAULT in "contextually typed - * expressions", but for us, it's easier to allow it in - * any a_expr and then throw error during parse analysis - * if it's in an inappropriate context. This way also - * lets us say something smarter than "syntax error". - */ - PGSetToDefault *n = makeNode(PGSetToDefault); - /* parse analysis will fill in the rest */ - n->location = (yylsp[(1) - (1)]); - (yyval.node) = (PGNode *)n; - ;} - break; +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); - case 835: -#line 2137 "third_party/libpg_query/grammar/statements/select.y" - { - PGList *func_name = list_make1(makeString("construct_array")); - PGFuncCall *n = makeFuncCall(func_name, (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - (yyval.node) = (PGNode *) n; - ;} - break; +#if defined(MBEDTLS_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_CIPHER_C */ - case 836: -#line 2154 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +#if defined(MBEDTLS_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, + mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_PKCS12_C */ - case 837: -#line 2156 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeTypeCast((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].typnam), 0, (yylsp[(2) - (3)])); ;} - break; +#ifdef __cplusplus +} +#endif - case 838: -#line 2158 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} - break; +#endif /* oid.h */ - case 839: -#line 2160 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = doNegate((yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} - break; - case 840: -#line 2162 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "+", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +// LICENSE_CHANGE_END - case 841: -#line 2164 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "-", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; - case 842: -#line 2166 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "*", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; - case 843: -#line 2168 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "/", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; - case 844: -#line 2170 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "%", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#include +#include - case 845: -#line 2172 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "^", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#if defined(MBEDTLS_PLATFORM_C) - case 846: -#line 2174 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "**", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#else +#define mbedtls_snprintf snprintf +#endif - case 847: -#line 2176 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) - case 848: -#line 2178 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +/* + * Macro to generate mbedtls_oid_descriptor_t + */ +#if !defined(MBEDTLS_X509_REMOVE_INFO) +#define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s), name, description } +#define NULL_OID_DESCRIPTOR { NULL, 0, NULL, NULL } +#else +#define OID_DESCRIPTOR(s, name, description) { ADD_LEN(s) } +#define NULL_OID_DESCRIPTOR { NULL, 0 } +#endif - case 849: -#line 2180 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +/* + * Macro to generate an internal function for oid_XXX_from_asn1() (used by + * the other functions) + */ +#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ + static const TYPE_T * oid_ ## NAME ## _from_asn1( \ + const mbedtls_asn1_buf *oid ) \ + { \ + const TYPE_T *p = (LIST); \ + const mbedtls_oid_descriptor_t *cur = \ + (const mbedtls_oid_descriptor_t *) p; \ + if( p == NULL || oid == NULL ) return( NULL ); \ + while( cur->asn1 != NULL ) { \ + if( cur->asn1_len == oid->len && \ + memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ + return( p ); \ + } \ + p++; \ + cur = (const mbedtls_oid_descriptor_t *) p; \ + } \ + return( NULL ); \ + } - case 850: -#line 2182 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +#if !defined(MBEDTLS_X509_REMOVE_INFO) +/* + * Macro to generate a function for retrieving a single attribute from the + * descriptor of an mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->descriptor.ATTR1; \ + return( 0 ); \ +} +#endif /* MBEDTLS_X509_REMOVE_INFO */ - case 851: -#line 2184 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, ">=", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +/* + * Macro to generate a function for retrieving a single attribute from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + return( 0 ); \ +} - case 852: -#line 2186 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "<>", (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +/* + * Macro to generate a function for retrieving two attributes from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, \ + ATTR2_TYPE * ATTR2 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *(ATTR1) = data->ATTR1; \ + *(ATTR2) = data->ATTR2; \ + return( 0 ); \ +} - case 853: -#line 2188 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(2) - (3)].list), (yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yylsp[(2) - (3)])); ;} - break; +/* + * Macro to generate a function for retrieving the OID based on a single + * attribute from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ +int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ +{ \ + const TYPE_T *cur = (LIST); \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == (ATTR1) ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} - case 854: -#line 2190 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(1) - (2)].list), NULL, (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); ;} - break; +/* + * Macro to generate a function for retrieving the OID based on two + * attributes from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ + size_t *olen ) \ +{ \ + const TYPE_T *cur = (LIST); \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == (ATTR1) && cur->ATTR2 == (ATTR2) ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} - case 855: -#line 2192 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *) makeAExpr(PG_AEXPR_OP, (yyvsp[(2) - (2)].list), (yyvsp[(1) - (2)].node), NULL, (yylsp[(2) - (2)])); ;} - break; +/* + * For X520 attribute types + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + const char *short_name; +} oid_x520_attr_t; - case 856: -#line 2194 "third_party/libpg_query/grammar/statements/select.y" +static const oid_x520_attr_t oid_x520_attr_type[] = +{ { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_DISTINCT, "=", (yyvsp[(1) - (5)].node), (yyvsp[(5) - (5)].node), (yylsp[(2) - (5)])); - ;} - break; - - case 857: -#line 2198 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_CN, "id-at-commonName", "Common Name" ), + "CN", + }, { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NOT_DISTINCT, "=", (yyvsp[(1) - (6)].node), (yyvsp[(6) - (6)].node), (yylsp[(2) - (6)])); - ;} - break; - - case 858: -#line 2202 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_COUNTRY, "id-at-countryName", "Country" ), + "C", + }, { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "=", (yyvsp[(1) - (6)].node), (PGNode *) (yyvsp[(5) - (6)].list), (yylsp[(2) - (6)])); - ;} - break; - - case 859: -#line 2206 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_LOCALITY, "id-at-locality", "Locality" ), + "L", + }, { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_OF, "<>", (yyvsp[(1) - (7)].node), (PGNode *) (yyvsp[(6) - (7)].list), (yylsp[(2) - (7)])); - ;} - break; - - case 860: -#line 2219 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; - - case 861: -#line 2220 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; - - case 862: -#line 2222 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_STATE, "id-at-state", "State" ), + "ST", + }, { - PGPositionalReference *n = makeNode(PGPositionalReference); - n->position = (yyvsp[(2) - (2)].ival); - n->location = (yylsp[(1) - (2)]); - (yyval.node) = (PGNode *) n; - ;} - break; - - case 863: -#line 2229 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_ORGANIZATION,"id-at-organizationName", "Organization" ), + "O", + }, { - if ((yyvsp[(2) - (2)].list)) - { - PGAIndirection *n = makeNode(PGAIndirection); - n->arg = makeParamRef(0, (yylsp[(1) - (2)])); - n->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); - (yyval.node) = (PGNode *) n; - } - else - (yyval.node) = makeParamRef(0, (yylsp[(1) - (2)])); - ;} - break; - - case 864: -#line 2241 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_ORG_UNIT, "id-at-organizationalUnitName", "Org Unit" ), + "OU", + }, { - PGParamRef *p = makeNode(PGParamRef); - p->number = (yyvsp[(1) - (2)].ival); - p->location = (yylsp[(1) - (2)]); - if ((yyvsp[(2) - (2)].list)) - { - PGAIndirection *n = makeNode(PGAIndirection); - n->arg = (PGNode *) p; - n->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); - (yyval.node) = (PGNode *) n; - } - else - (yyval.node) = (PGNode *) p; - ;} - break; - - case 865: -#line 2256 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_PKCS9_EMAIL, "emailAddress", "E-mail address" ), + "emailAddress", + }, { - if ((yyvsp[(4) - (4)].list)) - { - PGAIndirection *n = makeNode(PGAIndirection); - n->arg = (yyvsp[(2) - (4)].node); - n->indirection = check_indirection((yyvsp[(4) - (4)].list), yyscanner); - (yyval.node) = (PGNode *)n; - } - else - (yyval.node) = (yyvsp[(2) - (4)].node); - ;} - break; - - case 866: -#line 2268 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; - - case 867: -#line 2270 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_SERIAL_NUMBER,"id-at-serialNumber", "Serial number" ), + "serialNumber", + }, { - if ((yyvsp[(2) - (2)].list)) { - PGAIndirection *n = makeNode(PGAIndirection); - n->arg = (yyvsp[(1) - (2)].node); - n->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); - (yyval.node) = (PGNode *)n; - } - else { - (yyval.node) = (yyvsp[(1) - (2)].node); - } - ;} - break; - - case 868: -#line 2282 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_POSTAL_ADDRESS,"id-at-postalAddress", "Postal address" ), + "postalAddress", + }, { - PGSubLink *n = makeNode(PGSubLink); - n->subLinkType = PG_EXPR_SUBLINK; - n->subLinkId = 0; - n->testexpr = NULL; - n->operName = NIL; - n->subselect = (yyvsp[(1) - (1)].node); - n->location = (yylsp[(1) - (1)]); - (yyval.node) = (PGNode *)n; - ;} - break; - - case 869: -#line 2293 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_POSTAL_CODE, "id-at-postalCode", "Postal code" ), + "postalCode", + }, { - /* - * Because the select_with_parens nonterminal is designed - * to "eat" as many levels of parens as possible, the - * '(' a_expr ')' opt_indirection production above will - * fail to match a sub-SELECT with indirection decoration; - * the sub-SELECT won't be regarded as an a_expr as long - * as there are parens around it. To support applying - * subscripting or field selection to a sub-SELECT result, - * we need this redundant-looking production. - */ - PGSubLink *n = makeNode(PGSubLink); - PGAIndirection *a = makeNode(PGAIndirection); - n->subLinkType = PG_EXPR_SUBLINK; - n->subLinkId = 0; - n->testexpr = NULL; - n->operName = NIL; - n->subselect = (yyvsp[(1) - (2)].node); - n->location = (yylsp[(1) - (2)]); - a->arg = (PGNode *)n; - a->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); - (yyval.node) = (PGNode *)a; - ;} - break; - - case 870: -#line 2317 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_SUR_NAME, "id-at-surName", "Surname" ), + "SN", + }, { - PGSubLink *n = makeNode(PGSubLink); - n->subLinkType = PG_EXISTS_SUBLINK; - n->subLinkId = 0; - n->testexpr = NULL; - n->operName = NIL; - n->subselect = (yyvsp[(2) - (2)].node); - n->location = (yylsp[(1) - (2)]); - (yyval.node) = (PGNode *)n; - ;} - break; - - case 871: -#line 2328 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_GIVEN_NAME, "id-at-givenName", "Given name" ), + "GN", + }, { - PGGroupingFunc *g = makeNode(PGGroupingFunc); - g->args = (yyvsp[(3) - (4)].list); - g->location = (yylsp[(1) - (4)]); - (yyval.node) = (PGNode *)g; - ;} - break; - - case 872: -#line 2337 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_INITIALS, "id-at-initials", "Initials" ), + "initials", + }, { - (yyval.node) = (PGNode *) makeFuncCall((yyvsp[(1) - (3)].list), NIL, (yylsp[(1) - (3)])); - ;} - break; - - case 873: -#line 2341 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_GENERATION_QUALIFIER, "id-at-generationQualifier", "Generation qualifier" ), + "generationQualifier", + }, { - PGFuncCall *n = makeFuncCall((yyvsp[(1) - (6)].list), (yyvsp[(3) - (6)].list), (yylsp[(1) - (6)])); - n->agg_order = (yyvsp[(4) - (6)].list); - n->agg_ignore_nulls = (yyvsp[(5) - (6)].boolean); - (yyval.node) = (PGNode *)n; - ;} - break; - - case 874: -#line 2348 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_TITLE, "id-at-title", "Title" ), + "title", + }, { - PGFuncCall *n = makeFuncCall((yyvsp[(1) - (7)].list), list_make1((yyvsp[(4) - (7)].node)), (yylsp[(1) - (7)])); - n->func_variadic = true; - n->agg_order = (yyvsp[(5) - (7)].list); - n->agg_ignore_nulls = (yyvsp[(6) - (7)].boolean); - (yyval.node) = (PGNode *)n; - ;} - break; - - case 875: -#line 2356 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_DN_QUALIFIER,"id-at-dnQualifier", "Distinguished Name qualifier" ), + "dnQualifier", + }, { - PGFuncCall *n = makeFuncCall((yyvsp[(1) - (9)].list), lappend((yyvsp[(3) - (9)].list), (yyvsp[(6) - (9)].node)), (yylsp[(1) - (9)])); - n->func_variadic = true; - n->agg_order = (yyvsp[(7) - (9)].list); - n->agg_ignore_nulls = (yyvsp[(8) - (9)].boolean); - (yyval.node) = (PGNode *)n; - ;} - break; - - case 876: -#line 2364 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_PSEUDONYM, "id-at-pseudonym", "Pseudonym" ), + "pseudonym", + }, { - PGFuncCall *n = makeFuncCall((yyvsp[(1) - (7)].list), (yyvsp[(4) - (7)].list), (yylsp[(1) - (7)])); - n->agg_order = (yyvsp[(5) - (7)].list); - n->agg_ignore_nulls = (yyvsp[(6) - (7)].boolean); - /* Ideally we'd mark the PGFuncCall node to indicate - * "must be an aggregate", but there's no provision - * for that in PGFuncCall at the moment. - */ - (yyval.node) = (PGNode *)n; - ;} - break; - - case 877: -#line 2375 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_UID, "id-uid", "User Id" ), + "uid", + }, { - PGFuncCall *n = makeFuncCall((yyvsp[(1) - (7)].list), (yyvsp[(4) - (7)].list), (yylsp[(1) - (7)])); - n->agg_order = (yyvsp[(5) - (7)].list); - n->agg_ignore_nulls = (yyvsp[(6) - (7)].boolean); - n->agg_distinct = true; - (yyval.node) = (PGNode *)n; - ;} - break; - - case 878: -#line 2383 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_DOMAIN_COMPONENT, "id-domainComponent", "Domain component" ), + "DC", + }, { - /* - * We consider AGGREGATE(*) to invoke a parameterless - * aggregate. This does the right thing for COUNT(*), - * and there are no other aggregates in SQL that accept - * '*' as parameter. - * - * The PGFuncCall node is also marked agg_star = true, - * so that later processing can detect what the argument - * really was. - */ - PGFuncCall *n = makeFuncCall((yyvsp[(1) - (4)].list), NIL, (yylsp[(1) - (4)])); - n->agg_star = true; - (yyval.node) = (PGNode *)n; - ;} - break; - - case 879: -#line 2411 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER, "id-at-uniqueIdentifier", "Unique Identifier" ), + "uniqueIdentifier", + }, { - PGFuncCall *n = (PGFuncCall *) (yyvsp[(1) - (5)].node); - /* - * The order clause for WITHIN GROUP and the one for - * plain-aggregate ORDER BY share a field, so we have to - * check here that at most one is present. We also check - * for DISTINCT and VARIADIC here to give a better error - * location. Other consistency checks are deferred to - * parse analysis. - */ - if ((yyvsp[(2) - (5)].list) != NIL) - { - if (n->agg_order != NIL) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("cannot use multiple ORDER BY clauses with WITHIN GROUP"), - parser_errposition((yylsp[(2) - (5)])))); - if (n->agg_distinct) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("cannot use DISTINCT with WITHIN GROUP"), - parser_errposition((yylsp[(2) - (5)])))); - if (n->func_variadic) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("cannot use VARIADIC with WITHIN GROUP"), - parser_errposition((yylsp[(2) - (5)])))); - n->agg_order = (yyvsp[(2) - (5)].list); - n->agg_within_group = true; - } - n->agg_filter = (yyvsp[(3) - (5)].node); - n->export_state = (yyvsp[(4) - (5)].boolean); - n->over = (yyvsp[(5) - (5)].windef); - (yyval.node) = (PGNode *) n; - ;} - break; - - case 880: -#line 2447 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; + NULL_OID_DESCRIPTOR, + NULL, + } +}; - case 881: -#line 2457 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) +FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) - case 882: -#line 2458 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; +/* + * For X509 extensions + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; - case 883: -#line 2466 "third_party/libpg_query/grammar/statements/select.y" +static const oid_x509_ext_t oid_x509_ext[] = +{ { - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("pg_collation_for"), - list_make1((yyvsp[(4) - (5)].node)), - (yylsp[(1) - (5)])); - ;} - break; - - case 884: -#line 2472 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_BASIC_CONSTRAINTS, "id-ce-basicConstraints", "Basic Constraints" ), + MBEDTLS_OID_X509_EXT_BASIC_CONSTRAINTS, + }, { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_DATE, -1, (yylsp[(1) - (1)])); - ;} - break; - - case 885: -#line 2476 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_KEY_USAGE, "id-ce-keyUsage", "Key Usage" ), + MBEDTLS_OID_X509_EXT_KEY_USAGE, + }, { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_TIME, -1, (yylsp[(1) - (1)])); - ;} - break; - - case 886: -#line 2480 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_EXTENDED_KEY_USAGE, "id-ce-extKeyUsage", "Extended Key Usage" ), + MBEDTLS_OID_X509_EXT_EXTENDED_KEY_USAGE, + }, { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_TIME_N, (yyvsp[(3) - (4)].ival), (yylsp[(1) - (4)])); - ;} - break; - - case 887: -#line 2484 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_SUBJECT_ALT_NAME, "id-ce-subjectAltName", "Subject Alt Name" ), + MBEDTLS_OID_X509_EXT_SUBJECT_ALT_NAME, + }, { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_TIMESTAMP, -1, (yylsp[(1) - (1)])); - ;} - break; - - case 888: -#line 2488 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_NS_CERT_TYPE, "id-netscape-certtype", "Netscape Certificate Type" ), + MBEDTLS_OID_X509_EXT_NS_CERT_TYPE, + }, { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_TIMESTAMP_N, (yyvsp[(3) - (4)].ival), (yylsp[(1) - (4)])); - ;} - break; - - case 889: -#line 2492 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_CERTIFICATE_POLICIES, "id-ce-certificatePolicies", "Certificate Policies" ), + MBEDTLS_OID_X509_EXT_CERTIFICATE_POLICIES, + }, { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_LOCALTIME, -1, (yylsp[(1) - (1)])); - ;} - break; + NULL_OID_DESCRIPTOR, + 0, + }, +}; - case 890: -#line 2496 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_LOCALTIME_N, (yyvsp[(3) - (4)].ival), (yylsp[(1) - (4)])); - ;} - break; +FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) +FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) - case 891: -#line 2500 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_LOCALTIMESTAMP, -1, (yylsp[(1) - (1)])); - ;} - break; +#if !defined(MBEDTLS_X509_REMOVE_INFO) +static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = +{ + OID_DESCRIPTOR( MBEDTLS_OID_SERVER_AUTH, "id-kp-serverAuth", "TLS Web Server Authentication" ), + OID_DESCRIPTOR( MBEDTLS_OID_CLIENT_AUTH, "id-kp-clientAuth", "TLS Web Client Authentication" ), + OID_DESCRIPTOR( MBEDTLS_OID_CODE_SIGNING, "id-kp-codeSigning", "Code Signing" ), + OID_DESCRIPTOR( MBEDTLS_OID_EMAIL_PROTECTION, "id-kp-emailProtection", "E-mail Protection" ), + OID_DESCRIPTOR( MBEDTLS_OID_TIME_STAMPING, "id-kp-timeStamping", "Time Stamping" ), + OID_DESCRIPTOR( MBEDTLS_OID_OCSP_SIGNING, "id-kp-OCSPSigning", "OCSP Signing" ), + OID_DESCRIPTOR( MBEDTLS_OID_WISUN_FAN, "id-kp-wisun-fan-device", "Wi-SUN Alliance Field Area Network (FAN)" ), + NULL_OID_DESCRIPTOR, +}; - case 892: -#line 2504 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_LOCALTIMESTAMP_N, (yyvsp[(3) - (4)].ival), (yylsp[(1) - (4)])); - ;} - break; +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) +FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) - case 893: -#line 2508 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_ROLE, -1, (yylsp[(1) - (1)])); - ;} - break; +static const mbedtls_oid_descriptor_t oid_certificate_policies[] = +{ + OID_DESCRIPTOR( MBEDTLS_OID_ANY_POLICY, "anyPolicy", "Any Policy" ), + NULL_OID_DESCRIPTOR, +}; - case 894: -#line 2512 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_USER, -1, (yylsp[(1) - (1)])); - ;} - break; +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, certificate_policies, oid_certificate_policies) +FN_OID_GET_ATTR1(mbedtls_oid_get_certificate_policies, mbedtls_oid_descriptor_t, certificate_policies, const char *, description) +#endif /* MBEDTLS_X509_REMOVE_INFO */ - case 895: -#line 2516 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_SESSION_USER, -1, (yylsp[(1) - (1)])); - ;} - break; +#if defined(MBEDTLS_MD_C) +/* + * For SignatureAlgorithmIdentifier + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; +} oid_sig_alg_t; - case 896: -#line 2520 "third_party/libpg_query/grammar/statements/select.y" +static const oid_sig_alg_t oid_sig_alg[] = +{ +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_MD5_C) { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_USER, -1, (yylsp[(1) - (1)])); - ;} - break; - - case 897: -#line 2524 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_MD5, "md5WithRSAEncryption", "RSA with MD5" ), + MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_CATALOG, -1, (yylsp[(1) - (1)])); - ;} - break; - - case 898: -#line 2528 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_SHA1, "sha-1WithRSAEncryption", "RSA with SHA1" ), + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA224_C) { - (yyval.node) = makeSQLValueFunction(PG_SVFOP_CURRENT_SCHEMA, -1, (yylsp[(1) - (1)])); - ;} - break; - - case 899: -#line 2532 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeTypeCast((yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].typnam), 0, (yylsp[(1) - (6)])); ;} - break; - - case 900: -#line 2534 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = makeTypeCast((yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].typnam), 1, (yylsp[(1) - (6)])); ;} - break; - - case 901: -#line 2536 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_SHA224, "sha224WithRSAEncryption", "RSA with SHA-224" ), + MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, + }, +#endif +#if defined(MBEDTLS_SHA256_C) { - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("date_part"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} - break; - - case 902: -#line 2540 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_SHA256, "sha256WithRSAEncryption", "RSA with SHA-256" ), + MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) { - /* overlay(A PLACING B FROM C FOR D) is converted to - * overlay(A, B, C, D) - * overlay(A PLACING B FROM C) is converted to - * overlay(A, B, C) - */ - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("overlay"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} - break; - - case 903: -#line 2549 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_SHA384, "sha384WithRSAEncryption", "RSA with SHA-384" ), + MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA384_C */ +#if defined(MBEDTLS_SHA512_C) { - /* position(A in B) is converted to position(B, A) */ - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("position"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} - break; - - case 904: -#line 2554 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_SHA512, "sha512WithRSAEncryption", "RSA with SHA-512" ), + MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SHA1_C) { - /* substring(A from B for C) is converted to - * substring(A, B, C) - thomas 2000-11-28 - */ - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("substring"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} - break; - - case 905: -#line 2561 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_RSA_SHA_OBS, "sha-1WithRSAEncryption", "RSA with SHA1" ), + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_SHA1_C) { - /* TREAT(expr AS target) converts expr of a particular type to target, - * which is defined to be a subtype of the original expression. - * In SQL99, this is intended for use with structured UDTs, - * but let's make this a generally useful form allowing stronger - * coercions than are handled by implicit casting. - * - * Convert SystemTypeName() to SystemFuncName() even though - * at the moment they result in the same thing. - */ - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName(((PGValue *)llast((yyvsp[(5) - (6)].typnam)->names))->val.str), - list_make1((yyvsp[(3) - (6)].node)), - (yylsp[(1) - (6)])); - ;} - break; - - case 906: -#line 2576 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_ECDSA_SHA1, "ecdsa-with-SHA1", "ECDSA with SHA1" ), + MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA224_C) { - /* various trim expressions are defined in SQL - * - thomas 1997-07-19 - */ - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("trim"), (yyvsp[(4) - (5)].list), (yylsp[(1) - (5)])); - ;} - break; - - case 907: -#line 2583 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_ECDSA_SHA224, "ecdsa-with-SHA224", "ECDSA with SHA224" ), + MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, + }, +#endif +#if defined(MBEDTLS_SHA256_C) { - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("ltrim"), (yyvsp[(4) - (5)].list), (yylsp[(1) - (5)])); - ;} - break; - - case 908: -#line 2587 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_ECDSA_SHA256, "ecdsa-with-SHA256", "ECDSA with SHA256" ), + MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) { - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("rtrim"), (yyvsp[(4) - (5)].list), (yylsp[(1) - (5)])); - ;} - break; - - case 909: -#line 2591 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_ECDSA_SHA384, "ecdsa-with-SHA384", "ECDSA with SHA384" ), + MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA384_C */ +#if defined(MBEDTLS_SHA512_C) { - (yyval.node) = (PGNode *) makeFuncCall(SystemFuncName("trim"), (yyvsp[(3) - (4)].list), (yylsp[(1) - (4)])); - ;} - break; - - case 910: -#line 2595 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_ECDSA_SHA512, "ecdsa-with-SHA512", "ECDSA with SHA512" ), + MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_RSA_C) { - (yyval.node) = (PGNode *) makeSimpleAExpr(PG_AEXPR_NULLIF, "=", (yyvsp[(3) - (6)].node), (yyvsp[(5) - (6)].node), (yylsp[(1) - (6)])); - ;} - break; - - case 911: -#line 2599 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_RSASSA_PSS, "RSASSA-PSS", "RSASSA-PSS" ), + MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, + }, +#endif /* MBEDTLS_RSA_C */ { - PGCoalesceExpr *c = makeNode(PGCoalesceExpr); - c->args = (yyvsp[(3) - (4)].list); - c->location = (yylsp[(1) - (4)]); - (yyval.node) = (PGNode *)c; - ;} - break; + NULL_OID_DESCRIPTOR, + MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, + }, +}; - case 912: -#line 2612 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(4) - (5)].list); ;} - break; +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) - case 913: -#line 2613 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +#if !defined(MBEDTLS_X509_REMOVE_INFO) +FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) +#endif - case 914: -#line 2617 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(4) - (5)].node); ;} - break; +FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) +#endif /* MBEDTLS_MD_C */ - case 915: -#line 2618 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; +/* + * For PublicKeyInfo (PKCS1, RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_pk_type_t pk_alg; +} oid_pk_alg_t; - case 916: -#line 2622 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = true; ;} - break; +static const oid_pk_alg_t oid_pk_alg[] = +{ + { + OID_DESCRIPTOR( MBEDTLS_OID_PKCS1_RSA, "rsaEncryption", "RSA" ), + MBEDTLS_PK_RSA, + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_ALG_UNRESTRICTED, "id-ecPublicKey", "Generic EC key" ), + MBEDTLS_PK_ECKEY, + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_ALG_ECDH, "id-ecDH", "EC key for ECDH" ), + MBEDTLS_PK_ECKEY_DH, + }, + { + NULL_OID_DESCRIPTOR, + MBEDTLS_PK_NONE, + }, +}; - case 917: -#line 2623 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.boolean) = false; ;} - break; +FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) - case 918: -#line 2630 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} - break; +#if defined(MBEDTLS_ECP_C) +/* + * For namedCurve (RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_ecp_group_id grp_id; +} oid_ecp_grp_t; - case 919: -#line 2631 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +static const oid_ecp_grp_t oid_ecp_grp[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP192R1, "secp192r1", "secp192r1" ), + MBEDTLS_ECP_DP_SECP192R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP224R1, "secp224r1", "secp224r1" ), + MBEDTLS_ECP_DP_SECP224R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP256R1, "secp256r1", "secp256r1" ), + MBEDTLS_ECP_DP_SECP256R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP384R1, "secp384r1", "secp384r1" ), + MBEDTLS_ECP_DP_SECP384R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP521R1, "secp521r1", "secp521r1" ), + MBEDTLS_ECP_DP_SECP521R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP192K1, "secp192k1", "secp192k1" ), + MBEDTLS_ECP_DP_SECP192K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP224K1, "secp224k1", "secp224k1" ), + MBEDTLS_ECP_DP_SECP224K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_SECP256K1, "secp256k1", "secp256k1" ), + MBEDTLS_ECP_DP_SECP256K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_BP256R1, "brainpoolP256r1","brainpool256r1" ), + MBEDTLS_ECP_DP_BP256R1, + }, +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_BP384R1, "brainpoolP384r1","brainpool384r1" ), + MBEDTLS_ECP_DP_BP384R1, + }, +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { + OID_DESCRIPTOR( MBEDTLS_OID_EC_GRP_BP512R1, "brainpoolP512r1","brainpool512r1" ), + MBEDTLS_ECP_DP_BP512R1, + }, +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + { + NULL_OID_DESCRIPTOR, + MBEDTLS_ECP_DP_NONE, + }, +}; - case 920: -#line 2635 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].windef)); ;} - break; +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) +FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) +#endif /* MBEDTLS_ECP_C */ - case 921: -#line 2637 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].windef)); ;} - break; +#if defined(MBEDTLS_CIPHER_C) +/* + * For PKCS#5 PBES2 encryption algorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_cipher_type_t cipher_alg; +} oid_cipher_alg_t; - case 922: -#line 2642 "third_party/libpg_query/grammar/statements/select.y" +static const oid_cipher_alg_t oid_cipher_alg[] = +{ { - PGWindowDef *n = (yyvsp[(3) - (3)].windef); - n->name = (yyvsp[(1) - (3)].str); - (yyval.windef) = n; - ;} - break; - - case 923: -#line 2650 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.windef) = (yyvsp[(2) - (2)].windef); ;} - break; - - case 924: -#line 2652 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_DES_CBC, "desCBC", "DES-CBC" ), + MBEDTLS_CIPHER_DES_CBC, + }, { - PGWindowDef *n = makeNode(PGWindowDef); - n->name = (yyvsp[(2) - (2)].str); - n->refname = NULL; - n->partitionClause = NIL; - n->orderClause = NIL; - n->frameOptions = FRAMEOPTION_DEFAULTS; - n->startOffset = NULL; - n->endOffset = NULL; - n->location = (yylsp[(2) - (2)]); - (yyval.windef) = n; - ;} - break; - - case 925: -#line 2665 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.windef) = NULL; ;} - break; - - case 926: -#line 2670 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_DES_EDE3_CBC, "des-ede3-cbc", "DES-EDE3-CBC" ), + MBEDTLS_CIPHER_DES_EDE3_CBC, + }, { - PGWindowDef *n = makeNode(PGWindowDef); - n->name = NULL; - n->refname = (yyvsp[(2) - (6)].str); - n->partitionClause = (yyvsp[(3) - (6)].list); - n->orderClause = (yyvsp[(4) - (6)].list); - /* copy relevant fields of opt_frame_clause */ - n->frameOptions = (yyvsp[(5) - (6)].windef)->frameOptions; - n->startOffset = (yyvsp[(5) - (6)].windef)->startOffset; - n->endOffset = (yyvsp[(5) - (6)].windef)->endOffset; - n->location = (yylsp[(1) - (6)]); - (yyval.windef) = n; - ;} - break; + NULL_OID_DESCRIPTOR, + MBEDTLS_CIPHER_NONE, + }, +}; - case 927: -#line 2695 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; +FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_CIPHER_C */ - case 928: -#line 2696 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = NULL; ;} - break; +#if defined(MBEDTLS_MD_C) +/* + * For digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; +} oid_md_alg_t; - case 929: -#line 2699 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (3)].list); ;} - break; +static const oid_md_alg_t oid_md_alg[] = +{ +#if defined(MBEDTLS_MD5_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_MD5, "id-md5", "MD5" ), + MBEDTLS_MD_MD5, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_SHA1, "id-sha1", "SHA-1" ), + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA224_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_SHA224, "id-sha224", "SHA-224" ), + MBEDTLS_MD_SHA224, + }, +#endif +#if defined(MBEDTLS_SHA256_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_SHA256, "id-sha256", "SHA-256" ), + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_SHA384, "id-sha384", "SHA-384" ), + MBEDTLS_MD_SHA384, + }, +#endif /* MBEDTLS_SHA384_C */ +#if defined(MBEDTLS_SHA512_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_SHA512, "id-sha512", "SHA-512" ), + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_RIPEMD160_C) + { + OID_DESCRIPTOR( MBEDTLS_OID_DIGEST_ALG_RIPEMD160, "id-ripemd160", "RIPEMD-160" ), + MBEDTLS_MD_RIPEMD160, + }, +#endif /* MBEDTLS_RIPEMD160_C */ + { + NULL_OID_DESCRIPTOR, + MBEDTLS_MD_NONE, + }, +}; - case 930: -#line 2700 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) - case 931: -#line 2712 "third_party/libpg_query/grammar/statements/select.y" - { - PGWindowDef *n = (yyvsp[(2) - (2)].windef); - n->frameOptions |= FRAMEOPTION_NONDEFAULT | FRAMEOPTION_RANGE; - (yyval.windef) = n; - ;} - break; +/* + * For HMAC digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_hmac; +} oid_md_hmac_t; - case 932: -#line 2718 "third_party/libpg_query/grammar/statements/select.y" +static const oid_md_hmac_t oid_md_hmac[] = +{ +#if defined(MBEDTLS_SHA1_C) { - PGWindowDef *n = (yyvsp[(2) - (2)].windef); - n->frameOptions |= FRAMEOPTION_NONDEFAULT | FRAMEOPTION_ROWS; - (yyval.windef) = n; - ;} - break; - - case 933: -#line 2724 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_HMAC_SHA1, "hmacSHA1", "HMAC-SHA-1" ), + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA224_C) { - PGWindowDef *n = makeNode(PGWindowDef); - n->frameOptions = FRAMEOPTION_DEFAULTS; - n->startOffset = NULL; - n->endOffset = NULL; - (yyval.windef) = n; - ;} - break; - - case 934: -#line 2734 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_HMAC_SHA224, "hmacSHA224", "HMAC-SHA-224" ), + MBEDTLS_MD_SHA224, + }, +#endif +#if defined(MBEDTLS_SHA256_C) { - PGWindowDef *n = (yyvsp[(1) - (1)].windef); - /* reject invalid cases */ - if (n->frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) - ereport(ERROR, - (errcode(PG_ERRCODE_WINDOWING_ERROR), - errmsg("frame start cannot be UNBOUNDED FOLLOWING"), - parser_errposition((yylsp[(1) - (1)])))); - if (n->frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING) - ereport(ERROR, - (errcode(PG_ERRCODE_WINDOWING_ERROR), - errmsg("frame starting from following row cannot end with current row"), - parser_errposition((yylsp[(1) - (1)])))); - n->frameOptions |= FRAMEOPTION_END_CURRENT_ROW; - (yyval.windef) = n; - ;} - break; - - case 935: -#line 2751 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_HMAC_SHA256, "hmacSHA256", "HMAC-SHA-256" ), + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA384_C) { - PGWindowDef *n1 = (yyvsp[(2) - (4)].windef); - PGWindowDef *n2 = (yyvsp[(4) - (4)].windef); - /* form merged options */ - int frameOptions = n1->frameOptions; - /* shift converts START_ options to END_ options */ - frameOptions |= n2->frameOptions << 1; - frameOptions |= FRAMEOPTION_BETWEEN; - /* reject invalid cases */ - if (frameOptions & FRAMEOPTION_START_UNBOUNDED_FOLLOWING) - ereport(ERROR, - (errcode(PG_ERRCODE_WINDOWING_ERROR), - errmsg("frame start cannot be UNBOUNDED FOLLOWING"), - parser_errposition((yylsp[(2) - (4)])))); - if (frameOptions & FRAMEOPTION_END_UNBOUNDED_PRECEDING) - ereport(ERROR, - (errcode(PG_ERRCODE_WINDOWING_ERROR), - errmsg("frame end cannot be UNBOUNDED PRECEDING"), - parser_errposition((yylsp[(4) - (4)])))); - if ((frameOptions & FRAMEOPTION_START_CURRENT_ROW) && - (frameOptions & FRAMEOPTION_END_VALUE_PRECEDING)) - ereport(ERROR, - (errcode(PG_ERRCODE_WINDOWING_ERROR), - errmsg("frame starting from current row cannot have preceding rows"), - parser_errposition((yylsp[(4) - (4)])))); - if ((frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING) && - (frameOptions & (FRAMEOPTION_END_VALUE_PRECEDING | - FRAMEOPTION_END_CURRENT_ROW))) - ereport(ERROR, - (errcode(PG_ERRCODE_WINDOWING_ERROR), - errmsg("frame starting from following row cannot have preceding rows"), - parser_errposition((yylsp[(4) - (4)])))); - n1->frameOptions = frameOptions; - n1->endOffset = n2->startOffset; - (yyval.windef) = n1; - ;} - break; - - case 936: -#line 2796 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_HMAC_SHA384, "hmacSHA384", "HMAC-SHA-384" ), + MBEDTLS_MD_SHA384, + }, +#endif /* MBEDTLS_SHA384_C */ +#if defined(MBEDTLS_SHA512_C) { - PGWindowDef *n = makeNode(PGWindowDef); - n->frameOptions = FRAMEOPTION_START_UNBOUNDED_PRECEDING; - n->startOffset = NULL; - n->endOffset = NULL; - (yyval.windef) = n; - ;} - break; - - case 937: -#line 2804 "third_party/libpg_query/grammar/statements/select.y" + OID_DESCRIPTOR( MBEDTLS_OID_HMAC_SHA512, "hmacSHA512", "HMAC-SHA-512" ), + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ { - PGWindowDef *n = makeNode(PGWindowDef); - n->frameOptions = FRAMEOPTION_START_UNBOUNDED_FOLLOWING; - n->startOffset = NULL; - n->endOffset = NULL; - (yyval.windef) = n; - ;} - break; + NULL_OID_DESCRIPTOR, + MBEDTLS_MD_NONE, + }, +}; - case 938: -#line 2812 "third_party/libpg_query/grammar/statements/select.y" - { - PGWindowDef *n = makeNode(PGWindowDef); - n->frameOptions = FRAMEOPTION_START_CURRENT_ROW; - n->startOffset = NULL; - n->endOffset = NULL; - (yyval.windef) = n; - ;} - break; +FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) +#endif /* MBEDTLS_MD_C */ - case 939: -#line 2820 "third_party/libpg_query/grammar/statements/select.y" - { - PGWindowDef *n = makeNode(PGWindowDef); - n->frameOptions = FRAMEOPTION_START_VALUE_PRECEDING; - n->startOffset = (yyvsp[(1) - (2)].node); - n->endOffset = NULL; - (yyval.windef) = n; - ;} - break; +#if defined(MBEDTLS_PKCS12_C) +/* + * For PKCS#12 PBEs + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_cipher_type_t cipher_alg; +} oid_pkcs12_pbe_alg_t; - case 940: -#line 2828 "third_party/libpg_query/grammar/statements/select.y" +static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = +{ { - PGWindowDef *n = makeNode(PGWindowDef); - n->frameOptions = FRAMEOPTION_START_VALUE_FOLLOWING; - n->startOffset = (yyvsp[(1) - (2)].node); - n->endOffset = NULL; - (yyval.windef) = n; - ;} - break; + OID_DESCRIPTOR( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC, "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" ), + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + OID_DESCRIPTOR( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC, "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" ), + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, + }, + { + NULL_OID_DESCRIPTOR, + MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) +FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_PKCS12_C */ + +#define OID_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +/* Return the x.y.z.... style numeric string for the given OID */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, + const mbedtls_asn1_buf *oid ) +{ + return MBEDTLS_ERR_ERROR_GENERIC_ERROR; // patched because it used to require printf which would fail on Windows +} - case 941: -#line 2848 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} - break; +#endif /* MBEDTLS_OID_C */ - case 942: -#line 2849 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; - case 943: -#line 2852 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list);;} - break; +// LICENSE_CHANGE_END - case 944: -#line 2853 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(2) - (5)].list), (yyvsp[(4) - (5)].node)); ;} - break; - case 945: -#line 2857 "third_party/libpg_query/grammar/statements/select.y" - { - PGNamedArgExpr *na = makeNode(PGNamedArgExpr); - na->name = (yyvsp[(1) - (3)].str); - na->arg = (PGExpr *) (yyvsp[(3) - (3)].node); - na->argnumber = -1; - na->location = (yylsp[(1) - (3)]); - (yyval.node) = (PGNode *) na; - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 946: -#line 2867 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} - break; +/* + * Privacy Enhanced Mail (PEM) decoding + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - case 947: -#line 2868 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} - break; - case 948: -#line 2872 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; - case 949: -#line 2873 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} - break; +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) - case 950: -#line 2877 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.subquerytype) = PG_ANY_SUBLINK; ;} - break; - case 951: -#line 2878 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.subquerytype) = PG_ANY_SUBLINK; ;} - break; - case 952: -#line 2879 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.subquerytype) = PG_ALL_SUBLINK; ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 953: -#line 2882 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; +/** + * \file pem.h + * + * \brief Privacy Enhanced Mail (PEM) decoding + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef MBEDTLS_PEM_H +#define MBEDTLS_PEM_H - case 954: -#line 2883 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) (yyvsp[(1) - (1)].conststr); ;} - break; - case 955: -#line 2886 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "+"; ;} - break; - case 956: -#line 2887 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "-"; ;} - break; - case 957: -#line 2888 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "*"; ;} - break; +#include - case 958: -#line 2889 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "/"; ;} - break; +/** + * \name PEM Error codes + * These error codes are returned in case of errors reading the + * PEM data. + * \{ + */ +/** No PEM header or footer found. */ +#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 +/** PEM string is not as expected. */ +#define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 +/** Failed to allocate memory. */ +#define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 +/** RSA IV is not in hex-format. */ +#define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 +/** Unsupported key encryption algorithm. */ +#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 +/** Private key password can't be empty. */ +#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 +/** Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 +/** Unavailable feature, e.g. hashing/encryption combination. */ +#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 +/** Bad input parameters to function. */ +#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 +/* \} name */ - case 959: -#line 2890 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "%"; ;} - break; +#ifdef __cplusplus +extern "C" { +#endif - case 960: -#line 2891 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "^"; ;} - break; +#if defined(MBEDTLS_PEM_PARSE_C) +/** + * \brief PEM context structure + */ +typedef struct mbedtls_pem_context +{ + unsigned char *MBEDTLS_PRIVATE(buf); /*!< buffer for decoded data */ + size_t MBEDTLS_PRIVATE(buflen); /*!< length of the buffer */ + unsigned char *MBEDTLS_PRIVATE(info); /*!< buffer for extra header information */ +} +mbedtls_pem_context; - case 961: -#line 2892 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "**"; ;} - break; +/** + * \brief PEM context setup + * + * \param ctx context to be initialized + */ +void mbedtls_pem_init( mbedtls_pem_context *ctx ); - case 962: -#line 2893 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "<"; ;} - break; +/** + * \brief Read a buffer for PEM information and store the resulting + * data into the specified context buffers. + * + * \param ctx context to use + * \param header header string to seek and expect + * \param footer footer string to seek and expect + * \param data source data to look in (must be nul-terminated) + * \param pwd password for decryption (can be NULL) + * \param pwdlen length of password + * \param use_len destination for total length used (set after header is + * correctly read, so unless you get + * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or + * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is + * the length to skip) + * + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length + * + * \return 0 on success, or a specific PEM error code + */ +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, + const unsigned char *pwd, + size_t pwdlen, size_t *use_len ); - case 963: -#line 2894 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = ">"; ;} - break; +/** + * \brief PEM context memory freeing + * + * \param ctx context to be freed + */ +void mbedtls_pem_free( mbedtls_pem_context *ctx ); +#endif /* MBEDTLS_PEM_PARSE_C */ - case 964: -#line 2895 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "="; ;} - break; +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a buffer of PEM information from a DER encoded + * buffer. + * + * \param header The header string to write. + * \param footer The footer string to write. + * \param der_data The DER data to encode. + * \param der_len The length of the DER data \p der_data in Bytes. + * \param buf The buffer to write to. + * \param buf_len The length of the output buffer \p buf in Bytes. + * \param olen The address at which to store the total length written + * or required (if \p buf_len is not enough). + * + * \note You may pass \c NULL for \p buf and \c 0 for \p buf_len + * to request the length of the resulting PEM buffer in + * `*olen`. + * + * \note This function may be called with overlapping \p der_data + * and \p buf buffers. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL if \p buf isn't large + * enough to hold the PEM buffer. In this case, `*olen` holds + * the required minimum size of \p buf. + * \return Another PEM or BASE64 error code on other kinds of failure. + */ +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ); +#endif /* MBEDTLS_PEM_WRITE_C */ - case 965: -#line 2896 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "<="; ;} - break; +#ifdef __cplusplus +} +#endif - case 966: -#line 2897 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = ">="; ;} - break; +#endif /* pem.h */ - case 967: -#line 2898 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.conststr) = "<>"; ;} - break; - case 968: -#line 2902 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} - break; +// LICENSE_CHANGE_END - case 969: -#line 2904 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} - break; - case 970: -#line 2909 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} - break; - case 971: -#line 2911 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} - break; - case 972: -#line 2916 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 973: -#line 2918 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} - break; +/** + * \file des.h + * + * \brief DES block cipher + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +#ifndef MBEDTLS_DES_H +#define MBEDTLS_DES_H - case 974: -#line 2920 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString("~~")); ;} - break; - case 975: -#line 2922 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString("!~~")); ;} - break; - case 976: -#line 2924 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString("~~~")); ;} - break; - case 977: -#line 2926 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString("!~~~")); ;} - break; - case 978: -#line 2928 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString("~~*")); ;} - break; +#include +#include - case 979: -#line 2930 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString("!~~*")); ;} - break; +#define MBEDTLS_DES_ENCRYPT 1 +#define MBEDTLS_DES_DECRYPT 0 + +/** The data input has an invalid length. */ +#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 + +#define MBEDTLS_DES_KEY_SIZE 8 + +#ifdef __cplusplus +extern "C" { +#endif - case 980: -#line 2944 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} - break; +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// - case 981: -#line 2946 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lcons(makeString((yyvsp[(1) - (3)].str)), (yyvsp[(3) - (3)].list)); ;} - break; +/** + * \brief DES context structure + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +typedef struct mbedtls_des_context +{ + uint32_t MBEDTLS_PRIVATE(sk)[32]; /*!< DES subkeys */ +} +mbedtls_des_context; - case 982: -#line 2950 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} - break; +/** + * \brief Triple-DES context structure + */ +typedef struct mbedtls_des3_context +{ + uint32_t MBEDTLS_PRIVATE(sk)[96]; /*!< 3DES subkeys */ +} +mbedtls_des3_context; - case 983: -#line 2954 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); - ;} - break; +#else /* MBEDTLS_DES_ALT */ - case 984: -#line 2961 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = (yyvsp[(1) - (1)].list); - ;} - break; - case 985: -#line 2966 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = (yyvsp[(1) - (2)].list); - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 986: -#line 2973 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = (yyvsp[(1) - (1)].list); - ;} - break; +// dummy file to make amalgamantion happy - case 987: -#line 2977 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = NULL; - ;} - break; +// LICENSE_CHANGE_END - case 988: -#line 2986 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); - ;} - break; +#endif /* MBEDTLS_DES_ALT */ - case 989: -#line 2990 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); - ;} - break; +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_init( mbedtls_des_context *ctx ); - case 990: -#line 2996 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (yyvsp[(1) - (1)].node); - ;} - break; +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_free( mbedtls_des_context *ctx ); - case 991: -#line 3000 "third_party/libpg_query/grammar/statements/select.y" - { - PGNamedArgExpr *na = makeNode(PGNamedArgExpr); - na->name = (yyvsp[(1) - (3)].str); - na->arg = (PGExpr *) (yyvsp[(3) - (3)].node); - na->argnumber = -1; /* until determined */ - na->location = (yylsp[(1) - (3)]); - (yyval.node) = (PGNode *) na; - ;} - break; +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +void mbedtls_des3_init( mbedtls_des3_context *ctx ); - case 992: -#line 3009 "third_party/libpg_query/grammar/statements/select.y" - { - PGNamedArgExpr *na = makeNode(PGNamedArgExpr); - na->name = (yyvsp[(1) - (3)].str); - na->arg = (PGExpr *) (yyvsp[(3) - (3)].node); - na->argnumber = -1; /* until determined */ - na->location = (yylsp[(1) - (3)]); - (yyval.node) = (PGNode *) na; - ;} - break; +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + */ +void mbedtls_des3_free( mbedtls_des3_context *ctx ); - case 993: -#line 3019 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].typnam)); ;} - break; +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - case 994: -#line 3020 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].typnam)); ;} - break; +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \return 0 is parity was ok, 1 if parity was not correct. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - case 995: -#line 3025 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make2(makeStringConst((yyvsp[(1) - (3)].str), (yylsp[(1) - (3)])), (yyvsp[(3) - (3)].node)); - ;} - break; +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \return 0 if no weak key was found, 1 if a weak key was identified. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - case 996: -#line 3028 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - case 997: -#line 3035 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - case 998: -#line 3036 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "year"; ;} - break; +/** + * \brief Triple-DES key schedule (112-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); - case 999: -#line 3037 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "month"; ;} - break; +/** + * \brief Triple-DES key schedule (112-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); - case 1000: -#line 3038 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "day"; ;} - break; +/** + * \brief Triple-DES key schedule (168-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); - case 1001: -#line 3039 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "hour"; ;} - break; +/** + * \brief Triple-DES key schedule (168-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); - case 1002: -#line 3040 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "minute"; ;} - break; +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); - case 1003: -#line 3041 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "second"; ;} - break; +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ - case 1004: -#line 3042 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "millisecond"; ;} - break; +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); - case 1005: -#line 3043 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (char*) "microsecond"; ;} - break; +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx 3DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH + */ +MBEDTLS_CHECK_RETURN_TYPICAL +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ - case 1006: -#line 3044 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; +/** + * \brief Internal function for key expansion. + * (Only exposed to allow overriding it, + * see MBEDTLS_DES_SETKEY_ALT) + * + * \param SK Round keys + * \param key Base key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_setkey( uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); - case 1007: -#line 3055 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make4((yyvsp[(1) - (4)].node), (yyvsp[(2) - (4)].node), (yyvsp[(3) - (4)].node), (yyvsp[(4) - (4)].node)); - ;} - break; +#if defined(MBEDTLS_SELF_TEST) - case 1008: -#line 3059 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make3((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].node), (yyvsp[(3) - (3)].node)); - ;} - break; +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +MBEDTLS_CHECK_RETURN_CRITICAL +int mbedtls_des_self_test( int verbose ); - case 1009: -#line 3066 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} - break; +#endif /* MBEDTLS_SELF_TEST */ - case 1010: -#line 3072 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2((yyvsp[(3) - (3)].node), (yyvsp[(1) - (3)].node)); ;} - break; +#ifdef __cplusplus +} +#endif - case 1011: -#line 3073 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +#endif /* des.h */ - case 1012: -#line 3090 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make3((yyvsp[(1) - (3)].node), (yyvsp[(2) - (3)].node), (yyvsp[(3) - (3)].node)); - ;} - break; - case 1013: -#line 3094 "third_party/libpg_query/grammar/statements/select.y" - { - /* not legal per SQL99, but might as well allow it */ - (yyval.list) = list_make3((yyvsp[(1) - (3)].node), (yyvsp[(3) - (3)].node), (yyvsp[(2) - (3)].node)); - ;} - break; +// LICENSE_CHANGE_END - case 1014: -#line 3099 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = list_make2((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].node)); - ;} - break; +#ifdef MBEDTLS_AES_C - case 1015: -#line 3103 "third_party/libpg_query/grammar/statements/select.y" - { - /* - * Since there are no cases where this syntax allows - * a textual FOR value, we forcibly cast the argument - * to int4. The possible matches in pg_proc are - * substring(text,int4) and substring(text,text), - * and we don't want the parser to choose the latter, - * which it is likely to do if the second argument - * is unknown or doesn't have an implicit cast to int4. - */ - (yyval.list) = list_make3((yyvsp[(1) - (2)].node), makeIntConst(1, -1), - makeTypeCast((yyvsp[(2) - (2)].node), - SystemTypeName("int4"), 0, -1)); - ;} - break; - case 1016: -#line 3118 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = (yyvsp[(1) - (1)].list); - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 1017: -#line 3122 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +// dummy file to make amalgamantion happy - case 1018: -#line 3126 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} - break; +// LICENSE_CHANGE_END - case 1019: -#line 3129 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} - break; +#endif +#ifdef MBEDTLS_MD5_C - case 1020: -#line 3132 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(3) - (3)].list), (yyvsp[(1) - (3)].node)); ;} - break; +#endif - case 1021: -#line 3133 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} - break; - case 1022: -#line 3134 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; - case 1023: -#line 3138 "third_party/libpg_query/grammar/statements/select.y" - { - PGSubLink *n = makeNode(PGSubLink); - n->subselect = (yyvsp[(1) - (1)].node); - /* other fields will be filled later */ - (yyval.node) = (PGNode *)n; - ;} - break; - case 1024: -#line 3144 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (PGNode *)(yyvsp[(2) - (3)].list); ;} - break; +#include - case 1025: -#line 3155 "third_party/libpg_query/grammar/statements/select.y" - { - PGCaseExpr *c = makeNode(PGCaseExpr); - c->casetype = InvalidOid; /* not analyzed yet */ - c->arg = (PGExpr *) (yyvsp[(2) - (5)].node); - c->args = (yyvsp[(3) - (5)].list); - c->defresult = (PGExpr *) (yyvsp[(4) - (5)].node); - c->location = (yylsp[(1) - (5)]); - (yyval.node) = (PGNode *)c; - ;} - break; +#if defined(MBEDTLS_PLATFORM_C) - case 1026: -#line 3168 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} - break; +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif - case 1027: -#line 3169 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} - break; +#if defined(MBEDTLS_PEM_PARSE_C) +void mbedtls_pem_init( mbedtls_pem_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pem_context ) ); +} - case 1028: -#line 3174 "third_party/libpg_query/grammar/statements/select.y" - { - PGCaseWhen *w = makeNode(PGCaseWhen); - w->expr = (PGExpr *) (yyvsp[(2) - (4)].node); - w->result = (PGExpr *) (yyvsp[(4) - (4)].node); - w->location = (yylsp[(1) - (4)]); - (yyval.node) = (PGNode *)w; - ;} - break; +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) +/* + * Read a 16-byte hex string and convert it to binary + */ +static int pem_get_iv( const unsigned char *s, unsigned char *iv, + size_t iv_len ) +{ + size_t i, j, k; - case 1029: -#line 3184 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} - break; + memset( iv, 0, iv_len ); - case 1030: -#line 3185 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; + for( i = 0; i < iv_len * 2; i++, s++ ) + { + if( *s >= '0' && *s <= '9' ) j = *s - '0'; else + if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else + if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); - case 1031: -#line 3188 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; + k = ( ( i & 1 ) != 0 ) ? j : j << 4; - case 1032: -#line 3189 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; + iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); + } - case 1033: -#line 3193 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeColumnRef((yyvsp[(1) - (1)].str), NIL, (yylsp[(1) - (1)]), yyscanner); - ;} - break; + return( 0 ); +} - case 1034: -#line 3197 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeColumnRef((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].list), (yylsp[(1) - (2)]), yyscanner); - ;} - break; +static int pem_pbkdf1( unsigned char *key, size_t keylen, + unsigned char *iv, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_md5_context md5_ctx; + unsigned char md5sum[16]; + size_t use_len; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - case 1035: -#line 3204 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = (PGNode *) makeString((yyvsp[(2) - (2)].str)); - ;} - break; + mbedtls_md5_init( &md5_ctx ); - case 1036: -#line 3208 "third_party/libpg_query/grammar/statements/select.y" + /* + * key[ 0..15] = MD5(pwd || IV) + */ + if( ( ret = mbedtls_md5_starts( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + if( keylen <= 16 ) { - PGAIndices *ai = makeNode(PGAIndices); - ai->is_slice = false; - ai->lidx = NULL; - ai->uidx = (yyvsp[(2) - (3)].node); - (yyval.node) = (PGNode *) ai; - ;} - break; + memcpy( key, md5sum, keylen ); + goto exit; + } - case 1037: -#line 3216 "third_party/libpg_query/grammar/statements/select.y" - { - PGAIndices *ai = makeNode(PGAIndices); - ai->is_slice = true; - ai->lidx = (yyvsp[(2) - (5)].node); - ai->uidx = (yyvsp[(4) - (5)].node); - (yyval.node) = (PGNode *) ai; - ;} - break; + memcpy( key, md5sum, 16 ); - case 1038: -#line 3226 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = (yyvsp[(1) - (1)].node); ;} - break; + /* + * key[16..23] = MD5(key[ 0..15] || pwd || IV]) + */ + if( ( ret = mbedtls_md5_starts( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update( &md5_ctx, md5sum, 16 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish( &md5_ctx, md5sum ) ) != 0 ) + goto exit; - case 1039: -#line 3227 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.node) = NULL; ;} - break; + use_len = 16; + if( keylen < 32 ) + use_len = keylen - 16; - case 1040: -#line 3231 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} - break; + memcpy( key + 16, md5sum, use_len ); - case 1041: -#line 3232 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} - break; +exit: + mbedtls_md5_free( &md5_ctx ); + mbedtls_platform_zeroize( md5sum, 16 ); - case 1042: -#line 3236 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; + return( ret ); +} - case 1043: -#line 3237 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); ;} - break; +#if defined(MBEDTLS_DES_C) +/* + * Decrypt with DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des_decrypt( unsigned char des_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des_context des_ctx; + unsigned char des_key[8]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - case 1046: -#line 3251 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; + mbedtls_des_init( &des_ctx ); - case 1047: -#line 3252 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; + if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 ) + goto exit; - case 1048: -#line 3256 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].target)); ;} - break; + if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 ) + goto exit; + ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, + des_iv, buf, buf ); - case 1049: -#line 3257 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].target)); ;} - break; +exit: + mbedtls_des_free( &des_ctx ); + mbedtls_platform_zeroize( des_key, 8 ); - case 1050: -#line 3261 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; + return( ret ); +} - case 1051: -#line 3262 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} - break; +/* + * Decrypt with 3DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des3_decrypt( unsigned char des3_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des3_context des3_ctx; + unsigned char des3_key[24]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - case 1052: -#line 3266 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.target) = makeNode(PGResTarget); - (yyval.target)->name = (yyvsp[(3) - (3)].str); - (yyval.target)->indirection = NIL; - (yyval.target)->val = (PGNode *)(yyvsp[(1) - (3)].node); - (yyval.target)->location = (yylsp[(1) - (3)]); - ;} - break; + mbedtls_des3_init( &des3_ctx ); - case 1053: -#line 3282 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.target) = makeNode(PGResTarget); - (yyval.target)->name = (yyvsp[(2) - (2)].str); - (yyval.target)->indirection = NIL; - (yyval.target)->val = (PGNode *)(yyvsp[(1) - (2)].node); - (yyval.target)->location = (yylsp[(1) - (2)]); - ;} - break; + if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 ) + goto exit; - case 1054: -#line 3290 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.target) = makeNode(PGResTarget); - (yyval.target)->name = NULL; - (yyval.target)->indirection = NIL; - (yyval.target)->val = (PGNode *)(yyvsp[(1) - (1)].node); - (yyval.target)->location = (yylsp[(1) - (1)]); - ;} - break; + if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 ) + goto exit; + ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, + des3_iv, buf, buf ); - case 1055: -#line 3298 "third_party/libpg_query/grammar/statements/select.y" - { - PGColumnRef *n = makeNode(PGColumnRef); - PGAStar *star = makeNode(PGAStar); - n->fields = list_make1(star); - n->location = (yylsp[(1) - (3)]); - star->except_list = (yyvsp[(2) - (3)].list); - star->replace_list = (yyvsp[(3) - (3)].list); +exit: + mbedtls_des3_free( &des3_ctx ); + mbedtls_platform_zeroize( des3_key, 24 ); - (yyval.target) = makeNode(PGResTarget); - (yyval.target)->name = NULL; - (yyval.target)->indirection = NIL; - (yyval.target)->val = (PGNode *)n; - (yyval.target)->location = (yylsp[(1) - (3)]); - ;} - break; + return( ret ); +} +#endif /* MBEDTLS_DES_C */ - case 1056: -#line 3313 "third_party/libpg_query/grammar/statements/select.y" - { - PGColumnRef *n = makeNode(PGColumnRef); - PGAStar *star = makeNode(PGAStar); - n->fields = list_make1(star); - n->location = (yylsp[(1) - (5)]); - star->relation = (yyvsp[(1) - (5)].str); - star->except_list = (yyvsp[(4) - (5)].list); - star->replace_list = (yyvsp[(5) - (5)].list); +#if defined(MBEDTLS_AES_C) +/* + * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation + */ +static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_aes_context aes_ctx; + unsigned char aes_key[32]; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - (yyval.target) = makeNode(PGResTarget); - (yyval.target)->name = NULL; - (yyval.target)->indirection = NIL; - (yyval.target)->val = (PGNode *)n; - (yyval.target)->location = (yylsp[(1) - (5)]); - ;} - break; + mbedtls_aes_init( &aes_ctx ); - case 1057: -#line 3330 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} - break; + if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 ) + goto exit; - case 1058: -#line 3331 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(2) - (2)].str))); ;} - break; + if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 ) + goto exit; + ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, + aes_iv, buf, buf ); - case 1059: -#line 3334 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; +exit: + mbedtls_aes_free( &aes_ctx ); + mbedtls_platform_zeroize( aes_key, keylen ); - case 1060: -#line 3335 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NULL; ;} - break; + return( ret ); +} +#endif /* MBEDTLS_AES_C */ - case 1061: -#line 3338 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make2((yyvsp[(1) - (3)].node), makeString((yyvsp[(3) - (3)].str))); ;} - break; +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ - case 1062: -#line 3342 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].list)); ;} - break; +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, const unsigned char *pwd, + size_t pwdlen, size_t *use_len ) +{ + int ret, enc; + size_t len; + unsigned char *buf; + const unsigned char *s1, *s2, *end; +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + unsigned char pem_iv[16]; + mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ - case 1063: -#line 3343 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].list)); ;} - break; + if( ctx == NULL ) + return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ); - case 1064: -#line 3347 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; + s1 = (unsigned char *) strstr( (const char *) data, header ); - case 1065: -#line 3348 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} - break; + if( s1 == NULL ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); - case 1066: -#line 3351 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(3) - (4)].list); ;} - break; + s2 = (unsigned char *) strstr( (const char *) data, footer ); - case 1067: -#line 3352 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(2) - (2)].list)); ;} - break; + if( s2 == NULL || s2 <= s1 ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); - case 1068: -#line 3353 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NULL; ;} - break; + s1 += strlen( header ); + if( *s1 == ' ' ) s1++; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); - case 1069: -#line 3363 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].range)); ;} - break; + end = s2; + end += strlen( footer ); + if( *end == ' ' ) end++; + if( *end == '\r' ) end++; + if( *end == '\n' ) end++; + *use_len = end - data; - case 1070: -#line 3364 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].range)); ;} - break; + enc = 0; - case 1071: -#line 3376 "third_party/libpg_query/grammar/statements/select.y" + if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) { - (yyval.range) = makeRangeVar(NULL, (yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); - ;} - break; +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + enc++; - case 1072: -#line 3380 "third_party/libpg_query/grammar/statements/select.y" - { - check_qualified_name((yyvsp[(2) - (2)].list), yyscanner); - (yyval.range) = makeRangeVar(NULL, NULL, (yylsp[(1) - (2)])); - switch (list_length((yyvsp[(2) - (2)].list))) - { - case 1: - (yyval.range)->catalogname = NULL; - (yyval.range)->schemaname = (yyvsp[(1) - (2)].str); - (yyval.range)->relname = strVal(linitial((yyvsp[(2) - (2)].list))); - break; - case 2: - (yyval.range)->catalogname = (yyvsp[(1) - (2)].str); - (yyval.range)->schemaname = strVal(linitial((yyvsp[(2) - (2)].list))); - (yyval.range)->relname = strVal(lsecond((yyvsp[(2) - (2)].list))); - break; - default: - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("improper qualified name (too many dotted names): %s", - NameListToString(lcons(makeString((yyvsp[(1) - (2)].str)), (yyvsp[(2) - (2)].list)))), - parser_errposition((yylsp[(1) - (2)])))); - break; - } - ;} - break; + s1 += 22; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); - case 1073: -#line 3407 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} - break; - case 1074: -#line 3409 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeString((yyvsp[(3) - (3)].str))); ;} - break; +#if defined(MBEDTLS_DES_C) + if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; - case 1075: -#line 3414 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (1)].list); ;} - break; + s1 += 23; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); - case 1076: -#line 3415 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(1) - (2)].list); ;} - break; + s1 += 16; + } + else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_CBC; - case 1077: -#line 3418 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + s1 += 18; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); - case 1078: -#line 3420 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + s1 += 16; + } +#endif /* MBEDTLS_DES_C */ - case 1079: -#line 3431 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} - break; +#if defined(MBEDTLS_AES_C) + if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) + { + if( s2 - s1 < 22 ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_128_CBC; + else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_192_CBC; + else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_256_CBC; + else + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); - case 1080: -#line 3434 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.list) = check_func_name(lcons(makeString((yyvsp[(1) - (2)].str)), (yyvsp[(2) - (2)].list)), - yyscanner); - ;} - break; + s1 += 22; + if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); - case 1081: -#line 3445 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeIntConst((yyvsp[(1) - (1)].ival), (yylsp[(1) - (1)])); - ;} - break; + s1 += 32; + } +#endif /* MBEDTLS_AES_C */ - case 1082: -#line 3449 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeFloatConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); - ;} - break; + if( enc_alg == MBEDTLS_CIPHER_NONE ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); - case 1083: -#line 3453 "third_party/libpg_query/grammar/statements/select.y" - { - if ((yyvsp[(2) - (2)].list)) - { - PGAIndirection *n = makeNode(PGAIndirection); - n->arg = makeStringConst((yyvsp[(1) - (2)].str), (yylsp[(1) - (2)])); - n->indirection = check_indirection((yyvsp[(2) - (2)].list), yyscanner); - (yyval.node) = (PGNode *) n; - } - else - (yyval.node) = makeStringConst((yyvsp[(1) - (2)].str), (yylsp[(1) - (2)])); - ;} - break; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); +#else + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } - case 1084: -#line 3465 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeBitStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); - ;} - break; + if( s1 >= s2 ) + return( MBEDTLS_ERR_PEM_INVALID_DATA ); - case 1085: -#line 3469 "third_party/libpg_query/grammar/statements/select.y" - { - /* This is a bit constant per SQL99: - * Without Feature F511, "BIT data type", - * a shall not be a - * or a . - */ - (yyval.node) = makeBitStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); - ;} - break; + ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); - case 1086: -#line 3478 "third_party/libpg_query/grammar/statements/select.y" + if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PEM_INVALID_DATA, ret ) ); + + if( ( buf = (unsigned char *) mbedtls_calloc( 1, len ) ) == NULL ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) { - /* generic type 'literal' syntax */ - PGTypeName *t = makeTypeNameFromNameList((yyvsp[(1) - (2)].list)); - t->location = (yylsp[(1) - (2)]); - (yyval.node) = makeStringConstCast((yyvsp[(2) - (2)].str), (yylsp[(2) - (2)]), t); - ;} - break; + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PEM_INVALID_DATA, ret ) ); + } - case 1087: -#line 3485 "third_party/libpg_query/grammar/statements/select.y" + if( enc != 0 ) { - /* generic syntax with a type modifier */ - PGTypeName *t = makeTypeNameFromNameList((yyvsp[(1) - (7)].list)); - PGListCell *lc; +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + if( pwd == NULL ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); + } - /* - * We must use func_arg_list and opt_sort_clause in the - * production to avoid reduce/reduce conflicts, but we - * don't actually wish to allow PGNamedArgExpr in this - * context, ORDER BY, nor IGNORE NULLS. - */ - foreach(lc, (yyvsp[(3) - (7)].list)) - { - PGNamedArgExpr *arg = (PGNamedArgExpr *) lfirst(lc); + ret = 0; + +#if defined(MBEDTLS_DES_C) + if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) + ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) + ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) + ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) + ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) + ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_AES_C */ + + if( ret != 0 ) + { + mbedtls_free( buf ); + return( ret ); + } - if (IsA(arg, PGNamedArgExpr)) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("type modifier cannot have parameter name"), - parser_errposition(arg->location))); - } - if ((yyvsp[(4) - (7)].list) != NIL) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("type modifier cannot have ORDER BY"), - parser_errposition((yylsp[(4) - (7)])))); - if ((yyvsp[(5) - (7)].boolean) != false) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("type modifier cannot have IGNORE NULLS"), - parser_errposition((yylsp[(5) - (7)])))); + /* + * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 + * length bytes (allow 4 to be sure) in all known use cases. + * + * Use that as a heuristic to try to detect password mismatches. + */ + if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); + } +#else + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + ctx->buf = buf; + ctx->buflen = len; - t->typmods = (yyvsp[(3) - (7)].list); - t->location = (yylsp[(1) - (7)]); - (yyval.node) = makeStringConstCast((yyvsp[(7) - (7)].str), (yylsp[(7) - (7)]), t); - ;} - break; + return( 0 ); +} - case 1088: -#line 3523 "third_party/libpg_query/grammar/statements/select.y" +void mbedtls_pem_free( mbedtls_pem_context *ctx ) +{ + if ( ctx->buf != NULL ) { - (yyval.node) = makeStringConstCast((yyvsp[(2) - (2)].str), (yylsp[(2) - (2)]), (yyvsp[(1) - (2)].typnam)); - ;} - break; + mbedtls_platform_zeroize( ctx->buf, ctx->buflen ); + mbedtls_free( ctx->buf ); + } + mbedtls_free( ctx->info ); - case 1089: -#line 3527 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeIntervalNode((yyvsp[(3) - (5)].node), (yylsp[(3) - (5)]), (yyvsp[(5) - (5)].list)); - ;} - break; + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) ); +} +#endif /* MBEDTLS_PEM_PARSE_C */ - case 1090: -#line 3531 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeIntervalNode((yyvsp[(2) - (3)].ival), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].list)); - ;} - break; +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *encode_buf = NULL, *c, *p = buf; + size_t len = 0, use_len, add_len = 0; - case 1091: -#line 3535 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeIntervalNode((yyvsp[(2) - (3)].str), (yylsp[(2) - (3)]), (yyvsp[(3) - (3)].list)); - ;} - break; + mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len ); + add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1; - case 1092: -#line 3539 "third_party/libpg_query/grammar/statements/select.y" + if( use_len + add_len > buf_len ) { - (yyval.node) = makeBoolAConst(true, (yylsp[(1) - (1)])); - ;} - break; + *olen = use_len + add_len; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } - case 1093: -#line 3543 "third_party/libpg_query/grammar/statements/select.y" - { - (yyval.node) = makeBoolAConst(false, (yylsp[(1) - (1)])); - ;} - break; + if( use_len != 0 && + ( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); - case 1094: -#line 3547 "third_party/libpg_query/grammar/statements/select.y" + if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data, + der_len ) ) != 0 ) { - (yyval.node) = makeNullAConst((yylsp[(1) - (1)])); - ;} - break; - - case 1095: -#line 3552 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;} - break; - - case 1096: -#line 3553 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; - - case 1097: -#line 3569 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + mbedtls_free( encode_buf ); + return( ret ); + } - case 1098: -#line 3570 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} - break; + memcpy( p, header, strlen( header ) ); + p += strlen( header ); + c = encode_buf; - case 1099: -#line 3571 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} - break; + while( use_len ) + { + len = ( use_len > 64 ) ? 64 : use_len; + memcpy( p, c, len ); + use_len -= len; + p += len; + c += len; + *p++ = '\n'; + } - case 1100: -#line 3574 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + memcpy( p, footer, strlen( footer ) ); + p += strlen( footer ); - case 1101: -#line 3575 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + *p++ = '\0'; + *olen = p - buf; - case 1102: -#line 3581 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + /* Clean any remaining data previously written to the buffer */ + memset( buf + *olen, 0, buf_len - *olen ); - case 1103: -#line 3582 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} - break; + mbedtls_free( encode_buf ); + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ - case 1104: -#line 3583 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} - break; - case 1105: -#line 3586 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; - case 1106: -#line 3587 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} - break; +// LICENSE_CHANGE_END - case 1107: -#line 3588 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} - break; - case 1108: -#line 3591 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 1109: -#line 3592 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} - break; +/* + * Public Key abstraction layer + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - case 1110: -#line 3593 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} - break; - case 1111: -#line 3596 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(1) - (1)].str))); ;} - break; - case 1112: -#line 3597 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lcons(makeString((yyvsp[(1) - (2)].str)), (yyvsp[(2) - (2)].list)); ;} - break; +#if defined(MBEDTLS_PK_C) - case 1113: -#line 3601 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = list_make1(makeString((yyvsp[(2) - (2)].str))); ;} - break; - case 1114: -#line 3603 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), makeString((yyvsp[(3) - (3)].str))); ;} - break; - case 1115: -#line 3607 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 1116: -#line 3608 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.list) = NIL; ;} - break; +/** + * \file pk_wrap.h + * + * \brief Public Key abstraction layer: wrapper functions + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - case 1118: -#line 3619 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; +#ifndef MBEDTLS_PK_WRAP_H +#define MBEDTLS_PK_WRAP_H - case 1119: -#line 3620 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} - break; - case 1120: -#line 3621 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} - break; - case 1121: -#line 3622 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} - break; - case 1122: -#line 3625 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; - case 1123: -#line 3626 "third_party/libpg_query/grammar/statements/select.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; +struct mbedtls_pk_info_t +{ + /** Public key type */ + mbedtls_pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_bitlen)( const void * ); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)( mbedtls_pk_type_t type ); + + /** Verify signature */ + int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + + /** Make signature */ + int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Verify signature (restartable) */ + int (*verify_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + + /** Make signature (restartable) */ + int (*sign_rs_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Decrypt message */ + int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Encrypt message */ + int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Check public-private key pair */ + int (*check_pair_func)( const void *pub, const void *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /** Allocate the restart context */ + void * (*rs_alloc_func)( void ); + + /** Free the restart context */ + void (*rs_free_func)( void *rs_ctx ); +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + + /** Interface with the debug module */ + void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); + +}; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Container for RSA-alt */ +typedef struct +{ + void *key; + mbedtls_pk_rsa_alt_decrypt_func decrypt_func; + mbedtls_pk_rsa_alt_sign_func sign_func; + mbedtls_pk_rsa_alt_key_len_func key_len_func; +} mbedtls_rsa_alt_context; +#endif - case 1124: -#line 8 "third_party/libpg_query/grammar/statements/prepare.y" - { - PGPrepareStmt *n = makeNode(PGPrepareStmt); - n->name = (yyvsp[(2) - (5)].str); - n->argtypes = (yyvsp[(3) - (5)].list); - n->query = (yyvsp[(5) - (5)].node); - (yyval.node) = (PGNode *) n; - ;} - break; +#if defined(MBEDTLS_RSA_C) +extern const mbedtls_pk_info_t mbedtls_rsa_info; +#endif - case 1125: -#line 18 "third_party/libpg_query/grammar/statements/prepare.y" - { (yyval.list) = (yyvsp[(2) - (3)].list); ;} - break; +#if defined(MBEDTLS_ECP_C) +extern const mbedtls_pk_info_t mbedtls_eckey_info; +extern const mbedtls_pk_info_t mbedtls_eckeydh_info; +#endif - case 1126: -#line 19 "third_party/libpg_query/grammar/statements/prepare.y" - { (yyval.list) = NIL; ;} - break; +#if defined(MBEDTLS_ECDSA_C) +extern const mbedtls_pk_info_t mbedtls_ecdsa_info; +#endif - case 1131: -#line 8 "third_party/libpg_query/grammar/statements/create_schema.y" - { - PGCreateSchemaStmt *n = makeNode(PGCreateSchemaStmt); - /* ...but not both */ - n->schemaname = (yyvsp[(3) - (4)].str); - n->schemaElts = (yyvsp[(4) - (4)].list); - n->onconflict = PG_ERROR_ON_CONFLICT; - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; +#endif - case 1132: -#line 17 "third_party/libpg_query/grammar/statements/create_schema.y" - { - PGCreateSchemaStmt *n = makeNode(PGCreateSchemaStmt); - /* ...but not here */ - n->schemaname = (yyvsp[(6) - (7)].str); - if ((yyvsp[(7) - (7)].list) != NIL) - ereport(ERROR, - (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("CREATE SCHEMA IF NOT EXISTS cannot include schema elements"), - parser_errposition((yylsp[(7) - (7)])))); - n->schemaElts = (yyvsp[(7) - (7)].list); - n->onconflict = PG_IGNORE_ON_CONFLICT; - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(MBEDTLS_USE_PSA_CRYPTO) +extern const mbedtls_pk_info_t mbedtls_pk_opaque_info; +#endif - case 1133: -#line 35 "third_party/libpg_query/grammar/statements/create_schema.y" - { - if ((yyloc) < 0) /* see comments for YYLLOC_DEFAULT */ - (yyloc) = (yylsp[(2) - (2)]); - (yyval.list) = lappend((yyvsp[(1) - (2)].list), (yyvsp[(2) - (2)].node)); - ;} - break; +#endif /* MBEDTLS_PK_WRAP_H */ - case 1134: -#line 41 "third_party/libpg_query/grammar/statements/create_schema.y" - { (yyval.list) = NIL; ;} - break; - case 1139: -#line 11 "third_party/libpg_query/grammar/statements/index.y" - { - PGIndexStmt *n = makeNode(PGIndexStmt); - n->unique = (yyvsp[(2) - (13)].boolean); - n->concurrent = (yyvsp[(4) - (13)].boolean); - n->idxname = (yyvsp[(5) - (13)].str); - n->relation = (yyvsp[(7) - (13)].range); - n->accessMethod = (yyvsp[(8) - (13)].str); - n->indexParams = (yyvsp[(10) - (13)].list); - n->options = (yyvsp[(12) - (13)].list); - n->whereClause = (yyvsp[(13) - (13)].node); - n->excludeOpNames = NIL; - n->idxcomment = NULL; - n->indexOid = InvalidOid; - n->oldNode = InvalidOid; - n->primary = false; - n->isconstraint = false; - n->deferrable = false; - n->initdeferred = false; - n->transformed = false; - n->onconflict = PG_ERROR_ON_CONFLICT; - (yyval.node) = (PGNode *)n; - ;} - break; +// LICENSE_CHANGE_END - case 1140: -#line 36 "third_party/libpg_query/grammar/statements/index.y" - { - PGIndexStmt *n = makeNode(PGIndexStmt); - n->unique = (yyvsp[(2) - (16)].boolean); - n->concurrent = (yyvsp[(4) - (16)].boolean); - n->idxname = (yyvsp[(8) - (16)].str); - n->relation = (yyvsp[(10) - (16)].range); - n->accessMethod = (yyvsp[(11) - (16)].str); - n->indexParams = (yyvsp[(13) - (16)].list); - n->options = (yyvsp[(15) - (16)].list); - n->whereClause = (yyvsp[(16) - (16)].node); - n->excludeOpNames = NIL; - n->idxcomment = NULL; - n->indexOid = InvalidOid; - n->oldNode = InvalidOid; - n->primary = false; - n->isconstraint = false; - n->deferrable = false; - n->initdeferred = false; - n->transformed = false; - n->onconflict = PG_IGNORE_ON_CONFLICT; - (yyval.node) = (PGNode *)n; - ;} - break; - case 1141: -#line 62 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; - case 1142: -#line 66 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.str) = (yyvsp[(2) - (2)].str); ;} - break; - case 1143: -#line 67 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.str) = (char*) DEFAULT_INDEX_TYPE; ;} - break; - case 1144: -#line 72 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.boolean) = true; ;} - break; +#if defined(MBEDTLS_RSA_C) - case 1145: -#line 73 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.boolean) = false; ;} - break; +#endif +#if defined(MBEDTLS_ECP_C) - case 1146: -#line 78 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; +#endif +#if defined(MBEDTLS_ECDSA_C) - case 1147: -#line 79 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.str) = NULL; ;} - break; +#endif - case 1148: -#line 83 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} - break; +#if defined(MBEDTLS_USE_PSA_CRYPTO) - case 1149: -#line 84 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.list) = NIL; ;} - break; - case 1150: -#line 89 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.boolean) = true; ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 1151: -#line 90 "third_party/libpg_query/grammar/statements/index.y" - { (yyval.boolean) = false; ;} - break; +// dummy file to make amalgamantion happy - case 1152: -#line 8 "third_party/libpg_query/grammar/statements/alter_schema.y" - { - PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); - n->objectType = PG_OBJECT_TABLE; - n->relation = (yyvsp[(3) - (6)].range); - n->newschema = (yyvsp[(6) - (6)].str); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; +// LICENSE_CHANGE_END - case 1153: -#line 17 "third_party/libpg_query/grammar/statements/alter_schema.y" - { - PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); - n->objectType = PG_OBJECT_TABLE; - n->relation = (yyvsp[(5) - (8)].range); - n->newschema = (yyvsp[(8) - (8)].str); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; +#endif - case 1154: -#line 26 "third_party/libpg_query/grammar/statements/alter_schema.y" - { - PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); - n->objectType = PG_OBJECT_SEQUENCE; - n->relation = (yyvsp[(3) - (6)].range); - n->newschema = (yyvsp[(6) - (6)].str); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; +#include +#include - case 1155: -#line 35 "third_party/libpg_query/grammar/statements/alter_schema.y" - { - PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); - n->objectType = PG_OBJECT_SEQUENCE; - n->relation = (yyvsp[(5) - (8)].range); - n->newschema = (yyvsp[(8) - (8)].str); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) - case 1156: -#line 44 "third_party/libpg_query/grammar/statements/alter_schema.y" - { - PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); - n->objectType = PG_OBJECT_VIEW; - n->relation = (yyvsp[(3) - (6)].range); - n->newschema = (yyvsp[(6) - (6)].str); - n->missing_ok = false; - (yyval.node) = (PGNode *)n; - ;} - break; +/* + * Initialise a mbedtls_pk_context + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ) +{ + PK_VALIDATE( ctx != NULL ); - case 1157: -#line 53 "third_party/libpg_query/grammar/statements/alter_schema.y" - { - PGAlterObjectSchemaStmt *n = makeNode(PGAlterObjectSchemaStmt); - n->objectType = PG_OBJECT_VIEW; - n->relation = (yyvsp[(5) - (8)].range); - n->newschema = (yyvsp[(8) - (8)].str); - n->missing_ok = true; - (yyval.node) = (PGNode *)n; - ;} - break; + ctx->pk_info = NULL; + ctx->pk_ctx = NULL; +} - case 1158: -#line 6 "third_party/libpg_query/grammar/statements/checkpoint.y" - { - PGCheckPointStmt *n = makeNode(PGCheckPointStmt); - n->force = true; - (yyval.node) = (PGNode *)n; - ;} - break; +/* + * Free (the components of) a mbedtls_pk_context + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ) +{ + if( ctx == NULL ) + return; - case 1159: -#line 12 "third_party/libpg_query/grammar/statements/checkpoint.y" - { - PGCheckPointStmt *n = makeNode(PGCheckPointStmt); - n->force = false; - (yyval.node) = (PGNode *)n; - ;} - break; + if ( ctx->pk_info != NULL ) + ctx->pk_info->ctx_free_func( ctx->pk_ctx ); - case 1160: -#line 8 "third_party/libpg_query/grammar/statements/export.y" - { - PGExportStmt *n = makeNode(PGExportStmt); - n->filename = (yyvsp[(3) - (4)].str); - n->options = NIL; - if ((yyvsp[(4) - (4)].list)) { - n->options = list_concat(n->options, (yyvsp[(4) - (4)].list)); - } - (yyval.node) = (PGNode *)n; - ;} - break; + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); +} - case 1161: -#line 21 "third_party/libpg_query/grammar/statements/export.y" - { - PGImportStmt *n = makeNode(PGImportStmt); - n->filename = (yyvsp[(3) - (3)].str); - (yyval.node) = (PGNode *)n; - ;} - break; +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Initialize a restart context + */ +void mbedtls_pk_restart_init( mbedtls_pk_restart_ctx *ctx ) +{ + PK_VALIDATE( ctx != NULL ); + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} - case 1162: -#line 10 "third_party/libpg_query/grammar/statements/explain.y" +/* + * Free the components of a restart context + */ +void mbedtls_pk_restart_free( mbedtls_pk_restart_ctx *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + ctx->pk_info->rs_free_func == NULL ) { - PGExplainStmt *n = makeNode(PGExplainStmt); - n->query = (yyvsp[(2) - (2)].node); - n->options = NIL; - (yyval.node) = (PGNode *) n; - ;} - break; + return; + } - case 1163: -#line 17 "third_party/libpg_query/grammar/statements/explain.y" - { - PGExplainStmt *n = makeNode(PGExplainStmt); - n->query = (yyvsp[(4) - (4)].node); - n->options = list_make1(makeDefElem("analyze", NULL, (yylsp[(2) - (4)]))); - if ((yyvsp[(3) - (4)].boolean)) - n->options = lappend(n->options, - makeDefElem("verbose", NULL, (yylsp[(3) - (4)]))); - (yyval.node) = (PGNode *) n; - ;} - break; + ctx->pk_info->rs_free_func( ctx->rs_ctx ); - case 1164: -#line 27 "third_party/libpg_query/grammar/statements/explain.y" - { - PGExplainStmt *n = makeNode(PGExplainStmt); - n->query = (yyvsp[(3) - (3)].node); - n->options = list_make1(makeDefElem("verbose", NULL, (yylsp[(2) - (3)]))); - (yyval.node) = (PGNode *) n; - ;} - break; + ctx->pk_info = NULL; + ctx->rs_ctx = NULL; +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - case 1165: -#line 34 "third_party/libpg_query/grammar/statements/explain.y" - { - PGExplainStmt *n = makeNode(PGExplainStmt); - n->query = (yyvsp[(5) - (5)].node); - n->options = (yyvsp[(3) - (5)].list); - (yyval.node) = (PGNode *) n; - ;} - break; +/* + * Get pk_info structure from type + */ +const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) +{ + switch( pk_type ) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_PK_RSA: + return( &mbedtls_rsa_info ); +#endif +#if defined(MBEDTLS_ECP_C) + case MBEDTLS_PK_ECKEY: + return( &mbedtls_eckey_info ); + case MBEDTLS_PK_ECKEY_DH: + return( &mbedtls_eckeydh_info ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_PK_ECDSA: + return( &mbedtls_ecdsa_info ); +#endif + /* MBEDTLS_PK_RSA_ALT omitted on purpose */ + default: + return( NULL ); + } +} - case 1166: -#line 44 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.boolean) = true; ;} - break; +/* + * Initialise context + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) +{ + PK_VALIDATE_RET( ctx != NULL ); + if( info == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - case 1167: -#line 45 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.boolean) = false; ;} - break; + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); - case 1168: -#line 50 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.node) = (PGNode *) makeString((yyvsp[(1) - (1)].str)); ;} - break; + ctx->pk_info = info; - case 1169: -#line 51 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.node) = (PGNode *) (yyvsp[(1) - (1)].value); ;} - break; + return( 0 ); +} - case 1170: -#line 52 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.node) = NULL; ;} - break; +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * Initialise a PSA-wrapping context + */ +int mbedtls_pk_setup_opaque( mbedtls_pk_context *ctx, + const psa_key_id_t key ) +{ + const mbedtls_pk_info_t * const info = &mbedtls_pk_opaque_info; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t *pk_ctx; + psa_key_type_t type; - case 1176: -#line 65 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + if( ctx == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - case 1177: -#line 66 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} - break; + if( PSA_SUCCESS != psa_get_key_attributes( key, &attributes ) ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + type = psa_get_key_type( &attributes ); + psa_reset_key_attributes( &attributes ); - case 1178: -#line 67 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = pstrdup((yyvsp[(1) - (1)].keyword)); ;} - break; + /* Current implementation of can_do() relies on this. */ + if( ! PSA_KEY_TYPE_IS_ECC_KEY_PAIR( type ) ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ; - case 1179: -#line 72 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); - case 1180: -#line 73 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + ctx->pk_info = info; - case 1181: -#line 79 "third_party/libpg_query/grammar/statements/explain.y" - { - (yyval.list) = list_make1((yyvsp[(1) - (1)].defelt)); - ;} - break; + pk_ctx = (psa_key_id_t *) ctx->pk_ctx; + *pk_ctx = key; - case 1182: -#line 83 "third_party/libpg_query/grammar/statements/explain.y" - { - (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].defelt)); - ;} - break; + return( 0 ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ - case 1183: -#line 90 "third_party/libpg_query/grammar/statements/explain.y" - {;} - break; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Initialize an RSA-alt context + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ) +{ + mbedtls_rsa_alt_context *rsa_alt; + const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; - case 1184: -#line 91 "third_party/libpg_query/grammar/statements/explain.y" - {;} - break; + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - case 1185: -#line 96 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (char*) "true"; ;} - break; + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); - case 1186: -#line 97 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (char*) "false"; ;} - break; + ctx->pk_info = info; - case 1187: -#line 98 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (char*) "on"; ;} - break; + rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; - case 1188: -#line 104 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + rsa_alt->key = key; + rsa_alt->decrypt_func = decrypt_func; + rsa_alt->sign_func = sign_func; + rsa_alt->key_len_func = key_len_func; - case 1189: -#line 110 "third_party/libpg_query/grammar/statements/explain.y" - { - (yyval.defelt) = makeDefElem((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].node), (yylsp[(1) - (2)])); - ;} - break; + return( 0 ); +} +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ - case 1190: -#line 117 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; +/* + * Tell if a PK can do the operations of the given type + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) +{ + /* A context with null pk_info is not set up yet and can't do anything. + * For backward compatibility, also accept NULL instead of a context + * pointer. */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); - case 1191: -#line 118 "third_party/libpg_query/grammar/statements/explain.y" - { (yyval.str) = (char*) "analyze"; ;} - break; + return( ctx->pk_info->can_do( type ) ); +} - case 1192: -#line 11 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = (yyvsp[(2) - (2)].vsetstmt); - n->scope = VAR_SET_SCOPE_DEFAULT; - (yyval.node) = (PGNode *) n; - ;} - break; +/* + * Helper for mbedtls_pk_sign and mbedtls_pk_verify + */ +static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len ) +{ + const mbedtls_md_info_t *md_info; - case 1193: -#line 17 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = (yyvsp[(3) - (3)].vsetstmt); - n->scope = VAR_SET_SCOPE_LOCAL; - (yyval.node) = (PGNode *) n; - ;} - break; + if( *hash_len != 0 ) + return( 0 ); - case 1194: -#line 23 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = (yyvsp[(3) - (3)].vsetstmt); - n->scope = VAR_SET_SCOPE_SESSION; - (yyval.node) = (PGNode *) n; - ;} - break; + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( -1 ); - case 1195: -#line 29 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = (yyvsp[(3) - (3)].vsetstmt); - n->scope = VAR_SET_SCOPE_GLOBAL; - (yyval.node) = (PGNode *) n; - ;} - break; + *hash_len = mbedtls_md_get_size( md_info ); + return( 0 ); +} - case 1196: -#line 38 "third_party/libpg_query/grammar/statements/variable_set.y" - {(yyval.vsetstmt) = (yyvsp[(1) - (1)].vsetstmt);;} - break; +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) +/* + * Helper to set up a restart context if needed + */ +static int pk_restart_setup( mbedtls_pk_restart_ctx *ctx, + const mbedtls_pk_info_t *info ) +{ + /* Don't do anything if already set up or invalid */ + if( ctx == NULL || ctx->pk_info != NULL ) + return( 0 ); - case 1197: -#line 40 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = makeNode(PGVariableSetStmt); - n->kind = VAR_SET_CURRENT; - n->name = (yyvsp[(1) - (3)].str); - (yyval.vsetstmt) = n; - ;} - break; + /* Should never happen when we're called */ + if( info->rs_alloc_func == NULL || info->rs_free_func == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - case 1198: -#line 48 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = makeNode(PGVariableSetStmt); - n->kind = VAR_SET_VALUE; - n->name = (char*) "timezone"; - if ((yyvsp[(3) - (3)].node) != NULL) - n->args = list_make1((yyvsp[(3) - (3)].node)); - else - n->kind = VAR_SET_DEFAULT; - (yyval.vsetstmt) = n; - ;} - break; + if( ( ctx->rs_ctx = info->rs_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); - case 1199: -#line 59 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = makeNode(PGVariableSetStmt); - n->kind = VAR_SET_VALUE; - n->name = (char*) "search_path"; - n->args = list_make1(makeStringConst((yyvsp[(2) - (2)].str), (yylsp[(2) - (2)]))); - (yyval.vsetstmt) = n; - ;} - break; + ctx->pk_info = info; - case 1200: -#line 71 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = makeNode(PGVariableSetStmt); - n->kind = VAR_SET_VALUE; - n->name = (yyvsp[(1) - (3)].str); - n->args = (yyvsp[(3) - (3)].list); - (yyval.vsetstmt) = n; - ;} - break; + return( 0 ); +} +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - case 1201: -#line 79 "third_party/libpg_query/grammar/statements/variable_set.y" +/* + * Verify a signature (restartable) + */ +int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + mbedtls_pk_restart_ctx *rs_ctx ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->verify_rs_func != NULL ) { - PGVariableSetStmt *n = makeNode(PGVariableSetStmt); - n->kind = VAR_SET_VALUE; - n->name = (yyvsp[(1) - (3)].str); - n->args = (yyvsp[(3) - (3)].list); - (yyval.vsetstmt) = n; - ;} - break; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - case 1202: -#line 87 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = makeNode(PGVariableSetStmt); - n->kind = VAR_SET_DEFAULT; - n->name = (yyvsp[(1) - (3)].str); - (yyval.vsetstmt) = n; - ;} - break; + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); - case 1203: -#line 94 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGVariableSetStmt *n = makeNode(PGVariableSetStmt); - n->kind = VAR_SET_DEFAULT; - n->name = (yyvsp[(1) - (3)].str); - (yyval.vsetstmt) = n; - ;} - break; + ret = ctx->pk_info->verify_rs_func( ctx->pk_ctx, + md_alg, hash, hash_len, sig, sig_len, rs_ctx->rs_ctx ); - case 1204: -#line 104 "third_party/libpg_query/grammar/statements/variable_set.y" - { (yyval.node) = makeStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); ;} - break; + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); - case 1205: -#line 106 "third_party/libpg_query/grammar/statements/variable_set.y" - { (yyval.node) = makeAConst((yyvsp[(1) - (1)].value), (yylsp[(1) - (1)])); ;} - break; + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - case 1206: -#line 112 "third_party/libpg_query/grammar/statements/variable_set.y" - { - (yyval.node) = makeStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); - ;} - break; + if( ctx->pk_info->verify_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - case 1207: -#line 116 "third_party/libpg_query/grammar/statements/variable_set.y" - { - (yyval.node) = makeStringConst((yyvsp[(1) - (1)].str), (yylsp[(1) - (1)])); - ;} - break; + return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len ) ); +} - case 1208: -#line 120 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGTypeName *t = (yyvsp[(1) - (3)].typnam); - if ((yyvsp[(3) - (3)].list) != NIL) - { - PGAConst *n = (PGAConst *) linitial((yyvsp[(3) - (3)].list)); - if ((n->val.val.ival & ~(INTERVAL_MASK(HOUR) | INTERVAL_MASK(MINUTE))) != 0) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("time zone interval must be HOUR or HOUR TO MINUTE"), - parser_errposition((yylsp[(3) - (3)])))); - } - t->typmods = (yyvsp[(3) - (3)].list); - (yyval.node) = makeStringConstCast((yyvsp[(2) - (3)].str), (yylsp[(2) - (3)]), t); - ;} - break; +/* + * Verify a signature + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + return( mbedtls_pk_verify_restartable( ctx, md_alg, hash, hash_len, + sig, sig_len, NULL ) ); +} - case 1209: -#line 135 "third_party/libpg_query/grammar/statements/variable_set.y" - { - PGTypeName *t = (yyvsp[(1) - (5)].typnam); - t->typmods = list_make2(makeIntConst(INTERVAL_FULL_RANGE, -1), - makeIntConst((yyvsp[(3) - (5)].ival), (yylsp[(3) - (5)]))); - (yyval.node) = makeStringConstCast((yyvsp[(5) - (5)].str), (yylsp[(5) - (5)]), t); - ;} - break; +/* + * Verify a signature with options + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); - case 1210: -#line 141 "third_party/libpg_query/grammar/statements/variable_set.y" - { (yyval.node) = makeAConst((yyvsp[(1) - (1)].value), (yylsp[(1) - (1)])); ;} - break; + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - case 1211: -#line 142 "third_party/libpg_query/grammar/statements/variable_set.y" - { (yyval.node) = NULL; ;} - break; + if( ! mbedtls_pk_can_do( ctx, type ) ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - case 1212: -#line 143 "third_party/libpg_query/grammar/statements/variable_set.y" - { (yyval.node) = NULL; ;} - break; + if( type == MBEDTLS_PK_RSASSA_PSS ) + { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_pk_rsassa_pss_options *pss_opts; - case 1213: -#line 147 "third_party/libpg_query/grammar/statements/variable_set.y" - { (yyval.list) = list_make1((yyvsp[(1) - (1)].node)); ;} - break; +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ - case 1214: -#line 148 "third_party/libpg_query/grammar/statements/variable_set.y" - { (yyval.list) = lappend((yyvsp[(1) - (3)].list), (yyvsp[(3) - (3)].node)); ;} - break; + if( options == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - case 1215: -#line 8 "third_party/libpg_query/grammar/statements/load.y" - { - PGLoadStmt *n = makeNode(PGLoadStmt); - n->filename = (yyvsp[(2) - (2)].str); - n->load_type = PG_LOAD_TYPE_LOAD; - (yyval.node) = (PGNode *)n; - ;} - break; + pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; - case 1216: -#line 14 "third_party/libpg_query/grammar/statements/load.y" - { - PGLoadStmt *n = makeNode(PGLoadStmt); - n->filename = (yyvsp[(2) - (2)].str); - n->load_type = PG_LOAD_TYPE_INSTALL; - (yyval.node) = (PGNode *)n; - ;} - break; + if( sig_len < mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); - case 1217: -#line 20 "third_party/libpg_query/grammar/statements/load.y" - { - PGLoadStmt *n = makeNode(PGLoadStmt); - n->filename = (yyvsp[(3) - (3)].str); - n->load_type = PG_LOAD_TYPE_FORCE_INSTALL; - (yyval.node) = (PGNode *)n; - ;} - break; + ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ), + md_alg, (unsigned int) hash_len, hash, + pss_opts->mgf1_hash_id, + pss_opts->expected_salt_len, + sig ); + if( ret != 0 ) + return( ret ); - case 1218: -#line 28 "third_party/libpg_query/grammar/statements/load.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + if( sig_len > mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); - case 1219: -#line 29 "third_party/libpg_query/grammar/statements/load.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + return( 0 ); +#else + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ + } - case 1220: -#line 9 "third_party/libpg_query/grammar/statements/vacuum.y" - { - PGVacuumStmt *n = makeNode(PGVacuumStmt); - n->options = PG_VACOPT_VACUUM; - if ((yyvsp[(2) - (4)].boolean)) - n->options |= PG_VACOPT_FULL; - if ((yyvsp[(3) - (4)].boolean)) - n->options |= PG_VACOPT_FREEZE; - if ((yyvsp[(4) - (4)].boolean)) - n->options |= PG_VACOPT_VERBOSE; - n->relation = NULL; - n->va_cols = NIL; - (yyval.node) = (PGNode *)n; - ;} - break; + /* General case: no options */ + if( options != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - case 1221: -#line 23 "third_party/libpg_query/grammar/statements/vacuum.y" - { - PGVacuumStmt *n = makeNode(PGVacuumStmt); - n->options = PG_VACOPT_VACUUM; - if ((yyvsp[(2) - (5)].boolean)) - n->options |= PG_VACOPT_FULL; - if ((yyvsp[(3) - (5)].boolean)) - n->options |= PG_VACOPT_FREEZE; - if ((yyvsp[(4) - (5)].boolean)) - n->options |= PG_VACOPT_VERBOSE; - n->relation = (yyvsp[(5) - (5)].range); - n->va_cols = NIL; - (yyval.node) = (PGNode *)n; - ;} - break; + return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); +} - case 1222: -#line 37 "third_party/libpg_query/grammar/statements/vacuum.y" +/* + * Make a signature (restartable) + */ +int mbedtls_pk_sign_restartable( mbedtls_pk_context *ctx, + mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + mbedtls_pk_restart_ctx *rs_ctx ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && hash_len == 0 ) || + hash != NULL ); + PK_VALIDATE_RET( sig != NULL ); + + if( ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + /* optimization: use non-restartable version if restart disabled */ + if( rs_ctx != NULL && + mbedtls_ecp_restart_is_enabled() && + ctx->pk_info->sign_rs_func != NULL ) { - PGVacuumStmt *n = (PGVacuumStmt *) (yyvsp[(5) - (5)].node); - n->options |= PG_VACOPT_VACUUM; - if ((yyvsp[(2) - (5)].boolean)) - n->options |= PG_VACOPT_FULL; - if ((yyvsp[(3) - (5)].boolean)) - n->options |= PG_VACOPT_FREEZE; - if ((yyvsp[(4) - (5)].boolean)) - n->options |= PG_VACOPT_VERBOSE; - (yyval.node) = (PGNode *)n; - ;} - break; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - case 1223: -#line 49 "third_party/libpg_query/grammar/statements/vacuum.y" - { - PGVacuumStmt *n = makeNode(PGVacuumStmt); - n->options = PG_VACOPT_VACUUM | (yyvsp[(3) - (4)].ival); - n->relation = NULL; - n->va_cols = NIL; - (yyval.node) = (PGNode *) n; - ;} - break; + if( ( ret = pk_restart_setup( rs_ctx, ctx->pk_info ) ) != 0 ) + return( ret ); - case 1224: -#line 57 "third_party/libpg_query/grammar/statements/vacuum.y" - { - PGVacuumStmt *n = makeNode(PGVacuumStmt); - n->options = PG_VACOPT_VACUUM | (yyvsp[(3) - (6)].ival); - n->relation = (yyvsp[(5) - (6)].range); - n->va_cols = (yyvsp[(6) - (6)].list); - if (n->va_cols != NIL) /* implies analyze */ - n->options |= PG_VACOPT_ANALYZE; - (yyval.node) = (PGNode *) n; - ;} - break; + ret = ctx->pk_info->sign_rs_func( ctx->pk_ctx, md_alg, + hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng, rs_ctx->rs_ctx ); - case 1225: -#line 70 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.ival) = PG_VACOPT_ANALYZE; ;} - break; + if( ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) + mbedtls_pk_restart_free( rs_ctx ); - case 1226: -#line 71 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.ival) = PG_VACOPT_VERBOSE; ;} - break; + return( ret ); + } +#else /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ + (void) rs_ctx; +#endif /* MBEDTLS_ECDSA_C && MBEDTLS_ECP_RESTARTABLE */ - case 1227: -#line 72 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.ival) = PG_VACOPT_FREEZE; ;} - break; + if( ctx->pk_info->sign_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - case 1228: -#line 73 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.ival) = PG_VACOPT_FULL; ;} - break; + return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, + hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng ) ); +} - case 1229: -#line 75 "third_party/libpg_query/grammar/statements/vacuum.y" - { - if (strcmp((yyvsp[(1) - (1)].str), "disable_page_skipping") == 0) - (yyval.ival) = PG_VACOPT_DISABLE_PAGE_SKIPPING; - else - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("unrecognized VACUUM option \"%s\"", (yyvsp[(1) - (1)].str)), - parser_errposition((yylsp[(1) - (1)])))); - ;} - break; +/* + * Make a signature + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_pk_sign_restartable( ctx, md_alg, hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng, NULL ) ); +} - case 1230: -#line 87 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.boolean) = true; ;} - break; +/* + * Decrypt message + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); - case 1231: -#line 88 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.boolean) = false; ;} - break; + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - case 1232: -#line 93 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.ival) = (yyvsp[(1) - (1)].ival); ;} - break; + if( ctx->pk_info->decrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - case 1233: -#line 94 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.ival) = (yyvsp[(1) - (3)].ival) | (yyvsp[(3) - (3)].ival); ;} - break; + return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} - case 1234: -#line 98 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.boolean) = true; ;} - break; +/* + * Encrypt message + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( input != NULL || ilen == 0 ); + PK_VALIDATE_RET( output != NULL || osize == 0 ); + PK_VALIDATE_RET( olen != NULL ); - case 1235: -#line 99 "third_party/libpg_query/grammar/statements/vacuum.y" - { (yyval.boolean) = false; ;} - break; + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - case 1236: -#line 9 "third_party/libpg_query/grammar/statements/delete.y" - { - PGDeleteStmt *n = makeNode(PGDeleteStmt); - n->relation = (yyvsp[(4) - (7)].range); - n->usingClause = (yyvsp[(5) - (7)].list); - n->whereClause = (yyvsp[(6) - (7)].node); - n->returningList = (yyvsp[(7) - (7)].list); - n->withClause = (yyvsp[(1) - (7)].with); - (yyval.node) = (PGNode *)n; - ;} - break; + if( ctx->pk_info->encrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - case 1237: -#line 22 "third_party/libpg_query/grammar/statements/delete.y" - { - (yyval.range) = (yyvsp[(1) - (1)].range); - ;} - break; + return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} - case 1238: -#line 26 "third_party/libpg_query/grammar/statements/delete.y" - { - PGAlias *alias = makeNode(PGAlias); - alias->aliasname = (yyvsp[(2) - (2)].str); - (yyvsp[(1) - (2)].range)->alias = alias; - (yyval.range) = (yyvsp[(1) - (2)].range); - ;} - break; +/* + * Check public-private key pair + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, + const mbedtls_pk_context *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + PK_VALIDATE_RET( pub != NULL ); + PK_VALIDATE_RET( prv != NULL ); - case 1239: -#line 33 "third_party/libpg_query/grammar/statements/delete.y" + if( pub->pk_info == NULL || + prv->pk_info == NULL ) { - PGAlias *alias = makeNode(PGAlias); - alias->aliasname = (yyvsp[(3) - (3)].str); - (yyvsp[(1) - (3)].range)->alias = alias; - (yyval.range) = (yyvsp[(1) - (3)].range); - ;} - break; + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + } - case 1240: -#line 43 "third_party/libpg_query/grammar/statements/delete.y" - { (yyval.node) = (yyvsp[(2) - (2)].node); ;} - break; + if( f_rng == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - case 1241: -#line 44 "third_party/libpg_query/grammar/statements/delete.y" - { (yyval.node) = NULL; ;} - break; + if( prv->pk_info->check_pair_func == NULL ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); - case 1242: -#line 50 "third_party/libpg_query/grammar/statements/delete.y" - { (yyval.list) = (yyvsp[(2) - (2)].list); ;} - break; + if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) + { + if( pub->pk_info->type != MBEDTLS_PK_RSA ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + else + { + if( pub->pk_info != prv->pk_info ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } - case 1243: -#line 51 "third_party/libpg_query/grammar/statements/delete.y" - { (yyval.list) = NIL; ;} - break; + return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx, f_rng, p_rng ) ); +} - case 1244: -#line 10 "third_party/libpg_query/grammar/statements/analyze.y" - { - PGVacuumStmt *n = makeNode(PGVacuumStmt); - n->options = PG_VACOPT_ANALYZE; - if ((yyvsp[(2) - (2)].boolean)) - n->options |= PG_VACOPT_VERBOSE; - n->relation = NULL; - n->va_cols = NIL; - (yyval.node) = (PGNode *)n; - ;} - break; +/* + * Get key size in bits + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) +{ + /* For backward compatibility, accept NULL or a context that + * isn't set up yet, and return a fake value that should be safe. */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); - case 1245: -#line 20 "third_party/libpg_query/grammar/statements/analyze.y" - { - PGVacuumStmt *n = makeNode(PGVacuumStmt); - n->options = PG_VACOPT_ANALYZE; - if ((yyvsp[(2) - (4)].boolean)) - n->options |= PG_VACOPT_VERBOSE; - n->relation = (yyvsp[(3) - (4)].range); - n->va_cols = (yyvsp[(4) - (4)].list); - (yyval.node) = (PGNode *)n; - ;} - break; + return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); +} - case 1246: -#line 2 "third_party/libpg_query/grammar/statements/variable_reset.y" - { (yyval.node) = (PGNode *) (yyvsp[(2) - (2)].vsetstmt); ;} - break; +/* + * Export debug information + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) +{ + PK_VALIDATE_RET( ctx != NULL ); + if( ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - case 1247: -#line 8 "third_party/libpg_query/grammar/statements/variable_reset.y" - { - PGVariableSetStmt *n = makeNode(PGVariableSetStmt); - n->kind = VAR_RESET; - n->name = (yyvsp[(1) - (1)].str); - (yyval.vsetstmt) = n; - ;} - break; + if( ctx->pk_info->debug_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - case 1248: -#line 15 "third_party/libpg_query/grammar/statements/variable_reset.y" - { - PGVariableSetStmt *n = makeNode(PGVariableSetStmt); - n->kind = VAR_RESET_ALL; - (yyval.vsetstmt) = n; - ;} - break; + ctx->pk_info->debug_func( ctx->pk_ctx, items ); + return( 0 ); +} - case 1249: -#line 24 "third_party/libpg_query/grammar/statements/variable_reset.y" - { (yyval.vsetstmt) = (yyvsp[(1) - (1)].vsetstmt); ;} - break; +/* + * Access the PK type name + */ +const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( "invalid PK" ); - case 1250: -#line 26 "third_party/libpg_query/grammar/statements/variable_reset.y" - { - PGVariableSetStmt *n = makeNode(PGVariableSetStmt); - n->kind = VAR_RESET; - n->name = (char*) "timezone"; - (yyval.vsetstmt) = n; - ;} - break; + return( ctx->pk_info->name ); +} - case 1251: -#line 33 "third_party/libpg_query/grammar/statements/variable_reset.y" - { - PGVariableSetStmt *n = makeNode(PGVariableSetStmt); - n->kind = VAR_RESET; - n->name = (char*) "transaction_isolation"; - (yyval.vsetstmt) = n; - ;} - break; +/* + * Access the PK type + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_PK_NONE ); - case 1252: -#line 3 "third_party/libpg_query/grammar/statements/variable_show.y" - { - PGVariableShowSelectStmt *n = makeNode(PGVariableShowSelectStmt); - n->stmt = (yyvsp[(2) - (2)].node); - n->name = (char*) "select"; - n->is_summary = 0; - (yyval.node) = (PGNode *) n; - ;} - break; + return( ctx->pk_info->type ); +} - case 1253: -#line 10 "third_party/libpg_query/grammar/statements/variable_show.y" - { - PGVariableShowSelectStmt *n = makeNode(PGVariableShowSelectStmt); - n->stmt = (yyvsp[(2) - (2)].node); - n->name = (char*) "select"; - n->is_summary = 1; - (yyval.node) = (PGNode *) n; - ;} - break; +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * Load the key to a PSA key slot, + * then turn the PK context into a wrapper for that key slot. + * + * Currently only works for EC private keys. + */ +int mbedtls_pk_wrap_as_opaque( mbedtls_pk_context *pk, + psa_key_id_t *key, + psa_algorithm_t hash_alg ) +{ +#if !defined(MBEDTLS_ECP_C) + ((void) pk); + ((void) key); + ((void) hash_alg); + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); +#else + const mbedtls_ecp_keypair *ec; + unsigned char d[MBEDTLS_ECP_MAX_BYTES]; + size_t d_len; + psa_ecc_family_t curve_id; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_type_t key_type; + size_t bits; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - case 1254: -#line 18 "third_party/libpg_query/grammar/statements/variable_show.y" - { - PGVariableShowStmt *n = makeNode(PGVariableShowStmt); - n->name = (yyvsp[(2) - (2)].str); - n->is_summary = 1; - (yyval.node) = (PGNode *) n; - ;} - break; + /* export the private key material in the format PSA wants */ + if( mbedtls_pk_get_type( pk ) != MBEDTLS_PK_ECKEY ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); - case 1255: -#line 25 "third_party/libpg_query/grammar/statements/variable_show.y" - { - PGVariableShowStmt *n = makeNode(PGVariableShowStmt); - n->name = (yyvsp[(2) - (2)].str); - n->is_summary = 0; - (yyval.node) = (PGNode *) n; - ;} - break; + ec = mbedtls_pk_ec( *pk ); + d_len = ( ec->grp.nbits + 7 ) / 8; + if( ( ret = mbedtls_mpi_write_binary( &ec->d, d, d_len ) ) != 0 ) + return( ret ); - case 1256: -#line 32 "third_party/libpg_query/grammar/statements/variable_show.y" - { - PGVariableShowStmt *n = makeNode(PGVariableShowStmt); - n->name = (char*) "timezone"; - n->is_summary = 0; - (yyval.node) = (PGNode *) n; - ;} - break; + curve_id = mbedtls_ecc_group_to_psa( ec->grp.id, &bits ); + key_type = PSA_KEY_TYPE_ECC_KEY_PAIR( curve_id ); - case 1257: -#line 39 "third_party/libpg_query/grammar/statements/variable_show.y" - { - PGVariableShowStmt *n = makeNode(PGVariableShowStmt); - n->name = (char*) "transaction_isolation"; - n->is_summary = 0; - (yyval.node) = (PGNode *) n; - ;} - break; + /* prepare the key attributes */ + psa_set_key_type( &attributes, key_type ); + psa_set_key_bits( &attributes, bits ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_SIGN_HASH ); + psa_set_key_algorithm( &attributes, PSA_ALG_ECDSA(hash_alg) ); - case 1258: -#line 46 "third_party/libpg_query/grammar/statements/variable_show.y" - { - PGVariableShowStmt *n = makeNode(PGVariableShowStmt); - n->name = (char*) "__show_tables_expanded"; - n->is_summary = 0; - (yyval.node) = (PGNode *) n; - ;} - break; + /* import private key into PSA */ + if( PSA_SUCCESS != psa_import_key( &attributes, d, d_len, key ) ) + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); - case 1259: -#line 53 "third_party/libpg_query/grammar/statements/variable_show.y" - { - PGVariableShowStmt *n = makeNode(PGVariableShowStmt); - n->name = (char*) "__show_tables_expanded"; - n->is_summary = 0; - (yyval.node) = (PGNode *) n; - ;} - break; + /* make PK context wrap the key slot */ + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); - case 1262: -#line 63 "third_party/libpg_query/grammar/statements/variable_show.y" - { (yyval.str) = (yyvsp[(1) - (1)].str); ;} - break; + return( mbedtls_pk_setup_opaque( pk, *key ) ); +#endif /* MBEDTLS_ECP_C */ +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#endif /* MBEDTLS_PK_C */ - case 1263: -#line 65 "third_party/libpg_query/grammar/statements/variable_show.y" - { (yyval.str) = psprintf("%s.%s", (yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].str)); ;} - break; - case 1264: -#line 7 "third_party/libpg_query/grammar/statements/call.y" - { - PGCallStmt *n = makeNode(PGCallStmt); - n->func = (yyvsp[(2) - (2)].node); - (yyval.node) = (PGNode *) n; - ;} - break; +// LICENSE_CHANGE_END - case 1265: -#line 10 "third_party/libpg_query/grammar/statements/view.y" - { - PGViewStmt *n = makeNode(PGViewStmt); - n->view = (yyvsp[(4) - (9)].range); - n->view->relpersistence = (yyvsp[(2) - (9)].ival); - n->aliases = (yyvsp[(5) - (9)].list); - n->query = (yyvsp[(8) - (9)].node); - n->onconflict = PG_ERROR_ON_CONFLICT; - n->options = (yyvsp[(6) - (9)].list); - n->withCheckOption = (yyvsp[(9) - (9)].viewcheckoption); - (yyval.node) = (PGNode *) n; - ;} - break; - case 1266: -#line 23 "third_party/libpg_query/grammar/statements/view.y" - { - PGViewStmt *n = makeNode(PGViewStmt); - n->view = (yyvsp[(6) - (11)].range); - n->view->relpersistence = (yyvsp[(4) - (11)].ival); - n->aliases = (yyvsp[(7) - (11)].list); - n->query = (yyvsp[(10) - (11)].node); - n->onconflict = PG_REPLACE_ON_CONFLICT; - n->options = (yyvsp[(8) - (11)].list); - n->withCheckOption = (yyvsp[(11) - (11)].viewcheckoption); - (yyval.node) = (PGNode *) n; - ;} - break; +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - case 1267: -#line 36 "third_party/libpg_query/grammar/statements/view.y" - { - PGViewStmt *n = makeNode(PGViewStmt); - n->view = (yyvsp[(5) - (12)].range); - n->view->relpersistence = (yyvsp[(2) - (12)].ival); - n->aliases = (yyvsp[(7) - (12)].list); - n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, (yyvsp[(11) - (12)].node)); - n->onconflict = PG_ERROR_ON_CONFLICT; - n->options = (yyvsp[(9) - (12)].list); - n->withCheckOption = (yyvsp[(12) - (12)].viewcheckoption); - if (n->withCheckOption != PG_NO_CHECK_OPTION) - ereport(ERROR, - (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("WITH CHECK OPTION not supported on recursive views"), - parser_errposition((yylsp[(12) - (12)])))); - (yyval.node) = (PGNode *) n; - ;} - break; +/* + * Public Key abstraction layer: wrapper functions + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - case 1268: -#line 54 "third_party/libpg_query/grammar/statements/view.y" - { - PGViewStmt *n = makeNode(PGViewStmt); - n->view = (yyvsp[(7) - (14)].range); - n->view->relpersistence = (yyvsp[(4) - (14)].ival); - n->aliases = (yyvsp[(9) - (14)].list); - n->query = makeRecursiveViewSelect(n->view->relname, n->aliases, (yyvsp[(13) - (14)].node)); - n->onconflict = PG_REPLACE_ON_CONFLICT; - n->options = (yyvsp[(11) - (14)].list); - n->withCheckOption = (yyvsp[(14) - (14)].viewcheckoption); - if (n->withCheckOption != PG_NO_CHECK_OPTION) - ereport(ERROR, - (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("WITH CHECK OPTION not supported on recursive views"), - parser_errposition((yylsp[(14) - (14)])))); - (yyval.node) = (PGNode *) n; - ;} - break; - case 1269: -#line 74 "third_party/libpg_query/grammar/statements/view.y" - { (yyval.viewcheckoption) = CASCADED_CHECK_OPTION; ;} - break; - case 1270: -#line 75 "third_party/libpg_query/grammar/statements/view.y" - { (yyval.viewcheckoption) = CASCADED_CHECK_OPTION; ;} - break; +#if defined(MBEDTLS_PK_C) - case 1271: -#line 76 "third_party/libpg_query/grammar/statements/view.y" - { (yyval.viewcheckoption) = PG_LOCAL_CHECK_OPTION; ;} - break; - case 1272: -#line 77 "third_party/libpg_query/grammar/statements/view.y" - { (yyval.viewcheckoption) = PG_NO_CHECK_OPTION; ;} - break; - case 1273: -#line 12 "third_party/libpg_query/grammar/statements/create_as.y" - { - PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); - ctas->query = (yyvsp[(6) - (7)].node); - ctas->into = (yyvsp[(4) - (7)].into); - ctas->relkind = PG_OBJECT_TABLE; - ctas->is_select_into = false; - ctas->onconflict = PG_ERROR_ON_CONFLICT; - /* cram additional flags into the PGIntoClause */ - (yyvsp[(4) - (7)].into)->rel->relpersistence = (yyvsp[(2) - (7)].ival); - (yyvsp[(4) - (7)].into)->skipData = !((yyvsp[(7) - (7)].boolean)); - (yyval.node) = (PGNode *) ctas; - ;} - break; +/* Even if RSA not activated, for the sake of RSA-alt */ - case 1274: -#line 25 "third_party/libpg_query/grammar/statements/create_as.y" - { - PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); - ctas->query = (yyvsp[(9) - (10)].node); - ctas->into = (yyvsp[(7) - (10)].into); - ctas->relkind = PG_OBJECT_TABLE; - ctas->is_select_into = false; - ctas->onconflict = PG_IGNORE_ON_CONFLICT; - /* cram additional flags into the PGIntoClause */ - (yyvsp[(7) - (10)].into)->rel->relpersistence = (yyvsp[(2) - (10)].ival); - (yyvsp[(7) - (10)].into)->skipData = !((yyvsp[(10) - (10)].boolean)); - (yyval.node) = (PGNode *) ctas; - ;} - break; - case 1275: -#line 38 "third_party/libpg_query/grammar/statements/create_as.y" - { - PGCreateTableAsStmt *ctas = makeNode(PGCreateTableAsStmt); - ctas->query = (yyvsp[(8) - (9)].node); - ctas->into = (yyvsp[(6) - (9)].into); - ctas->relkind = PG_OBJECT_TABLE; - ctas->is_select_into = false; - ctas->onconflict = PG_REPLACE_ON_CONFLICT; - /* cram additional flags into the PGIntoClause */ - (yyvsp[(6) - (9)].into)->rel->relpersistence = (yyvsp[(4) - (9)].ival); - (yyvsp[(6) - (9)].into)->skipData = !((yyvsp[(9) - (9)].boolean)); - (yyval.node) = (PGNode *) ctas; - ;} - break; +#include - case 1276: -#line 54 "third_party/libpg_query/grammar/statements/create_as.y" - { (yyval.boolean) = true; ;} - break; +#if defined(MBEDTLS_ECP_C) - case 1277: -#line 55 "third_party/libpg_query/grammar/statements/create_as.y" - { (yyval.boolean) = false; ;} - break; +#endif - case 1278: -#line 56 "third_party/libpg_query/grammar/statements/create_as.y" - { (yyval.boolean) = true; ;} - break; +#if defined(MBEDTLS_ECDSA_C) + +#endif - case 1279: -#line 62 "third_party/libpg_query/grammar/statements/create_as.y" - { - (yyval.into) = makeNode(PGIntoClause); - (yyval.into)->rel = (yyvsp[(1) - (4)].range); - (yyval.into)->colNames = (yyvsp[(2) - (4)].list); - (yyval.into)->options = (yyvsp[(3) - (4)].list); - (yyval.into)->onCommit = (yyvsp[(4) - (4)].oncommit); - (yyval.into)->viewQuery = NULL; - (yyval.into)->skipData = false; /* might get changed later */ - ;} - break; +#if defined(MBEDTLS_USE_PSA_CRYPTO) -/* Line 1267 of yacc.c. */ -#line 25550 "third_party/libpg_query/grammar/grammar_out.cpp" - default: break; - } - YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); +// dummy file to make amalgamantion happy - *++yyvsp = yyval; - *++yylsp = yyloc; +// LICENSE_CHANGE_END - /* Now `shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ +#endif - yyn = yyr1[yyn]; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTOKENS]; +#endif - goto yynewstate; +#if defined(MBEDTLS_USE_PSA_CRYPTO) -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ -yyerrlab: - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; -#if ! YYERROR_VERBOSE - yyerror (&yylloc, yyscanner, YY_("syntax error")); -#else - { - YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); - if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) - { - YYSIZE_T yyalloc = 2 * yysize; - if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) - yyalloc = YYSTACK_ALLOC_MAXIMUM; - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); - yymsg = (char *) YYSTACK_ALLOC (yyalloc); - if (yymsg) - yymsg_alloc = yyalloc; - else - { - yymsg = yymsgbuf; - yymsg_alloc = sizeof yymsgbuf; - } - } - if (0 < yysize && yysize <= yymsg_alloc) - { - (void) yysyntax_error (yymsg, yystate, yychar); - yyerror (&yylloc, yyscanner, yymsg); - } - else - { - yyerror (&yylloc, yyscanner, YY_("syntax error")); - if (yysize != 0) - goto yyexhaustedlab; - } - } #endif - } - yyerror_range[0] = yylloc; +#if defined(MBEDTLS_PLATFORM_C) - if (yyerrstatus == 3) - { - /* If just tried and failed to reuse look-ahead token after an - error, discard it. */ +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif - if (yychar <= YYEOF) - { - /* Return failure if at end of input. */ - if (yychar == YYEOF) - YYABORT; - } - else - { - yydestruct ("Error: discarding", - yytoken, &yylval, &yylloc, yyscanner); - yychar = YYEMPTY; - } - } +#include +#include - /* Else will try to reuse look-ahead token after shifting the error - token. */ - goto yyerrlab1; +#if defined(MBEDTLS_RSA_C) +static int rsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA || + type == MBEDTLS_PK_RSASSA_PSS ); +} +static size_t rsa_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx; + return( 8 * mbedtls_rsa_get_len( rsa ) ); +} -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: +static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + size_t rsa_len = mbedtls_rsa_get_len( rsa ); + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( sig_len < rsa_len ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, md_alg, + (unsigned int) hash_len, + hash, sig ) ) != 0 ) + return( ret ); + + /* The buffer contains a valid signature followed by extra data. + * We have a special error code for that so that so that callers can + * use mbedtls_pk_verify() to check "Does the buffer start with a + * valid signature?" and not just "Does the buffer contain a valid + * signature?". */ + if( sig_len > rsa_len ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +} + +static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; - /* Pacify compilers like GCC when the user code never invokes - YYERROR and the label yyerrorlab therefore never appears in user - code. */ - if (/*CONSTCOND*/ 0) - goto yyerrorlab; +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ - yyerror_range[0] = yylsp[1-yylen]; - /* Do not reclaim the symbols of the rule which action triggered - this YYERROR. */ - YYPOPSTACK (yylen); - yylen = 0; - YY_STACK_PRINT (yyss, yyssp); - yystate = *yyssp; - goto yyerrlab1; + *sig_len = mbedtls_rsa_get_len( rsa ); + if( sig_size < *sig_len ) + return( MBEDTLS_ERR_PK_BUFFER_TOO_SMALL ); + return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, + md_alg, (unsigned int) hash_len, + hash, sig ) ); +} -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ +static int rsa_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; - for (;;) - { - yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } + if( ilen != mbedtls_rsa_get_len( rsa ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; + return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng, + olen, input, output, osize ) ); +} - yyerror_range[0] = *yylsp; - yydestruct ("Error: popping", - yystos[yystate], yyvsp, yylsp, yyscanner); - YYPOPSTACK (1); - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); - } +static int rsa_encrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + *olen = mbedtls_rsa_get_len( rsa ); - if (yyn == YYFINAL) - YYACCEPT; + if( *olen > osize ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); - *++yyvsp = yylval; + return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, + ilen, input, output ) ); +} - yyerror_range[1] = yylloc; - /* Using YYLLOC is tempting, but would change the location of - the look-ahead. YYLOC is available though. */ - YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2); - *++yylsp = yyloc; +static int rsa_check_pair_wrap( const void *pub, const void *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + (void) f_rng; + (void) p_rng; + return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub, + (const mbedtls_rsa_context *) prv ) ); +} - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); +static void *rsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); - yystate = yyn; - goto yynewstate; + if( ctx != NULL ) + mbedtls_rsa_init( (mbedtls_rsa_context *) ctx ); + return( ctx ); +} -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; +static void rsa_free_wrap( void *ctx ) +{ + mbedtls_rsa_free( (mbedtls_rsa_context *) ctx ); + mbedtls_free( ctx ); +} -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; +static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ +#if defined(MBEDTLS_RSA_ALT) + /* Not supported */ + (void) ctx; + (void) items; +#else + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.N"; + items->value = &( ((mbedtls_rsa_context *) ctx)->N ); -#ifndef yyoverflow -/*-------------------------------------------------. -| yyexhaustedlab -- memory exhaustion comes here. | -`-------------------------------------------------*/ -yyexhaustedlab: - yyerror (&yylloc, yyscanner, YY_("memory exhausted")); - yyresult = 2; - /* Fall through. */ + items++; + + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.E"; + items->value = &( ((mbedtls_rsa_context *) ctx)->E ); #endif +} -yyreturn: - if (yychar != YYEOF && yychar != YYEMPTY) - yydestruct ("Cleanup: discarding lookahead", - yytoken, &yylval, &yylloc, yyscanner); - /* Do not reclaim the symbols of the rule which action triggered - this YYABORT or YYACCEPT. */ - YYPOPSTACK (yylen); - YY_STACK_PRINT (yyss, yyssp); - while (yyssp != yyss) - { - yydestruct ("Cleanup: popping", - yystos[*yyssp], yyvsp, yylsp, yyscanner); - YYPOPSTACK (1); - } -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); +const mbedtls_pk_info_t mbedtls_rsa_info = { + MBEDTLS_PK_RSA, + "RSA", + rsa_get_bitlen, + rsa_can_do, + rsa_verify_wrap, + rsa_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, #endif -#if YYERROR_VERBOSE - if (yymsg != yymsgbuf) - YYSTACK_FREE (yymsg); + rsa_decrypt_wrap, + rsa_encrypt_wrap, + rsa_check_pair_wrap, + rsa_alloc_wrap, + rsa_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, #endif - /* Make sure YYID is used. */ - return YYID (yyresult); + rsa_debug, +}; +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Generic EC key + */ +static int eckey_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH || + type == MBEDTLS_PK_ECDSA ); +} + +static size_t eckey_get_bitlen( const void *ctx ) +{ + return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits ); } +#if defined(MBEDTLS_ECDSA_C) +/* Forward declarations */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); -#line 83 "third_party/libpg_query/grammar/statements/create_as.y" +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecdsa_context ecdsa; + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +#if defined(MBEDTLS_ECP_RESTARTABLE) +/* Forward declarations */ +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ); + +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ); -#line 1 "third_party/libpg_query/grammar/grammar.cpp" /* - * The signature of this function is required by bison. However, we - * ignore the passed yylloc and instead use the last token position - * available from the scanner. + * Restart context for ECDSA operations with ECKEY context + * + * We need to store an actual ECDSA context, as we need to pass the same to + * the underlying ecdsa function, so we can't create it on the fly every time. */ -static void -base_yyerror(YYLTYPE *yylloc, core_yyscan_t yyscanner, const char *msg) +typedef struct { - parser_yyerror(msg); + mbedtls_ecdsa_restart_ctx ecdsa_rs; + mbedtls_ecdsa_context ecdsa_ctx; +} eckey_restart_ctx; + +static void *eckey_rs_alloc( void ) +{ + eckey_restart_ctx *rs_ctx; + + void *ctx = mbedtls_calloc( 1, sizeof( eckey_restart_ctx ) ); + + if( ctx != NULL ) + { + rs_ctx = ctx; + mbedtls_ecdsa_restart_init( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_init( &rs_ctx->ecdsa_ctx ); + } + + return( ctx ); } -static PGRawStmt * -makeRawStmt(PGNode *stmt, int stmt_location) +static void eckey_rs_free( void *ctx ) { - PGRawStmt *rs = makeNode(PGRawStmt); + eckey_restart_ctx *rs_ctx; - rs->stmt = stmt; - rs->stmt_location = stmt_location; - rs->stmt_len = 0; /* might get changed later */ - return rs; + if( ctx == NULL) + return; + + rs_ctx = ctx; + mbedtls_ecdsa_restart_free( &rs_ctx->ecdsa_rs ); + mbedtls_ecdsa_free( &rs_ctx->ecdsa_ctx ); + + mbedtls_free( ctx ); } -/* Adjust a PGRawStmt to reflect that it doesn't run to the end of the string */ -static void -updateRawStmtEnd(PGRawStmt *rs, int end_location) +static int eckey_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) { - /* - * If we already set the length, don't change it. This is for situations - * like "select foo ;; select bar" where the same statement will be last - * in the string for more than one semicolon. - */ - if (rs->stmt_len > 0) - return; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + eckey_restart_ctx *rs = rs_ctx; - /* OK, update length of PGRawStmt */ - rs->stmt_len = end_location - rs->stmt_location; + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_verify_rs_wrap( &rs->ecdsa_ctx, + md_alg, hash, hash_len, + sig, sig_len, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); } -static PGNode * -makeColumnRef(char *colname, PGList *indirection, - int location, core_yyscan_t yyscanner) +static int eckey_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) { - /* - * Generate a PGColumnRef node, with an PGAIndirection node added if there - * is any subscripting in the specified indirection list. However, - * any field selection at the start of the indirection list must be - * transposed into the "fields" part of the PGColumnRef node. - */ - PGColumnRef *c = makeNode(PGColumnRef); - int nfields = 0; - PGListCell *l; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + eckey_restart_ctx *rs = rs_ctx; - c->location = location; - foreach(l, indirection) - { - if (IsA(lfirst(l), PGAIndices)) - { - PGAIndirection *i = makeNode(PGAIndirection); + /* Should never happen */ + if( rs == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); - if (nfields == 0) - { - /* easy case - all indirection goes to PGAIndirection */ - c->fields = list_make1(makeString(colname)); - i->indirection = check_indirection(indirection, yyscanner); - } - else - { - /* got to split the list in two */ - i->indirection = check_indirection(list_copy_tail(indirection, - nfields), - yyscanner); - indirection = list_truncate(indirection, nfields); - c->fields = lcons(makeString(colname), indirection); - } - i->arg = (PGNode *) c; - return (PGNode *) i; - } - else if (IsA(lfirst(l), PGAStar)) - { - /* We only allow '*' at the end of a PGColumnRef */ - if (lnext(l) != NULL) - parser_yyerror("improper use of \"*\""); - } - nfields++; - } - /* No subscripting, so all indirection gets added to field list */ - c->fields = lcons(makeString(colname), indirection); - return (PGNode *) c; + /* set up our own sub-context if needed (that is, on first run) */ + if( rs->ecdsa_ctx.grp.pbits == 0 ) + MBEDTLS_MPI_CHK( mbedtls_ecdsa_from_keypair( &rs->ecdsa_ctx, ctx ) ); + + MBEDTLS_MPI_CHK( ecdsa_sign_rs_wrap( &rs->ecdsa_ctx, md_alg, + hash, hash_len, sig, sig_size, sig_len, + f_rng, p_rng, &rs->ecdsa_rs ) ); + +cleanup: + return( ret ); } +#endif /* MBEDTLS_ECP_RESTARTABLE */ +#endif /* MBEDTLS_ECDSA_C */ -static PGNode * -makeTypeCast(PGNode *arg, PGTypeName *tpname, int trycast, int location) +static int eckey_check_pair( const void *pub, const void *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { - PGTypeCast *n = makeNode(PGTypeCast); - n->arg = arg; - n->typeName = tpname; - n->tryCast = trycast; - n->location = location; - return (PGNode *) n; + return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub, + (const mbedtls_ecp_keypair *) prv, + f_rng, p_rng ) ); } -static PGNode * -makeStringConst(char *str, int location) +static void *eckey_alloc_wrap( void ) { - PGAConst *n = makeNode(PGAConst); + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); - n->val.type = T_PGString; - n->val.val.str = str; - n->location = location; + if( ctx != NULL ) + mbedtls_ecp_keypair_init( ctx ); - return (PGNode *)n; + return( ctx ); } -static PGNode * -makeStringConstCast(char *str, int location, PGTypeName *tpname) +static void eckey_free_wrap( void *ctx ) { - PGNode *s = makeStringConst(str, location); + mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx ); + mbedtls_free( ctx ); +} - return makeTypeCast(s, tpname, 0, -1); +static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_ECP; + items->name = "eckey.Q"; + items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); +} + +const mbedtls_pk_info_t mbedtls_eckey_info = { + MBEDTLS_PK_ECKEY, + "EC", + eckey_get_bitlen, + eckey_can_do, +#if defined(MBEDTLS_ECDSA_C) + eckey_verify_wrap, + eckey_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + eckey_verify_rs_wrap, + eckey_sign_rs_wrap, +#endif +#else /* MBEDTLS_ECDSA_C */ + NULL, + NULL, +#endif /* MBEDTLS_ECDSA_C */ + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, + eckey_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + eckey_rs_alloc, + eckey_rs_free, +#endif + eckey_debug, +}; + +/* + * EC key restricted to ECDH + */ +static int eckeydh_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH ); +} + +const mbedtls_pk_info_t mbedtls_eckeydh_info = { + MBEDTLS_PK_ECKEY_DH, + "EC_DH", + eckey_get_bitlen, /* Same underlying key structure */ + eckeydh_can_do, + NULL, + NULL, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, /* Same underlying key structure */ + eckey_free_wrap, /* Same underlying key structure */ +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + eckey_debug, /* Same underlying key structure */ +}; +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_ECDSA_C) +static int ecdsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECDSA ); } -static PGNode * -makeIntervalNode(char *str, int location, PGList *typmods) { - PGIntervalConstant *n = makeNode(PGIntervalConstant); +#if defined(MBEDTLS_USE_PSA_CRYPTO) +/* + * An ASN.1 encoded signature is a sequence of two ASN.1 integers. Parse one of + * those integers and convert it to the fixed-length encoding expected by PSA. + */ +static int extract_ecdsa_sig_int( unsigned char **from, const unsigned char *end, + unsigned char *to, size_t to_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t unpadded_len, padding_len; - n->val_type = T_PGString; - n->sval = str; - n->location = location; - n->typmods = typmods; + if( ( ret = mbedtls_asn1_get_tag( from, end, &unpadded_len, + MBEDTLS_ASN1_INTEGER ) ) != 0 ) + { + return( ret ); + } - return (PGNode *)n; + while( unpadded_len > 0 && **from == 0x00 ) + { + ( *from )++; + unpadded_len--; + } + + if( unpadded_len > to_len || unpadded_len == 0 ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + padding_len = to_len - unpadded_len; + memset( to, 0x00, padding_len ); + memcpy( to + padding_len, *from, unpadded_len ); + ( *from ) += unpadded_len; + return( 0 ); } -static PGNode * -makeIntervalNode(int val, int location, PGList *typmods) { - PGIntervalConstant *n = makeNode(PGIntervalConstant); +/* + * Convert a signature from an ASN.1 sequence of two integers + * to a raw {r,s} buffer. Note: the provided sig buffer must be at least + * twice as big as int_size. + */ +static int extract_ecdsa_sig( unsigned char **p, const unsigned char *end, + unsigned char *sig, size_t int_size ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t tmp_size; - n->val_type = T_PGInteger; - n->ival = val; - n->location = location; - n->typmods = typmods; + if( ( ret = mbedtls_asn1_get_tag( p, end, &tmp_size, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); - return (PGNode *)n; + /* Extract r */ + if( ( ret = extract_ecdsa_sig_int( p, end, sig, int_size ) ) != 0 ) + return( ret ); + /* Extract s */ + if( ( ret = extract_ecdsa_sig_int( p, end, sig + int_size, int_size ) ) != 0 ) + return( ret ); + + return( 0 ); } -static PGNode * -makeIntervalNode(PGNode *arg, int location, PGList *typmods) { - PGIntervalConstant *n = makeNode(PGIntervalConstant); +static int ecdsa_verify_wrap( void *ctx_arg, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + mbedtls_ecdsa_context *ctx = ctx_arg; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + psa_key_id_t key_id = 0; + psa_status_t status; + mbedtls_pk_context key; + int key_len; + /* see ECP_PUB_DER_MAX_BYTES in pkwrite.c */ + unsigned char buf[30 + 2 * MBEDTLS_ECP_MAX_BYTES]; + unsigned char *p; + mbedtls_pk_info_t pk_info = mbedtls_eckey_info; + psa_algorithm_t psa_sig_md = PSA_ALG_ECDSA_ANY; + size_t curve_bits; + psa_ecc_family_t curve = + mbedtls_ecc_group_to_psa( ctx->grp.id, &curve_bits ); + const size_t signature_part_size = ( ctx->grp.nbits + 7 ) / 8; + ((void) md_alg); + + if( curve == 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + /* mbedtls_pk_write_pubkey() expects a full PK context; + * re-construct one to make it happy */ + key.pk_info = &pk_info; + key.pk_ctx = ctx; + p = buf + sizeof( buf ); + key_len = mbedtls_pk_write_pubkey( &p, buf, &key ); + if( key_len <= 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + psa_set_key_type( &attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY( curve ) ); + psa_set_key_usage_flags( &attributes, PSA_KEY_USAGE_VERIFY_HASH ); + psa_set_key_algorithm( &attributes, psa_sig_md ); + + status = psa_import_key( &attributes, + buf + sizeof( buf ) - key_len, key_len, + &key_id ); + if( status != PSA_SUCCESS ) + { + ret = mbedtls_psa_err_translate_pk( status ); + goto cleanup; + } - n->val_type = T_PGAExpr; - n->eval = arg; - n->location = location; - n->typmods = typmods; + /* We don't need the exported key anymore and can + * reuse its buffer for signature extraction. */ + if( 2 * signature_part_size > sizeof( buf ) ) + { + ret = MBEDTLS_ERR_PK_BAD_INPUT_DATA; + goto cleanup; + } - return (PGNode *)n; + p = (unsigned char*) sig; + if( ( ret = extract_ecdsa_sig( &p, sig + sig_len, buf, + signature_part_size ) ) != 0 ) + { + goto cleanup; + } + + if( psa_verify_hash( key_id, psa_sig_md, + hash, hash_len, + buf, 2 * signature_part_size ) + != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + if( p != sig + sig_len ) + { + ret = MBEDTLS_ERR_PK_SIG_LEN_MISMATCH; + goto cleanup; + } + ret = 0; + +cleanup: + psa_destroy_key( key_id ); + return( ret ); } +#else /* MBEDTLS_USE_PSA_CRYPTO */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void) md_alg); -static PGNode * -makeSampleSize(PGValue *sample_size, bool is_percentage) { - PGSampleSize *n = makeNode(PGSampleSize); + ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len ); - n->sample_size = *sample_size; - n->is_percentage = is_percentage; + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); - return (PGNode *)n; + return( ret ); } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ -static PGNode * -makeSampleOptions(PGNode *sample_size, char *method, int seed, int location) { - PGSampleOptions *n = makeNode(PGSampleOptions); +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, + sig, sig_size, sig_len, + f_rng, p_rng ) ); +} - n->sample_size = sample_size; - n->method = method; - n->seed = seed; - n->location = location; +#if defined(MBEDTLS_ECP_RESTARTABLE) +static int ecdsa_verify_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len, + void *rs_ctx ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + ((void) md_alg); - return (PGNode *)n; + ret = mbedtls_ecdsa_read_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); } -/* makeLimitPercent() - * Make limit percent node - */ -static PGNode * -makeLimitPercent(PGNode *limit_percent) { - PGLimitPercent *n = makeNode(PGLimitPercent); +static int ecdsa_sign_rs_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + void *rs_ctx ) +{ + return( mbedtls_ecdsa_write_signature_restartable( + (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_size, sig_len, f_rng, p_rng, + (mbedtls_ecdsa_restart_ctx *) rs_ctx ) ); - n->limit_percent = limit_percent; +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ - return (PGNode *)n; +static void *ecdsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx ); + + return( ctx ); } -static PGNode * -makeIntConst(int val, int location) +static void ecdsa_free_wrap( void *ctx ) { - PGAConst *n = makeNode(PGAConst); + mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx ); + mbedtls_free( ctx ); +} - n->val.type = T_PGInteger; - n->val.val.ival = val; - n->location = location; +#if defined(MBEDTLS_ECP_RESTARTABLE) +static void *ecdsa_rs_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_restart_ctx ) ); - return (PGNode *)n; + if( ctx != NULL ) + mbedtls_ecdsa_restart_init( ctx ); + + return( ctx ); } -static PGNode * -makeFloatConst(char *str, int location) +static void ecdsa_rs_free( void *ctx ) { - PGAConst *n = makeNode(PGAConst); + mbedtls_ecdsa_restart_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_ECP_RESTARTABLE */ + +const mbedtls_pk_info_t mbedtls_ecdsa_info = { + MBEDTLS_PK_ECDSA, + "ECDSA", + eckey_get_bitlen, /* Compatible key structures */ + ecdsa_can_do, + ecdsa_verify_wrap, + ecdsa_sign_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_verify_rs_wrap, + ecdsa_sign_rs_wrap, +#endif + NULL, + NULL, + eckey_check_pair, /* Compatible key structures */ + ecdsa_alloc_wrap, + ecdsa_free_wrap, +#if defined(MBEDTLS_ECP_RESTARTABLE) + ecdsa_rs_alloc, + ecdsa_rs_free, +#endif + eckey_debug, /* Compatible key structures */ +}; +#endif /* MBEDTLS_ECDSA_C */ - n->val.type = T_PGFloat; - n->val.val.str = str; - n->location = location; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Support for alternative RSA-private implementations + */ - return (PGNode *)n; +static int rsa_alt_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA ); } -static PGNode * -makeBitStringConst(char *str, int location) +static size_t rsa_alt_get_bitlen( const void *ctx ) { - PGAConst *n = makeNode(PGAConst); + const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; - n->val.type = T_PGBitString; - n->val.val.str = str; - n->location = location; + return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); +} - return (PGNode *)n; +static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = rsa_alt->key_len_func( rsa_alt->key ); + if( *sig_len > MBEDTLS_PK_SIGNATURE_MAX_SIZE ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + if( *sig_len > sig_size ) + return( MBEDTLS_ERR_PK_BUFFER_TOO_SMALL ); + + return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, + md_alg, (unsigned int) hash_len, hash, sig ) ); } -static PGNode * -makeNullAConst(int location) +static int rsa_alt_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - PGAConst *n = makeNode(PGAConst); + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; - n->val.type = T_PGNull; - n->location = location; + ((void) f_rng); + ((void) p_rng); - return (PGNode *)n; + if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_alt->decrypt_func( rsa_alt->key, + olen, input, output, osize ) ); } -static PGNode * -makeAConst(PGValue *v, int location) +#if defined(MBEDTLS_RSA_C) +static int rsa_alt_check_pair( const void *pub, const void *prv, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) { - PGNode *n; + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char hash[32]; + size_t sig_len = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - switch (v->type) - { - case T_PGFloat: - n = makeFloatConst(v->val.str, location); - break; + if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); - case T_PGInteger: - n = makeIntConst(v->val.ival, location); - break; + memset( hash, 0x2a, sizeof( hash ) ); - case T_PGString: - default: - n = makeStringConst(v->val.str, location); - break; - } + if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE, + hash, sizeof( hash ), + sig, sizeof( sig ), &sig_len, + f_rng, p_rng ) ) != 0 ) + { + return( ret ); + } - return n; + if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE, + hash, sizeof( hash ), sig, sig_len ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); } +#endif /* MBEDTLS_RSA_C */ -/* makeBoolAConst() - * Create an PGAConst string node and put it inside a boolean cast. - */ -static PGNode * -makeBoolAConst(bool state, int location) +static void *rsa_alt_alloc_wrap( void ) { - PGAConst *n = makeNode(PGAConst); + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) ); - n->val.type = T_PGString; - n->val.val.str = (state ? (char*) "t" : (char*) "f"); - n->location = location; + if( ctx != NULL ) + memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) ); - return makeTypeCast((PGNode *)n, SystemTypeName("bool"), 0, -1); + return( ctx ); } -/* check_qualified_name --- check the result of qualified_name production - * - * It's easiest to let the grammar production for qualified_name allow - * subscripts and '*', which we then must reject here. - */ -static void -check_qualified_name(PGList *names, core_yyscan_t yyscanner) +static void rsa_alt_free_wrap( void *ctx ) { - PGListCell *i; + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); + mbedtls_free( ctx ); +} + +const mbedtls_pk_info_t mbedtls_rsa_alt_info = { + MBEDTLS_PK_RSA_ALT, + "RSA-alt", + rsa_alt_get_bitlen, + rsa_alt_can_do, + NULL, + rsa_alt_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + rsa_alt_decrypt_wrap, + NULL, +#if defined(MBEDTLS_RSA_C) + rsa_alt_check_pair, +#else + NULL, +#endif + rsa_alt_alloc_wrap, + rsa_alt_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, + NULL, +#endif + NULL, +}; - foreach(i, names) - { - if (!IsA(lfirst(i), PGString)) - parser_yyerror("syntax error"); - } +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + +static void *pk_opaque_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( psa_key_id_t ) ); + + /* no _init() function to call, an calloc() already zeroized */ + + return( ctx ); } -/* check_func_name --- check the result of func_name production - * - * It's easiest to let the grammar production for func_name allow subscripts - * and '*', which we then must reject here. - */ -static PGList * -check_func_name(PGList *names, core_yyscan_t yyscanner) +static void pk_opaque_free_wrap( void *ctx ) { - PGListCell *i; + mbedtls_platform_zeroize( ctx, sizeof( psa_key_id_t ) ); + mbedtls_free( ctx ); +} - foreach(i, names) - { - if (!IsA(lfirst(i), PGString)) - parser_yyerror("syntax error"); - } - return names; +static size_t pk_opaque_get_bitlen( const void *ctx ) +{ + const psa_key_id_t *key = (const psa_key_id_t *) ctx; + size_t bits; + psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT; + + if( PSA_SUCCESS != psa_get_key_attributes( *key, &attributes ) ) + return( 0 ); + + bits = psa_get_key_bits( &attributes ); + psa_reset_key_attributes( &attributes ); + return( bits ); } -/* check_indirection --- check the result of indirection production +static int pk_opaque_can_do( mbedtls_pk_type_t type ) +{ + /* For now opaque PSA keys can only wrap ECC keypairs, + * as checked by setup_psa(). + * Also, ECKEY_DH does not really make sense with the current API. */ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECDSA ); +} + +#if defined(MBEDTLS_ECDSA_C) + +/* + * Simultaneously convert and move raw MPI from the beginning of a buffer + * to an ASN.1 MPI at the end of the buffer. + * See also mbedtls_asn1_write_mpi(). * - * We only allow '*' at the end of the list, but it's hard to enforce that - * in the grammar, so do it here. + * p: pointer to the end of the output buffer + * start: start of the output buffer, and also of the mpi to write at the end + * n_len: length of the mpi to read from start */ -static PGList * -check_indirection(PGList *indirection, core_yyscan_t yyscanner) +static int asn1_write_mpibuf( unsigned char **p, unsigned char *start, + size_t n_len ) { - PGListCell *l; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; - foreach(l, indirection) - { - if (IsA(lfirst(l), PGAStar)) - { - if (lnext(l) != NULL) - parser_yyerror("improper use of \"*\""); - } - } - return indirection; + if( (size_t)( *p - start ) < n_len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = n_len; + *p -= len; + memmove( *p, start, len ); + + /* ASN.1 DER encoding requires minimal length, so skip leading 0s. + * Neither r nor s should be 0, but as a failsafe measure, still detect + * that rather than overflowing the buffer in case of a PSA error. */ + while( len > 0 && **p == 0x00 ) + { + ++(*p); + --len; + } + + /* this is only reached if the signature was invalid */ + if( len == 0 ) + return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED ); + + /* if the msb is 1, ASN.1 requires that we prepend a 0. + * Neither r nor s can be 0, so we can assume len > 0 at all times. */ + if( **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_INTEGER ) ); + + return( (int) len ); } -/* makeParamRef - * Creates a new PGParamRef node +/* Transcode signature from PSA format to ASN.1 sequence. + * See ecdsa_signature_to_asn1 in ecdsa.c, but with byte buffers instead of + * MPIs, and in-place. + * + * [in/out] sig: the signature pre- and post-transcoding + * [in/out] sig_len: signature length pre- and post-transcoding + * [int] buf_len: the available size the in/out buffer */ -static PGNode* makeParamRef(int number, int location) +static int pk_ecdsa_sig_asn1_from_psa( unsigned char *sig, size_t *sig_len, + size_t buf_len ) { - PGParamRef *p = makeNode(PGParamRef); - p->number = number; - p->location = location; - return (PGNode *) p; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len = 0; + const size_t rs_len = *sig_len / 2; + unsigned char *p = sig + buf_len; + + MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig + rs_len, rs_len ) ); + MBEDTLS_ASN1_CHK_ADD( len, asn1_write_mpibuf( &p, sig, rs_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, sig, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, sig, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + memmove( sig, p, len ); + *sig_len = len; + + return( 0 ); } +#endif /* MBEDTLS_ECDSA_C */ -/* insertSelectOptions() - * Insert ORDER BY, etc into an already-constructed SelectStmt. +static int pk_opaque_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t sig_size, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ +#if !defined(MBEDTLS_ECDSA_C) + ((void) ctx); + ((void) md_alg); + ((void) hash); + ((void) hash_len); + ((void) sig); + ((void) sig_size); + ((void) sig_len); + ((void) f_rng); + ((void) p_rng); + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); +#else /* !MBEDTLS_ECDSA_C */ + const psa_key_id_t *key = (const psa_key_id_t *) ctx; + psa_algorithm_t alg = PSA_ALG_ECDSA( mbedtls_psa_translate_md( md_alg ) ); + psa_status_t status; + + /* PSA has its own RNG */ + (void) f_rng; + (void) p_rng; + + /* make the signature */ + status = psa_sign_hash( *key, alg, hash, hash_len, + sig, sig_size, sig_len ); + if( status != PSA_SUCCESS ) + return( mbedtls_psa_err_translate_pk( status ) ); + + /* transcode it to ASN.1 sequence */ + return( pk_ecdsa_sig_asn1_from_psa( sig, sig_len, sig_size ) ); +#endif /* !MBEDTLS_ECDSA_C */ +} + +const mbedtls_pk_info_t mbedtls_pk_opaque_info = { + MBEDTLS_PK_OPAQUE, + "Opaque", + pk_opaque_get_bitlen, + pk_opaque_can_do, + NULL, /* verify - will be done later */ + pk_opaque_sign_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, /* restartable verify - not relevant */ + NULL, /* restartable sign - not relevant */ +#endif + NULL, /* decrypt - will be done later */ + NULL, /* encrypt - will be done later */ + NULL, /* check_pair - could be done later or left NULL */ + pk_opaque_alloc_wrap, + pk_opaque_free_wrap, +#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_ECP_RESTARTABLE) + NULL, /* restart alloc - not relevant */ + NULL, /* restart free - not relevant */ +#endif + NULL, /* debug - could be done later, or even left NULL */ +}; + +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +#endif /* MBEDTLS_PK_C */ + + +// LICENSE_CHANGE_END + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/* + * Public Key layer for parsing key files and structures * - * This routine is just to avoid duplicating code in PGSelectStmt productions. + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ -static void -insertSelectOptions(PGSelectStmt *stmt, - PGList *sortClause, PGList *lockingClause, - PGNode *limitOffset, PGNode *limitCount, - PGWithClause *withClause, - core_yyscan_t yyscanner) + + + +#if defined(MBEDTLS_PK_PARSE_C) + + + + + + + +#include + +#if defined(MBEDTLS_RSA_C) + +#endif +#if defined(MBEDTLS_ECP_C) + +#endif +#if defined(MBEDTLS_ECDSA_C) + +#endif +#if defined(MBEDTLS_PEM_PARSE_C) + +#endif +#if defined(MBEDTLS_PKCS5_C) + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +// dummy file to make amalgamantion happy + +// LICENSE_CHANGE_END + +#endif +#if defined(MBEDTLS_PKCS12_C) + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +// dummy file to make amalgamantion happy + +// LICENSE_CHANGE_END + +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Parameter validation macros based on platform_util.h */ +#define PK_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_PK_BAD_INPUT_DATA ) +#define PK_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) { - Assert(IsA(stmt, PGSelectStmt)); + FILE *f; + long size; - /* - * Tests here are to reject constructs like - * (SELECT foo ORDER BY bar) ORDER BY baz - */ - if (sortClause) - { - if (stmt->sortClause) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("multiple ORDER BY clauses not allowed"), - parser_errposition(exprLocation((PGNode *) sortClause)))); - stmt->sortClause = sortClause; - } - /* We can handle multiple locking clauses, though */ - stmt->lockingClause = list_concat(stmt->lockingClause, lockingClause); - if (limitOffset) - { - if (stmt->limitOffset) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("multiple OFFSET clauses not allowed"), - parser_errposition(exprLocation(limitOffset)))); - stmt->limitOffset = limitOffset; - } - if (limitCount) - { - if (stmt->limitCount) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("multiple LIMIT clauses not allowed"), - parser_errposition(exprLocation(limitCount)))); - stmt->limitCount = limitCount; - } - if (withClause) - { - if (stmt->withClause) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("multiple WITH clauses not allowed"), - parser_errposition(exprLocation((PGNode *) withClause)))); - stmt->withClause = withClause; - } + PK_VALIDATE_RET( path != NULL ); + PK_VALIDATE_RET( buf != NULL ); + PK_VALIDATE_RET( n != NULL ); + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + + mbedtls_platform_zeroize( *buf, *n ); + mbedtls_free( *buf ); + + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); } -static PGNode * -makeSetOp(PGSetOperation op, bool all, PGNode *larg, PGNode *rarg) +/* + * Load and parse a private key + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *pwd, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - PGSelectStmt *n = makeNode(PGSelectStmt); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; - n->op = op; - n->all = all; - n->larg = (PGSelectStmt *) larg; - n->rarg = (PGSelectStmt *) rarg; - return (PGNode *) n; + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + if( pwd == NULL ) + ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0, f_rng, p_rng ); + else + ret = mbedtls_pk_parse_key( ctx, buf, n, + (const unsigned char *) pwd, strlen( pwd ), f_rng, p_rng ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); } -/* SystemFuncName() - * Build a properly-qualified reference to a built-in function. +/* + * Load and parse a public key */ -PGList * -SystemFuncName(const char *name) +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) { - return list_make2(makeString(DEFAULT_SCHEMA), makeString(name)); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t n; + unsigned char *buf; + + PK_VALIDATE_RET( ctx != NULL ); + PK_VALIDATE_RET( path != NULL ); + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_pk_parse_public_key( ctx, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); } +#endif /* MBEDTLS_FS_IO */ -/* SystemTypeName() - * Build a properly-qualified reference to a built-in type. +#if defined(MBEDTLS_ECP_C) +/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf * - * typmod is defaulted, but may be changed afterwards by caller. - * Likewise for the location. + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + * } */ -PGTypeName * -SystemTypeName(const char *name) +static int pk_get_ecparams( unsigned char **p, const unsigned char *end, + mbedtls_asn1_buf *params ) { - return makeTypeNameFromNameList(list_make2(makeString(DEFAULT_SCHEMA), - makeString(name))); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + + if ( end - *p < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); + + /* Tag may be either OID or SEQUENCE */ + params->tag = **p; + if( params->tag != MBEDTLS_ASN1_OID +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) +#endif + ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ); + } + + if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); } -/* doNegate() - * Handle negation of a numeric constant. +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. + * WARNING: the resulting group should only be used with + * pk_group_id_from_specified(), since its base point may not be set correctly + * if it was encoded compressed. * - * Formerly, we did this here because the optimizer couldn't cope with - * indexquals that looked like "var = -4" --- it wants "var = const" - * and a unary minus operator applied to a constant didn't qualify. - * As of Postgres 7.0, that problem doesn't exist anymore because there - * is a constant-subexpression simplifier in the optimizer. However, - * there's still a good reason for doing this here, which is that we can - * postpone committing to a particular internal representation for simple - * negative constants. It's better to leave "-123.456" in string form - * until we know what the desired type is. + * SpecifiedECDomain ::= SEQUENCE { + * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), + * fieldID FieldID {{FieldTypes}}, + * curve Curve, + * base ECPoint, + * order INTEGER, + * cofactor INTEGER OPTIONAL, + * hash HashAlgorithm OPTIONAL, + * ... + * } + * + * We only support prime-field as field type, and ignore hash and cofactor. */ -static PGNode * -doNegate(PGNode *n, int location) +static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) { - if (IsA(n, PGAConst)) - { - PGAConst *con = (PGAConst *)n; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = params->p; + const unsigned char * const end = params->p + params->len; + const unsigned char *end_field, *end_curve; + size_t len; + int ver; - /* report the constant's location as that of the '-' sign */ - con->location = location; + /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ + if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); - if (con->val.type == T_PGInteger) - { - con->val.val.ival = -con->val.val.ival; - return n; - } - if (con->val.type == T_PGFloat) - { - doNegateFloat(&con->val); - return n; - } - } + if( ver < 1 || ver > 3 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); - return (PGNode *) makeSimpleAExpr(PG_AEXPR_OP, "-", NULL, n, location); -} + /* + * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field + * fieldType FIELD-ID.&id({IOSet}), + * parameters FIELD-ID.&Type({IOSet}{@fieldType}) + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_field = p + len; + + /* + * FIELD-ID ::= TYPE-IDENTIFIER + * FieldTypes FIELD-ID ::= { + * { Prime-p IDENTIFIED BY prime-field } | + * { Characteristic-two IDENTIFIED BY characteristic-two-field } + * } + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); -static void -doNegateFloat(PGValue *v) -{ - char *oldval = v->val.str; + if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || + memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) + { + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + } - Assert(IsA(v, PGFloat)); - if (*oldval == '+') - oldval++; - if (*oldval == '-') - v->val.str = oldval+1; /* just strip the '-' */ - else - v->val.str = psprintf("-%s", oldval); + p += len; + + /* Prime-p ::= INTEGER -- Field of size p. */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + if( p != end_field ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* + * Curve ::= SEQUENCE { + * a FieldElement, + * b FieldElement, + * seed BIT STRING OPTIONAL + * -- Shall be present if used in SpecifiedECDomain + * -- with version equal to ecdpVer2 or ecdpVer3 + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_curve = p + len; + + /* + * FieldElement ::= OCTET STRING + * containing an integer in the case of a prime field + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + p += len; + + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + p += len; + + /* Ignore seed BIT STRING OPTIONAL */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) + p += len; + + if( p != end_curve ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + /* + * ECPoint ::= OCTET STRING + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G, + ( const unsigned char *) p, len ) ) != 0 ) + { + /* + * If we can't read the point because it's compressed, cheat by + * reading only the X coordinate and the parity bit of Y. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || + ( p[0] != 0x02 && p[0] != 0x03 ) || + len != mbedtls_mpi_size( &grp->P ) + 1 || + mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || + mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || + mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + + p += len; + + /* + * order INTEGER + */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + /* + * Allow optional elements by purposefully not enforcing p == end here. + */ + + return( 0 ); } -static PGNode * -makeAndExpr(PGNode *lexpr, PGNode *rexpr, int location) +/* + * Find the group id associated with an (almost filled) group as generated by + * pk_group_from_specified(), or return an error if unknown. + */ +static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) { - PGNode *lexp = lexpr; + int ret = 0; + mbedtls_ecp_group ref; + const mbedtls_ecp_group_id *id; - /* Look through AEXPR_PAREN nodes so they don't affect flattening */ - while (IsA(lexp, PGAExpr) && - ((PGAExpr *) lexp)->kind == AEXPR_PAREN) - lexp = ((PGAExpr *) lexp)->lexpr; - /* Flatten "a AND b AND c ..." to a single PGBoolExpr on sight */ - if (IsA(lexp, PGBoolExpr)) - { - PGBoolExpr *blexpr = (PGBoolExpr *) lexp; + mbedtls_ecp_group_init( &ref ); - if (blexpr->boolop == PG_AND_EXPR) - { - blexpr->args = lappend(blexpr->args, rexpr); - return (PGNode *) blexpr; - } - } - return (PGNode *) makeBoolExpr(PG_AND_EXPR, list_make2(lexpr, rexpr), location); + for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) + { + /* Load the group associated to that id */ + mbedtls_ecp_group_free( &ref ); + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); + + /* Compare to the group we were given, starting with easy tests */ + if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && + mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && + /* For Y we may only know the parity bit, so compare only that */ + mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) + { + break; + } + + } + +cleanup: + mbedtls_ecp_group_free( &ref ); + + *grp_id = *id; + + if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + + return( ret ); } -static PGNode * -makeOrExpr(PGNode *lexpr, PGNode *rexpr, int location) +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID + */ +static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *grp_id ) { - PGNode *lexp = lexpr; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group grp; - /* Look through AEXPR_PAREN nodes so they don't affect flattening */ - while (IsA(lexp, PGAExpr) && - ((PGAExpr *) lexp)->kind == AEXPR_PAREN) - lexp = ((PGAExpr *) lexp)->lexpr; - /* Flatten "a OR b OR c ..." to a single PGBoolExpr on sight */ - if (IsA(lexp, PGBoolExpr)) - { - PGBoolExpr *blexpr = (PGBoolExpr *) lexp; + mbedtls_ecp_group_init( &grp ); - if (blexpr->boolop == PG_OR_EXPR) - { - blexpr->args = lappend(blexpr->args, rexpr); - return (PGNode *) blexpr; - } - } - return (PGNode *) makeBoolExpr(PG_OR_EXPR, list_make2(lexpr, rexpr), location); + if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) + goto cleanup; + + ret = pk_group_id_from_group( &grp, grp_id ); + +cleanup: + mbedtls_ecp_group_free( &grp ); + + return( ret ); } +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ -static PGNode * -makeNotExpr(PGNode *expr, int location) +/* + * Use EC parameters to initialise an EC group + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + */ +static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) { - return (PGNode *) makeBoolExpr(PG_NOT_EXPR, list_make1(expr), location); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_ecp_group_id grp_id; + + if( params->tag == MBEDTLS_ASN1_OID ) + { + if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); + } + else + { +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) + return( ret ); +#else + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +#endif + } + + /* + * grp may already be initilialized; if so, make sure IDs match + */ + if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) + return( ret ); + + return( 0 ); } -static PGNode * -makeSQLValueFunction(PGSQLValueFunctionOp op, int32_t typmod, int location) +/* + * EC public key is an EC point + * + * The caller is responsible for clearing the structure upon failure if + * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE + * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. + */ +static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, + mbedtls_ecp_keypair *key ) { - PGSQLValueFunction *svf = makeNode(PGSQLValueFunction); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; - svf->op = op; - /* svf->type will be filled during parse analysis */ - svf->typmod = typmod; - svf->location = location; - return (PGNode *) svf; + if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, + (const unsigned char *) *p, end - *p ) ) == 0 ) + { + ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); + } + + /* + * We know mbedtls_ecp_point_read_binary consumed all bytes or failed + */ + *p = (unsigned char *) end; + + return( ret ); } +#endif /* MBEDTLS_ECP_C */ -/* Separate PGConstraint nodes from COLLATE clauses in a */ -static void -SplitColQualList(PGList *qualList, - PGList **constraintList, PGCollateClause **collClause, - core_yyscan_t yyscanner) +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_get_rsapubkey( unsigned char **p, + const unsigned char *end, + mbedtls_rsa_context *rsa ) { - PGListCell *cell; - PGListCell *prev; - PGListCell *next; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; - *collClause = NULL; - prev = NULL; - for (cell = list_head(qualList); cell; cell = next) - { - PGNode *n = (PGNode *) lfirst(cell); + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); - next = lnext(cell); - if (IsA(n, PGConstraint)) - { - /* keep it in list */ - prev = cell; - continue; - } - if (IsA(n, PGCollateClause)) - { - PGCollateClause *c = (PGCollateClause *) n; + if( *p + len != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); - if (*collClause) - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - errmsg("multiple COLLATE clauses not allowed"), - parser_errposition(c->location))); - *collClause = c; - } - else - elog(ERROR, "unexpected node type %d", (int) n->type); - /* remove non-Constraint nodes from qualList */ - qualList = list_delete_cell(qualList, cell, prev); - } - *constraintList = qualList; + /* Import N */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + /* Import E */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, *p, len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + if( mbedtls_rsa_complete( rsa ) != 0 || + mbedtls_rsa_check_pubkey( rsa ) != 0 ) + { + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + } + + if( *p != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +/* Get a PK algorithm identifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +static int pk_get_pk_alg( unsigned char **p, + const unsigned char *end, + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_asn1_buf alg_oid; + + memset( params, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_ALG, ret ) ); + + if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + /* + * No parameters with RSA (only for EC) + */ + if( *pk_alg == MBEDTLS_PK_RSA && + ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || + params->len != 0 ) ) + { + return( MBEDTLS_ERR_PK_INVALID_ALG ); + } + + return( 0 ); } /* - * Process result of ConstraintAttributeSpec, and set appropriate bool flags - * in the output command node. Pass NULL for any flags the particular - * command doesn't support. + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } */ -static void -processCASbits(int cas_bits, int location, const char *constrType, - bool *deferrable, bool *initdeferred, bool *not_valid, - bool *no_inherit, core_yyscan_t yyscanner) +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ) { - /* defaults */ - if (deferrable) - *deferrable = false; - if (initdeferred) - *initdeferred = false; - if (not_valid) - *not_valid = false; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t len; + mbedtls_asn1_buf alg_params; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; - if (cas_bits & (CAS_DEFERRABLE | CAS_INITIALLY_DEFERRED)) - { - if (deferrable) - *deferrable = true; - else - ereport(ERROR, - (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ - errmsg("%s constraints cannot be marked DEFERRABLE", - constrType), - parser_errposition(location))); - } + PK_VALIDATE_RET( p != NULL ); + PK_VALIDATE_RET( *p != NULL ); + PK_VALIDATE_RET( end != NULL ); + PK_VALIDATE_RET( pk != NULL ); - if (cas_bits & CAS_INITIALLY_DEFERRED) - { - if (initdeferred) - *initdeferred = true; - else - ereport(ERROR, - (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ - errmsg("%s constraints cannot be marked DEFERRABLE", - constrType), - parser_errposition(location))); - } + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } - if (cas_bits & CAS_NOT_VALID) - { - if (not_valid) - *not_valid = true; - else - ereport(ERROR, - (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ - errmsg("%s constraints cannot be marked NOT VALID", - constrType), - parser_errposition(location))); - } + end = *p + len; - if (cas_bits & CAS_NO_INHERIT) - { - if (no_inherit) - *no_inherit = true; - else - ereport(ERROR, - (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ - errmsg("%s constraints cannot be marked NO INHERIT", - constrType), - parser_errposition(location))); - } + if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, ret ) ); + + if( *p + len != end ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) + { + ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); + if( ret == 0 ) + ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); + } else +#endif /* MBEDTLS_ECP_C */ + ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + + if( ret == 0 && *p != end ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ret != 0 ) + mbedtls_pk_free( pk ); + + return( ret ); } -/*---------- - * Recursive view transformation - * - * Convert - * - * CREATE RECURSIVE VIEW relname (aliases) AS query - * - * to +#if defined(MBEDTLS_RSA_C) +/* + * Wrapper around mbedtls_asn1_get_mpi() that rejects zero. * - * CREATE VIEW relname (aliases) AS - * WITH RECURSIVE relname (aliases) AS (query) - * SELECT aliases FROM relname + * The value zero is: + * - never a valid value for an RSA parameter + * - interpreted as "omitted, please reconstruct" by mbedtls_rsa_complete(). * - * Actually, just the WITH ... part, which is then inserted into the original - * view as the query. - * ---------- + * Since values can't be omitted in PKCS#1, passing a zero value to + * rsa_complete() would be incorrect, so reject zero values early. */ -static PGNode * -makeRecursiveViewSelect(char *relname, PGList *aliases, PGNode *query) +static int asn1_get_nonzero_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) { - PGSelectStmt *s = makeNode(PGSelectStmt); - PGWithClause *w = makeNode(PGWithClause); - PGCommonTableExpr *cte = makeNode(PGCommonTableExpr); - PGList *tl = NIL; - PGListCell *lc; + int ret; - /* create common table expression */ - cte->ctename = relname; - cte->aliascolnames = aliases; - cte->ctequery = query; - cte->location = -1; + ret = mbedtls_asn1_get_mpi( p, end, X ); + if( ret != 0 ) + return( ret ); - /* create WITH clause and attach CTE */ - w->recursive = true; - w->ctes = list_make1(cte); - w->location = -1; + if( mbedtls_mpi_cmp_int( X, 0 ) == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); - /* create target list for the new SELECT from the alias list of the - * recursive view specification */ - foreach (lc, aliases) - { - PGResTarget *rt = makeNode(PGResTarget); + return( 0 ); +} - rt->name = NULL; - rt->indirection = NIL; - rt->val = makeColumnRef(strVal(lfirst(lc)), NIL, -1, 0); - rt->location = -1; +/* + * Parse a PKCS#1 encoded private RSA key + */ +static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, + const unsigned char *key, + size_t keylen ) +{ + int ret, version; + size_t len; + unsigned char *p, *end; - tl = lappend(tl, rt); - } + mbedtls_mpi T; + mbedtls_mpi_init( &T ); - /* create new SELECT combining WITH clause, target list, and fake FROM - * clause */ - s->withClause = w; - s->targetList = tl; - s->fromClause = list_make1(makeRangeVar(NULL, relname, -1)); + p = (unsigned char *) key; + end = p + keylen; - return (PGNode *) s; + /* + * This function parses the RSAPrivateKey (PKCS#1) + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + if( version != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + } + + /* Import N */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, &T, NULL, NULL, + NULL, NULL ) ) != 0 ) + goto cleanup; + + /* Import E */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + NULL, &T ) ) != 0 ) + goto cleanup; + + /* Import D */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, NULL, + &T, NULL ) ) != 0 ) + goto cleanup; + + /* Import P */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, &T, NULL, + NULL, NULL ) ) != 0 ) + goto cleanup; + + /* Import Q */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_rsa_import( rsa, NULL, NULL, &T, + NULL, NULL ) ) != 0 ) + goto cleanup; + +#if !defined(MBEDTLS_RSA_NO_CRT) && !defined(MBEDTLS_RSA_ALT) + /* + * The RSA CRT parameters DP, DQ and QP are nominally redundant, in + * that they can be easily recomputed from D, P and Q. However by + * parsing them from the PKCS1 structure it is possible to avoid + * recalculating them which both reduces the overhead of loading + * RSA private keys into memory and also avoids side channels which + * can arise when computing those values, since all of D, P, and Q + * are secret. See https://eprint.iacr.org/2020/055 for a + * description of one such attack. + */ + + /* Import DP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DP, &T ) ) != 0 ) + goto cleanup; + + /* Import DQ */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->DQ, &T ) ) != 0 ) + goto cleanup; + + /* Import QP */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_mpi_copy( &rsa->QP, &T ) ) != 0 ) + goto cleanup; + +#else + /* Verify existance of the CRT params */ + if( ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 || + ( ret = asn1_get_nonzero_mpi( &p, end, &T ) ) != 0 ) + goto cleanup; +#endif + + /* rsa_complete() doesn't complete anything with the default + * implementation but is still called: + * - for the benefit of alternative implementation that may want to + * pre-compute stuff beyond what's provided (eg Montgomery factors) + * - as is also sanity-checks the key + * + * Furthermore, we also check the public part for consistency with + * mbedtls_pk_parse_pubkey(), as it includes size minima for example. + */ + if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 || + ( ret = mbedtls_rsa_check_pubkey( rsa ) ) != 0 ) + { + goto cleanup; + } + + if( p != end ) + { + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + +cleanup: + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + { + /* Wrap error code if it's coming from a lower level */ + if( ( ret & 0xff80 ) == 0 ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ); + else + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + + mbedtls_rsa_free( rsa ); + } + + return( ret ); } +#endif /* MBEDTLS_RSA_C */ -/* parser_init() - * Initialize to parse one query string +#if defined(MBEDTLS_ECP_C) +/* + * Parse a SEC1 encoded private EC key */ -void -parser_init(base_yy_extra_type *yyext) +static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, + const unsigned char *key, size_t keylen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { - yyext->parsetree = NIL; /* in case grammar forgets to set it */ -} + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int version, pubkey_done; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + unsigned char *end2; -#undef yyparse -#undef yylex -#undef yyerror -#undef yylval -#undef yychar -#undef yydebug -#undef yynerrs -#undef yylloc + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } -} // namespace duckdb_libpgquery + end = p + len; + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + if( version != 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); -// LICENSE_CHANGE_END + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } -// LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 -// See the end of this file for a list + p += len; -/*-------------------------------------------------------------------- - * Symbols referenced in this file: - * - raw_parser - * - base_yylex - * - raw_parser - *-------------------------------------------------------------------- - */ + pubkey_done = 0; + if( p != end ) + { + /* + * Is 'parameters' present? + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || + ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + } -/*------------------------------------------------------------------------- - * - * parser.c - * Main entry point/driver for PostgreSQL grammar - * - * Note that the grammar is not allowed to perform any table access - * (since we need to be able to do basic parsing even while inside an - * aborted transaction). Therefore, the data structures returned by - * the grammar are "raw" parsetrees that still need to be analyzed by - * analyze.c and related files. + if( p != end ) + { + /* + * Is 'publickey' present? If not, or if we can't read it (eg because it + * is compressed), create it from the private key. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + + if( p + len != end2 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ) ); + + if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) + pubkey_done = 1; + else + { + /* + * The only acceptable failure mode of pk_get_ecpubkey() above + * is if the point format is not recognized. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + } + + if( ! pubkey_done && + ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, + f_rng, p_rng ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + + if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_ECP_C */ + +/* + * Parse an unencrypted PKCS#8 encoded private key * + * Notes: * - * Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup - * Portions Copyright (c) 1994, Regents of the University of California + * - This function does not own the key buffer. It is the + * responsibility of the caller to take care of zeroizing + * and freeing it after use. * - * IDENTIFICATION - * src/backend/parser/parser.c + * - The function is responsible for freeing the provided + * PK context on failure. * - *------------------------------------------------------------------------- */ +static int pk_parse_key_pkcs8_unencrypted_der( + mbedtls_pk_context *pk, + const unsigned char* key, size_t keylen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, version; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + +#if !defined(MBEDTLS_ECP_C) + (void) f_rng; + (void) p_rng; +#endif + /* + * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } + end = p + len; + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + if( version != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_VERSION, ret ) ); + if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) + { + return( ret ); + } -// LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 -// See the end of this file for a list + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + if( len < 1 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ); -namespace duckdb_libpgquery { -#define PG_KEYWORD(a,b,c) {a,b,c}, + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); -const PGScanKeyword ScanKeywords[] = { -PG_KEYWORD("abort", ABORT_P, UNRESERVED_KEYWORD) -PG_KEYWORD("absolute", ABSOLUTE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("access", ACCESS, UNRESERVED_KEYWORD) -PG_KEYWORD("action", ACTION, UNRESERVED_KEYWORD) -PG_KEYWORD("add", ADD_P, UNRESERVED_KEYWORD) -PG_KEYWORD("admin", ADMIN, UNRESERVED_KEYWORD) -PG_KEYWORD("after", AFTER, UNRESERVED_KEYWORD) -PG_KEYWORD("aggregate", AGGREGATE, UNRESERVED_KEYWORD) -PG_KEYWORD("all", ALL, RESERVED_KEYWORD) -PG_KEYWORD("also", ALSO, UNRESERVED_KEYWORD) -PG_KEYWORD("alter", ALTER, UNRESERVED_KEYWORD) -PG_KEYWORD("always", ALWAYS, UNRESERVED_KEYWORD) -PG_KEYWORD("analyse", ANALYSE, RESERVED_KEYWORD) -PG_KEYWORD("analyze", ANALYZE, RESERVED_KEYWORD) -PG_KEYWORD("and", AND, RESERVED_KEYWORD) -PG_KEYWORD("any", ANY, RESERVED_KEYWORD) -PG_KEYWORD("array", ARRAY, RESERVED_KEYWORD) -PG_KEYWORD("as", AS, RESERVED_KEYWORD) -PG_KEYWORD("asc", ASC_P, RESERVED_KEYWORD) -PG_KEYWORD("assertion", ASSERTION, UNRESERVED_KEYWORD) -PG_KEYWORD("assignment", ASSIGNMENT, UNRESERVED_KEYWORD) -PG_KEYWORD("asymmetric", ASYMMETRIC, RESERVED_KEYWORD) -PG_KEYWORD("at", AT, UNRESERVED_KEYWORD) -PG_KEYWORD("attach", ATTACH, UNRESERVED_KEYWORD) -PG_KEYWORD("attribute", ATTRIBUTE, UNRESERVED_KEYWORD) -PG_KEYWORD("authorization", AUTHORIZATION, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("backward", BACKWARD, UNRESERVED_KEYWORD) -PG_KEYWORD("before", BEFORE, UNRESERVED_KEYWORD) -PG_KEYWORD("begin", BEGIN_P, UNRESERVED_KEYWORD) -PG_KEYWORD("between", BETWEEN, COL_NAME_KEYWORD) -PG_KEYWORD("bigint", BIGINT, COL_NAME_KEYWORD) -PG_KEYWORD("binary", BINARY, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("bit", BIT, COL_NAME_KEYWORD) -PG_KEYWORD("boolean", BOOLEAN_P, COL_NAME_KEYWORD) -PG_KEYWORD("both", BOTH, RESERVED_KEYWORD) -PG_KEYWORD("by", BY, UNRESERVED_KEYWORD) -PG_KEYWORD("cache", CACHE, UNRESERVED_KEYWORD) -PG_KEYWORD("call", CALL_P, UNRESERVED_KEYWORD) -PG_KEYWORD("called", CALLED, UNRESERVED_KEYWORD) -PG_KEYWORD("cascade", CASCADE, UNRESERVED_KEYWORD) -PG_KEYWORD("cascaded", CASCADED, UNRESERVED_KEYWORD) -PG_KEYWORD("case", CASE, RESERVED_KEYWORD) -PG_KEYWORD("cast", CAST, RESERVED_KEYWORD) -PG_KEYWORD("catalog", CATALOG_P, UNRESERVED_KEYWORD) -PG_KEYWORD("chain", CHAIN, UNRESERVED_KEYWORD) -PG_KEYWORD("char", CHAR_P, COL_NAME_KEYWORD) -PG_KEYWORD("character", CHARACTER, COL_NAME_KEYWORD) -PG_KEYWORD("characteristics", CHARACTERISTICS, UNRESERVED_KEYWORD) -PG_KEYWORD("check", CHECK_P, RESERVED_KEYWORD) -PG_KEYWORD("checkpoint", CHECKPOINT, UNRESERVED_KEYWORD) -PG_KEYWORD("class", CLASS, UNRESERVED_KEYWORD) -PG_KEYWORD("close", CLOSE, UNRESERVED_KEYWORD) -PG_KEYWORD("cluster", CLUSTER, UNRESERVED_KEYWORD) -PG_KEYWORD("coalesce", COALESCE, COL_NAME_KEYWORD) -PG_KEYWORD("collate", COLLATE, RESERVED_KEYWORD) -PG_KEYWORD("collation", COLLATION, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("column", COLUMN, RESERVED_KEYWORD) -PG_KEYWORD("columns", COLUMNS, UNRESERVED_KEYWORD) -PG_KEYWORD("comment", COMMENT, UNRESERVED_KEYWORD) -PG_KEYWORD("comments", COMMENTS, UNRESERVED_KEYWORD) -PG_KEYWORD("commit", COMMIT, UNRESERVED_KEYWORD) -PG_KEYWORD("committed", COMMITTED, UNRESERVED_KEYWORD) -PG_KEYWORD("compression", COMPRESSION, UNRESERVED_KEYWORD) -PG_KEYWORD("concurrently", CONCURRENTLY, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("configuration", CONFIGURATION, UNRESERVED_KEYWORD) -PG_KEYWORD("conflict", CONFLICT, UNRESERVED_KEYWORD) -PG_KEYWORD("connection", CONNECTION, UNRESERVED_KEYWORD) -PG_KEYWORD("constraint", CONSTRAINT, RESERVED_KEYWORD) -PG_KEYWORD("constraints", CONSTRAINTS, UNRESERVED_KEYWORD) -PG_KEYWORD("content", CONTENT_P, UNRESERVED_KEYWORD) -PG_KEYWORD("continue", CONTINUE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("conversion", CONVERSION_P, UNRESERVED_KEYWORD) -PG_KEYWORD("copy", COPY, UNRESERVED_KEYWORD) -PG_KEYWORD("cost", COST, UNRESERVED_KEYWORD) -PG_KEYWORD("create", CREATE_P, RESERVED_KEYWORD) -PG_KEYWORD("cross", CROSS, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("csv", CSV, UNRESERVED_KEYWORD) -PG_KEYWORD("cube", CUBE, UNRESERVED_KEYWORD) -PG_KEYWORD("current", CURRENT_P, UNRESERVED_KEYWORD) -PG_KEYWORD("current_catalog", CURRENT_CATALOG, RESERVED_KEYWORD) -PG_KEYWORD("current_date", CURRENT_DATE, RESERVED_KEYWORD) -PG_KEYWORD("current_role", CURRENT_ROLE, RESERVED_KEYWORD) -PG_KEYWORD("current_schema", CURRENT_SCHEMA, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("current_time", CURRENT_TIME, RESERVED_KEYWORD) -PG_KEYWORD("current_timestamp", CURRENT_TIMESTAMP, RESERVED_KEYWORD) -PG_KEYWORD("current_user", CURRENT_USER, RESERVED_KEYWORD) -PG_KEYWORD("cursor", CURSOR, UNRESERVED_KEYWORD) -PG_KEYWORD("cycle", CYCLE, UNRESERVED_KEYWORD) -PG_KEYWORD("data", DATA_P, UNRESERVED_KEYWORD) -PG_KEYWORD("database", DATABASE, UNRESERVED_KEYWORD) -PG_KEYWORD("day", DAY_P, UNRESERVED_KEYWORD) -PG_KEYWORD("days", DAYS_P, UNRESERVED_KEYWORD) -PG_KEYWORD("deallocate", DEALLOCATE, UNRESERVED_KEYWORD) -PG_KEYWORD("dec", DEC, COL_NAME_KEYWORD) -PG_KEYWORD("decimal", DECIMAL_P, COL_NAME_KEYWORD) -PG_KEYWORD("declare", DECLARE, UNRESERVED_KEYWORD) -PG_KEYWORD("default", DEFAULT, RESERVED_KEYWORD) -PG_KEYWORD("defaults", DEFAULTS, UNRESERVED_KEYWORD) -PG_KEYWORD("deferrable", DEFERRABLE, RESERVED_KEYWORD) -PG_KEYWORD("deferred", DEFERRED, UNRESERVED_KEYWORD) -PG_KEYWORD("definer", DEFINER, UNRESERVED_KEYWORD) -PG_KEYWORD("delete", DELETE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("delimiter", DELIMITER, UNRESERVED_KEYWORD) -PG_KEYWORD("delimiters", DELIMITERS, UNRESERVED_KEYWORD) -PG_KEYWORD("depends", DEPENDS, UNRESERVED_KEYWORD) -PG_KEYWORD("desc", DESC_P, RESERVED_KEYWORD) -PG_KEYWORD("describe", DESCRIBE, UNRESERVED_KEYWORD) -PG_KEYWORD("detach", DETACH, UNRESERVED_KEYWORD) -PG_KEYWORD("dictionary", DICTIONARY, UNRESERVED_KEYWORD) -PG_KEYWORD("disable", DISABLE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("discard", DISCARD, UNRESERVED_KEYWORD) -PG_KEYWORD("distinct", DISTINCT, RESERVED_KEYWORD) -PG_KEYWORD("do", DO, RESERVED_KEYWORD) -PG_KEYWORD("document", DOCUMENT_P, UNRESERVED_KEYWORD) -PG_KEYWORD("domain", DOMAIN_P, UNRESERVED_KEYWORD) -PG_KEYWORD("double", DOUBLE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("drop", DROP, UNRESERVED_KEYWORD) -PG_KEYWORD("each", EACH, UNRESERVED_KEYWORD) -PG_KEYWORD("else", ELSE, RESERVED_KEYWORD) -PG_KEYWORD("enable", ENABLE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("encoding", ENCODING, UNRESERVED_KEYWORD) -PG_KEYWORD("encrypted", ENCRYPTED, UNRESERVED_KEYWORD) -PG_KEYWORD("end", END_P, RESERVED_KEYWORD) -PG_KEYWORD("enum", ENUM_P, UNRESERVED_KEYWORD) -PG_KEYWORD("escape", ESCAPE, UNRESERVED_KEYWORD) -PG_KEYWORD("event", EVENT, UNRESERVED_KEYWORD) -PG_KEYWORD("except", EXCEPT, RESERVED_KEYWORD) -PG_KEYWORD("exclude", EXCLUDE, UNRESERVED_KEYWORD) -PG_KEYWORD("excluding", EXCLUDING, UNRESERVED_KEYWORD) -PG_KEYWORD("exclusive", EXCLUSIVE, UNRESERVED_KEYWORD) -PG_KEYWORD("execute", EXECUTE, UNRESERVED_KEYWORD) -PG_KEYWORD("exists", EXISTS, COL_NAME_KEYWORD) -PG_KEYWORD("explain", EXPLAIN, UNRESERVED_KEYWORD) -PG_KEYWORD("export", EXPORT_P, UNRESERVED_KEYWORD) -PG_KEYWORD("export_state", EXPORT_STATE, UNRESERVED_KEYWORD) -PG_KEYWORD("extension", EXTENSION, UNRESERVED_KEYWORD) -PG_KEYWORD("external", EXTERNAL, UNRESERVED_KEYWORD) -PG_KEYWORD("extract", EXTRACT, COL_NAME_KEYWORD) -PG_KEYWORD("false", FALSE_P, RESERVED_KEYWORD) -PG_KEYWORD("family", FAMILY, UNRESERVED_KEYWORD) -PG_KEYWORD("fetch", FETCH, RESERVED_KEYWORD) -PG_KEYWORD("filter", FILTER, UNRESERVED_KEYWORD) -PG_KEYWORD("first", FIRST_P, UNRESERVED_KEYWORD) -PG_KEYWORD("float", FLOAT_P, COL_NAME_KEYWORD) -PG_KEYWORD("following", FOLLOWING, UNRESERVED_KEYWORD) -PG_KEYWORD("for", FOR, RESERVED_KEYWORD) -PG_KEYWORD("force", FORCE, UNRESERVED_KEYWORD) -PG_KEYWORD("foreign", FOREIGN, RESERVED_KEYWORD) -PG_KEYWORD("forward", FORWARD, UNRESERVED_KEYWORD) -PG_KEYWORD("freeze", FREEZE, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("from", FROM, RESERVED_KEYWORD) -PG_KEYWORD("full", FULL, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("function", FUNCTION, UNRESERVED_KEYWORD) -PG_KEYWORD("functions", FUNCTIONS, UNRESERVED_KEYWORD) -PG_KEYWORD("generated", GENERATED, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("glob", GLOB, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("global", GLOBAL, UNRESERVED_KEYWORD) -PG_KEYWORD("grant", GRANT, RESERVED_KEYWORD) -PG_KEYWORD("granted", GRANTED, UNRESERVED_KEYWORD) -PG_KEYWORD("group", GROUP_P, RESERVED_KEYWORD) -PG_KEYWORD("grouping", GROUPING, COL_NAME_KEYWORD) -PG_KEYWORD("grouping_id", GROUPING_ID, COL_NAME_KEYWORD) -PG_KEYWORD("handler", HANDLER, UNRESERVED_KEYWORD) -PG_KEYWORD("having", HAVING, RESERVED_KEYWORD) -PG_KEYWORD("header", HEADER_P, UNRESERVED_KEYWORD) -PG_KEYWORD("hold", HOLD, UNRESERVED_KEYWORD) -PG_KEYWORD("hour", HOUR_P, UNRESERVED_KEYWORD) -PG_KEYWORD("hours", HOURS_P, UNRESERVED_KEYWORD) -PG_KEYWORD("identity", IDENTITY_P, UNRESERVED_KEYWORD) -PG_KEYWORD("if", IF_P, UNRESERVED_KEYWORD) -PG_KEYWORD("ignore", IGNORE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("ilike", ILIKE, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("immediate", IMMEDIATE, UNRESERVED_KEYWORD) -PG_KEYWORD("immutable", IMMUTABLE, UNRESERVED_KEYWORD) -PG_KEYWORD("implicit", IMPLICIT_P, UNRESERVED_KEYWORD) -PG_KEYWORD("import", IMPORT_P, UNRESERVED_KEYWORD) -PG_KEYWORD("in", IN_P, RESERVED_KEYWORD) -PG_KEYWORD("including", INCLUDING, UNRESERVED_KEYWORD) -PG_KEYWORD("increment", INCREMENT, UNRESERVED_KEYWORD) -PG_KEYWORD("index", INDEX, UNRESERVED_KEYWORD) -PG_KEYWORD("indexes", INDEXES, UNRESERVED_KEYWORD) -PG_KEYWORD("inherit", INHERIT, UNRESERVED_KEYWORD) -PG_KEYWORD("inherits", INHERITS, UNRESERVED_KEYWORD) -PG_KEYWORD("initially", INITIALLY, RESERVED_KEYWORD) -PG_KEYWORD("inline", INLINE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("inner", INNER_P, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("inout", INOUT, COL_NAME_KEYWORD) -PG_KEYWORD("input", INPUT_P, UNRESERVED_KEYWORD) -PG_KEYWORD("insensitive", INSENSITIVE, UNRESERVED_KEYWORD) -PG_KEYWORD("insert", INSERT, UNRESERVED_KEYWORD) -PG_KEYWORD("install", INSTALL, UNRESERVED_KEYWORD) -PG_KEYWORD("instead", INSTEAD, UNRESERVED_KEYWORD) -PG_KEYWORD("int", INT_P, COL_NAME_KEYWORD) -PG_KEYWORD("integer", INTEGER, COL_NAME_KEYWORD) -PG_KEYWORD("intersect", INTERSECT, RESERVED_KEYWORD) -PG_KEYWORD("interval", INTERVAL, COL_NAME_KEYWORD) -PG_KEYWORD("into", INTO, RESERVED_KEYWORD) -PG_KEYWORD("invoker", INVOKER, UNRESERVED_KEYWORD) -PG_KEYWORD("is", IS, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("isnull", ISNULL, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("isolation", ISOLATION, UNRESERVED_KEYWORD) -PG_KEYWORD("join", JOIN, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("json", JSON, UNRESERVED_KEYWORD) -PG_KEYWORD("key", KEY, UNRESERVED_KEYWORD) -PG_KEYWORD("label", LABEL, UNRESERVED_KEYWORD) -PG_KEYWORD("language", LANGUAGE, UNRESERVED_KEYWORD) -PG_KEYWORD("large", LARGE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("last", LAST_P, UNRESERVED_KEYWORD) -PG_KEYWORD("lateral", LATERAL_P, RESERVED_KEYWORD) -PG_KEYWORD("leading", LEADING, RESERVED_KEYWORD) -PG_KEYWORD("leakproof", LEAKPROOF, UNRESERVED_KEYWORD) -PG_KEYWORD("left", LEFT, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("level", LEVEL, UNRESERVED_KEYWORD) -PG_KEYWORD("like", LIKE, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("limit", LIMIT, RESERVED_KEYWORD) -PG_KEYWORD("listen", LISTEN, UNRESERVED_KEYWORD) -PG_KEYWORD("load", LOAD, UNRESERVED_KEYWORD) -PG_KEYWORD("local", LOCAL, UNRESERVED_KEYWORD) -PG_KEYWORD("localtime", LOCALTIME, RESERVED_KEYWORD) -PG_KEYWORD("localtimestamp", LOCALTIMESTAMP, RESERVED_KEYWORD) -PG_KEYWORD("location", LOCATION, UNRESERVED_KEYWORD) -PG_KEYWORD("lock", LOCK_P, UNRESERVED_KEYWORD) -PG_KEYWORD("locked", LOCKED, UNRESERVED_KEYWORD) -PG_KEYWORD("logged", LOGGED, UNRESERVED_KEYWORD) -PG_KEYWORD("macro", MACRO, UNRESERVED_KEYWORD) -PG_KEYWORD("map", MAP, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("mapping", MAPPING, UNRESERVED_KEYWORD) -PG_KEYWORD("match", MATCH, UNRESERVED_KEYWORD) -PG_KEYWORD("materialized", MATERIALIZED, UNRESERVED_KEYWORD) -PG_KEYWORD("maxvalue", MAXVALUE, UNRESERVED_KEYWORD) -PG_KEYWORD("method", METHOD, UNRESERVED_KEYWORD) -PG_KEYWORD("microsecond", MICROSECOND_P, UNRESERVED_KEYWORD) -PG_KEYWORD("microseconds", MICROSECONDS_P, UNRESERVED_KEYWORD) -PG_KEYWORD("millisecond", MILLISECOND_P, UNRESERVED_KEYWORD) -PG_KEYWORD("milliseconds", MILLISECONDS_P, UNRESERVED_KEYWORD) -PG_KEYWORD("minute", MINUTE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("minutes", MINUTES_P, UNRESERVED_KEYWORD) -PG_KEYWORD("minvalue", MINVALUE, UNRESERVED_KEYWORD) -PG_KEYWORD("mode", MODE, UNRESERVED_KEYWORD) -PG_KEYWORD("month", MONTH_P, UNRESERVED_KEYWORD) -PG_KEYWORD("months", MONTHS_P, UNRESERVED_KEYWORD) -PG_KEYWORD("move", MOVE, UNRESERVED_KEYWORD) -PG_KEYWORD("name", NAME_P, UNRESERVED_KEYWORD) -PG_KEYWORD("names", NAMES, UNRESERVED_KEYWORD) -PG_KEYWORD("national", NATIONAL, COL_NAME_KEYWORD) -PG_KEYWORD("natural", NATURAL, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("nchar", NCHAR, COL_NAME_KEYWORD) -PG_KEYWORD("new", NEW, UNRESERVED_KEYWORD) -PG_KEYWORD("next", NEXT, UNRESERVED_KEYWORD) -PG_KEYWORD("no", NO, UNRESERVED_KEYWORD) -PG_KEYWORD("none", NONE, COL_NAME_KEYWORD) -PG_KEYWORD("not", NOT, RESERVED_KEYWORD) -PG_KEYWORD("nothing", NOTHING, UNRESERVED_KEYWORD) -PG_KEYWORD("notify", NOTIFY, UNRESERVED_KEYWORD) -PG_KEYWORD("notnull", NOTNULL, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("nowait", NOWAIT, UNRESERVED_KEYWORD) -PG_KEYWORD("null", NULL_P, RESERVED_KEYWORD) -PG_KEYWORD("nullif", NULLIF, COL_NAME_KEYWORD) -PG_KEYWORD("nulls", NULLS_P, UNRESERVED_KEYWORD) -PG_KEYWORD("numeric", NUMERIC, COL_NAME_KEYWORD) -PG_KEYWORD("object", OBJECT_P, UNRESERVED_KEYWORD) -PG_KEYWORD("of", OF, UNRESERVED_KEYWORD) -PG_KEYWORD("off", OFF, UNRESERVED_KEYWORD) -PG_KEYWORD("offset", OFFSET, RESERVED_KEYWORD) -PG_KEYWORD("oids", OIDS, UNRESERVED_KEYWORD) -PG_KEYWORD("old", OLD, UNRESERVED_KEYWORD) -PG_KEYWORD("on", ON, RESERVED_KEYWORD) -PG_KEYWORD("only", ONLY, RESERVED_KEYWORD) -PG_KEYWORD("operator", OPERATOR, UNRESERVED_KEYWORD) -PG_KEYWORD("option", OPTION, UNRESERVED_KEYWORD) -PG_KEYWORD("options", OPTIONS, UNRESERVED_KEYWORD) -PG_KEYWORD("or", OR, RESERVED_KEYWORD) -PG_KEYWORD("order", ORDER, RESERVED_KEYWORD) -PG_KEYWORD("ordinality", ORDINALITY, UNRESERVED_KEYWORD) -PG_KEYWORD("out", OUT_P, COL_NAME_KEYWORD) -PG_KEYWORD("outer", OUTER_P, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("over", OVER, UNRESERVED_KEYWORD) -PG_KEYWORD("overlaps", OVERLAPS, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("overlay", OVERLAY, COL_NAME_KEYWORD) -PG_KEYWORD("overriding", OVERRIDING, UNRESERVED_KEYWORD) -PG_KEYWORD("owned", OWNED, UNRESERVED_KEYWORD) -PG_KEYWORD("owner", OWNER, UNRESERVED_KEYWORD) -PG_KEYWORD("parallel", PARALLEL, UNRESERVED_KEYWORD) -PG_KEYWORD("parser", PARSER, UNRESERVED_KEYWORD) -PG_KEYWORD("partial", PARTIAL, UNRESERVED_KEYWORD) -PG_KEYWORD("partition", PARTITION, UNRESERVED_KEYWORD) -PG_KEYWORD("passing", PASSING, UNRESERVED_KEYWORD) -PG_KEYWORD("password", PASSWORD, UNRESERVED_KEYWORD) -PG_KEYWORD("percent", PERCENT, UNRESERVED_KEYWORD) -PG_KEYWORD("placing", PLACING, RESERVED_KEYWORD) -PG_KEYWORD("plans", PLANS, UNRESERVED_KEYWORD) -PG_KEYWORD("policy", POLICY, UNRESERVED_KEYWORD) -PG_KEYWORD("position", POSITION, COL_NAME_KEYWORD) -PG_KEYWORD("pragma", PRAGMA_P, UNRESERVED_KEYWORD) -PG_KEYWORD("preceding", PRECEDING, UNRESERVED_KEYWORD) -PG_KEYWORD("precision", PRECISION, COL_NAME_KEYWORD) -PG_KEYWORD("prepare", PREPARE, UNRESERVED_KEYWORD) -PG_KEYWORD("prepared", PREPARED, UNRESERVED_KEYWORD) -PG_KEYWORD("preserve", PRESERVE, UNRESERVED_KEYWORD) -PG_KEYWORD("primary", PRIMARY, RESERVED_KEYWORD) -PG_KEYWORD("prior", PRIOR, UNRESERVED_KEYWORD) -PG_KEYWORD("privileges", PRIVILEGES, UNRESERVED_KEYWORD) -PG_KEYWORD("procedural", PROCEDURAL, UNRESERVED_KEYWORD) -PG_KEYWORD("procedure", PROCEDURE, UNRESERVED_KEYWORD) -PG_KEYWORD("program", PROGRAM, UNRESERVED_KEYWORD) -PG_KEYWORD("publication", PUBLICATION, UNRESERVED_KEYWORD) -PG_KEYWORD("qualify", QUALIFY, RESERVED_KEYWORD) -PG_KEYWORD("quote", QUOTE, UNRESERVED_KEYWORD) -PG_KEYWORD("range", RANGE, UNRESERVED_KEYWORD) -PG_KEYWORD("read", READ_P, UNRESERVED_KEYWORD) -PG_KEYWORD("real", REAL, COL_NAME_KEYWORD) -PG_KEYWORD("reassign", REASSIGN, UNRESERVED_KEYWORD) -PG_KEYWORD("recheck", RECHECK, UNRESERVED_KEYWORD) -PG_KEYWORD("recursive", RECURSIVE, UNRESERVED_KEYWORD) -PG_KEYWORD("ref", REF, UNRESERVED_KEYWORD) -PG_KEYWORD("references", REFERENCES, RESERVED_KEYWORD) -PG_KEYWORD("referencing", REFERENCING, UNRESERVED_KEYWORD) -PG_KEYWORD("refresh", REFRESH, UNRESERVED_KEYWORD) -PG_KEYWORD("reindex", REINDEX, UNRESERVED_KEYWORD) -PG_KEYWORD("relative", RELATIVE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("release", RELEASE, UNRESERVED_KEYWORD) -PG_KEYWORD("rename", RENAME, UNRESERVED_KEYWORD) -PG_KEYWORD("repeatable", REPEATABLE, UNRESERVED_KEYWORD) -PG_KEYWORD("replace", REPLACE, UNRESERVED_KEYWORD) -PG_KEYWORD("replica", REPLICA, UNRESERVED_KEYWORD) -PG_KEYWORD("reset", RESET, UNRESERVED_KEYWORD) -PG_KEYWORD("respect", RESPECT_P, UNRESERVED_KEYWORD) -PG_KEYWORD("restart", RESTART, UNRESERVED_KEYWORD) -PG_KEYWORD("restrict", RESTRICT, UNRESERVED_KEYWORD) -PG_KEYWORD("returning", RETURNING, RESERVED_KEYWORD) -PG_KEYWORD("returns", RETURNS, UNRESERVED_KEYWORD) -PG_KEYWORD("revoke", REVOKE, UNRESERVED_KEYWORD) -PG_KEYWORD("right", RIGHT, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("role", ROLE, UNRESERVED_KEYWORD) -PG_KEYWORD("rollback", ROLLBACK, UNRESERVED_KEYWORD) -PG_KEYWORD("rollup", ROLLUP, UNRESERVED_KEYWORD) -PG_KEYWORD("row", ROW, COL_NAME_KEYWORD) -PG_KEYWORD("rows", ROWS, UNRESERVED_KEYWORD) -PG_KEYWORD("rule", RULE, UNRESERVED_KEYWORD) -PG_KEYWORD("sample", SAMPLE, UNRESERVED_KEYWORD) -PG_KEYWORD("savepoint", SAVEPOINT, UNRESERVED_KEYWORD) -PG_KEYWORD("schema", SCHEMA, UNRESERVED_KEYWORD) -PG_KEYWORD("schemas", SCHEMAS, UNRESERVED_KEYWORD) -PG_KEYWORD("scroll", SCROLL, UNRESERVED_KEYWORD) -PG_KEYWORD("search", SEARCH, UNRESERVED_KEYWORD) -PG_KEYWORD("second", SECOND_P, UNRESERVED_KEYWORD) -PG_KEYWORD("seconds", SECONDS_P, UNRESERVED_KEYWORD) -PG_KEYWORD("security", SECURITY, UNRESERVED_KEYWORD) -PG_KEYWORD("select", SELECT, RESERVED_KEYWORD) -PG_KEYWORD("sequence", SEQUENCE, UNRESERVED_KEYWORD) -PG_KEYWORD("sequences", SEQUENCES, UNRESERVED_KEYWORD) -PG_KEYWORD("serializable", SERIALIZABLE, UNRESERVED_KEYWORD) -PG_KEYWORD("server", SERVER, UNRESERVED_KEYWORD) -PG_KEYWORD("session", SESSION, UNRESERVED_KEYWORD) -PG_KEYWORD("session_user", SESSION_USER, RESERVED_KEYWORD) -PG_KEYWORD("set", SET, UNRESERVED_KEYWORD) -PG_KEYWORD("setof", SETOF, COL_NAME_KEYWORD) -PG_KEYWORD("sets", SETS, UNRESERVED_KEYWORD) -PG_KEYWORD("share", SHARE, UNRESERVED_KEYWORD) -PG_KEYWORD("show", SHOW, UNRESERVED_KEYWORD) -PG_KEYWORD("similar", SIMILAR, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("simple", SIMPLE, UNRESERVED_KEYWORD) -PG_KEYWORD("skip", SKIP, UNRESERVED_KEYWORD) -PG_KEYWORD("smallint", SMALLINT, COL_NAME_KEYWORD) -PG_KEYWORD("snapshot", SNAPSHOT, UNRESERVED_KEYWORD) -PG_KEYWORD("some", SOME, RESERVED_KEYWORD) -PG_KEYWORD("sql", SQL_P, UNRESERVED_KEYWORD) -PG_KEYWORD("stable", STABLE, UNRESERVED_KEYWORD) -PG_KEYWORD("standalone", STANDALONE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("start", START, UNRESERVED_KEYWORD) -PG_KEYWORD("statement", STATEMENT, UNRESERVED_KEYWORD) -PG_KEYWORD("statistics", STATISTICS, UNRESERVED_KEYWORD) -PG_KEYWORD("stdin", STDIN, UNRESERVED_KEYWORD) -PG_KEYWORD("stdout", STDOUT, UNRESERVED_KEYWORD) -PG_KEYWORD("storage", STORAGE, UNRESERVED_KEYWORD) -PG_KEYWORD("stored", STORED, UNRESERVED_KEYWORD) -PG_KEYWORD("strict", STRICT_P, UNRESERVED_KEYWORD) -PG_KEYWORD("strip", STRIP_P, UNRESERVED_KEYWORD) -PG_KEYWORD("struct", STRUCT, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("subscription", SUBSCRIPTION, UNRESERVED_KEYWORD) -PG_KEYWORD("substring", SUBSTRING, COL_NAME_KEYWORD) -PG_KEYWORD("summarize", SUMMARIZE, UNRESERVED_KEYWORD) -PG_KEYWORD("symmetric", SYMMETRIC, RESERVED_KEYWORD) -PG_KEYWORD("sysid", SYSID, UNRESERVED_KEYWORD) -PG_KEYWORD("system", SYSTEM_P, UNRESERVED_KEYWORD) -PG_KEYWORD("table", TABLE, RESERVED_KEYWORD) -PG_KEYWORD("tables", TABLES, UNRESERVED_KEYWORD) -PG_KEYWORD("tablesample", TABLESAMPLE, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("tablespace", TABLESPACE, UNRESERVED_KEYWORD) -PG_KEYWORD("temp", TEMP, UNRESERVED_KEYWORD) -PG_KEYWORD("template", TEMPLATE, UNRESERVED_KEYWORD) -PG_KEYWORD("temporary", TEMPORARY, UNRESERVED_KEYWORD) -PG_KEYWORD("text", TEXT_P, UNRESERVED_KEYWORD) -PG_KEYWORD("then", THEN, RESERVED_KEYWORD) -PG_KEYWORD("time", TIME, COL_NAME_KEYWORD) -PG_KEYWORD("timestamp", TIMESTAMP, COL_NAME_KEYWORD) -PG_KEYWORD("to", TO, RESERVED_KEYWORD) -PG_KEYWORD("trailing", TRAILING, RESERVED_KEYWORD) -PG_KEYWORD("transaction", TRANSACTION, UNRESERVED_KEYWORD) -PG_KEYWORD("transform", TRANSFORM, UNRESERVED_KEYWORD) -PG_KEYWORD("treat", TREAT, COL_NAME_KEYWORD) -PG_KEYWORD("trigger", TRIGGER, UNRESERVED_KEYWORD) -PG_KEYWORD("trim", TRIM, COL_NAME_KEYWORD) -PG_KEYWORD("true", TRUE_P, RESERVED_KEYWORD) -PG_KEYWORD("truncate", TRUNCATE, UNRESERVED_KEYWORD) -PG_KEYWORD("trusted", TRUSTED, UNRESERVED_KEYWORD) -PG_KEYWORD("try_cast", TRY_CAST, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("type", TYPE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("types", TYPES_P, UNRESERVED_KEYWORD) -PG_KEYWORD("unbounded", UNBOUNDED, UNRESERVED_KEYWORD) -PG_KEYWORD("uncommitted", UNCOMMITTED, UNRESERVED_KEYWORD) -PG_KEYWORD("unencrypted", UNENCRYPTED, UNRESERVED_KEYWORD) -PG_KEYWORD("union", UNION, RESERVED_KEYWORD) -PG_KEYWORD("unique", UNIQUE, RESERVED_KEYWORD) -PG_KEYWORD("unknown", UNKNOWN, UNRESERVED_KEYWORD) -PG_KEYWORD("unlisten", UNLISTEN, UNRESERVED_KEYWORD) -PG_KEYWORD("unlogged", UNLOGGED, UNRESERVED_KEYWORD) -PG_KEYWORD("until", UNTIL, UNRESERVED_KEYWORD) -PG_KEYWORD("update", UPDATE, UNRESERVED_KEYWORD) -PG_KEYWORD("user", USER, RESERVED_KEYWORD) -PG_KEYWORD("using", USING, RESERVED_KEYWORD) -PG_KEYWORD("vacuum", VACUUM, UNRESERVED_KEYWORD) -PG_KEYWORD("valid", VALID, UNRESERVED_KEYWORD) -PG_KEYWORD("validate", VALIDATE, UNRESERVED_KEYWORD) -PG_KEYWORD("validator", VALIDATOR, UNRESERVED_KEYWORD) -PG_KEYWORD("value", VALUE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("values", VALUES, COL_NAME_KEYWORD) -PG_KEYWORD("varchar", VARCHAR, COL_NAME_KEYWORD) -PG_KEYWORD("variadic", VARIADIC, RESERVED_KEYWORD) -PG_KEYWORD("varying", VARYING, UNRESERVED_KEYWORD) -PG_KEYWORD("verbose", VERBOSE, TYPE_FUNC_NAME_KEYWORD) -PG_KEYWORD("version", VERSION_P, UNRESERVED_KEYWORD) -PG_KEYWORD("view", VIEW, UNRESERVED_KEYWORD) -PG_KEYWORD("views", VIEWS, UNRESERVED_KEYWORD) -PG_KEYWORD("virtual", VIRTUAL, UNRESERVED_KEYWORD) -PG_KEYWORD("volatile", VOLATILE, UNRESERVED_KEYWORD) -PG_KEYWORD("when", WHEN, RESERVED_KEYWORD) -PG_KEYWORD("where", WHERE, RESERVED_KEYWORD) -PG_KEYWORD("whitespace", WHITESPACE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("window", WINDOW, RESERVED_KEYWORD) -PG_KEYWORD("with", WITH, RESERVED_KEYWORD) -PG_KEYWORD("within", WITHIN, UNRESERVED_KEYWORD) -PG_KEYWORD("without", WITHOUT, UNRESERVED_KEYWORD) -PG_KEYWORD("work", WORK, UNRESERVED_KEYWORD) -PG_KEYWORD("wrapper", WRAPPER, UNRESERVED_KEYWORD) -PG_KEYWORD("write", WRITE_P, UNRESERVED_KEYWORD) -PG_KEYWORD("xml", XML_P, UNRESERVED_KEYWORD) -PG_KEYWORD("xmlattributes", XMLATTRIBUTES, COL_NAME_KEYWORD) -PG_KEYWORD("xmlconcat", XMLCONCAT, COL_NAME_KEYWORD) -PG_KEYWORD("xmlelement", XMLELEMENT, COL_NAME_KEYWORD) -PG_KEYWORD("xmlexists", XMLEXISTS, COL_NAME_KEYWORD) -PG_KEYWORD("xmlforest", XMLFOREST, COL_NAME_KEYWORD) -PG_KEYWORD("xmlnamespaces", XMLNAMESPACES, COL_NAME_KEYWORD) -PG_KEYWORD("xmlparse", XMLPARSE, COL_NAME_KEYWORD) -PG_KEYWORD("xmlpi", XMLPI, COL_NAME_KEYWORD) -PG_KEYWORD("xmlroot", XMLROOT, COL_NAME_KEYWORD) -PG_KEYWORD("xmlserialize", XMLSERIALIZE, COL_NAME_KEYWORD) -PG_KEYWORD("xmltable", XMLTABLE, COL_NAME_KEYWORD) -PG_KEYWORD("year", YEAR_P, UNRESERVED_KEYWORD) -PG_KEYWORD("years", YEARS_P, UNRESERVED_KEYWORD) -PG_KEYWORD("yes", YES_P, UNRESERVED_KEYWORD) -PG_KEYWORD("zone", ZONE, UNRESERVED_KEYWORD) + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); -}; +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len, f_rng, p_rng ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); -const int NumScanKeywords = lengthof(ScanKeywords); -} // namespace duckdb_libpgquery + return( 0 ); +} +/* + * Parse an encrypted PKCS#8 encoded private key + * + * To save space, the decryption happens in-place on the given key buffer. + * Also, while this function may modify the keybuffer, it doesn't own it, + * and instead it is the responsibility of the caller to zeroize and properly + * free it after use. + * + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +static int pk_parse_key_pkcs8_encrypted_der( + mbedtls_pk_context *pk, + unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, decrypted = 0; + size_t len; + unsigned char *buf; + unsigned char *p, *end; + mbedtls_asn1_buf pbe_alg_oid, pbe_params; +#if defined(MBEDTLS_PKCS12_C) + mbedtls_cipher_type_t cipher_alg; + mbedtls_md_type_t md_alg; +#endif -// LICENSE_CHANGE_END + p = key; + end = p + keylen; + if( pwdlen == 0 ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); -namespace duckdb_libpgquery { + /* + * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData + * } + * + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * EncryptedData ::= OCTET STRING + * + * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); + } -/* - * raw_parser - * Given a query in string form, do lexical and grammatical analysis. - * - * Returns a list of raw (un-analyzed) parse trees. The immediate elements - * of the list are always PGRawStmt nodes. - */ -PGList *raw_parser(const char *str) { - core_yyscan_t yyscanner; - base_yy_extra_type yyextra; - int yyresult; + end = p + len; - /* initialize the flex scanner */ - yyscanner = scanner_init(str, &yyextra.core_yy_extra, ScanKeywords, NumScanKeywords); + if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); - /* base_yylex() only needs this much initialization */ - yyextra.have_lookahead = false; + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT, ret ) ); - /* initialize the bison parser */ - parser_init(&yyextra); + buf = p; - /* Parse! */ - yyresult = base_yyparse(yyscanner); + /* + * Decrypt EncryptedData with appropriate PBE + */ +#if defined(MBEDTLS_PKCS12_C) + if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, + pwd, pwdlen, p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - /* Clean up (release memory) */ - scanner_finish(yyscanner); + return( ret ); + } - if (yyresult) /* error */ - return NIL; + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PKCS5_C) + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); - return yyextra.parsetree; -} + return( ret ); + } -bool is_keyword(const char *text) { - return ScanKeywordLookup(text, ScanKeywords, NumScanKeywords) != NULL; -} + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS5_C */ + { + ((void) pwd); + } -std::vector keyword_list() { - std::vector result; - for(size_t i = 0; i < NumScanKeywords; i++) { - PGKeyword keyword; - keyword.text = ScanKeywords[i].name; - switch(ScanKeywords[i].category) { - case UNRESERVED_KEYWORD: - keyword.category = PGKeywordCategory::PG_KEYWORD_UNRESERVED; - break; - case RESERVED_KEYWORD: - keyword.category = PGKeywordCategory::PG_KEYWORD_RESERVED; - break; - case TYPE_FUNC_NAME_KEYWORD: - keyword.category = PGKeywordCategory::PG_KEYWORD_TYPE_FUNC; - break; - case COL_NAME_KEYWORD: - keyword.category = PGKeywordCategory::PG_KEYWORD_COL_NAME; - break; - } - result.push_back(keyword); - } - return result; + if( decrypted == 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len, f_rng, p_rng ) ); } +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ -std::vector tokenize(const char *str) { - core_yyscan_t yyscanner; - base_yy_extra_type yyextra; +/* + * Parse a private key + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + const mbedtls_pk_info_t *pk_info; +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; +#endif - std::vector result; - yyscanner = scanner_init(str, &yyextra.core_yy_extra, ScanKeywords, NumScanKeywords); - yyextra.have_lookahead = false; + PK_VALIDATE_RET( pk != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL ); - while(true) { - YYSTYPE type; - YYLTYPE loc; - int token; - try { - token = base_yylex(&type, &loc, yyscanner); - } catch(...) { - token = 0; - } - if (token == 0) { - break; - } - PGSimplifiedToken current_token; - switch(token) { - case IDENT: - current_token.type = PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_IDENTIFIER; - break; - case ICONST: - case FCONST: - current_token.type = PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_NUMERIC_CONSTANT; - break; - case SCONST: - case BCONST: - case XCONST: - current_token.type = PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_STRING_CONSTANT; - break; - case Op: - case PARAM: - case COLON_EQUALS: - case EQUALS_GREATER: - case LESS_EQUALS: - case GREATER_EQUALS: - case NOT_EQUALS: - current_token.type = PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_OPERATOR; - break; - default: - if (token >= 255) { - // non-ascii value, probably a keyword - current_token.type = PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_KEYWORD; - } else { - // ascii value, probably an operator - current_token.type = PGSimplifiedTokenType::PG_SIMPLIFIED_TOKEN_OPERATOR; - } - break; - } - current_token.start = loc; - result.push_back(current_token); - } +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); - scanner_finish(yyscanner); - return result; -} +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); -/* - * Intermediate filter between parser and core lexer (core_yylex in scan.l). - * - * This filter is needed because in some cases the standard SQL grammar - * requires more than one token lookahead. We reduce these cases to one-token - * lookahead by replacing tokens here, in order to keep the grammar LALR(1). - * - * Using a filter is simpler than trying to recognize multiword tokens - * directly in scan.l, because we'd have to allow for comments between the - * words. Furthermore it's not clear how to do that without re-introducing - * scanner backtrack, which would cost more performance than this filter - * layer does. - * - * The filter also provides a convenient place to translate between - * the core_YYSTYPE and YYSTYPE representations (which are really the - * same thing anyway, but notationally they're different). - */ -int base_yylex(YYSTYPE *lvalp, YYLTYPE *llocp, core_yyscan_t yyscanner) { - base_yy_extra_type *yyextra = pg_yyget_extra(yyscanner); - int cur_token; - int next_token; - int cur_token_length; - YYLTYPE cur_yylloc; + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + pem.buf, pem.buflen, + f_rng, p_rng ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } - /* Get next token --- we might already have it */ - if (yyextra->have_lookahead) { - cur_token = yyextra->lookahead_token; - lvalp->core_yystype = yyextra->lookahead_yylval; - *llocp = yyextra->lookahead_yylloc; - *(yyextra->lookahead_end) = yyextra->lookahead_hold_char; - yyextra->have_lookahead = false; - } else - cur_token = core_yylex(&(lvalp->core_yystype), llocp, yyscanner); + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_ECP_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, + pem.buf, pem.buflen, f_rng, p_rng ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } - /* - * If this token isn't one that requires lookahead, just return it. If it - * does, determine the token length. (We could get that via strlen(), but - * since we have such a small set of possibilities, hardwiring seems - * feasible and more efficient.) - */ - switch (cur_token) { - case NOT: - cur_token_length = 3; - break; - case NULLS_P: - cur_token_length = 5; - break; - case WITH: - cur_token_length = 4; - break; - default: - return cur_token; - } + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); - /* - * Identify end+1 of current token. core_yylex() has temporarily stored a - * '\0' here, and will undo that when we call it again. We need to redo - * it to fully revert the lookahead call for error reporting purposes. - */ - yyextra->lookahead_end = yyextra->core_yy_extra.scanbuf + *llocp + cur_token_length; - Assert(*(yyextra->lookahead_end) == '\0'); +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN ENCRYPTED PRIVATE KEY-----", + "-----END ENCRYPTED PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, pem.buf, pem.buflen, + pwd, pwdlen, f_rng, p_rng ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } - /* - * Save and restore *llocp around the call. It might look like we could - * avoid this by just passing &lookahead_yylloc to core_yylex(), but that - * does not work because flex actually holds onto the last-passed pointer - * internally, and will use that for error reporting. We need any error - * reports to point to the current token, not the next one. - */ - cur_yylloc = *llocp; + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_PEM_PARSE_C */ - /* Get next token, saving outputs into lookahead variables */ - next_token = core_yylex(&(yyextra->lookahead_yylval), llocp, yyscanner); - yyextra->lookahead_token = next_token; - yyextra->lookahead_yylloc = *llocp; + /* + * At this point we only know it's not a PEM formatted key. Could be any + * of the known DER encoded private key formats + * + * We try the different DER format parsers to see if one passes without + * error + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + { + unsigned char *key_copy; - *llocp = cur_yylloc; + if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); - /* Now revert the un-truncation of the current token */ - yyextra->lookahead_hold_char = *(yyextra->lookahead_end); - *(yyextra->lookahead_end) = '\0'; + memcpy( key_copy, key, keylen ); - yyextra->have_lookahead = true; + ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, + pwd, pwdlen, f_rng, p_rng ); - /* Replace cur_token if needed, based on lookahead */ - switch (cur_token) { - case NOT: - /* Replace NOT by NOT_LA if it's followed by BETWEEN, IN, etc */ - switch (next_token) { - case BETWEEN: - case IN_P: - case LIKE: - case ILIKE: - case SIMILAR: - cur_token = NOT_LA; - break; - } - break; + mbedtls_platform_zeroize( key_copy, keylen ); + mbedtls_free( key_copy ); + } - case NULLS_P: - /* Replace NULLS_P by NULLS_LA if it's followed by FIRST or LAST */ - switch (next_token) { - case FIRST_P: - case LAST_P: - cur_token = NULLS_LA; - break; - } - break; + if( ret == 0 ) + return( 0 ); - case WITH: - /* Replace WITH by WITH_LA if it's followed by TIME or ORDINALITY */ - switch (next_token) { - case TIME: - case ORDINALITY: - cur_token = WITH_LA; - break; - } - break; - } + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); + + if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) + { + return( ret ); + } +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + + ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen, f_rng, p_rng ); + if( ret == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); + +#if defined(MBEDTLS_RSA_C) + + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), key, keylen ) == 0 ) + { + return( 0 ); + } + + mbedtls_pk_free( pk ); + mbedtls_pk_init( pk ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + if( mbedtls_pk_setup( pk, pk_info ) == 0 && + pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + key, keylen, f_rng, p_rng ) == 0 ) + { + return( 0 ); + } + mbedtls_pk_free( pk ); +#endif /* MBEDTLS_ECP_C */ - return cur_token; -} + /* If MBEDTLS_RSA_C is defined but MBEDTLS_ECP_C isn't, + * it is ok to leave the PK context initialized but not + * freed: It is the caller's responsibility to call pk_init() + * before calling this function, and to call pk_free() + * when it fails. If MBEDTLS_ECP_C is defined but MBEDTLS_RSA_C + * isn't, this leads to mbedtls_pk_free() being called + * twice, once here and once by the caller, but this is + * also ok and in line with the mbedtls_pk_free() calls + * on failed PEM parsing attempts. */ + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); } -// LICENSE_CHANGE_END +/* + * Parse a public key + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p; +#if defined(MBEDTLS_RSA_C) + const mbedtls_pk_info_t *pk_info; +#endif +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; +#endif + PK_VALIDATE_RET( ctx != NULL ); + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + PK_VALIDATE_RET( key != NULL || keylen == 0 ); + +#if defined(MBEDTLS_PEM_PARSE_C) + mbedtls_pem_init( &pem ); +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PUBLIC KEY-----", + "-----END RSA PUBLIC KEY-----", + key, NULL, 0, &len ); -// LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 -// See the end of this file for a list + if( ret == 0 ) + { + p = pem.buf; + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); -#line 1 "third_party/libpg_query/src_backend_parser_scan.cpp" -/*------------------------------------------------------------------------- - * - * scan.l - * lexical scanner for PostgreSQL - * - * NOTE NOTE NOTE: - * - * The rules in this file must be kept in sync with src/fe_utils/psqlscan.l! - * - * The rules are designed so that the scanner never has to backtrack, - * in the sense that there is always a rule that can match the input - * consumed so far (the rule action may internally throw back some input - * with yyless(), however). As explained in the flex manual, this makes - * for a useful speed increase --- about a third faster than a plain -CF - * lexer, in simple testing. The extra complexity is mostly in the rules - * for handling float numbers and continued string literals. If you change - * the lexical rules, verify that you haven't broken the no-backtrack ' - * property by running flex with the "-b" option and checking that the - * resulting "lex.backup" file says that no backing up is needed. (As of - * Postgres 9.2, this check is made automatically by the Makefile.) - * - * - * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group - * Portions Copyright (c) 1994, Regents of the University of California - * - * IDENTIFICATION - * src/backend/parser/scan.l - * - *------------------------------------------------------------------------- - */ -#include -//#include + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 ) + mbedtls_pk_free( ctx ); + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); - /* only needed for GUC variables */ + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + p = pem.buf; + + ret = mbedtls_pk_parse_subpubkey( &p, p + pem.buflen, ctx ); + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + mbedtls_pem_free( &pem ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_RSA_C) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + p = (unsigned char *)key; + ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) ); + if( ret == 0 ) + { + return( ret ); + } + mbedtls_pk_free( ctx ); + if( ret != ( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_PK_INVALID_PUBKEY, + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) ) + { + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + p = (unsigned char *) key; + + ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PK_PARSE_C */ +// LICENSE_CHANGE_END + // LICENSE_CHANGE_BEGIN // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 // See the end of this file for a list -/*------------------------------------------------------------------------- - * - * pg_wchar.h - * multibyte-character support +/* + * Common and shared functions used by multiple modules in the Mbed TLS + * library. * - * Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup - * Portions Copyright (c) 1994, Regents of the University of California + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 * - * src/include/mb/pg_wchar.h + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * NOTES - * This is used both by the backend and by libpq, but should not be - * included by libpq client programs. In particular, a libpq client - * should not assume that the encoding IDs used by the version of libpq - * it's linked to match up with the IDs declared here. + * http://www.apache.org/licenses/LICENSE-2.0 * - *------------------------------------------------------------------------- + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ - -#include - /* - * The pg_wchar type + * Ensure gmtime_r is available even with -std=c99; must be defined before + * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms. */ -namespace duckdb_libpgquery { -typedef unsigned int pg_wchar; -} - -// LICENSE_CHANGE_END +#if !defined(_POSIX_C_SOURCE) +#define _POSIX_C_SOURCE 200112L +#endif -#include -#line 43 "third_party/libpg_query/src_backend_parser_scan.cpp" -#define YY_INT_ALIGNED short int -/* A lexical scanner generated by flex */ +#ifdef MBEDTLS_THREADING_C -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 6 -#define YY_FLEX_SUBMINOR_VERSION 4 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA #endif +#include +#include -#ifdef yy_create_buffer -#define core_yy_create_buffer_ALREADY_DEFINED -#else -#define yy_create_buffer core_yy_create_buffer -#endif +#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) +/* + * This implementation should never be optimized out by the compiler + * + * This implementation for mbedtls_platform_zeroize() was inspired from Colin + * Percival's blog article at: + * + * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html + * + * It uses a volatile function pointer to the standard memset(). Because the + * pointer is volatile the compiler expects it to change at + * any time and will not optimize out the call that could potentially perform + * other operations on the input buffer instead of just setting it to 0. + * Nevertheless, as pointed out by davidtgoldblatt on Hacker News + * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for + * details), optimizations of the following form are still possible: + * + * if( memset_func != memset ) + * memset_func( buf, 0, len ); + * + * Note that it is extremely difficult to guarantee that + * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers + * in a portable way. For this reason, Mbed TLS also provides the configuration + * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for their + * platform and needs. + */ +static void * (* const volatile memset_func)( void *, int, size_t ) = memset; -#ifdef yy_delete_buffer -#define core_yy_delete_buffer_ALREADY_DEFINED -#else -#define yy_delete_buffer core_yy_delete_buffer -#endif +void mbedtls_platform_zeroize( void *buf, size_t len ) +{ + MBEDTLS_INTERNAL_VALIDATE( len == 0 || buf != NULL ); -#ifdef yy_scan_buffer -#define core_yy_scan_buffer_ALREADY_DEFINED -#else -#define yy_scan_buffer core_yy_scan_buffer -#endif + if( len > 0 ) + memset_func( buf, 0, len ); +} +#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ -#ifdef yy_scan_string -#define core_yy_scan_string_ALREADY_DEFINED -#else -#define yy_scan_string core_yy_scan_string -#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) +#include +#if !defined(_WIN32) && (defined(unix) || \ + defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \ + defined(__MACH__))) +#include +#endif /* !_WIN32 && (unix || __unix || __unix__ || + * (__APPLE__ && __MACH__)) */ -#ifdef yy_scan_bytes -#define core_yy_scan_bytes_ALREADY_DEFINED -#else -#define yy_scan_bytes core_yy_scan_bytes -#endif +#if !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) +/* + * This is a convenience shorthand macro to avoid checking the long + * preprocessor conditions above. Ideally, we could expose this macro in + * platform_util.h and simply use it in platform_util.c, threading.c and + * threading.h. However, this macro is not part of the Mbed TLS public API, so + * we keep it private by only defining it in this file + */ +#if ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) +#define PLATFORM_UTIL_USE_GMTIME +#endif /* ! ( defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) ) */ -#ifdef yy_init_buffer -#define core_yy_init_buffer_ALREADY_DEFINED -#else -#define yy_init_buffer core_yy_init_buffer -#endif +#endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \ + ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \ + _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */ -#ifdef yy_flush_buffer -#define core_yy_flush_buffer_ALREADY_DEFINED +struct tm *mbedtls_platform_gmtime_r( const mbedtls_time_t *tt, + struct tm *tm_buf ) +{ +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + return( ( gmtime_s( tm_buf, tt ) == 0 ) ? tm_buf : NULL ); +#elif !defined(PLATFORM_UTIL_USE_GMTIME) + return( gmtime_r( tt, tm_buf ) ); #else -#define yy_flush_buffer core_yy_flush_buffer -#endif + struct tm *lt; -#ifdef yy_load_buffer_state -#define core_yy_load_buffer_state_ALREADY_DEFINED -#else -#define yy_load_buffer_state core_yy_load_buffer_state -#endif +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_lock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ -#ifdef yy_switch_to_buffer -#define core_yy_switch_to_buffer_ALREADY_DEFINED -#else -#define yy_switch_to_buffer core_yy_switch_to_buffer -#endif + lt = gmtime( tt ); -#ifdef yypush_buffer_state -#define core_yypush_buffer_state_ALREADY_DEFINED -#else -#define yypush_buffer_state core_yypush_buffer_state -#endif + if( lt != NULL ) + { + memcpy( tm_buf, lt, sizeof( struct tm ) ); + } -#ifdef yypop_buffer_state -#define core_yypop_buffer_state_ALREADY_DEFINED -#else -#define yypop_buffer_state core_yypop_buffer_state -#endif +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_gmtime_mutex ) != 0 ) + return( NULL ); +#endif /* MBEDTLS_THREADING_C */ -#ifdef yyensure_buffer_stack -#define core_yyensure_buffer_stack_ALREADY_DEFINED -#else -#define yyensure_buffer_stack core_yyensure_buffer_stack -#endif + return( ( lt == NULL ) ? NULL : tm_buf ); +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +} +#endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */ -#ifdef yylex -#define core_yylex_ALREADY_DEFINED -#else -#define yylex core_yylex -#endif +#if defined(MBEDTLS_TEST_HOOKS) +void (*mbedtls_test_hook_test_fail)( const char *, int, const char *); +#endif /* MBEDTLS_TEST_HOOKS */ -#ifdef yyrestart -#define core_yyrestart_ALREADY_DEFINED -#else -#define yyrestart core_yyrestart -#endif -#ifdef yylex_init -#define core_yylex_init_ALREADY_DEFINED -#else -#define yylex_init core_yylex_init -#endif -#ifdef yylex_init_extra -#define core_yylex_init_extra_ALREADY_DEFINED -#else -#define yylex_init_extra core_yylex_init_extra -#endif +// LICENSE_CHANGE_END -#ifdef yylex_destroy -#define core_yylex_destroy_ALREADY_DEFINED -#else -#define yylex_destroy core_yylex_destroy -#endif -#ifdef yyget_debug -#define core_yyget_debug_ALREADY_DEFINED -#else -#define yyget_debug core_yyget_debug -#endif +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list -#ifdef yyset_debug -#define core_yyset_debug_ALREADY_DEFINED -#else -#define yyset_debug core_yyset_debug -#endif +/* + * The RSA public-key cryptosystem + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -#ifdef yyget_extra -#define core_yyget_extra_ALREADY_DEFINED -#else -#define yyget_extra core_yyget_extra -#endif +/* + * The following sources were referenced in the design of this implementation + * of the RSA algorithm: + * + * [1] A method for obtaining digital signatures and public-key cryptosystems + * R Rivest, A Shamir, and L Adleman + * http://people.csail.mit.edu/rivest/pubs.html#RSA78 + * + * [2] Handbook of Applied Cryptography - 1997, Chapter 8 + * Menezes, van Oorschot and Vanstone + * + * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks + * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and + * Stefan Mangard + * https://arxiv.org/abs/1702.08719v2 + * + */ -#ifdef yyset_extra -#define core_yyset_extra_ALREADY_DEFINED -#else -#define yyset_extra core_yyset_extra -#endif -#ifdef yyget_in -#define core_yyget_in_ALREADY_DEFINED -#else -#define yyget_in core_yyget_in -#endif -#ifdef yyset_in -#define core_yyset_in_ALREADY_DEFINED -#else -#define yyset_in core_yyset_in -#endif +#if defined(MBEDTLS_RSA_C) -#ifdef yyget_out -#define core_yyget_out_ALREADY_DEFINED -#else -#define yyget_out core_yyget_out -#endif -#ifdef yyset_out -#define core_yyset_out_ALREADY_DEFINED -#else -#define yyset_out core_yyset_out -#endif -#ifdef yyget_leng -#define core_yyget_leng_ALREADY_DEFINED -#else -#define yyget_leng core_yyget_leng -#endif -#ifdef yyget_text -#define core_yyget_text_ALREADY_DEFINED -#else -#define yyget_text core_yyget_text -#endif +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list -#ifdef yyget_lineno -#define core_yyget_lineno_ALREADY_DEFINED -#else -#define yyget_lineno core_yyget_lineno -#endif +/** + * \file rsa_alt_helpers.h + * + * \brief Context-independent RSA helper functions + * + * This module declares some RSA-related helper functions useful when + * implementing the RSA interface. These functions are provided in a separate + * compilation unit in order to make it easy for designers of alternative RSA + * implementations to use them in their own code, as it is conceived that the + * functionality they provide will be necessary for most complete + * implementations. + * + * End-users of Mbed TLS who are not providing their own alternative RSA + * implementations should not use these functions directly, and should instead + * use only the functions declared in rsa.h. + * + * The interface provided by this module will be maintained through LTS (Long + * Term Support) branches of Mbed TLS, but may otherwise be subject to change, + * and must be considered an internal interface of the library. + * + * There are two classes of helper functions: + * + * (1) Parameter-generating helpers. These are: + * - mbedtls_rsa_deduce_primes + * - mbedtls_rsa_deduce_private_exponent + * - mbedtls_rsa_deduce_crt + * Each of these functions takes a set of core RSA parameters and + * generates some other, or CRT related parameters. + * + * (2) Parameter-checking helpers. These are: + * - mbedtls_rsa_validate_params + * - mbedtls_rsa_validate_crt + * They take a set of core or CRT related RSA parameters and check their + * validity. + * + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ -#ifdef yyset_lineno -#define core_yyset_lineno_ALREADY_DEFINED -#else -#define yyset_lineno core_yyset_lineno -#endif +#ifndef MBEDTLS_RSA_INTERNAL_H +#define MBEDTLS_RSA_INTERNAL_H -#ifdef yyget_column -#define core_yyget_column_ALREADY_DEFINED -#else -#define yyget_column core_yyget_column -#endif -#ifdef yyset_column -#define core_yyset_column_ALREADY_DEFINED -#else -#define yyset_column core_yyset_column -#endif -#ifdef yywrap -#define core_yywrap_ALREADY_DEFINED -#else -#define yywrap core_yywrap -#endif -#ifdef yyget_lval -#define core_yyget_lval_ALREADY_DEFINED -#else -#define yyget_lval core_yyget_lval -#endif -#ifdef yyset_lval -#define core_yyset_lval_ALREADY_DEFINED -#else -#define yyset_lval core_yyset_lval +#ifdef __cplusplus +extern "C" { #endif -#ifdef yyget_lloc -#define core_yyget_lloc_ALREADY_DEFINED -#else -#define yyget_lloc core_yyget_lloc -#endif -#ifdef yyset_lloc -#define core_yyset_lloc_ALREADY_DEFINED -#else -#define yyset_lloc core_yyset_lloc -#endif +/** + * \brief Compute RSA prime moduli P, Q from public modulus N=PQ + * and a pair of private and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ, with P, Q to be found + * \param E RSA public exponent + * \param D RSA private exponent + * \param P Pointer to MPI holding first prime factor of N on success + * \param Q Pointer to MPI holding second prime factor of N on success + * + * \return + * - 0 if successful. In this case, P and Q constitute a + * factorization of N. + * - A non-zero error code otherwise. + * + * \note It is neither checked that P, Q are prime nor that + * D, E are modular inverses wrt. P-1 and Q-1. For that, + * use the helper function \c mbedtls_rsa_validate_params. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, mbedtls_mpi const *E, + mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ); -#ifdef yyalloc -#define core_yyalloc_ALREADY_DEFINED -#else -#define yyalloc core_yyalloc -#endif +/** + * \brief Compute RSA private exponent from + * prime moduli and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param E RSA public exponent + * \param D Pointer to MPI holding the private exponent on success. + * + * \return + * - 0 if successful. In this case, D is set to a simultaneous + * modular inverse of E modulo both P-1 and Q-1. + * - A non-zero error code otherwise. + * + * \note This function does not check whether P and Q are primes. + * + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ); -#ifdef yyrealloc -#define core_yyrealloc_ALREADY_DEFINED -#else -#define yyrealloc core_yyrealloc -#endif -#ifdef yyfree -#define core_yyfree_ALREADY_DEFINED -#else -#define yyfree core_yyfree -#endif +/** + * \brief Generate RSA-CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param DP Output variable for D modulo P-1 + * \param DQ Output variable for D modulo Q-1 + * \param QP Output variable for the modular inverse of Q modulo P. + * + * \return 0 on success, non-zero error code otherwise. + * + * \note This function does not check whether P, Q are + * prime and whether D is a valid private exponent. + * + */ +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ); -/* First, we deal with platform-specific or compiler-specific issues. */ -/* begin standard C headers. */ -#include -#include -#include -#include +/** + * \brief Check validity of core RSA parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param E RSA public exponent + * \param f_rng PRNG to be used for primality check, or NULL + * \param p_rng PRNG context for f_rng, or NULL + * + * \return + * - 0 if the following conditions are satisfied + * if all relevant parameters are provided: + * - P prime if f_rng != NULL (%) + * - Q prime if f_rng != NULL (%) + * - 1 < N = P * Q + * - 1 < D, E < N + * - D and E are modular inverses modulo P-1 and Q-1 + * (%) This is only done if MBEDTLS_GENPRIME is defined. + * - A non-zero error code otherwise. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with + * (-,P,-,-,-) and a PRNG amounts to a primality check for P. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); -/* end standard C headers. */ +/** + * \brief Check validity of RSA CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param D RSA private exponent + * \param DP MPI to check for D modulo P-1 + * \param DQ MPI to check for D modulo P-1 + * \param QP MPI to check for the modular inverse of Q modulo P. + * + * \return + * - 0 if the following conditions are satisfied: + * - D = DP mod P-1 if P, D, DP != NULL + * - Q = DQ mod P-1 if P, D, DQ != NULL + * - QP = Q^-1 mod P if P, Q, QP != NULL + * - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed, + * potentially including \c MBEDTLS_ERR_MPI_XXX if some + * MPI calculations failed. + * - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient + * data was provided to check DP, DQ or QP. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with the + * parameters (P, -, D, DP, -, -) will check DP = D mod P-1. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ); -/* flex integer type definitions */ +#ifdef __cplusplus +} +#endif -#ifndef FLEXINT_H -#define FLEXINT_H -namespace duckdb_libpgquery { +#endif /* rsa_alt_helpers.h */ -/* C99 systems have . Non-C99 systems may or may not. */ -#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +// LICENSE_CHANGE_END -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif -#include -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -typedef uint64_t flex_uint64_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) -#endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) -#endif -#ifndef SIZE_MAX -#define SIZE_MAX (~(size_t)0) -#endif -#endif /* ! C99 */ -#endif /* ! FLEXINT_H */ -/* begin standard C++ headers. */ +#include -/* TODO: this is always defined, so inline it */ -#define yyconst const +#if defined(MBEDTLS_PKCS1_V21) -#if defined(__GNUC__) && __GNUC__ >= 3 -#define yynoreturn __attribute__((__noreturn__)) -#else -#define yynoreturn #endif -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an - * integer in range [0..255] for use as an array index. - */ -#define YY_SC_TO_UI(c) ((YY_CHAR) (c)) - -/* An opaque pointer. */ -#ifndef YY_TYPEDEF_YY_SCANNER_T -#define YY_TYPEDEF_YY_SCANNER_T -typedef void* yyscan_t; +#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) && !defined(__NetBSD__) +#include #endif -/* For convenience, these vars (plus the bison vars far below) - are macros in the reentrant scanner. */ -#define yyin yyg->yyin_r -#define yyout yyg->yyout_r -#define yyextra yyg->yyextra_r -#define yyleng yyg->yyleng_r -#define yytext yyg->yytext_r -#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) -#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) -#define yy_flex_debug yyg->yy_flex_debug_r - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN yyg->yy_start = 1 + 2 * -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START ((yyg->yy_start - 1) / 2) -#define YYSTATE YY_START -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE yyrestart( yyin , yyscanner ) -#define YY_END_OF_BUFFER_CHAR 0 +#if defined(MBEDTLS_PLATFORM_C) -/* Size of default input buffer. */ -#ifndef YY_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k. - * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. - * Ditto for the __ia64__ case accordingly. - */ -#define YY_BUF_SIZE 32768 #else -#define YY_BUF_SIZE 16384 -#endif /* __ia64__ */ -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE -typedef struct yy_buffer_state *YY_BUFFER_STATE; +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free #endif -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T -typedef size_t yy_size_t; -#endif +#if !defined(MBEDTLS_RSA_ALT) -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - - #define YY_LESS_LINENO(n) - #define YY_LINENO_REWIND_TO(ptr) - -/* Return all but the first "n" matched characters back to the input stream. */ -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = yyg->yy_hold_char; \ - YY_RESTORE_YY_MORE_OFFSET \ - yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up yytext again */ \ - } \ - while ( 0 ) -#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) +/* Parameter validation macros */ +#define RSA_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) +#define RSA_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE -struct yy_buffer_state - { - FILE *yy_input_file; +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + RSA_VALIDATE_RET( ctx != NULL ); + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ + if( N != NULL ) + ctx->len = mbedtls_mpi_size( &ctx->N ); - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - int yy_buf_size; + return( 0 ); +} - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - yy_size_t yy_n_chars; +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ) +{ + int ret = 0; + RSA_VALIDATE_RET( ctx != NULL ); - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; + if( N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) ); + ctx->len = mbedtls_mpi_size( &ctx->N ); + } - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) ); - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) ); - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) ); - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) ); - int yy_buffer_status; +cleanup: -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via yyrestart()), so that the user can continue scanning by - * just pointing yyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + return( 0 ); +} -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - * - * Returns the top of the stack, or NULL. - */ -#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ - ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ - : NULL) -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. +/* + * Checks whether the context fields are set in such a way + * that the RSA primitives will be able to execute without error. + * It does *not* make guarantees for consistency of the parameters. */ -#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] - -void yyrestart ( FILE *input_file , yyscan_t yyscanner ); -void yy_switch_to_buffer ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); -YY_BUFFER_STATE yy_create_buffer ( FILE *file, int size , yyscan_t yyscanner ); -void yy_delete_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); -void yy_flush_buffer ( YY_BUFFER_STATE b , yyscan_t yyscanner ); -void yypush_buffer_state ( YY_BUFFER_STATE new_buffer , yyscan_t yyscanner ); -void yypop_buffer_state ( yyscan_t yyscanner ); - -static void yyensure_buffer_stack ( yyscan_t yyscanner ); -static void yy_load_buffer_state ( yyscan_t yyscanner ); -static void yy_init_buffer ( YY_BUFFER_STATE b, FILE *file , yyscan_t yyscanner ); -#define YY_FLUSH_BUFFER yy_flush_buffer( YY_CURRENT_BUFFER , yyscanner) - -YY_BUFFER_STATE yy_scan_buffer ( char *base, yy_size_t size , yyscan_t yyscanner ); -YY_BUFFER_STATE yy_scan_string ( const char *yy_str , yyscan_t yyscanner ); -YY_BUFFER_STATE yy_scan_bytes ( const char *bytes, yy_size_t len , yyscan_t yyscanner ); - -void *yyalloc ( yy_size_t , yyscan_t yyscanner ); -void *yyrealloc ( void *, yy_size_t , yyscan_t yyscanner ); -void yyfree ( void * , yyscan_t yyscanner ); +static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv, + int blinding_needed ) +{ +#if !defined(MBEDTLS_RSA_NO_CRT) + /* blinding_needed is only used for NO_CRT to decide whether + * P,Q need to be present or not. */ + ((void) blinding_needed); +#endif -#define yy_new_buffer yy_create_buffer -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! YY_CURRENT_BUFFER ){ \ - yyensure_buffer_stack (yyscanner); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ - } -#define yy_set_bol(at_bol) \ - { \ - if ( ! YY_CURRENT_BUFFER ){\ - yyensure_buffer_stack (yyscanner); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ - } -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + if( ctx->len != mbedtls_mpi_size( &ctx->N ) || + ctx->len > MBEDTLS_MPI_MAX_SIZE ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } -/* Begin user sect3 */ + /* + * 1. Modular exponentiation needs positive, odd moduli. + */ -#define core_yywrap(yyscanner) (/*CONSTCOND*/1) -#define YY_SKIP_YYWRAP -typedef flex_uint8_t YY_CHAR; + /* Modular exponentiation wrt. N is always used for + * RSA public key operations. */ + if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } -typedef int yy_state_type; +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Modular exponentiation for P and Q is only + * used for private key operations and if CRT + * is used. */ + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* !MBEDTLS_RSA_NO_CRT */ -#define yytext_ptr yytext_r + /* + * 2. Exponents must be positive + */ -static yy_state_type yy_get_previous_state ( yyscan_t yyscanner ); -static yy_state_type yy_try_NUL_trans ( yy_state_type current_state , yyscan_t yyscanner); -static int yy_get_next_buffer ( yyscan_t yyscanner ); -static void yynoreturn yy_fatal_error ( const char* msg , yyscan_t yyscanner ); + /* Always need E for public key operations */ + if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); -/* Done after the current pattern has been matched and before the - * corresponding action - sets up yytext. - */ -#define YY_DO_BEFORE_ACTION \ - yyg->yytext_ptr = yy_bp; \ - yyleng = (yy_size_t) (yy_cp - yy_bp); \ - yyg->yy_hold_char = *yy_cp; \ - *yy_cp = '\0'; \ - yyg->yy_c_buf_p = yy_cp; -#define YY_NUM_RULES 82 -#define YY_END_OF_BUFFER 83 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static const flex_int16_t yy_accept[295] = - { 0, - 0, 0, 12, 12, 0, 0, 0, 0, 11, 11, - 0, 0, 0, 0, 0, 0, 0, 0, 55, 55, - 0, 0, 28, 28, 0, 0, 83, 81, 1, 1, - 71, 49, 81, 70, 71, 19, 70, 70, 70, 70, - 70, 74, 70, 70, 70, 70, 81, 80, 80, 80, - 80, 80, 80, 12, 9, 5, 5, 6, 6, 58, - 51, 11, 16, 32, 32, 22, 42, 31, 22, 46, - 46, 48, 52, 54, 53, 53, 54, 54, 24, 27, - 26, 26, 27, 27, 35, 36, 35, 1, 71, 69, - 43, 72, 44, 64, 1, 63, 61, 75, 2, 75, +#if defined(MBEDTLS_RSA_NO_CRT) + /* For private key operations, use D or DP & DQ + * as (unblinded) exponents. */ + if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); +#else + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Blinding shouldn't make exponents negative either, + * so check that P, Q >= 1 if that hasn't yet been + * done as part of 1. */ +#if defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && blinding_needed && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif - 74, 78, 60, 62, 66, 68, 65, 67, 73, 80, - 8, 20, 18, 59, 15, 12, 9, 9, 10, 5, - 7, 4, 3, 58, 57, 11, 16, 16, 17, 32, - 22, 22, 30, 23, 38, 39, 37, 37, 38, 31, - 46, 45, 47, 53, 53, 55, 24, 24, 25, 26, - 26, 28, 37, 37, 44, 1, 1, 2, 76, 75, - 79, 77, 50, 21, 9, 14, 10, 9, 3, 16, - 13, 17, 16, 22, 41, 23, 22, 39, 37, 37, - 40, 47, 53, 55, 24, 25, 24, 26, 28, 37, - 37, 9, 9, 9, 9, 16, 16, 16, 16, 22, - - 22, 22, 22, 39, 37, 37, 40, 55, 24, 24, - 24, 24, 28, 37, 37, 9, 9, 9, 9, 9, - 16, 16, 16, 16, 16, 22, 22, 22, 22, 22, - 37, 37, 55, 24, 24, 24, 24, 24, 28, 37, - 37, 9, 16, 22, 37, 33, 55, 24, 28, 37, - 34, 37, 55, 28, 37, 37, 55, 55, 55, 28, - 28, 28, 37, 37, 55, 55, 28, 28, 37, 56, - 55, 55, 55, 55, 29, 28, 28, 28, 28, 55, - 55, 55, 55, 55, 28, 28, 28, 28, 28, 55, - 55, 28, 28, 0 + /* It wouldn't lead to an error if it wasn't satisfied, + * but check for QP >= 1 nonetheless. */ +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && + mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif - } ; + return( 0 ); +} -static const YY_CHAR yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 2, 4, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 5, 6, 1, 7, 8, 9, 10, 11, - 11, 12, 13, 11, 14, 15, 16, 17, 17, 17, - 17, 17, 17, 17, 17, 18, 18, 19, 11, 20, - 21, 22, 23, 24, 25, 26, 27, 28, 29, 28, - 30, 30, 30, 30, 30, 30, 30, 31, 30, 32, - 30, 30, 33, 30, 34, 30, 30, 35, 30, 30, - 11, 36, 11, 8, 30, 24, 25, 26, 27, 28, +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) +{ + int ret = 0; + int have_N, have_P, have_Q, have_D, have_E; +#if !defined(MBEDTLS_RSA_NO_CRT) + int have_DP, have_DQ, have_QP; +#endif + int n_missing, pq_missing, d_missing, is_pub, is_priv; - 29, 28, 30, 30, 30, 30, 30, 30, 30, 31, - 30, 32, 30, 30, 33, 30, 37, 30, 30, 38, - 30, 30, 1, 24, 1, 24, 1, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, + RSA_VALIDATE_RET( ctx != NULL ); - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, - 30, 30, 30, 30, 30 - } ; + have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 ); + have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 ); + have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 ); + have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); + have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); -static const YY_CHAR yy_meta[39] = - { 0, - 1, 1, 2, 2, 3, 4, 5, 3, 3, 6, - 1, 7, 3, 3, 1, 7, 8, 8, 1, 3, - 3, 3, 1, 3, 9, 9, 9, 9, 9, 10, - 10, 10, 10, 10, 10, 11, 10, 10 - } ; +#if !defined(MBEDTLS_RSA_NO_CRT) + have_DP = ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) != 0 ); + have_DQ = ( mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) != 0 ); + have_QP = ( mbedtls_mpi_cmp_int( &ctx->QP, 0 ) != 0 ); +#endif -static const flex_int16_t yy_base[362] = - { 0, - 0, 0, 430, 424, 34, 54, 419, 418, 409, 408, - 41, 50, 402, 401, 38, 54, 393, 392, 85, 121, - 386, 385, 157, 193, 37, 46, 383, 1208, 77, 81, - 361, 1208, 83, 0, 0, 1208, 1208, 365, 50, 76, - 364, 80, 50, 81, 348, 348, 87, 0, 347, 346, - 344, 344, 331, 0, 104, 0, 0, 80, 328, 0, - 329, 0, 112, 0, 0, 126, 100, 0, 129, 0, - 0, 327, 321, 1208, 108, 142, 306, 285, 160, 1208, - 145, 148, 298, 282, 1208, 1208, 119, 163, 0, 0, - 1208, 103, 297, 0, 226, 0, 1208, 151, 0, 158, + /* + * Check whether provided parameters are enough + * to deduce all others. The following incomplete + * parameter sets for private keys are supported: + * + * (1) P, Q missing. + * (2) D and potentially N missing. + * + */ - 164, 171, 1208, 1208, 0, 0, 0, 0, 124, 0, - 1208, 1208, 1208, 180, 1208, 0, 196, 199, 283, 0, - 192, 1208, 0, 0, 1208, 0, 212, 215, 276, 0, - 218, 241, 1208, 268, 1208, 261, 0, 0, 0, 0, - 0, 1208, 270, 250, 0, 241, 254, 257, 259, 260, - 0, 237, 0, 0, 262, 0, 267, 0, 1208, 194, - 160, 188, 1208, 1208, 282, 1208, 252, 291, 0, 296, - 1208, 251, 299, 305, 1208, 235, 314, 224, 0, 0, - 0, 230, 0, 209, 319, 219, 322, 0, 201, 0, - 0, 328, 335, 341, 344, 348, 357, 361, 364, 370, - - 377, 383, 386, 1208, 0, 0, 1208, 199, 390, 399, - 403, 406, 167, 0, 0, 412, 419, 425, 428, 434, - 441, 447, 450, 454, 463, 467, 470, 476, 485, 489, - 0, 0, 151, 492, 498, 505, 514, 518, 140, 0, - 0, 521, 527, 534, 0, 1208, 128, 540, 125, 0, - 1208, 0, 543, 548, 0, 0, 557, 0, 113, 562, - 0, 99, 0, 0, 55, 571, 42, 576, 0, 1208, - 585, 590, 599, 604, 1208, 613, 618, 627, 632, 641, - 646, 655, 660, 669, 674, 683, 688, 697, 702, 711, - 0, 716, 0, 1208, 730, 741, 752, 763, 774, 785, - - 796, 807, 818, 829, 838, 841, 847, 857, 868, 879, - 890, 901, 911, 922, 933, 940, 946, 956, 965, 970, - 970, 972, 974, 979, 989, 1000, 1004, 1006, 1015, 1026, - 1037, 1041, 1043, 1045, 1054, 1058, 1060, 1069, 1080, 1091, - 1095, 1097, 1106, 1110, 1112, 1114, 1116, 1118, 1120, 1122, - 1124, 1126, 1128, 1130, 1139, 1150, 1154, 1163, 1174, 1185, - 1196 - } ; + n_missing = have_P && have_Q && have_D && have_E; + pq_missing = have_N && !have_P && !have_Q && have_D && have_E; + d_missing = have_P && have_Q && !have_D && have_E; + is_pub = have_N && !have_P && !have_Q && !have_D && have_E; -static const flex_int16_t yy_def[362] = - { 0, - 294, 1, 295, 295, 296, 296, 297, 297, 298, 298, - 299, 299, 300, 300, 301, 301, 297, 297, 302, 302, - 300, 300, 303, 303, 304, 304, 294, 294, 294, 294, - 305, 294, 306, 305, 305, 294, 294, 305, 305, 294, - 305, 294, 294, 305, 305, 305, 294, 307, 307, 307, - 307, 307, 307, 308, 294, 309, 309, 294, 294, 310, - 294, 311, 294, 312, 312, 294, 313, 314, 294, 315, - 315, 316, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 305, 305, - 294, 294, 317, 305, 318, 305, 294, 294, 319, 294, - - 294, 294, 294, 294, 305, 305, 305, 305, 294, 307, - 294, 294, 294, 294, 294, 308, 294, 294, 294, 309, - 294, 294, 320, 310, 294, 311, 294, 294, 294, 312, - 294, 294, 294, 294, 294, 294, 321, 322, 323, 314, - 315, 294, 324, 294, 325, 294, 294, 294, 294, 294, - 326, 294, 327, 328, 317, 318, 318, 319, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 329, 320, 294, - 294, 294, 330, 294, 294, 294, 331, 294, 332, 333, - 334, 324, 325, 294, 294, 294, 335, 326, 294, 336, - 337, 338, 329, 329, 329, 339, 330, 330, 330, 340, - - 331, 331, 331, 294, 341, 342, 294, 294, 343, 335, - 335, 335, 294, 344, 345, 338, 338, 294, 338, 329, - 339, 339, 294, 339, 330, 340, 340, 294, 340, 331, - 346, 347, 294, 343, 343, 294, 343, 335, 294, 348, - 349, 338, 339, 340, 350, 294, 294, 343, 294, 351, - 294, 352, 294, 294, 353, 354, 294, 355, 294, 294, - 356, 294, 357, 347, 294, 358, 294, 359, 349, 294, - 358, 358, 360, 358, 294, 359, 359, 361, 359, 358, - 358, 294, 358, 358, 359, 359, 294, 359, 359, 360, - 355, 361, 356, 0, 294, 294, 294, 294, 294, 294, - - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294 - } ; + /* These three alternatives are mutually exclusive */ + is_priv = n_missing || pq_missing || d_missing; -static const flex_int16_t yy_nxt[1247] = - { 0, - 28, 29, 30, 29, 31, 32, 33, 34, 35, 36, - 37, 38, 34, 39, 40, 41, 42, 42, 43, 44, - 45, 46, 47, 35, 48, 49, 48, 48, 50, 48, - 51, 48, 48, 52, 53, 28, 52, 53, 57, 86, - 71, 57, 57, 65, 72, 58, 57, 57, 86, 59, - 66, 275, 65, 57, 57, 57, 71, 57, 57, 66, - 72, 57, 57, 95, 270, 58, 57, 57, 103, 59, - 104, 96, 87, 57, 57, 57, 67, 57, 88, 88, - 88, 87, 88, 88, 88, 67, 75, 76, 75, 91, - 97, 121, 98, 98, 100, 122, 101, 101, 77, 92, + if( !is_priv && !is_pub ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - 92, 105, 106, 109, 109, 117, 118, 118, 102, 144, - 144, 144, 268, 127, 128, 128, 136, 119, 78, 92, - 92, 78, 75, 76, 75, 129, 266, 131, 132, 132, - 131, 132, 132, 137, 77, 133, 138, 139, 133, 134, - 109, 109, 134, 144, 144, 144, 150, 150, 150, 150, - 150, 150, 153, 254, 78, 154, 253, 78, 81, 82, - 81, 147, 148, 148, 88, 88, 88, 98, 98, 133, - 83, 249, 159, 149, 160, 160, 162, 162, 100, 102, - 101, 101, 247, 161, 161, 163, 102, 162, 162, 164, - 84, 239, 102, 84, 81, 82, 81, 117, 118, 118, - - 165, 165, 165, 121, 162, 162, 83, 122, 166, 119, - 160, 160, 167, 127, 128, 128, 170, 170, 170, 131, - 132, 132, 102, 233, 171, 129, 84, 213, 172, 84, - 157, 134, 209, 157, 157, 208, 142, 157, 157, 157, - 204, 157, 174, 174, 174, 157, 157, 157, 200, 157, - 175, 144, 144, 144, 176, 147, 148, 148, 185, 185, - 185, 150, 150, 150, 196, 192, 175, 149, 91, 189, - 186, 157, 187, 184, 157, 157, 142, 178, 157, 157, - 157, 177, 157, 165, 165, 165, 157, 157, 157, 173, - 157, 166, 194, 118, 118, 167, 168, 170, 170, 170, - - 198, 128, 128, 91, 195, 171, 174, 174, 174, 172, - 152, 151, 199, 146, 175, 202, 132, 132, 176, 145, - 185, 185, 185, 211, 148, 148, 125, 203, 175, 217, - 218, 218, 186, 142, 125, 212, 194, 118, 118, 123, - 115, 219, 194, 118, 118, 194, 118, 118, 195, 222, - 223, 223, 114, 113, 195, 112, 111, 220, 198, 128, - 128, 224, 198, 128, 128, 198, 128, 128, 108, 107, - 199, 227, 228, 228, 199, 99, 94, 225, 202, 132, - 132, 90, 294, 229, 202, 132, 132, 202, 132, 132, - 203, 235, 236, 236, 79, 79, 203, 73, 73, 230, - - 211, 148, 148, 237, 211, 148, 148, 211, 148, 148, - 69, 69, 212, 217, 218, 218, 212, 63, 63, 238, - 217, 218, 218, 61, 61, 219, 165, 165, 165, 217, - 218, 218, 219, 55, 166, 194, 118, 118, 167, 55, - 294, 242, 222, 223, 223, 294, 294, 220, 222, 223, - 223, 170, 170, 170, 224, 222, 223, 223, 294, 171, - 224, 294, 294, 172, 198, 128, 128, 243, 227, 228, - 228, 227, 228, 228, 294, 294, 225, 174, 174, 174, - 229, 294, 294, 229, 294, 175, 227, 228, 228, 176, - 202, 132, 132, 235, 236, 236, 294, 294, 244, 235, - - 236, 236, 230, 294, 294, 237, 185, 185, 185, 294, - 294, 237, 294, 294, 175, 235, 236, 236, 186, 211, - 148, 148, 217, 218, 218, 294, 294, 248, 222, 223, - 223, 238, 294, 294, 242, 227, 228, 228, 294, 294, - 243, 235, 236, 236, 257, 257, 257, 244, 294, 260, - 260, 260, 258, 248, 294, 294, 259, 261, 257, 257, - 257, 262, 294, 260, 260, 260, 258, 294, 294, 294, - 259, 261, 272, 257, 257, 262, 294, 277, 260, 260, - 273, 294, 294, 294, 274, 278, 272, 257, 257, 279, - 294, 272, 257, 257, 273, 294, 294, 294, 274, 273, - - 281, 282, 282, 274, 294, 272, 257, 257, 273, 294, - 294, 294, 283, 273, 277, 260, 260, 284, 294, 277, - 260, 260, 278, 294, 294, 294, 279, 278, 286, 287, - 287, 279, 294, 277, 260, 260, 278, 294, 294, 294, - 288, 278, 272, 257, 257, 289, 294, 272, 257, 257, - 290, 294, 294, 294, 274, 290, 257, 257, 257, 274, - 294, 272, 257, 257, 291, 294, 294, 294, 259, 290, - 272, 257, 257, 284, 294, 277, 260, 260, 273, 294, - 294, 294, 284, 292, 277, 260, 260, 279, 294, 260, - 260, 260, 292, 294, 294, 294, 279, 293, 277, 260, - - 260, 262, 294, 277, 260, 260, 292, 294, 294, 294, - 289, 278, 281, 282, 282, 289, 294, 286, 287, 287, - 273, 294, 294, 294, 283, 278, 294, 294, 294, 288, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 56, 56, 56, 56, 56, 56, 56, 56, 56, - 56, 56, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 60, 60, 62, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 62, 64, 64, 64, 64, 64, 64, - 64, 64, 64, 64, 64, 68, 68, 68, 68, 68, - 68, 68, 68, 68, 68, 68, 70, 70, 70, 70, + /* + * Step 1: Deduce N if P, Q are provided. + */ - 70, 70, 70, 70, 70, 70, 70, 74, 74, 74, - 74, 74, 74, 74, 74, 74, 74, 74, 80, 80, - 80, 80, 80, 80, 80, 80, 80, 80, 80, 85, - 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, - 89, 294, 294, 294, 89, 93, 294, 294, 93, 93, - 93, 110, 294, 294, 110, 110, 110, 116, 116, 116, - 116, 116, 294, 116, 116, 116, 116, 116, 120, 120, - 120, 120, 120, 120, 294, 120, 120, 120, 120, 124, - 124, 124, 294, 124, 124, 124, 124, 124, 124, 124, - 126, 126, 126, 126, 126, 294, 126, 126, 126, 126, - - 126, 130, 130, 130, 130, 130, 294, 130, 130, 130, - 130, 135, 135, 135, 135, 135, 135, 135, 135, 135, - 135, 135, 140, 140, 140, 140, 140, 294, 140, 140, - 140, 140, 140, 141, 141, 141, 141, 294, 141, 141, - 141, 141, 141, 141, 143, 294, 294, 294, 143, 143, - 155, 294, 294, 155, 155, 155, 156, 294, 156, 156, - 156, 156, 156, 156, 156, 156, 156, 158, 294, 294, - 294, 158, 169, 294, 294, 294, 169, 179, 179, 180, - 180, 181, 181, 182, 294, 294, 182, 182, 182, 183, - 294, 183, 183, 183, 183, 183, 183, 183, 183, 183, - - 188, 294, 188, 188, 188, 188, 188, 188, 188, 188, - 188, 190, 190, 191, 191, 193, 193, 193, 193, 193, - 193, 193, 193, 193, 193, 193, 197, 197, 197, 197, - 197, 197, 197, 197, 197, 197, 197, 201, 201, 201, - 201, 201, 201, 201, 201, 201, 201, 201, 205, 205, - 206, 206, 207, 207, 210, 210, 210, 210, 210, 210, - 210, 210, 210, 210, 210, 214, 214, 215, 215, 216, - 216, 216, 216, 216, 216, 216, 216, 216, 216, 216, - 221, 221, 221, 221, 221, 221, 221, 221, 221, 221, - 221, 226, 226, 226, 226, 226, 226, 226, 226, 226, - - 226, 226, 231, 231, 232, 232, 234, 234, 234, 234, - 234, 234, 234, 234, 234, 234, 234, 240, 240, 241, - 241, 245, 245, 246, 246, 250, 250, 251, 251, 252, - 252, 255, 255, 256, 256, 263, 263, 264, 264, 265, - 265, 265, 265, 265, 294, 265, 265, 265, 265, 265, - 267, 267, 267, 267, 267, 294, 267, 267, 267, 267, - 267, 269, 269, 271, 271, 271, 271, 271, 271, 271, - 271, 271, 271, 271, 276, 276, 276, 276, 276, 276, - 276, 276, 276, 276, 276, 280, 280, 280, 280, 280, - 280, 280, 280, 280, 280, 280, 285, 285, 285, 285, - - 285, 285, 285, 285, 285, 285, 285, 27, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294 - } ; + if( !have_N && have_P && have_Q ) + { + if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, + &ctx->Q ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } -static const flex_int16_t yy_chk[1247] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 5, 25, - 15, 5, 5, 11, 15, 5, 5, 5, 26, 5, - 11, 267, 12, 5, 5, 5, 16, 5, 6, 12, - 16, 6, 6, 39, 265, 6, 6, 6, 43, 6, - 43, 39, 25, 6, 6, 6, 11, 6, 29, 29, - 29, 26, 30, 30, 30, 12, 19, 19, 19, 33, - 40, 58, 40, 40, 42, 58, 42, 42, 19, 33, + ctx->len = mbedtls_mpi_size( &ctx->N ); + } - 33, 44, 44, 47, 47, 55, 55, 55, 42, 75, - 75, 75, 262, 63, 63, 63, 67, 55, 19, 92, - 92, 19, 20, 20, 20, 63, 259, 66, 66, 66, - 69, 69, 69, 67, 20, 66, 67, 67, 69, 66, - 109, 109, 69, 76, 76, 76, 81, 81, 81, 82, - 82, 82, 87, 249, 20, 87, 247, 20, 23, 23, - 23, 79, 79, 79, 88, 88, 88, 98, 98, 79, - 23, 239, 100, 79, 100, 100, 161, 161, 101, 98, - 101, 101, 233, 102, 102, 114, 100, 102, 102, 114, - 23, 213, 101, 23, 24, 24, 24, 117, 117, 117, - - 118, 118, 118, 121, 162, 162, 24, 121, 118, 117, - 160, 160, 118, 127, 127, 127, 128, 128, 128, 131, - 131, 131, 160, 208, 128, 127, 24, 189, 128, 24, - 95, 131, 186, 95, 95, 184, 182, 95, 95, 95, - 178, 95, 132, 132, 132, 95, 95, 95, 176, 95, - 132, 144, 144, 144, 132, 147, 147, 147, 148, 148, - 148, 150, 150, 150, 172, 167, 148, 147, 155, 152, - 148, 157, 149, 146, 157, 157, 143, 136, 157, 157, - 157, 134, 157, 165, 165, 165, 157, 157, 157, 129, - 157, 165, 168, 168, 168, 165, 119, 170, 170, 170, - - 173, 173, 173, 93, 168, 170, 174, 174, 174, 170, - 84, 83, 173, 78, 174, 177, 177, 177, 174, 77, - 185, 185, 185, 187, 187, 187, 73, 177, 185, 192, - 192, 192, 185, 72, 61, 187, 193, 193, 193, 59, - 53, 192, 194, 194, 194, 195, 195, 195, 193, 196, - 196, 196, 52, 51, 194, 50, 49, 195, 197, 197, - 197, 196, 198, 198, 198, 199, 199, 199, 46, 45, - 197, 200, 200, 200, 198, 41, 38, 199, 201, 201, - 201, 31, 27, 200, 202, 202, 202, 203, 203, 203, - 201, 209, 209, 209, 22, 21, 202, 18, 17, 203, - - 210, 210, 210, 209, 211, 211, 211, 212, 212, 212, - 14, 13, 210, 216, 216, 216, 211, 10, 9, 212, - 217, 217, 217, 8, 7, 216, 218, 218, 218, 219, - 219, 219, 217, 4, 218, 220, 220, 220, 218, 3, - 0, 219, 221, 221, 221, 0, 0, 220, 222, 222, - 222, 223, 223, 223, 221, 224, 224, 224, 0, 223, - 222, 0, 0, 223, 225, 225, 225, 224, 226, 226, - 226, 227, 227, 227, 0, 0, 225, 228, 228, 228, - 226, 0, 0, 227, 0, 228, 229, 229, 229, 228, - 230, 230, 230, 234, 234, 234, 0, 0, 229, 235, - - 235, 235, 230, 0, 0, 234, 236, 236, 236, 0, - 0, 235, 0, 0, 236, 237, 237, 237, 236, 238, - 238, 238, 242, 242, 242, 0, 0, 237, 243, 243, - 243, 238, 0, 0, 242, 244, 244, 244, 0, 0, - 243, 248, 248, 248, 253, 253, 253, 244, 0, 254, - 254, 254, 253, 248, 0, 0, 253, 254, 257, 257, - 257, 254, 0, 260, 260, 260, 257, 0, 0, 0, - 257, 260, 266, 266, 266, 260, 0, 268, 268, 268, - 266, 0, 0, 0, 266, 268, 271, 271, 271, 268, - 0, 272, 272, 272, 271, 0, 0, 0, 271, 272, - - 273, 273, 273, 272, 0, 274, 274, 274, 273, 0, - 0, 0, 273, 274, 276, 276, 276, 274, 0, 277, - 277, 277, 276, 0, 0, 0, 276, 277, 278, 278, - 278, 277, 0, 279, 279, 279, 278, 0, 0, 0, - 278, 279, 280, 280, 280, 279, 0, 281, 281, 281, - 280, 0, 0, 0, 280, 281, 282, 282, 282, 281, - 0, 283, 283, 283, 282, 0, 0, 0, 282, 283, - 284, 284, 284, 283, 0, 285, 285, 285, 284, 0, - 0, 0, 284, 285, 286, 286, 286, 285, 0, 287, - 287, 287, 286, 0, 0, 0, 286, 287, 288, 288, - - 288, 287, 0, 289, 289, 289, 288, 0, 0, 0, - 288, 289, 290, 290, 290, 289, 0, 292, 292, 292, - 290, 0, 0, 0, 290, 292, 0, 0, 0, 292, - 295, 295, 295, 295, 295, 295, 295, 295, 295, 295, - 295, 296, 296, 296, 296, 296, 296, 296, 296, 296, - 296, 296, 297, 297, 297, 297, 297, 297, 297, 297, - 297, 297, 297, 298, 298, 298, 298, 298, 298, 298, - 298, 298, 298, 298, 299, 299, 299, 299, 299, 299, - 299, 299, 299, 299, 299, 300, 300, 300, 300, 300, - 300, 300, 300, 300, 300, 300, 301, 301, 301, 301, - - 301, 301, 301, 301, 301, 301, 301, 302, 302, 302, - 302, 302, 302, 302, 302, 302, 302, 302, 303, 303, - 303, 303, 303, 303, 303, 303, 303, 303, 303, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 305, 0, 0, 0, 305, 306, 0, 0, 306, 306, - 306, 307, 0, 0, 307, 307, 307, 308, 308, 308, - 308, 308, 0, 308, 308, 308, 308, 308, 309, 309, - 309, 309, 309, 309, 0, 309, 309, 309, 309, 310, - 310, 310, 0, 310, 310, 310, 310, 310, 310, 310, - 311, 311, 311, 311, 311, 0, 311, 311, 311, 311, - - 311, 312, 312, 312, 312, 312, 0, 312, 312, 312, - 312, 313, 313, 313, 313, 313, 313, 313, 313, 313, - 313, 313, 314, 314, 314, 314, 314, 0, 314, 314, - 314, 314, 314, 315, 315, 315, 315, 0, 315, 315, - 315, 315, 315, 315, 316, 0, 0, 0, 316, 316, - 317, 0, 0, 317, 317, 317, 318, 0, 318, 318, - 318, 318, 318, 318, 318, 318, 318, 319, 0, 0, - 0, 319, 320, 0, 0, 0, 320, 321, 321, 322, - 322, 323, 323, 324, 0, 0, 324, 324, 324, 325, - 0, 325, 325, 325, 325, 325, 325, 325, 325, 325, - - 326, 0, 326, 326, 326, 326, 326, 326, 326, 326, - 326, 327, 327, 328, 328, 329, 329, 329, 329, 329, - 329, 329, 329, 329, 329, 329, 330, 330, 330, 330, - 330, 330, 330, 330, 330, 330, 330, 331, 331, 331, - 331, 331, 331, 331, 331, 331, 331, 331, 332, 332, - 333, 333, 334, 334, 335, 335, 335, 335, 335, 335, - 335, 335, 335, 335, 335, 336, 336, 337, 337, 338, - 338, 338, 338, 338, 338, 338, 338, 338, 338, 338, - 339, 339, 339, 339, 339, 339, 339, 339, 339, 339, - 339, 340, 340, 340, 340, 340, 340, 340, 340, 340, - - 340, 340, 341, 341, 342, 342, 343, 343, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 344, 344, 345, - 345, 346, 346, 347, 347, 348, 348, 349, 349, 350, - 350, 351, 351, 352, 352, 353, 353, 354, 354, 355, - 355, 355, 355, 355, 0, 355, 355, 355, 355, 355, - 356, 356, 356, 356, 356, 0, 356, 356, 356, 356, - 356, 357, 357, 358, 358, 358, 358, 358, 358, 358, - 358, 358, 358, 358, 359, 359, 359, 359, 359, 359, - 359, 359, 359, 359, 359, 360, 360, 360, 360, 360, - 360, 360, 360, 360, 360, 360, 361, 361, 361, 361, - - 361, 361, 361, 361, 361, 361, 361, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 294, 294, 294, 294, 294 - } ; + /* + * Step 2: Deduce and verify all remaining core parameters. + */ -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -#line 1 "third_party/libpg_query/scan.l" + if( pq_missing ) + { + ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D, + &ctx->P, &ctx->Q ); + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); -#line 46 "third_party/libpg_query/scan.l" + } + else if( d_missing ) + { + if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P, + &ctx->Q, + &ctx->E, + &ctx->D ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } + } -/* LCOV_EXCL_START */ + /* + * Step 3: Deduce all additional parameters specific + * to our current RSA implementation. + */ -/* - * GUC variables. This is a DIRECT violation of the warning given at the - * head of gram.y, ie flex/bison code must not depend on any GUC variables; - * as such, changing their values can induce very unintuitive behavior. - * But we shall have to live with it until we can remove these variables. - */ +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && ! ( have_DP && have_DQ && have_QP ) ) + { + ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ); + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ -int backslash_quote = PG_BACKSLASH_QUOTE_SAFE_ENCODING; -bool escape_string_warning = true; -bool standard_conforming_strings = true; + /* + * Step 3: Basic sanity checks + */ -/* - * Set the type of YYSTYPE. - */ -#define YYSTYPE core_YYSTYPE + return( rsa_check_context( ctx, is_priv, 1 ) ); +} -/* - * Set the type of yyextra. All state variables used by the scanner should - * be in yyextra, *not* statically allocated. - */ -#define YY_EXTRA_TYPE core_yy_extra_type * +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ) +{ + int ret = 0; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); -/* - * Each call to yylex must set yylloc to the location of the found token - * (expressed as a byte offset from the start of the input text). - * When we parse a token that requires multiple lexer rules to process, - * this should be done in the first such rule, else yylloc will point - * into the middle of the token. - */ -#define SET_YYLLOC() (*(yylloc) = yytext - yyextra->scanbuf) + } -/* - * Advance yylloc by the given number of bytes. - */ -#define ADVANCE_YYLLOC(delta) ( *(yylloc) += (delta) ) + if( N != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) ); -#define startlit() ( yyextra->literallen = 0 ) -static void addlit(char *ytext, int yleng, core_yyscan_t yyscanner); -static void addlitchar(unsigned char ychar, core_yyscan_t yyscanner); -static char *litbufdup(core_yyscan_t yyscanner); -static char *litbuf_udeescape(unsigned char escape, core_yyscan_t yyscanner); -static unsigned char unescape_single_char(unsigned char c, core_yyscan_t yyscanner); -static int process_integer_literal(const char *token, YYSTYPE *lval); -static bool is_utf16_surrogate_first(pg_wchar c); -static bool is_utf16_surrogate_second(pg_wchar c); -static pg_wchar surrogate_pair_to_codepoint(pg_wchar first, pg_wchar second); -static void addunicode(pg_wchar c, yyscan_t yyscanner); -static bool check_uescapechar(unsigned char escape); + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) ); -#define yyerror(msg) scanner_yyerror(msg, yyscanner) + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) ); -#define lexer_errposition() scanner_errposition(*(yylloc), yyscanner) + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) ); -static void check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner); -static void check_escape_warning(core_yyscan_t yyscanner); + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) ); -/* - * Work around a bug in flex 2.5.35: it emits a couple of functions that - * it forgets to emit declarations for. Since we use -Wmissing-prototypes, - * this would cause warnings. Providing our own declarations should be - * harmless even when the bug gets fixed. - */ -extern int core_yyget_column(yyscan_t yyscanner); -extern void core_yyset_column(int column_no, yyscan_t yyscanner); +cleanup: -#line 1151 "third_party/libpg_query/src_backend_parser_scan.cpp" -#define YY_NO_INPUT 1 -/* - * OK, here is a short description of lex/flex rules behavior. - * The longest pattern which matches an input string is always chosen. - * For equal-length patterns, the first occurring in the rules list is chosen. - * INITIAL is the starting state, to which all non-conditional rules apply. - * Exclusive states change parsing rules while the state is active. When in - * an exclusive state, only those rules defined for that state apply. - * - * We use exclusive states for quoted strings, extended comments, - * and to eliminate parsing troubles for numeric strings. - * Exclusive states: - * bit string literal - * extended C-style comments - * delimited identifiers (double-quoted identifiers) - * hexadecimal numeric string - * standard quoted strings - * extended quoted strings (support backslash escape sequences) - * $foo$ quoted strings - * quoted identifier with Unicode escapes - * end of a quoted identifier with Unicode escapes, UESCAPE can follow - * quoted string with Unicode escapes - * end of a quoted string with Unicode escapes, UESCAPE can follow - * Unicode surrogate pair in extended quoted string - * - * Remember to add an <> case whenever you add a new exclusive state! - * The default one is probably not the right thing. - */ + return( ret ); +} + +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + /* Export all requested core parameters. */ + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) ) + { + return( ret ); + } + + return( 0 ); +} /* - * In order to make the world safe for Windows and Mac clients as well as - * Unix ones, we accept either \n or \r as a newline. A DOS-style \r\n - * sequence will be seen as two successive newlines, but that doesn't cause ' - * any problems. Comments that start with -- and extend to the next - * newline are treated as equivalent to a single whitespace character. - * - * NOTE a fine point: if there is no newline following --, we will absorb - * everything to the end of the input as a comment. This is correct. Older - * versions of Postgres failed to recognize -- as a comment if the input - * did not end with a newline. - * - * XXX perhaps \f (formfeed) should be treated as a newline as well? - * - * XXX if you change the set of whitespace characters, fix scanner_isspace() - * to agree, and see also the plpgsql lexer. - */ -/* - * SQL requires at least one newline in the whitespace separating - * string literals that are to be concatenated. Silly, but who are we - * to argue? Note that {whitespace_with_newline} should not have * after - * it, whereas {whitespace} should generally have a * after it... - */ -/* - * To ensure that {quotecontinue} can be scanned without having to back up - * if the full pattern isn't matched, we include trailing whitespace in - * {quotestop}. This matches all cases where {quotecontinue} fails to match, - * except for {quote} followed by whitespace and just one "-" (not two, - * which would start a {comment}). To cover that we have {quotefail}. - * The actions for {quotestop} and {quotefail} must throw back characters - * beyond the quote proper. - */ -/* Bit string - * It is tempting to scan the string for only those characters - * which are allowed. However, this leads to silently swallowed - * characters if illegal characters are included in the string. - * For example, if xbinside is [01] then B'ABCD' is interpreted - * as a zero-length string, and the ABCD' is lost! - * Better to pass the string forward and let the input routines - * validate the contents. - */ -/* Hexadecimal number */ -/* National character */ -/* Quoted string that allows backslash escapes */ -/* Extended quote - * xqdouble implements embedded quote, '''' - */ -/* $foo$ style quotes ("dollar quoting") - * The quoted string starts with $foo$ where "foo" is an optional string - * in the form of an identifier, except that it may not contain "$", - * and extends to the first occurrence of an identical string. - * There is *no* processing of the quoted text. - * - * {dolqfailed} is an error rule to avoid scanner backup when {dolqdelim} - * fails to match its trailing "$". - */ -/* Double quote - * Allows embedded spaces and other special characters into identifiers. - */ -/* Unicode escapes */ -/* error rule to avoid backup */ -/* Quoted identifier with Unicode escapes */ -/* Quoted string with Unicode escapes */ -/* Optional UESCAPE after a quoted string or identifier with Unicode escapes. */ -/* error rule to avoid backup */ -/* C-style comments - * - * The "extended comment" syntax closely resembles allowable operator syntax. - * The tricky part here is to get lex to recognize a string starting with - * slash-star as a comment, when interpreting it as an operator would produce - * a longer match --- remember lex will prefer a longer match! Also, if we - * have something like plus-slash-star, lex will think this is a 3-character - * operator whereas we want to see it as a + operator and a comment start. - * The solution is two-fold: - * 1. append {op_chars}* to xcstart so that it matches as much text as - * {operator} would. Then the tie-breaker (first matching rule of same - * length) ensures xcstart wins. We put back the extra stuff with yyless() - * in case it contains a star-slash that should terminate the comment. - * 2. In the operator rule, check for slash-star within the operator, and - * if found throw it back with yyless(). This handles the plus-slash-star - * problem. - * Dash-dash comments have similar interactions with the operator rule. - */ -/* Assorted special-case operators and operator-like tokens */ -/* " */ -/* - * These operator-like tokens (unlike the above ones) also match the {operator} - * rule, which means that they might be overridden by a longer match if they - * are followed by a comment start or a + or - character. Accordingly, if you - * add to this list, you must also add corresponding code to the {operator} - * block to return the correct token in such cases. (This is not needed in - * psqlscan.l since the token value is ignored there.) + * Export CRT parameters + * This must also be implemented if CRT is not used, for being able to + * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt + * can be used in this case. */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + int is_priv; + RSA_VALIDATE_RET( ctx != NULL ); + + /* Check if key is private or public */ + is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Export all requested blinding parameters. */ + if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) || + ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) || + ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } +#else + if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + DP, DQ, QP ) ) != 0 ) + { + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_BAD_INPUT_DATA, ret ) ); + } +#endif + + return( 0 ); +} + /* - * "self" is the set of chars that should be returned as single-character - * tokens. "op_chars" is the set of chars that can make up "Op" tokens, - * which can be one or more characters long (but if a single-char token - * appears in the "self" set, it is not to be returned as an Op). Note - * that the sets overlap, but each has some chars that are not in the other. - * - * If you change either set, adjust the character lists appearing in the - * rule for "operator"! - */ -/* we no longer allow unary minus in numbers. - * instead we pass it separately to parser. there it gets - * coerced via doNegate() -- Leon aug 20 1999 - * - * {decimalfail} is used because we would like "1..10" to lex as 1, dot_dot, 10. - * - * {realfail1} and {realfail2} are added to prevent the need for scanner - * backup when the {real} rule fails to match completely. + * Initialize an RSA context */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); + + ctx->padding = MBEDTLS_RSA_PKCS_V15; + ctx->hash_id = MBEDTLS_MD_NONE; + +#if defined(MBEDTLS_THREADING_C) + /* Set ctx->ver to nonzero to indicate that the mutex has been + * initialized and will need to be freed. */ + ctx->ver = 1; + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + /* - * Dollar quoted strings are totally opaque, and no escaping is done on them. - * Other quoted strings must allow some special characters such as single-quote - * and newline. - * Embedded single-quotes are implemented both in the SQL standard - * style of two adjacent single quotes "''" and in the Postgres/Java style - * of escaped-quote "\'". - * Other embedded escaped characters are matched explicitly and the leading - * backslash is dropped from the string. - * Note that xcstart must appear before operator, as explained above! - * Also whitespace (comment) must appear before operator. + * Set padding for an existing RSA context */ -#line 1305 "third_party/libpg_query/src_backend_parser_scan.cpp" - -#define INITIAL 0 -#define xb 1 -#define xc 2 -#define xd 3 -#define xh 4 -#define xe 5 -#define xq 6 -#define xdolq 7 -#define xui 8 -#define xuiend 9 -#define xus 10 -#define xusend 11 -#define xeu 12 +int mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + mbedtls_md_type_t hash_id ) +{ + switch( padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + break; +#endif -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + break; #endif + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } -/* Holds the entire state of the reentrant scanner. */ -struct yyguts_t + if( ( padding == MBEDTLS_RSA_PKCS_V21 ) && + ( hash_id != MBEDTLS_MD_NONE ) ) { + const mbedtls_md_info_t *md_info; - /* User-defined. Not touched by flex. */ - YY_EXTRA_TYPE yyextra_r; + md_info = mbedtls_md_info_from_type( hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } - /* The rest are the same as the globals declared in the non-reentrant scanner. */ - FILE *yyin_r, *yyout_r; - size_t yy_buffer_stack_top; /**< index of top of stack. */ - size_t yy_buffer_stack_max; /**< capacity of stack. */ - YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ - char yy_hold_char; - yy_size_t yy_n_chars; - yy_size_t yyleng_r; - char *yy_c_buf_p; - int yy_init; - int yy_start; - int yy_did_buffer_switch_on_eof; - int yy_start_stack_ptr; - int yy_start_stack_depth; - int *yy_start_stack; - yy_state_type yy_last_accepting_state; - char* yy_last_accepting_cpos; + ctx->padding = padding; + ctx->hash_id = hash_id; - int yylineno_r; - int yy_flex_debug_r; + return( 0 ); +} - char *yytext_r; - int yy_more_flag; - int yy_more_len; +/* + * Get length in bytes of RSA modulus + */ - YYSTYPE * yylval_r; +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ) +{ + return( ctx->len ); +} - YYLTYPE * yylloc_r; - }; /* end struct yyguts_t */ +#if defined(MBEDTLS_GENPRIME) -static int yy_init_globals ( yyscan_t yyscanner ); +/* + * Generate an RSA keypair + * + * This generation method follows the RSA key pair generation procedure of + * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_mpi H, G, L; + int prime_quality = 0; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( f_rng != NULL ); + + /* + * If the modulus is 1024 bit long or shorter, then the security strength of + * the RSA algorithm is less than or equal to 80 bits and therefore an error + * rate of 2^-80 is sufficient. + */ + if( nbits > 1024 ) + prime_quality = MBEDTLS_MPI_GEN_PRIME_FLAG_LOW_ERR; - /* This must go here because YYSTYPE and YYLTYPE are included - * from bison output in section 1.*/ - # define yylval yyg->yylval_r - - # define yylloc yyg->yylloc_r - -int yylex_init (yyscan_t* scanner); + mbedtls_mpi_init( &H ); + mbedtls_mpi_init( &G ); + mbedtls_mpi_init( &L ); -int yylex_init_extra ( YY_EXTRA_TYPE user_defined, yyscan_t* scanner); + if( nbits < 128 || exponent < 3 || nbits % 2 != 0 ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } -/* Accessor methods to globals. - These are made visible to non-reentrant scanners for convenience. */ + /* + * find primes P and Q with Q < P so that: + * 1. |P-Q| > 2^( nbits / 2 - 100 ) + * 2. GCD( E, (P-1)*(Q-1) ) == 1 + * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); -int yylex_destroy ( yyscan_t yyscanner ); + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, + prime_quality, f_rng, p_rng ) ); -int yyget_debug ( yyscan_t yyscanner ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, + prime_quality, f_rng, p_rng ) ); -void yyset_debug ( int debug_flag , yyscan_t yyscanner ); + /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); + if( mbedtls_mpi_bitlen( &H ) <= ( ( nbits >= 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) ) + continue; -YY_EXTRA_TYPE yyget_extra ( yyscan_t yyscanner ); + /* not required by any standards, but some users rely on the fact that P > Q */ + if( H.s < 0 ) + mbedtls_mpi_swap( &ctx->P, &ctx->Q ); -void yyset_extra ( YY_EXTRA_TYPE user_defined , yyscan_t yyscanner ); + /* Temporarily replace P,Q by P-1, Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) ); -FILE *yyget_in ( yyscan_t yyscanner ); + /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + continue; -void yyset_in ( FILE * _in_str , yyscan_t yyscanner ); + /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->P, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L, NULL, &H, &G ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &L ) ); -FILE *yyget_out ( yyscan_t yyscanner ); + if( mbedtls_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a)) + continue; -void yyset_out ( FILE * _out_str , yyscan_t yyscanner ); + break; + } + while( 1 ); - yy_size_t yyget_leng ( yyscan_t yyscanner ); + /* Restore P,Q */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) ); -char *yyget_text ( yyscan_t yyscanner ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); -int yyget_lineno ( yyscan_t yyscanner ); + ctx->len = mbedtls_mpi_size( &ctx->N ); -void yyset_lineno ( int _line_number , yyscan_t yyscanner ); +#if !defined(MBEDTLS_RSA_NO_CRT) + /* + * DP = D mod (P - 1) + * DQ = D mod (Q - 1) + * QP = Q^-1 mod P + */ + MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ -int yyget_column ( yyscan_t yyscanner ); + /* Double-check */ + MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) ); -void yyset_column ( int _column_no , yyscan_t yyscanner ); +cleanup: -YYSTYPE * yyget_lval ( yyscan_t yyscanner ); + mbedtls_mpi_free( &H ); + mbedtls_mpi_free( &G ); + mbedtls_mpi_free( &L ); -void yyset_lval ( YYSTYPE * yylval_param , yyscan_t yyscanner ); + if( ret != 0 ) + { + mbedtls_rsa_free( ctx ); - YYLTYPE *yyget_lloc ( yyscan_t yyscanner ); - - void yyset_lloc ( YYLTYPE * yylloc_param , yyscan_t yyscanner ); - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ + if( ( -ret & ~0x7f ) == 0 ) + ret = MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_KEY_GEN_FAILED, ret ); + return( ret ); + } -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int yywrap ( yyscan_t yyscanner ); -#else -extern int yywrap ( yyscan_t yyscanner ); -#endif -#endif + return( 0 ); +} -#ifndef YY_NO_UNPUT - -#endif +#endif /* MBEDTLS_GENPRIME */ -#ifndef yytext_ptr -static void yy_flex_strncpy ( char *, const char *, int , yyscan_t yyscanner); -#endif +/* + * Check a public RSA key + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE_RET( ctx != NULL ); -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen ( const char * , yyscan_t yyscanner); -#endif + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); -#ifndef YY_NO_INPUT -#ifdef __cplusplus -static int yyinput ( yyscan_t yyscanner ); -#else -static int input ( yyscan_t yyscanner ); -#endif + if( mbedtls_mpi_bitlen( &ctx->N ) < 128 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } -#endif + if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 || + mbedtls_mpi_bitlen( &ctx->E ) < 2 || + mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#ifdef __ia64__ -/* On IA-64, the buffer size is 16k, not 8k */ -#define YY_READ_BUF_SIZE 16384 -#else -#define YY_READ_BUF_SIZE 8192 -#endif /* __ia64__ */ -#endif + return( 0 ); +} -/* Copy whatever the last rule matched to the standard output. */ -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). +/* + * Check for the consistency of all fields in an RSA private key context */ -#define ECHO do { if (fwrite( yytext, (size_t) yyleng, 1, yyout )) {} } while (0) +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) +{ + RSA_VALIDATE_RET( ctx != NULL ); + + if( mbedtls_rsa_check_pubkey( ctx ) != 0 || + rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q, + &ctx->D, &ctx->E, NULL, NULL ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } #endif -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". + return( 0 ); +} + +/* + * Check if contexts holding a public and private key match */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ - { \ - int c = '*'; \ - yy_size_t n; \ - for ( n = 0; n < max_size && \ - (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else \ - { \ - errno=0; \ - while ( (result = (int) fread(buf, 1, (yy_size_t) max_size, yyin)) == 0 && ferror(yyin)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(yyin); \ - } \ - }\ -\ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ) +{ + RSA_VALIDATE_RET( pub != NULL ); + RSA_VALIDATE_RET( prv != NULL ); -#endif + if( mbedtls_rsa_check_pubkey( pub ) != 0 || + mbedtls_rsa_check_privkey( prv ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. + if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || + mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Do an RSA public key operation */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; + mbedtls_mpi T; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); #endif -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); #endif -/* end tables serialization structures and prototypes */ + mbedtls_mpi_free( &T ); -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. + if( ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_PUBLIC_FAILED, ret ) ); + + return( 0 ); +} + +/* + * Generate or update blinding values, see section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. */ -#ifndef YY_DECL -#define YY_DECL_IS_OURS 1 +static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count = 0; + mbedtls_mpi R; -extern int yylex \ - (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner); + mbedtls_mpi_init( &R ); -#define YY_DECL int yylex \ - (YYSTYPE * yylval_param, YYLTYPE * yylloc_param , yyscan_t yyscanner) -#endif /* !YY_DECL */ + if( ctx->Vf.p != NULL ) + { + /* We already have blinding values, just update them by squaring */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); -/* Code executed at the beginning of each rule, after yytext and yyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif + goto cleanup; + } -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK /*LINTED*/break; -#endif + /* Unblinding value: Vf = random number, invertible mod N */ + do { + if( count++ > 10 ) + { + ret = MBEDTLS_ERR_RSA_RNG_FAILED; + goto cleanup; + } -#define YY_RULE_SETUP \ - YY_USER_ACTION + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); -/** The main scanner function which does all the work. + /* Compute Vf^-1 as R * (R Vf)^-1 to avoid leaks from inv_mod. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, ctx->len - 1, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vf, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* At this point, Vi is invertible mod N if and only if both Vf and R + * are invertible mod N. If one of them isn't, we don't need to know + * which one, we just loop and choose new values for both of them. + * (Each iteration succeeds with overwhelming probability.) */ + ret = mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vi, &ctx->N ); + if( ret != 0 && ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + } while( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + /* Finish the computation of Vf^-1 = R * (R Vf)^-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + + /* Blinding value: Vi = Vf^(-e) mod N + * (Vi already contains Vf^-1 at this point) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); + + +cleanup: + mbedtls_mpi_free( &R ); + + return( ret ); +} + +/* + * Exponent blinding supposed to prevent side-channel attacks using multiple + * traces of measurements to recover the RSA key. The more collisions are there, + * the more bits of the key can be recovered. See [3]. + * + * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) + * observations on avarage. + * + * For example with 28 byte blinding to achieve 2 collisions the adversary has + * to make 2^112 observations on avarage. + * + * (With the currently (as of 2017 April) known best algorithms breaking 2048 + * bit RSA requires approximately as much time as trying out 2^112 random keys. + * Thus in this sense with 28 byte blinding the security is not reduced by + * side-channel attacks like the one in [3]) + * + * This countermeasure does not help if the key recovery is possible with a + * single trace. */ -YY_DECL +#define RSA_EXPONENT_BLINDING 28 + +/* + * Do an RSA private key operation + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ) { - yy_state_type yy_current_state; - char *yy_cp, *yy_bp; - int yy_act; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t olen; - yylval = yylval_param; + /* Temporary holding the result */ + mbedtls_mpi T; - yylloc = yylloc_param; + /* Temporaries holding P-1, Q-1 and the + * exponent blinding factor, respectively. */ + mbedtls_mpi P1, Q1, R; - if ( !yyg->yy_init ) - { - yyg->yy_init = 1; +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Temporaries holding the results mod p resp. mod q. */ + mbedtls_mpi TP, TQ; -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif + /* Temporaries holding the blinded exponents for + * the mod p resp. mod q computation (if used). */ + mbedtls_mpi DP_blind, DQ_blind; - if ( ! yyg->yy_start ) - yyg->yy_start = 1; /* first start state */ - if ( ! YY_CURRENT_BUFFER ) { - yyensure_buffer_stack (yyscanner); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); - } + /* Pointers to actual exponents to be used - either the unblinded + * or the blinded ones, depending on the presence of a PRNG. */ + mbedtls_mpi *DP = &ctx->DP; + mbedtls_mpi *DQ = &ctx->DQ; +#else + /* Temporary holding the blinded exponent (if used). */ + mbedtls_mpi D_blind; - yy_load_buffer_state( yyscanner ); - } + /* Pointer to actual exponent to be used - either the unblinded + * or the blinded one, depending on the presence of a PRNG. */ + mbedtls_mpi *D = &ctx->D; +#endif /* MBEDTLS_RSA_NO_CRT */ - { -#line 402 "third_party/libpg_query/scan.l" + /* Temporaries holding the initial input and the double + * checked result; should be the same in the end. */ + mbedtls_mpi I, C; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( output != NULL ); -#line 1594 "third_party/libpg_query/src_backend_parser_scan.cpp" + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ - { - yy_cp = yyg->yy_c_buf_p; + if( rsa_check_context( ctx, 1 /* private key checks */, + 1 /* blinding on */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } - /* Support of yytext. */ - *yy_cp = yyg->yy_hold_char; +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; + /* MPI Initialization */ + mbedtls_mpi_init( &T ); - yy_current_state = yyg->yy_start; -yy_match: - do - { - YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)] ; - if ( yy_accept[yy_current_state] ) - { - yyg->yy_last_accepting_state = yy_current_state; - yyg->yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 295 ) - yy_c = yy_meta[yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - ++yy_cp; - } - while ( yy_current_state != 294 ); - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; + mbedtls_mpi_init( &P1 ); + mbedtls_mpi_init( &Q1 ); + mbedtls_mpi_init( &R ); -yy_find_action: - yy_act = yy_accept[yy_current_state]; +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &D_blind ); +#else + mbedtls_mpi_init( &DP_blind ); + mbedtls_mpi_init( &DQ_blind ); +#endif - YY_DO_BEFORE_ACTION; +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ ); +#endif -do_action: /* This label is used only to access EOF actions. */ + mbedtls_mpi_init( &I ); + mbedtls_mpi_init( &C ); - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = yyg->yy_hold_char; - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; - goto yy_find_action; + /* End of MPI initialization */ -case 1: -/* rule 1 can match eol */ -YY_RULE_SETUP -#line 404 "third_party/libpg_query/scan.l" -{ - /* ignore */ - } - YY_BREAK -case 2: -YY_RULE_SETUP -#line 408 "third_party/libpg_query/scan.l" -{ - /* Set location in case of syntax error in comment */ - SET_YYLLOC(); - yyextra->xcdepth = 0; - BEGIN(xc); - /* Put back any characters past slash-star; see above */ - yyless(2); - } - YY_BREAK -case 3: -YY_RULE_SETUP -#line 417 "third_party/libpg_query/scan.l" -{ - (yyextra->xcdepth)++; - /* Put back any characters past slash-star; see above */ - yyless(2); - } - YY_BREAK -case 4: -YY_RULE_SETUP -#line 423 "third_party/libpg_query/scan.l" -{ - if (yyextra->xcdepth <= 0) - BEGIN(INITIAL); - else - (yyextra->xcdepth)--; - } - YY_BREAK -case 5: -/* rule 5 can match eol */ -YY_RULE_SETUP -#line 430 "third_party/libpg_query/scan.l" -{ - /* ignore */ - } - YY_BREAK -case 6: -YY_RULE_SETUP -#line 434 "third_party/libpg_query/scan.l" -{ - /* ignore */ - } - YY_BREAK -case 7: -YY_RULE_SETUP -#line 438 "third_party/libpg_query/scan.l" -{ - /* ignore */ - } - YY_BREAK -case YY_STATE_EOF(xc): -#line 442 "third_party/libpg_query/scan.l" -{ yyerror("unterminated /* comment"); } - YY_BREAK -case 8: -YY_RULE_SETUP -#line 444 "third_party/libpg_query/scan.l" -{ - /* Binary bit type. - * At some point we should simply pass the string - * forward to the parser and label it there. - * In the meantime, place a leading "b" on the string - * to mark it for the input routine as a binary string. - */ - SET_YYLLOC(); - BEGIN(xb); - startlit(); - addlitchar('b', yyscanner); - } - YY_BREAK -case 9: -/* rule 9 can match eol */ -#line 457 "third_party/libpg_query/scan.l" -case 10: -/* rule 10 can match eol */ -YY_RULE_SETUP -#line 457 "third_party/libpg_query/scan.l" -{ - yyless(1); - BEGIN(INITIAL); - yylval->str = litbufdup(yyscanner); - return BCONST; - } - YY_BREAK -case 11: -/* rule 11 can match eol */ -#line 464 "third_party/libpg_query/scan.l" -case 12: -/* rule 12 can match eol */ -YY_RULE_SETUP -#line 464 "third_party/libpg_query/scan.l" -{ - addlit(yytext, yyleng, yyscanner); - } - YY_BREAK -case 13: -/* rule 13 can match eol */ -#line 468 "third_party/libpg_query/scan.l" -case 14: -/* rule 14 can match eol */ -YY_RULE_SETUP -#line 468 "third_party/libpg_query/scan.l" -{ - /* ignore */ - } - YY_BREAK -case YY_STATE_EOF(xb): -#line 471 "third_party/libpg_query/scan.l" -{ yyerror("unterminated bit string literal"); } - YY_BREAK -case 15: -YY_RULE_SETUP -#line 473 "third_party/libpg_query/scan.l" -{ - /* Hexadecimal bit type. - * At some point we should simply pass the string - * forward to the parser and label it there. - * In the meantime, place a leading "x" on the string - * to mark it for the input routine as a hex string. - */ - SET_YYLLOC(); - BEGIN(xh); - startlit(); - addlitchar('x', yyscanner); - } - YY_BREAK -case 16: -/* rule 16 can match eol */ -#line 486 "third_party/libpg_query/scan.l" -case 17: -/* rule 17 can match eol */ -YY_RULE_SETUP -#line 486 "third_party/libpg_query/scan.l" -{ - yyless(1); - BEGIN(INITIAL); - yylval->str = litbufdup(yyscanner); - return XCONST; - } - YY_BREAK -case YY_STATE_EOF(xh): -#line 492 "third_party/libpg_query/scan.l" -{ yyerror("unterminated hexadecimal string literal"); } - YY_BREAK -case 18: -YY_RULE_SETUP -#line 494 "third_party/libpg_query/scan.l" -{ - /* National character. - * We will pass this along as a normal character string, - * but preceded with an internally-generated "NCHAR". - */ - const PGScanKeyword *keyword; + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } - SET_YYLLOC(); - yyless(1); /* eat only 'n' this time */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) ); - keyword = ScanKeywordLookup("nchar", - yyextra->keywords, - yyextra->num_keywords); - if (keyword != NULL) - { - yylval->keyword = keyword->name; - return keyword->value; - } - else - { - /* If NCHAR isn't a keyword, just return "n" */ - yylval->str = pstrdup("n"); - return IDENT; - } - } - YY_BREAK -case 19: -YY_RULE_SETUP -#line 520 "third_party/libpg_query/scan.l" -{ - yyextra->warn_on_first_escape = true; - yyextra->saw_non_ascii = false; - SET_YYLLOC(); - if (yyextra->standard_conforming_strings) - BEGIN(xq); - else - BEGIN(xe); - startlit(); - } - YY_BREAK -case 20: -YY_RULE_SETUP -#line 530 "third_party/libpg_query/scan.l" -{ - yyextra->warn_on_first_escape = false; - yyextra->saw_non_ascii = false; - SET_YYLLOC(); - BEGIN(xe); - startlit(); - } - YY_BREAK -case 21: -YY_RULE_SETUP -#line 537 "third_party/libpg_query/scan.l" -{ - SET_YYLLOC(); - if (!yyextra->standard_conforming_strings) - ereport(ERROR, - (errcode(PG_ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("unsafe use of string constant with Unicode escapes"), - errdetail("String constants with Unicode escapes cannot be used when standard_conforming_strings is off."), - lexer_errposition())); - BEGIN(xus); - startlit(); - } - YY_BREAK -case 22: -/* rule 22 can match eol */ -#line 549 "third_party/libpg_query/scan.l" -case 23: -/* rule 23 can match eol */ -YY_RULE_SETUP -#line 549 "third_party/libpg_query/scan.l" -{ - yyless(1); - BEGIN(INITIAL); - /* - * check that the data remains valid if it might have been - * made invalid by unescaping any chars. - */ - if (yyextra->saw_non_ascii) - pg_verifymbstr(yyextra->literalbuf, - yyextra->literallen, - false); - yylval->str = litbufdup(yyscanner); - return SCONST; - } - YY_BREAK -case 24: -/* rule 24 can match eol */ -#line 564 "third_party/libpg_query/scan.l" -case 25: -/* rule 25 can match eol */ -YY_RULE_SETUP -#line 564 "third_party/libpg_query/scan.l" -{ - /* throw back all but the quote */ - yyless(1); - /* xusend state looks for possible UESCAPE */ - BEGIN(xusend); - } - YY_BREAK -case 26: -/* rule 26 can match eol */ -YY_RULE_SETUP -#line 570 "third_party/libpg_query/scan.l" -{ - /* stay in xusend state over whitespace */ - } - YY_BREAK -case YY_STATE_EOF(xusend): -#line 573 "third_party/libpg_query/scan.l" -case 27: -/* rule 27 can match eol */ -#line 575 "third_party/libpg_query/scan.l" -case 28: -/* rule 28 can match eol */ -YY_RULE_SETUP -#line 575 "third_party/libpg_query/scan.l" -{ - /* no UESCAPE after the quote, throw back everything */ - yyless(0); - BEGIN(INITIAL); - yylval->str = litbuf_udeescape('\\', yyscanner); - return SCONST; - } - YY_BREAK -case 29: -/* rule 29 can match eol */ -YY_RULE_SETUP -#line 582 "third_party/libpg_query/scan.l" -{ - /* found UESCAPE after the end quote */ - BEGIN(INITIAL); - if (!check_uescapechar(yytext[yyleng - 2])) - { - SET_YYLLOC(); - ADVANCE_YYLLOC(yyleng - 2); - yyerror("invalid Unicode escape character"); - } - yylval->str = litbuf_udeescape(yytext[yyleng - 2], - yyscanner); - return SCONST; - } - YY_BREAK -case 30: -YY_RULE_SETUP -#line 595 "third_party/libpg_query/scan.l" -{ - addlitchar('\'', yyscanner); - } - YY_BREAK -case 31: -/* rule 31 can match eol */ -YY_RULE_SETUP -#line 598 "third_party/libpg_query/scan.l" -{ - addlit(yytext, yyleng, yyscanner); - } - YY_BREAK -case 32: -/* rule 32 can match eol */ -YY_RULE_SETUP -#line 601 "third_party/libpg_query/scan.l" -{ - addlit(yytext, yyleng, yyscanner); - } - YY_BREAK -case 33: -YY_RULE_SETUP -#line 604 "third_party/libpg_query/scan.l" -{ - pg_wchar c = strtoul(yytext + 2, NULL, 16); + /* + * Blinding + * T = T * Vi mod N + */ + MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); - check_escape_warning(yyscanner); + /* + * Exponent blinding + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - if (is_utf16_surrogate_first(c)) - { - yyextra->utf16_first_part = c; - BEGIN(xeu); - } - else if (is_utf16_surrogate_second(c)) - yyerror("invalid Unicode surrogate pair"); - else - addunicode(c, yyscanner); - } - YY_BREAK -case 34: -YY_RULE_SETUP -#line 619 "third_party/libpg_query/scan.l" -{ - pg_wchar c = strtoul(yytext + 2, NULL, 16); +#if defined(MBEDTLS_RSA_NO_CRT) + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); - if (!is_utf16_surrogate_second(c)) - yyerror("invalid Unicode surrogate pair"); + D = &D_blind; +#else + /* + * DP_blind = ( P - 1 ) * R + DP + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, + &ctx->DP ) ); - c = surrogate_pair_to_codepoint(yyextra->utf16_first_part, c); + DP = &DP_blind; - addunicode(c, yyscanner); + /* + * DQ_blind = ( Q - 1 ) * R + DQ + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, + &ctx->DQ ) ); - BEGIN(xe); - } - YY_BREAK -case 35: -YY_RULE_SETUP -#line 631 "third_party/libpg_query/scan.l" -{ yyerror("invalid Unicode surrogate pair"); } - YY_BREAK -case 36: -/* rule 36 can match eol */ -YY_RULE_SETUP -#line 632 "third_party/libpg_query/scan.l" -{ yyerror("invalid Unicode surrogate pair"); } - YY_BREAK -case YY_STATE_EOF(xeu): -#line 633 "third_party/libpg_query/scan.l" -{ yyerror("invalid Unicode surrogate pair"); } - YY_BREAK -case 37: -YY_RULE_SETUP -#line 634 "third_party/libpg_query/scan.l" -{ - ereport(ERROR, - (errcode(PG_ERRCODE_INVALID_ESCAPE_SEQUENCE), - errmsg("invalid Unicode escape"), - errhint("Unicode escapes must be \\uXXXX or \\UXXXXXXXX."), - lexer_errposition())); - } - YY_BREAK -case 38: -/* rule 38 can match eol */ -YY_RULE_SETUP -#line 641 "third_party/libpg_query/scan.l" -{ - // if (yytext[1] == '\'') - // { - // if (yyextra->backslash_quote == PG_BACKSLASH_QUOTE_OFF || - // (yyextra->backslash_quote == PG_BACKSLASH_QUOTE_SAFE_ENCODING && - // PG_ENCODING_IS_CLIENT_ONLY(pg_get_client_encoding()))) - // ereport(ERROR, - // (errcode(PG_ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), - // errmsg("unsafe use of \\' in a string literal"), - // errhint("Use '' to write quotes in strings. \\' is insecure in client-only encodings."), - // lexer_errposition())); - // } - check_string_escape_warning(yytext[1], yyscanner); - addlitchar(unescape_single_char(yytext[1], yyscanner), - yyscanner); - } - YY_BREAK -case 39: -YY_RULE_SETUP -#line 657 "third_party/libpg_query/scan.l" -{ - unsigned char c = strtoul(yytext + 1, NULL, 8); + DQ = &DQ_blind; +#endif /* MBEDTLS_RSA_NO_CRT */ - check_escape_warning(yyscanner); - addlitchar(c, yyscanner); - if (c == '\0' || IS_HIGHBIT_SET(c)) - yyextra->saw_non_ascii = true; - } - YY_BREAK -case 40: -YY_RULE_SETUP -#line 665 "third_party/libpg_query/scan.l" -{ - unsigned char c = strtoul(yytext + 2, NULL, 16); +#if defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); +#else + /* + * Faster decryption using the CRT + * + * TP = input ^ dP mod P + * TQ = input ^ dQ mod Q + */ - check_escape_warning(yyscanner); - addlitchar(c, yyscanner); - if (c == '\0' || IS_HIGHBIT_SET(c)) - yyextra->saw_non_ascii = true; - } - YY_BREAK -case 41: -/* rule 41 can match eol */ -YY_RULE_SETUP -#line 673 "third_party/libpg_query/scan.l" -{ - /* ignore */ - } - YY_BREAK -case 42: -YY_RULE_SETUP -#line 676 "third_party/libpg_query/scan.l" -{ - /* This is only needed for \ just before EOF */ - addlitchar(yytext[0], yyscanner); - } - YY_BREAK -case YY_STATE_EOF(xq): -case YY_STATE_EOF(xe): -case YY_STATE_EOF(xus): -#line 680 "third_party/libpg_query/scan.l" -{ yyerror("unterminated quoted string"); } - YY_BREAK -case 43: -YY_RULE_SETUP -#line 682 "third_party/libpg_query/scan.l" -{ - SET_YYLLOC(); - yyextra->dolqstart = pstrdup(yytext); - BEGIN(xdolq); - startlit(); - } - YY_BREAK -case 44: -YY_RULE_SETUP -#line 688 "third_party/libpg_query/scan.l" -{ - SET_YYLLOC(); - /* throw back all but the initial "$" */ - yyless(1); - /* and treat it as {other} */ - return yytext[0]; - } - YY_BREAK -case 45: -YY_RULE_SETUP -#line 695 "third_party/libpg_query/scan.l" -{ - if (strcmp(yytext, yyextra->dolqstart) == 0) - { - pfree(yyextra->dolqstart); - yyextra->dolqstart = NULL; - BEGIN(INITIAL); - yylval->str = litbufdup(yyscanner); - return SCONST; - } - else - { - /* - * When we fail to match $...$ to dolqstart, transfer - * the $... part to the output, but put back the final - * $ for rescanning. Consider $delim$...$junk$delim$ - */ - addlit(yytext, yyleng - 1, yyscanner); - yyless(yyleng - 1); - } - } - YY_BREAK -case 46: -/* rule 46 can match eol */ -YY_RULE_SETUP -#line 715 "third_party/libpg_query/scan.l" -{ - addlit(yytext, yyleng, yyscanner); - } - YY_BREAK -case 47: -YY_RULE_SETUP -#line 718 "third_party/libpg_query/scan.l" -{ - addlit(yytext, yyleng, yyscanner); - } - YY_BREAK -case 48: -YY_RULE_SETUP -#line 721 "third_party/libpg_query/scan.l" -{ - /* This is only needed for $ inside the quoted text */ - addlitchar(yytext[0], yyscanner); - } - YY_BREAK -case YY_STATE_EOF(xdolq): -#line 725 "third_party/libpg_query/scan.l" -{ yyerror("unterminated dollar-quoted string"); } - YY_BREAK -case 49: -YY_RULE_SETUP -#line 727 "third_party/libpg_query/scan.l" -{ - SET_YYLLOC(); - BEGIN(xd); - startlit(); - } - YY_BREAK -case 50: -YY_RULE_SETUP -#line 732 "third_party/libpg_query/scan.l" -{ - SET_YYLLOC(); - BEGIN(xui); - startlit(); - } - YY_BREAK -case 51: -YY_RULE_SETUP -#line 737 "third_party/libpg_query/scan.l" -{ - char *ident; + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) ); - BEGIN(INITIAL); - if (yyextra->literallen == 0) - yyerror("zero-length delimited identifier"); - ident = litbufdup(yyscanner); - yylval->str = ident; - return IDENT; - } - YY_BREAK -case 52: -YY_RULE_SETUP -#line 747 "third_party/libpg_query/scan.l" -{ - yyless(1); - /* xuiend state looks for possible UESCAPE */ - BEGIN(xuiend); - } - YY_BREAK -case 53: -/* rule 53 can match eol */ -YY_RULE_SETUP -#line 752 "third_party/libpg_query/scan.l" -{ - /* stay in xuiend state over whitespace */ - } - YY_BREAK -case YY_STATE_EOF(xuiend): -#line 755 "third_party/libpg_query/scan.l" -case 54: -/* rule 54 can match eol */ -#line 757 "third_party/libpg_query/scan.l" -case 55: -/* rule 55 can match eol */ -YY_RULE_SETUP -#line 757 "third_party/libpg_query/scan.l" -{ - /* no UESCAPE after the quote, throw back everything */ - char *ident; - int identlen; + /* + * T = (TP - TQ) * (Q^-1 mod P) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) ); - yyless(0); + /* + * T = TQ + T * Q + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ - BEGIN(INITIAL); - if (yyextra->literallen == 0) - yyerror("zero-length delimited identifier"); - ident = litbuf_udeescape('\\', yyscanner); - identlen = strlen(ident); - yylval->str = ident; - return IDENT; - } - YY_BREAK -case 56: -/* rule 56 can match eol */ -YY_RULE_SETUP -#line 772 "third_party/libpg_query/scan.l" -{ - /* found UESCAPE after the end quote */ - char *ident; - int identlen; + /* + * Unblind + * T = T * Vf mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); - BEGIN(INITIAL); - if (yyextra->literallen == 0) - yyerror("zero-length delimited identifier"); - if (!check_uescapechar(yytext[yyleng - 2])) - { - SET_YYLLOC(); - ADVANCE_YYLLOC(yyleng - 2); - yyerror("invalid Unicode escape character"); - } - ident = litbuf_udeescape(yytext[yyleng - 2], yyscanner); - identlen = strlen(ident); - yylval->str = ident; - return IDENT; - } - YY_BREAK -case 57: -YY_RULE_SETUP -#line 791 "third_party/libpg_query/scan.l" -{ - addlitchar('"', yyscanner); - } - YY_BREAK -case 58: -/* rule 58 can match eol */ -YY_RULE_SETUP -#line 794 "third_party/libpg_query/scan.l" -{ - addlit(yytext, yyleng, yyscanner); - } - YY_BREAK -case YY_STATE_EOF(xd): -case YY_STATE_EOF(xui): -#line 797 "third_party/libpg_query/scan.l" -{ yyerror("unterminated quoted identifier"); } - YY_BREAK -case 59: -YY_RULE_SETUP -#line 799 "third_party/libpg_query/scan.l" -{ - char *ident; + /* Verify the result to prevent glitching attacks. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E, + &ctx->N, &ctx->RN ) ); + if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } - SET_YYLLOC(); - /* throw back all but the initial u/U */ - yyless(1); - /* and treat it as {identifier} */ - ident = downcase_truncate_identifier(yytext, yyleng, true); - yylval->str = ident; - return IDENT; - } - YY_BREAK -case 60: -YY_RULE_SETUP -#line 811 "third_party/libpg_query/scan.l" -{ - SET_YYLLOC(); - return TYPECAST; - } - YY_BREAK -case 61: -YY_RULE_SETUP -#line 816 "third_party/libpg_query/scan.l" + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &P1 ); + mbedtls_mpi_free( &Q1 ); + mbedtls_mpi_free( &R ); + +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &D_blind ); +#else + mbedtls_mpi_free( &DP_blind ); + mbedtls_mpi_free( &DQ_blind ); +#endif + + mbedtls_mpi_free( &T ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ ); +#endif + + mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &I ); + + if( ret != 0 && ret >= -0x007f ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_PRIVATE_FAILED, ret ) ); + + return( ret ); +} + +#if defined(MBEDTLS_PKCS1_V21) +/** + * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. + * + * \param dst buffer to mask + * \param dlen length of destination buffer + * \param src source of the mask generation + * \param slen length of the source buffer + * \param md_ctx message digest context to use + */ +static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, + size_t slen, mbedtls_md_context_t *md_ctx ) { - SET_YYLLOC(); - return DOT_DOT; - } - YY_BREAK -case 62: -YY_RULE_SETUP -#line 821 "third_party/libpg_query/scan.l" + unsigned char mask[MBEDTLS_MD_MAX_SIZE]; + unsigned char counter[4]; + unsigned char *p; + unsigned int hlen; + size_t i, use_len; + int ret = 0; + + memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); + memset( counter, 0, 4 ); + + hlen = mbedtls_md_get_size( md_ctx->md_info ); + + /* Generate and apply dbMask */ + p = dst; + + while( dlen > 0 ) + { + use_len = hlen; + if( dlen < hlen ) + use_len = dlen; + + if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 ) + goto exit; + + for( i = 0; i < use_len; ++i ) + *p++ ^= mask[i]; + + counter[3]++; + + dlen -= use_len; + } + +exit: + mbedtls_platform_zeroize( mask, sizeof( mask ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ) { - SET_YYLLOC(); - return COLON_EQUALS; - } - YY_BREAK -case 63: -YY_RULE_SETUP -#line 826 "third_party/libpg_query/scan.l" + size_t olen; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = output; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + hlen = mbedtls_md_get_size( md_info ); + + /* first comparison checks for overflow */ + if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + memset( output, 0, olen ); + + *p++ = 0; + + /* Generate a random octet string seed */ + if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) ); + + p += hlen; + + /* Construct DB */ + if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 ) + return( ret ); + p += hlen; + p += olen - 2 * hlen - 2 - ilen; + *p++ = 1; + if( ilen != 0 ) + memcpy( p, input, ilen ); + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + /* maskedSeed: Apply seedMask to seed */ + if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, + &md_ctx ) ) != 0 ) + goto exit; + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( mbedtls_rsa_public( ctx, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, size_t ilen, + const unsigned char *input, + unsigned char *output ) { - SET_YYLLOC(); - return LAMBDA_ARROW; - } - YY_BREAK -case 64: -YY_RULE_SETUP -#line 831 "third_party/libpg_query/scan.l" + size_t nb_pad, olen; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *p = output; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + + olen = ctx->len; + + /* first comparison checks for overflow */ + if( ilen + 11 < ilen || olen < ilen + 11 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + *p++ = MBEDTLS_RSA_CRYPT; + + while( nb_pad-- > 0 ) + { + int rng_dl = 100; + + do { + ret = f_rng( p_rng, p, 1 ); + } while( *p == 0 && --rng_dl && ret == 0 ); + + /* Check if RNG failed to generate data */ + if( rng_dl == 0 || ret != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) ); + + p++; + } + + *p++ = 0; + if( ilen != 0 ) + memcpy( p, input, ilen ); + + return( mbedtls_rsa_public( ctx, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Add the message padding, then do an RSA operation + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t ilen, + const unsigned char *input, + unsigned char *output ) { - SET_YYLLOC(); - return POWER_OF; - } - YY_BREAK -case 65: -YY_RULE_SETUP -#line 836 "third_party/libpg_query/scan.l" + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( output != NULL ); + RSA_VALIDATE_RET( ilen == 0 || input != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, + ilen, input, output ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, NULL, 0, + ilen, input, output ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) { - SET_YYLLOC(); - return EQUALS_GREATER; - } - YY_BREAK -case 66: -YY_RULE_SETUP -#line 841 "third_party/libpg_query/scan.l" + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t ilen, i, pad_len; + unsigned char *p, bad, pad_done; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( label_len == 0 || label != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + /* + * Parameters sanity checks + */ + if( ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + // checking for integer underflow + if( 2 * hlen + 2 > ilen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * RSA operation + */ + ret = mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + /* + * Unmask data and generate lHash + */ + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + /* seed: Apply seedMask to maskedSeed */ + if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + &md_ctx ) ) != 0 || + /* DB: Apply dbMask to maskedDB */ + ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + &md_ctx ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + mbedtls_md_free( &md_ctx ); + + /* Generate lHash */ + if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 ) + goto cleanup; + + /* + * Check contents, in "constant-time" + */ + p = buf; + bad = 0; + + bad |= *p++; /* First byte must be 0 */ + + p += hlen; /* Skip seed */ + + /* Check lHash */ + for( i = 0; i < hlen; i++ ) + bad |= lhash[i] ^ *p++; + + /* Get zero-padding len, but always read till end of buffer + * (minus one, for the 01 byte) */ + pad_len = 0; + pad_done = 0; + for( i = 0; i < ilen - 2 * hlen - 2; i++ ) + { + pad_done |= p[i]; + pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_len; + bad |= *p++ ^ 0x01; + + /* + * The only information "leaked" is whether the padding was correct or not + * (eg, no data is copied if it was not correct). This meets the + * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between + * the different error conditions. + */ + if( bad != 0 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + if( *olen != 0 ) + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( lhash, sizeof( lhash ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) { - SET_YYLLOC(); - return LESS_EQUALS; - } - YY_BREAK -case 67: -YY_RULE_SETUP -#line 846 "third_party/libpg_query/scan.l" + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t ilen; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + ilen = ctx->len; + + if( ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + ret = mbedtls_ct_rsaes_pkcs1_v15_unpadding( buf, ilen, + output, output_max_len, olen ); + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation, then remove the message padding + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) { - SET_YYLLOC(); - return GREATER_EQUALS; - } - YY_BREAK -case 68: -YY_RULE_SETUP -#line 851 "third_party/libpg_query/scan.l" + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( output_max_len == 0 || output != NULL ); + RSA_VALIDATE_RET( input != NULL ); + RSA_VALIDATE_RET( olen != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, olen, + input, output, output_max_len ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, NULL, 0, + olen, input, output, + output_max_len ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +static int rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + int saltlen, + unsigned char *sig ) { - /* We accept both "<>" and "!=" as meaning NOT_EQUALS */ - SET_YYLLOC(); - return NOT_EQUALS; - } - YY_BREAK -case 69: -YY_RULE_SETUP -#line 857 "third_party/libpg_query/scan.l" + size_t olen; + unsigned char *p = sig; + unsigned char *salt = NULL; + size_t slen, min_slen, hlen, offset = 0; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + if( ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( hashlen != mbedtls_md_get_size( md_info ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + if (saltlen == MBEDTLS_RSA_SALT_LEN_ANY) + { + /* Calculate the largest possible salt length, up to the hash size. + * Normally this is the hash length, which is the maximum salt length + * according to FIPS 185-4 §5.5 (e) and common practice. If there is not + * enough room, use the maximum salt length that fits. The constraint is + * that the hash length plus the salt length plus 2 bytes must be at most + * the key length. This complies with FIPS 186-4 §5.5 (e) and RFC 8017 + * (PKCS#1 v2.2) §9.1.1 step 3. */ + min_slen = hlen - 2; + if( olen < hlen + min_slen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + else if( olen >= hlen + hlen + 2 ) + slen = hlen; + else + slen = olen - hlen - 2; + } + else if ( (saltlen < 0) || (saltlen + hlen + 2 > olen) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + else + { + slen = (size_t) saltlen; + } + + memset( sig, 0, olen ); + + /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + p += olen - hlen - slen - 2; + *p++ = 0x01; + + /* Generate salt of length slen in place in the encoded message */ + salt = p; + if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) + return( MBEDTLS_ERROR_ADD( MBEDTLS_ERR_RSA_RNG_FAILED, ret ) ); + + p += slen; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* Generate H = Hash( M' ) */ + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 ) + goto exit; + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + offset = 1; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + sig[0] &= 0xFF >> ( olen * 8 - msb ); + + p += hlen; + *p++ = 0xBC; + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ); +} + +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function with + * the option to pass in the salt length. + */ +int mbedtls_rsa_rsassa_pss_sign_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + int saltlen, + unsigned char *sig ) { - /* We accept both "<>" and "!=" as meaning NOT_EQUALS */ - SET_YYLLOC(); - return NOT_EQUALS; - } - YY_BREAK -case 70: -YY_RULE_SETUP -#line 863 "third_party/libpg_query/scan.l" + return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, md_alg, + hashlen, hash, saltlen, sig ); +} + + +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) { - SET_YYLLOC(); - return yytext[0]; - } - YY_BREAK -case 71: -YY_RULE_SETUP -#line 868 "third_party/libpg_query/scan.l" + return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, md_alg, + hashlen, hash, MBEDTLS_RSA_SALT_LEN_ANY, sig ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function + */ + +/* Construct a PKCS v1.5 encoding of a hashed message + * + * This is used both for signature generation and verification. + * + * Parameters: + * - md_alg: Identifies the hash algorithm used to generate the given hash; + * MBEDTLS_MD_NONE if raw data is signed. + * - hashlen: Length of hash. Must match md_alg if that's not NONE. + * - hash: Buffer containing the hashed message or the raw data. + * - dst_len: Length of the encoded message. + * - dst: Buffer to hold the encoded message. + * + * Assumptions: + * - hash has size hashlen. + * - dst points to a buffer of size at least dst_len. + * + */ +static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + size_t dst_len, + unsigned char *dst ) { - /* - * Check for embedded slash-star or dash-dash; those - * are comment starts, so operator must stop there. - * Note that slash-star or dash-dash at the first - * character will match a prior rule, not this one. - */ - int nchars = yyleng; - char *slashstar = strstr(yytext, "/*"); /* slash star */ - char *dashdash = strstr(yytext, "--"); + size_t oid_size = 0; + size_t nb_pad = dst_len; + unsigned char *p = dst; + const char *oid = NULL; - if (slashstar && dashdash) { - /* if both appear, take the first one */ - if (slashstar > dashdash) - slashstar = dashdash; - } else if (!slashstar) { - slashstar = dashdash; - } - if (slashstar) { - nchars = slashstar - yytext; - } + /* Are we signing hashed or raw data? */ + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( hashlen != mbedtls_md_get_size( md_info ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Double-check that 8 + hashlen + oid_size can be used as a + * 1-byte ASN.1 length encoding and that there's no overflow. */ + if( 8 + hashlen + oid_size >= 0x80 || + 10 + hashlen < hashlen || + 10 + hashlen + oid_size < 10 + hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Static bounds check: + * - Need 10 bytes for five tag-length pairs. + * (Insist on 1-byte length encodings to protect against variants of + * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) + * - Need hashlen bytes for hash + * - Need oid_size bytes for hash alg OID. + */ + if( nb_pad < 10 + hashlen + oid_size ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 10 + hashlen + oid_size; + } + else + { + if( nb_pad < hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); - /* - * For SQL compatibility, '+' and '-' cannot be the - * last char of a multi-char operator unless the operator - * contains chars that are not in SQL operators. - * The idea is to lex '=-' as two operators, but not - * to forbid operator names like '?-' that could not be - * sequences of SQL operators. - */ - while (nchars > 1 && - (yytext[nchars - 1] == '+' || - yytext[nchars - 1] == '-')) - { - int ic; + nb_pad -= hashlen; + } - for (ic = nchars - 2; ic >= 0; ic--) - { - if (strchr("~!@^&|`?%", yytext[ic])) - break; - } - if (ic >= 0) - break; /* found a char that makes it OK */ - nchars--; /* else remove the +/-, and check again */ - } + /* Need space for signature header and padding delimiter (3 bytes), + * and 8 bytes for the minimal padding */ + if( nb_pad < 3 + 8 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 3; - /* We don't accept leading ? in any multi-character operators - * except for those in use by hstore, JSON and geometric operators. - * - * We don't accept contained or trailing ? in any - * multi-character operators. - * - * This is necessary in order to support normalized queries without - * spacing between ? as a substition character and a simple operator (e.g. "?=?") - */ - if (yytext[0] == '?' && - strcmp(yytext, "?|") != 0 && strcmp(yytext, "?&") != 0 && - strcmp(yytext, "?-") != 0 && - strcmp(yytext, "?-|") != 0 && strcmp(yytext, "?||") != 0) { - nchars = 1; - } + /* Now nb_pad is the amount of memory to be filled + * with padding, and at least 8 bytes long. */ - if (yytext[0] != '?' && strchr(yytext, '?')) { - /* Lex up to just before the ? character */ - nchars = strchr(yytext, '?') - yytext; - } + /* Write signature header and padding */ + *p++ = 0; + *p++ = MBEDTLS_RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; - SET_YYLLOC(); + /* Are we signing raw data? */ + if( md_alg == MBEDTLS_MD_NONE ) + { + memcpy( p, hash, hashlen ); + return( 0 ); + } - if ((yy_size_t) nchars < yyleng) - { - /* Strip the unwanted chars from the token */ - yyless(nchars); - /* - * If what we have left is only one char, and it's - * one of the characters matching "self", then - * return it as a character token the same way - * that the "self" rule would have. - */ - if (nchars == 1 && - strchr(",()[].;:+-*/%^<>=?", yytext[0])) { - return yytext[0]; - } - /* - * Likewise, if what we have left is two chars, and - * those match the tokens ">=", "<=", "=>", "<>" or - * "!=", then we must return the appropriate token - * rather than the generic Op. - */ - if (nchars == 2) - { - if (yytext[0] == '=' && yytext[1] == '>') - return EQUALS_GREATER; - if (yytext[0] == '>' && yytext[1] == '=') - return GREATER_EQUALS; - if (yytext[0] == '<' && yytext[1] == '=') - return LESS_EQUALS; - if (yytext[0] == '<' && yytext[1] == '>') - return NOT_EQUALS; - if (yytext[0] == '!' && yytext[1] == '=') - return NOT_EQUALS; - } - } + /* Signing hashed data, add corresponding ASN.1 structure + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * Digest ::= OCTET STRING + * + * Schematic: + * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] + * TAG-NULL + LEN [ NULL ] ] + * TAG-OCTET + LEN [ HASH ] ] + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = (unsigned char) oid_size; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = (unsigned char) hashlen; + memcpy( p, hash, hashlen ); + p += hashlen; + + /* Just a sanity-check, should be automatic + * after the initial bounds check. */ + if( p != dst + dst_len ) + { + mbedtls_platform_zeroize( dst, dst_len ); + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } - /* - * Complain if operator is too long. Unlike the case - * for identifiers, we make this an error not a notice- - * and-truncate, because the odds are we are looking at - * a syntactic mistake anyway. NAMEDDATALEN - */ - if (nchars >= 64) - yyerror("operator too long: operators longer than 64 bytes are not supported"); + return( 0 ); +} - yylval->str = pstrdup(yytext); - return Op; - } - YY_BREAK -case 72: -YY_RULE_SETUP -#line 985 "third_party/libpg_query/scan.l" -{ - SET_YYLLOC(); - yylval->ival = atol(yytext + 1); - return PARAM; - } - YY_BREAK -case 73: -YY_RULE_SETUP -#line 991 "third_party/libpg_query/scan.l" +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) { - SET_YYLLOC(); - yylval->ival = atol(yytext + 1); - return PARAM; - } - YY_BREAK -case 74: -YY_RULE_SETUP -#line 997 "third_party/libpg_query/scan.l" + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned char *sig_try = NULL, *verif = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + if( ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare PKCS1-v1.5 encoding (padding and hash identifier) + */ + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, + ctx->len, sig ) ) != 0 ) + return( ret ); + + /* Private key operation + * + * In order to prevent Lenstra's attack, make the signature in a + * temporary buffer and check it before returning it. + */ + + sig_try = (unsigned char *) mbedtls_calloc( 1, ctx->len ); + if( sig_try == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + verif = (unsigned char *) mbedtls_calloc( 1, ctx->len ); + if( verif == NULL ) + { + mbedtls_free( sig_try ); + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + } + + MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); + + if( mbedtls_ct_memcmp( verif, sig, ctx->len ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; + goto cleanup; + } + + memcpy( sig, sig_try, ctx->len ); + +cleanup: + mbedtls_platform_zeroize( sig_try, ctx->len ); + mbedtls_platform_zeroize( verif, ctx->len ); + mbedtls_free( sig_try ); + mbedtls_free( verif ); + + if( ret != 0 ) + memset( sig, '!', ctx->len ); + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) { - SET_YYLLOC(); - return process_integer_literal(yytext, yylval); - } - YY_BREAK -case 75: -YY_RULE_SETUP -#line 1001 "third_party/libpg_query/scan.l" + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, + md_alg, hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ) { - SET_YYLLOC(); - yylval->str = pstrdup(yytext); - return FCONST; - } - YY_BREAK -case 76: -YY_RULE_SETUP -#line 1006 "third_party/libpg_query/scan.l" + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t siglen; + unsigned char *p; + unsigned char *hash_start; + unsigned char result[MBEDTLS_MD_MAX_SIZE]; + unsigned char zeros[8]; + unsigned int hlen; + size_t observed_salt_len, msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = mbedtls_rsa_public( ctx, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( buf[siglen - 1] != 0xBC ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( hashlen != mbedtls_md_get_size( md_info ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + md_info = mbedtls_md_info_from_type( mgf1_hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + memset( zeros, 0, 8 ); + + /* + * Note: EMSA-PSS verification is over the length of N - 1 bits + */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + + if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + { + p++; + siglen -= 1; + } + + if( siglen < hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + hash_start = p + siglen - hlen - 1; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx ); + if( ret != 0 ) + goto exit; + + buf[0] &= 0xFF >> ( siglen * 8 - msb ); + + while( p < hash_start - 1 && *p == 0 ) + p++; + + if( *p++ != 0x01 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + observed_salt_len = hash_start - p; + + if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && + observed_salt_len != (size_t) expected_salt_len ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + /* + * Generate H = Hash( M' ) + */ + ret = mbedtls_md_starts( &md_ctx ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, zeros, 8 ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, hash, hashlen ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, p, observed_salt_len ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_finish( &md_ctx, result ); + if ( ret != 0 ) + goto exit; + + if( memcmp( hash_start, result, hlen ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto exit; + } + +exit: + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +/* + * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) { - /* throw back the .., and treat as integer */ - yyless(yyleng - 2); - SET_YYLLOC(); - return process_integer_literal(yytext, yylval); - } - YY_BREAK -case 77: -YY_RULE_SETUP -#line 1012 "third_party/libpg_query/scan.l" + mbedtls_md_type_t mgf1_hash_id; + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) + ? (mbedtls_md_type_t) ctx->hash_id + : md_alg; + + return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, + md_alg, hashlen, hash, + mgf1_hash_id, + MBEDTLS_RSA_SALT_LEN_ANY, + sig ) ); + +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) { - SET_YYLLOC(); - yylval->str = pstrdup(yytext); - return FCONST; - } - YY_BREAK -case 78: -YY_RULE_SETUP -#line 1017 "third_party/libpg_query/scan.l" + int ret = 0; + size_t sig_len; + unsigned char *encoded = NULL, *encoded_expected = NULL; + + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + sig_len = ctx->len; + + /* + * Prepare expected PKCS1 v1.5 encoding of hash. + */ + + if( ( encoded = (unsigned char *) mbedtls_calloc( 1, sig_len ) ) == NULL || + ( encoded_expected = (unsigned char *) mbedtls_calloc( 1, sig_len ) ) == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto cleanup; + } + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len, + encoded_expected ) ) != 0 ) + goto cleanup; + + /* + * Apply RSA primitive to get what should be PKCS1 encoded hash. + */ + + ret = mbedtls_rsa_public( ctx, sig, encoded ); + if( ret != 0 ) + goto cleanup; + + /* + * Compare + */ + + if( ( ret = mbedtls_ct_memcmp( encoded, encoded_expected, + sig_len ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + + if( encoded != NULL ) + { + mbedtls_platform_zeroize( encoded, sig_len ); + mbedtls_free( encoded ); + } + + if( encoded_expected != NULL ) + { + mbedtls_platform_zeroize( encoded_expected, sig_len ); + mbedtls_free( encoded_expected ); + } + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation and check the message digest + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) { - /* - * throw back the [Ee], and treat as {decimal}. Note - * that it is possible the input is actually {integer}, - * but since this case will almost certainly lead to a - * syntax error anyway, we don't bother to distinguish. - */ - yyless(yyleng - 1); - SET_YYLLOC(); - yylval->str = pstrdup(yytext); - return FCONST; - } - YY_BREAK -case 79: -YY_RULE_SETUP -#line 1029 "third_party/libpg_query/scan.l" + RSA_VALIDATE_RET( ctx != NULL ); + RSA_VALIDATE_RET( sig != NULL ); + RSA_VALIDATE_RET( ( md_alg == MBEDTLS_MD_NONE && + hashlen == 0 ) || + hash != NULL ); + + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_verify( ctx, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +/* + * Copy the components of an RSA key + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) { - /* throw back the [Ee][+-], and proceed as above */ - yyless(yyleng - 2); - SET_YYLLOC(); - yylval->str = pstrdup(yytext); - return FCONST; - } - YY_BREAK -case 80: -YY_RULE_SETUP -#line 1038 "third_party/libpg_query/scan.l" + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + RSA_VALIDATE_RET( dst != NULL ); + RSA_VALIDATE_RET( src != NULL ); + + dst->len = src->len; + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); + + dst->padding = src->padding; + dst->hash_id = src->hash_id; + +cleanup: + if( ret != 0 ) + mbedtls_rsa_free( dst ); + + return( ret ); +} + +/* + * Free the components of an RSA key + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) { - const PGScanKeyword *keyword; - char *ident; - char *keyword_text = pstrdup(yytext); + if( ctx == NULL ) + return; - SET_YYLLOC(); + mbedtls_mpi_free( &ctx->Vi ); + mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->RN ); + mbedtls_mpi_free( &ctx->D ); + mbedtls_mpi_free( &ctx->Q ); + mbedtls_mpi_free( &ctx->P ); + mbedtls_mpi_free( &ctx->E ); + mbedtls_mpi_free( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &ctx->RQ ); + mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->QP ); + mbedtls_mpi_free( &ctx->DQ ); + mbedtls_mpi_free( &ctx->DP ); +#endif /* MBEDTLS_RSA_NO_CRT */ + +#if defined(MBEDTLS_THREADING_C) + /* Free the mutex, but only if it hasn't been freed already. */ + if( ctx->ver != 0 ) + { + mbedtls_mutex_free( &ctx->mutex ); + ctx->ver = 0; + } +#endif +} - if (yytext[yyleng - 1] == '?') { - keyword_text[yyleng - 1] = '\0'; - } +#endif /* !MBEDTLS_RSA_ALT */ - /* Is it a keyword? */ - keyword = ScanKeywordLookup(keyword_text, - yyextra->keywords, - yyextra->num_keywords); - if (keyword != NULL) - { - if (keyword_text[yyleng - 1] == '\0') { - yyless(yyleng - 1); - } - yylval->keyword = keyword->name; - return keyword->value; - } +#if defined(MBEDTLS_SELF_TEST) - /* - * No. Convert the identifier to lower case, and truncate - * if necessary. - */ - ident = downcase_truncate_identifier(yytext, yyleng, true); - yylval->str = ident; - return IDENT; - } - YY_BREAK -case 81: -YY_RULE_SETUP -#line 1071 "third_party/libpg_query/scan.l" + + +/* + * Example RSA-1024 keypair, for test purposes + */ +#define KEY_LEN 128 + +#define RSA_N "9292758453063D803DD603D5E777D788" \ + "8ED1D5BF35786190FA2F23EBC0848AEA" \ + "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ + "7130B9CED7ACDF54CFC7555AC14EEBAB" \ + "93A89813FBF3C4F8066D2D800F7C38A8" \ + "1AE31942917403FF4946B0A83D3D3E05" \ + "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ + "5E94BB77B07507233A0BC7BAC8F90F79" + +#define RSA_E "10001" + +#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ + "66CA472BC44D253102F8B4A9D3BFA750" \ + "91386C0077937FE33FA3252D28855837" \ + "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ + "DF79C5CE07EE72C7F123142198164234" \ + "CABB724CF78B8173B9F880FC86322407" \ + "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ + "071513A1E85B5DFA031F21ECAE91A34D" + +#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ + "2C01CAD19EA484A87EA4377637E75500" \ + "FCB2005C5C7DD6EC4AC023CDA285D796" \ + "C3D9E75E1EFC42488BB4F1D13AC30A57" + +#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ + "E211C2B9E5DB1ED0BF61D0D9899620F4" \ + "910E4168387E3C30AA1E00C339A79508" \ + "8452DD96A9A5EA5D9DCA68DA636032AF" + +#define PT_LEN 24 +#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ + "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" + +#if defined(MBEDTLS_PKCS1_V15) +static int myrand( void *rng_state, unsigned char *output, size_t len ) { - SET_YYLLOC(); - return yytext[0]; - } - YY_BREAK -case YY_STATE_EOF(INITIAL): -#line 1076 "third_party/libpg_query/scan.l" +#if !defined(__OpenBSD__) && !defined(__NetBSD__) + size_t i; + + if( rng_state != NULL ) + rng_state = NULL; + + for( i = 0; i < len; ++i ) + output[i] = rand(); +#else + if( rng_state != NULL ) + rng_state = NULL; + + arc4random_buf( output, len ); +#endif /* !OpenBSD && !NetBSD */ + + return( 0 ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Checkup routine + */ +int mbedtls_rsa_self_test( int verbose ) { - SET_YYLLOC(); - yyterminate(); - } - YY_BREAK -case 82: -YY_RULE_SETUP -#line 1081 "third_party/libpg_query/scan.l" -YY_FATAL_ERROR( "flex scanner jammed" ); - YY_BREAK -#line 2653 "third_party/libpg_query/src_backend_parser_scan.cpp" + int ret = 0; +#if defined(MBEDTLS_PKCS1_V15) + size_t len; + mbedtls_rsa_context rsa; + unsigned char rsa_plaintext[PT_LEN]; + unsigned char rsa_decrypted[PT_LEN]; + unsigned char rsa_ciphertext[KEY_LEN]; +#if defined(MBEDTLS_SHA1_C) + unsigned char sha1sum[20]; +#endif - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + mbedtls_mpi K; - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = yyg->yy_hold_char; - YY_RESTORE_YY_MORE_OFFSET + mbedtls_mpi_init( &K ); + mbedtls_rsa_init( &rsa ); - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed yyin at a new source and called - * yylex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; - } + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) ); - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; + MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) ); - yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + if( verbose != 0 ) + mbedtls_printf( " RSA key validation: " ); - yy_current_state = yy_get_previous_state( yyscanner ); + if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || + mbedtls_rsa_check_privkey( &rsa ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ + ret = 1; + goto cleanup; + } - yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 encryption : " ); - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + memcpy( rsa_plaintext, RSA_PT, PT_LEN ); - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++yyg->yy_c_buf_p; - yy_current_state = yy_next_state; - goto yy_match; - } + if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, + PT_LEN, rsa_plaintext, + rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); - else - { - yy_cp = yyg->yy_last_accepting_cpos; - yy_current_state = yyg->yy_last_accepting_state; - goto yy_find_action; - } - } + ret = 1; + goto cleanup; + } - else switch ( yy_get_next_buffer( yyscanner ) ) - { - case EOB_ACT_END_OF_FILE: - { - yyg->yy_did_buffer_switch_on_eof = 0; + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 decryption : " ); - if ( yywrap( yyscanner ) ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * yytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, + &len, rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } + ret = 1; + goto cleanup; + } - else - { - if ( ! yyg->yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; - } - break; - } + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); - case EOB_ACT_CONTINUE_SCAN: - yyg->yy_c_buf_p = - yyg->yytext_ptr + yy_amount_of_matched_text; + ret = 1; + goto cleanup; + } - yy_current_state = yy_get_previous_state( yyscanner ); + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); - yy_cp = yyg->yy_c_buf_p; - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; - goto yy_match; +#if defined(MBEDTLS_SHA1_C) + if( verbose != 0 ) + mbedtls_printf( " PKCS#1 data sign : " ); - case EOB_ACT_LAST_MATCH: - yyg->yy_c_buf_p = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + if( mbedtls_sha1( rsa_plaintext, PT_LEN, sha1sum ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); - yy_current_state = yy_get_previous_state( yyscanner ); + return( 1 ); + } - yy_cp = yyg->yy_c_buf_p; - yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } + if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, + MBEDTLS_MD_SHA1, 20, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ - } /* end of user's declarations */ -} /* end of yylex */ + ret = 1; + goto cleanup; + } -/* yy_get_next_buffer - try to read in a new buffer + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); + + if( mbedtls_rsa_pkcs1_verify( &rsa, MBEDTLS_MD_SHA1, 20, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* MBEDTLS_SHA1_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +cleanup: + mbedtls_mpi_free( &K ); + mbedtls_rsa_free( &rsa ); +#else /* MBEDTLS_PKCS1_V15 */ + ((void) verbose); +#endif /* MBEDTLS_PKCS1_V15 */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RSA_C */ + + +// LICENSE_CHANGE_END + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/* + * Helper functions for the RSA module + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file */ -static int yy_get_next_buffer (yyscan_t yyscanner) + + + +#if defined(MBEDTLS_RSA_C) + + + + + +/* + * Compute RSA prime factors from public and private exponents + * + * Summary of algorithm: + * Setting F := lcm(P-1,Q-1), the idea is as follows: + * + * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) + * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the + * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four + * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) + * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime + * factors of N. + * + * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same + * construction still applies since (-)^K is the identity on the set of + * roots of 1 in Z/NZ. + * + * The public and private key primitives (-)^E and (-)^D are mutually inverse + * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. + * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. + * Splitting L = 2^t * K with K odd, we have + * + * DE - 1 = FL = (F/2) * (2^(t+1)) * K, + * + * so (F / 2) * K is among the numbers + * + * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord + * + * where ord is the order of 2 in (DE - 1). + * We can therefore iterate through these numbers apply the construction + * of (a) and (b) above to attempt to factor N. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, + mbedtls_mpi const *E, mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ) { - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - char *source = yyg->yytext_ptr; - int number_to_move, i; - int ret_val; + int ret = 0; - if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); + uint16_t attempt; /* Number of current attempt */ + uint16_t iter; /* Number of squares computed in the current attempt */ - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } + uint16_t order; /* Order of 2 in DE - 1 */ - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } + mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ + mbedtls_mpi K; /* Temporary holding the current candidate */ - /* Try to read more data. */ + const unsigned char primes[] = { 2, + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251 + }; - /* First move last chars to start of buffer. */ - number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr - 1); + const size_t num_primes = sizeof( primes ) / sizeof( *primes ); - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); + if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || + mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } - else - { - yy_size_t num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + /* + * Initializations and temporary changes + */ - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &T ); - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE; + /* T := DE - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) ); - int yy_c_buf_p_offset = - (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } - if ( b->yy_is_our_buffer ) - { - yy_size_t new_size = b->yy_buf_size * 2; + /* After this operation, T holds the largest odd divisor of DE - 1. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) ); - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; + /* + * Actual work + */ - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - yyrealloc( (void *) b->yy_ch_buf, - (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = NULL; + /* Skip trying 2 if N == 1 mod 8 */ + attempt = 0; + if( N->p[0] % 8 == 1 ) + attempt = 1; - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); + for( ; attempt < num_primes; ++attempt ) + { + mbedtls_mpi_lset( &K, primes[attempt] ); - yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + /* Check if gcd(K,N) = 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + if( mbedtls_mpi_cmp_int( P, 1 ) != 0 ) + continue; - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - - number_to_move - 1; + /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... + * and check whether they have nontrivial GCD with N. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N, + Q /* temporarily use Q for storing Montgomery + * multiplication helper values */ ) ); - } + for( iter = 1; iter <= order; ++iter ) + { + /* If we reach 1 prematurely, there's no point + * in continuing to square K */ + if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 ) + break; - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + + if( mbedtls_mpi_cmp_int( P, 1 ) == 1 && + mbedtls_mpi_cmp_mpi( P, N ) == -1 ) + { + /* + * Have found a nontrivial divisor P of N. + * Set Q := N / P. + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) ); + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) ); + } + + /* + * If we get here, then either we prematurely aborted the loop because + * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must + * be 1 if D,E,N were consistent. + * Check if that's the case and abort if not, to avoid very long, + * yet eventually failing, computations if N,D,E were not sane. + */ + if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 ) + { + break; + } + } + + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &T ); + return( ret ); +} + +/* + * Given P, Q and the public exponent E, deduce D. + * This is essentially a modular inversion. + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ) +{ + int ret = 0; + mbedtls_mpi K, L; + + if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 0 ) == 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Temporarily put K := P-1 and L := Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + + /* Temporarily put D := gcd(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) ); + + /* K := LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) ); + + /* Compute modular inverse of E in LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) ); + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = 0; + mbedtls_mpi K; + mbedtls_mpi_init( &K ); + + /* DP = D mod P-1 */ + if( DP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) ); + } + + /* DQ = D mod Q-1 */ + if( DQ != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) ); + } + + /* QP = Q^{-1} mod P */ + if( QP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) ); + } + +cleanup: + mbedtls_mpi_free( &K ); + + return( ret ); +} + +/* + * Check that core RSA parameters are sane. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = 0; + mbedtls_mpi K, L; + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* + * Step 1: If PRNG provided, check that P and Q are prime + */ + +#if defined(MBEDTLS_GENPRIME) + /* + * When generating keys, the strongest security we support aims for an error + * rate of at most 2^-100 and we are aiming for the same certainty here as + * well. + */ + if( f_rng != NULL && P != NULL && + ( ret = mbedtls_mpi_is_prime_ext( P, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + if( f_rng != NULL && Q != NULL && + ( ret = mbedtls_mpi_is_prime_ext( Q, 50, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } +#else + ((void) f_rng); + ((void) p_rng); +#endif /* MBEDTLS_GENPRIME */ + + /* + * Step 2: Check that 1 < N = P * Q + */ + + if( P != NULL && Q != NULL && N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) ); + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( &K, N ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 3: Check and 1 < D, E < N if present. + */ + + if( N != NULL && D != NULL && E != NULL ) + { + if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 4: Check that D, E are inverse modulo P-1 and Q-1 + */ + + if( P != NULL && Q != NULL && D != NULL && E != NULL ) + { + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod P-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + return( ret ); +} + +/* + * Check that RSA CRT parameters are in accordance with core parameters. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ) +{ + int ret = 0; + + mbedtls_mpi K, L; + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Check that DP - D == 0 mod P - 1 */ + if( DP != NULL ) + { + if( P == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } - /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - yyg->yy_n_chars, num_to_read ); + /* Check that DQ - D == 0 mod Q - 1 */ + if( DQ != NULL ) + { + if( Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; - } + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); - if ( yyg->yy_n_chars == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - yyrestart( yyin , yyscanner); - } + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } - else - { - ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } + /* Check that QP * Q - 1 == 0 mod P */ + if( QP != NULL ) + { + if( P == NULL || Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } - else - ret_val = EOB_ACT_CONTINUE_SCAN; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } - if ((yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { - /* Extend the array by 50%, plus the number we really need. */ - yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc( - (void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf, (yy_size_t) new_size , yyscanner ); - if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); - /* "- 2" to take care of EOB's */ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2); - } +cleanup: - yyg->yy_n_chars += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && + ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && + ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } - yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); - return ret_val; + return( ret ); } -/* yy_get_previous_state - get the state just before the EOB char was reached */ +#endif /* MBEDTLS_RSA_C */ - static yy_state_type yy_get_previous_state (yyscan_t yyscanner) -{ - yy_state_type yy_current_state; - char *yy_cp; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yy_current_state = yyg->yy_start; +// LICENSE_CHANGE_END - for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) - { - YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - yyg->yy_last_accepting_state = yy_current_state; - yyg->yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 295 ) - yy_c = yy_meta[yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - } - return yy_current_state; -} +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list -/* yy_try_NUL_trans - try to make a transition on the NUL character +/* + * FIPS-180-1 compliant SHA-1 implementation * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) -{ - int yy_is_jam; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ - char *yy_cp = yyg->yy_c_buf_p; - YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - yyg->yy_last_accepting_state = yy_current_state; - yyg->yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 295 ) - yy_c = yy_meta[yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 294); - (void)yyg; - return yy_is_jam ? 0 : yy_current_state; -} -#ifndef YY_NO_UNPUT +#if defined(MBEDTLS_SHA1_C) -#endif -#ifndef YY_NO_INPUT -#ifdef __cplusplus - static int yyinput (yyscan_t yyscanner) -#else - static int input (yyscan_t yyscanner) -#endif -{ - int c; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - *yyg->yy_c_buf_p = yyg->yy_hold_char; - if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) - /* This was really a NUL. */ - *yyg->yy_c_buf_p = '\0'; +#include - else - { /* need more input */ - yy_size_t offset = yyg->yy_c_buf_p - yyg->yytext_ptr; - ++yyg->yy_c_buf_p; +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) - switch ( yy_get_next_buffer( yyscanner ) ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ - /* Reset buffer status. */ - yyrestart( yyin , yyscanner); +#define SHA1_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA ) - /*FALLTHROUGH*/ +#define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) - case EOB_ACT_END_OF_FILE: - { - if ( yywrap( yyscanner ) ) - return 0; +#if !defined(MBEDTLS_SHA1_ALT) - if ( ! yyg->yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(yyscanner); -#else - return input(yyscanner); -#endif - } +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) +{ + SHA1_VALIDATE( ctx != NULL ); - case EOB_ACT_CONTINUE_SCAN: - yyg->yy_c_buf_p = yyg->yytext_ptr + offset; - break; - } - } - } + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); +} - c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ - *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ - yyg->yy_hold_char = *++yyg->yy_c_buf_p; +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) +{ + if( ctx == NULL ) + return; - return c; + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); } -#endif /* ifndef YY_NO_INPUT */ -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * @param yyscanner The scanner object. - * @note This function does not reset the start condition to @c INITIAL . - */ - void yyrestart (FILE * input_file , yyscan_t yyscanner) +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) { - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - if ( ! YY_CURRENT_BUFFER ){ - yyensure_buffer_stack (yyscanner); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer( yyin, YY_BUF_SIZE , yyscanner); - } + SHA1_VALIDATE( dst != NULL ); + SHA1_VALIDATE( src != NULL ); - yy_init_buffer( YY_CURRENT_BUFFER, input_file , yyscanner); - yy_load_buffer_state( yyscanner ); + *dst = *src; } -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * @param yyscanner The scanner object. +/* + * SHA-1 context setup */ - void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +int mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) { - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - /* TODO. We should be able to replace this entire function body - * with - * yypop_buffer_state(); - * yypush_buffer_state(new_buffer); - */ - yyensure_buffer_stack (yyscanner); - if ( YY_CURRENT_BUFFER == new_buffer ) - return; + SHA1_VALIDATE_RET( ctx != NULL ); - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *yyg->yy_c_buf_p = yyg->yy_hold_char; - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; - } + ctx->total[0] = 0; + ctx->total[1] = 0; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - yy_load_buffer_state( yyscanner ); + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; - /* We don't actually know whether we did this switch during - * EOF (yywrap()) processing, but the only time this flag - * is looked at is after yywrap() is called, so it's safe - * to go ahead and always set it. - */ - yyg->yy_did_buffer_switch_on_eof = 1; + return( 0 ); } -static void yy_load_buffer_state (yyscan_t yyscanner) +#if !defined(MBEDTLS_SHA1_PROCESS_ALT) +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) { - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - yyg->yy_hold_char = *yyg->yy_c_buf_p; -} + struct + { + uint32_t temp, W[16], A, B, C, D, E; + } local; + + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (const unsigned char *)data != NULL ); + + local.W[ 0] = MBEDTLS_GET_UINT32_BE( data, 0 ); + local.W[ 1] = MBEDTLS_GET_UINT32_BE( data, 4 ); + local.W[ 2] = MBEDTLS_GET_UINT32_BE( data, 8 ); + local.W[ 3] = MBEDTLS_GET_UINT32_BE( data, 12 ); + local.W[ 4] = MBEDTLS_GET_UINT32_BE( data, 16 ); + local.W[ 5] = MBEDTLS_GET_UINT32_BE( data, 20 ); + local.W[ 6] = MBEDTLS_GET_UINT32_BE( data, 24 ); + local.W[ 7] = MBEDTLS_GET_UINT32_BE( data, 28 ); + local.W[ 8] = MBEDTLS_GET_UINT32_BE( data, 32 ); + local.W[ 9] = MBEDTLS_GET_UINT32_BE( data, 36 ); + local.W[10] = MBEDTLS_GET_UINT32_BE( data, 40 ); + local.W[11] = MBEDTLS_GET_UINT32_BE( data, 44 ); + local.W[12] = MBEDTLS_GET_UINT32_BE( data, 48 ); + local.W[13] = MBEDTLS_GET_UINT32_BE( data, 52 ); + local.W[14] = MBEDTLS_GET_UINT32_BE( data, 56 ); + local.W[15] = MBEDTLS_GET_UINT32_BE( data, 60 ); + +#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n)))) + +#define R(t) \ + ( \ + local.temp = local.W[( (t) - 3 ) & 0x0F] ^ \ + local.W[( (t) - 8 ) & 0x0F] ^ \ + local.W[( (t) - 14 ) & 0x0F] ^ \ + local.W[ (t) & 0x0F], \ + ( local.W[(t) & 0x0F] = S(local.temp,1) ) \ + ) + +#define P(a,b,c,d,e,x) \ + do \ + { \ + (e) += S((a),5) + F((b),(c),(d)) + K + (x); \ + (b) = S((b),30); \ + } while( 0 ) + + local.A = ctx->state[0]; + local.B = ctx->state[1]; + local.C = ctx->state[2]; + local.D = ctx->state[3]; + local.E = ctx->state[4]; + +#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) +#define K 0x5A827999 + + P( local.A, local.B, local.C, local.D, local.E, local.W[0] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[1] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[2] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[3] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[4] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[5] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[6] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[7] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[8] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[9] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[10] ); + P( local.E, local.A, local.B, local.C, local.D, local.W[11] ); + P( local.D, local.E, local.A, local.B, local.C, local.W[12] ); + P( local.C, local.D, local.E, local.A, local.B, local.W[13] ); + P( local.B, local.C, local.D, local.E, local.A, local.W[14] ); + P( local.A, local.B, local.C, local.D, local.E, local.W[15] ); + P( local.E, local.A, local.B, local.C, local.D, R(16) ); + P( local.D, local.E, local.A, local.B, local.C, R(17) ); + P( local.C, local.D, local.E, local.A, local.B, R(18) ); + P( local.B, local.C, local.D, local.E, local.A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define K 0x6ED9EBA1 + + P( local.A, local.B, local.C, local.D, local.E, R(20) ); + P( local.E, local.A, local.B, local.C, local.D, R(21) ); + P( local.D, local.E, local.A, local.B, local.C, R(22) ); + P( local.C, local.D, local.E, local.A, local.B, R(23) ); + P( local.B, local.C, local.D, local.E, local.A, R(24) ); + P( local.A, local.B, local.C, local.D, local.E, R(25) ); + P( local.E, local.A, local.B, local.C, local.D, R(26) ); + P( local.D, local.E, local.A, local.B, local.C, R(27) ); + P( local.C, local.D, local.E, local.A, local.B, R(28) ); + P( local.B, local.C, local.D, local.E, local.A, R(29) ); + P( local.A, local.B, local.C, local.D, local.E, R(30) ); + P( local.E, local.A, local.B, local.C, local.D, R(31) ); + P( local.D, local.E, local.A, local.B, local.C, R(32) ); + P( local.C, local.D, local.E, local.A, local.B, R(33) ); + P( local.B, local.C, local.D, local.E, local.A, R(34) ); + P( local.A, local.B, local.C, local.D, local.E, R(35) ); + P( local.E, local.A, local.B, local.C, local.D, R(36) ); + P( local.D, local.E, local.A, local.B, local.C, R(37) ); + P( local.C, local.D, local.E, local.A, local.B, R(38) ); + P( local.B, local.C, local.D, local.E, local.A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define K 0x8F1BBCDC + + P( local.A, local.B, local.C, local.D, local.E, R(40) ); + P( local.E, local.A, local.B, local.C, local.D, R(41) ); + P( local.D, local.E, local.A, local.B, local.C, R(42) ); + P( local.C, local.D, local.E, local.A, local.B, R(43) ); + P( local.B, local.C, local.D, local.E, local.A, R(44) ); + P( local.A, local.B, local.C, local.D, local.E, R(45) ); + P( local.E, local.A, local.B, local.C, local.D, R(46) ); + P( local.D, local.E, local.A, local.B, local.C, R(47) ); + P( local.C, local.D, local.E, local.A, local.B, R(48) ); + P( local.B, local.C, local.D, local.E, local.A, R(49) ); + P( local.A, local.B, local.C, local.D, local.E, R(50) ); + P( local.E, local.A, local.B, local.C, local.D, R(51) ); + P( local.D, local.E, local.A, local.B, local.C, R(52) ); + P( local.C, local.D, local.E, local.A, local.B, R(53) ); + P( local.B, local.C, local.D, local.E, local.A, R(54) ); + P( local.A, local.B, local.C, local.D, local.E, R(55) ); + P( local.E, local.A, local.B, local.C, local.D, R(56) ); + P( local.D, local.E, local.A, local.B, local.C, R(57) ); + P( local.C, local.D, local.E, local.A, local.B, R(58) ); + P( local.B, local.C, local.D, local.E, local.A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) ((x) ^ (y) ^ (z)) +#define K 0xCA62C1D6 + + P( local.A, local.B, local.C, local.D, local.E, R(60) ); + P( local.E, local.A, local.B, local.C, local.D, R(61) ); + P( local.D, local.E, local.A, local.B, local.C, R(62) ); + P( local.C, local.D, local.E, local.A, local.B, R(63) ); + P( local.B, local.C, local.D, local.E, local.A, R(64) ); + P( local.A, local.B, local.C, local.D, local.E, R(65) ); + P( local.E, local.A, local.B, local.C, local.D, R(66) ); + P( local.D, local.E, local.A, local.B, local.C, R(67) ); + P( local.C, local.D, local.E, local.A, local.B, R(68) ); + P( local.B, local.C, local.D, local.E, local.A, R(69) ); + P( local.A, local.B, local.C, local.D, local.E, R(70) ); + P( local.E, local.A, local.B, local.C, local.D, R(71) ); + P( local.D, local.E, local.A, local.B, local.C, R(72) ); + P( local.C, local.D, local.E, local.A, local.B, R(73) ); + P( local.B, local.C, local.D, local.E, local.A, R(74) ); + P( local.A, local.B, local.C, local.D, local.E, R(75) ); + P( local.E, local.A, local.B, local.C, local.D, R(76) ); + P( local.D, local.E, local.A, local.B, local.C, R(77) ); + P( local.C, local.D, local.E, local.A, local.B, R(78) ); + P( local.B, local.C, local.D, local.E, local.A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += local.A; + ctx->state[1] += local.B; + ctx->state[2] += local.C; + ctx->state[3] += local.D; + ctx->state[4] += local.E; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); +} + +#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * @param yyscanner The scanner object. - * @return the allocated buffer state. +/* + * SHA-1 process buffer */ - YY_BUFFER_STATE yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) +int mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) { - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; - b->yy_buf_size = size; + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) yyalloc( (yy_size_t) (b->yy_buf_size + 2) , yyscanner ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + if( ilen == 0 ) + return( 0 ); - b->yy_is_our_buffer = 1; + left = ctx->total[0] & 0x3F; + fill = 64 - left; - yy_init_buffer( b, file , yyscanner); + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; - return b; -} + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; -/** Destroy the buffer. - * @param b a buffer created with yy_create_buffer() - * @param yyscanner The scanner object. - */ - void yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); - if ( ! b ) - return; + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + input += fill; + ilen -= fill; + left = 0; + } - if ( b->yy_is_our_buffer ) - yyfree( (void *) b->yy_ch_buf , yyscanner ); + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) + return( ret ); - yyfree( (void *) b , yyscanner ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); } -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a yyrestart() or at EOF. +/* + * SHA-1 final digest */ - static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) - +int mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ) { - int oerrno = errno; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - - yy_flush_buffer( b , yyscanner); + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; - b->yy_input_file = file; - b->yy_fill_buffer = 1; + SHA1_VALIDATE_RET( ctx != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); - /* If b is the current buffer, then yy_init_buffer was _probably_ - * called from yyrestart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); - b->yy_is_interactive = 0; - - errno = oerrno; -} + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * @param yyscanner The scanner object. - */ - void yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if ( ! b ) - return; + memset( ctx->buffer, 0, 56 ); + } - b->yy_n_chars = 0; + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + MBEDTLS_PUT_UINT32_BE( high, ctx->buffer, 56 ); + MBEDTLS_PUT_UINT32_BE( low, ctx->buffer, 60 ); - b->yy_buf_pos = &b->yy_ch_buf[0]; + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; + /* + * Output final state + */ + MBEDTLS_PUT_UINT32_BE( ctx->state[0], output, 0 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[1], output, 4 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[2], output, 8 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[3], output, 12 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[4], output, 16 ); - if ( b == YY_CURRENT_BUFFER ) - yy_load_buffer_state( yyscanner ); + return( 0 ); } -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * @param yyscanner The scanner object. +#endif /* !MBEDTLS_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) */ -void yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +int mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) { - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if (new_buffer == NULL) - return; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha1_context ctx; - yyensure_buffer_stack(yyscanner); + SHA1_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA1_VALIDATE_RET( (unsigned char *)output != NULL ); - /* This block is copied from yy_switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *yyg->yy_c_buf_p = yyg->yy_hold_char; - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; - } + mbedtls_sha1_init( &ctx ); - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - yyg->yy_buffer_stack_top++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; + if( ( ret = mbedtls_sha1_starts( &ctx ) ) != 0 ) + goto exit; - /* copied from yy_switch_to_buffer. */ - yy_load_buffer_state( yyscanner ); - yyg->yy_did_buffer_switch_on_eof = 1; + if( ( ret = mbedtls_sha1_update( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_finish( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); } -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * @param yyscanner The scanner object. +#if defined(MBEDTLS_SELF_TEST) +/* + * FIPS-180-1 test vectors */ -void yypop_buffer_state (yyscan_t yyscanner) +static const unsigned char sha1_test_buf[3][57] = { - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - if (!YY_CURRENT_BUFFER) - return; + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; - yy_delete_buffer(YY_CURRENT_BUFFER , yyscanner); - YY_CURRENT_BUFFER_LVALUE = NULL; - if (yyg->yy_buffer_stack_top > 0) - --yyg->yy_buffer_stack_top; +static const size_t sha1_test_buflen[3] = +{ + 3, 56, 1000 +}; - if (YY_CURRENT_BUFFER) { - yy_load_buffer_state( yyscanner ); - yyg->yy_did_buffer_switch_on_eof = 1; - } -} +static const unsigned char sha1_test_sum[3][20] = +{ + { 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D }, + { 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 }, + { 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } +}; -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. +/* + * Checkup routine */ -static void yyensure_buffer_stack (yyscan_t yyscanner) +int mbedtls_sha1_self_test( int verbose ) { - yy_size_t num_to_alloc; - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + int i, j, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + mbedtls_sha1_context ctx; - if (!yyg->yy_buffer_stack) { + mbedtls_sha1_init( &ctx ); - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; /* After all that talk, this was set to 1 anyways... */ - yyg->yy_buffer_stack = (struct yy_buffer_state**)yyalloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - , yyscanner); - if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + /* + * SHA-1 + */ + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); - memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + if( ( ret = mbedtls_sha1_starts( &ctx ) ) != 0 ) + goto fail; - yyg->yy_buffer_stack_max = num_to_alloc; - yyg->yy_buffer_stack_top = 0; - return; - } + if( i == 2 ) + { + memset( buf, 'a', buflen = 1000 ); - if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha1_update( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha1_update( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + if( ret != 0 ) + goto fail; + } - /* Increase the buffer to prepare for a possible push. */ - yy_size_t grow_size = 8 /* arbitrary grow size */; + if( ( ret = mbedtls_sha1_finish( &ctx, sha1sum ) ) != 0 ) + goto fail; - num_to_alloc = yyg->yy_buffer_stack_max + grow_size; - yyg->yy_buffer_stack = (struct yy_buffer_state**)yyrealloc - (yyg->yy_buffer_stack, - num_to_alloc * sizeof(struct yy_buffer_state*) - , yyscanner); - if ( ! yyg->yy_buffer_stack ) - YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" ); + if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) + { + ret = 1; + goto fail; + } - /* zero only the new slots.*/ - memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); - yyg->yy_buffer_stack_max = num_to_alloc; - } -} + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) -{ - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return NULL; + if( verbose != 0 ) + mbedtls_printf( "\n" ); - b = (YY_BUFFER_STATE) yyalloc( sizeof( struct yy_buffer_state ) , yyscanner ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + goto exit; - b->yy_buf_size = (int) (size - 2); /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = NULL; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); - yy_switch_to_buffer( b , yyscanner ); +exit: + mbedtls_sha1_free( &ctx ); - return b; + return( ret ); } -/** Setup the input buffer state to scan a string. The next call to yylex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * yy_scan_bytes() instead. - */ -YY_BUFFER_STATE yy_scan_string (const char * yystr , yyscan_t yyscanner) -{ - - return yy_scan_bytes( yystr, (int) strlen(yystr) , yyscanner); -} +#endif /* MBEDTLS_SELF_TEST */ -/** Setup the input buffer state to scan the given bytes. The next call to yylex() will - * scan from a @e copy of @a bytes. - * @param yybytes the byte buffer to scan - * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. - * @param yyscanner The scanner object. - * @return the newly allocated buffer state object. +#endif /* MBEDTLS_SHA1_C */ + + +// LICENSE_CHANGE_END + + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf */ -YY_BUFFER_STATE yy_scan_bytes (const char * yybytes, yy_size_t _yybytes_len , yyscan_t yyscanner) -{ - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - yy_size_t i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = (yy_size_t) (_yybytes_len + 2); - buf = (char *) yyalloc( n , yyscanner ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; - b = yy_scan_buffer( buf, n , yyscanner); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); +#if defined(MBEDTLS_SHA256_C) - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - return b; -} -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif -static void yynoreturn yy_fatal_error (const char* msg , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - (void)yyg; - //( stderr, "%s\n", msg ); - throw std::runtime_error(msg); // YY_EXIT_FAILURE ); -} -/* Redefine yyless() so it works in section 3 code. */ +#include -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - yy_size_t yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - yytext[yyleng] = yyg->yy_hold_char; \ - yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ - yyg->yy_hold_char = *yyg->yy_c_buf_p; \ - *yyg->yy_c_buf_p = '\0'; \ - yyleng = yyless_macro_arg; \ - } \ - while ( 0 ) +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) -/* Accessor methods (get/set functions) to struct members. */ +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ -/** Get the user-defined data for this scanner. - * @param yyscanner The scanner object. - */ -YY_EXTRA_TYPE yyget_extra (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyextra; -} +#define SHA256_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA ) +#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) -/** Get the current line number. - * @param yyscanner The scanner object. - */ -int yyget_lineno (yyscan_t yyscanner) +#if !defined(MBEDTLS_SHA256_ALT) + +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ) { - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + SHA256_VALIDATE( ctx != NULL ); - if (! YY_CURRENT_BUFFER) - return 0; - - return yylineno; + memset( ctx, 0, sizeof( mbedtls_sha256_context ) ); } -/** Get the current column number. - * @param yyscanner The scanner object. - */ -int yyget_column (yyscan_t yyscanner) +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) { - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if( ctx == NULL ) + return; - if (! YY_CURRENT_BUFFER) - return 0; - - return yycolumn; + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); } -/** Get the input stream. - * @param yyscanner The scanner object. - */ -FILE *yyget_in (yyscan_t yyscanner) +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) { - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyin; -} + SHA256_VALIDATE( dst != NULL ); + SHA256_VALIDATE( src != NULL ); -/** Get the output stream. - * @param yyscanner The scanner object. - */ -FILE *yyget_out (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyout; + *dst = *src; } -/** Get the length of the current token. - * @param yyscanner The scanner object. +/* + * SHA-256 context setup */ -yy_size_t yyget_leng (yyscan_t yyscanner) +int mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) { - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yyleng; -} + SHA256_VALIDATE_RET( ctx != NULL ); -/** Get the current token. - * @param yyscanner The scanner object. - */ +#if defined(MBEDTLS_SHA224_C) + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); +#else + SHA256_VALIDATE_RET( is224 == 0 ); +#endif -char *yyget_text (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yytext; -} + ctx->total[0] = 0; + ctx->total[1] = 0; -/** Set the user-defined data. This data is never touched by the scanner. - * @param user_defined The data to be associated with this scanner. - * @param yyscanner The scanner object. - */ -void yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyextra = user_defined ; -} + if( is224 == 0 ) + { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } + else + { +#if defined(MBEDTLS_SHA224_C) + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; +#endif + } -/** Set the current line number. - * @param _line_number line number - * @param yyscanner The scanner object. - */ -void yyset_lineno (int _line_number , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + ctx->is224 = is224; - /* lineno is only valid if an input buffer exists. */ - if (! YY_CURRENT_BUFFER ) - YY_FATAL_ERROR( "yyset_lineno called with no buffer" ); - - yylineno = _line_number; + return( 0 ); } -/** Set the current column. - * @param _column_no column number - * @param yyscanner The scanner object. - */ -void yyset_column (int _column_no , yyscan_t yyscanner) +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) +static const uint32_t K[] = { - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, +}; + +#define SHR(x,n) (((x) & 0xFFFFFFFF) >> (n)) +#define ROTR(x,n) (SHR(x,n) | ((x) << (32 - (n)))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + +#define R(t) \ + ( \ + local.W[t] = S1(local.W[(t) - 2]) + local.W[(t) - 7] + \ + S0(local.W[(t) - 15]) + local.W[(t) - 16] \ + ) + +#define P(a,b,c,d,e,f,g,h,x,K) \ + do \ + { \ + local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ + local.temp2 = S2(a) + F0((a),(b),(c)); \ + (d) += local.temp1; (h) = local.temp1 + local.temp2; \ + } while( 0 ) + +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + struct + { + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + } local; - /* column is only valid if an input buffer exists. */ - if (! YY_CURRENT_BUFFER ) - YY_FATAL_ERROR( "yyset_column called with no buffer" ); - - yycolumn = _column_no; -} + unsigned int i; -/** Set the input stream. This does not discard the current - * input buffer. - * @param _in_str A readable stream. - * @param yyscanner The scanner object. - * @see yy_switch_to_buffer - */ -void yyset_in (FILE * _in_str , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyin = _in_str ; -} + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (const unsigned char *)data != NULL ); -void yyset_out (FILE * _out_str , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yyout = _out_str ; -} + for( i = 0; i < 8; i++ ) + local.A[i] = ctx->state[i]; -int yyget_debug (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yy_flex_debug; -} +#if defined(MBEDTLS_SHA256_SMALLER) + for( i = 0; i < 64; i++ ) + { + if( i < 16 ) + local.W[i] = MBEDTLS_GET_UINT32_BE( data, 4 * i ); + else + R( i ); -void yyset_debug (int _bdebug , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yy_flex_debug = _bdebug ; -} + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); -/* Accessor methods for yylval and yylloc */ + local.temp1 = local.A[7]; local.A[7] = local.A[6]; + local.A[6] = local.A[5]; local.A[5] = local.A[4]; + local.A[4] = local.A[3]; local.A[3] = local.A[2]; + local.A[2] = local.A[1]; local.A[1] = local.A[0]; + local.A[0] = local.temp1; + } +#else /* MBEDTLS_SHA256_SMALLER */ + for( i = 0; i < 16; i++ ) + local.W[i] = MBEDTLS_GET_UINT32_BE( data, 4 * i ); -YYSTYPE * yyget_lval (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yylval; -} + for( i = 0; i < 16; i += 8 ) + { + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0] ); + P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], + local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1] ); + P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], + local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2] ); + P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], + local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3] ); + P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], + local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4] ); + P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], + local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5] ); + P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], + local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6] ); + P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], + local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7] ); + } -void yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yylval = yylval_param; -} + for( i = 16; i < 64; i += 8 ) + { + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], R(i+0), K[i+0] ); + P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], + local.A[4], local.A[5], local.A[6], R(i+1), K[i+1] ); + P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], + local.A[3], local.A[4], local.A[5], R(i+2), K[i+2] ); + P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], + local.A[2], local.A[3], local.A[4], R(i+3), K[i+3] ); + P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], + local.A[1], local.A[2], local.A[3], R(i+4), K[i+4] ); + P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], + local.A[0], local.A[1], local.A[2], R(i+5), K[i+5] ); + P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], + local.A[7], local.A[0], local.A[1], R(i+6), K[i+6] ); + P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], + local.A[6], local.A[7], local.A[0], R(i+7), K[i+7] ); + } +#endif /* MBEDTLS_SHA256_SMALLER */ -YYLTYPE *yyget_lloc (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - return yylloc; -} - -void yyset_lloc (YYLTYPE * yylloc_param , yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - yylloc = yylloc_param; + for( i = 0; i < 8; i++ ) + ctx->state[i] += local.A[i]; + + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); } - -/* User-visible API */ -/* yylex_init is special because it creates the scanner itself, so it is - * the ONLY reentrant function that doesn't take the scanner as the last argument. - * That's why we explicitly handle the declaration, instead of using our macros. +#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +/* + * SHA-256 process buffer */ -int yylex_init(yyscan_t* ptr_yy_globals) +int mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) { - if (ptr_yy_globals == NULL){ - errno = EINVAL; - return 1; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + uint32_t left; + + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + + if( ilen == 0 ) + return( 0 ); + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if( ctx->total[0] < (uint32_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; } - *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), NULL ); + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) + return( ret ); - if (*ptr_yy_globals == NULL){ - errno = ENOMEM; - return 1; + input += 64; + ilen -= 64; } - /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ - memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); - return yy_init_globals ( *ptr_yy_globals ); + return( 0 ); } -/* yylex_init_extra has the same functionality as yylex_init, but follows the - * convention of taking the scanner as the last argument. Note however, that - * this is a *pointer* to a scanner, as it will be allocated by this call (and - * is the reason, too, why this function also must handle its own declaration). - * The user defined value in the first argument will be available to yyalloc in - * the yyextra field. +/* + * SHA-256 final digest */ -int yylex_init_extra( YY_EXTRA_TYPE yy_user_defined, yyscan_t* ptr_yy_globals ) +int mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char *output ) { - struct yyguts_t dummy_yyguts; + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + uint32_t used; + uint32_t high, low; - yyset_extra (yy_user_defined, &dummy_yyguts); + SHA256_VALIDATE_RET( ctx != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); - if (ptr_yy_globals == NULL){ - errno = EINVAL; - return 1; + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); - *ptr_yy_globals = (yyscan_t) yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); - if (*ptr_yy_globals == NULL){ - errno = ENOMEM; - return 1; + memset( ctx->buffer, 0, 56 ); } - /* By setting to 0xAA, we expose bugs in - yy_init_globals. Leave at 0x00 for releases. */ - memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); - yyset_extra (yy_user_defined, *ptr_yy_globals); + MBEDTLS_PUT_UINT32_BE( high, ctx->buffer, 56 ); + MBEDTLS_PUT_UINT32_BE( low, ctx->buffer, 60 ); - return yy_init_globals ( *ptr_yy_globals ); -} + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); -static int yy_init_globals (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from yylex_destroy(), so don't allocate here. + /* + * Output final state */ + MBEDTLS_PUT_UINT32_BE( ctx->state[0], output, 0 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[1], output, 4 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[2], output, 8 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[3], output, 12 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[4], output, 16 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[5], output, 20 ); + MBEDTLS_PUT_UINT32_BE( ctx->state[6], output, 24 ); + +#if defined(MBEDTLS_SHA224_C) + if( ctx->is224 == 0 ) +#endif + MBEDTLS_PUT_UINT32_BE( ctx->state[7], output, 28 ); - yyg->yy_buffer_stack = NULL; - yyg->yy_buffer_stack_top = 0; - yyg->yy_buffer_stack_max = 0; - yyg->yy_c_buf_p = NULL; - yyg->yy_init = 0; - yyg->yy_start = 0; + return( 0 ); +} - yyg->yy_start_stack_ptr = 0; - yyg->yy_start_stack_depth = 0; - yyg->yy_start_stack = NULL; +#endif /* !MBEDTLS_SHA256_ALT */ -/* Defined in main.c */ -#ifdef YY_STDINIT - yyin = stdin; - yyout = stdout; +/* + * output = SHA-256( input buffer ) + */ +int mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char *output, + int is224 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha256_context ctx; + +#if defined(MBEDTLS_SHA224_C) + SHA256_VALIDATE_RET( is224 == 0 || is224 == 1 ); #else - yyin = NULL; - yyout = NULL; + SHA256_VALIDATE_RET( is224 == 0 ); #endif - /* For future reference: Set errno on error, since we are called by - * yylex_init() - */ - return 0; -} + SHA256_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA256_VALIDATE_RET( (unsigned char *)output != NULL ); -/* yylex_destroy is for both reentrant and non-reentrant scanners. */ -int yylex_destroy (yyscan_t yyscanner) -{ - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + mbedtls_sha256_init( &ctx ); - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - yy_delete_buffer( YY_CURRENT_BUFFER , yyscanner ); - YY_CURRENT_BUFFER_LVALUE = NULL; - yypop_buffer_state(yyscanner); - } + if( ( ret = mbedtls_sha256_starts( &ctx, is224 ) ) != 0 ) + goto exit; - /* Destroy the stack itself. */ - yyfree(yyg->yy_buffer_stack , yyscanner); - yyg->yy_buffer_stack = NULL; + if( ( ret = mbedtls_sha256_update( &ctx, input, ilen ) ) != 0 ) + goto exit; - /* Destroy the start condition stack. */ - yyfree( yyg->yy_start_stack , yyscanner ); - yyg->yy_start_stack = NULL; + if( ( ret = mbedtls_sha256_finish( &ctx, output ) ) != 0 ) + goto exit; - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * yylex() is called, initialization will occur. */ - yy_init_globals( yyscanner); +exit: + mbedtls_sha256_free( &ctx ); - /* Destroy the main struct (reentrant only). */ - yyfree ( yyscanner , yyscanner ); - yyscanner = NULL; - return 0; + return( ret ); } +#if defined(MBEDTLS_SELF_TEST) /* - * Internal utility routines. + * FIPS-180-2 test vectors */ +static const unsigned char sha256_test_buf[3][57] = +{ + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; -#ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, const char * s2, int n , yyscan_t yyscanner) +static const size_t sha256_test_buflen[3] = { - struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; - (void)yyg; + 3, 56, 1000 +}; - int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; -} -#endif +static const unsigned char sha256_test_sum[6][32] = +{ + /* + * SHA-224 test vectors + */ + { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, + 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, + 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, + 0xE3, 0x6C, 0x9D, 0xA7 }, + { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, + 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, + 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, + 0x52, 0x52, 0x25, 0x25 }, + { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 }, + + /* + * SHA-256 test vectors + */ + { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD }, + { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 }, + { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 } +}; -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen (const char * s , yyscan_t yyscanner) +/* + * Checkup routine + */ +int mbedtls_sha256_self_test( int verbose ) { - int n; - for ( n = 0; s[n]; ++n ) - ; + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha256sum[32]; + mbedtls_sha256_context ctx; - return n; -} -#endif + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); -#define YYTABLES_NAME "yytables" + return( 1 ); + } -#line 1081 "third_party/libpg_query/scan.l" + mbedtls_sha256_init( &ctx ); + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; -/* LCOV_EXCL_STOP */ + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); -/* - * Arrange access to yyextra for subroutines of the main yylex() function. - * We expect each subroutine to have a yyscanner parameter. Rather than - * use the yyget_xxx functions, which might or might not get inlined by the - * compiler, we cheat just a bit and cast yyscanner to the right type. - */ -#undef yyextra -#define yyextra (((struct yyguts_t *) yyscanner)->yyextra_r) + if( ( ret = mbedtls_sha256_starts( &ctx, k ) ) != 0 ) + goto fail; -/* Likewise for a couple of other things we need. */ -#undef yylloc -#define yylloc (((struct yyguts_t *) yyscanner)->yylloc_r) -#undef yyleng -#define yyleng (((struct yyguts_t *) yyscanner)->yyleng_r) + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha256_update( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } -/* - * scanner_errposition - * Report a lexer or grammar error cursor position, if possible. - * - * This is expected to be used within an ereport() call. The return value - * is a dummy (always 0, in fact). - * - * Note that this can only be used for messages emitted during raw parsing - * (essentially, scan.l and gram.y), since it requires the yyscanner struct - * to still be available. - */ -int -scanner_errposition(int location, core_yyscan_t yyscanner) -{ - int pos; + } + else + { + ret = mbedtls_sha256_update( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } - if (location < 0) - return 0; /* no-op if location is unknown */ + if( ( ret = mbedtls_sha256_finish( &ctx, sha256sum ) ) != 0 ) + goto fail; - /* Convert byte offset to character number */ - pos = pg_mbstrlen_with_len(yyextra->scanbuf, location) + 1; - /* And pass it to the ereport mechanism */ - return errposition(pos); -} -/* - * scanner_yyerror - * Report a lexer or grammar error. - * - * The message's cursor position is whatever YYLLOC was last set to, - * ie, the start of the current token if called within yylex(), or the - * most recently lexed token if called from the grammar. - * This is OK for syntax error messages from the Bison parser, because Bison - * parsers report error as soon as the first unparsable token is reached. - * Beware of using yyerror for other purposes, as the cursor position might - * be misleading! - */ -void -scanner_yyerror(const char *message, core_yyscan_t yyscanner) -{ - const char *loc = yyextra->scanbuf + *yylloc; + if( memcmp( sha256sum, sha256_test_sum[i], 32 - k * 4 ) != 0 ) + { + ret = 1; + goto fail; + } - if (*loc == YY_END_OF_BUFFER_CHAR) - { - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - /* translator: %s is typically the translation of "syntax error" */ - errmsg("%s at end of input", _(message)), - lexer_errposition())); - } - else - { - ereport(ERROR, - (errcode(PG_ERRCODE_SYNTAX_ERROR), - /* translator: first %s is typically the translation of "syntax error" */ - errmsg("%s at or near \"%s\"", _(message), loc), - lexer_errposition())); - } -} + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + if( verbose != 0 ) + mbedtls_printf( "\n" ); -/* - * Called before any actual parsing is done - */ -core_yyscan_t -scanner_init(const char *str, - core_yy_extra_type *yyext, - const PGScanKeyword *keywords, - int num_keywords) -{ - PGSize slen = strlen(str); - yyscan_t scanner; + goto exit; - if (yylex_init(&scanner) != 0) - elog(ERROR, "yylex_init() failed: %m"); +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); - core_yyset_extra(yyext, scanner); +exit: + mbedtls_sha256_free( &ctx ); + mbedtls_free( buf ); - yyext->keywords = keywords; - yyext->num_keywords = num_keywords; + return( ret ); +} - yyext->backslash_quote = backslash_quote; - yyext->escape_string_warning = escape_string_warning; - yyext->standard_conforming_strings = standard_conforming_strings; +#endif /* MBEDTLS_SELF_TEST */ - /* - * Make a scan buffer with special termination needed by flex. - */ - yyext->scanbuf = (char *) palloc(slen + 2); - yyext->scanbuflen = slen; - memcpy(yyext->scanbuf, str, slen); - yyext->scanbuf[slen] = yyext->scanbuf[slen + 1] = YY_END_OF_BUFFER_CHAR; - yy_scan_buffer(yyext->scanbuf, slen + 2, scanner); +#endif /* MBEDTLS_SHA256_C */ - /* initialize literal buffer to a reasonable but expansible size */ - yyext->literalalloc = 1024; - yyext->literalbuf = (char *) palloc(yyext->literalalloc); - yyext->literallen = 0; - return scanner; -} +// LICENSE_CHANGE_END +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 +// See the end of this file for a list + /* - * Called after parsing is done to clean up after scanner_init() + * FIPS-180-2 compliant SHA-384/512 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The SHA-512 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf */ -void -scanner_finish(core_yyscan_t yyscanner) -{ - /* - * We don't bother to call yylex_destroy(), because all it would do is - * pfree a small amount of control storage. It's cheaper to leak the - * storage until the parsing context is destroyed. The amount of space - * involved is usually negligible compared to the output parse tree - * anyway. - * - * We do bother to pfree the scanbuf and literal buffer, but only if they - * represent a nontrivial amount of space. The 8K cutoff is arbitrary. - */ - if (yyextra->scanbuflen >= 8192) - pfree(yyextra->scanbuf); - if (yyextra->literalalloc >= 8192) - pfree(yyextra->literalbuf); -} -static void -addlit(char *ytext, int yleng, core_yyscan_t yyscanner) -{ - /* enlarge buffer if needed */ - if ((yyextra->literallen + yleng) >= yyextra->literalalloc) - { - do - { - yyextra->literalalloc *= 2; - } while ((yyextra->literallen + yleng) >= yyextra->literalalloc); - yyextra->literalbuf = (char *) repalloc(yyextra->literalbuf, - yyextra->literalalloc); - } - /* append new data */ - memcpy(yyextra->literalbuf + yyextra->literallen, ytext, yleng); - yyextra->literallen += yleng; -} +#if defined(MBEDTLS_SHA512_C) + + + + + +#if defined(_MSC_VER) || defined(__WATCOMC__) + #define UL64(x) x##ui64 +#else + #define UL64(x) x##ULL +#endif + +#include -static void -addlitchar(unsigned char ychar, core_yyscan_t yyscanner) -{ - /* enlarge buffer if needed */ - if ((yyextra->literallen + 1) >= yyextra->literalalloc) - { - yyextra->literalalloc *= 2; - yyextra->literalbuf = (char *) repalloc(yyextra->literalbuf, - yyextra->literalalloc); - } - /* append new data */ - yyextra->literalbuf[yyextra->literallen] = ychar; - yyextra->literallen += 1; -} +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ -/* - * Create a palloc'd copy of literalbuf, adding a trailing null. - */ -static char * -litbufdup(core_yyscan_t yyscanner) -{ - int llen = yyextra->literallen; - char *newbuf; +#define SHA512_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ) +#define SHA512_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) - newbuf = (char*) palloc(llen + 1); - memcpy(newbuf, yyextra->literalbuf, llen); - newbuf[llen] = '\0'; - return newbuf; -} +#if !defined(MBEDTLS_SHA512_ALT) -static int -process_integer_literal(const char *token, YYSTYPE *lval) +#if defined(MBEDTLS_SHA512_SMALLER) +static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i ) { - long val; - char *endptr; - - errno = 0; - val = strtol(token, &endptr, 10); - if (*endptr != '\0' || errno == ERANGE - /* if long > 32 bits, check for overflow of int4_t */ - || val != (long) ((int32_t) val) ) - { - /* integer too large, treat it as a float */ - lval->str = pstrdup(token); - return FCONST; - } - lval->ival = val; - return ICONST; + MBEDTLS_PUT_UINT64_BE(n, b, i); } +#else +#define sha512_put_uint64_be MBEDTLS_PUT_UINT64_BE +#endif /* MBEDTLS_SHA512_SMALLER */ -static unsigned int -hexval(unsigned char c) +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) { - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 0xA; - if (c >= 'A' && c <= 'F') - return c - 'A' + 0xA; - elog(ERROR, "invalid hexadecimal digit"); - return 0; /* not reached */ + SHA512_VALIDATE( ctx != NULL ); + + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); } -static void -check_unicode_value(pg_wchar c, char *loc, core_yyscan_t yyscanner) +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) { - // database encoding is always UTF8 - // if (GetDatabaseEncoding() == PG_UTF8) - // return; + if( ctx == NULL ) + return; - // if (c > 0x7F) - // { - // ADVANCE_YYLLOC(loc - yyextra->literalbuf + 3); /* 3 for U&" */ - // yyerror("Unicode escape values cannot be used for code point values above 007F when the server encoding is not UTF8"); - // } + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); } -static bool -is_utf16_surrogate_first(pg_wchar c) +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ) { - return (c >= 0xD800 && c <= 0xDBFF); -} + SHA512_VALIDATE( dst != NULL ); + SHA512_VALIDATE( src != NULL ); -static bool -is_utf16_surrogate_second(pg_wchar c) -{ - return (c >= 0xDC00 && c <= 0xDFFF); + *dst = *src; } -static pg_wchar -surrogate_pair_to_codepoint(pg_wchar first, pg_wchar second) +/* + * SHA-512 context setup + */ +int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) { - return ((first & 0x3FF) << 10) + 0x10000 + (second & 0x3FF); -} + SHA512_VALIDATE_RET( ctx != NULL ); +#if defined(MBEDTLS_SHA384_C) + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); +#else + SHA512_VALIDATE_RET( is384 == 0 ); +#endif -static void -addunicode(pg_wchar c, core_yyscan_t yyscanner) -{ - char buf[8]; + ctx->total[0] = 0; + ctx->total[1] = 0; - if (c == 0 || c > 0x10FFFF) - yyerror("invalid Unicode escape value"); - if (c > 0x7F) - { - // if (GetDatabaseEncoding() != PG_UTF8) - // yyerror("Unicode escape values cannot be used for code point values above 007F when the server encoding is not UTF8"); - yyextra->saw_non_ascii = true; - } - unicode_to_utf8(c, (unsigned char *) buf); - addlit(buf, pg_mblen(buf), yyscanner); -} + if( is384 == 0 ) + { + /* SHA-512 */ + ctx->state[0] = UL64(0x6A09E667F3BCC908); + ctx->state[1] = UL64(0xBB67AE8584CAA73B); + ctx->state[2] = UL64(0x3C6EF372FE94F82B); + ctx->state[3] = UL64(0xA54FF53A5F1D36F1); + ctx->state[4] = UL64(0x510E527FADE682D1); + ctx->state[5] = UL64(0x9B05688C2B3E6C1F); + ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); + ctx->state[7] = UL64(0x5BE0CD19137E2179); + } + else + { +#if !defined(MBEDTLS_SHA384_C) + return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA ); +#else + /* SHA-384 */ + ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); + ctx->state[1] = UL64(0x629A292A367CD507); + ctx->state[2] = UL64(0x9159015A3070DD17); + ctx->state[3] = UL64(0x152FECD8F70E5939); + ctx->state[4] = UL64(0x67332667FFC00B31); + ctx->state[5] = UL64(0x8EB44A8768581511); + ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); + ctx->state[7] = UL64(0x47B5481DBEFA4FA4); +#endif /* MBEDTLS_SHA384_C */ + } -/* is 'escape' acceptable as Unicode escape character (UESCAPE syntax) ? */ -static bool -check_uescapechar(unsigned char escape) -{ - if (isxdigit(escape) - || escape == '+' - || escape == '\'' - || escape == '"' - || scanner_isspace(escape)) - { - return false; - } - else - return true; +#if defined(MBEDTLS_SHA384_C) + ctx->is384 = is384; +#endif + + return( 0 ); } -/* like litbufdup, but handle unicode escapes */ -static char * -litbuf_udeescape(unsigned char escape, core_yyscan_t yyscanner) +#if !defined(MBEDTLS_SHA512_PROCESS_ALT) + +/* + * Round constants + */ +static const uint64_t K[80] = { - char *newbuf; - char *litbuf, - *in, - *out; - pg_wchar pair_first = 0; + UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), + UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), + UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), + UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), + UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), + UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), + UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), + UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), + UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), + UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), + UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), + UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), + UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), + UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), + UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), + UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), + UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), + UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), + UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), + UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), + UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), + UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), + UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), + UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), + UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), + UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), + UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), + UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), + UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), + UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), + UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), + UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), + UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), + UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), + UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), + UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), + UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), + UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), + UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), + UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) +}; + +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + int i; + struct + { + uint64_t temp1, temp2, W[80]; + uint64_t A[8]; + } local; - /* Make literalbuf null-terminated to simplify the scanning loop */ - litbuf = yyextra->literalbuf; - litbuf[yyextra->literallen] = '\0'; + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (const unsigned char *)data != NULL ); - /* - * This relies on the subtle assumption that a UTF-8 expansion cannot be - * longer than its escaped representation. - */ - newbuf = (char*) palloc(yyextra->literallen + 1); +#define SHR(x,n) ((x) >> (n)) +#define ROTR(x,n) (SHR((x),(n)) | ((x) << (64 - (n)))) - in = litbuf; - out = newbuf; - while (*in) - { - if (in[0] == escape) - { - if (in[1] == escape) - { - if (pair_first) - { - ADVANCE_YYLLOC(in - litbuf + 3); /* 3 for U&" */ - yyerror("invalid Unicode surrogate pair"); - } - *out++ = escape; - in += 2; - } - else if (isxdigit((unsigned char) in[1]) && - isxdigit((unsigned char) in[2]) && - isxdigit((unsigned char) in[3]) && - isxdigit((unsigned char) in[4])) - { - pg_wchar unicode; +#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) - unicode = (hexval(in[1]) << 12) + - (hexval(in[2]) << 8) + - (hexval(in[3]) << 4) + - hexval(in[4]); - check_unicode_value(unicode, in, yyscanner); - if (pair_first) - { - if (is_utf16_surrogate_second(unicode)) - { - unicode = surrogate_pair_to_codepoint(pair_first, unicode); - pair_first = 0; - } - else - { - ADVANCE_YYLLOC(in - litbuf + 3); /* 3 for U&" */ - yyerror("invalid Unicode surrogate pair"); - } - } - else if (is_utf16_surrogate_second(unicode)) - yyerror("invalid Unicode surrogate pair"); +#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) - if (is_utf16_surrogate_first(unicode)) - pair_first = unicode; - else - { - unicode_to_utf8(unicode, (unsigned char *) out); - out += pg_mblen(out); - } - in += 5; - } - else if (in[1] == '+' && - isxdigit((unsigned char) in[2]) && - isxdigit((unsigned char) in[3]) && - isxdigit((unsigned char) in[4]) && - isxdigit((unsigned char) in[5]) && - isxdigit((unsigned char) in[6]) && - isxdigit((unsigned char) in[7])) - { - pg_wchar unicode; +#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y)))) +#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) - unicode = (hexval(in[2]) << 20) + - (hexval(in[3]) << 16) + - (hexval(in[4]) << 12) + - (hexval(in[5]) << 8) + - (hexval(in[6]) << 4) + - hexval(in[7]); - check_unicode_value(unicode, in, yyscanner); - if (pair_first) - { - if (is_utf16_surrogate_second(unicode)) - { - unicode = surrogate_pair_to_codepoint(pair_first, unicode); - pair_first = 0; - } - else - { - ADVANCE_YYLLOC(in - litbuf + 3); /* 3 for U&" */ - yyerror("invalid Unicode surrogate pair"); - } - } - else if (is_utf16_surrogate_second(unicode)) - yyerror("invalid Unicode surrogate pair"); +#define P(a,b,c,d,e,f,g,h,x,K) \ + do \ + { \ + local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \ + local.temp2 = S2(a) + F0((a),(b),(c)); \ + (d) += local.temp1; (h) = local.temp1 + local.temp2; \ + } while( 0 ) - if (is_utf16_surrogate_first(unicode)) - pair_first = unicode; - else - { - unicode_to_utf8(unicode, (unsigned char *) out); - out += pg_mblen(out); - } - in += 8; - } - else - { - ADVANCE_YYLLOC(in - litbuf + 3); /* 3 for U&" */ - yyerror("invalid Unicode escape value"); - } - } - else - { - if (pair_first) - { - ADVANCE_YYLLOC(in - litbuf + 3); /* 3 for U&" */ - yyerror("invalid Unicode surrogate pair"); - } - *out++ = *in++; - } - } + for( i = 0; i < 8; i++ ) + local.A[i] = ctx->state[i]; - /* unfinished surrogate pair? */ - if (pair_first) - { - ADVANCE_YYLLOC(in - litbuf + 3); /* 3 for U&" */ - yyerror("invalid Unicode surrogate pair"); - } +#if defined(MBEDTLS_SHA512_SMALLER) + for( i = 0; i < 80; i++ ) + { + if( i < 16 ) + { + local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 ); + } + else + { + local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] + + S0(local.W[i - 15]) + local.W[i - 16]; + } - *out = '\0'; + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); - /* - * We could skip pg_verifymbstr if we didn't process any non-7-bit-ASCII - * codes; but it's probably not worth the trouble, since this isn't likely - * to be a performance-critical path. - */ - pg_verifymbstr(newbuf, out - newbuf, false); - return newbuf; -} + local.temp1 = local.A[7]; local.A[7] = local.A[6]; + local.A[6] = local.A[5]; local.A[5] = local.A[4]; + local.A[4] = local.A[3]; local.A[3] = local.A[2]; + local.A[2] = local.A[1]; local.A[1] = local.A[0]; + local.A[0] = local.temp1; + } +#else /* MBEDTLS_SHA512_SMALLER */ + for( i = 0; i < 16; i++ ) + { + local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 ); + } -static unsigned char -unescape_single_char(unsigned char c, core_yyscan_t yyscanner) -{ - switch (c) - { - case 'b': - return '\b'; - case 'f': - return '\f'; - case 'n': - return '\n'; - case 'r': - return '\r'; - case 't': - return '\t'; - default: - /* check for backslash followed by non-7-bit-ASCII */ - if (c == '\0' || IS_HIGHBIT_SET(c)) - yyextra->saw_non_ascii = true; + for( ; i < 80; i++ ) + { + local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] + + S0(local.W[i - 15]) + local.W[i - 16]; + } - return c; - } -} + i = 0; + do + { + P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4], + local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); i++; + P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3], + local.A[4], local.A[5], local.A[6], local.W[i], K[i] ); i++; + P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2], + local.A[3], local.A[4], local.A[5], local.W[i], K[i] ); i++; + P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1], + local.A[2], local.A[3], local.A[4], local.W[i], K[i] ); i++; + P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0], + local.A[1], local.A[2], local.A[3], local.W[i], K[i] ); i++; + P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7], + local.A[0], local.A[1], local.A[2], local.W[i], K[i] ); i++; + P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6], + local.A[7], local.A[0], local.A[1], local.W[i], K[i] ); i++; + P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5], + local.A[6], local.A[7], local.A[0], local.W[i], K[i] ); i++; + } + while( i < 80 ); +#endif /* MBEDTLS_SHA512_SMALLER */ -static void -check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner) -{ - if (ychar == '\'') - { - if (yyextra->warn_on_first_escape && yyextra->escape_string_warning) - ereport(PGWARNING, - (errcode(PG_ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), - errmsg("nonstandard use of \\' in a string literal"), - errhint("Use '' to write quotes in strings, or use the escape string syntax (E'...')."), - lexer_errposition())); - yyextra->warn_on_first_escape = false; /* warn only once per string */ - } - else if (ychar == '\\') - { - if (yyextra->warn_on_first_escape && yyextra->escape_string_warning) - ereport(PGWARNING, - (errcode(PG_ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), - errmsg("nonstandard use of \\\\ in a string literal"), - errhint("Use the escape string syntax for backslashes, e.g., E'\\\\'."), - lexer_errposition())); - yyextra->warn_on_first_escape = false; /* warn only once per string */ - } - else - check_escape_warning(yyscanner); -} + for( i = 0; i < 8; i++ ) + ctx->state[i] += local.A[i]; -static void -check_escape_warning(core_yyscan_t yyscanner) -{ - if (yyextra->warn_on_first_escape && yyextra->escape_string_warning) - ereport(PGWARNING, - (errcode(PG_ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), - errmsg("nonstandard use of escape in a string literal"), - errhint("Use the escape string syntax for escapes, e.g., E'\\r\\n'."), - lexer_errposition())); - yyextra->warn_on_first_escape = false; /* warn only once per string */ + /* Zeroise buffers and variables to clear sensitive data from memory. */ + mbedtls_platform_zeroize( &local, sizeof( local ) ); + + return( 0 ); } +#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ + /* - * Interface functions to make flex use palloc() instead of malloc(). - * It'd be better to make these static, but flex insists otherwise. + * SHA-512 process buffer */ - -void * -core_yyalloc(yy_size_t bytes, core_yyscan_t yyscanner) +int mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) { - return palloc(bytes); -} + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + size_t fill; + unsigned int left; -void * -core_yyrealloc(void *ptr, yy_size_t bytes, core_yyscan_t yyscanner) -{ - if (ptr) - return repalloc(ptr, bytes); - else - return palloc(bytes); -} + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); -void -core_yyfree(void *ptr, core_yyscan_t yyscanner) -{ - if (ptr) - pfree(ptr); -} + if( ilen == 0 ) + return( 0 ); -#undef yyerror -#undef yylloc -#undef yylval -#undef yyin -#undef yyout -#undef yyextra -#undef yyleng -#undef yytext -#undef yylineno -#undef yycolumn -#undef yy_flex_debug -#undef yyless -#undef YYSTYPE -#undef YY_EXTRA_TYPE -#undef SET_YYLLOC -#undef ADVANCE_YYLLOC -#undef BEGIN -#undef REJECT -#undef INITIAL -#undef xb -#undef xc -#undef xd -#undef xh -#undef xe -#undef xq -#undef xdolq -#undef xui -#undef xuiend -#undef xus -#undef xusend -#undef xeu -#undef ECHO + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = 128 - left; + ctx->total[0] += (uint64_t) ilen; -} /* duckdb_libpgquery */ + if( ctx->total[0] < (uint64_t) ilen ) + ctx->total[1]++; + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); -// LICENSE_CHANGE_END + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + input += fill; + ilen -= fill; + left = 0; + } -// LICENSE_CHANGE_BEGIN -// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 -// See the end of this file for a list + while( ilen >= 128 ) + { + if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) + return( ret ); -/*-------------------------------------------------------------------- - * Symbols referenced in this file: - * - truncate_identifier - * - downcase_truncate_identifier - * - downcase_identifier - * - scanner_isspace - *-------------------------------------------------------------------- - */ + input += 128; + ilen -= 128; + } -/*------------------------------------------------------------------------- - * - * scansup.c - * support routines for the lex/flex scanner, used by both the normal - * backend as well as the bootstrap backend - * - * Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * src/backend/parser/scansup.c - * - *------------------------------------------------------------------------- + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +/* + * SHA-512 final digest */ +int mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char *output ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + unsigned used; + uint64_t high, low; -#include + SHA512_VALIDATE_RET( ctx != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); -#include + /* + * Add padding: 0x80 then 0x00 until 16 bytes remain for the length + */ + used = ctx->total[0] & 0x7F; + ctx->buffer[used++] = 0x80; + if( used <= 112 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 112 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 128 - used ); + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); -namespace duckdb_libpgquery { + memset( ctx->buffer, 0, 112 ); + } -/* ---------------- - * scanstr - * - * if the string passed in has escaped codes, map the escape codes to actual - * chars - * - * the string returned is palloc'd and should eventually be pfree'd by the - * caller! - * ---------------- - */ + /* + * Add message length + */ + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); -/* - * downcase_truncate_identifier() --- do appropriate downcasing and - * truncation of an unquoted identifier. Optionally warn of truncation. - * - * Returns a palloc'd string containing the adjusted identifier. - * - * Note: in some usages the passed string is not null-terminated. - * - * Note: the API of this function is designed to allow for downcasing - * transformations that increase the string length, but we don't yet - * support that. If you want to implement it, you'll need to fix - * SplitIdentifierString() in utils/adt/varlena.c. - */ -char *downcase_truncate_identifier(const char *ident, int len, bool warn) { - return downcase_identifier(ident, len, warn, true); -} + sha512_put_uint64_be( high, ctx->buffer, 112 ); + sha512_put_uint64_be( low, ctx->buffer, 120 ); -static __thread bool pg_preserve_identifier_case = false; + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); -void set_preserve_identifier_case(bool preserve) { - pg_preserve_identifier_case = preserve; -} + /* + * Output final state + */ + sha512_put_uint64_be( ctx->state[0], output, 0 ); + sha512_put_uint64_be( ctx->state[1], output, 8 ); + sha512_put_uint64_be( ctx->state[2], output, 16 ); + sha512_put_uint64_be( ctx->state[3], output, 24 ); + sha512_put_uint64_be( ctx->state[4], output, 32 ); + sha512_put_uint64_be( ctx->state[5], output, 40 ); + +#if defined(MBEDTLS_SHA384_C) + if( ctx->is384 == 0 ) +#endif + { + sha512_put_uint64_be( ctx->state[6], output, 48 ); + sha512_put_uint64_be( ctx->state[7], output, 56 ); + } -bool get_preserve_identifier_case() { - return pg_preserve_identifier_case; + return( 0 ); } +#endif /* !MBEDTLS_SHA512_ALT */ + /* - * a workhorse for downcase_truncate_identifier + * output = SHA-512( input buffer ) */ -char *downcase_identifier(const char *ident, int len, bool warn, bool truncate) { - char *result; - int i; - bool enc_is_single_byte; +int mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char *output, + int is384 ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha512_context ctx; - result = (char *)palloc(len + 1); - enc_is_single_byte = pg_database_encoding_max_length() == 1; +#if defined(MBEDTLS_SHA384_C) + SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 ); +#else + SHA512_VALIDATE_RET( is384 == 0 ); +#endif + SHA512_VALIDATE_RET( ilen == 0 || input != NULL ); + SHA512_VALIDATE_RET( (unsigned char *)output != NULL ); - /* - * SQL99 specifies Unicode-aware case normalization, which we don't yet - * have the infrastructure for. Instead we use tolower() to provide a - * locale-aware translation. However, there are some locales where this - * is not right either (eg, Turkish may do strange things with 'i' and - * 'I'). Our current compromise is to use tolower() for characters with - * the high bit set, as long as they aren't part of a multi-byte - * character, and use an ASCII-only downcasing for 7-bit characters. - */ - for (i = 0; i < len; i++) { - unsigned char ch = (unsigned char)ident[i]; + mbedtls_sha512_init( &ctx ); - if (!get_preserve_identifier_case()) { - if (ch >= 'A' && ch <= 'Z') - ch += 'a' - 'A'; - else if (enc_is_single_byte && IS_HIGHBIT_SET(ch) && isupper(ch)) - ch = tolower(ch); - } - result[i] = (char)ch; - } - result[i] = '\0'; + if( ( ret = mbedtls_sha512_starts( &ctx, is384 ) ) != 0 ) + goto exit; - return result; + if( ( ret = mbedtls_sha512_update( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_finish( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha512_free( &ctx ); + + return( ret ); } +#if defined(MBEDTLS_SELF_TEST) + /* - * scanner_isspace() --- return true if flex scanner considers char whitespace - * - * This should be used instead of the potentially locale-dependent isspace() - * function when it's important to match the lexer's behavior. - * - * In principle we might need similar functions for isalnum etc, but for the - * moment only isspace seems needed. + * FIPS-180-2 test vectors */ -bool scanner_isspace(char ch) { - /* This must match scan.l's list of {space} characters */ - if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '\f') - return true; - return false; -} +static const unsigned char sha512_test_buf[3][113] = +{ + { "abc" }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, + { "" } +}; + +static const size_t sha512_test_buflen[3] = +{ + 3, 112, 1000 +}; + +static const unsigned char sha512_test_sum[][64] = +{ +#if defined(MBEDTLS_SHA384_C) + /* + * SHA-384 test vectors + */ + { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, + 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, + 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, + 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, + 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, + 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, + { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, + 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, + 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, + 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, + 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, + 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, + { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, + 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, + 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, + 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, + 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, + 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, +#endif /* MBEDTLS_SHA384_C */ + + /* + * SHA-512 test vectors + */ + { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, + 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, + 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, + 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, + 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, + 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, + 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, + 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, + { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, + 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, + 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, + 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, + 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, + 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, + 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, + 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, + { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, + 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, + 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, + 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, + 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, + 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, + 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, + 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } +}; + +#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( ( a )[0] ) ) + +/* + * Checkup routine + */ +int mbedtls_sha512_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha512sum[64]; + mbedtls_sha512_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha512_init( &ctx ); + + for( i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++ ) + { + j = i % 3; +#if defined(MBEDTLS_SHA384_C) + k = i < 3; +#else + k = 0; +#endif + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); + + if( ( ret = mbedtls_sha512_starts( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha512_update( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha512_update( &ctx, sha512_test_buf[j], + sha512_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha512_finish( &ctx, sha512sum ) ) != 0 ) + goto fail; + + if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha512_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); } +#undef ARRAY_LENGTH + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA512_C */ + + // LICENSE_CHANGE_END @@ -283606,101 +328630,69 @@ bool scanner_isspace(char ch) { // The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #11 // See the end of this file for a list -/*-------------------------------------------------------------------- - * Symbols referenced in this file: - * - ScanKeywords - * - NumScanKeywords - * - ScanKeywordLookup - *-------------------------------------------------------------------- - */ - -/*------------------------------------------------------------------------- - * - * keywords.c - * lexical token lookup for key words in PostgreSQL - * - * - * Portions Copyright (c) 1996-2017, PostgreSQL Global Development PGGroup - * Portions Copyright (c) 1994, Regents of the University of California - * - * - * IDENTIFICATION - * src/common/keywords.c - * - *------------------------------------------------------------------------- - */ -#include -#include -#include +#include -namespace duckdb_libpgquery { +using namespace std; +using namespace duckdb_mbedtls; /* - * ScanKeywordLookup - see if a given word is a keyword - * - * The table to be searched is passed explicitly, so that this can be used - * to search keyword lists other than the standard list appearing above. - * - * Returns a pointer to the PGScanKeyword table entry, or NULL if no match. - * - * The match is done case-insensitively. Note that we deliberately use a - * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z', - * even if we are in a locale where tolower() would produce more or different - * translations. This is to conform to the SQL99 spec, which says that - * keywords are to be matched in this way even though non-keyword identifiers - * receive a different case-normalization mapping. - */ -const PGScanKeyword *ScanKeywordLookup(const char *text, const PGScanKeyword *keywords, int num_keywords) { - int len, i; - const PGScanKeyword *low; - const PGScanKeyword *high; +# Command line tricks to help here +# Create a new key +openssl genrsa -out private.pem 2048 - len = strlen(text); - auto data = std::unique_ptr(new char[len + 1]); - auto word = data.get(); - /* We assume all keywords are shorter than NAMEDATALEN. */ +# Export public key +openssl rsa -in private.pem -outform PEM -pubout -out public.pem - /* - * Apply an ASCII-only downcasing. We must not use tolower() since it may - * produce the wrong translation in some locales (eg, Turkish). - */ - for (i = 0; i < len; i++) { - char ch = text[i]; +# Calculate digest and write to 'hash' file on command line +openssl dgst -binary -sha256 dummy > hash - if (ch >= 'A' && ch <= 'Z') - ch += 'a' - 'A'; - word[i] = ch; +# Calculate signature from hash +openssl pkeyutl -sign -in hash -inkey private.pem -pkeyopt digest:sha256 -out dummy.sign +*/ + + +string MbedTlsWrapper::ComputeSha256Hash(const string& file_content) { + string hash; + hash.resize(32); + + mbedtls_sha256_context sha_context; + mbedtls_sha256_init(&sha_context); + if(mbedtls_sha256_starts(&sha_context, false) || mbedtls_sha256_update(&sha_context, (const unsigned char*) file_content.data(), file_content.size()) || mbedtls_sha256_finish(&sha_context, (unsigned char*)hash.data())) { + throw runtime_error("SHA256 Error"); } - word[len] = '\0'; + mbedtls_sha256_free(&sha_context); + return hash; +} - /* - * Now do a binary search using plain strcmp() comparison. - */ - low = keywords; - high = keywords + (num_keywords - 1); - while (low <= high) { - const PGScanKeyword *middle; - int difference; +bool MbedTlsWrapper::IsValidSha256Signature(const std::string &pubkey, const std::string &signature, const std::string &sha256_hash) { - middle = low + (high - low) / 2; - difference = strcmp(middle->name, word); - if (difference == 0) - return middle; - else if (difference < 0) - low = middle + 1; - else - high = middle - 1; + if (signature.size() != 256 || sha256_hash.size() != 32) { + throw std::runtime_error("Invalid input lengths, expected signature length 256, got " + to_string(signature.size()) + ", hash length 32, got " + to_string(sha256_hash.size())); } - return NULL; -} + mbedtls_pk_context pk_context; + mbedtls_pk_init(&pk_context); + + if (mbedtls_pk_parse_public_key( &pk_context, + (const unsigned char*) pubkey.c_str(),pubkey.size() + 1 )) { + throw runtime_error("RSA public key import error"); + } + + // actually verify + bool valid = mbedtls_pk_verify(&pk_context, MBEDTLS_MD_SHA256, + (const unsigned char*) sha256_hash.data(), sha256_hash.size(), + (const unsigned char*)signature.data(), signature.length()) == 0; + + mbedtls_pk_free(&pk_context); + return valid; } + // LICENSE_CHANGE_END @@ -283710,6 +328702,29 @@ const PGScanKeyword *ScanKeywordLookup(const char *text, const PGScanKeyword *ke ### THIRD PARTY LICENSE #1 ### +Copyright (c) 2012 Art.sy, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +### THIRD PARTY LICENSE #2 ### + Copyright (c) 2012 - present, Victor Zverovich Permission is hereby granted, free of charge, to any person obtaining @@ -283740,7 +328755,7 @@ without including the above copyright and permission notices. -### THIRD PARTY LICENSE #2 ### +### THIRD PARTY LICENSE #3 ### ## utf8proc license ## @@ -283838,7 +328853,7 @@ trademarks mentioned herein are the property of their respective owners. -### THIRD PARTY LICENSE #3 ### +### THIRD PARTY LICENSE #4 ### Copyright 2013-2014 RAD Game Tools and Valve Software Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC @@ -283865,7 +328880,39 @@ THE SOFTWARE. -### THIRD PARTY LICENSE #4 ### +### THIRD PARTY LICENSE #5 ### + +// Copyright (c) 2009 The RE2 Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +### THIRD PARTY LICENSE #6 ### Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated @@ -283893,7 +328940,7 @@ DEALINGS IN THE SOFTWARE. -### THIRD PARTY LICENSE #5 ### +### THIRD PARTY LICENSE #7 ### Copyright (c) 2014-2017 Melissa O'Neill and PCG Project contributors @@ -283916,61 +328963,6 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -### THIRD PARTY LICENSE #6 ### - -// Copyright (c) 2009 The RE2 Authors. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - - -### THIRD PARTY LICENSE #7 ### - -Copyright (c) 2012 Art.sy, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - ### THIRD PARTY LICENSE #8 ### Apache License @@ -284178,6 +329170,31 @@ SOFTWARE. ### THIRD PARTY LICENSE #9 ### +Copyright © 2022 Max Bachmann + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + + +### THIRD PARTY LICENSE #10 ### + The MIT License (MIT) Copyright (c) 2017 yhirose @@ -284203,7 +329220,214 @@ SOFTWARE. -### THIRD PARTY LICENSE #10 ### +### THIRD PARTY LICENSE #11 ### + + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +### THIRD PARTY LICENSE #12 ### This license file applies to everything in this repository except that which is explicitly annotated as being written by other authors, i.e. the Boost @@ -284269,7 +329493,7 @@ DEALINGS IN THE SOFTWARE. -### THIRD PARTY LICENSE #11 ### +### THIRD PARTY LICENSE #13 ### Copyright (c) 2015, Lukas Fittl All rights reserved. @@ -284301,7 +329525,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -### THIRD PARTY LICENSE #12 ### +### THIRD PARTY LICENSE #14 ### Apache License Version 2.0, January 2004 diff --git a/libduckdb-sys/duckdb/duckdb.h b/libduckdb-sys/duckdb/duckdb.h index ad89d3f8..9cf278e8 100644 --- a/libduckdb-sys/duckdb/duckdb.h +++ b/libduckdb-sys/duckdb/duckdb.h @@ -229,6 +229,7 @@ typedef struct { typedef void *duckdb_database; typedef void *duckdb_connection; typedef void *duckdb_prepared_statement; +typedef void *duckdb_pending_result; typedef void *duckdb_appender; typedef void *duckdb_arrow; typedef void *duckdb_config; @@ -240,6 +241,11 @@ typedef void *duckdb_vector; typedef void *duckdb_value; typedef enum { DuckDBSuccess = 0, DuckDBError = 1 } duckdb_state; +typedef enum { + DUCKDB_PENDING_RESULT_READY = 0, + DUCKDB_PENDING_RESULT_NOT_READY = 1, + DUCKDB_PENDING_ERROR = 2 +} duckdb_pending_state; //===--------------------------------------------------------------------===// // Open/Connect @@ -488,7 +494,7 @@ Returns the error message contained within the result. The error is only set if The result of this function must not be freed. It will be cleaned up when `duckdb_destroy_result` is called. -* result: The result object to fetch the nullmask from. +* result: The result object to fetch the error from. * returns: The error of the result. */ DUCKDB_API const char *duckdb_result_error(duckdb_result *result); @@ -815,6 +821,11 @@ Returns `DUCKDB_TYPE_INVALID` if the parameter index is out of range or the stat */ DUCKDB_API duckdb_type duckdb_param_type(duckdb_prepared_statement prepared_statement, idx_t param_idx); +/*! +Clear the params bind to the prepared statement. +*/ +DUCKDB_API duckdb_state duckdb_clear_bindings(duckdb_prepared_statement prepared_statement); + /*! Binds a bool value to the prepared statement at the specified index. */ @@ -946,6 +957,67 @@ Executes the prepared statement with the given bound parameters, and returns an DUCKDB_API duckdb_state duckdb_execute_prepared_arrow(duckdb_prepared_statement prepared_statement, duckdb_arrow *out_result); +//===--------------------------------------------------------------------===// +// Pending Result Interface +//===--------------------------------------------------------------------===// +/*! +Executes the prepared statement with the given bound parameters, and returns a pending result. +The pending result represents an intermediate structure for a query that is not yet fully executed. +The pending result can be used to incrementally execute a query, returning control to the client between tasks. + +Note that after calling `duckdb_pending_prepared`, the pending result should always be destroyed using +`duckdb_destroy_pending`, even if this function returns DuckDBError. + +* prepared_statement: The prepared statement to execute. +* out_result: The pending query result. +* returns: `DuckDBSuccess` on success or `DuckDBError` on failure. +*/ +DUCKDB_API duckdb_state duckdb_pending_prepared(duckdb_prepared_statement prepared_statement, + duckdb_pending_result *out_result); + +/*! +Closes the pending result and de-allocates all memory allocated for the result. + +* pending_result: The pending result to destroy. +*/ +DUCKDB_API void duckdb_destroy_pending(duckdb_pending_result *pending_result); + +/*! +Returns the error message contained within the pending result. + +The result of this function must not be freed. It will be cleaned up when `duckdb_destroy_pending` is called. + +* result: The pending result to fetch the error from. +* returns: The error of the pending result. +*/ +DUCKDB_API const char *duckdb_pending_error(duckdb_pending_result pending_result); + +/*! +Executes a single task within the query, returning whether or not the query is ready. + +If this returns DUCKDB_PENDING_RESULT_READY, the duckdb_execute_pending function can be called to obtain the result. +If this returns DUCKDB_PENDING_RESULT_NOT_READY, the duckdb_pending_execute_task function should be called again. +If this returns DUCKDB_PENDING_ERROR, an error occurred during execution. + +The error message can be obtained by calling duckdb_pending_error on the pending_result. + +* pending_result: The pending result to execute a task within.. +* returns: The state of the pending result after the execution. +*/ +DUCKDB_API duckdb_pending_state duckdb_pending_execute_task(duckdb_pending_result pending_result); + +/*! +Fully execute a pending query result, returning the final query result. + +If duckdb_pending_execute_task has been called until DUCKDB_PENDING_RESULT_READY was returned, this will return fast. +Otherwise, all remaining tasks must be executed first. + +* pending_result: The pending result to execute. +* out_result: The result object. +* returns: `DuckDBSuccess` on success or `DuckDBError` on failure. +*/ +DUCKDB_API duckdb_state duckdb_execute_pending(duckdb_pending_result pending_result, duckdb_result *out_result); + //===--------------------------------------------------------------------===// // Value Interface //===--------------------------------------------------------------------===// @@ -1539,6 +1611,14 @@ Sets the user-provided bind data in the bind object. This object can be retrieve */ DUCKDB_API void duckdb_bind_set_bind_data(duckdb_bind_info info, void *bind_data, duckdb_delete_callback_t destroy); +/*! +Sets the cardinality estimate for the table function, used for optimization. + +* info: The bind data object. +* is_exact: Whether or not the cardinality estimate is exact, or an approximation +*/ +DUCKDB_API void duckdb_bind_set_cardinality(duckdb_bind_info info, idx_t cardinality, bool is_exact); + /*! Report that an error has occurred while calling bind. @@ -1962,6 +2042,8 @@ DUCKDB_API void duckdb_destroy_arrow(duckdb_arrow *result); //===--------------------------------------------------------------------===// // Threading Information //===--------------------------------------------------------------------===// +typedef void *duckdb_task_state; + /*! Execute DuckDB tasks on this thread. @@ -1972,6 +2054,66 @@ Will return after `max_tasks` have been executed, or if there are no more tasks */ DUCKDB_API void duckdb_execute_tasks(duckdb_database database, idx_t max_tasks); +/*! +Creates a task state that can be used with duckdb_execute_tasks_state to execute tasks until + duckdb_finish_execution is called on the state. + +duckdb_destroy_state should be called on the result in order to free memory. + +* database: The database object to create the task state for +* returns: The task state that can be used with duckdb_execute_tasks_state. +*/ +DUCKDB_API duckdb_task_state duckdb_create_task_state(duckdb_database database); + +/*! +Execute DuckDB tasks on this thread. + +The thread will keep on executing tasks forever, until duckdb_finish_execution is called on the state. +Multiple threads can share the same duckdb_task_state. + +* state: The task state of the executor +*/ +DUCKDB_API void duckdb_execute_tasks_state(duckdb_task_state state); + +/*! +Execute DuckDB tasks on this thread. + +The thread will keep on executing tasks until either duckdb_finish_execution is called on the state, +max_tasks tasks have been executed or there are no more tasks to be executed. + +Multiple threads can share the same duckdb_task_state. + +* state: The task state of the executor +* max_tasks: The maximum amount of tasks to execute +* returns: The amount of tasks that have actually been executed +*/ +DUCKDB_API idx_t duckdb_execute_n_tasks_state(duckdb_task_state state, idx_t max_tasks); + +/*! +Finish execution on a specific task. + +* state: The task state to finish execution +*/ +DUCKDB_API void duckdb_finish_execution(duckdb_task_state state); + +/*! +Check if the provided duckdb_task_state has finished execution + +* state: The task state to inspect +* returns: Whether or not duckdb_finish_execution has been called on the task state +*/ +DUCKDB_API bool duckdb_task_state_is_finished(duckdb_task_state state); + +/*! +Destroys the task state returned from duckdb_create_task_state. + +Note that this should not be called while there is an active duckdb_execute_tasks_state running +on the task state. + +* state: The task state to clean up +*/ +DUCKDB_API void duckdb_destroy_task_state(duckdb_task_state state); + #ifdef __cplusplus } #endif diff --git a/libduckdb-sys/duckdb/duckdb.hpp b/libduckdb-sys/duckdb/duckdb.hpp index 59448dc7..60a5a75f 100644 --- a/libduckdb-sys/duckdb/duckdb.hpp +++ b/libduckdb-sys/duckdb/duckdb.hpp @@ -10,8 +10,8 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI #pragma once #define DUCKDB_AMALGAMATION 1 -#define DUCKDB_SOURCE_ID "da9ee490d" -#define DUCKDB_VERSION "v0.4.0" +#define DUCKDB_SOURCE_ID "109f932c4" +#define DUCKDB_VERSION "v0.5.0" //===----------------------------------------------------------------------===// // DuckDB // @@ -164,7 +164,8 @@ typedef idx_t column_t; //! Type used for storage (column) identifiers typedef idx_t storage_t; //! Special value used to signify the ROW ID of a table -extern const column_t COLUMN_IDENTIFIER_ROW_ID; +DUCKDB_API extern const column_t COLUMN_IDENTIFIER_ROW_ID; +DUCKDB_API bool IsRowIdColumnId(column_t column_id); //! The maximum row identifier used in tables extern const row_t MAX_ROW_ID; @@ -203,7 +204,7 @@ uint64_t NextPowerOfTwo(uint64_t v); namespace duckdb { -enum class ProfilerPrintFormat : uint8_t { NONE, QUERY_TREE, JSON, QUERY_TREE_OPTIMIZER }; +enum class ProfilerPrintFormat : uint8_t { QUERY_TREE, JSON, QUERY_TREE_OPTIMIZER }; } // namespace duckdb @@ -400,6 +401,7 @@ DUCKDB_API void DuckDBAssertInternal(bool condition, const char *condition_name, #endif + //===----------------------------------------------------------------------===// // DuckDB // @@ -632,6 +634,7 @@ class Deserializer; class Value; class TypeCatalogEntry; class Vector; +class ClientContext; //! Type used to represent dates (days since 1970-01-01) struct date_t { // NOLINT int32_t days; @@ -750,57 +753,57 @@ struct hugeint_t { int64_t upper; public: - hugeint_t() = default; - hugeint_t(int64_t value); // NOLINT: Allow implicit conversion from `int64_t` - 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; + DUCKDB_API hugeint_t() = default; + DUCKDB_API hugeint_t(int64_t value); // NOLINT: Allow implicit conversion from `int64_t` + DUCKDB_API hugeint_t(const hugeint_t &rhs) = default; + DUCKDB_API hugeint_t(hugeint_t &&rhs) = default; + DUCKDB_API hugeint_t &operator=(const hugeint_t &rhs) = default; + DUCKDB_API hugeint_t &operator=(hugeint_t &&rhs) = default; DUCKDB_API string ToString() const; // comparison operators - bool operator==(const hugeint_t &rhs) const; - bool operator!=(const hugeint_t &rhs) const; - bool operator<=(const hugeint_t &rhs) const; - bool operator<(const hugeint_t &rhs) const; - bool operator>(const hugeint_t &rhs) const; - bool operator>=(const hugeint_t &rhs) const; + DUCKDB_API bool operator==(const hugeint_t &rhs) const; + DUCKDB_API bool operator!=(const hugeint_t &rhs) const; + DUCKDB_API bool operator<=(const hugeint_t &rhs) const; + DUCKDB_API bool operator<(const hugeint_t &rhs) const; + DUCKDB_API bool operator>(const hugeint_t &rhs) const; + DUCKDB_API bool operator>=(const hugeint_t &rhs) const; // arithmetic operators - hugeint_t operator+(const hugeint_t &rhs) const; - hugeint_t operator-(const hugeint_t &rhs) const; - hugeint_t operator*(const hugeint_t &rhs) const; - hugeint_t operator/(const hugeint_t &rhs) const; - hugeint_t operator%(const hugeint_t &rhs) const; - hugeint_t operator-() const; + DUCKDB_API hugeint_t operator+(const hugeint_t &rhs) const; + DUCKDB_API hugeint_t operator-(const hugeint_t &rhs) const; + DUCKDB_API hugeint_t operator*(const hugeint_t &rhs) const; + DUCKDB_API hugeint_t operator/(const hugeint_t &rhs) const; + DUCKDB_API hugeint_t operator%(const hugeint_t &rhs) const; + DUCKDB_API hugeint_t operator-() const; // bitwise operators - hugeint_t operator>>(const hugeint_t &rhs) const; - hugeint_t operator<<(const hugeint_t &rhs) const; - hugeint_t operator&(const hugeint_t &rhs) const; - hugeint_t operator|(const hugeint_t &rhs) const; - hugeint_t operator^(const hugeint_t &rhs) const; - hugeint_t operator~() const; + DUCKDB_API hugeint_t operator>>(const hugeint_t &rhs) const; + DUCKDB_API hugeint_t operator<<(const hugeint_t &rhs) const; + DUCKDB_API hugeint_t operator&(const hugeint_t &rhs) const; + DUCKDB_API hugeint_t operator|(const hugeint_t &rhs) const; + DUCKDB_API hugeint_t operator^(const hugeint_t &rhs) const; + DUCKDB_API hugeint_t operator~() const; // in-place operators - hugeint_t &operator+=(const hugeint_t &rhs); - hugeint_t &operator-=(const hugeint_t &rhs); - hugeint_t &operator*=(const hugeint_t &rhs); - hugeint_t &operator/=(const hugeint_t &rhs); - hugeint_t &operator%=(const hugeint_t &rhs); - hugeint_t &operator>>=(const hugeint_t &rhs); - hugeint_t &operator<<=(const hugeint_t &rhs); - hugeint_t &operator&=(const hugeint_t &rhs); - hugeint_t &operator|=(const hugeint_t &rhs); - hugeint_t &operator^=(const hugeint_t &rhs); + DUCKDB_API hugeint_t &operator+=(const hugeint_t &rhs); + DUCKDB_API hugeint_t &operator-=(const hugeint_t &rhs); + DUCKDB_API hugeint_t &operator*=(const hugeint_t &rhs); + DUCKDB_API hugeint_t &operator/=(const hugeint_t &rhs); + DUCKDB_API hugeint_t &operator%=(const hugeint_t &rhs); + DUCKDB_API hugeint_t &operator>>=(const hugeint_t &rhs); + DUCKDB_API hugeint_t &operator<<=(const hugeint_t &rhs); + DUCKDB_API hugeint_t &operator&=(const hugeint_t &rhs); + DUCKDB_API hugeint_t &operator|=(const hugeint_t &rhs); + DUCKDB_API hugeint_t &operator^=(const hugeint_t &rhs); }; struct string_t; template using child_list_t = std::vector>; -// we should be using single_thread_ptr here but cross-thread access to ChunkCollections currently prohibits this. +//! FIXME: this should be a single_thread_ptr template using buffer_ptr = shared_ptr; @@ -824,8 +827,8 @@ struct list_entry_t { // taken from arrow's type.h enum class PhysicalType : uint8_t { - /// A NULL type having no physical storage - NA = 0, + ///// A NULL type having no physical storage + //NA = 0, /// Boolean as 8 bit "bool" value BOOL = 1, @@ -854,8 +857,8 @@ enum class PhysicalType : uint8_t { /// Signed 64-bit little-endian integer INT64 = 9, - /// 2-byte floating point value - HALF_FLOAT = 10, + ///// 2-byte floating point value + //HALF_FLOAT = 10, /// 4-byte floating point value FLOAT = 11, @@ -863,32 +866,32 @@ enum class PhysicalType : uint8_t { /// 8-byte floating point value DOUBLE = 12, - /// UTF8 variable-length string as List - STRING = 13, + ///// UTF8 variable-length string as List + //STRING = 13, - /// Variable-length bytes (no guarantee of UTF8-ness) - BINARY = 14, + ///// Variable-length bytes (no guarantee of UTF8-ness) + //BINARY = 14, - /// Fixed-size binary. Each value occupies the same number of bytes - FIXED_SIZE_BINARY = 15, + ///// Fixed-size binary. Each value occupies the same number of bytes + //FIXED_SIZE_BINARY = 15, - /// int32_t days since the UNIX epoch - DATE32 = 16, + ///// int32_t days since the UNIX epoch + //DATE32 = 16, - /// int64_t milliseconds since the UNIX epoch - DATE64 = 17, + ///// int64_t milliseconds since the UNIX epoch + //DATE64 = 17, - /// Exact timestamp encoded with int64 since UNIX epoch - /// Default unit millisecond - TIMESTAMP = 18, + ///// Exact timestamp encoded with int64 since UNIX epoch + ///// Default unit millisecond + //TIMESTAMP = 18, - /// Time as signed 32-bit integer, representing either seconds or - /// milliseconds since midnight - TIME32 = 19, + ///// Time as signed 32-bit integer, representing either seconds or + ///// milliseconds since midnight + //TIME32 = 19, - /// Time as signed 64-bit integer, representing either microseconds or - /// nanoseconds since midnight - TIME64 = 20, + ///// Time as signed 64-bit integer, representing either microseconds or + ///// nanoseconds since midnight + //TIME64 = 20, /// YEAR_MONTH or DAY_TIME interval in SQL style INTERVAL = 21, @@ -903,36 +906,36 @@ enum class PhysicalType : uint8_t { /// Struct of logical types STRUCT = 24, - /// Unions of logical types - UNION = 25, + ///// Unions of logical types + //UNION = 25, - /// Dictionary-encoded type, also called "categorical" or "factor" - /// in other programming languages. Holds the dictionary value - /// type but not the dictionary itself, which is part of the - /// ArrayData struct - DICTIONARY = 26, + ///// Dictionary-encoded type, also called "categorical" or "factor" + ///// in other programming languages. Holds the dictionary value + ///// type but not the dictionary itself, which is part of the + ///// ArrayData struct + //DICTIONARY = 26, /// Map, a repeated struct logical type MAP = 27, - /// Custom data type, implemented by user - EXTENSION = 28, + ///// Custom data type, implemented by user + //EXTENSION = 28, - /// Fixed size list of some logical type - FIXED_SIZE_LIST = 29, + ///// Fixed size list of some logical type + //FIXED_SIZE_LIST = 29, - /// Measure of elapsed time in either seconds, milliseconds, microseconds - /// or nanoseconds. - DURATION = 30, + ///// Measure of elapsed time in either seconds, milliseconds, microseconds + ///// or nanoseconds. + //DURATION = 30, - /// Like STRING, but with 64-bit offsets - LARGE_STRING = 31, + ///// Like STRING, but with 64-bit offsets + //LARGE_STRING = 31, - /// Like BINARY, but with 64-bit offsets - LARGE_BINARY = 32, + ///// Like BINARY, but with 64-bit offsets + //LARGE_BINARY = 32, - /// Like LIST, but with 64-bit offsets - LARGE_LIST = 33, + ///// Like LIST, but with 64-bit offsets + //LARGE_LIST = 33, /// DuckDB Extensions VARCHAR = 200, // our own string representation, different from STRING and LARGE_STRING above @@ -981,7 +984,7 @@ enum class LogicalTypeId : uint8_t { HUGEINT = 50, POINTER = 51, - HASH = 52, + // HASH = 52, // deprecated, uses UBIGINT instead VALIDITY = 53, UUID = 54, @@ -990,7 +993,8 @@ enum class LogicalTypeId : uint8_t { MAP = 102, TABLE = 103, ENUM = 104, - AGGREGATE_STATE = 105 + AGGREGATE_STATE = 105, + LAMBDA = 106 }; struct ExtraTypeInfo; @@ -1046,7 +1050,8 @@ struct LogicalType { DUCKDB_API bool IsIntegral() const; DUCKDB_API bool IsNumeric() const; DUCKDB_API hash_t Hash() const; - DUCKDB_API void SetAlias(string &alias); + DUCKDB_API void SetAlias(string alias); + DUCKDB_API bool HasAlias() const; DUCKDB_API string GetAlias() const; DUCKDB_API static LogicalType MaxLogicalType(const LogicalType &left, const LogicalType &right); @@ -1058,6 +1063,8 @@ struct LogicalType { DUCKDB_API void Verify() const; + DUCKDB_API bool IsValid() const; + private: LogicalTypeId id_; PhysicalType physical_type_; @@ -1068,6 +1075,7 @@ struct LogicalType { public: static constexpr const LogicalTypeId SQLNULL = LogicalTypeId::SQLNULL; + static constexpr const LogicalTypeId UNKNOWN = LogicalTypeId::UNKNOWN; static constexpr const LogicalTypeId BOOLEAN = LogicalTypeId::BOOLEAN; static constexpr const LogicalTypeId TINYINT = LogicalTypeId::TINYINT; static constexpr const LogicalTypeId UTINYINT = LogicalTypeId::UTINYINT; @@ -1093,9 +1101,10 @@ struct LogicalType { static constexpr const LogicalTypeId INTERVAL = LogicalTypeId::INTERVAL; static constexpr const LogicalTypeId HUGEINT = LogicalTypeId::HUGEINT; static constexpr const LogicalTypeId UUID = LogicalTypeId::UUID; - static constexpr const LogicalTypeId HASH = LogicalTypeId::HASH; + static constexpr const LogicalTypeId HASH = LogicalTypeId::UBIGINT; static constexpr const LogicalTypeId POINTER = LogicalTypeId::POINTER; static constexpr const LogicalTypeId TABLE = LogicalTypeId::TABLE; + static constexpr const LogicalTypeId LAMBDA = LogicalTypeId::LAMBDA; static constexpr const LogicalTypeId INVALID = LogicalTypeId::INVALID; static constexpr const LogicalTypeId JSON = LogicalTypeId::JSON; static constexpr const LogicalTypeId ROW_TYPE = LogicalTypeId::BIGINT; @@ -1122,6 +1131,7 @@ struct LogicalType { struct DecimalType { DUCKDB_API static uint8_t GetWidth(const LogicalType &type); DUCKDB_API static uint8_t GetScale(const LogicalType &type); + DUCKDB_API static uint8_t MaxWidth(); }; struct StringType { @@ -1195,11 +1205,11 @@ PhysicalType GetTypeId() { } else if (std::is_same()) { return PhysicalType::INT128; } else if (std::is_same()) { - return PhysicalType::DATE32; + return PhysicalType::INT32; } else if (std::is_same()) { - return PhysicalType::TIME32; + return PhysicalType::INT64; } else if (std::is_same()) { - return PhysicalType::TIMESTAMP; + return PhysicalType::INT64; } else if (std::is_same()) { return PhysicalType::FLOAT; } else if (std::is_same()) { @@ -1358,12 +1368,13 @@ enum class ExceptionType { NULL_POINTER = 27, // nullptr exception IO = 28, // IO exception INTERRUPT = 29, // interrupt - FATAL = 30, // Fatal exception: fatal exceptions are non-recoverable, and render the entire DB in an unusable state - INTERNAL = - 31, // Internal exception: exception that indicates something went wrong internally (i.e. bug in the code base) - INVALID_INPUT = 32, // Input or arguments error - OUT_OF_MEMORY = 33, // out of memory - PERMISSION = 34 // insufficient permissions + FATAL = 30, // Fatal exceptions are non-recoverable, and render the entire DB in an unusable state + INTERNAL = 31, // Internal exceptions indicate something went wrong internally (i.e. bug in the code base) + INVALID_INPUT = 32, // Input or arguments error + OUT_OF_MEMORY = 33, // out of memory + PERMISSION = 34, // insufficient permissions + PARAMETER_NOT_RESOLVED = 35, // parameter types could not be resolved + PARAMETER_NOT_ALLOWED = 36 // parameter types not allowed }; class Exception : public std::exception { @@ -1375,8 +1386,10 @@ class Exception : public std::exception { public: DUCKDB_API const char *what() const noexcept override; + DUCKDB_API const string &RawMessage() const; - DUCKDB_API string ExceptionTypeToString(ExceptionType type); + DUCKDB_API static string ExceptionTypeToString(ExceptionType type); + [[noreturn]] DUCKDB_API static void ThrowAsTypeWithMessage(ExceptionType type, const string &message); template static string ConstructMessage(const string &msg, Args... params) { @@ -1397,6 +1410,7 @@ class Exception : public std::exception { private: string exception_message_; + string raw_message_; }; //===--------------------------------------------------------------------===// @@ -1418,6 +1432,16 @@ class CatalogException : public StandardException { } }; +class ConnectionException : public StandardException { +public: + DUCKDB_API explicit ConnectionException(const string &msg); + + template + explicit ConnectionException(const string &msg, Args... params) + : ConnectionException(ConstructMessage(msg, params...)) { + } +}; + class ParserException : public StandardException { public: DUCKDB_API explicit ParserException(const string &msg); @@ -1551,14 +1575,21 @@ class InterruptException : public Exception { class FatalException : public Exception { public: - DUCKDB_API explicit FatalException(const string &msg); - + DUCKDB_API explicit FatalException(const string &msg) : FatalException(ExceptionType::FATAL, msg) { + } template explicit FatalException(const string &msg, Args... params) : FatalException(ConstructMessage(msg, params...)) { } + +protected: + DUCKDB_API explicit FatalException(ExceptionType type, const string &msg); + template + explicit FatalException(ExceptionType type, const string &msg, Args... params) + : FatalException(type, ConstructMessage(msg, params...)) { + } }; -class InternalException : public Exception { +class InternalException : public FatalException { public: DUCKDB_API explicit InternalException(const string &msg); @@ -1582,18 +1613,24 @@ class CastException : public Exception { public: DUCKDB_API CastException(const PhysicalType origType, const PhysicalType newType); DUCKDB_API CastException(const LogicalType &origType, const LogicalType &newType); + DUCKDB_API + CastException(const string &msg); //! Needed to be able to recreate the exception after it's been serialized }; class InvalidTypeException : public Exception { public: DUCKDB_API InvalidTypeException(PhysicalType type, const string &msg); DUCKDB_API InvalidTypeException(const LogicalType &type, const string &msg); + DUCKDB_API + InvalidTypeException(const string &msg); //! Needed to be able to recreate the exception after it's been serialized }; class TypeMismatchException : public Exception { public: DUCKDB_API TypeMismatchException(const PhysicalType type_1, const PhysicalType type_2, const string &msg); DUCKDB_API TypeMismatchException(const LogicalType &type_1, const LogicalType &type_2, const string &msg); + DUCKDB_API + TypeMismatchException(const string &msg); //! Needed to be able to recreate the exception after it's been serialized }; class ValueOutOfRangeException : public Exception { @@ -1602,6 +1639,26 @@ class ValueOutOfRangeException : public Exception { DUCKDB_API ValueOutOfRangeException(const hugeint_t value, const PhysicalType origType, const PhysicalType newType); DUCKDB_API ValueOutOfRangeException(const double value, const PhysicalType origType, const PhysicalType newType); DUCKDB_API ValueOutOfRangeException(const PhysicalType varType, const idx_t length); + DUCKDB_API ValueOutOfRangeException( + const string &msg); //! Needed to be able to recreate the exception after it's been serialized +}; + +class ParameterNotAllowedException : public StandardException { +public: + DUCKDB_API explicit ParameterNotAllowedException(const string &msg); + + template + explicit ParameterNotAllowedException(const string &msg, Args... params) + : ParameterNotAllowedException(ConstructMessage(msg, params...)) { + } +}; + +//! Special exception that should be thrown in the binder if parameter types could not be resolved +//! This will cause prepared statements to be forcibly rebound with the actual parameter values +//! This exception is fatal if thrown outside of the binder (i.e. it should never be thrown outside of the binder) +class ParameterNotResolvedException : public Exception { +public: + DUCKDB_API explicit ParameterNotResolvedException(); }; } // namespace duckdb @@ -1613,10 +1670,26 @@ namespace duckdb { //! The Serialize class is a base class that can be used to serializing objects into a binary buffer class Serializer { +private: + uint64_t version = 0L; + public: virtual ~Serializer() { } + //! Sets the version of the serialization that writers are expected to use + //! The version is mostly the most recent one, unless modifying old data or streaming to + //! an older version + void SetVersion(uint64_t v) { + D_ASSERT(this->version == 0); // version can only be set once + this->version = v; + } + + //! Returns the version of serialization that writers are expected to use + uint64_t GetVersion() { + return version; + } + virtual void WriteData(const_data_ptr_t buffer, idx_t write_size) = 0; template @@ -1668,10 +1741,26 @@ class Serializer { //! The Deserializer class assists in deserializing a binary blob back into an //! object class Deserializer { +private: + uint64_t version = 0L; + public: virtual ~Deserializer() { } + //! Sets the version of the serialization that readers are expected to use + //! The version is mostly the most recent one, unless reading old data or streaming from + //! an older version + void SetVersion(uint64_t v) { + D_ASSERT(this->version == 0); // version can only be set once + this->version = v; + } + + //! Returns the version of serialization that readers are expected to use + uint64_t GetVersion() { + return version; + } + //! Reads [read_size] bytes into the buffer virtual void ReadData(data_ptr_t buffer, idx_t read_size) = 0; @@ -1681,20 +1770,21 @@ class Deserializer { ReadData((data_ptr_t)&value, sizeof(T)); return value; } - template - void ReadList(vector> &list) { + + template + void ReadList(vector> &list, ARGS &&...args) { auto select_count = Read(); for (uint32_t i = 0; i < select_count; i++) { - auto child = T::Deserialize(*this); + auto child = T::Deserialize(*this, std::forward(args)...); list.push_back(move(child)); } } - template - unique_ptr ReadOptional() { + template + unique_ptr ReadOptional(ARGS &&...args) { auto has_entry = Read(); if (has_entry) { - return T::Deserialize(*this); + return T::Deserialize(*this, std::forward(args)...); } return nullptr; } @@ -1703,7 +1793,7 @@ class Deserializer { }; template <> -string Deserializer::Read(); +DUCKDB_API string Deserializer::Read(); } // namespace duckdb @@ -1980,8 +2070,10 @@ class FileSystem { //! Gets the working directory DUCKDB_API static string GetWorkingDirectory(); //! Gets the users home directory - DUCKDB_API static string GetHomeDirectory(); - //! Returns the system-available memory in bytes + DUCKDB_API static string GetHomeDirectory(FileOpener *opener); + //! Expands a given path, including e.g. expanding the home directory of the user + DUCKDB_API static string ExpandPath(const string &path, FileOpener *opener); + //! Returns the system-available memory in bytes. Returns DConstants::INVALID_INDEX if the system function fails. DUCKDB_API static idx_t GetAvailableMemory(); //! Path separator for the current file system DUCKDB_API static string PathSeparator(); @@ -2038,8 +2130,8 @@ class BufferedFileWriter : public Serializer { //! Serializes to a buffer allocated by the serializer, will expand when //! writing past the initial threshold - BufferedFileWriter(FileSystem &fs, const string &path, uint8_t open_flags = DEFAULT_OPEN_FLAGS, - FileOpener *opener = nullptr); + DUCKDB_API BufferedFileWriter(FileSystem &fs, const string &path, uint8_t open_flags = DEFAULT_OPEN_FLAGS, + FileOpener *opener = nullptr); FileSystem &fs; string path; @@ -2049,17 +2141,17 @@ class BufferedFileWriter : public Serializer { unique_ptr handle; public: - void WriteData(const_data_ptr_t buffer, uint64_t write_size) override; + DUCKDB_API void WriteData(const_data_ptr_t buffer, uint64_t write_size) override; //! Flush the buffer to disk and sync the file to ensure writing is completed - void Sync(); + DUCKDB_API void Sync(); //! Flush the buffer to the file (without sync) - void Flush(); + DUCKDB_API void Flush(); //! Returns the current size of the file - int64_t GetFileSize(); + DUCKDB_API int64_t GetFileSize(); //! Truncate the size to a previous size (given that size <= GetFileSize()) - void Truncate(int64_t size); + DUCKDB_API void Truncate(int64_t size); - idx_t GetTotalWritten(); + DUCKDB_API idx_t GetTotalWritten(); }; } // namespace duckdb @@ -2193,7 +2285,7 @@ namespace duckdb { class VectorBuffer; struct SelectionData { - explicit SelectionData(idx_t count); + DUCKDB_API explicit SelectionData(idx_t count); unique_ptr owned_data; }; @@ -2238,15 +2330,15 @@ struct SelectionVector { sel_vector = other.sel_vector; } - void set_index(idx_t idx, idx_t loc) { + inline void set_index(idx_t idx, idx_t loc) { sel_vector[idx] = loc; } - void swap(idx_t i, idx_t j) { + inline 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 { + inline idx_t get_index(idx_t idx) const { return sel_vector ? sel_vector[idx] : idx; } sel_t *data() { @@ -2263,7 +2355,7 @@ struct SelectionVector { string ToString(idx_t count = 0) const; void Print(idx_t count = 0) const; - sel_t &operator[](idx_t index) { + inline sel_t &operator[](idx_t index) const { return sel_vector[index]; } @@ -2717,6 +2809,9 @@ class Value { // move assignment DUCKDB_API Value &operator=(Value &&other) noexcept; + inline LogicalType &type() { + return type_; + } inline const LogicalType &type() const { return type_; } @@ -3226,6 +3321,174 @@ DUCKDB_API bool Value::IsFinite(timestamp_t input); +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/storage/arena_allocator.hpp +// +// +//===----------------------------------------------------------------------===// + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/allocator.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { +class Allocator; +class ClientContext; +class DatabaseInstance; +class ExecutionContext; +class ThreadContext; + +struct AllocatorDebugInfo; + +struct PrivateAllocatorData { + PrivateAllocatorData(); + virtual ~PrivateAllocatorData(); + + unique_ptr debug_info; +}; + +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 old_size, + idx_t size); + +class AllocatedData { +public: + DUCKDB_API AllocatedData(); + DUCKDB_API AllocatedData(Allocator &allocator, data_ptr_t pointer, idx_t allocated_size); + DUCKDB_API ~AllocatedData(); + // disable copy constructors + DUCKDB_API AllocatedData(const AllocatedData &other) = delete; + DUCKDB_API AllocatedData &operator=(const AllocatedData &) = delete; + //! enable move constructors + DUCKDB_API AllocatedData(AllocatedData &&other) noexcept; + DUCKDB_API AllocatedData &operator=(AllocatedData &&) noexcept; + + data_ptr_t get() { + return pointer; + } + const_data_ptr_t get() const { + return pointer; + } + idx_t GetSize() const { + return allocated_size; + } + void Reset(); + +private: + Allocator *allocator; + data_ptr_t pointer; + idx_t allocated_size; +}; + +class Allocator { +public: + DUCKDB_API Allocator(); + DUCKDB_API Allocator(allocate_function_ptr_t allocate_function_p, free_function_ptr_t free_function_p, + reallocate_function_ptr_t reallocate_function_p, + unique_ptr private_data); + Allocator &operator=(Allocator &&allocator) noexcept = delete; + DUCKDB_API ~Allocator(); + + DUCKDB_API data_ptr_t AllocateData(idx_t size); + DUCKDB_API void FreeData(data_ptr_t pointer, idx_t size); + DUCKDB_API data_ptr_t ReallocateData(data_ptr_t pointer, idx_t old_size, idx_t new_size); + + AllocatedData Allocate(idx_t size) { + return 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 old_size, + 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(); + } + + static Allocator &DefaultAllocator(); + +private: + allocate_function_ptr_t allocate_function; + free_function_ptr_t free_function; + reallocate_function_ptr_t reallocate_function; + + unique_ptr private_data; +}; + +//! The BufferAllocator is a wrapper around the global allocator class that sends any allocations made through the +//! buffer manager. This makes the buffer manager aware of the memory usage, allowing it to potentially free +//! other blocks to make space in memory. +//! Note that there is a cost to doing so (several atomic operations will be performed on allocation/free). +//! As such this class should be used primarily for larger allocations. +struct BufferAllocator { + DUCKDB_API static Allocator &Get(ClientContext &context); +}; + +} // namespace duckdb + + +namespace duckdb { + +struct ArenaChunk { + ArenaChunk(Allocator &allocator, idx_t size); + ~ArenaChunk(); + + AllocatedData data; + idx_t current_position; + idx_t maximum_size; + unique_ptr next; + ArenaChunk *prev; +}; + +class ArenaAllocator { + static constexpr const idx_t ARENA_ALLOCATOR_INITIAL_CAPACITY = 2048; + +public: + ArenaAllocator(Allocator &allocator, idx_t initial_capacity = ARENA_ALLOCATOR_INITIAL_CAPACITY); + ~ArenaAllocator(); + + data_ptr_t Allocate(idx_t size); + void Destroy(); + void Move(ArenaAllocator &allocator); + + ArenaChunk *GetHead(); + ArenaChunk *GetTail(); + + bool IsEmpty(); + +private: + //! Internal allocator that is used by the arena allocator + Allocator &allocator; + idx_t current_capacity; + unique_ptr head; + ArenaChunk *tail; +}; + +} // namespace duckdb + namespace duckdb { //! A string heap is the owner of a set of strings, strings can be inserted into @@ -3235,17 +3498,8 @@ 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; - } + void Destroy(); + void Move(StringHeap &other); //! Add a string to the string heap, returns a pointer to the string string_t AddString(const char *data, idx_t len); @@ -3256,31 +3510,14 @@ class StringHeap { //! Add a string to the string heap, returns a pointer to the string string_t AddString(const string_t &data); //! Add a blob to the string heap; blobs can be non-valid UTF8 + string_t AddBlob(const string_t &data); + //! Add a blob to the string heap; blobs can be non-valid UTF8 string_t AddBlob(const char *data, idx_t len); //! Allocates space for an empty string of size "len" on the heap string_t EmptyString(idx_t len); private: - struct StringChunk { - explicit StringChunk(idx_t size) : current_position(0), maximum_size(size) { - data = unique_ptr(new char[maximum_size]); - } - ~StringChunk() { - if (prev) { - auto current_prev = move(prev); - while (current_prev) { - current_prev = move(current_prev->prev); - } - } - } - - unique_ptr data; - idx_t current_position; - idx_t maximum_size; - unique_ptr prev; - }; - StringChunk *tail; - unique_ptr chunk; + ArenaAllocator allocator; }; } // namespace duckdb @@ -3381,8 +3618,8 @@ struct string_t { } } - void Verify(); - void VerifyNull(); + void Verify() const; + void VerifyNull() const; bool operator<(const string_t &r) const { auto this_str = this->GetString(); auto r_str = r.GetString(); @@ -3405,78 +3642,195 @@ struct string_t { } // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/storage/buffer/buffer_handle.hpp +// +// +//===----------------------------------------------------------------------===// -namespace duckdb { -class BufferHandle; -class VectorBuffer; -class Vector; -class ChunkCollection; -enum class VectorBufferType : uint8_t { - STANDARD_BUFFER, // standard buffer, holds a single array of data - DICTIONARY_BUFFER, // dictionary buffer, holds a selection vector - VECTOR_CHILD_BUFFER, // vector child buffer: holds another vector - STRING_BUFFER, // string buffer, holds a string heap - STRUCT_BUFFER, // struct buffer, holds a ordered mapping from name to child vector - LIST_BUFFER, // list buffer, holds a single flatvector child - MANAGED_BUFFER, // managed buffer, holds a buffer managed by the buffermanager - OPAQUE_BUFFER // opaque buffer, can be created for example by the parquet reader -}; +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/storage/storage_info.hpp +// +// +//===----------------------------------------------------------------------===// -enum class VectorAuxiliaryDataType : uint8_t { - ARROW_AUXILIARY // Holds Arrow Chunks that this vector depends on -}; -struct VectorAuxiliaryData { - explicit VectorAuxiliaryData(VectorAuxiliaryDataType type_p) - : type(type_p) { - }; - VectorAuxiliaryDataType type; - virtual ~VectorAuxiliaryData() { - } -}; -//! The VectorBuffer is a class used by the vector to hold its data -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(new data_t[data_size]); - } - } - explicit VectorBuffer(unique_ptr data_p) - : buffer_type(VectorBufferType::STANDARD_BUFFER), data(move(data_p)) { - } - virtual ~VectorBuffer() { - } - VectorBuffer() { - } +namespace duckdb { +class Serializer; +class Deserializer; +struct FileHandle; -public: - data_ptr_t GetData() { - return data.get(); - } +//! The version number of the database storage format +extern const uint64_t VERSION_NUMBER; - void SetData(unique_ptr new_data) { - data = move(new_data); - } +using block_id_t = int64_t; - VectorAuxiliaryData *GetAuxiliaryData() { - return aux_data.get(); - } +#define INVALID_BLOCK (-1) - void SetAuxiliaryData(unique_ptr aux_data_p) { - aux_data = move(aux_data_p); - } +// maximum block id, 2^62 +#define MAXIMUM_BLOCK 4611686018427388000LL - static buffer_ptr CreateStandardVector(PhysicalType type, idx_t capacity = STANDARD_VECTOR_SIZE); - static buffer_ptr CreateConstantVector(PhysicalType type); - static buffer_ptr CreateConstantVector(const LogicalType &logical_type); +//! The MainHeader is the first header in the storage file. The MainHeader is typically written only once for a database +//! file. +struct MainHeader { + static constexpr idx_t MAGIC_BYTE_SIZE = 4; + static constexpr idx_t MAGIC_BYTE_OFFSET = sizeof(uint64_t); + static constexpr idx_t FLAG_COUNT = 4; + // the magic bytes in front of the file + // should be "DUCK" + static const char MAGIC_BYTES[]; + //! The version of the database + uint64_t version_number; + //! The set of flags used by the database + uint64_t flags[FLAG_COUNT]; + + static void CheckMagicBytes(FileHandle &handle); + + void Serialize(Serializer &ser); + static MainHeader Deserialize(Deserializer &source); +}; + +//! The DatabaseHeader contains information about the current state of the database. Every storage file has two +//! DatabaseHeaders. On startup, the DatabaseHeader with the highest iteration count is used as the active header. When +//! a checkpoint is performed, the active DatabaseHeader is switched by increasing the iteration count of the +//! DatabaseHeader. +struct DatabaseHeader { + //! The iteration count, increases by 1 every time the storage is checkpointed. + uint64_t iteration; + //! A pointer to the initial meta block + block_id_t meta_block; + //! A pointer to the block containing the free list + block_id_t free_list; + //! The number of blocks that is in the file as of this database header. If the file is larger than BLOCK_SIZE * + //! block_count any blocks appearing AFTER block_count are implicitly part of the free_list. + uint64_t block_count; + + void Serialize(Serializer &ser); + static DatabaseHeader Deserialize(Deserializer &source); +}; + +} // namespace duckdb + + +namespace duckdb { +class BlockHandle; +class FileBuffer; + +class BufferHandle { +public: + DUCKDB_API BufferHandle(); + DUCKDB_API BufferHandle(shared_ptr handle, FileBuffer *node); + DUCKDB_API ~BufferHandle(); + // disable copy constructors + BufferHandle(const BufferHandle &other) = delete; + BufferHandle &operator=(const BufferHandle &) = delete; + //! enable move constructors + DUCKDB_API BufferHandle(BufferHandle &&other) noexcept; + DUCKDB_API BufferHandle &operator=(BufferHandle &&) noexcept; + +public: + //! Returns whether or not the BufferHandle is valid. + DUCKDB_API bool IsValid() const; + //! Returns a pointer to the buffer data. Handle must be valid. + DUCKDB_API data_ptr_t Ptr() const; + //! Returns a pointer to the buffer data. Handle must be valid. + DUCKDB_API data_ptr_t Ptr(); + //! Gets the block id of the underlying block. Handle must be valid. + DUCKDB_API block_id_t GetBlockId() const; + //! Gets the underlying file buffer. Handle must be valid. + DUCKDB_API FileBuffer &GetFileBuffer(); + //! Destroys the buffer handle + DUCKDB_API void Destroy(); + +private: + //! The block handle + shared_ptr handle; + //! The managed buffer node + FileBuffer *node; +}; + +} // namespace duckdb + + +namespace duckdb { + +class BufferHandle; +class VectorBuffer; +class Vector; + +enum class VectorBufferType : uint8_t { + STANDARD_BUFFER, // standard buffer, holds a single array of data + DICTIONARY_BUFFER, // dictionary buffer, holds a selection vector + VECTOR_CHILD_BUFFER, // vector child buffer: holds another vector + STRING_BUFFER, // string buffer, holds a string heap + STRUCT_BUFFER, // struct buffer, holds a ordered mapping from name to child vector + LIST_BUFFER, // list buffer, holds a single flatvector child + MANAGED_BUFFER, // managed buffer, holds a buffer managed by the buffermanager + OPAQUE_BUFFER // opaque buffer, can be created for example by the parquet reader +}; + +enum class VectorAuxiliaryDataType : uint8_t { + ARROW_AUXILIARY // Holds Arrow Chunks that this vector depends on +}; + +struct VectorAuxiliaryData { + explicit VectorAuxiliaryData(VectorAuxiliaryDataType type_p) + : type(type_p) { + + }; + VectorAuxiliaryDataType type; + + virtual ~VectorAuxiliaryData() { + } +}; + +//! The VectorBuffer is a class used by the vector to hold its data +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(new data_t[data_size]); + } + } + explicit VectorBuffer(unique_ptr 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 new_data) { + data = move(new_data); + } + + VectorAuxiliaryData *GetAuxiliaryData() { + return aux_data.get(); + } + + void SetAuxiliaryData(unique_ptr aux_data_p) { + aux_data = move(aux_data_p); + } + + static buffer_ptr CreateStandardVector(PhysicalType type, idx_t capacity = STANDARD_VECTOR_SIZE); + static buffer_ptr CreateConstantVector(PhysicalType type); + static buffer_ptr CreateConstantVector(const LogicalType &logical_type); static buffer_ptr CreateStandardVector(const LogicalType &logical_type, idx_t capacity = STANDARD_VECTOR_SIZE); @@ -3599,11 +3953,11 @@ class VectorListBuffer : public VectorBuffer { //! The ManagedVectorBuffer holds a buffer handle class ManagedVectorBuffer : public VectorBuffer { public: - explicit ManagedVectorBuffer(unique_ptr handle); + explicit ManagedVectorBuffer(BufferHandle handle); ~ManagedVectorBuffer() override; private: - unique_ptr handle; + BufferHandle handle; }; } // namespace duckdb @@ -3612,7 +3966,7 @@ class ManagedVectorBuffer : public VectorBuffer { namespace duckdb { -struct VectorData { +struct UnifiedVectorFormat { const SelectionVector *sel; data_ptr_t data; ValidityMask validity; @@ -3622,7 +3976,6 @@ struct VectorData { class VectorCache; class VectorStructBuffer; class VectorListBuffer; -class ChunkCollection; struct SelCache; @@ -3706,10 +4059,15 @@ class Vector { DUCKDB_API void Print(); //! Flatten the vector, removing any compression and turning it into a FLAT_VECTOR - DUCKDB_API void Normalify(idx_t count); - DUCKDB_API void Normalify(const SelectionVector &sel, idx_t count); - //! Obtains a selection vector and data pointer through which the data of this vector can be accessed - DUCKDB_API void Orrify(idx_t count, VectorData &data); + DUCKDB_API void Flatten(idx_t count); + DUCKDB_API void Flatten(const SelectionVector &sel, idx_t count); + //! Creates a UnifiedVectorFormat of a vector + //! The UnifiedVectorFormat allows efficient reading of vectors regardless of their vector type + //! It contains (1) a data pointer, (2) a validity mask, and (3) a selection vector + //! Access to the individual vector elements can be performed through data_pointer[sel_idx[i]]/validity[sel_idx[i]] + //! The most common vector types (flat, constant & dictionary) can be converted to the canonical format "for free" + //! ToUnifiedFormat was originally called Orrify, as a tribute to Orri Erling who came up with it + DUCKDB_API void ToUnifiedFormat(idx_t count, UnifiedVectorFormat &data); //! Turn the vector into a sequence vector DUCKDB_API void Sequence(int64_t start, int64_t increment); @@ -3764,7 +4122,9 @@ class Vector { private: //! Returns the [index] element of the Vector as a Value. - DUCKDB_API static Value GetValue(const Vector &v, idx_t index); + static Value GetValue(const Vector &v, idx_t index); + //! Returns the [index] element of the Vector as a Value. + static Value GetValueInternal(const Vector &v, idx_t index); protected: //! The vector type specifies how the data of the vector is physically stored (i.e. if it is a single repeated @@ -3881,7 +4241,7 @@ struct FlatVector { D_ASSERT(vector.GetVectorType() == VectorType::FLAT_VECTOR); vector.validity.Initialize(new_validity); } - static void SetNull(Vector &vector, idx_t idx, bool is_null); + DUCKDB_API 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); @@ -3935,7 +4295,7 @@ struct StringVector { //! result of an operation DUCKDB_API static string_t EmptyString(Vector &vector, idx_t len); //! Adds a reference to a handle that stores strings of this vector - DUCKDB_API static void AddHandle(Vector &vector, unique_ptr handle); + DUCKDB_API static void AddHandle(Vector &vector, BufferHandle handle); //! Adds a reference to an unspecified vector buffer that stores strings of this vector DUCKDB_API static void AddBuffer(Vector &vector, buffer_ptr buffer); //! Add a reference from this vector to the string heap of the provided vector @@ -3985,7 +4345,7 @@ struct SequenceVector { //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/arrow_wrapper.hpp +// duckdb/common/arrow/arrow_wrapper.hpp // // //===----------------------------------------------------------------------===// @@ -3994,7 +4354,7 @@ struct SequenceVector { //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/arrow.hpp +// duckdb/common/arrow/arrow.hpp // // //===----------------------------------------------------------------------===// @@ -4083,6 +4443,58 @@ struct ArrowArrayStream { #endif +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/preserved_error.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +class PreservedError { +public: + //! Not initialized, default constructor + DUCKDB_API PreservedError(); + //! From std::exception + DUCKDB_API explicit PreservedError(const std::exception &exception); + //! From a raw string + DUCKDB_API explicit PreservedError(const string &raw_message); + //! From an Exception + DUCKDB_API PreservedError(const Exception &exception); + +public: + //! Throw the error + [[noreturn]] DUCKDB_API void Throw(const string &prepended_message = "") const; + //! Get the internal exception type of the error + DUCKDB_API const ExceptionType &Type() const; + //! Allows adding addition information to the message + DUCKDB_API PreservedError &AddToMessage(const string &prepended_message); + //! Used in clients like C-API, creates the final message and returns a reference to it + DUCKDB_API const string &Message(); + //! Let's us do things like 'if (error)' + operator bool() const; + bool operator==(const PreservedError &other) const; + +private: + //! Whether this PreservedError contains an exception or not + bool initialized; + //! The ExceptionType of the preserved exception + ExceptionType type; + //! The message the exception was constructed with (does not contain the Exception Type) + string raw_message; + //! The final message (stored in the preserved error for compatibility reasons with C-API) + string final_message; +}; + +} // namespace duckdb + //! Here we have the internal duckdb classes that interact with Arrow's Internal Header (i.e., duckdb/commons/arrow.hpp) namespace duckdb { @@ -4113,6 +4525,8 @@ class ArrowArrayStreamWrapper { public: ArrowArrayStream arrow_array_stream; int64_t number_of_rows; + +public: void GetSchema(ArrowSchemaWrapper &schema); shared_ptr GetNextChunk(); @@ -4127,10 +4541,12 @@ class ArrowArrayStreamWrapper { class ArrowUtil { public: - static unique_ptr FetchChunk(QueryResult *result, idx_t chunk_size); + static bool TryFetchChunk(QueryResult *result, idx_t chunk_size, ArrowArray *out, idx_t &result_count, + PreservedError &error); + static idx_t FetchChunk(QueryResult *result, idx_t chunk_size, ArrowArray *out); private: - static unique_ptr FetchNext(QueryResult &result); + static bool TryFetchNext(QueryResult &result, unique_ptr &out, PreservedError &error); }; } // namespace duckdb @@ -4138,6 +4554,9 @@ class ArrowUtil { struct ArrowArray; namespace duckdb { +class Allocator; +class ClientContext; +class ExecutionContext; class VectorCache; //! A Data Chunk represents a set of vectors. @@ -4188,6 +4607,9 @@ class DataChunk { 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); + //! Returns true if all vectors in the DataChunk are constant + DUCKDB_API bool AllConstant() const; + //! Set the DataChunk to reference another data chunk DUCKDB_API void Reference(DataChunk &chunk); //! Set the DataChunk to own the data of data chunk, destroying the other chunk in the process @@ -4197,7 +4619,8 @@ class DataChunk { //! This will create one vector of the specified type for each LogicalType in the //! types list. The vector will be referencing vector to the data owned by //! the DataChunk. - DUCKDB_API void Initialize(const vector &types); + DUCKDB_API void Initialize(Allocator &allocator, const vector &types); + DUCKDB_API void Initialize(ClientContext &context, const vector &types); //! Initializes an empty DataChunk with the given types. The vectors will *not* have any data allocated for them. DUCKDB_API void InitializeEmpty(const vector &types); //! Append the other DataChunk to this one. The column count and types of @@ -4220,12 +4643,18 @@ class DataChunk { //! Fuses a DataChunk onto the right of this one, and destroys the other. Inverse of Split. DUCKDB_API void Fuse(DataChunk &other); + //! Makes this DataChunk reference the specified columns in the other DataChunk + DUCKDB_API void ReferenceColumns(DataChunk &other, vector column_ids); + //! Turn all the vectors from the chunk into flat vectors - DUCKDB_API void Normalify(); + DUCKDB_API void Flatten(); - DUCKDB_API unique_ptr Orrify(); + DUCKDB_API unique_ptr ToUnifiedFormat(); DUCKDB_API void Slice(const SelectionVector &sel_vector, idx_t count); + + //! Slice all Vectors from other.data[i] to data[i + 'col_offset'] + //! Turning all Vectors into Dictionary Vectors, using 'sel' DUCKDB_API void Slice(DataChunk &other, const SelectionVector &sel, idx_t count, idx_t col_offset = 0); //! Resets the DataChunk to its state right after the DataChunk::Initialize @@ -4254,9 +4683,6 @@ class DataChunk { //! FUNCTION ONLY! DUCKDB_API void Verify(); - //! export data chunk as a arrow struct array that can be imported as arrow record batch - DUCKDB_API void ToArrowArray(ArrowArray *out_array); - private: //! The amount of tuples stored in the data chunk idx_t count; @@ -4416,7 +4842,7 @@ struct VectorOperations { DUCKDB_API static bool TryCast(Vector &source, Vector &result, idx_t count, string *error_message, bool strict = false); //! Cast the data from the source type to the target type. Throws an exception if the cast fails. - static void Cast(Vector &source, Vector &result, idx_t count, bool strict = false); + DUCKDB_API static void Cast(Vector &source, Vector &result, idx_t count, bool strict = false); // Copy the data of to the target vector static void Copy(const Vector &source, Vector &target, idx_t source_count, idx_t source_offset, @@ -4635,10 +5061,10 @@ struct BinaryExecutor { template static void ExecuteGeneric(Vector &left, Vector &right, Vector &result, idx_t count, FUNC fun) { - VectorData ldata, rdata; + UnifiedVectorFormat ldata, rdata; - left.Orrify(count, ldata); - right.Orrify(count, rdata); + left.ToUnifiedFormat(count, ldata); + right.ToUnifiedFormat(count, rdata); result.SetVectorType(VectorType::FLAT_VECTOR); auto result_data = FlatVector::GetData(result); @@ -4809,9 +5235,19 @@ struct BinaryExecutor { auto rdata = FlatVector::GetData(right); if (LEFT_CONSTANT && ConstantVector::IsNull(left)) { + if (false_sel) { + for (idx_t i = 0; i < count; i++) { + false_sel->set_index(i, sel->get_index(i)); + } + } return 0; } if (RIGHT_CONSTANT && ConstantVector::IsNull(right)) { + if (false_sel) { + for (idx_t i = 0; i < count; i++) { + false_sel->set_index(i, sel->get_index(i)); + } + } return 0; } @@ -4894,10 +5330,10 @@ struct BinaryExecutor { template static idx_t SelectGeneric(Vector &left, Vector &right, const SelectionVector *sel, idx_t count, SelectionVector *true_sel, SelectionVector *false_sel) { - VectorData ldata, rdata; + UnifiedVectorFormat ldata, rdata; - left.Orrify(count, ldata); - right.Orrify(count, rdata); + left.ToUnifiedFormat(count, ldata); + right.ToUnifiedFormat(count, rdata); return SelectGenericLoopSwitch((LEFT_TYPE *)ldata.data, (RIGHT_TYPE *)rdata.data, ldata.sel, rdata.sel, sel, count, ldata.validity, @@ -5013,10 +5449,10 @@ struct TernaryExecutor { } else { result.SetVectorType(VectorType::FLAT_VECTOR); - VectorData adata, bdata, cdata; - a.Orrify(count, adata); - b.Orrify(count, bdata); - c.Orrify(count, cdata); + UnifiedVectorFormat adata, bdata, cdata; + a.ToUnifiedFormat(count, adata); + b.ToUnifiedFormat(count, bdata); + c.ToUnifiedFormat(count, cdata); ExecuteLoop( (A_TYPE *)adata.data, (B_TYPE *)bdata.data, (C_TYPE *)cdata.data, @@ -5071,9 +5507,9 @@ struct TernaryExecutor { } template - static inline idx_t SelectLoopSelSwitch(VectorData &adata, VectorData &bdata, VectorData &cdata, - const SelectionVector *sel, idx_t count, SelectionVector *true_sel, - SelectionVector *false_sel) { + static inline idx_t SelectLoopSelSwitch(UnifiedVectorFormat &adata, UnifiedVectorFormat &bdata, + UnifiedVectorFormat &cdata, const SelectionVector *sel, idx_t count, + SelectionVector *true_sel, SelectionVector *false_sel) { if (true_sel && false_sel) { return SelectLoop( (A_TYPE *)adata.data, (B_TYPE *)bdata.data, (C_TYPE *)cdata.data, sel, count, *adata.sel, *bdata.sel, @@ -5091,9 +5527,9 @@ struct TernaryExecutor { } template - static inline idx_t SelectLoopSwitch(VectorData &adata, VectorData &bdata, VectorData &cdata, - const SelectionVector *sel, idx_t count, SelectionVector *true_sel, - SelectionVector *false_sel) { + static inline idx_t SelectLoopSwitch(UnifiedVectorFormat &adata, UnifiedVectorFormat &bdata, + UnifiedVectorFormat &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(adata, bdata, cdata, sel, count, true_sel, false_sel); @@ -5110,10 +5546,10 @@ struct TernaryExecutor { if (!sel) { sel = FlatVector::IncrementalSelectionVector(); } - VectorData adata, bdata, cdata; - a.Orrify(count, adata); - b.Orrify(count, bdata); - c.Orrify(count, cdata); + UnifiedVectorFormat adata, bdata, cdata; + a.ToUnifiedFormat(count, adata); + b.ToUnifiedFormat(count, bdata); + c.ToUnifiedFormat(count, cdata); return SelectLoopSwitch(adata, bdata, cdata, sel, count, true_sel, false_sel); } @@ -5293,8 +5729,8 @@ struct UnaryExecutor { break; } default: { - VectorData vdata; - input.Orrify(count, vdata); + UnifiedVectorFormat vdata; + input.ToUnifiedFormat(count, vdata); result.SetVectorType(VectorType::FLAT_VECTOR); auto result_data = FlatVector::GetData(result); @@ -5450,7 +5886,6 @@ class CycleCounter { - //===----------------------------------------------------------------------===// // DuckDB // @@ -5552,6 +5987,15 @@ class StringUtil { //! Join multiple strings into one string. Components are concatenated by the given separator DUCKDB_API static string Join(const vector &input, const string &separator); + template + static string ToString(const vector &input, const string &separator) { + vector input_list; + for (auto &i : input) { + input_list.push_back(i.ToString()); + } + return StringUtil::Join(input_list, separator); + } + //! Join multiple items of container with given size, transformed to string //! using function, into one string using the given separator template @@ -5656,6 +6100,29 @@ using named_parameter_map_t = case_insensitive_map_t; } // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/main/external_dependencies.hpp +// +// +//===----------------------------------------------------------------------===// + + + +namespace duckdb { + +enum ExternalDependenciesType { PYTHON_DEPENDENCY }; +class ExternalDependency { +public: + explicit ExternalDependency(ExternalDependenciesType type_p) : type(type_p) {}; + virtual ~ExternalDependency() {}; + ExternalDependenciesType type; +}; + +} // namespace duckdb + //===----------------------------------------------------------------------===// // DuckDB // @@ -5882,6 +6349,7 @@ enum class ExpressionClass : uint8_t { BOUND_WINDOW = 38, BOUND_BETWEEN = 39, BOUND_UNNEST = 40, + BOUND_LAMBDA = 41, //===--------------------------------------------------------------------===// // Miscellaneous //===--------------------------------------------------------------------===// @@ -5899,6 +6367,8 @@ ExpressionType NegateComparisionExpression(ExpressionType type); //! Flip a comparison expression, turning e.g. < into >, or = into = ExpressionType FlipComparisionExpression(ExpressionType type); +DUCKDB_API string ExpressionClassToString(ExpressionClass type); + } // namespace duckdb @@ -6301,7 +6771,10 @@ class ColumnDefinition { void ChangeGeneratedExpressionType(const LogicalType &type); void GetListOfDependencies(vector &dependencies) const; -private: + string GetName(); + + LogicalType GetType(); + private: //! The name of the entry string name; @@ -6334,13 +6807,19 @@ class AggregateFunction; class AggregateFunctionSet; class CopyFunction; class PragmaFunction; +class PragmaFunctionSet; class ScalarFunctionSet; class ScalarFunction; class TableFunctionSet; class TableFunction; +class SimpleFunction; struct PragmaInfo; +//! The default null handling is NULL in, NULL out +enum class FunctionNullHandling : uint8_t { DEFAULT_NULL_HANDLING = 0, SPECIAL_HANDLING = 1 }; +enum class FunctionSideEffects : uint8_t { NO_SIDE_EFFECTS = 0, HAS_SIDE_EFFECTS = 1 }; + struct FunctionData { DUCKDB_API virtual ~FunctionData(); @@ -6359,6 +6838,11 @@ struct TableFunctionData : public FunctionData { DUCKDB_API bool Equals(const FunctionData &other) const override; }; +struct PyTableFunctionData : public TableFunctionData { + //! External dependencies of this table function + unique_ptr external_dependency; +}; + struct FunctionParameters { vector values; named_parameter_map_t named_parameters; @@ -6385,28 +6869,29 @@ class Function { //! Bind a scalar function from the set of functions and input arguments. Returns the index of the chosen function, //! returns DConstants::INVALID_INDEX and sets error if none could be found - DUCKDB_API static idx_t BindFunction(const string &name, vector &functions, - vector &arguments, string &error, bool &cast_parameters); - DUCKDB_API static idx_t BindFunction(const string &name, vector &functions, - vector> &arguments, string &error, - bool &cast_parameters); + DUCKDB_API static idx_t BindFunction(const string &name, ScalarFunctionSet &functions, + const vector &arguments, string &error); + DUCKDB_API static idx_t BindFunction(const string &name, ScalarFunctionSet &functions, + vector> &arguments, string &error); //! Bind an aggregate function from the set of functions and input arguments. Returns the index of the chosen //! function, returns DConstants::INVALID_INDEX and sets error if none could be found - DUCKDB_API static idx_t BindFunction(const string &name, vector &functions, - vector &arguments, string &error, bool &cast_parameters); - DUCKDB_API static idx_t BindFunction(const string &name, vector &functions, - vector &arguments, string &error); - DUCKDB_API static idx_t BindFunction(const string &name, vector &functions, + DUCKDB_API static idx_t BindFunction(const string &name, AggregateFunctionSet &functions, + const vector &arguments, string &error); + DUCKDB_API static idx_t BindFunction(const string &name, AggregateFunctionSet &functions, vector> &arguments, string &error); //! Bind a table function from the set of functions and input arguments. Returns the index of the chosen //! function, returns DConstants::INVALID_INDEX and sets error if none could be found - DUCKDB_API static idx_t BindFunction(const string &name, vector &functions, - vector &arguments, string &error); - DUCKDB_API static idx_t BindFunction(const string &name, vector &functions, + DUCKDB_API static idx_t BindFunction(const string &name, TableFunctionSet &functions, + const vector &arguments, string &error); + DUCKDB_API static idx_t BindFunction(const string &name, TableFunctionSet &functions, vector> &arguments, string &error); //! Bind a pragma function from the set of functions and input arguments - DUCKDB_API static idx_t BindFunction(const string &name, vector &functions, PragmaInfo &info, + DUCKDB_API static idx_t BindFunction(const string &name, PragmaFunctionSet &functions, PragmaInfo &info, string &error); + + //! Used in the bind to erase an argument from a function + DUCKDB_API static void EraseArgument(SimpleFunction &bound_function, vector> &arguments, + idx_t argument_index); }; class SimpleFunction : public Function { @@ -6417,6 +6902,9 @@ class SimpleFunction : public Function { //! The set of arguments of the function vector arguments; + //! The set of original arguments of the function - only set if Function::EraseArgument is called + //! Used for (de)serialization purposes + vector original_arguments; //! The type of varargs to support, or LogicalTypeId::INVALID if the function does not accept variable length //! arguments LogicalType varargs; @@ -6444,24 +6932,24 @@ class SimpleNamedParameterFunction : public SimpleFunction { class BaseScalarFunction : public SimpleFunction { public: DUCKDB_API BaseScalarFunction(string name, vector arguments, LogicalType return_type, - bool has_side_effects, LogicalType varargs = LogicalType(LogicalTypeId::INVALID), - bool propagates_null_values = false); + FunctionSideEffects side_effects, + LogicalType varargs = LogicalType(LogicalTypeId::INVALID), + FunctionNullHandling null_handling = FunctionNullHandling::DEFAULT_NULL_HANDLING); DUCKDB_API ~BaseScalarFunction() override; //! Return type of the function LogicalType return_type; //! Whether or not the function has side effects (e.g. sequence increments, random() functions, NOW()). Functions //! with side-effects cannot be constant-folded. - bool has_side_effects; - //! Whether or not the function propagates null values - bool propagates_null_values; + FunctionSideEffects side_effects; + //! How this function handles NULL values + FunctionNullHandling null_handling; public: DUCKDB_API hash_t Hash() const; //! Cast a set of expressions to the arguments of this function - DUCKDB_API void CastToFunctionArguments(vector> &children, - bool cast_parameter_expressions = true); + DUCKDB_API void CastToFunctionArguments(vector> &children); DUCKDB_API string ToString() override; }; @@ -6478,7 +6966,7 @@ class BuiltinFunctions { void AddFunction(AggregateFunction function); void AddFunction(ScalarFunctionSet set); void AddFunction(PragmaFunction function); - void AddFunction(const string &name, vector functions); + void AddFunction(const string &name, PragmaFunctionSet functions); void AddFunction(ScalarFunction function); void AddFunction(const vector &names, ScalarFunction function); void AddFunction(TableFunctionSet set); @@ -6499,6 +6987,7 @@ class BuiltinFunctions { } // table-producing functions + void RegisterTableScanFunctions(); void RegisterSQLiteFunctions(); void RegisterReadFunctions(); void RegisterTableFunctions(); @@ -6627,130 +7116,130 @@ namespace duckdb { template struct NumericLimits { - static T Minimum(); - static T Maximum(); - static bool IsSigned(); - static idx_t Digits(); + DUCKDB_API static T Minimum(); + DUCKDB_API static T Maximum(); + DUCKDB_API static bool IsSigned(); + DUCKDB_API static idx_t Digits(); }; template <> struct NumericLimits { - static int8_t Minimum(); - static int8_t Maximum(); - static bool IsSigned() { + DUCKDB_API static int8_t Minimum(); + DUCKDB_API static int8_t Maximum(); + DUCKDB_API static bool IsSigned() { return true; } - static idx_t Digits() { + DUCKDB_API static idx_t Digits() { return 3; } }; template <> struct NumericLimits { - static int16_t Minimum(); - static int16_t Maximum(); - static bool IsSigned() { + DUCKDB_API static int16_t Minimum(); + DUCKDB_API static int16_t Maximum(); + DUCKDB_API static bool IsSigned() { return true; } - static idx_t Digits() { + DUCKDB_API static idx_t Digits() { return 5; } }; template <> struct NumericLimits { - static int32_t Minimum(); - static int32_t Maximum(); - static bool IsSigned() { + DUCKDB_API static int32_t Minimum(); + DUCKDB_API static int32_t Maximum(); + DUCKDB_API static bool IsSigned() { return true; } - static idx_t Digits() { + DUCKDB_API static idx_t Digits() { return 10; } }; template <> struct NumericLimits { - static int64_t Minimum(); - static int64_t Maximum(); - static bool IsSigned() { + DUCKDB_API static int64_t Minimum(); + DUCKDB_API static int64_t Maximum(); + DUCKDB_API static bool IsSigned() { return true; } - static idx_t Digits() { + DUCKDB_API static idx_t Digits() { return 19; } }; template <> struct NumericLimits { - static hugeint_t Minimum(); - static hugeint_t Maximum(); - static bool IsSigned() { + DUCKDB_API static hugeint_t Minimum(); + DUCKDB_API static hugeint_t Maximum(); + DUCKDB_API static bool IsSigned() { return true; } - static idx_t Digits() { + DUCKDB_API static idx_t Digits() { return 39; } }; template <> struct NumericLimits { - static uint8_t Minimum(); - static uint8_t Maximum(); - static bool IsSigned() { + DUCKDB_API static uint8_t Minimum(); + DUCKDB_API static uint8_t Maximum(); + DUCKDB_API static bool IsSigned() { return false; } - static idx_t Digits() { + DUCKDB_API static idx_t Digits() { return 3; } }; template <> struct NumericLimits { - static uint16_t Minimum(); - static uint16_t Maximum(); - static bool IsSigned() { + DUCKDB_API static uint16_t Minimum(); + DUCKDB_API static uint16_t Maximum(); + DUCKDB_API static bool IsSigned() { return false; } - static idx_t Digits() { + DUCKDB_API static idx_t Digits() { return 5; } }; template <> struct NumericLimits { - static uint32_t Minimum(); - static uint32_t Maximum(); - static bool IsSigned() { + DUCKDB_API static uint32_t Minimum(); + DUCKDB_API static uint32_t Maximum(); + DUCKDB_API static bool IsSigned() { return false; } - static idx_t Digits() { + DUCKDB_API static idx_t Digits() { return 10; } }; template <> struct NumericLimits { - static uint64_t Minimum(); - static uint64_t Maximum(); - static bool IsSigned() { + DUCKDB_API static uint64_t Minimum(); + DUCKDB_API static uint64_t Maximum(); + DUCKDB_API static bool IsSigned() { return false; } - static idx_t Digits() { + DUCKDB_API static idx_t Digits() { return 20; } }; template <> struct NumericLimits { - static float Minimum(); - static float Maximum(); - static bool IsSigned() { + DUCKDB_API static float Minimum(); + DUCKDB_API static float Maximum(); + DUCKDB_API static bool IsSigned() { return true; } - static idx_t Digits() { + DUCKDB_API static idx_t Digits() { return 127; } }; template <> struct NumericLimits { - static double Minimum(); - static double Maximum(); - static bool IsSigned() { + DUCKDB_API static double Minimum(); + DUCKDB_API static double Maximum(); + DUCKDB_API static bool IsSigned() { return true; } - static idx_t Digits() { + DUCKDB_API static idx_t Digits() { return 250; } }; @@ -6764,21 +7253,11 @@ namespace duckdb { //! The Hugeint class contains static operations for the INT128 type class Hugeint { public: - //! Convert a string to a hugeint object - static bool FromString(string str, hugeint_t &result); - //! Convert a string to a hugeint object - static bool FromCString(const char *str, idx_t len, hugeint_t &result); //! Convert a hugeint object to a string static string ToString(hugeint_t input); - static hugeint_t FromString(string str) { - hugeint_t result; - FromString(str, result); - return result; - } - template - static bool TryCast(hugeint_t input, T &result); + DUCKDB_API static bool TryCast(hugeint_t input, T &result); template static T Cast(hugeint_t input) { @@ -6800,6 +7279,9 @@ class Hugeint { } static void NegateInPlace(hugeint_t &input) { + if (input.upper == NumericLimits::Minimum() && input.lower == 0) { + throw OutOfRangeException("HUGEINT is out of range"); + } input.lower = NumericLimits::Maximum() - input.lower + 1; input.upper = -1 - input.upper + (input.lower == 0); } @@ -6865,29 +7347,29 @@ class Hugeint { }; template <> -bool Hugeint::TryCast(hugeint_t input, int8_t &result); +DUCKDB_API bool Hugeint::TryCast(hugeint_t input, int8_t &result); template <> -bool Hugeint::TryCast(hugeint_t input, int16_t &result); +DUCKDB_API bool Hugeint::TryCast(hugeint_t input, int16_t &result); template <> -bool Hugeint::TryCast(hugeint_t input, int32_t &result); +DUCKDB_API bool Hugeint::TryCast(hugeint_t input, int32_t &result); template <> -bool Hugeint::TryCast(hugeint_t input, int64_t &result); +DUCKDB_API bool Hugeint::TryCast(hugeint_t input, int64_t &result); template <> -bool Hugeint::TryCast(hugeint_t input, uint8_t &result); +DUCKDB_API bool Hugeint::TryCast(hugeint_t input, uint8_t &result); template <> -bool Hugeint::TryCast(hugeint_t input, uint16_t &result); +DUCKDB_API bool Hugeint::TryCast(hugeint_t input, uint16_t &result); template <> -bool Hugeint::TryCast(hugeint_t input, uint32_t &result); +DUCKDB_API bool Hugeint::TryCast(hugeint_t input, uint32_t &result); template <> -bool Hugeint::TryCast(hugeint_t input, uint64_t &result); +DUCKDB_API bool Hugeint::TryCast(hugeint_t input, uint64_t &result); template <> -bool Hugeint::TryCast(hugeint_t input, hugeint_t &result); +DUCKDB_API bool Hugeint::TryCast(hugeint_t input, hugeint_t &result); template <> -bool Hugeint::TryCast(hugeint_t input, float &result); +DUCKDB_API bool Hugeint::TryCast(hugeint_t input, float &result); template <> -bool Hugeint::TryCast(hugeint_t input, double &result); +DUCKDB_API bool Hugeint::TryCast(hugeint_t input, double &result); template <> -bool Hugeint::TryCast(hugeint_t input, long double &result); +DUCKDB_API bool Hugeint::TryCast(hugeint_t input, long double &result); template <> bool Hugeint::TryConvert(int8_t value, hugeint_t &result); @@ -6991,6 +7473,9 @@ class Interval { //! Returns the exact difference between two timestamps (days and seconds) static interval_t GetDifference(timestamp_t timestamp_1, timestamp_t timestamp_2); + //! Returns the inverted interval + static interval_t Invert(interval_t interval); + //! Add an interval to a date static date_t Add(date_t left, interval_t right); //! Add an interval to a timestamp @@ -7017,59 +7502,59 @@ namespace duckdb { //===--------------------------------------------------------------------===// struct Equals { template - static inline bool Operation(T left, T right) { + DUCKDB_API static inline bool Operation(T left, T right) { return left == right; } }; struct NotEquals { template - static inline bool Operation(T left, T right) { + DUCKDB_API static inline bool Operation(T left, T right) { return !Equals::Operation(left, right); } }; struct GreaterThan { template - static inline bool Operation(T left, T right) { + DUCKDB_API static inline bool Operation(T left, T right) { return left > right; } }; struct GreaterThanEquals { template - static inline bool Operation(T left, T right) { + DUCKDB_API static inline bool Operation(T left, T right) { return left >= right; } }; struct LessThan { template - static inline bool Operation(T left, T right) { + DUCKDB_API static inline bool Operation(T left, T right) { return GreaterThan::Operation(right, left); } }; struct LessThanEquals { template - static inline bool Operation(T left, T right) { + DUCKDB_API static inline bool Operation(T left, T right) { return GreaterThanEquals::Operation(right, left); } }; template <> -bool Equals::Operation(float left, float right); +DUCKDB_API bool Equals::Operation(float left, float right); template <> -bool Equals::Operation(double left, double right); +DUCKDB_API bool Equals::Operation(double left, double right); template <> -bool GreaterThan::Operation(float left, float right); +DUCKDB_API bool GreaterThan::Operation(float left, float right); template <> -bool GreaterThan::Operation(double left, double right); +DUCKDB_API bool GreaterThan::Operation(double left, double right); template <> -bool GreaterThanEquals::Operation(float left, float right); +DUCKDB_API bool GreaterThanEquals::Operation(float left, float right); template <> -bool GreaterThanEquals::Operation(double left, double right); +DUCKDB_API bool GreaterThanEquals::Operation(double left, double right); // Distinct semantics are from Postgres record sorting. NULL = NULL and not-NULL < NULL // Deferring to the non-distinct operations removes the need for further specialisation. @@ -7302,7 +7787,7 @@ class FieldReader; class Vector; class ValidityStatistics; class DistinctStatistics; -struct VectorData; +struct UnifiedVectorFormat; enum StatisticsType { LOCAL_STATS = 0, GLOBAL_STATS = 1 }; @@ -7341,6 +7826,8 @@ class BaseStatistics { virtual void Serialize(Serializer &serializer) const; virtual void Serialize(FieldWriter &writer) const; + idx_t GetDistinctCount(); + static unique_ptr Deserialize(Deserializer &source, LogicalType type); //! Verify that a vector does not violate the statistics @@ -7362,6 +7849,7 @@ struct FunctionLocalState { DUCKDB_API virtual ~FunctionLocalState(); }; +class Binder; class BoundFunctionExpression; class ScalarFunctionCatalogEntry; @@ -7388,20 +7876,27 @@ typedef unique_ptr (*function_statistics_t)(ClientContext &conte //! Adds the dependencies of this BoundFunctionExpression to the set of dependencies typedef void (*dependency_function_t)(BoundFunctionExpression &expr, unordered_set &dependencies); +typedef void (*function_serialize_t)(FieldWriter &writer, const FunctionData *bind_data, + const ScalarFunction &function); +typedef unique_ptr (*function_deserialize_t)(ClientContext &context, FieldReader &reader, + ScalarFunction &function); + class ScalarFunction : public BaseScalarFunction { public: DUCKDB_API ScalarFunction(string name, vector 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, init_local_state_t init_local_state = nullptr, + scalar_function_t function, bind_scalar_function_t bind = nullptr, + dependency_function_t dependency = nullptr, function_statistics_t statistics = nullptr, + init_local_state_t init_local_state = nullptr, LogicalType varargs = LogicalType(LogicalTypeId::INVALID), - bool propagate_null_values = false); + FunctionSideEffects side_effects = FunctionSideEffects::NO_SIDE_EFFECTS, + FunctionNullHandling null_handling = FunctionNullHandling::DEFAULT_NULL_HANDLING); DUCKDB_API ScalarFunction(vector arguments, LogicalType return_type, scalar_function_t function, - bool propagate_null_values = false, bool has_side_effects = false, bind_scalar_function_t bind = nullptr, dependency_function_t dependency = nullptr, function_statistics_t statistics = nullptr, init_local_state_t init_local_state = nullptr, - LogicalType varargs = LogicalType(LogicalTypeId::INVALID)); + LogicalType varargs = LogicalType(LogicalTypeId::INVALID), + FunctionSideEffects side_effects = FunctionSideEffects::NO_SIDE_EFFECTS, + FunctionNullHandling null_handling = FunctionNullHandling::DEFAULT_NULL_HANDLING); //! The main scalar function to execute scalar_function_t function; @@ -7414,18 +7909,22 @@ class ScalarFunction : public BaseScalarFunction { //! The statistics propagation function (if any) function_statistics_t statistics; + function_serialize_t serialize; + function_deserialize_t deserialize; + + DUCKDB_API static unique_ptr BindScalarFunction(ClientContext &context, const string &schema, + const string &name, + vector> children, string &error, + bool is_operator = false, Binder *binder = nullptr); + DUCKDB_API static unique_ptr BindScalarFunction(ClientContext &context, + ScalarFunctionCatalogEntry &function, + vector> children, string &error, + bool is_operator = false, Binder *binder = nullptr); + DUCKDB_API static unique_ptr BindScalarFunction(ClientContext &context, - const string &schema, const string &name, - vector> children, - string &error, bool is_operator = false); - DUCKDB_API static unique_ptr BindScalarFunction(ClientContext &context, - ScalarFunctionCatalogEntry &function, + ScalarFunction bound_function, vector> children, - string &error, bool is_operator = false); - - DUCKDB_API static unique_ptr - BindScalarFunction(ClientContext &context, ScalarFunction bound_function, vector> children, - bool is_operator = false, bool cast_parameters = true); + bool is_operator = false); DUCKDB_API bool operator==(const ScalarFunction &rhs) const; DUCKDB_API bool operator!=(const ScalarFunction &rhs) const; @@ -7550,10 +8049,12 @@ class ScalarFunction : public BaseScalarFunction { + + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/vector_operations/aggregate_executor.hpp +// duckdb/storage/statistics/node_statistics.hpp // // //===----------------------------------------------------------------------===// @@ -7562,356 +8063,728 @@ class ScalarFunction : public BaseScalarFunction { - - - namespace duckdb { -struct FunctionData; -typedef std::pair FrameBounds; -class AggregateExecutor { -private: - template - 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(states[i], bind_data, i); - } +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) { } - template - static inline void NullaryScatterLoop(STATE_TYPE **__restrict states, FunctionData *bind_data, - const SelectionVector &ssel, idx_t count) { + //! Whether or not the node has an estimated cardinality specified + bool has_estimated_cardinality; + //! The estimated cardinality at the specified node + idx_t estimated_cardinality; + //! Whether or not the node has a maximum cardinality specified + bool has_max_cardinality; + //! The max possible cardinality at the specified node + idx_t max_cardinality; +}; + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/bound_result_modifier.hpp +// +// +//===----------------------------------------------------------------------===// + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/result_modifier.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/enums/order_type.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +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 + + + +namespace duckdb { +class FieldWriter; +class FieldReader; + +enum ResultModifierType : uint8_t { + LIMIT_MODIFIER = 1, + ORDER_MODIFIER = 2, + DISTINCT_MODIFIER = 3, + LIMIT_PERCENT_MODIFIER = 4 +}; + +//! A ResultModifier +class ResultModifier { +public: + explicit ResultModifier(ResultModifierType type) : type(type) { + } + virtual ~ResultModifier() { + } + + ResultModifierType type; + +public: + //! Returns true if the two result modifiers are equivalent + virtual bool Equals(const ResultModifier *other) const; + + //! Create a copy of this ResultModifier + virtual unique_ptr Copy() const = 0; + //! Serializes a ResultModifier to a stand-alone binary blob + void Serialize(Serializer &serializer) const; + //! Serializes a ResultModifier to a stand-alone binary blob + virtual void Serialize(FieldWriter &writer) const = 0; + //! Deserializes a blob back into a ResultModifier + static unique_ptr Deserialize(Deserializer &source); +}; + +//! Single node in ORDER BY statement +struct OrderByNode { + OrderByNode(OrderType type, OrderByNullType null_order, unique_ptr expression) + : type(type), null_order(null_order), expression(move(expression)) { + } + + //! Sort order, ASC or DESC + OrderType type; + //! The NULL sort order, NULLS_FIRST or NULLS_LAST + OrderByNullType null_order; + //! Expression to order by + unique_ptr expression; + +public: + void Serialize(Serializer &serializer) const; + string ToString() const; + static OrderByNode Deserialize(Deserializer &source); +}; + +class LimitModifier : public ResultModifier { +public: + LimitModifier() : ResultModifier(ResultModifierType::LIMIT_MODIFIER) { + } + + //! LIMIT count + unique_ptr limit; + //! OFFSET + unique_ptr offset; + +public: + bool Equals(const ResultModifier *other) const override; + unique_ptr Copy() const override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(FieldReader &reader); +}; + +class OrderModifier : public ResultModifier { +public: + OrderModifier() : ResultModifier(ResultModifierType::ORDER_MODIFIER) { + } + + //! List of order nodes + vector orders; + +public: + bool Equals(const ResultModifier *other) const override; + unique_ptr Copy() const override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(FieldReader &reader); +}; + +class DistinctModifier : public ResultModifier { +public: + DistinctModifier() : ResultModifier(ResultModifierType::DISTINCT_MODIFIER) { + } + + //! list of distinct on targets (if any) + vector> distinct_on_targets; + +public: + bool Equals(const ResultModifier *other) const override; + unique_ptr Copy() const override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(FieldReader &reader); +}; + +class LimitPercentModifier : public ResultModifier { +public: + LimitPercentModifier() : ResultModifier(ResultModifierType::LIMIT_PERCENT_MODIFIER) { + } + + //! LIMIT % + unique_ptr limit; + //! OFFSET + unique_ptr offset; + +public: + bool Equals(const ResultModifier *other) const override; + unique_ptr Copy() const override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(FieldReader &reader); +}; + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/bound_statement.hpp +// +// +//===----------------------------------------------------------------------===// + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/logical_operator.hpp +// +// +//===----------------------------------------------------------------------===// + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/catalog/catalog.hpp +// +// +//===----------------------------------------------------------------------===// + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/catalog/catalog_entry.hpp +// +// +//===----------------------------------------------------------------------===// + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/enums/catalog_type.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { + +//===--------------------------------------------------------------------===// +// Catalog Types +//===--------------------------------------------------------------------===// +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, + TYPE_ENTRY = 8, + + // functions + TABLE_FUNCTION_ENTRY = 25, + SCALAR_FUNCTION_ENTRY = 26, + AGGREGATE_FUNCTION_ENTRY = 27, + PRAGMA_FUNCTION_ENTRY = 28, + COPY_FUNCTION_ENTRY = 29, + MACRO_ENTRY = 30, + TABLE_MACRO_ENTRY = 31, + + // version info + UPDATED_ENTRY = 50, + DELETED_ENTRY = 51, +}; + +DUCKDB_API string CatalogTypeToString(CatalogType type); + +} // namespace duckdb + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/atomic.hpp +// +// +//===----------------------------------------------------------------------===// + + + +#include + +namespace duckdb { +using std::atomic; +} + + +#include + +namespace duckdb { +struct AlterInfo; +class Catalog; +class CatalogSet; +class ClientContext; + +//! Abstract base class of an entry in the catalog +class CatalogEntry { +public: + CatalogEntry(CatalogType type, Catalog *catalog, string name); + virtual ~CatalogEntry(); + + //! The oid of the entry + idx_t oid; + //! The type of this catalog entry + CatalogType type; + //! Reference to the catalog this entry belongs to + Catalog *catalog; + //! Reference to the catalog set this entry is stored in + CatalogSet *set; + //! The name of the entry + string name; + //! Whether or not the object is deleted + bool deleted; + //! Whether or not the object is temporary and should not be added to the WAL + bool temporary; + //! Whether or not the entry is an internal entry (cannot be deleted, not dumped, etc) + bool internal; + //! Timestamp at which the catalog entry was created + atomic timestamp; + //! Child entry + unique_ptr child; + //! Parent entry (the node that dependents_map this node) + CatalogEntry *parent; + +public: + virtual unique_ptr AlterEntry(ClientContext &context, AlterInfo *info); + + virtual unique_ptr Copy(ClientContext &context); + + //! Sets the CatalogEntry as the new root entry (i.e. the newest entry) + // this is called on a rollback to an AlterEntry + virtual void SetAsRoot(); + + //! Convert the catalog entry to a SQL string that can be used to re-construct the catalog entry + virtual string ToSQL(); +}; +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/mutex.hpp +// +// +//===----------------------------------------------------------------------===// - for (idx_t i = 0; i < count; i++) { - auto sidx = ssel.get_index(i); - OP::template Operation(states[sidx], bind_data, sidx); - } + + +#include + +namespace duckdb { +using std::lock_guard; +using std::mutex; +using std::unique_lock; +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/query_error_context.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + +namespace duckdb { +class SQLStatement; + +class QueryErrorContext { +public: + explicit QueryErrorContext(SQLStatement *statement_ = nullptr, idx_t query_location_ = DConstants::INVALID_INDEX) + : statement(statement_), query_location(query_location_) { + } + + //! The query statement + SQLStatement *statement; + //! The location in which the error should be thrown + idx_t query_location; + +public: + static string Format(const string &query, const string &error_message, int error_location); + + string FormatErrorRecursive(const string &msg, vector &values); + template + string FormatErrorRecursive(const string &msg, vector &values, T param, Args... params) { + values.push_back(ExceptionFormatValue::CreateFormatValue(param)); + return FormatErrorRecursive(msg, values, params...); + } + + template + string FormatError(const string &msg, Args... params) { + vector values; + return FormatErrorRecursive(msg, values, params...); + } +}; + +} // namespace duckdb + + +#include + + +namespace duckdb { +struct CreateSchemaInfo; +struct DropInfo; +struct BoundCreateTableInfo; +struct AlterTableInfo; +struct CreateTableFunctionInfo; +struct CreateCopyFunctionInfo; +struct CreatePragmaFunctionInfo; +struct CreateFunctionInfo; +struct CreateViewInfo; +struct CreateSequenceInfo; +struct CreateCollationInfo; +struct CreateTypeInfo; +struct CreateTableInfo; + +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; + +//! Return value of Catalog::LookupEntry +struct CatalogEntryLookup { + SchemaCatalogEntry *schema; + CatalogEntry *entry; + + DUCKDB_API bool Found() const { + return entry; + } +}; + +//! Return value of SimilarEntryInSchemas +struct SimilarCatalogEntry { + //! The entry name. Empty if absent + string name; + //! The distance to the given name. + idx_t distance; + //! The schema of the entry. + SchemaCatalogEntry *schema; + + DUCKDB_API bool Found() const { + return !name.empty(); + } + + DUCKDB_API string GetQualifiedName() const; +}; + +//! The Catalog object represents the catalog of the database. +class Catalog { +public: + explicit Catalog(DatabaseInstance &db); + ~Catalog(); + + //! Reference to the database + DatabaseInstance &db; + //! The catalog set holding the schemas + unique_ptr schemas; + //! The DependencyManager manages dependencies between different catalog objects + unique_ptr dependency_manager; + //! Write lock for the catalog + mutex write_lock; + +public: + //! Get the Catalog from the ClientContext + DUCKDB_API static Catalog &GetCatalog(ClientContext &context); + //! Get the Catalog from the DatabaseInstance + DUCKDB_API static Catalog &GetCatalog(DatabaseInstance &db); + + DUCKDB_API DependencyManager &GetDependencyManager() { + return *dependency_manager; } - template - 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(base_idx + ValidityMask::BITS_PER_VALUE, count); - if (!OP::IgnoreNull() || ValidityMask::AllValid(validity_entry)) { - // all valid: perform operation - for (; base_idx < next; base_idx++) { - OP::template Operation(states[base_idx], bind_data, idata, mask, - base_idx); - } - } else if (ValidityMask::NoneValid(validity_entry)) { - // nothing valid: skip all - base_idx = next; - continue; - } else { - // partially valid: need to check individual elements for validity - idx_t start = base_idx; - for (; base_idx < next; base_idx++) { - if (ValidityMask::RowIsValid(validity_entry, base_idx - start)) { - OP::template Operation(states[base_idx], bind_data, idata, mask, - base_idx); - } - } - } - } - } else { - for (idx_t i = 0; i < count; i++) { - OP::template Operation(states[i], bind_data, idata, mask, i); - } - } - } + //! Returns the current version of the catalog (incremented whenever anything changes, not stored between restarts) + DUCKDB_API idx_t GetCatalogVersion(); + //! Trigger a modification in the catalog, increasing the catalog version and returning the previous version + DUCKDB_API idx_t ModifyCatalog(); + + //! Creates a schema in the catalog. + DUCKDB_API CatalogEntry *CreateSchema(ClientContext &context, CreateSchemaInfo *info); + //! Creates a table in the catalog. + DUCKDB_API CatalogEntry *CreateTable(ClientContext &context, BoundCreateTableInfo *info); + //! Creates a table in the catalog. + DUCKDB_API CatalogEntry *CreateTable(ClientContext &context, unique_ptr info); + //! Create a table function in the catalog + DUCKDB_API CatalogEntry *CreateTableFunction(ClientContext &context, CreateTableFunctionInfo *info); + //! Create a copy function in the catalog + DUCKDB_API CatalogEntry *CreateCopyFunction(ClientContext &context, CreateCopyFunctionInfo *info); + //! Create a pragma function in the catalog + DUCKDB_API CatalogEntry *CreatePragmaFunction(ClientContext &context, CreatePragmaFunctionInfo *info); + //! Create a scalar or aggregate function in the catalog + DUCKDB_API CatalogEntry *CreateFunction(ClientContext &context, CreateFunctionInfo *info); + //! Creates a table in the catalog. + DUCKDB_API CatalogEntry *CreateView(ClientContext &context, CreateViewInfo *info); + //! Creates a sequence in the catalog. + DUCKDB_API CatalogEntry *CreateSequence(ClientContext &context, CreateSequenceInfo *info); + //! Creates a Enum in the catalog. + DUCKDB_API CatalogEntry *CreateType(ClientContext &context, CreateTypeInfo *info); + //! Creates a collation in the catalog + DUCKDB_API CatalogEntry *CreateCollation(ClientContext &context, CreateCollationInfo *info); + + //! Creates a table in the catalog. + DUCKDB_API CatalogEntry *CreateTable(ClientContext &context, SchemaCatalogEntry *schema, + BoundCreateTableInfo *info); + //! Create a table function in the catalog + DUCKDB_API CatalogEntry *CreateTableFunction(ClientContext &context, SchemaCatalogEntry *schema, + CreateTableFunctionInfo *info); + //! Create a copy function in the catalog + DUCKDB_API CatalogEntry *CreateCopyFunction(ClientContext &context, SchemaCatalogEntry *schema, + CreateCopyFunctionInfo *info); + //! Create a pragma function in the catalog + DUCKDB_API CatalogEntry *CreatePragmaFunction(ClientContext &context, SchemaCatalogEntry *schema, + CreatePragmaFunctionInfo *info); + //! Create a scalar or aggregate function in the catalog + DUCKDB_API CatalogEntry *CreateFunction(ClientContext &context, SchemaCatalogEntry *schema, + CreateFunctionInfo *info); + //! Creates a table in the catalog. + DUCKDB_API CatalogEntry *CreateView(ClientContext &context, SchemaCatalogEntry *schema, CreateViewInfo *info); + //! Creates a table in the catalog. + DUCKDB_API CatalogEntry *CreateSequence(ClientContext &context, SchemaCatalogEntry *schema, + CreateSequenceInfo *info); + //! Creates a enum in the catalog. + DUCKDB_API CatalogEntry *CreateType(ClientContext &context, SchemaCatalogEntry *schema, CreateTypeInfo *info); + //! Creates a collation in the catalog + DUCKDB_API CatalogEntry *CreateCollation(ClientContext &context, SchemaCatalogEntry *schema, + CreateCollationInfo *info); + + //! Drops an entry from the catalog + DUCKDB_API void DropEntry(ClientContext &context, DropInfo *info); + + //! Returns the schema object with the specified name, or throws an exception if it does not exist + DUCKDB_API SchemaCatalogEntry *GetSchema(ClientContext &context, const string &name = DEFAULT_SCHEMA, + bool if_exists = false, + QueryErrorContext error_context = QueryErrorContext()); + //! Scans all the schemas in the system one-by-one, invoking the callback for each entry + DUCKDB_API void ScanSchemas(ClientContext &context, std::function callback); + //! Gets the "schema.name" entry of the specified type, if if_exists=true returns nullptr if entry does not + //! exist, otherwise an exception is thrown + DUCKDB_API CatalogEntry *GetEntry(ClientContext &context, CatalogType type, const string &schema, + const string &name, bool if_exists = false, + QueryErrorContext error_context = QueryErrorContext()); + + //! Gets the "schema.name" entry without a specified type, if entry does not exist an exception is thrown + DUCKDB_API CatalogEntry *GetEntry(ClientContext &context, const string &schema, const string &name); + + //! Fetches a logical type from the catalog + DUCKDB_API LogicalType GetType(ClientContext &context, const string &schema, const string &name); + + template + T *GetEntry(ClientContext &context, const string &schema_name, const string &name, bool if_exists = false, + QueryErrorContext error_context = QueryErrorContext()); + + //! Append a scalar or aggregate function to the catalog + DUCKDB_API CatalogEntry *AddFunction(ClientContext &context, CreateFunctionInfo *info); + //! Append a scalar or aggregate function to the catalog + DUCKDB_API CatalogEntry *AddFunction(ClientContext &context, SchemaCatalogEntry *schema, CreateFunctionInfo *info); + + //! Alter an existing entry in the catalog. + DUCKDB_API void Alter(ClientContext &context, AlterInfo *info); + +private: + //! The catalog version, incremented whenever anything changes in the catalog + atomic catalog_version; + +private: + //! A variation of GetEntry that returns an associated schema as well. + CatalogEntryLookup LookupEntry(ClientContext &context, CatalogType type, const string &schema, const string &name, + bool if_exists = false, QueryErrorContext error_context = QueryErrorContext()); + + //! Return an exception with did-you-mean suggestion. + CatalogException CreateMissingEntryException(ClientContext &context, const string &entry_name, CatalogType type, + const vector &schemas, + QueryErrorContext error_context); + + //! Return the close entry name, the distance and the belonging schema. + SimilarCatalogEntry SimilarEntryInSchemas(ClientContext &context, const string &entry_name, CatalogType type, + const vector &schemas); + + void DropSchema(ClientContext &context, DropInfo *info); +}; + +template <> +DUCKDB_API TableCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, const string &name, + bool if_exists, QueryErrorContext error_context); +template <> +DUCKDB_API SequenceCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, + const string &name, bool if_exists, QueryErrorContext error_context); +template <> +DUCKDB_API TableFunctionCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, + const string &name, bool if_exists, + QueryErrorContext error_context); +template <> +DUCKDB_API CopyFunctionCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, + const string &name, bool if_exists, + QueryErrorContext error_context); +template <> +DUCKDB_API PragmaFunctionCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, + const string &name, bool if_exists, + QueryErrorContext error_context); +template <> +DUCKDB_API AggregateFunctionCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, + const string &name, bool if_exists, + QueryErrorContext error_context); +template <> +DUCKDB_API CollateCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, const string &name, + bool if_exists, QueryErrorContext error_context); +template <> +DUCKDB_API TypeCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, const string &name, + bool if_exists, QueryErrorContext error_context); + +} // namespace duckdb - template - 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()) { - // potential NULL values and NULL values are ignored - 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(states[sidx], bind_data, idata, mask, idx); - } - } - } else { - // quick path: no NULL values or NULL values are not ignored - for (idx_t i = 0; i < count; i++) { - auto idx = isel.get_index(i); - auto sidx = ssel.get_index(i); - OP::template Operation(states[sidx], bind_data, idata, mask, idx); - } - } - } +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/optimizer/estimated_properties.hpp +// +// +//===----------------------------------------------------------------------===// - template - 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(base_idx + ValidityMask::BITS_PER_VALUE, count); - if (!OP::IgnoreNull() || ValidityMask::AllValid(validity_entry)) { - // all valid: perform operation - for (; base_idx < next; base_idx++) { - OP::template Operation(state, bind_data, idata, mask, base_idx); - } - } else if (ValidityMask::NoneValid(validity_entry)) { - // nothing valid: skip all - base_idx = next; - continue; - } else { - // partially valid: need to check individual elements for validity - idx_t start = base_idx; - for (; base_idx < next; base_idx++) { - if (ValidityMask::RowIsValid(validity_entry, base_idx - start)) { - OP::template Operation(state, bind_data, idata, mask, base_idx); - } - } - } - } - } - template - 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()) { - // potential NULL values and NULL values are ignored - for (idx_t i = 0; i < count; i++) { - auto idx = sel_vector.get_index(i); - if (mask.RowIsValid(idx)) { - OP::template Operation(state, bind_data, idata, mask, idx); - } - } - } else { - // quick path: no NULL values or NULL values are not ignored - for (idx_t i = 0; i < count; i++) { - auto idx = sel_vector.get_index(i); - OP::template Operation(state, bind_data, idata, mask, idx); - } - } - } - template - 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())) { - // potential NULL values and NULL values are ignored - 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(states[sidx], bind_data, adata, bdata, - avalidity, bvalidity, aidx, bidx); - } - } - } else { - // quick path: no NULL values or NULL values are not ignored - 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(states[sidx], bind_data, adata, bdata, avalidity, - bvalidity, aidx, bidx); - } - } - } - template - 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())) { - // potential NULL values and NULL values are ignored - 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(state, bind_data, adata, bdata, avalidity, - bvalidity, aidx, bidx); - } - } - } else { - // quick path: no NULL values or NULL values are not ignored - for (idx_t i = 0; i < count; i++) { - auto aidx = asel.get_index(i); - auto bidx = bsel.get_index(i); - OP::template Operation(state, bind_data, adata, bdata, avalidity, - bvalidity, aidx, bidx); - } - } - } -public: - template - static void NullaryScatter(Vector &states, FunctionData *bind_data, idx_t count) { - if (states.GetVectorType() == VectorType::CONSTANT_VECTOR) { - auto sdata = ConstantVector::GetData(states); - OP::template ConstantOperation(*sdata, bind_data, count); - } else if (states.GetVectorType() == VectorType::FLAT_VECTOR) { - auto sdata = FlatVector::GetData(states); - NullaryFlatLoop(sdata, bind_data, count); - } else { - VectorData sdata; - states.Orrify(count, sdata); - NullaryScatterLoop((STATE_TYPE **)sdata.data, bind_data, *sdata.sel, count); - } - } +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/optimizer/join_order/join_relation.hpp +// +// +//===----------------------------------------------------------------------===// - template - static void NullaryUpdate(data_ptr_t state, FunctionData *bind_data, idx_t count) { - OP::template ConstantOperation((STATE_TYPE *)state, bind_data, count); - } - template - 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)) { - // constant NULL input in function that ignores NULL values - return; - } - // regular constant: get first state - auto idata = ConstantVector::GetData(input); - auto sdata = ConstantVector::GetData(states); - OP::template ConstantOperation(*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); - auto sdata = FlatVector::GetData(states); - UnaryFlatLoop(idata, bind_data, sdata, FlatVector::Validity(input), count); - } else { - VectorData idata, sdata; - input.Orrify(count, idata); - states.Orrify(count, sdata); - UnaryScatterLoop((INPUT_TYPE *)idata.data, bind_data, (STATE_TYPE **)sdata.data, - *idata.sel, *sdata.sel, idata.validity, count); - } - } - template - 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); - OP::template ConstantOperation((STATE_TYPE *)state, bind_data, idata, - ConstantVector::Validity(input), count); - break; - } - case VectorType::FLAT_VECTOR: { - auto idata = FlatVector::GetData(input); - UnaryFlatUpdateLoop(idata, bind_data, (STATE_TYPE *)state, count, - FlatVector::Validity(input)); - break; - } - default: { - VectorData idata; - input.Orrify(count, idata); - UnaryUpdateLoop((INPUT_TYPE *)idata.data, bind_data, (STATE_TYPE *)state, count, - idata.validity, *idata.sel); - break; - } - } - } - template - 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((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 - static void BinaryUpdate(FunctionData *bind_data, Vector &a, Vector &b, data_ptr_t state, idx_t count) { - VectorData adata, bdata; +namespace duckdb { +class LogicalOperator; - a.Orrify(count, adata); - b.Orrify(count, bdata); +//! Represents a single relation and any metadata accompanying that relation +struct SingleJoinRelation { + LogicalOperator *op; + LogicalOperator *parent; - BinaryUpdateLoop((A_TYPE *)adata.data, bind_data, (B_TYPE *)bdata.data, - (STATE_TYPE *)state, count, *adata.sel, *bdata.sel, - adata.validity, bdata.validity); + SingleJoinRelation() { } + SingleJoinRelation(LogicalOperator *op, LogicalOperator *parent) : op(op), parent(parent) { + } +}; - template - static void Combine(Vector &source, Vector &target, FunctionData *bind_data, idx_t count) { - D_ASSERT(source.GetType().id() == LogicalTypeId::POINTER && target.GetType().id() == LogicalTypeId::POINTER); - auto sdata = FlatVector::GetData(source); - auto tdata = FlatVector::GetData(target); - - for (idx_t i = 0; i < count; i++) { - OP::template Combine(*sdata[i], tdata[i], bind_data); - } +//! Set of relations, used in the join graph. +struct JoinRelationSet { + JoinRelationSet(unique_ptr relations, idx_t count) : relations(move(relations)), count(count) { } - template - 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); + string ToString() const; - auto sdata = ConstantVector::GetData(states); - auto rdata = ConstantVector::GetData(result); - OP::template Finalize(result, bind_data, *sdata, rdata, - ConstantVector::Validity(result), 0); - } else { - D_ASSERT(states.GetVectorType() == VectorType::FLAT_VECTOR); - result.SetVectorType(VectorType::FLAT_VECTOR); + unique_ptr relations; + idx_t count; - auto sdata = FlatVector::GetData(states); - auto rdata = FlatVector::GetData(result); - for (idx_t i = 0; i < count; i++) { - OP::template Finalize(result, bind_data, sdata[i], rdata, - FlatVector::Validity(result), i + offset); - } - } - } + static bool IsSubset(JoinRelationSet *super, JoinRelationSet *sub); +}; - template - static void UnaryWindow(Vector &input, const ValidityMask &ifilter, FunctionData *bind_data, data_ptr_t state, - const FrameBounds &frame, const FrameBounds &prev, Vector &result, idx_t rid, idx_t bias) { +//! The JoinRelationTree is a structure holding all the created JoinRelationSet objects and allowing fast lookup on to +//! them +class JoinRelationSetManager { +public: + //! Contains a node with a JoinRelationSet and child relations + // FIXME: this structure is inefficient, could use a bitmap for lookup instead (todo: profile) + struct JoinRelationTreeNode { + unique_ptr relation; + unordered_map> children; + }; - auto idata = FlatVector::GetData(input) - bias; - const auto &ivalid = FlatVector::Validity(input); - OP::template Window(idata, ifilter, ivalid, bind_data, (STATE *)state, frame, - prev, result, rid, bias); - } +public: + //! Create or get a JoinRelationSet from a single node with the given index + JoinRelationSet *GetJoinRelation(idx_t index); + //! Create or get a JoinRelationSet from a set of relation bindings + JoinRelationSet *GetJoinRelation(unordered_set &bindings); + //! Create or get a JoinRelationSet from a (sorted, duplicate-free!) list of relations + JoinRelationSet *GetJoinRelation(unique_ptr relations, idx_t count); + //! Union two sets of relations together and create a new relation set + JoinRelationSet *Union(JoinRelationSet *left, JoinRelationSet *right); + // //! Create the set difference of left \ right (i.e. all elements in left that are not in right) + // JoinRelationSet *Difference(JoinRelationSet *left, JoinRelationSet *right); - template - static void Destroy(Vector &states, idx_t count) { - auto sdata = FlatVector::GetData(states); - for (idx_t i = 0; i < count; i++) { - OP::template Destroy(sdata[i]); - } - } +private: + JoinRelationTreeNode root; }; } // namespace duckdb - - //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/storage/statistics/node_statistics.hpp +// duckdb/parser/expression_map.hpp // // //===----------------------------------------------------------------------===// @@ -7920,36 +8793,34 @@ class AggregateExecutor { + + namespace duckdb { +class Expression; -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) { +struct ExpressionHashFunction { + uint64_t operator()(const BaseExpression *const &expr) const { + return (uint64_t)expr->Hash(); } +}; - //! Whether or not the node has an estimated cardinality specified - bool has_estimated_cardinality; - //! The estimated cardinality at the specified node - idx_t estimated_cardinality; - //! Whether or not the node has a maximum cardinality specified - bool has_max_cardinality; - //! The max possible cardinality at the specified node - idx_t max_cardinality; +struct ExpressionEquality { + bool operator()(const BaseExpression *const &a, const BaseExpression *const &b) const { + return a->Equals(b); + } }; +template +using expression_map_t = unordered_map; + +using expression_set_t = unordered_set; + } // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/planner/bound_result_modifier.hpp +// duckdb/planner/logical_operator_visitor.hpp // // //===----------------------------------------------------------------------===// @@ -7960,334 +8831,473 @@ class NodeStatistics { //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/parser/result_modifier.hpp +// duckdb/planner/bound_tokens.hpp // // //===----------------------------------------------------------------------===// +namespace duckdb { + +//===--------------------------------------------------------------------===// +// Query Node +//===--------------------------------------------------------------------===// +class BoundQueryNode; +class BoundSelectNode; +class BoundSetOperationNode; +class BoundRecursiveCTENode; + +//===--------------------------------------------------------------------===// +// Expressions +//===--------------------------------------------------------------------===// +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; + +//===--------------------------------------------------------------------===// +// TableRefs +//===--------------------------------------------------------------------===// +class BoundTableRef; + +class BoundBaseTableRef; +class BoundCrossProductRef; +class BoundJoinRef; +class BoundSubqueryRef; +class BoundTableFunction; +class BoundEmptyTableRef; +class BoundExpressionListRef; +class BoundCTERef; +} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/enums/order_type.hpp +// duckdb/planner/logical_tokens.hpp // // //===----------------------------------------------------------------------===// - - 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 }; +class LogicalOperator; + +class LogicalAggregate; +class LogicalAnyJoin; +class LogicalColumnDataGet; +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; } // namespace duckdb +#include namespace duckdb { -class FieldWriter; -class FieldReader; - -enum ResultModifierType : uint8_t { - LIMIT_MODIFIER = 1, - ORDER_MODIFIER = 2, - DISTINCT_MODIFIER = 3, - LIMIT_PERCENT_MODIFIER = 4 -}; - -//! A ResultModifier -class ResultModifier { -public: - explicit ResultModifier(ResultModifierType type) : type(type) { - } - virtual ~ResultModifier() { - } - - ResultModifierType type; - -public: - //! Returns true if the two result modifiers are equivalent - virtual bool Equals(const ResultModifier *other) const; - - //! Create a copy of this ResultModifier - virtual unique_ptr Copy() const = 0; - //! Serializes a ResultModifier to a stand-alone binary blob - void Serialize(Serializer &serializer) const; - //! Serializes a ResultModifier to a stand-alone binary blob - virtual void Serialize(FieldWriter &writer) const = 0; - //! Deserializes a blob back into a ResultModifier - static unique_ptr Deserialize(Deserializer &source); -}; - -//! Single node in ORDER BY statement -struct OrderByNode { - OrderByNode(OrderType type, OrderByNullType null_order, unique_ptr expression) - : type(type), null_order(null_order), expression(move(expression)) { - } - - //! Sort order, ASC or DESC - OrderType type; - //! The NULL sort order, NULLS_FIRST or NULLS_LAST - OrderByNullType null_order; - //! Expression to order by - unique_ptr expression; - -public: - void Serialize(Serializer &serializer) const; - string ToString() const; - static OrderByNode Deserialize(Deserializer &source); -}; - -class LimitModifier : public ResultModifier { -public: - LimitModifier() : ResultModifier(ResultModifierType::LIMIT_MODIFIER) { - } - - //! LIMIT count - unique_ptr limit; - //! OFFSET - unique_ptr offset; - -public: - bool Equals(const ResultModifier *other) const override; - unique_ptr Copy() const override; - void Serialize(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader); -}; - -class OrderModifier : public ResultModifier { -public: - OrderModifier() : ResultModifier(ResultModifierType::ORDER_MODIFIER) { - } - - //! List of order nodes - vector orders; - -public: - bool Equals(const ResultModifier *other) const override; - unique_ptr Copy() const override; - void Serialize(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader); -}; - -class DistinctModifier : public ResultModifier { +//! The LogicalOperatorVisitor is an abstract base class that implements the +//! Visitor pattern on LogicalOperator. +class LogicalOperatorVisitor { public: - DistinctModifier() : ResultModifier(ResultModifierType::DISTINCT_MODIFIER) { - } + virtual ~LogicalOperatorVisitor() {}; - //! list of distinct on targets (if any) - vector> distinct_on_targets; + virtual void VisitOperator(LogicalOperator &op); + virtual void VisitExpression(unique_ptr *expression); -public: - bool Equals(const ResultModifier *other) const override; - unique_ptr Copy() const override; - void Serialize(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader); -}; + static void EnumerateExpressions(LogicalOperator &op, + const std::function *child)> &callback); -class LimitPercentModifier : public ResultModifier { -public: - LimitPercentModifier() : ResultModifier(ResultModifierType::LIMIT_PERCENT_MODIFIER) { - } +protected: + //! Automatically calls the Visit method for LogicalOperator children of the current operator. Can be overloaded to + //! change this behavior. + void VisitOperatorChildren(LogicalOperator &op); + //! Automatically calls the Visit method for Expression children of the current operator. Can be overloaded to + //! change this behavior. + void VisitOperatorExpressions(LogicalOperator &op); - //! LIMIT % - unique_ptr limit; - //! OFFSET - unique_ptr offset; + // The VisitExpressionChildren method is called at the end of every call to VisitExpression to recursively visit all + // expressions in an expression tree. It can be overloaded to prevent automatically visiting the entire tree. + virtual void VisitExpressionChildren(Expression &expression); -public: - bool Equals(const ResultModifier *other) const override; - unique_ptr Copy() const override; - void Serialize(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader); + virtual unique_ptr VisitReplace(BoundAggregateExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundBetweenExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundCaseExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundCastExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundColumnRefExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundComparisonExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundConjunctionExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundConstantExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundDefaultExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundFunctionExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundOperatorExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundReferenceExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundSubqueryExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundParameterExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundWindowExpression &expr, unique_ptr *expr_ptr); + virtual unique_ptr VisitReplace(BoundUnnestExpression &expr, unique_ptr *expr_ptr); }; - } // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/planner/bound_statement.hpp +// duckdb/storage/statistics/distinct_statistics.hpp // // //===----------------------------------------------------------------------===// + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/planner/logical_operator.hpp +// duckdb/common/types/hyperloglog.hpp // // //===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/catalog/catalog.hpp -// -// -//===----------------------------------------------------------------------===// + +// LICENSE_CHANGE_BEGIN +// The following code up to LICENSE_CHANGE_END is subject to THIRD PARTY LICENSE #1 +// See the end of this file for a list + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/catalog/catalog_entry.hpp +// third_party/hyperloglog/hyperloglog.hpp // // //===----------------------------------------------------------------------===// +#include +#include -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/enums/catalog_type.hpp -// -// -//===----------------------------------------------------------------------===// +namespace duckdb_hll { + +/* Error codes */ +#define HLL_C_OK 0 +#define HLL_C_ERR -1 + +typedef struct { + void *ptr; +} robj; + +//! Create a new empty HyperLogLog object +robj *hll_create(void); +//! Convert hll from sparse to dense +int hllSparseToDense(robj *o); +//! Destroy the specified HyperLogLog object +void hll_destroy(robj *obj); +//! Add an element with the specified amount of bytes to the HyperLogLog. Returns C_ERR on failure, otherwise returns 0 +//! if the cardinality did not change, and 1 otherwise. +int hll_add(robj *o, unsigned char *ele, size_t elesize); +//! Returns the estimated amount of unique elements seen by the HyperLogLog. Returns C_OK on success, or C_ERR on +//! failure. +int hll_count(robj *o, size_t *result); +//! Merge hll_count HyperLogLog objects into a single one. Returns NULL on failure, or the new HLL object on success. +robj *hll_merge(robj **hlls, size_t hll_count); +//! Get size (in bytes) of the HLL +uint64_t get_size(); + +uint64_t MurmurHash64A(const void *key, int len, unsigned int seed); + +} // namespace duckdb_hll + +namespace duckdb { + +void AddToLogsInternal(UnifiedVectorFormat &vdata, idx_t count, uint64_t indices[], uint8_t counts[], void ***logs[], + const SelectionVector *log_sel); +void AddToSingleLogInternal(UnifiedVectorFormat &vdata, idx_t count, uint64_t indices[], uint8_t counts[], void *log); + +} // namespace duckdb +// LICENSE_CHANGE_END namespace duckdb { -//===--------------------------------------------------------------------===// -// Catalog Types -//===--------------------------------------------------------------------===// -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, - TYPE_ENTRY = 8, +enum class HLLStorageType { UNCOMPRESSED = 1 }; - // functions - TABLE_FUNCTION_ENTRY = 25, - SCALAR_FUNCTION_ENTRY = 26, - AGGREGATE_FUNCTION_ENTRY = 27, - PRAGMA_FUNCTION_ENTRY = 28, - COPY_FUNCTION_ENTRY = 29, - MACRO_ENTRY = 30, - TABLE_MACRO_ENTRY = 31, +class FieldWriter; +class FieldReader; - // version info - UPDATED_ENTRY = 50, - DELETED_ENTRY = 51, +//! The HyperLogLog class holds a HyperLogLog counter for approximate cardinality counting +class HyperLogLog { +public: + HyperLogLog(); + ~HyperLogLog(); + // implicit copying of HyperLogLog is not allowed + HyperLogLog(const HyperLogLog &) = delete; + + //! Adds an element of the specified size to the HyperLogLog counter + void Add(data_ptr_t element, idx_t size); + //! Return the count of this HyperLogLog counter + idx_t Count() const; + //! Merge this HyperLogLog counter with another counter to create a new one + unique_ptr Merge(HyperLogLog &other); + HyperLogLog *MergePointer(HyperLogLog &other); + //! Merge a set of HyperLogLogs to create one big one + static unique_ptr Merge(HyperLogLog logs[], idx_t count); + //! Get the size (in bytes) of a HLL + static idx_t GetSize(); + //! Get pointer to the HLL + data_ptr_t GetPtr() const; + //! Get copy of the HLL + unique_ptr Copy(); + //! (De)Serialize the HLL + void Serialize(FieldWriter &writer) const; + static unique_ptr Deserialize(FieldReader &reader); + +public: + //! Compute HLL hashes over vdata, and store them in 'hashes' + //! Then, compute register indices and prefix lengths, and also store them in 'hashes' as a pair of uint32_t + static void ProcessEntries(UnifiedVectorFormat &vdata, const LogicalType &type, uint64_t hashes[], uint8_t counts[], + idx_t count); + //! Add the indices and counts to the logs + static void AddToLogs(UnifiedVectorFormat &vdata, idx_t count, uint64_t indices[], uint8_t counts[], + HyperLogLog **logs[], const SelectionVector *log_sel); + //! Add the indices and counts to THIS log + void AddToLog(UnifiedVectorFormat &vdata, idx_t count, uint64_t indices[], uint8_t counts[]); + +private: + explicit HyperLogLog(void *hll); + + void *hll; + mutex lock; }; +} // namespace duckdb + + + +namespace duckdb { +class Serializer; +class Deserializer; +class Vector; + +class DistinctStatistics : public BaseStatistics { +public: + DistinctStatistics(); + explicit DistinctStatistics(unique_ptr log, idx_t sample_count, idx_t total_count); + + //! The HLL of the table + unique_ptr log; + //! How many values have been sampled into the HLL + atomic sample_count; + //! How many values have been inserted (before sampling) + atomic total_count; + +public: + void Merge(const BaseStatistics &other) override; + + unique_ptr Copy() const override; -string CatalogTypeToString(CatalogType type); + void Serialize(Serializer &serializer) const override; + void Serialize(FieldWriter &writer) const override; + + static unique_ptr Deserialize(Deserializer &source); + static unique_ptr Deserialize(FieldReader &reader); + + void Update(Vector &update, idx_t count, bool sample = true); + void Update(UnifiedVectorFormat &update_data, const LogicalType &ptype, idx_t count, bool sample = true); + + string ToString() const override; + idx_t GetCount() const; + +private: + //! For distinct statistics we sample the input to speed up insertions + static constexpr const double SAMPLE_RATE = 0.1; +}; } // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/table_filter.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/atomic.hpp +// duckdb/common/enums/filter_propagate_result.hpp // // //===----------------------------------------------------------------------===// -#include + namespace duckdb { -using std::atomic; -} +enum class FilterPropagateResult : uint8_t { + NO_PRUNING_POSSIBLE = 0, + FILTER_ALWAYS_TRUE = 1, + FILTER_ALWAYS_FALSE = 2, + FILTER_TRUE_OR_NULL = 3, + FILTER_FALSE_OR_NULL = 4 +}; + +} // namespace duckdb -#include namespace duckdb { -struct AlterInfo; -class Catalog; -class CatalogSet; -class ClientContext; +class BaseStatistics; +class FieldWriter; +class FieldReader; -//! Abstract base class of an entry in the catalog -class CatalogEntry { +enum class TableFilterType : uint8_t { + CONSTANT_COMPARISON = 0, // constant comparison (e.g. =C, >C, >=C, timestamp; - //! Child entry - unique_ptr child; - //! Parent entry (the node that dependents_map this node) - CatalogEntry *parent; + TableFilterType filter_type; public: - virtual unique_ptr AlterEntry(ClientContext &context, AlterInfo *info); + //! Returns true if the statistics indicate that the segment can contain values that satisfy that filter + virtual FilterPropagateResult CheckStatistics(BaseStatistics &stats) = 0; + virtual string ToString(const string &column_name) = 0; + virtual bool Equals(const TableFilter &other) const { + return filter_type != other.filter_type; + } - virtual unique_ptr Copy(ClientContext &context); + void Serialize(Serializer &serializer) const; + virtual void Serialize(FieldWriter &writer) const = 0; + static unique_ptr Deserialize(Deserializer &source); +}; - //! Sets the CatalogEntry as the new root entry (i.e. the newest entry) - // this is called on a rollback to an AlterEntry - virtual void SetAsRoot(); +class TableFilterSet { +public: + unordered_map> filters; - //! Convert the catalog entry to a SQL string that can be used to re-construct the catalog entry - virtual string ToSQL(); +public: + void PushFilter(idx_t table_index, unique_ptr filter); + + bool Equals(TableFilterSet &other) { + if (filters.size() != other.filters.size()) { + return false; + } + for (auto &entry : filters) { + auto other_entry = other.filters.find(entry.first); + if (other_entry == other.filters.end()) { + return false; + } + if (!entry.second->Equals(*other_entry->second)) { + return false; + } + } + return true; + } + static bool Equals(TableFilterSet *left, TableFilterSet *right) { + if (left == right) { + return true; + } + if (!left || !right) { + return false; + } + return left->Equals(*right); + } + + void Serialize(Serializer &serializer) const; + static unique_ptr Deserialize(Deserializer &source); }; + } // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/mutex.hpp +// duckdb/catalog/catalog_entry/table_catalog_entry.hpp // // //===----------------------------------------------------------------------===// -#include - -namespace duckdb { -using std::lock_guard; -using std::mutex; -using std::unique_lock; -} // namespace duckdb - //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/parser/query_error_context.hpp +// duckdb/catalog/standard_entry.hpp // // //===----------------------------------------------------------------------===// @@ -8296,265 +9306,150 @@ using std::unique_lock; - - namespace duckdb { -class SQLStatement; +class SchemaCatalogEntry; -class QueryErrorContext { +//! A StandardEntry is a catalog entry that is a member of a schema +class StandardEntry : public CatalogEntry { public: - explicit QueryErrorContext(SQLStatement *statement_ = nullptr, idx_t query_location_ = DConstants::INVALID_INDEX) - : statement(statement_), query_location(query_location_) { + StandardEntry(CatalogType type, SchemaCatalogEntry *schema, Catalog *catalog, string name) + : CatalogEntry(type, catalog, name), schema(schema) { } - - //! The query statement - SQLStatement *statement; - //! The location in which the error should be thrown - idx_t query_location; - -public: - static string Format(const string &query, const string &error_message, int error_location); - - string FormatErrorRecursive(const string &msg, vector &values); - template - string FormatErrorRecursive(const string &msg, vector &values, T param, Args... params) { - values.push_back(ExceptionFormatValue::CreateFormatValue(param)); - return FormatErrorRecursive(msg, values, params...); + ~StandardEntry() override { } - template - string FormatError(const string &msg, Args... params) { - vector values; - return FormatErrorRecursive(msg, values, params...); - } + //! The schema the entry belongs to + SchemaCatalogEntry *schema; }; - } // namespace duckdb -#include + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/constraint.hpp +// +// +//===----------------------------------------------------------------------===// + + -namespace duckdb { -struct CreateSchemaInfo; -struct DropInfo; -struct BoundCreateTableInfo; -struct AlterTableInfo; -struct CreateTableFunctionInfo; -struct CreateCopyFunctionInfo; -struct CreatePragmaFunctionInfo; -struct CreateFunctionInfo; -struct CreateViewInfo; -struct CreateSequenceInfo; -struct CreateCollationInfo; -struct CreateTypeInfo; -struct CreateTableInfo; -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; +namespace duckdb { -//! Return value of Catalog::LookupEntry -struct CatalogEntryLookup { - SchemaCatalogEntry *schema; - CatalogEntry *entry; +class Serializer; +class Deserializer; +class FieldWriter; +class FieldReader; - DUCKDB_API bool Found() const { - return entry; - } +//===--------------------------------------------------------------------===// +// Constraint Types +//===--------------------------------------------------------------------===// +enum class ConstraintType : uint8_t { + INVALID = 0, // invalid constraint type + NOT_NULL = 1, // NOT NULL constraint + CHECK = 2, // CHECK constraint + UNIQUE = 3, // UNIQUE constraint + FOREIGN_KEY = 4, // FOREIGN KEY constraint }; -//! Return value of SimilarEntryInSchemas -struct SimilarCatalogEntry { - //! The entry name. Empty if absent - string name; - //! The distance to the given name. - idx_t distance; - //! The schema of the entry. - SchemaCatalogEntry *schema; - - DUCKDB_API bool Found() const { - return !name.empty(); - } +enum class ForeignKeyType : uint8_t { + FK_TYPE_PRIMARY_KEY_TABLE = 0, // main table + FK_TYPE_FOREIGN_KEY_TABLE = 1, // referencing table + FK_TYPE_SELF_REFERENCE_TABLE = 2 // self refrencing table +}; - DUCKDB_API string GetQualifiedName() const; +struct ForeignKeyInfo { + ForeignKeyType type; + string schema; + //! if type is FK_TYPE_FOREIGN_KEY_TABLE, means main key table, if type is FK_TYPE_PRIMARY_KEY_TABLE, means foreign + //! key table + string table; + //! The set of main key table's column's index + vector pk_keys; + //! The set of foreign key table's column's index + vector fk_keys; }; -//! The Catalog object represents the catalog of the database. -class Catalog { +//! Constraint is the base class of any type of table constraint. +class Constraint { public: - explicit Catalog(DatabaseInstance &db); - ~Catalog(); + DUCKDB_API explicit Constraint(ConstraintType type); + DUCKDB_API virtual ~Constraint(); - //! Reference to the database - DatabaseInstance &db; - //! The catalog set holding the schemas - unique_ptr schemas; - //! The DependencyManager manages dependencies between different catalog objects - unique_ptr dependency_manager; - //! Write lock for the catalog - mutex write_lock; + ConstraintType type; public: - //! Get the Catalog from the ClientContext - DUCKDB_API static Catalog &GetCatalog(ClientContext &context); - //! Get the Catalog from the DatabaseInstance - DUCKDB_API static Catalog &GetCatalog(DatabaseInstance &db); - - DUCKDB_API DependencyManager &GetDependencyManager() { - return *dependency_manager; - } - - //! Returns the current version of the catalog (incremented whenever anything changes, not stored between restarts) - DUCKDB_API idx_t GetCatalogVersion(); - //! Trigger a modification in the catalog, increasing the catalog version and returning the previous version - DUCKDB_API idx_t ModifyCatalog(); - - //! Creates a schema in the catalog. - DUCKDB_API CatalogEntry *CreateSchema(ClientContext &context, CreateSchemaInfo *info); - //! Creates a table in the catalog. - DUCKDB_API CatalogEntry *CreateTable(ClientContext &context, BoundCreateTableInfo *info); - //! Creates a table in the catalog. - DUCKDB_API CatalogEntry *CreateTable(ClientContext &context, unique_ptr info); - //! Create a table function in the catalog - DUCKDB_API CatalogEntry *CreateTableFunction(ClientContext &context, CreateTableFunctionInfo *info); - //! Create a copy function in the catalog - DUCKDB_API CatalogEntry *CreateCopyFunction(ClientContext &context, CreateCopyFunctionInfo *info); - //! Create a pragma function in the catalog - DUCKDB_API CatalogEntry *CreatePragmaFunction(ClientContext &context, CreatePragmaFunctionInfo *info); - //! Create a scalar or aggregate function in the catalog - DUCKDB_API CatalogEntry *CreateFunction(ClientContext &context, CreateFunctionInfo *info); - //! Creates a table in the catalog. - DUCKDB_API CatalogEntry *CreateView(ClientContext &context, CreateViewInfo *info); - //! Creates a sequence in the catalog. - DUCKDB_API CatalogEntry *CreateSequence(ClientContext &context, CreateSequenceInfo *info); - //! Creates a Enum in the catalog. - DUCKDB_API CatalogEntry *CreateType(ClientContext &context, CreateTypeInfo *info); - //! Creates a collation in the catalog - DUCKDB_API CatalogEntry *CreateCollation(ClientContext &context, CreateCollationInfo *info); - - //! Creates a table in the catalog. - DUCKDB_API CatalogEntry *CreateTable(ClientContext &context, SchemaCatalogEntry *schema, - BoundCreateTableInfo *info); - //! Create a table function in the catalog - DUCKDB_API CatalogEntry *CreateTableFunction(ClientContext &context, SchemaCatalogEntry *schema, - CreateTableFunctionInfo *info); - //! Create a copy function in the catalog - DUCKDB_API CatalogEntry *CreateCopyFunction(ClientContext &context, SchemaCatalogEntry *schema, - CreateCopyFunctionInfo *info); - //! Create a pragma function in the catalog - DUCKDB_API CatalogEntry *CreatePragmaFunction(ClientContext &context, SchemaCatalogEntry *schema, - CreatePragmaFunctionInfo *info); - //! Create a scalar or aggregate function in the catalog - DUCKDB_API CatalogEntry *CreateFunction(ClientContext &context, SchemaCatalogEntry *schema, - CreateFunctionInfo *info); - //! Creates a table in the catalog. - DUCKDB_API CatalogEntry *CreateView(ClientContext &context, SchemaCatalogEntry *schema, CreateViewInfo *info); - //! Creates a table in the catalog. - DUCKDB_API CatalogEntry *CreateSequence(ClientContext &context, SchemaCatalogEntry *schema, - CreateSequenceInfo *info); - //! Creates a enum in the catalog. - DUCKDB_API CatalogEntry *CreateType(ClientContext &context, SchemaCatalogEntry *schema, CreateTypeInfo *info); - //! Creates a collation in the catalog - DUCKDB_API CatalogEntry *CreateCollation(ClientContext &context, SchemaCatalogEntry *schema, - CreateCollationInfo *info); + DUCKDB_API virtual string ToString() const = 0; + DUCKDB_API void Print() const; - //! Drops an entry from the catalog - DUCKDB_API void DropEntry(ClientContext &context, DropInfo *info); + DUCKDB_API virtual unique_ptr Copy() const = 0; + //! Serializes a Constraint to a stand-alone binary blob + DUCKDB_API void Serialize(Serializer &serializer) const; + //! Serializes a Constraint to a stand-alone binary blob + DUCKDB_API virtual void Serialize(FieldWriter &writer) const = 0; + //! Deserializes a blob back into a Constraint + DUCKDB_API static unique_ptr Deserialize(Deserializer &source); +}; +} // namespace duckdb - //! Returns the schema object with the specified name, or throws an exception if it does not exist - DUCKDB_API SchemaCatalogEntry *GetSchema(ClientContext &context, const string &name = DEFAULT_SCHEMA, - bool if_exists = false, - QueryErrorContext error_context = QueryErrorContext()); - //! Scans all the schemas in the system one-by-one, invoking the callback for each entry - DUCKDB_API void ScanSchemas(ClientContext &context, std::function callback); - //! Gets the "schema.name" entry of the specified type, if if_exists=true returns nullptr if entry does not exist, - //! otherwise an exception is thrown - DUCKDB_API CatalogEntry *GetEntry(ClientContext &context, CatalogType type, const string &schema, - const string &name, bool if_exists = false, - QueryErrorContext error_context = QueryErrorContext()); +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/bound_constraint.hpp +// +// +//===----------------------------------------------------------------------===// - //! Gets the "schema.name" entry without a specified type, if entry does not exist an exception is thrown - DUCKDB_API CatalogEntry *GetEntry(ClientContext &context, const string &schema, const string &name); - //! Fetches a logical type from the catalog - DUCKDB_API LogicalType GetType(ClientContext &context, const string &schema, const string &name); - template - T *GetEntry(ClientContext &context, const string &schema_name, const string &name, bool if_exists = false, - QueryErrorContext error_context = QueryErrorContext()); - //! Append a scalar or aggregate function to the catalog - DUCKDB_API CatalogEntry *AddFunction(ClientContext &context, CreateFunctionInfo *info); - //! Append a scalar or aggregate function to the catalog - DUCKDB_API CatalogEntry *AddFunction(ClientContext &context, SchemaCatalogEntry *schema, CreateFunctionInfo *info); - //! Alter an existing entry in the catalog. - DUCKDB_API void Alter(ClientContext &context, AlterInfo *info); -private: - //! The catalog version, incremented whenever anything changes in the catalog - atomic catalog_version; -private: - //! A variation of GetEntry that returns an associated schema as well. - CatalogEntryLookup LookupEntry(ClientContext &context, CatalogType type, const string &schema, const string &name, - bool if_exists = false, QueryErrorContext error_context = QueryErrorContext()); +namespace duckdb { +//! Bound equivalent of Constraint +class BoundConstraint { +public: + explicit BoundConstraint(ConstraintType type) : type(type) {}; + virtual ~BoundConstraint() { + } - //! Return an exception with did-you-mean suggestion. - CatalogException CreateMissingEntryException(ClientContext &context, const string &entry_name, CatalogType type, - const vector &schemas, - QueryErrorContext error_context); + void Serialize(Serializer &serializer) const { + serializer.Write(type); + } - //! Return the close entry name, the distance and the belonging schema. - SimilarCatalogEntry SimilarEntryInSchemas(ClientContext &context, const string &entry_name, CatalogType type, - const vector &schemas); + static unique_ptr Deserialize(Deserializer &source) { + return make_unique(source.Read()); + } - void DropSchema(ClientContext &context, DropInfo *info); + ConstraintType type; }; +} // namespace duckdb -template <> -DUCKDB_API TableCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, const string &name, - bool if_exists, QueryErrorContext error_context); -template <> -DUCKDB_API SequenceCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, - const string &name, bool if_exists, QueryErrorContext error_context); -template <> -DUCKDB_API TableFunctionCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, - const string &name, bool if_exists, - QueryErrorContext error_context); -template <> -DUCKDB_API CopyFunctionCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, - const string &name, bool if_exists, - QueryErrorContext error_context); -template <> -DUCKDB_API PragmaFunctionCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, - const string &name, bool if_exists, - QueryErrorContext error_context); -template <> -DUCKDB_API AggregateFunctionCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, - const string &name, bool if_exists, - QueryErrorContext error_context); -template <> -DUCKDB_API CollateCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, const string &name, - bool if_exists, QueryErrorContext error_context); -template <> -DUCKDB_API TypeCatalogEntry *Catalog::GetEntry(ClientContext &context, const string &schema_name, const string &name, - bool if_exists, QueryErrorContext error_context); +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/expression.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/plan_serialization.hpp +// +// +//===----------------------------------------------------------------------===// -} // namespace duckdb //===----------------------------------------------------------------------===// @@ -8662,10 +9557,11 @@ DUCKDB_API string LogicalOperatorToString(LogicalOperatorType type); } // namespace duckdb + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/planner/expression.hpp +// duckdb/planner/bound_parameter_map.hpp // // //===----------------------------------------------------------------------===// @@ -8675,8 +9571,52 @@ DUCKDB_API string LogicalOperatorToString(LogicalOperatorType type); +namespace duckdb { + +struct BoundParameterData; + +using bound_parameter_map_t = unordered_map>; + +} // namespace duckdb + + +namespace duckdb { +class ClientContext; +class LogicalOperator; +struct BoundParameterData; + +struct PlanDeserializationState { + PlanDeserializationState(ClientContext &context); + ~PlanDeserializationState(); + + ClientContext &context; + bound_parameter_map_t parameter_data; +}; + +struct LogicalDeserializationState { + LogicalDeserializationState(PlanDeserializationState &gstate, LogicalOperatorType type, + vector> &children); + + PlanDeserializationState &gstate; + LogicalOperatorType type; + vector> &children; +}; + +struct ExpressionDeserializationState { + ExpressionDeserializationState(PlanDeserializationState &gstate, ExpressionType type); + + PlanDeserializationState &gstate; + ExpressionType type; +}; + +} // namespace duckdb + + namespace duckdb { class BaseStatistics; +class FieldWriter; +class FieldReader; +class ClientContext; //! The Expression class represents a bound Expression with a return type class Expression : public BaseExpression { @@ -8701,39 +9641,241 @@ class Expression : public BaseExpression { 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; - } + 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); + } + //! Create a copy of this expression + virtual unique_ptr Copy() = 0; + + //! Serializes an Expression to a stand-alone binary blob + void Serialize(Serializer &serializer) const; + //! Serializes an Expression to a stand-alone binary blob + virtual void Serialize(FieldWriter &writer) const = 0; + + //! Deserializes a blob back into an Expression [CAN THROW: + //! SerializationException] + static unique_ptr Deserialize(Deserializer &source, PlanDeserializationState &state); + +protected: + //! Copy base Expression properties from another expression to this one, + //! used in Copy method + void CopyProperties(Expression &other) { + type = other.type; + expression_class = other.expression_class; + alias = other.alias; + return_type = other.return_type; + } +}; + +} // namespace duckdb + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/catalog/catalog_entry/column_dependency_manager.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/set.hpp +// +// +//===----------------------------------------------------------------------===// + + + +#include + +namespace duckdb { +using std::set; +} + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/stack.hpp +// +// +//===----------------------------------------------------------------------===// + + + +#include + +namespace duckdb { +using std::stack; +} + + +namespace duckdb { + +//! Dependency Manager local to a table, responsible for keeping track of generated column dependencies + +class ColumnDependencyManager { +public: + DUCKDB_API ColumnDependencyManager(); + DUCKDB_API ~ColumnDependencyManager(); + DUCKDB_API ColumnDependencyManager(ColumnDependencyManager &&other) = default; + ColumnDependencyManager(const ColumnDependencyManager &other) = delete; + +public: + //! Get the bind order that ensures dependencies are resolved before dependents are + stack GetBindOrder(const vector &columns); + + //! Adds a connection between the dependent and its dependencies + void AddGeneratedColumn(column_t index, const vector &indices, bool root = true); + //! Add a generated column from a column definition + void AddGeneratedColumn(const ColumnDefinition &column, const case_insensitive_map_t &name_map); + + //! Removes the column(s) and outputs the new column indices + vector RemoveColumn(column_t index, column_t column_amount); + + bool IsDependencyOf(column_t dependent, column_t dependency) const; + bool HasDependencies(column_t index) const; + const unordered_set &GetDependencies(column_t index) const; + + bool HasDependents(column_t index) const; + const unordered_set &GetDependents(column_t index) const; + +private: + void RemoveStandardColumn(column_t index); + void RemoveGeneratedColumn(column_t index); + + void AdjustSingle(column_t idx, idx_t offset); + // Clean up the gaps created by a Remove operation + vector CleanupInternals(column_t column_amount); + +private: + //! A map of column dependency to generated column(s) + unordered_map> dependencies_map; + //! A map of generated column name to (potentially generated)column dependencies + unordered_map> dependents_map; + //! For resolve-order purposes, keep track of the 'direct' (not inherited) dependencies of a generated column + unordered_map> direct_dependencies; + set deleted_columns; +}; + +} // namespace duckdb + + +namespace duckdb { + +class DataTable; +struct CreateTableInfo; +struct BoundCreateTableInfo; + +struct RenameColumnInfo; +struct AddColumnInfo; +struct RemoveColumnInfo; +struct SetDefaultInfo; +struct ChangeColumnTypeInfo; +struct AlterForeignKeyInfo; +struct SetNotNullInfo; +struct DropNotNullInfo; + +//! A table catalog entry +class TableCatalogEntry : public StandardEntry { +public: + //! Create a real TableCatalogEntry and initialize storage for it + TableCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, BoundCreateTableInfo *info, + std::shared_ptr inherited_storage = nullptr); + + //! A reference to the underlying storage unit used for this table + std::shared_ptr storage; + //! A list of columns that are part of this table + vector columns; + //! A list of constraints that are part of this table + vector> constraints; + //! A list of constraints that are part of this table + vector> bound_constraints; + ColumnDependencyManager column_dependency_manager; + //! A map of column name to column index + case_insensitive_map_t name_map; + +public: + //! For debugging purposes, count how many columns are STANDARD + idx_t StandardColumnCount() const; + unique_ptr AlterEntry(ClientContext &context, AlterInfo *info) override; + //! Returns whether or not a column with the given name exists + DUCKDB_API bool ColumnExists(const string &name); + //! Returns a reference to the column of the specified name. Throws an + //! exception if the column does not exist. + ColumnDefinition &GetColumn(const string &name); + //! Returns a list of types of the table + vector GetTypes(); + string ToSQL() override; + + //! Serialize the meta information of the TableCatalogEntry a serializer + virtual void Serialize(Serializer &serializer); + //! Deserializes to a CreateTableInfo + static unique_ptr Deserialize(Deserializer &source, ClientContext &context); + + unique_ptr Copy(ClientContext &context) override; + + void SetAsRoot() override; + + void CommitAlter(AlterInfo &info); + void CommitDrop(); + + //! Returns the column index of the specified column name. + //! If the column does not exist: + //! If if_column_exists is true, returns DConstants::INVALID_INDEX + //! If if_column_exists is false, throws an exception + column_t GetColumnIndex(string &name, bool if_exists = false); + +private: + const string &GetColumnName(column_t index); + unique_ptr RenameColumn(ClientContext &context, RenameColumnInfo &info); + unique_ptr AddColumn(ClientContext &context, AddColumnInfo &info); + unique_ptr RemoveColumn(ClientContext &context, RemoveColumnInfo &info); + unique_ptr SetDefault(ClientContext &context, SetDefaultInfo &info); + unique_ptr ChangeColumnType(ClientContext &context, ChangeColumnTypeInfo &info); + unique_ptr SetNotNull(ClientContext &context, SetNotNullInfo &info); + unique_ptr DropNotNull(ClientContext &context, DropNotNullInfo &info); + unique_ptr AddForeignKeyConstraint(ClientContext &context, AlterForeignKeyInfo &info); + unique_ptr DropForeignKeyConstraint(ClientContext &context, AlterForeignKeyInfo &info); +}; +} // namespace duckdb + + +namespace duckdb { + +class EstimatedProperties { +public: + EstimatedProperties(double cardinality, double cost) : cardinality(cardinality), cost(cost) {}; + EstimatedProperties() : cardinality(0), cost(0) {}; + + double GetCardinality(); + double GetCost(); + void SetCost(double new_cost); + void SetCardinality(double cardinality); - static bool Equals(Expression *left, Expression *right) { - return BaseExpression::Equals((BaseExpression *)left, (BaseExpression *)right); - } - //! Create a copy of this expression - virtual unique_ptr Copy() = 0; +private: + double cardinality; + double cost; -protected: - //! Copy base Expression properties from another expression to this one, - //! used in Copy method - void CopyProperties(Expression &other) { - type = other.type; - expression_class = other.expression_class; - alias = other.alias; - return_type = other.return_type; - } +public: + unique_ptr Copy(); }; - } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/logical_operator_visitor.hpp -// -// -//===----------------------------------------------------------------------===// @@ -8741,169 +9883,201 @@ class Expression : public BaseExpression { //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/planner/bound_tokens.hpp +// duckdb/planner/column_binding.hpp // // //===----------------------------------------------------------------------===// -namespace duckdb { -//===--------------------------------------------------------------------===// -// Query Node -//===--------------------------------------------------------------------===// -class BoundQueryNode; -class BoundSelectNode; -class BoundSetOperationNode; -class BoundRecursiveCTENode; +#include -//===--------------------------------------------------------------------===// -// Expressions -//===--------------------------------------------------------------------===// -class Expression; +namespace duckdb { -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; +struct ColumnBinding { + idx_t table_index; + idx_t column_index; -//===--------------------------------------------------------------------===// -// TableRefs -//===--------------------------------------------------------------------===// -class BoundTableRef; + ColumnBinding() : table_index(DConstants::INVALID_INDEX), column_index(DConstants::INVALID_INDEX) { + } + ColumnBinding(idx_t table, idx_t column) : table_index(table), column_index(column) { + } -class BoundBaseTableRef; -class BoundCrossProductRef; -class BoundJoinRef; -class BoundSubqueryRef; -class BoundTableFunction; -class BoundEmptyTableRef; -class BoundExpressionListRef; -class BoundCTERef; + bool operator==(const ColumnBinding &rhs) const { + return table_index == rhs.table_index && column_index == rhs.column_index; + } +}; } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/logical_tokens.hpp -// -// -//===----------------------------------------------------------------------===// +#include +#include namespace duckdb { -class LogicalOperator; +class FieldWriter; +class FieldReader; -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; +//! The current version of the plan serialization format. Exposed via by @Serializer & @Deserializer +//! to be used by various Operator to know what format to read and write. +extern const uint64_t PLAN_SERIALIZATION_VERSION; + +//! LogicalOperator is the base class of the logical operators present in the +//! logical query tree +class LogicalOperator { +public: + explicit LogicalOperator(LogicalOperatorType type); + LogicalOperator(LogicalOperatorType type, vector> expressions); + virtual ~LogicalOperator(); + + //! The type of the logical operator + LogicalOperatorType type; + //! The set of children of the operator + vector> children; + //! The set of expressions contained within the operator, if any + vector> expressions; + //! The types returned by this logical operator. Set by calling LogicalOperator::ResolveTypes. + vector types; + //! Estimated Cardinality + idx_t estimated_cardinality; + bool has_estimated_cardinality; + + unique_ptr estimated_props; + +public: + virtual vector GetColumnBindings(); + static vector GenerateColumnBindings(idx_t table_idx, idx_t column_count); + static vector MapTypes(const vector &types, const vector &projection_map); + static vector MapBindings(const vector &types, const vector &projection_map); + + //! Resolve the types of the logical operator and its children + void ResolveOperatorTypes(); + + virtual string GetName() const; + virtual string ParamsToString() const; + virtual string ToString() const; + DUCKDB_API void Print(); + //! Debug method: verify that the integrity of expressions & child nodes are maintained + virtual void Verify(ClientContext &context); + + void AddChild(unique_ptr child); + virtual idx_t EstimateCardinality(ClientContext &context); + + //! Serializes a LogicalOperator to a stand-alone binary blob + void Serialize(Serializer &serializer) const; + //! Serializes an LogicalOperator to a stand-alone binary blob + virtual void Serialize(FieldWriter &writer) const = 0; + + static unique_ptr Deserialize(Deserializer &deserializer, PlanDeserializationState &state); + + virtual bool RequireOptimizer() const { + return true; + } + +protected: + //! Resolve types for this specific operator + virtual void ResolveTypes() = 0; +}; +} // namespace duckdb + + +namespace duckdb { + +struct BoundStatement { + unique_ptr plan; + vector types; + vector names; +}; } // namespace duckdb -#include + namespace duckdb { -//! The LogicalOperatorVisitor is an abstract base class that implements the -//! Visitor pattern on LogicalOperator. -class LogicalOperatorVisitor { + +//! A ResultModifier +class BoundResultModifier { public: - virtual ~LogicalOperatorVisitor() {}; + explicit BoundResultModifier(ResultModifierType type); + virtual ~BoundResultModifier(); - virtual void VisitOperator(LogicalOperator &op); - virtual void VisitExpression(unique_ptr *expression); + ResultModifierType type; +}; - static void EnumerateExpressions(LogicalOperator &op, - const std::function *child)> &callback); +struct BoundOrderByNode { +public: + BoundOrderByNode(OrderType type, OrderByNullType null_order, unique_ptr expression); + BoundOrderByNode(OrderType type, OrderByNullType null_order, unique_ptr expression, + unique_ptr stats); -protected: - //! Automatically calls the Visit method for LogicalOperator children of the current operator. Can be overloaded to - //! change this behavior. - void VisitOperatorChildren(LogicalOperator &op); - //! Automatically calls the Visit method for Expression children of the current operator. Can be overloaded to - //! change this behavior. - void VisitOperatorExpressions(LogicalOperator &op); + OrderType type; + OrderByNullType null_order; + unique_ptr expression; + unique_ptr stats; + +public: + BoundOrderByNode Copy() const; + string ToString() const; + + void Serialize(Serializer &serializer) const; + static BoundOrderByNode Deserialize(Deserializer &source, PlanDeserializationState &state); +}; + +class BoundLimitModifier : public BoundResultModifier { +public: + BoundLimitModifier(); + + //! LIMIT + int64_t limit_val = NumericLimits::Maximum(); + //! OFFSET + int64_t offset_val = 0; + //! Expression in case limit is not constant + unique_ptr limit; + //! Expression in case limit is not constant + unique_ptr offset; +}; + +class BoundOrderModifier : public BoundResultModifier { +public: + BoundOrderModifier(); + + //! List of order nodes + vector orders; +}; + +class BoundDistinctModifier : public BoundResultModifier { +public: + BoundDistinctModifier(); - // The VisitExpressionChildren method is called at the end of every call to VisitExpression to recursively visit all - // expressions in an expression tree. It can be overloaded to prevent automatically visiting the entire tree. - virtual void VisitExpressionChildren(Expression &expression); + //! list of distinct on targets (if any) + vector> target_distincts; +}; - virtual unique_ptr VisitReplace(BoundAggregateExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundBetweenExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundCaseExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundCastExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundColumnRefExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundComparisonExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundConjunctionExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundConstantExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundDefaultExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundFunctionExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundOperatorExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundReferenceExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundSubqueryExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundParameterExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundWindowExpression &expr, unique_ptr *expr_ptr); - virtual unique_ptr VisitReplace(BoundUnnestExpression &expr, unique_ptr *expr_ptr); +class BoundLimitPercentModifier : public BoundResultModifier { +public: + BoundLimitPercentModifier(); + + //! LIMIT % + double limit_percent = 100.0; + //! OFFSET + int64_t offset_val = 0; + //! Expression in case limit is not constant + unique_ptr limit; + //! Expression in case limit is not constant + unique_ptr offset; }; + } // namespace duckdb + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/planner/column_binding.hpp +// duckdb/common/vector_operations/aggregate_executor.hpp // // //===----------------------------------------------------------------------===// @@ -8911,196 +10085,384 @@ class LogicalOperatorVisitor { -#include + + namespace duckdb { -struct ColumnBinding { - idx_t table_index; - idx_t column_index; +struct AggregateInputData; - ColumnBinding() : table_index(DConstants::INVALID_INDEX), column_index(DConstants::INVALID_INDEX) { - } - ColumnBinding(idx_t table, idx_t column) : table_index(table), column_index(column) { - } +typedef std::pair FrameBounds; - bool operator==(const ColumnBinding &rhs) const { - return table_index == rhs.table_index && column_index == rhs.column_index; +class AggregateExecutor { +private: + template + static inline void NullaryFlatLoop(STATE_TYPE **__restrict states, AggregateInputData &aggr_input_data, + idx_t count) { + for (idx_t i = 0; i < count; i++) { + OP::template Operation(states[i], aggr_input_data, i); + } } -}; -} // namespace duckdb + template + static inline void NullaryScatterLoop(STATE_TYPE **__restrict states, AggregateInputData &aggr_input_data, + const SelectionVector &ssel, idx_t count) { + for (idx_t i = 0; i < count; i++) { + auto sidx = ssel.get_index(i); + OP::template Operation(states[sidx], aggr_input_data, sidx); + } + } -#include -#include + template + static inline void UnaryFlatLoop(INPUT_TYPE *__restrict idata, AggregateInputData &aggr_input_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(base_idx + ValidityMask::BITS_PER_VALUE, count); + if (!OP::IgnoreNull() || ValidityMask::AllValid(validity_entry)) { + // all valid: perform operation + for (; base_idx < next; base_idx++) { + OP::template Operation(states[base_idx], aggr_input_data, idata, + mask, base_idx); + } + } else if (ValidityMask::NoneValid(validity_entry)) { + // nothing valid: skip all + base_idx = next; + continue; + } else { + // partially valid: need to check individual elements for validity + idx_t start = base_idx; + for (; base_idx < next; base_idx++) { + if (ValidityMask::RowIsValid(validity_entry, base_idx - start)) { + OP::template Operation(states[base_idx], aggr_input_data, idata, + mask, base_idx); + } + } + } + } + } else { + for (idx_t i = 0; i < count; i++) { + OP::template Operation(states[i], aggr_input_data, idata, mask, i); + } + } + } -namespace duckdb { + template + static inline void UnaryScatterLoop(INPUT_TYPE *__restrict idata, AggregateInputData &aggr_input_data, + STATE_TYPE **__restrict states, const SelectionVector &isel, + const SelectionVector &ssel, ValidityMask &mask, idx_t count) { + if (OP::IgnoreNull() && !mask.AllValid()) { + // potential NULL values and NULL values are ignored + 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(states[sidx], aggr_input_data, idata, mask, idx); + } + } + } else { + // quick path: no NULL values or NULL values are not ignored + for (idx_t i = 0; i < count; i++) { + auto idx = isel.get_index(i); + auto sidx = ssel.get_index(i); + OP::template Operation(states[sidx], aggr_input_data, idata, mask, idx); + } + } + } -//! LogicalOperator is the base class of the logical operators present in the -//! logical query tree -class LogicalOperator { -public: - explicit LogicalOperator(LogicalOperatorType type) : type(type) { + template + static inline void UnaryFlatUpdateLoop(INPUT_TYPE *__restrict idata, AggregateInputData &aggr_input_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(base_idx + ValidityMask::BITS_PER_VALUE, count); + if (!OP::IgnoreNull() || ValidityMask::AllValid(validity_entry)) { + // all valid: perform operation + for (; base_idx < next; base_idx++) { + OP::template Operation(state, aggr_input_data, idata, mask, base_idx); + } + } else if (ValidityMask::NoneValid(validity_entry)) { + // nothing valid: skip all + base_idx = next; + continue; + } else { + // partially valid: need to check individual elements for validity + idx_t start = base_idx; + for (; base_idx < next; base_idx++) { + if (ValidityMask::RowIsValid(validity_entry, base_idx - start)) { + OP::template Operation(state, aggr_input_data, idata, mask, + base_idx); + } + } + } + } } - LogicalOperator(LogicalOperatorType type, vector> expressions) - : type(type), expressions(move(expressions)) { + + template + static inline void UnaryUpdateLoop(INPUT_TYPE *__restrict idata, AggregateInputData &aggr_input_data, + STATE_TYPE *__restrict state, idx_t count, ValidityMask &mask, + const SelectionVector &__restrict sel_vector) { + if (OP::IgnoreNull() && !mask.AllValid()) { + // potential NULL values and NULL values are ignored + for (idx_t i = 0; i < count; i++) { + auto idx = sel_vector.get_index(i); + if (mask.RowIsValid(idx)) { + OP::template Operation(state, aggr_input_data, idata, mask, idx); + } + } + } else { + // quick path: no NULL values or NULL values are not ignored + for (idx_t i = 0; i < count; i++) { + auto idx = sel_vector.get_index(i); + OP::template Operation(state, aggr_input_data, idata, mask, idx); + } + } } - virtual ~LogicalOperator() { + + template + static inline void BinaryScatterLoop(A_TYPE *__restrict adata, AggregateInputData &aggr_input_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())) { + // potential NULL values and NULL values are ignored + 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(states[sidx], aggr_input_data, adata, bdata, + avalidity, bvalidity, aidx, bidx); + } + } + } else { + // quick path: no NULL values or NULL values are not ignored + 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(states[sidx], aggr_input_data, adata, bdata, + avalidity, bvalidity, aidx, bidx); + } + } } - //! The type of the logical operator - LogicalOperatorType type; - //! The set of children of the operator - vector> children; - //! The set of expressions contained within the operator, if any - vector> expressions; - //! The types returned by this logical operator. Set by calling LogicalOperator::ResolveTypes. - vector types; - //! Estimated Cardinality - idx_t estimated_cardinality = 0; + template + static inline void BinaryUpdateLoop(A_TYPE *__restrict adata, AggregateInputData &aggr_input_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())) { + // potential NULL values and NULL values are ignored + 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(state, aggr_input_data, adata, bdata, + avalidity, bvalidity, aidx, bidx); + } + } + } else { + // quick path: no NULL values or NULL values are not ignored + for (idx_t i = 0; i < count; i++) { + auto aidx = asel.get_index(i); + auto bidx = bsel.get_index(i); + OP::template Operation(state, aggr_input_data, adata, bdata, avalidity, + bvalidity, aidx, bidx); + } + } + } public: - virtual vector GetColumnBindings() { - return {ColumnBinding(0, 0)}; + template + static void NullaryScatter(Vector &states, AggregateInputData &aggr_input_data, idx_t count) { + if (states.GetVectorType() == VectorType::CONSTANT_VECTOR) { + auto sdata = ConstantVector::GetData(states); + OP::template ConstantOperation(*sdata, aggr_input_data, count); + } else if (states.GetVectorType() == VectorType::FLAT_VECTOR) { + auto sdata = FlatVector::GetData(states); + NullaryFlatLoop(sdata, aggr_input_data, count); + } else { + UnifiedVectorFormat sdata; + states.ToUnifiedFormat(count, sdata); + NullaryScatterLoop((STATE_TYPE **)sdata.data, aggr_input_data, *sdata.sel, count); + } } - static vector GenerateColumnBindings(idx_t table_idx, idx_t column_count); - static vector MapTypes(const vector &types, const vector &projection_map); - static vector MapBindings(const vector &types, const vector &projection_map); - - //! Resolve the types of the logical operator and its children - void ResolveOperatorTypes(); - virtual string GetName() const; - virtual string ParamsToString() const; - virtual string ToString() const; - DUCKDB_API void Print(); - //! Debug method: verify that the integrity of expressions & child nodes are maintained - virtual void Verify(); + template + static void NullaryUpdate(data_ptr_t state, AggregateInputData &aggr_input_data, idx_t count) { + OP::template ConstantOperation((STATE_TYPE *)state, aggr_input_data, count); + } - void AddChild(unique_ptr child) { - children.push_back(move(child)); + template + static void UnaryScatter(Vector &input, Vector &states, AggregateInputData &aggr_input_data, idx_t count) { + if (input.GetVectorType() == VectorType::CONSTANT_VECTOR && + states.GetVectorType() == VectorType::CONSTANT_VECTOR) { + if (OP::IgnoreNull() && ConstantVector::IsNull(input)) { + // constant NULL input in function that ignores NULL values + return; + } + // regular constant: get first state + auto idata = ConstantVector::GetData(input); + auto sdata = ConstantVector::GetData(states); + OP::template ConstantOperation(*sdata, aggr_input_data, idata, + ConstantVector::Validity(input), count); + } else if (input.GetVectorType() == VectorType::FLAT_VECTOR && + states.GetVectorType() == VectorType::FLAT_VECTOR) { + auto idata = FlatVector::GetData(input); + auto sdata = FlatVector::GetData(states); + UnaryFlatLoop(idata, aggr_input_data, sdata, FlatVector::Validity(input), + count); + } else { + UnifiedVectorFormat idata, sdata; + input.ToUnifiedFormat(count, idata); + states.ToUnifiedFormat(count, sdata); + UnaryScatterLoop((INPUT_TYPE *)idata.data, aggr_input_data, + (STATE_TYPE **)sdata.data, *idata.sel, *sdata.sel, + idata.validity, count); + } } - virtual idx_t EstimateCardinality(ClientContext &context) { - // simple estimator, just take the max of the children - idx_t max_cardinality = 0; - for (auto &child : children) { - max_cardinality = MaxValue(child->EstimateCardinality(context), max_cardinality); + template + static void UnaryUpdate(Vector &input, AggregateInputData &aggr_input_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); + OP::template ConstantOperation((STATE_TYPE *)state, aggr_input_data, idata, + ConstantVector::Validity(input), count); + break; + } + case VectorType::FLAT_VECTOR: { + auto idata = FlatVector::GetData(input); + UnaryFlatUpdateLoop(idata, aggr_input_data, (STATE_TYPE *)state, count, + FlatVector::Validity(input)); + break; + } + default: { + UnifiedVectorFormat idata; + input.ToUnifiedFormat(count, idata); + UnaryUpdateLoop((INPUT_TYPE *)idata.data, aggr_input_data, (STATE_TYPE *)state, + count, idata.validity, *idata.sel); + break; + } } - return max_cardinality; } -protected: - //! Resolve types for this specific operator - virtual void ResolveTypes() = 0; -}; -} // namespace duckdb - - -namespace duckdb { - -struct BoundStatement { - unique_ptr plan; - vector types; - vector names; -}; - -} // namespace duckdb - - - - -namespace duckdb { + template + static void BinaryScatter(AggregateInputData &aggr_input_data, Vector &a, Vector &b, Vector &states, idx_t count) { + UnifiedVectorFormat adata, bdata, sdata; -//! A ResultModifier -class BoundResultModifier { -public: - explicit BoundResultModifier(ResultModifierType type); - virtual ~BoundResultModifier(); + a.ToUnifiedFormat(count, adata); + b.ToUnifiedFormat(count, bdata); + states.ToUnifiedFormat(count, sdata); - ResultModifierType type; -}; + BinaryScatterLoop((A_TYPE *)adata.data, aggr_input_data, (B_TYPE *)bdata.data, + (STATE_TYPE **)sdata.data, count, *adata.sel, *bdata.sel, + *sdata.sel, adata.validity, bdata.validity); + } -struct BoundOrderByNode { -public: - BoundOrderByNode(OrderType type, OrderByNullType null_order, unique_ptr expression); - BoundOrderByNode(OrderType type, OrderByNullType null_order, unique_ptr expression, - unique_ptr stats); + template + static void BinaryUpdate(AggregateInputData &aggr_input_data, Vector &a, Vector &b, data_ptr_t state, idx_t count) { + UnifiedVectorFormat adata, bdata; - OrderType type; - OrderByNullType null_order; - unique_ptr expression; - unique_ptr stats; + a.ToUnifiedFormat(count, adata); + b.ToUnifiedFormat(count, bdata); -public: - BoundOrderByNode Copy() const; - string ToString() const; -}; + BinaryUpdateLoop((A_TYPE *)adata.data, aggr_input_data, (B_TYPE *)bdata.data, + (STATE_TYPE *)state, count, *adata.sel, *bdata.sel, + adata.validity, bdata.validity); + } -class BoundLimitModifier : public BoundResultModifier { -public: - BoundLimitModifier(); + template + static void Combine(Vector &source, Vector &target, AggregateInputData &aggr_input_data, idx_t count) { + D_ASSERT(source.GetType().id() == LogicalTypeId::POINTER && target.GetType().id() == LogicalTypeId::POINTER); + auto sdata = FlatVector::GetData(source); + auto tdata = FlatVector::GetData(target); - //! LIMIT - int64_t limit_val = NumericLimits::Maximum(); - //! OFFSET - int64_t offset_val = 0; - //! Expression in case limit is not constant - unique_ptr limit; - //! Expression in case limit is not constant - unique_ptr offset; -}; + for (idx_t i = 0; i < count; i++) { + OP::template Combine(*sdata[i], tdata[i], aggr_input_data); + } + } -class BoundOrderModifier : public BoundResultModifier { -public: - BoundOrderModifier(); + template + static void Finalize(Vector &states, AggregateInputData &aggr_input_data, Vector &result, idx_t count, + idx_t offset) { + if (states.GetVectorType() == VectorType::CONSTANT_VECTOR) { + result.SetVectorType(VectorType::CONSTANT_VECTOR); - //! List of order nodes - vector orders; -}; + auto sdata = ConstantVector::GetData(states); + auto rdata = ConstantVector::GetData(result); + OP::template Finalize(result, aggr_input_data, *sdata, rdata, + ConstantVector::Validity(result), 0); + } else { + D_ASSERT(states.GetVectorType() == VectorType::FLAT_VECTOR); + result.SetVectorType(VectorType::FLAT_VECTOR); -class BoundDistinctModifier : public BoundResultModifier { -public: - BoundDistinctModifier(); + auto sdata = FlatVector::GetData(states); + auto rdata = FlatVector::GetData(result); + for (idx_t i = 0; i < count; i++) { + OP::template Finalize(result, aggr_input_data, sdata[i], rdata, + FlatVector::Validity(result), i + offset); + } + } + } - //! list of distinct on targets (if any) - vector> target_distincts; -}; + template + static void UnaryWindow(Vector &input, const ValidityMask &ifilter, AggregateInputData &aggr_input_data, + data_ptr_t state, const FrameBounds &frame, const FrameBounds &prev, Vector &result, + idx_t rid, idx_t bias) { -class BoundLimitPercentModifier : public BoundResultModifier { -public: - BoundLimitPercentModifier(); + auto idata = FlatVector::GetData(input) - bias; + const auto &ivalid = FlatVector::Validity(input); + OP::template Window(idata, ifilter, ivalid, aggr_input_data, (STATE *)state, + frame, prev, result, rid, bias); + } - //! LIMIT % - double limit_percent = 100.0; - //! OFFSET - int64_t offset_val = 0; - //! Expression in case limit is not constant - unique_ptr limit; - //! Expression in case limit is not constant - unique_ptr offset; + template + static void Destroy(Vector &states, idx_t count) { + auto sdata = FlatVector::GetData(states); + for (idx_t i = 0; i < count; i++) { + OP::template Destroy(sdata[i]); + } + } }; } // namespace duckdb - namespace duckdb { class BoundAggregateExpression; +struct AggregateInputData { + AggregateInputData(FunctionData *bind_data_p, Allocator &allocator_p) + : bind_data(bind_data_p), allocator(allocator_p) {}; + FunctionData *bind_data; + Allocator &allocator; +}; + //! The type used for sizing hashed aggregate function states typedef idx_t (*aggregate_size_t)(); //! The type used for initializing hashed aggregate function states typedef void (*aggregate_initialize_t)(data_ptr_t state); //! The type used for updating hashed aggregate functions -typedef void (*aggregate_update_t)(Vector inputs[], FunctionData *bind_data, idx_t input_count, Vector &state, - idx_t count); +typedef void (*aggregate_update_t)(Vector inputs[], AggregateInputData &aggr_input_data, idx_t input_count, + Vector &state, idx_t count); //! The type used for combining hashed aggregate states -typedef void (*aggregate_combine_t)(Vector &state, Vector &combined, FunctionData *bind_data, idx_t count); +typedef void (*aggregate_combine_t)(Vector &state, Vector &combined, AggregateInputData &aggr_input_data, idx_t count); //! The type used for finalizing hashed aggregate function payloads -typedef void (*aggregate_finalize_t)(Vector &state, FunctionData *bind_data, Vector &result, idx_t count, idx_t offset); +typedef void (*aggregate_finalize_t)(Vector &state, AggregateInputData &aggr_input_data, Vector &result, idx_t count, + idx_t offset); //! The type used for propagating statistics in aggregate functions (optional) typedef unique_ptr (*aggregate_statistics_t)(ClientContext &context, BoundAggregateExpression &expr, FunctionData *bind_data, @@ -9113,60 +10475,78 @@ typedef unique_ptr (*bind_aggregate_function_t)(ClientContext &con typedef void (*aggregate_destructor_t)(Vector &state, idx_t count); //! The type used for updating simple (non-grouped) aggregate functions -typedef void (*aggregate_simple_update_t)(Vector inputs[], FunctionData *bind_data, idx_t input_count, data_ptr_t state, - idx_t count); +typedef void (*aggregate_simple_update_t)(Vector inputs[], AggregateInputData &aggr_input_data, idx_t input_count, + data_ptr_t state, idx_t count); //! The type used for updating complex windowed aggregate functions (optional) typedef std::pair FrameBounds; -typedef void (*aggregate_window_t)(Vector inputs[], const ValidityMask &filter_mask, FunctionData *bind_data, - idx_t input_count, data_ptr_t state, const FrameBounds &frame, - const FrameBounds &prev, Vector &result, idx_t rid, idx_t bias); +typedef void (*aggregate_window_t)(Vector inputs[], const ValidityMask &filter_mask, + AggregateInputData &aggr_input_data, idx_t input_count, data_ptr_t state, + const FrameBounds &frame, const FrameBounds &prev, Vector &result, idx_t rid, + idx_t bias); + +typedef void (*aggregate_serialize_t)(FieldWriter &writer, const FunctionData *bind_data, + const AggregateFunction &function); +typedef unique_ptr (*aggregate_deserialize_t)(ClientContext &context, FieldReader &reader, + AggregateFunction &function); class AggregateFunction : public BaseScalarFunction { public: - DUCKDB_API AggregateFunction(const string &name, const vector &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, - bool propagates_null_values = false, 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) - : BaseScalarFunction(name, arguments, return_type, false, LogicalType(LogicalTypeId::INVALID), - propagates_null_values), + DUCKDB_API + AggregateFunction(const string &name, const vector &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, + FunctionNullHandling null_handling = FunctionNullHandling::DEFAULT_NULL_HANDLING, + 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, aggregate_serialize_t serialize = nullptr, + aggregate_deserialize_t deserialize = nullptr) + : BaseScalarFunction(name, arguments, return_type, FunctionSideEffects::NO_SIDE_EFFECTS, + LogicalType(LogicalTypeId::INVALID), null_handling), state_size(state_size), initialize(initialize), update(update), combine(combine), finalize(finalize), - simple_update(simple_update), window(window), bind(bind), destructor(destructor), statistics(statistics) { + simple_update(simple_update), window(window), bind(bind), destructor(destructor), statistics(statistics), + serialize(serialize), deserialize(deserialize) { } - DUCKDB_API AggregateFunction(const string &name, const vector &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) - : BaseScalarFunction(name, arguments, return_type, false, LogicalType(LogicalTypeId::INVALID), false), + DUCKDB_API + AggregateFunction(const string &name, const vector &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, aggregate_serialize_t serialize = nullptr, + aggregate_deserialize_t deserialize = nullptr) + : BaseScalarFunction(name, arguments, return_type, FunctionSideEffects::NO_SIDE_EFFECTS, + LogicalType(LogicalTypeId::INVALID)), state_size(state_size), initialize(initialize), update(update), combine(combine), finalize(finalize), - simple_update(simple_update), window(window), bind(bind), destructor(destructor), statistics(statistics) { + simple_update(simple_update), window(window), bind(bind), destructor(destructor), statistics(statistics), + serialize(serialize), deserialize(deserialize) { } DUCKDB_API AggregateFunction(const vector &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, - bool propagates_null_values = false, aggregate_simple_update_t simple_update = nullptr, + FunctionNullHandling null_handling = FunctionNullHandling::DEFAULT_NULL_HANDLING, + 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) + aggregate_statistics_t statistics = nullptr, aggregate_window_t window = nullptr, + aggregate_serialize_t serialize = nullptr, + aggregate_deserialize_t deserialize = nullptr) : AggregateFunction(string(), arguments, return_type, state_size, initialize, update, combine, finalize, - propagates_null_values, simple_update, bind, destructor, statistics, window) { + null_handling, simple_update, bind, destructor, statistics, window, serialize, + deserialize) { } - DUCKDB_API AggregateFunction(const vector &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) - : AggregateFunction(string(), arguments, return_type, state_size, initialize, update, combine, finalize, false, - simple_update, bind, destructor, statistics, window) { + DUCKDB_API + AggregateFunction(const vector &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, + aggregate_serialize_t serialize = nullptr, aggregate_deserialize_t deserialize = nullptr) + : AggregateFunction(string(), arguments, return_type, state_size, initialize, update, combine, finalize, + FunctionNullHandling::DEFAULT_NULL_HANDLING, simple_update, bind, destructor, statistics, + window, serialize, deserialize) { } //! The hashed aggregate state sizing function aggregate_size_t state_size; @@ -9191,6 +10571,9 @@ class AggregateFunction : public BaseScalarFunction { //! The statistics propagation function (may be null) aggregate_statistics_t statistics; + aggregate_serialize_t serialize; + aggregate_deserialize_t deserialize; + DUCKDB_API 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; @@ -9202,8 +10585,7 @@ class AggregateFunction : public BaseScalarFunction { DUCKDB_API static unique_ptr BindAggregateFunction(ClientContext &context, AggregateFunction bound_function, vector> children, unique_ptr filter = nullptr, - bool is_distinct = false, unique_ptr order_bys = nullptr, - bool cast_parameters = true); + bool is_distinct = false, unique_ptr order_bys = nullptr); DUCKDB_API static unique_ptr BindSortedAggregate(AggregateFunction &bound_function, vector> &children, @@ -9220,13 +10602,14 @@ class AggregateFunction : public BaseScalarFunction { } template - static AggregateFunction UnaryAggregate(const LogicalType &input_type, LogicalType return_type, - bool propagates_null_values = false) { + static AggregateFunction + UnaryAggregate(const LogicalType &input_type, LogicalType return_type, + FunctionNullHandling null_handling = FunctionNullHandling::DEFAULT_NULL_HANDLING) { return AggregateFunction( {input_type}, return_type, AggregateFunction::StateSize, AggregateFunction::StateInitialize, AggregateFunction::UnaryScatterUpdate, AggregateFunction::StateCombine, AggregateFunction::StateFinalize, - propagates_null_values, AggregateFunction::UnaryUpdate); + null_handling, AggregateFunction::UnaryUpdate); } template @@ -9259,64 +10642,66 @@ class AggregateFunction : public BaseScalarFunction { } template - static void NullaryScatterUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, Vector &states, - idx_t count) { + static void NullaryScatterUpdate(Vector inputs[], AggregateInputData &aggr_input_data, idx_t input_count, + Vector &states, idx_t count) { D_ASSERT(input_count == 0); - AggregateExecutor::NullaryScatter(states, bind_data, count); + AggregateExecutor::NullaryScatter(states, aggr_input_data, count); } template - static void NullaryUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, data_ptr_t state, + static void NullaryUpdate(Vector inputs[], AggregateInputData &aggr_input_data, idx_t input_count, data_ptr_t state, idx_t count) { D_ASSERT(input_count == 0); - AggregateExecutor::NullaryUpdate(state, bind_data, count); + AggregateExecutor::NullaryUpdate(state, aggr_input_data, count); } template - static void UnaryScatterUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, Vector &states, - idx_t count) { + static void UnaryScatterUpdate(Vector inputs[], AggregateInputData &aggr_input_data, idx_t input_count, + Vector &states, idx_t count) { D_ASSERT(input_count == 1); - AggregateExecutor::UnaryScatter(inputs[0], states, bind_data, count); + AggregateExecutor::UnaryScatter(inputs[0], states, aggr_input_data, count); } template - static void UnaryUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, data_ptr_t state, + static void UnaryUpdate(Vector inputs[], AggregateInputData &aggr_input_data, idx_t input_count, data_ptr_t state, idx_t count) { D_ASSERT(input_count == 1); - AggregateExecutor::UnaryUpdate(inputs[0], bind_data, state, count); + AggregateExecutor::UnaryUpdate(inputs[0], aggr_input_data, state, count); } template - static void UnaryWindow(Vector inputs[], const ValidityMask &filter_mask, FunctionData *bind_data, + static void UnaryWindow(Vector inputs[], const ValidityMask &filter_mask, AggregateInputData &aggr_input_data, idx_t input_count, data_ptr_t state, const FrameBounds &frame, const FrameBounds &prev, Vector &result, idx_t rid, idx_t bias) { D_ASSERT(input_count == 1); - AggregateExecutor::UnaryWindow(inputs[0], filter_mask, bind_data, state, - frame, prev, result, rid, bias); + AggregateExecutor::UnaryWindow(inputs[0], filter_mask, aggr_input_data, + state, frame, prev, result, rid, bias); } template - static void BinaryScatterUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, Vector &states, - idx_t count) { + static void BinaryScatterUpdate(Vector inputs[], AggregateInputData &aggr_input_data, idx_t input_count, + Vector &states, idx_t count) { D_ASSERT(input_count == 2); - AggregateExecutor::BinaryScatter(bind_data, inputs[0], inputs[1], states, count); + AggregateExecutor::BinaryScatter(aggr_input_data, inputs[0], inputs[1], states, + count); } template - static void BinaryUpdate(Vector inputs[], FunctionData *bind_data, idx_t input_count, data_ptr_t state, + static void BinaryUpdate(Vector inputs[], AggregateInputData &aggr_input_data, idx_t input_count, data_ptr_t state, idx_t count) { D_ASSERT(input_count == 2); - AggregateExecutor::BinaryUpdate(bind_data, inputs[0], inputs[1], state, count); + AggregateExecutor::BinaryUpdate(aggr_input_data, inputs[0], inputs[1], state, count); } template - static void StateCombine(Vector &source, Vector &target, FunctionData *bind_data, idx_t count) { - AggregateExecutor::Combine(source, target, bind_data, count); + static void StateCombine(Vector &source, Vector &target, AggregateInputData &aggr_input_data, idx_t count) { + AggregateExecutor::Combine(source, target, aggr_input_data, count); } template - static void StateFinalize(Vector &states, FunctionData *bind_data, Vector &result, idx_t count, idx_t offset) { - AggregateExecutor::Finalize(states, bind_data, result, count, offset); + static void StateFinalize(Vector &states, AggregateInputData &aggr_input_data, Vector &result, idx_t count, + idx_t offset) { + AggregateExecutor::Finalize(states, aggr_input_data, result, count, offset); } template @@ -9440,6 +10825,7 @@ struct UDFWrapper { AggregateFunction aggr_function(move(name), move(arguments), move(return_type), state_size, initialize, update, combine, finalize, simple_update, bind, destructor); + aggr_function.null_handling = FunctionNullHandling::SPECIAL_HANDLING; return aggr_function; } @@ -9658,181 +11044,416 @@ struct UDFWrapper { return CreateUnaryAggregateFunction(name, return_type, input_type); } - template - static AggregateFunction CreateUnaryAggregateFunction(const string &name, LogicalType ret_type, - LogicalType input_type) { - AggregateFunction aggr_function = - AggregateFunction::UnaryAggregate(input_type, ret_type); - aggr_function.name = name; - return aggr_function; - } + template + static AggregateFunction CreateUnaryAggregateFunction(const string &name, LogicalType ret_type, + LogicalType input_type) { + AggregateFunction aggr_function = + AggregateFunction::UnaryAggregate(input_type, ret_type); + aggr_function.name = name; + return aggr_function; + } + + template + static AggregateFunction CreateBinaryAggregateFunction(const string &name) { + LogicalType return_type = GetArgumentType(); + LogicalType input_typeA = GetArgumentType(); + LogicalType input_typeB = GetArgumentType(); + return CreateBinaryAggregateFunction(name, return_type, input_typeA, input_typeB); + } + + template + static AggregateFunction CreateBinaryAggregateFunction(const string &name, LogicalType ret_type, + LogicalType input_typeA, LogicalType input_typeB) { + AggregateFunction aggr_function = + AggregateFunction::BinaryAggregate(input_typeA, input_typeB, ret_type); + aggr_function.name = name; + return aggr_function; + } +}; // end UDFWrapper + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/main/materialized_query_result.hpp +// +// +//===----------------------------------------------------------------------===// + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/types/column_data_collection.hpp +// +// +//===----------------------------------------------------------------------===// + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/types/column_data_collection_iterators.hpp +// +// +//===----------------------------------------------------------------------===// + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/types/column_data_scan_states.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + +namespace duckdb { + +enum class ColumnDataAllocatorType : uint8_t { + //! Use a buffer manager to allocate large chunks of memory that vectors then use + BUFFER_MANAGER_ALLOCATOR, + //! Use an in-memory allocator, allocating data for every chunk + //! This causes the column data collection to behave similar to the old chunk collection + IN_MEMORY_ALLOCATOR +}; + +enum class ColumnDataScanProperties : uint8_t { + INVALID, + //! Allow zero copy scans - this introduces a dependency on the resulting vector on the scan state of the column + //! data collection, which means vectors might not be valid anymore after the next chunk is scanned. + ALLOW_ZERO_COPY, + //! Disallow zero-copy scans, always copying data into the target vector + //! As a result, data scanned will be valid even after the column data collection is destroyed + DISALLOW_ZERO_COPY +}; + +struct ChunkManagementState { + unordered_map handles; + ColumnDataScanProperties properties = ColumnDataScanProperties::INVALID; +}; + +struct ColumnDataAppendState { + ChunkManagementState current_chunk_state; + vector vector_data; +}; + +struct ColumnDataScanState { + ChunkManagementState current_chunk_state; + idx_t segment_index; + idx_t chunk_index; + idx_t current_row_index; + idx_t next_row_index; + ColumnDataScanProperties properties; + vector column_ids; +}; + +struct ColumnDataParallelScanState { + ColumnDataScanState scan_state; + mutex lock; +}; + +struct ColumnDataLocalScanState { + ChunkManagementState current_chunk_state; + idx_t current_segment_index = DConstants::INVALID_INDEX; + idx_t current_row_index; +}; + +class ColumnDataRow { +public: + ColumnDataRow(DataChunk &chunk, idx_t row_index, idx_t base_index); + + DataChunk &chunk; + idx_t row_index; + idx_t base_index; + +public: + Value GetValue(idx_t column_index) const; + idx_t RowIndex() const; +}; + +} // namespace duckdb + + +namespace duckdb { +class ColumnDataCollection; + +class ColumnDataChunkIterationHelper { +public: + DUCKDB_API ColumnDataChunkIterationHelper(const ColumnDataCollection &collection, vector column_ids); + +private: + const ColumnDataCollection &collection; + vector column_ids; + +private: + class ColumnDataChunkIterator; + + class ColumnDataChunkIterator { + public: + DUCKDB_API explicit ColumnDataChunkIterator(const ColumnDataCollection *collection_p, + vector column_ids); - template - static AggregateFunction CreateBinaryAggregateFunction(const string &name) { - LogicalType return_type = GetArgumentType(); - LogicalType input_typeA = GetArgumentType(); - LogicalType input_typeB = GetArgumentType(); - return CreateBinaryAggregateFunction(name, return_type, input_typeA, input_typeB); - } + const ColumnDataCollection *collection; + ColumnDataScanState scan_state; + shared_ptr scan_chunk; + idx_t row_index; - template - static AggregateFunction CreateBinaryAggregateFunction(const string &name, LogicalType ret_type, - LogicalType input_typeA, LogicalType input_typeB) { - AggregateFunction aggr_function = - AggregateFunction::BinaryAggregate(input_typeA, input_typeB, ret_type); - aggr_function.name = name; - return aggr_function; - } -}; // end UDFWrapper + public: + DUCKDB_API void Next(); -} // namespace duckdb + DUCKDB_API ColumnDataChunkIterator &operator++(); + DUCKDB_API bool operator!=(const ColumnDataChunkIterator &other) const; + DUCKDB_API DataChunk &operator*() const; + }; -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/main/materialized_query_result.hpp -// -// -//===----------------------------------------------------------------------===// +public: + DUCKDB_API ColumnDataChunkIterator begin() { + return ColumnDataChunkIterator(&collection, column_ids); + } + DUCKDB_API ColumnDataChunkIterator end() { + return ColumnDataChunkIterator(nullptr, vector()); + } +}; +class ColumnDataRowIterationHelper { +public: + DUCKDB_API ColumnDataRowIterationHelper(const ColumnDataCollection &collection); +private: + const ColumnDataCollection &collection; -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/types/chunk_collection.hpp -// -// -//===----------------------------------------------------------------------===// +private: + class ColumnDataRowIterator; + + class ColumnDataRowIterator { + public: + DUCKDB_API explicit ColumnDataRowIterator(const ColumnDataCollection *collection_p); + const ColumnDataCollection *collection; + ColumnDataScanState scan_state; + shared_ptr scan_chunk; + ColumnDataRow current_row; + public: + void Next(); + DUCKDB_API ColumnDataRowIterator &operator++(); + DUCKDB_API bool operator!=(const ColumnDataRowIterator &other) const; + DUCKDB_API const ColumnDataRow &operator*() const; + }; +public: + DUCKDB_API ColumnDataRowIterator begin(); + DUCKDB_API ColumnDataRowIterator end(); +}; +} // namespace duckdb namespace duckdb { +class BufferManager; +class BlockHandle; +class ClientContext; +struct ColumnDataCopyFunction; +class ColumnDataAllocator; +class ColumnDataCollection; +class ColumnDataCollectionSegment; +class ColumnDataRowCollection; + +//! The ColumnDataCollection represents a set of (buffer-managed) data stored in columnar format +//! It is efficient to read and scan +class ColumnDataCollection { +public: + //! Constructs an in-memory column data collection from an allocator + DUCKDB_API ColumnDataCollection(Allocator &allocator, vector types); + //! Constructs an empty (but valid) in-memory column data collection from an allocator + DUCKDB_API ColumnDataCollection(Allocator &allocator); + //! Constructs a buffer-managed column data collection + DUCKDB_API ColumnDataCollection(BufferManager &buffer_manager, vector types); + //! Constructs either an in-memory or a buffer-managed column data collection + DUCKDB_API ColumnDataCollection(ClientContext &context, vector types, + ColumnDataAllocatorType type = ColumnDataAllocatorType::BUFFER_MANAGER_ALLOCATOR); + //! Creates a column data collection that inherits the blocks to write to. This allows blocks to be shared + //! between multiple column data collections and prevents wasting space. + //! Note that after one CDC inherits blocks from another, the other + //! cannot be written to anymore (i.e. we take ownership of the half-written blocks). + DUCKDB_API ColumnDataCollection(ColumnDataCollection &parent); + DUCKDB_API ColumnDataCollection(shared_ptr allocator, vector types); + DUCKDB_API ~ColumnDataCollection(); -//! A ChunkCollection represents a set of DataChunks that all have the same -//! types -/*! - A ChunkCollection represents a set of DataChunks concatenated together in a - list. Individual values of the collection can be iterated over using the - iterator. It is also possible to iterate directly over the chunks for more - direct access. -*/ -class ChunkCollection { public: - ChunkCollection() : count(0) { - } - - //! The amount of columns in the ChunkCollection DUCKDB_API vector &Types() { return types; } - const vector &Types() const { + DUCKDB_API const vector &Types() const { return types; } - //! The amount of rows in the ChunkCollection + //! The amount of rows in the ColumnDataCollection DUCKDB_API const idx_t &Count() const { return count; } - //! The amount of columns in the ChunkCollection + //! The amount of columns in the ColumnDataCollection DUCKDB_API idx_t ColumnCount() const { return types.size(); } - //! Append a new DataChunk directly to this ChunkCollection + //! Initializes an Append state - useful for optimizing many appends made to the same column data collection + DUCKDB_API void InitializeAppend(ColumnDataAppendState &state); + //! Append a DataChunk to this ColumnDataCollection using the specified append state + DUCKDB_API void Append(ColumnDataAppendState &state, DataChunk &new_chunk); + + //! Initializes a chunk with the correct types that can be used to call Scan + DUCKDB_API void InitializeScanChunk(DataChunk &chunk) const; + //! Initializes a chunk with the correct types for a given scan state + DUCKDB_API void InitializeScanChunk(ColumnDataScanState &state, DataChunk &chunk) const; + //! Initializes a Scan state for scanning all columns + DUCKDB_API void + InitializeScan(ColumnDataScanState &state, + ColumnDataScanProperties properties = ColumnDataScanProperties::ALLOW_ZERO_COPY) const; + //! Initializes a Scan state for scanning a subset of the columns + DUCKDB_API void + InitializeScan(ColumnDataScanState &state, vector column_ids, + ColumnDataScanProperties properties = ColumnDataScanProperties::ALLOW_ZERO_COPY) const; + //! Initialize a parallel scan over the column data collection over all columns + DUCKDB_API void + InitializeScan(ColumnDataParallelScanState &state, + ColumnDataScanProperties properties = ColumnDataScanProperties::ALLOW_ZERO_COPY) const; + //! Initialize a parallel scan over the column data collection over a subset of the columns + DUCKDB_API void + InitializeScan(ColumnDataParallelScanState &state, vector column_ids, + ColumnDataScanProperties properties = ColumnDataScanProperties::ALLOW_ZERO_COPY) const; + //! Scans a DataChunk from the ColumnDataCollection + DUCKDB_API bool Scan(ColumnDataScanState &state, DataChunk &result) const; + //! Scans a DataChunk from the ColumnDataCollection + DUCKDB_API bool Scan(ColumnDataParallelScanState &state, ColumnDataLocalScanState &lstate, DataChunk &result) const; + + //! Append a DataChunk directly to this ColumnDataCollection - calls InitializeAppend and Append internally DUCKDB_API void Append(DataChunk &new_chunk); - //! Append a new DataChunk directly to this ChunkCollection - DUCKDB_API void Append(unique_ptr new_chunk); + //! Appends the other ColumnDataCollection to this, destroying the other data collection + DUCKDB_API void Combine(ColumnDataCollection &other); - //! Append another ChunkCollection directly to this ChunkCollection - DUCKDB_API void Append(ChunkCollection &other); + DUCKDB_API void Verify(); - //! Merge is like Append but messes up the order and destroys the other collection - DUCKDB_API void Merge(ChunkCollection &other); + DUCKDB_API string ToString() const; + DUCKDB_API void Print() const; - //! Fuse adds new columns to the right of the collection - DUCKDB_API void Fuse(ChunkCollection &other); + DUCKDB_API void Reset(); - DUCKDB_API void Verify(); + //! Returns the number of data chunks present in the ColumnDataCollection + DUCKDB_API idx_t ChunkCount() const; + //! Fetch an individual chunk from the ColumnDataCollection + DUCKDB_API void FetchChunk(idx_t chunk_idx, DataChunk &result) const; + + //! Constructs a class that can be iterated over to fetch individual chunks + //! Iterating over this is syntactic sugar over just calling Scan + DUCKDB_API ColumnDataChunkIterationHelper Chunks() const; + //! Constructs a class that can be iterated over to fetch individual chunks + //! Only the column indexes specified in the column_ids list are scanned + DUCKDB_API ColumnDataChunkIterationHelper Chunks(vector column_ids) const; + + //! Constructs a class that can be iterated over to fetch individual rows + //! Note that row iteration is slow, and the `.Chunks()` method should be used instead + DUCKDB_API ColumnDataRowIterationHelper Rows() const; + + //! Returns a materialized set of all of the rows in the column data collection + //! Note that usage of this is slow - avoid using this unless the amount of rows is small, or if you do not care + //! about performance + DUCKDB_API ColumnDataRowCollection GetRows() const; + + //! Compare two column data collections to another. If they are equal according to result equality rules, + //! return true. That means null values are equal, and approx equality is used for floating point values. + //! If they are not equal, return false and fill in the error message. + static bool ResultEquals(const ColumnDataCollection &left, const ColumnDataCollection &right, + string &error_message); + + //! Obtains the next scan index to scan from + bool NextScanIndex(ColumnDataScanState &state, idx_t &chunk_index, idx_t &segment_index, idx_t &row_index) const; + //! Scans at the indices (obtained from NextScanIndex) + void ScanAtIndex(ColumnDataParallelScanState &state, ColumnDataLocalScanState &lstate, DataChunk &result, + idx_t chunk_index, idx_t segment_index, idx_t row_index) const; - //! Gets the value of the column at the specified index - DUCKDB_API Value GetValue(idx_t column, idx_t index); - //! Sets the value of the column at the specified index - DUCKDB_API void SetValue(idx_t column, idx_t index, const Value &value); +private: + //! Initialize the column data collection + void Initialize(vector types); - //! Copy a single cell to a target vector - DUCKDB_API void CopyCell(idx_t column, idx_t index, Vector &target, idx_t target_offset); + //! Creates a new segment within the ColumnDataCollection + void CreateSegment(); - DUCKDB_API string ToString() const; - DUCKDB_API void Print() const; + static ColumnDataCopyFunction GetCopyFunction(const LogicalType &type); - //! Gets a reference to the chunk at the given index - DUCKDB_API DataChunk &GetChunkForRow(idx_t row_index) { - return *chunks[LocateChunk(row_index)]; - } +private: + //! The Column Data Allocator + buffer_ptr allocator; + //! The types of the stored entries + vector types; + //! The number of entries stored in the column data collection + idx_t count; + //! The data segments of the column data collection + vector> segments; + //! The set of copy functions + vector copy_functions; + //! When the column data collection is marked as finished - new tuples can no longer be appended to it + bool finished_append; +}; - //! Gets a reference to the chunk at the given 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]; - } +//! The ColumnDataRowCollection represents a set of materialized rows, as obtained from the ColumnDataCollection +class ColumnDataRowCollection { +public: + DUCKDB_API ColumnDataRowCollection(const ColumnDataCollection &collection); - DUCKDB_API const vector> &Chunks() { - return chunks; - } +public: + DUCKDB_API Value GetValue(idx_t column, idx_t index) const; - DUCKDB_API idx_t ChunkCount() const { - return chunks.size(); +public: + // container API + DUCKDB_API bool empty() const { + return rows.empty(); } - - DUCKDB_API void Reset() { - count = 0; - chunks.clear(); - types.clear(); + DUCKDB_API idx_t size() const { + return rows.size(); } - DUCKDB_API unique_ptr Fetch() { - if (ChunkCount() == 0) { - return nullptr; - } + DUCKDB_API ColumnDataRow &operator[](idx_t i); + DUCKDB_API const ColumnDataRow &operator[](idx_t i) const; - auto res = move(chunks[0]); - chunks.erase(chunks.begin() + 0); - return res; + DUCKDB_API vector::iterator begin() { + return rows.begin(); } - - DUCKDB_API void Sort(vector &desc, vector &null_order, idx_t result[]); - //! Reorders the rows in the collection according to the given indices. - DUCKDB_API void Reorder(idx_t order[]); - - //! Returns true if the ChunkCollections are equivalent - DUCKDB_API bool Equals(ChunkCollection &other); - - //! Locates the chunk that belongs to the specific index - DUCKDB_API idx_t LocateChunk(idx_t index) { - idx_t result = index / STANDARD_VECTOR_SIZE; - D_ASSERT(result < chunks.size()); - return result; + DUCKDB_API vector::iterator end() { + return rows.end(); + } + DUCKDB_API vector::const_iterator cbegin() const { + return rows.cbegin(); + } + DUCKDB_API vector::const_iterator cend() const { + return rows.cend(); + } + DUCKDB_API vector::const_iterator begin() const { + return rows.begin(); + } + DUCKDB_API vector::const_iterator end() const { + return rows.end(); } private: - //! The total amount of elements in the collection - idx_t count; - //! The set of data chunks in the collection + vector rows; vector> chunks; - //! The types of the ChunkCollection - vector types; }; + } // namespace duckdb @@ -9887,7 +11508,10 @@ enum class StatementType : uint8_t { CALL_STATEMENT, // CALL statement type SET_STATEMENT, // SET statement type LOAD_STATEMENT, // LOAD statement type - RELATION_STATEMENT + RELATION_STATEMENT, + EXTENSION_STATEMENT, + LOGICAL_PLAN_STATEMENT + }; string StatementTypeToString(StatementType type); @@ -9927,19 +11551,23 @@ struct StatementProperties { -struct ArrowSchema; namespace duckdb { enum class QueryResultType : uint8_t { MATERIALIZED_RESULT, STREAM_RESULT, PENDING_RESULT }; +//! A set of properties from the client context that can be used to interpret the query result +struct ClientProperties { + string timezone; +}; + class BaseQueryResult { public: //! Creates a successful query result with the specified names and types DUCKDB_API BaseQueryResult(QueryResultType type, StatementType statement_type, StatementProperties properties, vector types, vector names); //! Creates an unsuccessful query result with error condition - DUCKDB_API BaseQueryResult(QueryResultType type, string error); + DUCKDB_API BaseQueryResult(QueryResultType type, PreservedError error); DUCKDB_API virtual ~BaseQueryResult(); //! The type of the result (MATERIALIZED or STREAMING) @@ -9952,15 +11580,21 @@ class BaseQueryResult { vector types; //! The names of the result vector names; - //! Whether or not execution was successful - bool success; - //! The error string (in case execution was not successful) - string error; public: - DUCKDB_API bool HasError(); - DUCKDB_API const string &GetError(); + DUCKDB_API void ThrowError(const string &prepended_message = "") const; + DUCKDB_API void SetError(PreservedError error); + DUCKDB_API bool HasError() const; + DUCKDB_API const ExceptionType &GetErrorType() const; + DUCKDB_API const std::string &GetError(); + DUCKDB_API PreservedError &GetErrorObject(); DUCKDB_API idx_t ColumnCount(); + +protected: + //! Whether or not execution was successful + bool success; + //! The error (in case execution was not successful) + PreservedError error; }; //! The QueryResult object holds the result of a query. It can either be a MaterializedQueryResult, in which case the @@ -9970,11 +11604,13 @@ class QueryResult : public BaseQueryResult { public: //! Creates a successful query result with the specified names and types DUCKDB_API QueryResult(QueryResultType type, StatementType statement_type, StatementProperties properties, - vector types, vector names); + vector types, vector names, ClientProperties client_properties); //! Creates an unsuccessful query result with error condition - DUCKDB_API QueryResult(QueryResultType type, string error); + DUCKDB_API QueryResult(QueryResultType type, PreservedError error); DUCKDB_API virtual ~QueryResult() override; + //! Properties from the client context + ClientProperties client_properties; //! The next result (if any) unique_ptr next; @@ -9993,33 +11629,29 @@ class QueryResult : public BaseQueryResult { //! Fetch() until both results are exhausted. The data in the results will be lost. DUCKDB_API bool Equals(QueryResult &other); - DUCKDB_API bool TryFetch(unique_ptr &result, string &error) { + DUCKDB_API bool TryFetch(unique_ptr &result, PreservedError &error) { try { result = Fetch(); return success; + } catch (const Exception &ex) { + error = PreservedError(ex); + return false; } catch (std::exception &ex) { - error = ex.what(); + error = PreservedError(ex); return false; } catch (...) { - error = "Unknown error in Fetch"; + error = PreservedError("Unknown error in Fetch"); return false; } } - DUCKDB_API static void ToArrowSchema(ArrowSchema *out_schema, vector &types, vector &names, - string &config_timezone); - static string GetConfigTimezone(QueryResult &query_result); -private: - //! The current chunk used by the iterator - unique_ptr iterator_chunk; - private: class QueryResultIterator; class QueryResultRow { public: - explicit QueryResultRow(QueryResultIterator &iterator) : iterator(iterator), row(0) { + explicit QueryResultRow(QueryResultIterator &iterator_p, idx_t row_idx) : iterator(iterator_p), row(0) { } QueryResultIterator &iterator; @@ -10027,32 +11659,39 @@ class QueryResult : public BaseQueryResult { template T GetValue(idx_t col_idx) const { - return iterator.result->iterator_chunk->GetValue(col_idx, iterator.row_idx).GetValue(); + return iterator.chunk->GetValue(col_idx, row).GetValue(); } }; //! The row-based query result iterator. Invoking the class QueryResultIterator { public: - explicit QueryResultIterator(QueryResult *result) : current_row(*this), result(result), row_idx(0) { + explicit QueryResultIterator(QueryResult *result) : current_row(*this, 0), result(result), base_row(0) { if (result) { - result->iterator_chunk = result->Fetch(); + chunk = shared_ptr(result->Fetch().release()); } } QueryResultRow current_row; + shared_ptr chunk; QueryResult *result; - idx_t row_idx; + idx_t base_row; public: void Next() { - if (!result->iterator_chunk) { + if (!chunk) { return; } current_row.row++; - row_idx++; - if (row_idx >= result->iterator_chunk->size()) { - result->iterator_chunk = result->Fetch(); - row_idx = 0; + if (current_row.row >= chunk->size()) { + base_row += chunk->size(); + chunk = result->Fetch(); + current_row.row = 0; + if (!chunk || chunk->size() == 0) { + // exhausted all rows + base_row = 0; + result = nullptr; + chunk.reset(); + } } } @@ -10061,7 +11700,7 @@ class QueryResult : public BaseQueryResult { return *this; } bool operator!=(const QueryResultIterator &other) const { - return result->iterator_chunk && result->iterator_chunk->ColumnCount() > 0; + return result != other.result || base_row != other.base_row || current_row.row != other.current_row.row; } const QueryResultRow &operator*() const { return current_row; @@ -10085,6 +11724,7 @@ class QueryResult : public BaseQueryResult { } // namespace duckdb + namespace duckdb { class ClientContext; @@ -10094,25 +11734,21 @@ class MaterializedQueryResult : public QueryResult { friend class ClientContext; //! Creates a successful query result with the specified names and types DUCKDB_API MaterializedQueryResult(StatementType statement_type, StatementProperties properties, - vector types, vector names, - const shared_ptr &context); + vector names, unique_ptr collection, + ClientProperties client_properties); //! Creates an unsuccessful query result with error condition - DUCKDB_API explicit MaterializedQueryResult(string error); - - ChunkCollection collection; - - //! The client context this MaterializedQueryResult belongs to - std::weak_ptr context; + DUCKDB_API explicit MaterializedQueryResult(PreservedError error); public: //! Fetches a DataChunk from the query result. - //! This will consume the result (i.e. the chunks are taken directly from the ChunkCollection). + //! This will consume the result (i.e. the result can only be scanned once with this function) DUCKDB_API unique_ptr Fetch() override; DUCKDB_API unique_ptr FetchRaw() override; //! Converts the QueryResult to a string DUCKDB_API string ToString() override; - //! Gets the (index) value of the (column index) column + //! Gets the (index) value of the (column index) column. + //! Note: this is very slow. Scanning over the underlying collection is much faster. DUCKDB_API Value GetValue(idx_t column, idx_t index); template @@ -10120,13 +11756,102 @@ class MaterializedQueryResult : public QueryResult { auto value = GetValue(column, index); return (T)value.GetValue(); } + + DUCKDB_API idx_t RowCount() const; + + //! Returns a reference to the underlying column data collection + ColumnDataCollection &Collection(); + +private: + unique_ptr collection; + //! Row collection, only created if GetValue is called + unique_ptr row_collection; + //! Scan state for Fetch calls + ColumnDataScanState scan_state; + bool scan_initialized; }; -} // namespace duckdb +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/main/pending_query_result.hpp +// +// +//===----------------------------------------------------------------------===// + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/common/enums/pending_execution_result.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +namespace duckdb { + +enum class PendingExecutionResult : uint8_t { RESULT_READY, RESULT_NOT_READY, EXECUTION_ERROR }; + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/executor.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parallel/pipeline.hpp +// +// +//===----------------------------------------------------------------------===// + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/execution/physical_operator.hpp +// +// +//===----------------------------------------------------------------------===// + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/optimizer/join_node.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/main/pending_query_result.hpp +// duckdb/optimizer/join_order/query_graph.hpp // // //===----------------------------------------------------------------------===// @@ -10137,54 +11862,136 @@ class MaterializedQueryResult : public QueryResult { //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/enums/pending_execution_result.hpp +// duckdb/common/pair.hpp // // //===----------------------------------------------------------------------===// +#include + +namespace duckdb { +using std::make_pair; +using std::pair; +} // namespace duckdb + + + + + + +#include namespace duckdb { +class Expression; +class LogicalOperator; -enum class PendingExecutionResult : uint8_t { RESULT_READY, RESULT_NOT_READY, EXECUTION_ERROR }; +struct FilterInfo { + idx_t filter_index; + JoinRelationSet *left_set = nullptr; + JoinRelationSet *right_set = nullptr; + ColumnBinding left_binding; + ColumnBinding right_binding; + JoinRelationSet *set = nullptr; +}; + +struct FilterNode { + vector filters; + unordered_map> children; +}; + +struct NeighborInfo { + JoinRelationSet *neighbor; + vector filters; +}; + +//! The QueryGraph contains edges between relations and allows edges to be created/queried +class QueryGraph { +public: + //! Contains a node with info about neighboring relations and child edge infos + struct QueryEdge { + vector> neighbors; + unordered_map> children; + }; + +public: + string ToString() const; + void Print(); + + //! Create an edge in the edge_set + void CreateEdge(JoinRelationSet *left, JoinRelationSet *right, FilterInfo *info); + //! Returns a connection if there is an edge that connects these two sets, or nullptr otherwise + vector GetConnections(JoinRelationSet *node, JoinRelationSet *other); + //! Enumerate the neighbors of a specific node that do not belong to any of the exclusion_set. Note that if a + //! neighbor has multiple nodes, this function will return the lowest entry in that set. + vector GetNeighbors(JoinRelationSet *node, unordered_set &exclusion_set); + //! Enumerate all neighbors of a given JoinRelationSet node + void EnumerateNeighbors(JoinRelationSet *node, const std::function &callback); + +private: + //! Get the QueryEdge of a specific node + QueryEdge *GetQueryEdge(JoinRelationSet *left); + + QueryEdge root; +}; } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/executor.hpp -// -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/parallel/pipeline.hpp -// -// -//===----------------------------------------------------------------------===// +namespace duckdb { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/execution/physical_operator.hpp -// -// -//===----------------------------------------------------------------------===// +class JoinOrderOptimizer; + +class JoinNode { +public: + //! Represents a node in the join plan + JoinRelationSet *set; + NeighborInfo *info; + //! If the JoinNode is a base table, then base_cardinality is the cardinality before filters + //! estimated_props.cardinality will be the cardinality after filters. With no filters, the two are equal + bool has_filter; + JoinNode *left; + JoinNode *right; + + unique_ptr estimated_props; + + //! Create a leaf node in the join tree + //! set cost to 0 for leaf nodes + //! cost will be the cost to *produce* an intermediate table + JoinNode(JoinRelationSet *set, const double base_cardinality); + + //! Create an intermediate node in the join tree. base_cardinality = estimated_props.cardinality + JoinNode(JoinRelationSet *set, NeighborInfo *info, JoinNode *left, JoinNode *right, const double base_cardinality, + double cost); + bool operator==(const JoinNode &other) { + return other.set->ToString().compare(set->ToString()) == 0; + } + +private: + double base_cardinality; +public: + double GetCardinality() const; + double GetCost(); + void SetCost(double cost); + double GetBaseTableCardinality(); + void SetBaseTableCardinality(double base_card); + void SetEstimatedCardinality(double estimated_card); + void PrintJoinNode(); + string ToString(); +}; +} // namespace duckdb //===----------------------------------------------------------------------===// @@ -10213,7 +12020,7 @@ enum class PhysicalOperatorType : uint8_t { TOP_N, WINDOW, UNNEST, - SIMPLE_AGGREGATE, + UNGROUPED_AGGREGATE, HASH_GROUP_BY, PERFECT_HASH_GROUP_BY, FILTER, @@ -10227,6 +12034,7 @@ enum class PhysicalOperatorType : uint8_t { // ----------------------------- TABLE_SCAN, DUMMY_SCAN, + COLUMN_DATA_SCAN, CHUNK_SCAN, RECURSIVE_CTE_SCAN, DELIM_SCAN, @@ -10431,7 +12239,9 @@ class PhysicalOperator { public: PhysicalOperator(PhysicalOperatorType type, vector types, idx_t estimated_cardinality) : type(type), types(std::move(types)), estimated_cardinality(estimated_cardinality) { + estimated_props = make_unique(estimated_cardinality, 0); } + virtual ~PhysicalOperator() { } @@ -10443,6 +12253,8 @@ class PhysicalOperator { vector types; //! The estimated cardinality of this physical operator idx_t estimated_cardinality; + unique_ptr estimated_props; + //! The global sink state of this operator unique_ptr sink_state; //! The global state of this operator @@ -10476,7 +12288,7 @@ class PhysicalOperator { public: // Operator interface - virtual unique_ptr GetOperatorState(ClientContext &context) const; + virtual unique_ptr GetOperatorState(ExecutionContext &context) const; virtual unique_ptr GetGlobalOperatorState(ClientContext &context) const; virtual OperatorResultType Execute(ExecutionContext &context, DataChunk &input, DataChunk &chunk, GlobalOperatorState &gstate, OperatorState &state) const; @@ -10511,6 +12323,10 @@ class PhysicalOperator { return false; } + virtual bool IsOrderPreserving() const { + return true; + } + //! Returns the current progress percentage, or a negative value if progress bars are not supported virtual double GetProgress(ClientContext &context, GlobalSourceState &gstate) const; @@ -10534,6 +12350,9 @@ class PhysicalOperator { virtual unique_ptr GetLocalSinkState(ExecutionContext &context) const; virtual unique_ptr GetGlobalSinkState(ClientContext &context) const; + //! The maximum amount of memory the operator should use per thread. + static idx_t GetMaxThreadMemory(ClientContext &context); + virtual bool IsSink() const { return false; } @@ -10550,6 +12369,7 @@ class PhysicalOperator { // Pipeline construction virtual vector GetSources() const; bool AllSourcesSupportBatchIndex() const; + bool AllOperatorsPreserveOrder() const; void AddPipeline(Executor &executor, shared_ptr current, PipelineBuildState &state); virtual void BuildPipelines(Executor &executor, Pipeline ¤t, PipelineBuildState &state); @@ -10573,6 +12393,7 @@ class PhysicalOperator { + #include namespace duckdb { @@ -10643,14 +12464,14 @@ typedef unique_ptr (*table_function_bind_t)(ClientContext &context vector &return_types, vector &names); typedef unique_ptr (*table_function_init_global_t)(ClientContext &context, TableFunctionInitInput &input); -typedef unique_ptr (*table_function_init_local_t)(ClientContext &context, +typedef unique_ptr (*table_function_init_local_t)(ExecutionContext &context, TableFunctionInitInput &input, GlobalTableFunctionState *global_state); typedef unique_ptr (*table_statistics_t)(ClientContext &context, const FunctionData *bind_data, column_t column_index); typedef void (*table_function_t)(ClientContext &context, TableFunctionInput &data, DataChunk &output); -typedef OperatorResultType (*table_in_out_function_t)(ClientContext &context, TableFunctionInput &data, +typedef OperatorResultType (*table_in_out_function_t)(ExecutionContext &context, TableFunctionInput &data, DataChunk &input, DataChunk &output); typedef idx_t (*table_function_get_batch_index_t)(ClientContext &context, const FunctionData *bind_data, LocalTableFunctionState *local_state, @@ -10665,6 +12486,11 @@ typedef void (*table_function_pushdown_complex_filter_t)(ClientContext &context, vector> &filters); typedef string (*table_function_to_string_t)(const FunctionData *bind_data); +typedef void (*table_function_serialize_t)(FieldWriter &writer, const FunctionData *bind_data, + const TableFunction &function); +typedef unique_ptr (*table_function_deserialize_t)(ClientContext &context, FieldReader &reader, + TableFunction &function); + class TableFunction : public SimpleNamedParameterFunction { public: DUCKDB_API @@ -10711,6 +12537,10 @@ class TableFunction : public SimpleNamedParameterFunction { table_function_progress_t table_scan_progress; //! (Optional) returns the current batch index of the current scan operator table_function_get_batch_index_t get_batch_index; + + table_function_serialize_t serialize; + table_function_deserialize_t deserialize; + //! Whether or not the table function supports projection pushdown. If not supported a projection will be added //! that filters out unused columns. bool projection_pushdown; @@ -10826,6 +12656,9 @@ class TaskScheduler { bool GetTaskFromProducer(ProducerToken &token, unique_ptr &task); //! Run tasks forever until "marker" is set to false, "marker" must remain valid until the thread is joined void ExecuteForever(atomic *marker); + //! Run tasks until `marker` is set to false, `max_tasks` have been completed, or until there are no more tasks + //! available. Returns the number of tasks that were completed. + idx_t ExecuteTasks(atomic *marker, idx_t max_tasks); //! Run tasks until `max_tasks` have been completed, or until there are no more tasks available void ExecuteTasks(idx_t max_tasks); @@ -10835,6 +12668,9 @@ class TaskScheduler { //! Returns the number of threads int32_t NumberOfThreads(); + //! Send signals to n threads, signalling for them to wake up and attempt to execute a task + void Signal(idx_t n); + private: void SetThreadsInternal(int32_t n); @@ -10881,7 +12717,6 @@ class PipelineBuildState { unordered_map>> &GetUnionPipelines(Executor &executor); unordered_map>> &GetChildPipelines(Executor &executor); - unordered_map> &GetChildDependencies(Executor &executor); PhysicalOperator *GetPipelineSource(Pipeline &pipeline); PhysicalOperator *GetPipelineSink(Pipeline &pipeline); @@ -10933,6 +12768,8 @@ class Pipeline : public std::enable_shared_from_this { private: //! Whether or not the pipeline has been readied bool ready; + //! Whether or not the pipeline has been initialized + atomic initialized; //! The source of this pipeline PhysicalOperator *source; //! The chain of intermediate operators @@ -10961,22 +12798,6 @@ class Pipeline : public std::enable_shared_from_this { } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/pair.hpp -// -// -//===----------------------------------------------------------------------===// - - - -#include - -namespace duckdb { -using std::make_pair; -using std::pair; -} // namespace duckdb @@ -10992,8 +12813,7 @@ class Task; struct PipelineEventStack; struct ProducerToken; - -using event_map_t = unordered_map; +struct ScheduleEventData; class Executor { friend class Pipeline; @@ -11022,7 +12842,7 @@ class Executor { unique_ptr FetchChunk(); //! Push a new error - void PushError(ExceptionType type, const string &exception); + void PushError(PreservedError exception); //! True if an error has been thrown bool HasError(); //! Throw the exception that was pushed using PushError. @@ -11057,16 +12877,12 @@ class Executor { void InitializeInternal(PhysicalOperator *physical_plan); void ScheduleEvents(); - void ScheduleEventsInternal(const vector> &pipelines, - unordered_map>> &child_pipelines, - vector> &events, bool main_schedule = true); - - void SchedulePipeline(const shared_ptr &pipeline, event_map_t &event_map, - vector> &events, bool complete_pipeline); - Pipeline *ScheduleUnionPipeline(const shared_ptr &pipeline, const Pipeline *parent, - event_map_t &event_map, vector> &events); - void ScheduleChildPipeline(Pipeline *parent, const shared_ptr &pipeline, event_map_t &event_map, - vector> &events); + static void ScheduleEventsInternal(ScheduleEventData &event_data); + + static void SchedulePipeline(const shared_ptr &pipeline, ScheduleEventData &event_data, + vector &scheduled_pipelines); + static void ScheduleChildPipeline(Pipeline *parent, const shared_ptr &pipeline, + ScheduleEventData &event_data); void ExtractPipelines(shared_ptr &pipeline, vector> &result); bool NextExecutor(); @@ -11092,7 +12908,7 @@ class Executor { //! The producer of this query unique_ptr producer; //! Exceptions that occurred during the execution of the current query - vector> exceptions; + vector exceptions; //! List of events vector> events; //! The query profiler @@ -11111,8 +12927,6 @@ class Executor { //! Unlike union pipelines, child pipelines should be run AFTER their dependencies are completed //! i.e. they should be run after the dependencies are completed, but before finalize is called on the sink unordered_map>> child_pipelines; - //! Dependencies of child pipelines - unordered_map> child_dependencies; //! The last pending execution result (if any) PendingExecutionResult execution_result; @@ -11133,7 +12947,7 @@ class PendingQueryResult : public BaseQueryResult { public: DUCKDB_API PendingQueryResult(shared_ptr context, PreparedStatementData &statement, vector types, bool allow_stream_result); - DUCKDB_API explicit PendingQueryResult(string error_message); + DUCKDB_API explicit PendingQueryResult(PreservedError error_message); DUCKDB_API ~PendingQueryResult(); public: @@ -11178,6 +12992,7 @@ class PendingQueryResult : public BaseQueryResult { + namespace duckdb { class ClientContext; class PreparedStatementData; @@ -11189,7 +13004,7 @@ class PreparedStatement { DUCKDB_API PreparedStatement(shared_ptr context, shared_ptr data, string query, idx_t n_param); //! Create a prepared statement that was not successfully prepared - DUCKDB_API explicit PreparedStatement(string error); + DUCKDB_API explicit PreparedStatement(PreservedError error); DUCKDB_API ~PreparedStatement(); @@ -11203,11 +13018,15 @@ class PreparedStatement { //! Whether or not the statement was successfully prepared bool success; //! The error message (if success = false) - string error; + PreservedError error; //! The amount of bound parameters idx_t n_param; public: + //! Returns the stored error message + const string &GetError(); + //! Returns whether or not an error occurred + bool HasError() const; //! Returns the number of columns in the result idx_t ColumnCount(); //! Returns the statement type of the underlying prepared statement object @@ -11263,6 +13082,7 @@ class PreparedStatement { } // namespace duckdb + //===----------------------------------------------------------------------===// // DuckDB // @@ -11399,164 +13219,11 @@ string RelationTypeToString(RelationType type); - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/catalog/default/default_generator.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { -class ClientContext; - -class DefaultGenerator { -public: - explicit DefaultGenerator(Catalog &catalog) : catalog(catalog), created_all_entries(false) { - } - virtual ~DefaultGenerator() { - } - - Catalog &catalog; - atomic created_all_entries; - -public: - //! Creates a default entry with the specified name, or returns nullptr if no such entry can be generated - virtual unique_ptr CreateDefaultEntry(ClientContext &context, const string &entry_name) = 0; - //! Get a list of all default entries in the generator - virtual vector GetDefaultEntries() = 0; -}; - -} // namespace duckdb - - - - - - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/catalog/catalog_entry/table_catalog_entry.hpp -// -// -//===----------------------------------------------------------------------===// - - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/catalog/standard_entry.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - -namespace duckdb { -class SchemaCatalogEntry; - -//! A StandardEntry is a catalog entry that is a member of a schema -class StandardEntry : public CatalogEntry { -public: - StandardEntry(CatalogType type, SchemaCatalogEntry *schema, Catalog *catalog, string name) - : CatalogEntry(type, catalog, name), schema(schema) { - } - ~StandardEntry() override { - } - - //! The schema the entry belongs to - SchemaCatalogEntry *schema; -}; -} // namespace duckdb - - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/parser/constraint.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - -namespace duckdb { - -class Serializer; -class Deserializer; -class FieldWriter; -class FieldReader; - -//===--------------------------------------------------------------------===// -// Constraint Types -//===--------------------------------------------------------------------===// -enum class ConstraintType : uint8_t { - INVALID = 0, // invalid constraint type - NOT_NULL = 1, // NOT NULL constraint - CHECK = 2, // CHECK constraint - UNIQUE = 3, // UNIQUE constraint - FOREIGN_KEY = 4, // FOREIGN KEY constraint -}; - -enum class ForeignKeyType : uint8_t { - FK_TYPE_PRIMARY_KEY_TABLE = 0, // main table - FK_TYPE_FOREIGN_KEY_TABLE = 1, // referencing table - FK_TYPE_SELF_REFERENCE_TABLE = 2 // self refrencing table -}; - -struct ForeignKeyInfo { - ForeignKeyType type; - string schema; - //! if type is FK_TYPE_FOREIGN_KEY_TABLE, means main key table, if type is FK_TYPE_PRIMARY_KEY_TABLE, means foreign - //! key table - string table; - //! The set of main key table's column's index - vector pk_keys; - //! The set of foreign key table's column's index - vector fk_keys; -}; - -//! Constraint is the base class of any type of table constraint. -class Constraint { -public: - DUCKDB_API explicit Constraint(ConstraintType type); - DUCKDB_API virtual ~Constraint(); - - ConstraintType type; - -public: - DUCKDB_API virtual string ToString() const = 0; - DUCKDB_API void Print() const; - - DUCKDB_API virtual unique_ptr Copy() const = 0; - //! Serializes a Constraint to a stand-alone binary blob - DUCKDB_API void Serialize(Serializer &serializer) const; - //! Serializes a Constraint to a stand-alone binary blob - DUCKDB_API virtual void Serialize(FieldWriter &writer) const = 0; - //! Deserializes a blob back into a Constraint - DUCKDB_API static unique_ptr Deserialize(Deserializer &source); -}; -} // namespace duckdb - + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/planner/bound_constraint.hpp +// duckdb/catalog/default/default_generator.hpp // // //===----------------------------------------------------------------------===// @@ -11567,222 +13234,427 @@ class Constraint { namespace duckdb { -//! Bound equivalent of Constraint -class BoundConstraint { +class ClientContext; + +class DefaultGenerator { public: - explicit BoundConstraint(ConstraintType type) : type(type) {}; - virtual ~BoundConstraint() { + explicit DefaultGenerator(Catalog &catalog) : catalog(catalog), created_all_entries(false) { + } + virtual ~DefaultGenerator() { } - ConstraintType type; + Catalog &catalog; + atomic created_all_entries; + +public: + //! Creates a default entry with the specified name, or returns nullptr if no such entry can be generated + virtual unique_ptr CreateDefaultEntry(ClientContext &context, const string &entry_name) = 0; + //! Get a list of all default entries in the generator + virtual vector GetDefaultEntries() = 0; }; + } // namespace duckdb + + + + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/catalog/catalog_entry/column_dependency_manager.hpp +// duckdb/catalog/catalog_entry/sequence_catalog_entry.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/parsed_data/create_sequence_info.hpp // // //===----------------------------------------------------------------------===// +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/parsed_data/create_info.hpp +// +// +//===----------------------------------------------------------------------===// + //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/set.hpp +// duckdb/common/field_writer.hpp // // //===----------------------------------------------------------------------===// -#include -namespace duckdb { -using std::set; -} //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/common/stack.hpp +// duckdb/common/serializer/buffered_serializer.hpp // // //===----------------------------------------------------------------------===// -#include + namespace duckdb { -using std::stack; -} +#define SERIALIZER_DEFAULT_SIZE 1024 -namespace duckdb { +struct BinaryData { + unique_ptr data; + idx_t size; +}; -//! Dependency Manager local to a table, responsible for keeping track of generated column dependencies +class BufferedSerializer : public Serializer { +public: + //! Serializes to a buffer allocated by the serializer, will expand when + //! writing past the initial threshold + DUCKDB_API explicit BufferedSerializer(idx_t maximum_size = SERIALIZER_DEFAULT_SIZE); + //! Serializes to a provided (owned) data pointer + BufferedSerializer(unique_ptr data, idx_t size); + BufferedSerializer(data_ptr_t data, idx_t size); + + idx_t maximum_size; + data_ptr_t data; + + BinaryData blob; -class ColumnDependencyManager { public: - DUCKDB_API ColumnDependencyManager(); - DUCKDB_API ~ColumnDependencyManager(); - DUCKDB_API ColumnDependencyManager(ColumnDependencyManager &&other) = default; - DUCKDB_API ColumnDependencyManager(const ColumnDependencyManager &other) = delete; + void WriteData(const_data_ptr_t buffer, uint64_t write_size) override; + + //! Retrieves the data after the writing has been completed + BinaryData GetData() { + return std::move(blob); + } + + void Reset() { + blob.size = 0; + } +}; + +} // namespace duckdb +#include + +namespace duckdb { +class BufferedSerializer; + +class FieldWriter { public: - //! Get the bind order that ensures dependencies are resolved before dependents are - stack GetBindOrder(const vector &columns); + DUCKDB_API FieldWriter(Serializer &serializer); + DUCKDB_API ~FieldWriter(); - //! Adds a connection between the dependent and its dependencies - void AddGeneratedColumn(column_t index, const vector &indices, bool root = true); - //! Add a generated column from a column definition - void AddGeneratedColumn(const ColumnDefinition &column, const case_insensitive_map_t &name_map); +public: + template + void WriteField(const T &element) { + static_assert(std::is_trivially_destructible(), "WriteField object must be trivially destructible"); - //! Removes the column(s) and outputs the new column indices - vector RemoveColumn(column_t index, column_t column_amount); + AddField(); + WriteData((const_data_ptr_t)&element, sizeof(T)); + } - bool IsDependencyOf(column_t dependent, column_t dependency) const; - bool HasDependencies(column_t index) const; - const unordered_set &GetDependencies(column_t index) const; + //! Write a string with a length prefix + void WriteString(const string &val) { + WriteStringLen((const_data_ptr_t)val.c_str(), val.size()); + } + void WriteStringLen(const_data_ptr_t val, idx_t len) { + AddField(); + Write((uint32_t)len); + if (len > 0) { + WriteData(val, len); + } + } + void WriteBlob(const_data_ptr_t val, idx_t len) { + AddField(); + if (len > 0) { + WriteData(val, len); + } + } - bool HasDependents(column_t index) const; - const unordered_set &GetDependents(column_t index) const; + template > + void WriteList(const CONTAINER_TYPE &elements) { + AddField(); + Write(elements.size()); + for (auto &element : elements) { + Write(element); + } + } -private: - void RemoveStandardColumn(column_t index); - void RemoveGeneratedColumn(column_t index); + // vector yay + template > + void WriteListNoReference(const CONTAINER_TYPE &elements) { + AddField(); + Write(elements.size()); + for (auto element : elements) { + Write(element); + } + } - void AdjustSingle(column_t idx, idx_t offset); - // Clean up the gaps created by a Remove operation - vector CleanupInternals(column_t column_amount); + template + void WriteSerializable(const T &element) { + AddField(); + element.Serialize(*buffer); + } + + template + void WriteSerializableList(const vector> &elements) { + AddField(); + Write(elements.size()); + for (idx_t i = 0; i < elements.size(); i++) { + elements[i]->Serialize(*buffer); + } + } + + template + void WriteRegularSerializableList(const vector &elements) { + AddField(); + Write(elements.size()); + for (idx_t i = 0; i < elements.size(); i++) { + elements[i].Serialize(*buffer); + } + } + + template + void WriteOptional(const unique_ptr &element) { + AddField(); + Write(element ? true : false); + if (element) { + element->Serialize(*buffer); + } + } + + // Called after all fields have been written. Should always be called. + DUCKDB_API void Finalize(); + + Serializer &GetSerializer() { + return *buffer; + } private: - //! A map of column dependency to generated column(s) - unordered_map> dependencies_map; - //! A map of generated column name to (potentially generated)column dependencies - unordered_map> dependents_map; - //! For resolve-order purposes, keep track of the 'direct' (not inherited) dependencies of a generated column - unordered_map> direct_dependencies; - set deleted_columns; -}; + void AddField() { + field_count++; + } -} // namespace duckdb + template + void Write(const T &element) { + WriteData((const_data_ptr_t)&element, sizeof(T)); + } + DUCKDB_API void WriteData(const_data_ptr_t buffer, idx_t write_size); -namespace duckdb { +private: + Serializer &serializer; + unique_ptr buffer; + idx_t field_count; + bool finalized; +}; -class DataTable; -struct CreateTableInfo; -struct BoundCreateTableInfo; +template <> +DUCKDB_API void FieldWriter::Write(const string &val); -struct RenameColumnInfo; -struct AddColumnInfo; -struct RemoveColumnInfo; -struct SetDefaultInfo; -struct ChangeColumnTypeInfo; -struct AlterForeignKeyInfo; +class FieldDeserializer : public Deserializer { +public: + FieldDeserializer(Deserializer &root); -//! A table catalog entry -class TableCatalogEntry : public StandardEntry { public: - //! Create a real TableCatalogEntry and initialize storage for it - TableCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, BoundCreateTableInfo *info, - std::shared_ptr inherited_storage = nullptr); + void ReadData(data_ptr_t buffer, idx_t read_size) override; - //! A reference to the underlying storage unit used for this table - std::shared_ptr storage; - //! A list of columns that are part of this table - vector columns; - //! A list of constraints that are part of this table - vector> constraints; - //! A list of constraints that are part of this table - vector> bound_constraints; - ColumnDependencyManager column_dependency_manager; - //! A map of column name to column index - case_insensitive_map_t name_map; + void SetRemainingData(idx_t remaining_data); + idx_t RemainingData(); + Deserializer &GetRoot() { + return root; + } -public: - //! For debugging purposes, count how many columns are STANDARD - idx_t StandardColumnCount() const; - unique_ptr AlterEntry(ClientContext &context, AlterInfo *info) override; - //! Returns whether or not a column with the given name exists - DUCKDB_API bool ColumnExists(const string &name); - //! Returns a reference to the column of the specified name. Throws an - //! exception if the column does not exist. - ColumnDefinition &GetColumn(const string &name); - //! Returns a list of types of the table - vector GetTypes(); - string ToSQL() override; +private: + Deserializer &root; + idx_t remaining_data; +}; - //! Serialize the meta information of the TableCatalogEntry a serializer - virtual void Serialize(Serializer &serializer); - //! Deserializes to a CreateTableInfo - static unique_ptr Deserialize(Deserializer &source); +class FieldReader { +public: + DUCKDB_API FieldReader(Deserializer &source); + DUCKDB_API ~FieldReader(); - unique_ptr Copy(ClientContext &context) override; +public: + template + T ReadRequired() { + if (field_count >= max_field_count) { + // field is not there, throw an exception + throw SerializationException("Attempting to read a required field, but field is missing"); + } + // field is there, read the actual value + AddField(); + return source.Read(); + } - void SetAsRoot() override; + template + T ReadField(T default_value) { + if (field_count >= max_field_count) { + // field is not there, read the default value + return default_value; + } + // field is there, read the actual value + AddField(); + return source.Read(); + } - void CommitAlter(AlterInfo &info); - void CommitDrop(); + template + vector ReadRequiredList() { + if (field_count >= max_field_count) { + // field is not there, throw an exception + throw SerializationException("Attempting to read a required field, but field is missing"); + } + AddField(); + auto result_count = source.Read(); + vector result; + result.reserve(result_count); + for (idx_t i = 0; i < result_count; i++) { + result.push_back(source.Read()); + } + return result; + } - //! Returns the column index of the specified column name. - //! If the column does not exist: - //! If if_exists is true, returns DConstants::INVALID_INDEX - //! If if_exists is false, throws an exception - column_t GetColumnIndex(string &name, bool if_exists = false); + template + set ReadRequiredSet() { + if (field_count >= max_field_count) { + // field is not there, throw an exception + throw SerializationException("Attempting to read a required field, but field is missing"); + } + AddField(); + auto result_count = source.Read(); + set result; + for (idx_t i = 0; i < result_count; i++) { + result.insert(source.Read()); + } + return result; + } -private: - const string &GetColumnName(column_t index); - unique_ptr RenameColumn(ClientContext &context, RenameColumnInfo &info); - unique_ptr AddColumn(ClientContext &context, AddColumnInfo &info); - unique_ptr RemoveColumn(ClientContext &context, RemoveColumnInfo &info); - unique_ptr SetDefault(ClientContext &context, SetDefaultInfo &info); - unique_ptr ChangeColumnType(ClientContext &context, ChangeColumnTypeInfo &info); - unique_ptr SetForeignKeyConstraint(ClientContext &context, AlterForeignKeyInfo &info); -}; -} // namespace duckdb + template + unique_ptr ReadOptional(unique_ptr default_value, ARGS &&...args) { + if (field_count >= max_field_count) { + // field is not there, read the default value + return default_value; + } + // field is there, read the actual value + AddField(); + return source.template ReadOptional(std::forward(args)...); + } -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/catalog/catalog_entry/sequence_catalog_entry.hpp -// -// -//===----------------------------------------------------------------------===// + template > + RETURN_TYPE ReadSerializable(RETURN_TYPE default_value) { + if (field_count >= max_field_count) { + // field is not there, read the default value + return default_value; + } + // field is there, read the actual value + AddField(); + return T::Deserialize(source); + } + template , typename... ARGS> + RETURN_TYPE ReadSerializable(RETURN_TYPE default_value, ARGS &&...args) { + if (field_count >= max_field_count) { + // field is not there, read the default value + return default_value; + } + // field is there, read the actual value + AddField(); + return T::Deserialize(source, std::forward(args)...); + } + template > + RETURN_TYPE ReadRequiredSerializable() { + if (field_count >= max_field_count) { + // field is not there, throw an exception + throw SerializationException("Attempting to read mandatory field, but field is missing"); + } + // field is there, read the actual value + AddField(); + return T::Deserialize(source); + } + template , typename... ARGS> + RETURN_TYPE ReadRequiredSerializable(ARGS &&...args) { + if (field_count >= max_field_count) { + // field is not there, throw an exception + throw SerializationException("Attempting to read mandatory field, but field is missing"); + } + // field is there, read the actual value + AddField(); + return T::Deserialize(source, std::forward(args)...); + } + template , typename... ARGS> + vector ReadRequiredSerializableList(ARGS &&...args) { + if (field_count >= max_field_count) { + // field is not there, throw an exception + throw SerializationException("Attempting to read mandatory field, but field is missing"); + } + // field is there, read the actual value + AddField(); + auto result_count = source.Read(); -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/parser/parsed_data/create_sequence_info.hpp -// -// -//===----------------------------------------------------------------------===// + vector result; + for (idx_t i = 0; i < result_count; i++) { + result.push_back(T::Deserialize(source, std::forward(args)...)); + } + return result; + } + void ReadBlob(data_ptr_t result, idx_t read_size) { + if (field_count >= max_field_count) { + // field is not there, throw an exception + throw SerializationException("Attempting to read a required field, but field is missing"); + } + // field is there, read the actual value + AddField(); + source.ReadData(result, read_size); + } + //! Called after all fields have been read. Should always be called. + DUCKDB_API void Finalize(); -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/parser/parsed_data/create_info.hpp -// -// -//===----------------------------------------------------------------------===// + Deserializer &GetSource() { + return source; + } + +private: + void AddField() { + field_count++; + } +private: + FieldDeserializer source; + idx_t field_count; + idx_t max_field_count; + idx_t total_size; + bool finalized; +}; +} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -11806,7 +13678,6 @@ struct ParseInfo { } // namespace duckdb - namespace duckdb { enum class OnCreateConflict : uint8_t { @@ -11839,16 +13710,19 @@ struct CreateInfo : public ParseInfo { //! The SQL string of the CREATE statement string sql; +protected: + virtual void SerializeInternal(Serializer &) const = 0; + + void DeserializeBase(Deserializer &deserializer); + public: + void Serialize(Serializer &serializer) const; + + static unique_ptr Deserialize(Deserializer &deserializer); + virtual unique_ptr 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; - } + + DUCKDB_API void CopyProperties(CreateInfo &other) const; }; } // namespace duckdb @@ -11857,6 +13731,21 @@ struct CreateInfo : public ParseInfo { namespace duckdb { +enum class SequenceInfo : uint8_t { + // Sequence start + SEQ_START, + // Sequence increment + SEQ_INC, + // Sequence minimum value + SEQ_MIN, + // Sequence maximum value + SEQ_MAX, + // Sequence cycle option + SEQ_CYCLE, + // Sequence owner table + SEQ_OWN +}; + struct CreateSequenceInfo : public CreateInfo { CreateSequenceInfo() : CreateInfo(CatalogType::SEQUENCE_ENTRY, INVALID_SCHEMA), name(string()), usage_count(0), increment(1), @@ -11892,6 +13781,11 @@ struct CreateSequenceInfo : public CreateInfo { result->cycle = cycle; return move(result); } + +protected: + void SerializeInternal(Serializer &) const override { + throw NotImplementedException("Cannot serialize '%s'", CatalogTypeToString(type)); + } }; } // namespace duckdb @@ -11924,10 +13818,12 @@ enum class AlterType : uint8_t { enum AlterForeignKeyType : uint8_t { AFT_ADD = 0, AFT_DELETE = 1 }; struct AlterInfo : public ParseInfo { - AlterInfo(AlterType type, string schema, string name); + AlterInfo(AlterType type, string schema, string name, bool if_exists); ~AlterInfo() override; AlterType type; + //! if exists + bool if_exists; //! Schema name to alter string schema; //! Entry name to alter @@ -11946,7 +13842,7 @@ struct AlterInfo : public ParseInfo { //===--------------------------------------------------------------------===// struct ChangeOwnershipInfo : public AlterInfo { ChangeOwnershipInfo(CatalogType entry_catalog_type, string entry_schema, string entry_name, string owner_schema, - string owner_name); + string owner_name, bool if_exists); // Catalog type refers to the entry type, since this struct is usually built from an // ALTER . OWNED BY . statement @@ -11974,10 +13870,12 @@ enum class AlterTableType : uint8_t { ALTER_COLUMN_TYPE = 5, SET_DEFAULT = 6, FOREIGN_KEY_CONSTRAINT = 7, + SET_NOT_NULL = 8, + DROP_NOT_NULL = 9 }; struct AlterTableInfo : public AlterInfo { - AlterTableInfo(AlterTableType type, string schema, string table); + AlterTableInfo(AlterTableType type, string schema, string table, bool if_exists); ~AlterTableInfo() override; AlterTableType alter_table_type; @@ -11993,7 +13891,7 @@ struct AlterTableInfo : public AlterInfo { // RenameColumnInfo //===--------------------------------------------------------------------===// struct RenameColumnInfo : public AlterTableInfo { - RenameColumnInfo(string schema, string table, string old_name_p, string new_name_p); + RenameColumnInfo(string schema, string table, bool if_exists, string old_name_p, string new_name_p); ~RenameColumnInfo() override; //! Column old name @@ -12004,14 +13902,14 @@ struct RenameColumnInfo : public AlterTableInfo { public: unique_ptr Copy() const override; void SerializeAlterTable(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader, string schema, string table); + static unique_ptr Deserialize(FieldReader &reader, string schema, string table, bool if_exists); }; //===--------------------------------------------------------------------===// // RenameTableInfo //===--------------------------------------------------------------------===// struct RenameTableInfo : public AlterTableInfo { - RenameTableInfo(string schema, string table, string new_name); + RenameTableInfo(string schema, string table, bool if_exists, string new_name); ~RenameTableInfo() override; //! Relation new name @@ -12020,50 +13918,53 @@ struct RenameTableInfo : public AlterTableInfo { public: unique_ptr Copy() const override; void SerializeAlterTable(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader, string schema, string table); + static unique_ptr Deserialize(FieldReader &reader, string schema, string table, bool if_exists); }; //===--------------------------------------------------------------------===// // AddColumnInfo //===--------------------------------------------------------------------===// struct AddColumnInfo : public AlterTableInfo { - AddColumnInfo(string schema, string table, ColumnDefinition new_column); + AddColumnInfo(string schema, string table, bool if_exists, ColumnDefinition new_column, bool if_column_not_exists); ~AddColumnInfo() override; //! New column ColumnDefinition new_column; + //! Whether or not an error should be thrown if the column exist + bool if_column_not_exists; public: unique_ptr Copy() const override; void SerializeAlterTable(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader, string schema, string table); + static unique_ptr Deserialize(FieldReader &reader, string schema, string table, bool if_exists); }; //===--------------------------------------------------------------------===// // RemoveColumnInfo //===--------------------------------------------------------------------===// struct RemoveColumnInfo : public AlterTableInfo { - RemoveColumnInfo(string schema, string table, string removed_column, bool if_exists, bool cascade); + RemoveColumnInfo(string schema, string table, bool if_exists, string removed_column, bool if_column_exists, + bool cascade); ~RemoveColumnInfo() override; //! The column to remove string removed_column; //! Whether or not an error should be thrown if the column does not exist - bool if_exists; + bool if_column_exists; //! Whether or not the column should be removed if a dependency conflict arises (used by GENERATED columns) bool cascade; public: unique_ptr Copy() const override; void SerializeAlterTable(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader, string schema, string table); + static unique_ptr Deserialize(FieldReader &reader, string schema, string table, bool if_exists); }; //===--------------------------------------------------------------------===// // ChangeColumnTypeInfo //===--------------------------------------------------------------------===// struct ChangeColumnTypeInfo : public AlterTableInfo { - ChangeColumnTypeInfo(string schema, string table, string column_name, LogicalType target_type, + ChangeColumnTypeInfo(string schema, string table, bool if_exists, string column_name, LogicalType target_type, unique_ptr expression); ~ChangeColumnTypeInfo() override; @@ -12077,14 +13978,15 @@ struct ChangeColumnTypeInfo : public AlterTableInfo { public: unique_ptr Copy() const override; void SerializeAlterTable(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader, string schema, string table); + static unique_ptr Deserialize(FieldReader &reader, string schema, string table, bool if_exists); }; //===--------------------------------------------------------------------===// // SetDefaultInfo //===--------------------------------------------------------------------===// struct SetDefaultInfo : public AlterTableInfo { - SetDefaultInfo(string schema, string table, string column_name, unique_ptr new_default); + SetDefaultInfo(string schema, string table, bool if_exists, string column_name, + unique_ptr new_default); ~SetDefaultInfo() override; //! The column name to alter @@ -12095,14 +13997,14 @@ struct SetDefaultInfo : public AlterTableInfo { public: unique_ptr Copy() const override; void SerializeAlterTable(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader, string schema, string table); + static unique_ptr Deserialize(FieldReader &reader, string schema, string table, bool if_exists); }; //===--------------------------------------------------------------------===// // AlterForeignKeyInfo //===--------------------------------------------------------------------===// struct AlterForeignKeyInfo : public AlterTableInfo { - AlterForeignKeyInfo(string schema, string table, string fk_table, vector pk_columns, + AlterForeignKeyInfo(string schema, string table, bool if_exists, string fk_table, vector pk_columns, vector fk_columns, vector pk_keys, vector fk_keys, AlterForeignKeyType type); ~AlterForeignKeyInfo() override; @@ -12117,7 +14019,7 @@ struct AlterForeignKeyInfo : public AlterTableInfo { public: unique_ptr Copy() const override; void SerializeAlterTable(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader, string schema, string table); + static unique_ptr Deserialize(FieldReader &reader, string schema, string table, bool if_exists); }; //===--------------------------------------------------------------------===// @@ -12126,7 +14028,7 @@ struct AlterForeignKeyInfo : public AlterTableInfo { enum class AlterViewType : uint8_t { INVALID = 0, RENAME_VIEW = 1 }; struct AlterViewInfo : public AlterInfo { - AlterViewInfo(AlterViewType type, string schema, string view); + AlterViewInfo(AlterViewType type, string schema, string view, bool if_exists); ~AlterViewInfo() override; AlterViewType alter_view_type; @@ -12142,7 +14044,7 @@ struct AlterViewInfo : public AlterInfo { // RenameViewInfo //===--------------------------------------------------------------------===// struct RenameViewInfo : public AlterViewInfo { - RenameViewInfo(string schema, string view, string new_name); + RenameViewInfo(string schema, string view, bool if_exists, string new_name); ~RenameViewInfo() override; //! Relation new name @@ -12151,7 +14053,39 @@ struct RenameViewInfo : public AlterViewInfo { public: unique_ptr Copy() const override; void SerializeAlterView(FieldWriter &writer) const override; - static unique_ptr Deserialize(FieldReader &reader, string schema, string table); + static unique_ptr Deserialize(FieldReader &reader, string schema, string view, bool if_exists); +}; + +//===--------------------------------------------------------------------===// +// SetNotNullInfo +//===--------------------------------------------------------------------===// +struct SetNotNullInfo : public AlterTableInfo { + SetNotNullInfo(string schema, string table, bool if_exists, string column_name); + ~SetNotNullInfo() override; + + //! The column name to alter + string column_name; + +public: + unique_ptr Copy() const override; + void SerializeAlterTable(FieldWriter &writer) const override; + static unique_ptr Deserialize(FieldReader &reader, string schema, string table, bool if_exists); +}; + +//===--------------------------------------------------------------------===// +// DropNotNullInfo +//===--------------------------------------------------------------------===// +struct DropNotNullInfo : public AlterTableInfo { + DropNotNullInfo(string schema, string table, bool if_exists, string column_name); + ~DropNotNullInfo() override; + + //! The column name to alter + string column_name; + +public: + unique_ptr Copy() const override; + void SerializeAlterTable(FieldWriter &writer) const override; + static unique_ptr Deserialize(FieldReader &reader, string schema, string table, bool if_exists); }; } // namespace duckdb @@ -12246,7 +14180,7 @@ class SequenceCatalogEntry : public StandardEntry { namespace duckdb { -enum class UndoFlags : uint32_t { // far to big but aligned (TM) +enum class UndoFlags : uint32_t { // far too big but aligned (TM) EMPTY_ENTRY = 0, CATALOG_ENTRY = 1, INSERT_TUPLE = 2, @@ -12257,36 +14191,24 @@ enum class UndoFlags : uint32_t { // far to big but aligned (TM) } // namespace duckdb + namespace duckdb { class WriteAheadLog; -struct UndoChunk { - explicit UndoChunk(idx_t size); - ~UndoChunk(); - - data_ptr_t WriteEntry(UndoFlags type, uint32_t len); - - unique_ptr data; - idx_t current_position; - idx_t maximum_size; - unique_ptr next; - UndoChunk *prev; -}; - //! The undo buffer of a transaction is used to hold previous versions of tuples //! that might be required in the future (because of rollbacks or previous //! transactions accessing them) class UndoBuffer { public: struct IteratorState { - UndoChunk *current; + ArenaChunk *current; data_ptr_t start; data_ptr_t end; }; public: - UndoBuffer(); + UndoBuffer(const shared_ptr &context); //! Reserve space for an entry of the specified type and length in the undo //! buffer @@ -12306,8 +14228,8 @@ class UndoBuffer { void Rollback() noexcept; private: - unique_ptr head; - UndoChunk *tail; + ClientContext &context; + ArenaAllocator allocator; private: template @@ -12330,11 +14252,10 @@ class UndoBuffer { - //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/storage/table/scan_state.hpp +// duckdb/common/types/chunk_collection.hpp // // //===----------------------------------------------------------------------===// @@ -12342,102 +14263,151 @@ class UndoBuffer { -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/storage/buffer/buffer_handle.hpp -// -// -//===----------------------------------------------------------------------===// -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/storage/storage_info.hpp -// -// -//===----------------------------------------------------------------------===// +namespace duckdb { +class Allocator; +class ClientContext; + +//! A ChunkCollection represents a set of DataChunks that all have the same +//! types +/*! + A ChunkCollection represents a set of DataChunks concatenated together in a + list. Individual values of the collection can be iterated over using the + iterator. It is also possible to iterate directly over the chunks for more + direct access. +*/ +class ChunkCollection { +public: + ChunkCollection(Allocator &allocator); + ChunkCollection(ClientContext &context); + + //! The amount of columns in the ChunkCollection + DUCKDB_API vector &Types() { + return types; + } + const vector &Types() const { + return types; + } + //! The amount of rows in the ChunkCollection + DUCKDB_API const idx_t &Count() const { + return count; + } + //! The amount of columns in the ChunkCollection + DUCKDB_API idx_t ColumnCount() const { + return types.size(); + } + //! Append a new DataChunk directly to this ChunkCollection + DUCKDB_API void Append(DataChunk &new_chunk); + //! Append a new DataChunk directly to this ChunkCollection + DUCKDB_API void Append(unique_ptr new_chunk); -namespace duckdb { -class Serializer; -class Deserializer; -struct FileHandle; + //! Append another ChunkCollection directly to this ChunkCollection + DUCKDB_API void Append(ChunkCollection &other); -//! The version number of the database storage format -extern const uint64_t VERSION_NUMBER; + //! Merge is like Append but messes up the order and destroys the other collection + DUCKDB_API void Merge(ChunkCollection &other); -using block_id_t = int64_t; + //! Fuse adds new columns to the right of the collection + DUCKDB_API void Fuse(ChunkCollection &other); -#define INVALID_BLOCK (-1) + DUCKDB_API void Verify(); -// maximum block id, 2^62 -#define MAXIMUM_BLOCK 4611686018427388000LL + //! Gets the value of the column at the specified index + DUCKDB_API Value GetValue(idx_t column, idx_t index); + //! Sets the value of the column at the specified index + DUCKDB_API void SetValue(idx_t column, idx_t index, const Value &value); -//! The MainHeader is the first header in the storage file. The MainHeader is typically written only once for a database -//! file. -struct MainHeader { - static constexpr idx_t MAGIC_BYTE_SIZE = 4; - static constexpr idx_t MAGIC_BYTE_OFFSET = sizeof(uint64_t); - static constexpr idx_t FLAG_COUNT = 4; - // the magic bytes in front of the file - // should be "DUCK" - static const char MAGIC_BYTES[]; - //! The version of the database - uint64_t version_number; - //! The set of flags used by the database - uint64_t flags[FLAG_COUNT]; + //! Copy a single cell to a target vector + DUCKDB_API void CopyCell(idx_t column, idx_t index, Vector &target, idx_t target_offset); - static void CheckMagicBytes(FileHandle &handle); + DUCKDB_API string ToString() const; + DUCKDB_API void Print() const; - void Serialize(Serializer &ser); - static MainHeader Deserialize(Deserializer &source); -}; + //! Gets a reference to the chunk at the given index + DUCKDB_API DataChunk &GetChunkForRow(idx_t row_index) { + return *chunks[LocateChunk(row_index)]; + } -//! The DatabaseHeader contains information about the current state of the database. Every storage file has two -//! DatabaseHeaders. On startup, the DatabaseHeader with the highest iteration count is used as the active header. When -//! a checkpoint is performed, the active DatabaseHeader is switched by increasing the iteration count of the -//! DatabaseHeader. -struct DatabaseHeader { - //! The iteration count, increases by 1 every time the storage is checkpointed. - uint64_t iteration; - //! A pointer to the initial meta block - block_id_t meta_block; - //! A pointer to the block containing the free list - block_id_t free_list; - //! The number of blocks that is in the file as of this database header. If the file is larger than BLOCK_SIZE * - //! block_count any blocks appearing AFTER block_count are implicitly part of the free_list. - uint64_t block_count; + //! Gets a reference to the chunk at the given 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]; + } - void Serialize(Serializer &ser); - static DatabaseHeader Deserialize(Deserializer &source); + DUCKDB_API const vector> &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 Fetch() { + if (ChunkCount() == 0) { + return nullptr; + } + + auto res = move(chunks[0]); + chunks.erase(chunks.begin() + 0); + return res; + } + + DUCKDB_API void Sort(vector &desc, vector &null_order, idx_t result[]); + //! Reorders the rows in the collection according to the given indices. + DUCKDB_API void Reorder(idx_t order[]); + + //! Returns true if the ChunkCollections are equivalent + DUCKDB_API bool Equals(ChunkCollection &other); + + //! Locates the chunk that belongs to the specific index + DUCKDB_API idx_t LocateChunk(idx_t index) { + idx_t result = index / STANDARD_VECTOR_SIZE; + D_ASSERT(result < chunks.size()); + return result; + } + + Allocator &GetAllocator() { + return allocator; + } + +private: + Allocator &allocator; + //! The total amount of elements in the collection + idx_t count; + //! The set of data chunks in the collection + vector> chunks; + //! The types of the ChunkCollection + vector types; }; - } // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/storage/table/scan_state.hpp +// +// +//===----------------------------------------------------------------------===// -namespace duckdb { -class BlockHandle; -class FileBuffer; -class BufferHandle { -public: - BufferHandle(shared_ptr handle, FileBuffer *node); - DUCKDB_API ~BufferHandle(); - //! The block handle - shared_ptr handle; - //! The managed buffer node - FileBuffer *node; - DUCKDB_API data_ptr_t Ptr(); -}; -} // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -12549,6 +14519,8 @@ class BoundAggregateExpression : public Expression { hash_t Hash() const override; bool Equals(const BaseExpression *other) const override; unique_ptr Copy() override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -12583,6 +14555,8 @@ class BoundBetweenExpression : public Expression { bool Equals(const BaseExpression *other) const override; unique_ptr Copy() override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); public: ExpressionType LowerComparisonType() { @@ -12611,6 +14585,9 @@ namespace duckdb { struct BoundCaseCheck { unique_ptr when_expr; unique_ptr then_expr; + + void Serialize(Serializer &serializer) const; + static BoundCaseCheck Deserialize(Deserializer &source, PlanDeserializationState &state); }; class BoundCaseExpression : public Expression { @@ -12628,6 +14605,9 @@ class BoundCaseExpression : public Expression { bool Equals(const BaseExpression *other) const override; unique_ptr Copy() override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -12656,6 +14636,7 @@ class BoundCastExpression : public Expression { public: LogicalType source_type() { + D_ASSERT(child->return_type.IsValid()); return child->return_type; } @@ -12671,6 +14652,9 @@ class BoundCastExpression : public Expression { bool Equals(const BaseExpression *other) const override; unique_ptr Copy() override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -12689,6 +14673,9 @@ class BoundCastExpression : public Expression { namespace duckdb { +class FieldReader; +class FieldWriter; + //! A BoundColumnRef expression represents a ColumnRef expression that was bound to an actual table and column index. It //! is not yet executable, however. The ColumnBindingResolver transforms the BoundColumnRefExpressions into //! BoundExpressions, which refer to indexes into the physical chunks that pass through the executor. @@ -12717,6 +14704,9 @@ class BoundColumnRefExpression : public Expression { hash_t Hash() const override; unique_ptr Copy() override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -12747,6 +14737,8 @@ class BoundComparisonExpression : public Expression { bool Equals(const BaseExpression *other) const override; unique_ptr Copy() override; + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); public: static LogicalType BindComparison(LogicalType left_type, LogicalType right_type); @@ -12782,6 +14774,9 @@ class BoundConjunctionExpression : public Expression { bool PropagatesNullValues() const override; unique_ptr Copy() override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -12813,6 +14808,9 @@ class BoundConstantExpression : public Expression { hash_t Hash() const override; unique_ptr Copy() override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -12851,6 +14849,9 @@ class BoundDefaultExpression : public Expression { unique_ptr Copy() override { return make_unique(return_type); } + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -12877,7 +14878,7 @@ class BoundFunctionExpression : public Expression { vector> arguments, unique_ptr bind_info, bool is_operator = false); - // The bound function expression + //! The bound function expression ScalarFunction function; //! List of child-expressions of the function vector> children; @@ -12896,6 +14897,87 @@ class BoundFunctionExpression : public Expression { unique_ptr Copy() override; void Verify() const override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); +}; +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/expression/bound_lambda_expression.hpp +// +// +//===----------------------------------------------------------------------===// + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/expression/lambda_expression.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +//! LambdaExpression represents either: +//! 1. A lambda operator that can be used for e.g. mapping an expression to a list +//! 2. An OperatorExpression with the "->" operator +//! Lambda expressions are written in the form of "params -> expr", e.g. "x -> x + 1" +class LambdaExpression : public ParsedExpression { +public: + LambdaExpression(unique_ptr lhs, unique_ptr expr); + + // we need the context to determine if this is a list of column references or an expression (for JSON) + unique_ptr lhs; + + vector> params; + unique_ptr expr; + +public: + string ToString() const override; + + static bool Equals(const LambdaExpression *a, const LambdaExpression *b); + hash_t Hash() const override; + + unique_ptr Copy() const override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionType type, FieldReader &source); +}; + +} // namespace duckdb + + +namespace duckdb { + +class BoundLambdaExpression : public Expression { +public: + BoundLambdaExpression(ExpressionType type_p, LogicalType return_type_p, unique_ptr lambda_expr_p, + idx_t parameter_count_p); + + unique_ptr lambda_expr; + vector> captures; + idx_t parameter_count; + +public: + string ToString() const override; + + bool Equals(const BaseExpression *other) const override; + + unique_ptr Copy() override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -12925,6 +15007,9 @@ class BoundOperatorExpression : public Expression { bool Equals(const BaseExpression *other) const override; unique_ptr Copy() override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -12939,6 +15024,65 @@ class BoundOperatorExpression : public Expression { +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/expression/bound_parameter_data.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + +namespace duckdb { + +struct BoundParameterData { + BoundParameterData() { + } + BoundParameterData(Value val) : value(move(val)), return_type(value.type()) { + } + + Value value; + LogicalType return_type; + +public: + void Serialize(Serializer &serializer) const { + FieldWriter writer(serializer); + value.Serialize(writer.GetSerializer()); + writer.WriteSerializable(return_type); + writer.Finalize(); + } + + static shared_ptr Deserialize(Deserializer &source) { + FieldReader reader(source); + auto value = Value::Deserialize(reader.GetSource()); + auto result = make_shared(move(value)); + result->return_type = reader.ReadRequiredSerializable(); + reader.Finalize(); + return result; + } +}; + +struct BoundParameterMap { + BoundParameterMap(vector ¶meter_data) : parameter_data(parameter_data) { + } + + bound_parameter_map_t parameters; + vector ¶meter_data; + + LogicalType GetReturnType(idx_t index) { + if (index >= parameter_data.size()) { + return LogicalTypeId::UNKNOWN; + } + return parameter_data[index].return_type; + } +}; + +} // namespace duckdb namespace duckdb { @@ -12948,9 +15092,14 @@ class BoundParameterExpression : public Expression { explicit BoundParameterExpression(idx_t parameter_nr); idx_t parameter_nr; - Value *value; + shared_ptr parameter_data; public: + //! Invalidate a bound parameter expression - forcing a rebind on any subsequent filters + DUCKDB_API static void Invalidate(Expression &expr); + //! Invalidate all parameters within an expression + DUCKDB_API static void InvalidateRecursive(Expression &expr); + bool IsScalar() const override; bool HasParameter() const override; bool IsFoldable() const override; @@ -12961,7 +15110,11 @@ class BoundParameterExpression : public Expression { hash_t Hash() const override; unique_ptr Copy() override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; + } // namespace duckdb //===----------------------------------------------------------------------===// @@ -13001,6 +15154,9 @@ class BoundReferenceExpression : public Expression { bool Equals(const BaseExpression *other) const override; unique_ptr Copy() override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -13076,6 +15232,7 @@ class CopyStatement; class CreateStatement; class DeleteStatement; class DropStatement; +class ExtensionStatement; class InsertStatement; class SelectStatement; class TransactionStatement; @@ -13090,6 +15247,7 @@ class VacuumStatement; class RelationStatement; class SetStatement; class LoadStatement; +class LogicalPlanStatement; //===--------------------------------------------------------------------===// // Query Node @@ -13177,6 +15335,191 @@ struct SampleOptions; +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/function/function_set.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/function/pragma_function.hpp +// +// +//===----------------------------------------------------------------------===// + + + + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/parsed_data/pragma_info.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + + +namespace duckdb { + +enum class PragmaType : uint8_t { PRAGMA_STATEMENT, PRAGMA_CALL }; + +struct PragmaInfo : public ParseInfo { + //! Name of the PRAGMA statement + string name; + //! Parameter list (if any) + vector parameters; + //! Named parameter list (if any) + named_parameter_map_t named_parameters; + +public: + unique_ptr Copy() const { + auto result = make_unique(); + result->name = name; + result->parameters = parameters; + result->named_parameters = named_parameters; + return result; + } +}; + +} // namespace duckdb + + + +namespace duckdb { +class ClientContext; + +//! Return a substitute query to execute instead of this pragma statement +typedef string (*pragma_query_t)(ClientContext &context, const FunctionParameters ¶meters); +//! Execute the main pragma function +typedef void (*pragma_function_t)(ClientContext &context, const FunctionParameters ¶meters); + +//! Pragma functions are invoked by calling PRAGMA x +//! Pragma functions come in three types: +//! * Call: function call, e.g. PRAGMA table_info('tbl') +//! -> call statements can take multiple parameters +//! * Statement: statement without parameters, e.g. PRAGMA show_tables +//! -> this is similar to a call pragma but without parameters +//! Pragma functions can either return a new query to execute (pragma_query_t) +//! or they can +class PragmaFunction : public SimpleNamedParameterFunction { +public: + // Call + DUCKDB_API static PragmaFunction PragmaCall(const string &name, pragma_query_t query, vector arguments, + LogicalType varargs = LogicalType::INVALID); + DUCKDB_API static PragmaFunction PragmaCall(const string &name, pragma_function_t function, + vector arguments, + LogicalType varargs = LogicalType::INVALID); + // Statement + DUCKDB_API static PragmaFunction PragmaStatement(const string &name, pragma_query_t query); + DUCKDB_API static PragmaFunction PragmaStatement(const string &name, pragma_function_t function); + + DUCKDB_API string ToString() override; + +public: + PragmaType type; + + pragma_query_t query; + pragma_function_t function; + named_parameter_type_map_t named_parameters; + +private: + PragmaFunction(string name, PragmaType pragma_type, pragma_query_t query, pragma_function_t function, + vector arguments, LogicalType varargs); +}; + +} // namespace duckdb + + +namespace duckdb { + +template +class FunctionSet { +public: + explicit FunctionSet(string name) : name(name) { + } + + //! The name of the function set + string name; + //! The set of functions. + vector functions; + +public: + void AddFunction(T function) { + functions.push_back(move(function)); + } + idx_t Size() { + return functions.size(); + } + T GetFunctionByOffset(idx_t offset) { + return functions[offset]; + } + T &GetFunctionReferenceByOffset(idx_t offset) { + return functions[offset]; + } + bool MergeFunctionSet(FunctionSet new_functions) { + D_ASSERT(!new_functions.functions.empty()); + bool need_rewrite_entry = false; + for (auto &new_func : new_functions.functions) { + bool can_add = true; + for (auto &func : functions) { + if (new_func.Equal(func)) { + can_add = false; + break; + } + } + if (can_add) { + functions.push_back(new_func); + need_rewrite_entry = true; + } + } + return need_rewrite_entry; + } +}; + +class ScalarFunctionSet : public FunctionSet { +public: + DUCKDB_API explicit ScalarFunctionSet(string name); + + DUCKDB_API ScalarFunction GetFunctionByArguments(const vector &arguments); +}; + +class AggregateFunctionSet : public FunctionSet { +public: + DUCKDB_API explicit AggregateFunctionSet(string name); + + DUCKDB_API AggregateFunction GetFunctionByArguments(const vector &arguments); +}; + +class TableFunctionSet : public FunctionSet { +public: + DUCKDB_API explicit TableFunctionSet(string name); + + TableFunction GetFunctionByArguments(const vector &arguments); +}; + +class PragmaFunctionSet : public FunctionSet { +public: + explicit PragmaFunctionSet(string name) : FunctionSet(move(name)) { + } +}; + +} // namespace duckdb + namespace duckdb { @@ -13191,7 +15534,7 @@ class TableFunctionCatalogEntry : public StandardEntry { TableFunctionCatalogEntry(Catalog *catalog, SchemaCatalogEntry *schema, CreateTableFunctionInfo *info); //! The table function - vector functions; + TableFunctionSet functions; }; } // namespace duckdb @@ -13282,7 +15625,12 @@ struct string_t; // see: https://nullprogram.com/blog/2018/07/31/ inline hash_t murmurhash64(uint64_t x) { - return x * UINT64_C(0xbf58476d1ce4e5b9); + x ^= x >> 32; + x *= 0xd6e8feb86659fd93U; + x ^= x >> 32; + x *= 0xd6e8feb86659fd93U; + x ^= x >> 32; + return x; } inline hash_t murmurhash32(uint32_t x) { @@ -13300,25 +15648,25 @@ inline hash_t CombineHash(hash_t left, hash_t right) { } template <> -hash_t Hash(uint64_t val); +DUCKDB_API hash_t Hash(uint64_t val); template <> -hash_t Hash(int64_t val); +DUCKDB_API hash_t Hash(int64_t val); template <> -hash_t Hash(hugeint_t val); +DUCKDB_API hash_t Hash(hugeint_t val); template <> -hash_t Hash(float val); +DUCKDB_API hash_t Hash(float val); template <> -hash_t Hash(double val); +DUCKDB_API hash_t Hash(double val); template <> -hash_t Hash(const char *val); +DUCKDB_API hash_t Hash(const char *val); template <> -hash_t Hash(char *val); +DUCKDB_API hash_t Hash(char *val); template <> -hash_t Hash(string_t val); +DUCKDB_API hash_t Hash(string_t val); template <> -hash_t Hash(interval_t val); -hash_t Hash(const char *val, size_t size); -hash_t Hash(uint8_t *val, size_t size); +DUCKDB_API hash_t Hash(interval_t val); +DUCKDB_API hash_t Hash(const char *val, size_t size); +DUCKDB_API hash_t Hash(uint8_t *val, size_t size); } // namespace duckdb @@ -13369,6 +15717,7 @@ using qualified_column_set_t = unordered_set expr) - : ParsedExpression(ExpressionType::INVALID, ExpressionClass::BOUND_EXPRESSION), expr(move(expr)) { - } + BoundExpression(unique_ptr expr); unique_ptr expr; public: - string ToString() const override { - if (!expr) { - throw InternalException("ToString(): BoundExpression does not have a child"); - } - return expr->ToString(); - } + string ToString() const override; - bool Equals(const BaseExpression *other) const override { - return false; - } - hash_t Hash() const override { - return 0; - } + bool Equals(const BaseExpression *other) const override; + hash_t Hash() const override; - unique_ptr Copy() const override { - throw SerializationException("Cannot copy or serialize bound expression"); - } + unique_ptr Copy() const override; - void Serialize(FieldWriter &writer) const override { - throw SerializationException("Cannot copy or serialize bound expression"); - } + void Serialize(FieldWriter &writer) const override; }; } // namespace duckdb @@ -13425,7 +15759,7 @@ class ScalarMacroCatalogEntry; class CatalogEntry; class SimpleFunction; -struct MacroBinding; +struct DummyBinding; struct BoundColumnReferenceInfo { string name; @@ -13444,632 +15778,358 @@ struct BindResult { return !error.empty(); } - unique_ptr expression; - string error; -}; - -class ExpressionBinder { -public: - ExpressionBinder(Binder &binder, ClientContext &context, bool replace_binder = false); - virtual ~ExpressionBinder(); - - //! The target type that should result from the binder. If the result is not of this type, a cast to this type will - //! be added. Defaults to INVALID. - LogicalType target_type; - - MacroBinding *macro_binding; - -public: - unique_ptr Bind(unique_ptr &expr, LogicalType *result_type = nullptr, - bool root_expression = true); - - //! Returns whether or not any columns have been bound by the expression binder - bool HasBoundColumns() { - return !bound_columns.empty(); - } - const vector &GetBoundColumns() { - return bound_columns; - } - - string Bind(unique_ptr *expr, idx_t depth, bool root_expression = false); - - unique_ptr CreateStructExtract(unique_ptr base, string field_name); - unique_ptr CreateStructPack(ColumnRefExpression &colref); - BindResult BindQualifiedColumnName(ColumnRefExpression &colref, const string &table_name); - - unique_ptr QualifyColumnName(const string &column_name, string &error_message); - unique_ptr QualifyColumnName(ColumnRefExpression &colref, string &error_message); - - // Bind table names to ColumnRefExpressions - void QualifyColumnNames(unique_ptr &expr); - static void QualifyColumnNames(Binder &binder, unique_ptr &expr); - - static unique_ptr PushCollation(ClientContext &context, unique_ptr source, - const string &collation, bool equality_only = false); - static void TestCollation(ClientContext &context, const string &collation); - - bool BindCorrelatedColumns(unique_ptr &expr); - - void BindChild(unique_ptr &expr, idx_t depth, string &error); - static void ExtractCorrelatedExpressions(Binder &binder, Expression &expr); - - static bool ContainsNullType(const LogicalType &type); - static LogicalType ExchangeNullType(const LogicalType &type); - static bool ContainsType(const LogicalType &type, LogicalTypeId target); - static LogicalType ExchangeType(const LogicalType &type, LogicalTypeId target, LogicalType new_type); - - //! Bind the given expresion. Unlike Bind(), this does *not* mute the given ParsedExpression. - //! Exposed to be used from sub-binders that aren't subclasses of ExpressionBinder. - virtual BindResult BindExpression(unique_ptr *expr_ptr, idx_t depth, - bool root_expression = false); - - void ReplaceMacroParametersRecursive(unique_ptr &expr); - -protected: - BindResult BindExpression(BetweenExpression &expr, idx_t depth); - BindResult BindExpression(CaseExpression &expr, idx_t depth); - BindResult BindExpression(CollateExpression &expr, idx_t depth); - BindResult BindExpression(CastExpression &expr, idx_t depth); - BindResult BindExpression(ColumnRefExpression &expr, idx_t depth); - BindResult BindExpression(ComparisonExpression &expr, idx_t depth); - BindResult BindExpression(ConjunctionExpression &expr, idx_t depth); - BindResult BindExpression(ConstantExpression &expr, idx_t depth); - BindResult BindExpression(FunctionExpression &expr, idx_t depth, unique_ptr *expr_ptr); - BindResult BindExpression(LambdaExpression &expr, idx_t depth); - BindResult BindExpression(OperatorExpression &expr, idx_t depth); - BindResult BindExpression(ParameterExpression &expr, idx_t depth); - BindResult BindExpression(PositionalReferenceExpression &ref, idx_t depth); - BindResult BindExpression(SubqueryExpression &expr, idx_t depth); - -protected: - virtual BindResult BindGroupingFunction(OperatorExpression &op, idx_t depth); - virtual BindResult BindFunction(FunctionExpression &expr, ScalarFunctionCatalogEntry *function, idx_t depth); - virtual BindResult BindAggregate(FunctionExpression &expr, AggregateFunctionCatalogEntry *function, idx_t depth); - virtual BindResult BindUnnest(FunctionExpression &expr, idx_t depth); - virtual BindResult BindMacro(FunctionExpression &expr, ScalarMacroCatalogEntry *macro, idx_t depth, - unique_ptr *expr_ptr); - - virtual string UnsupportedAggregateMessage(); - virtual string UnsupportedUnnestMessage(); - - Binder &binder; - ClientContext &context; - ExpressionBinder *stored_binder; - vector bound_columns; -}; - -} // namespace duckdb - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/table_binding.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - - - - -namespace duckdb { -class BindContext; -class BoundQueryNode; -class ColumnRefExpression; -class SubqueryRef; -class LogicalGet; -class TableCatalogEntry; -class TableFunctionCatalogEntry; -class BoundTableFunction; -class StandardEntry; - -enum class BindingType { BASE, TABLE, MACRO, CATALOG_ENTRY }; - -//! A Binding represents a binding to a table, table-producing function or subquery with a specified table index. -struct Binding { - Binding(BindingType binding_type, const string &alias, vector types, vector names, - idx_t index); - virtual ~Binding() = default; - - //! The type of Binding - BindingType binding_type; - //! The alias of the binding - string alias; - //! The table index of the binding - idx_t index; - vector types; - //! Column names of the subquery - vector names; - //! Name -> index for the names - case_insensitive_map_t name_map; - -public: - bool TryGetBindingIndex(const string &column_name, column_t &column_index); - column_t GetBindingIndex(const string &column_name); - bool HasMatchingBinding(const string &column_name); - virtual string ColumnNotFoundError(const string &column_name) const; - virtual BindResult Bind(ColumnRefExpression &colref, idx_t depth); - virtual StandardEntry *GetStandardEntry(); -}; - -struct EntryBinding : public Binding { -public: - EntryBinding(const string &alias, vector types, vector names, idx_t index, - StandardEntry &entry); - StandardEntry &entry; - -public: - StandardEntry *GetStandardEntry() override; -}; - -//! TableBinding is exactly like the Binding, except it keeps track of which columns were bound in the linked LogicalGet -//! node for projection pushdown purposes. -struct TableBinding : public Binding { - TableBinding(const string &alias, vector types, vector names, LogicalGet &get, idx_t index, - bool add_row_id = false); - - //! the underlying LogicalGet - LogicalGet &get; - -public: - unique_ptr ExpandGeneratedColumn(const string &column_name); - BindResult Bind(ColumnRefExpression &colref, idx_t depth) override; - StandardEntry *GetStandardEntry() override; - string ColumnNotFoundError(const string &column_name) const override; -}; - -//! MacroBinding is like the Binding, except the alias and index are set by default. Used for binding Macro -//! Params/Arguments. -struct MacroBinding : public Binding { - static constexpr const char *MACRO_NAME = "0_macro_parameters"; - -public: - MacroBinding(vector types_p, vector names_p, string macro_name); - - //! Arguments - vector> arguments; - //! The name of the macro - string macro_name; - -public: - BindResult Bind(ColumnRefExpression &colref, idx_t depth) override; - - //! Given the parameter colref, returns a copy of the argument that was supplied for this parameter - unique_ptr ParamToArg(ColumnRefExpression &colref); -}; - -} // namespace duckdb - - -namespace duckdb { -class Binder; -class LogicalGet; -class BoundQueryNode; - -class StarExpression; - -struct UsingColumnSet { - string primary_binding; - unordered_set bindings; -}; - -//! The BindContext object keeps track of all the tables and columns that are -//! encountered during the binding process. -class BindContext { -public: - //! Keep track of recursive CTE references - case_insensitive_map_t> cte_references; - -public: - //! Given a column name, find the matching table it belongs to. Throws an - //! exception if no table has a column of the given name. - string GetMatchingBinding(const string &column_name); - //! Like GetMatchingBinding, but instead of throwing an error if multiple tables have the same binding it will - //! return a list of all the matching ones - unordered_set GetMatchingBindings(const string &column_name); - //! Like GetMatchingBindings, but returns the top 3 most similar bindings (in levenshtein distance) instead of the - //! matching ones - vector GetSimilarBindings(const string &column_name); - - Binding *GetCTEBinding(const string &ctename); - //! Binds a column expression to the base table. Returns the bound expression - //! or throws an exception if the column could not be bound. - BindResult BindColumn(ColumnRefExpression &colref, idx_t depth); - string BindColumn(PositionalReferenceExpression &ref, string &table_name, string &column_name); - BindResult BindColumn(PositionalReferenceExpression &ref, idx_t depth); + unique_ptr expression; + string error; +}; - unique_ptr ExpandGeneratedColumn(const string &table_name, const string &column_name); +class ExpressionBinder { +public: + ExpressionBinder(Binder &binder, ClientContext &context, bool replace_binder = false); + virtual ~ExpressionBinder(); - unique_ptr CreateColumnReference(const string &table_name, const string &column_name); - unique_ptr CreateColumnReference(const string &schema_name, const string &table_name, - const string &column_name); + //! The target type that should result from the binder. If the result is not of this type, a cast to this type will + //! be added. Defaults to INVALID. + LogicalType target_type; - //! Generate column expressions for all columns that are present in the - //! referenced tables. This is used to resolve the * expression in a - //! selection list. - void GenerateAllColumnExpressions(StarExpression &expr, vector> &new_select_list); - //! Check if the given (binding, column_name) is in the exclusion/replacement lists. - //! Returns true if it is in one of these lists, and should therefore be skipped. - bool CheckExclusionList(StarExpression &expr, Binding *binding, const string &column_name, - vector> &new_select_list, - case_insensitive_set_t &excluded_columns); + DummyBinding *macro_binding; + vector *lambda_bindings = nullptr; - const vector> &GetBindingsList() { - return bindings_list; +public: + unique_ptr Bind(unique_ptr &expr, LogicalType *result_type = nullptr, + bool root_expression = true); + + //! Returns whether or not any columns have been bound by the expression binder + bool HasBoundColumns() { + return !bound_columns.empty(); + } + const vector &GetBoundColumns() { + return bound_columns; } - //! Adds a base table with the given alias to the BindContext. - void AddBaseTable(idx_t index, const string &alias, const vector &names, const vector &types, - LogicalGet &get); - //! Adds a call to a table function with the given alias to the BindContext. - void AddTableFunction(idx_t index, const string &alias, const vector &names, - const vector &types, LogicalGet &get); - //! Adds a table view with a given alias to the BindContext. - void AddView(idx_t index, const string &alias, SubqueryRef &ref, BoundQueryNode &subquery, ViewCatalogEntry *view); - //! Adds a subquery with a given alias to the BindContext. - void AddSubquery(idx_t index, const string &alias, SubqueryRef &ref, BoundQueryNode &subquery); - //! Adds a subquery with a given alias to the BindContext. - void AddSubquery(idx_t index, const string &alias, TableFunctionRef &ref, BoundQueryNode &subquery); - //! Adds a binding to a catalog entry with a given alias to the BindContext. - void AddEntryBinding(idx_t index, const string &alias, const vector &names, - const vector &types, StandardEntry *entry); - //! Adds a base table with the given alias to the BindContext. - void AddGenericBinding(idx_t index, const string &alias, const vector &names, - const vector &types); + string Bind(unique_ptr *expr, idx_t depth, bool root_expression = false); - //! Adds a base table with the given alias to the CTE BindContext. - //! We need this to correctly bind recursive CTEs with multiple references. - void AddCTEBinding(idx_t index, const string &alias, const vector &names, const vector &types); + unique_ptr CreateStructExtract(unique_ptr base, string field_name); + unique_ptr CreateStructPack(ColumnRefExpression &colref); + BindResult BindQualifiedColumnName(ColumnRefExpression &colref, const string &table_name); - //! Add an implicit join condition (e.g. USING (x)) - void AddUsingBinding(const string &column_name, UsingColumnSet *set); + unique_ptr QualifyColumnName(const string &column_name, string &error_message); + unique_ptr QualifyColumnName(ColumnRefExpression &colref, string &error_message); - void AddUsingBindingSet(unique_ptr set); + // Bind table names to ColumnRefExpressions + void QualifyColumnNames(unique_ptr &expr); + static void QualifyColumnNames(Binder &binder, unique_ptr &expr); - //! Returns any using column set for the given column name, or nullptr if there is none. On conflict (multiple using - //! column sets with the same name) throw an exception. - UsingColumnSet *GetUsingBinding(const string &column_name); - //! Returns any using column set for the given column name, or nullptr if there is none - UsingColumnSet *GetUsingBinding(const string &column_name, const string &binding_name); - //! Erase a using binding from the set of using bindings - void RemoveUsingBinding(const string &column_name, UsingColumnSet *set); - //! Finds the using bindings for a given column. Returns true if any exists, false otherwise. - bool FindUsingBinding(const string &column_name, unordered_set **using_columns); - //! Transfer a using binding from one bind context to this bind context - void TransferUsingBinding(BindContext ¤t_context, UsingColumnSet *current_set, UsingColumnSet *new_set, - const string &binding, const string &using_column); + static unique_ptr PushCollation(ClientContext &context, unique_ptr source, + const string &collation, bool equality_only = false); + static void TestCollation(ClientContext &context, const string &collation); - //! Fetch the actual column name from the given binding, or throws if none exists - //! This can be different from "column_name" because of case insensitivity - //! (e.g. "column_name" might return "COLUMN_NAME") - string GetActualColumnName(const string &binding, const string &column_name); + bool BindCorrelatedColumns(unique_ptr &expr); - case_insensitive_map_t> GetCTEBindings() { - return cte_bindings; - } - void SetCTEBindings(case_insensitive_map_t> bindings) { - cte_bindings = bindings; - } + void BindChild(unique_ptr &expr, idx_t depth, string &error); + static void ExtractCorrelatedExpressions(Binder &binder, Expression &expr); - //! Alias a set of column names for the specified table, using the original names if there are not enough aliases - //! specified. - static vector AliasColumnNames(const string &table_name, const vector &names, - const vector &column_aliases); + static bool ContainsNullType(const LogicalType &type); + static LogicalType ExchangeNullType(const LogicalType &type); + static bool ContainsType(const LogicalType &type, LogicalTypeId target); + static LogicalType ExchangeType(const LogicalType &type, LogicalTypeId target, LogicalType new_type); - //! Add all the bindings from a BindContext to this BindContext. The other BindContext is destroyed in the process. - void AddContext(BindContext other); + //! Bind the given expresion. Unlike Bind(), this does *not* mute the given ParsedExpression. + //! Exposed to be used from sub-binders that aren't subclasses of ExpressionBinder. + virtual BindResult BindExpression(unique_ptr *expr_ptr, idx_t depth, + bool root_expression = false); - //! Gets a binding of the specified name. Returns a nullptr and sets the out_error if the binding could not be - //! found. - Binding *GetBinding(const string &name, string &out_error); + void ReplaceMacroParametersRecursive(unique_ptr &expr); -private: - void AddBinding(const string &alias, unique_ptr binding); +protected: + BindResult BindExpression(BetweenExpression &expr, idx_t depth); + BindResult BindExpression(CaseExpression &expr, idx_t depth); + BindResult BindExpression(CollateExpression &expr, idx_t depth); + BindResult BindExpression(CastExpression &expr, idx_t depth); + BindResult BindExpression(ColumnRefExpression &expr, idx_t depth); + BindResult BindExpression(ComparisonExpression &expr, idx_t depth); + BindResult BindExpression(ConjunctionExpression &expr, idx_t depth); + BindResult BindExpression(ConstantExpression &expr, idx_t depth); + BindResult BindExpression(FunctionExpression &expr, idx_t depth, unique_ptr *expr_ptr); + BindResult BindExpression(LambdaExpression &expr, idx_t depth, const bool is_lambda, + const LogicalType &list_child_type); + BindResult BindExpression(OperatorExpression &expr, idx_t depth); + BindResult BindExpression(ParameterExpression &expr, idx_t depth); + BindResult BindExpression(PositionalReferenceExpression &ref, idx_t depth); + BindResult BindExpression(SubqueryExpression &expr, idx_t depth); -private: - //! The set of bindings - case_insensitive_map_t> bindings; - //! The list of bindings in insertion order - vector> bindings_list; - //! The set of columns used in USING join conditions - case_insensitive_map_t> using_columns; - //! Using column sets - vector> using_column_sets; + void TransformCapturedLambdaColumn(unique_ptr &original, unique_ptr &replacement, + vector> &captures, LogicalType &list_child_type, + string &alias); + void CaptureLambdaColumns(vector> &captures, LogicalType &list_child_type, + unique_ptr &expr, string &alias); - //! The set of CTE bindings - case_insensitive_map_t> cte_bindings; -}; -} // namespace duckdb +protected: + virtual BindResult BindGroupingFunction(OperatorExpression &op, idx_t depth); + virtual BindResult BindFunction(FunctionExpression &expr, ScalarFunctionCatalogEntry *function, idx_t depth); + virtual BindResult BindLambdaFunction(FunctionExpression &expr, ScalarFunctionCatalogEntry *function, idx_t depth); + virtual BindResult BindAggregate(FunctionExpression &expr, AggregateFunctionCatalogEntry *function, idx_t depth); + virtual BindResult BindUnnest(FunctionExpression &expr, idx_t depth); + virtual BindResult BindMacro(FunctionExpression &expr, ScalarMacroCatalogEntry *macro, idx_t depth, + unique_ptr *expr_ptr); + virtual string UnsupportedAggregateMessage(); + virtual string UnsupportedUnnestMessage(); + Binder &binder; + ClientContext &context; + ExpressionBinder *stored_binder; + vector bound_columns; +}; +} // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/table_binding.hpp +// +// +//===----------------------------------------------------------------------===// -namespace duckdb { -class BoundResultModifier; -class BoundSelectNode; -class ClientContext; -class ExpressionBinder; -class LimitModifier; -class OrderBinder; -class TableCatalogEntry; -class ViewCatalogEntry; -class TableMacroCatalogEntry; -struct CreateInfo; -struct BoundCreateTableInfo; -struct BoundCreateFunctionInfo; -struct CommonTableExpressionInfo; -enum class BindingMode : uint8_t { STANDARD_BINDING, EXTRACT_NAMES }; -struct CorrelatedColumnInfo { - ColumnBinding binding; - LogicalType type; - string name; - idx_t depth; - explicit CorrelatedColumnInfo(BoundColumnRefExpression &expr) - : binding(expr.binding), type(expr.return_type), name(expr.GetName()), depth(expr.depth) { - } - bool operator==(const CorrelatedColumnInfo &rhs) const { - return binding == rhs.binding; - } -}; +namespace duckdb { +class BindContext; +class BoundQueryNode; +class ColumnRefExpression; +class SubqueryRef; +class LogicalGet; +class TableCatalogEntry; +class TableFunctionCatalogEntry; +class BoundTableFunction; +class StandardEntry; -//! Bind the parsed query tree to the actual columns present in the catalog. -/*! - The binder is responsible for binding tables and columns to actual physical - tables and columns in the catalog. In the process, it also resolves types of - all expressions. -*/ -class Binder : public std::enable_shared_from_this { - friend class ExpressionBinder; - friend class SelectBinder; - friend class RecursiveSubqueryPlanner; +enum class BindingType { BASE, TABLE, DUMMY, CATALOG_ENTRY }; -public: - static shared_ptr CreateBinder(ClientContext &context, Binder *parent = nullptr, bool inherit_ctes = true); +//! A Binding represents a binding to a table, table-producing function or subquery with a specified table index. +struct Binding { + Binding(BindingType binding_type, const string &alias, vector types, vector names, + idx_t index); + virtual ~Binding() = default; - //! The client context - ClientContext &context; - //! A mapping of names to common table expressions - case_insensitive_map_t CTE_bindings; - //! The CTEs that have already been bound - unordered_set bound_ctes; - //! The bind context - BindContext bind_context; - //! The set of correlated columns bound by this binder (FIXME: this should probably be an unordered_set and not a - //! vector) - vector correlated_columns; - //! The set of parameter expressions bound by this binder - vector *parameters; - //! The types of the prepared statement parameters, if any - vector *parameter_types; - //! Statement properties - StatementProperties properties; - //! The alias for the currently processing subquery, if it exists + //! The type of Binding + BindingType binding_type; + //! The alias of the binding string alias; - //! Macro parameter bindings (if any) - MacroBinding *macro_binding = nullptr; + //! The table index of the binding + idx_t index; + vector types; + //! Column names of the subquery + vector names; + //! Name -> index for the names + case_insensitive_map_t name_map; public: - BoundStatement Bind(SQLStatement &statement); - BoundStatement Bind(QueryNode &node); - - unique_ptr BindCreateTableInfo(unique_ptr info); - void BindCreateViewInfo(CreateViewInfo &base); - SchemaCatalogEntry *BindSchema(CreateInfo &info); - SchemaCatalogEntry *BindCreateFunctionInfo(CreateInfo &info); + bool TryGetBindingIndex(const string &column_name, column_t &column_index); + column_t GetBindingIndex(const string &column_name); + bool HasMatchingBinding(const string &column_name); + virtual string ColumnNotFoundError(const string &column_name) const; + virtual BindResult Bind(ColumnRefExpression &colref, idx_t depth); + virtual StandardEntry *GetStandardEntry(); +}; - //! Check usage, and cast named parameters to their types - static void BindNamedParameters(named_parameter_type_map_t &types, named_parameter_map_t &values, - QueryErrorContext &error_context, string &func_name); +struct EntryBinding : public Binding { +public: + EntryBinding(const string &alias, vector types, vector names, idx_t index, + StandardEntry &entry); + StandardEntry &entry; - unique_ptr Bind(TableRef &ref); - unique_ptr CreatePlan(BoundTableRef &ref); +public: + StandardEntry *GetStandardEntry() override; +}; - //! Generates an unused index for a table - idx_t GenerateTableIndex(); +//! TableBinding is exactly like the Binding, except it keeps track of which columns were bound in the linked LogicalGet +//! node for projection pushdown purposes. +struct TableBinding : public Binding { + TableBinding(const string &alias, vector types, vector names, LogicalGet &get, idx_t index, + bool add_row_id = false); - //! Add a common table expression to the binder - void AddCTE(const string &name, CommonTableExpressionInfo *cte); - //! Find a common table expression by name; returns nullptr if none exists - CommonTableExpressionInfo *FindCTE(const string &name, bool skip = false); + //! the underlying LogicalGet + LogicalGet &get; - bool CTEIsAlreadyBound(CommonTableExpressionInfo *cte); +public: + unique_ptr ExpandGeneratedColumn(const string &column_name); + BindResult Bind(ColumnRefExpression &colref, idx_t depth) override; + StandardEntry *GetStandardEntry() override; + string ColumnNotFoundError(const string &column_name) const override; +}; - //! Add the view to the set of currently bound views - used for detecting recursive view definitions - void AddBoundView(ViewCatalogEntry *view); +//! DummyBinding is like the Binding, except the alias and index are set by default. Used for binding lambdas and macro +//! parameters. +struct DummyBinding : public Binding { + // NOTE: changing this string conflicts with the storage version + static constexpr const char *DUMMY_NAME = "0_macro_parameters"; - void PushExpressionBinder(ExpressionBinder *binder); - void PopExpressionBinder(); - void SetActiveBinder(ExpressionBinder *binder); - ExpressionBinder *GetActiveBinder(); - bool HasActiveBinder(); +public: + DummyBinding(vector types_p, vector names_p, string dummy_name_p); - vector &GetActiveBinders(); + //! Arguments + vector> *arguments; + //! The name of the dummy binding + string dummy_name; - void MergeCorrelatedColumns(vector &other); - //! Add a correlated column to this binder (if it does not exist) - void AddCorrelatedColumn(const CorrelatedColumnInfo &info); +public: + BindResult Bind(ColumnRefExpression &colref, idx_t depth) override; - string FormatError(ParsedExpression &expr_context, const string &message); - string FormatError(TableRef &ref_context, const string &message); + //! Given the parameter colref, returns a copy of the argument that was supplied for this parameter + unique_ptr ParamToArg(ColumnRefExpression &colref); +}; - string FormatErrorRecursive(idx_t query_location, const string &message, vector &values); - template - string FormatErrorRecursive(idx_t query_location, const string &msg, vector &values, T param, - Args... params) { - values.push_back(ExceptionFormatValue::CreateFormatValue(param)); - return FormatErrorRecursive(query_location, msg, values, params...); - } +} // namespace duckdb - template - string FormatError(idx_t query_location, const string &msg, Args... params) { - vector values; - return FormatErrorRecursive(query_location, msg, values, params...); - } - static void BindLogicalType(ClientContext &context, LogicalType &type, const string &schema = ""); +namespace duckdb { +class Binder; +class LogicalGet; +class BoundQueryNode; - bool HasMatchingBinding(const string &table_name, const string &column_name, string &error_message); - bool HasMatchingBinding(const string &schema_name, const string &table_name, const string &column_name, - string &error_message); +class StarExpression; - void SetBindingMode(BindingMode mode); - BindingMode GetBindingMode(); - void AddTableName(string table_name); - const unordered_set &GetTableNames(); +struct UsingColumnSet { + string primary_binding; + unordered_set bindings; +}; -private: - //! The parent binder (if any) - shared_ptr parent; - //! The vector of active binders - vector active_binders; - //! The count of bound_tables - idx_t bound_tables; - //! Whether or not the binder has any unplanned subqueries that still need to be planned - bool has_unplanned_subqueries = false; - //! Whether or not subqueries should be planned already - bool plan_subquery = true; - //! Whether CTEs should reference the parent binder (if it exists) - bool inherit_ctes = true; - //! Whether or not the binder can contain NULLs as the root of expressions - bool can_contain_nulls = false; - //! The root statement of the query that is currently being parsed - SQLStatement *root_statement = nullptr; - //! Binding mode - BindingMode mode = BindingMode::STANDARD_BINDING; - //! Table names extracted for BindingMode::EXTRACT_NAMES - unordered_set table_names; - //! The set of bound views - unordered_set bound_views; +//! The BindContext object keeps track of all the tables and columns that are +//! encountered during the binding process. +class BindContext { +public: + //! Keep track of recursive CTE references + case_insensitive_map_t> cte_references; -private: - //! Bind the expressions of generated columns to check for errors - void BindGeneratedColumns(BoundCreateTableInfo &info); - //! Bind the default values of the columns of a table - void BindDefaultValues(vector &columns, vector> &bound_defaults); - //! Bind a limit value (LIMIT or OFFSET) - unique_ptr BindDelimiter(ClientContext &context, OrderBinder &order_binder, - unique_ptr delimiter, const LogicalType &type, - Value &delimiter_value); +public: + //! Given a column name, find the matching table it belongs to. Throws an + //! exception if no table has a column of the given name. + string GetMatchingBinding(const string &column_name); + //! Like GetMatchingBinding, but instead of throwing an error if multiple tables have the same binding it will + //! return a list of all the matching ones + unordered_set GetMatchingBindings(const string &column_name); + //! Like GetMatchingBindings, but returns the top 3 most similar bindings (in levenshtein distance) instead of the + //! matching ones + vector GetSimilarBindings(const string &column_name); - //! Move correlated expressions from the child binder to this binder - void MoveCorrelatedExpressions(Binder &other); + Binding *GetCTEBinding(const string &ctename); + //! Binds a column expression to the base table. Returns the bound expression + //! or throws an exception if the column could not be bound. + BindResult BindColumn(ColumnRefExpression &colref, idx_t depth); + string BindColumn(PositionalReferenceExpression &ref, string &table_name, string &column_name); + BindResult BindColumn(PositionalReferenceExpression &ref, idx_t depth); - BoundStatement Bind(SelectStatement &stmt); - BoundStatement Bind(InsertStatement &stmt); - BoundStatement Bind(CopyStatement &stmt); - BoundStatement Bind(DeleteStatement &stmt); - BoundStatement Bind(UpdateStatement &stmt); - BoundStatement Bind(CreateStatement &stmt); - BoundStatement Bind(DropStatement &stmt); - BoundStatement Bind(AlterStatement &stmt); - BoundStatement Bind(TransactionStatement &stmt); - BoundStatement Bind(PragmaStatement &stmt); - BoundStatement Bind(ExplainStatement &stmt); - BoundStatement Bind(VacuumStatement &stmt); - BoundStatement Bind(RelationStatement &stmt); - BoundStatement Bind(ShowStatement &stmt); - BoundStatement Bind(CallStatement &stmt); - BoundStatement Bind(ExportStatement &stmt); - BoundStatement Bind(SetStatement &stmt); - BoundStatement Bind(LoadStatement &stmt); - BoundStatement BindReturning(vector> returning_list, TableCatalogEntry *table, - idx_t update_table_index, unique_ptr child_operator, - BoundStatement result); + unique_ptr ExpandGeneratedColumn(const string &table_name, const string &column_name); - unique_ptr BindTableMacro(FunctionExpression &function, TableMacroCatalogEntry *macro_func, idx_t depth); + unique_ptr CreateColumnReference(const string &table_name, const string &column_name); + unique_ptr CreateColumnReference(const string &schema_name, const string &table_name, + const string &column_name); - unique_ptr BindNode(SelectNode &node); - unique_ptr BindNode(SetOperationNode &node); - unique_ptr BindNode(RecursiveCTENode &node); - unique_ptr BindNode(QueryNode &node); + //! Generate column expressions for all columns that are present in the + //! referenced tables. This is used to resolve the * expression in a + //! selection list. + void GenerateAllColumnExpressions(StarExpression &expr, vector> &new_select_list); + //! Check if the given (binding, column_name) is in the exclusion/replacement lists. + //! Returns true if it is in one of these lists, and should therefore be skipped. + bool CheckExclusionList(StarExpression &expr, Binding *binding, const string &column_name, + vector> &new_select_list, + case_insensitive_set_t &excluded_columns); - unique_ptr VisitQueryNode(BoundQueryNode &node, unique_ptr root); - unique_ptr CreatePlan(BoundRecursiveCTENode &node); - unique_ptr CreatePlan(BoundSelectNode &statement); - unique_ptr CreatePlan(BoundSetOperationNode &node); - unique_ptr CreatePlan(BoundQueryNode &node); + const vector> &GetBindingsList() { + return bindings_list; + } - unique_ptr Bind(BaseTableRef &ref); - unique_ptr Bind(CrossProductRef &ref); - unique_ptr Bind(JoinRef &ref); - unique_ptr Bind(SubqueryRef &ref, CommonTableExpressionInfo *cte = nullptr); - unique_ptr Bind(TableFunctionRef &ref); - unique_ptr Bind(EmptyTableRef &ref); - unique_ptr Bind(ExpressionListRef &ref); + //! Adds a base table with the given alias to the BindContext. + void AddBaseTable(idx_t index, const string &alias, const vector &names, const vector &types, + LogicalGet &get); + //! Adds a call to a table function with the given alias to the BindContext. + void AddTableFunction(idx_t index, const string &alias, const vector &names, + const vector &types, LogicalGet &get); + //! Adds a table view with a given alias to the BindContext. + void AddView(idx_t index, const string &alias, SubqueryRef &ref, BoundQueryNode &subquery, ViewCatalogEntry *view); + //! Adds a subquery with a given alias to the BindContext. + void AddSubquery(idx_t index, const string &alias, SubqueryRef &ref, BoundQueryNode &subquery); + //! Adds a subquery with a given alias to the BindContext. + void AddSubquery(idx_t index, const string &alias, TableFunctionRef &ref, BoundQueryNode &subquery); + //! Adds a binding to a catalog entry with a given alias to the BindContext. + void AddEntryBinding(idx_t index, const string &alias, const vector &names, + const vector &types, StandardEntry *entry); + //! Adds a base table with the given alias to the BindContext. + void AddGenericBinding(idx_t index, const string &alias, const vector &names, + const vector &types); - bool BindTableFunctionParameters(TableFunctionCatalogEntry &table_function, - vector> &expressions, vector &arguments, - vector ¶meters, named_parameter_map_t &named_parameters, - unique_ptr &subquery, string &error); - bool BindTableInTableOutFunction(vector> &expressions, - unique_ptr &subquery, string &error); + //! Adds a base table with the given alias to the CTE BindContext. + //! We need this to correctly bind recursive CTEs with multiple references. + void AddCTEBinding(idx_t index, const string &alias, const vector &names, const vector &types); - unique_ptr CreatePlan(BoundBaseTableRef &ref); - unique_ptr CreatePlan(BoundCrossProductRef &ref); - unique_ptr CreatePlan(BoundJoinRef &ref); - unique_ptr CreatePlan(BoundSubqueryRef &ref); - unique_ptr CreatePlan(BoundTableFunction &ref); - unique_ptr CreatePlan(BoundEmptyTableRef &ref); - unique_ptr CreatePlan(BoundExpressionListRef &ref); - unique_ptr CreatePlan(BoundCTERef &ref); + //! Add an implicit join condition (e.g. USING (x)) + void AddUsingBinding(const string &column_name, UsingColumnSet *set); - BoundStatement BindCopyTo(CopyStatement &stmt); - BoundStatement BindCopyFrom(CopyStatement &stmt); + void AddUsingBindingSet(unique_ptr set); - void BindModifiers(OrderBinder &order_binder, QueryNode &statement, BoundQueryNode &result); - void BindModifierTypes(BoundQueryNode &result, const vector &sql_types, idx_t projection_index); + //! Returns any using column set for the given column name, or nullptr if there is none. On conflict (multiple using + //! column sets with the same name) throw an exception. + UsingColumnSet *GetUsingBinding(const string &column_name); + //! Returns any using column set for the given column name, or nullptr if there is none + UsingColumnSet *GetUsingBinding(const string &column_name, const string &binding_name); + //! Erase a using binding from the set of using bindings + void RemoveUsingBinding(const string &column_name, UsingColumnSet *set); + //! Finds the using bindings for a given column. Returns true if any exists, false otherwise. + bool FindUsingBinding(const string &column_name, unordered_set **using_columns); + //! Transfer a using binding from one bind context to this bind context + void TransferUsingBinding(BindContext ¤t_context, UsingColumnSet *current_set, UsingColumnSet *new_set, + const string &binding, const string &using_column); - BoundStatement BindSummarize(ShowStatement &stmt); - unique_ptr BindLimit(OrderBinder &order_binder, LimitModifier &limit_mod); - unique_ptr BindLimitPercent(OrderBinder &order_binder, LimitPercentModifier &limit_mod); - unique_ptr BindOrderExpression(OrderBinder &order_binder, unique_ptr expr); + //! Fetch the actual column name from the given binding, or throws if none exists + //! This can be different from "column_name" because of case insensitivity + //! (e.g. "column_name" might return "COLUMN_NAME") + string GetActualColumnName(const string &binding, const string &column_name); - unique_ptr PlanFilter(unique_ptr condition, unique_ptr root); + case_insensitive_map_t> GetCTEBindings() { + return cte_bindings; + } + void SetCTEBindings(case_insensitive_map_t> bindings) { + cte_bindings = bindings; + } - void PlanSubqueries(unique_ptr *expr, unique_ptr *root); - unique_ptr PlanSubquery(BoundSubqueryExpression &expr, unique_ptr &root); + //! Alias a set of column names for the specified table, using the original names if there are not enough aliases + //! specified. + static vector AliasColumnNames(const string &table_name, const vector &names, + const vector &column_aliases); - unique_ptr CastLogicalOperatorToTypes(vector &source_types, - vector &target_types, - unique_ptr op); + //! Add all the bindings from a BindContext to this BindContext. The other BindContext is destroyed in the process. + void AddContext(BindContext other); - string FindBinding(const string &using_column, const string &join_side); - bool TryFindBinding(const string &using_column, const string &join_side, string &result); + //! Gets a binding of the specified name. Returns a nullptr and sets the out_error if the binding could not be + //! found. + Binding *GetBinding(const string &name, string &out_error); - void AddUsingBindingSet(unique_ptr set); - string RetrieveUsingBinding(Binder ¤t_binder, UsingColumnSet *current_set, const string &column_name, - const string &join_side, UsingColumnSet *new_set); +private: + void AddBinding(const string &alias, unique_ptr binding); -public: - // This should really be a private constructor, but make_shared does not allow it... - // If you are thinking about calling this, you should probably call Binder::CreateBinder - Binder(bool I_know_what_I_am_doing, ClientContext &context, shared_ptr parent, bool inherit_ctes); -}; +private: + //! The set of bindings + case_insensitive_map_t> bindings; + //! The list of bindings in insertion order + vector> bindings_list; + //! The set of columns used in USING join conditions + case_insensitive_map_t> using_columns; + //! Using column sets + vector> using_column_sets; + //! The set of CTE bindings + case_insensitive_map_t> cte_bindings; +}; } // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/planner/bound_query_node.hpp -// -// -//===----------------------------------------------------------------------===// @@ -14179,7 +16239,8 @@ class SQLStatement { public: virtual string ToString() const { - throw InternalException("ToString not supported for this type of SQLStatement"); + throw InternalException("ToString not supported for this type of SQLStatement: '%s'", + StatementTypeToString(type)); } //! Create a copy of this SelectStatement virtual unique_ptr Copy() const = 0; @@ -14243,164 +16304,480 @@ enum class TableReferenceType : uint8_t { -namespace duckdb { +namespace duckdb { + +enum class SampleMethod : uint8_t { SYSTEM_SAMPLE = 0, BERNOULLI_SAMPLE = 1, RESERVOIR_SAMPLE = 2 }; + +string SampleMethodToString(SampleMethod method); + +struct SampleOptions { + Value sample_size; + bool is_percentage; + SampleMethod method; + int64_t seed = -1; + + unique_ptr Copy(); + void Serialize(Serializer &serializer); + static unique_ptr Deserialize(Deserializer &source); + static bool Equals(SampleOptions *a, SampleOptions *b); +}; + +} // namespace duckdb + + +namespace duckdb { +class Deserializer; +class Serializer; + +//! Represents a generic expression that returns a table. +class TableRef { +public: + explicit TableRef(TableReferenceType type) : type(type) { + } + virtual ~TableRef() { + } + + TableReferenceType type; + string alias; + //! Sample options (if any) + unique_ptr sample; + //! The location in the query (if any) + idx_t query_location = DConstants::INVALID_INDEX; + +public: + //! Convert the object to a string + virtual string ToString() const = 0; + string BaseToString(string result) const; + string BaseToString(string result, const vector &column_name_alias) const; + void Print(); + + virtual bool Equals(const TableRef *other) const; + + virtual unique_ptr Copy() = 0; + + //! Serializes a TableRef to a stand-alone binary blob + DUCKDB_API void Serialize(Serializer &serializer) const; + //! Serializes a TableRef to a stand-alone binary blob + DUCKDB_API virtual void Serialize(FieldWriter &writer) const = 0; + //! Deserializes a blob back into a TableRef + DUCKDB_API static unique_ptr Deserialize(Deserializer &source); + + //! Copy the properties of this table ref to the target + void CopyProperties(TableRef &target) const; +}; +} // namespace duckdb + + +namespace duckdb { + +class QueryNode; + +//! SelectStatement is a typical SELECT clause +class SelectStatement : public SQLStatement { +public: + SelectStatement() : SQLStatement(StatementType::SELECT_STATEMENT) { + } + + //! The main query node + unique_ptr node; + +protected: + SelectStatement(const SelectStatement &other); + +public: + //! Convert the SELECT statement to a string + string ToString() const override; + //! Create a copy of this SelectStatement + unique_ptr Copy() const override; + //! Serializes a SelectStatement to a stand-alone binary blob + void Serialize(Serializer &serializer) const; + //! Deserializes a blob back into a SelectStatement, returns nullptr if + //! deserialization is not possible + static unique_ptr Deserialize(Deserializer &source); + //! Whether or not the statements are equivalent + bool Equals(const SQLStatement *other) const; +}; +} // namespace duckdb + + +namespace duckdb { + +class SelectStatement; + +struct CommonTableExpressionInfo { + vector aliases; + unique_ptr query; +}; + +} // namespace duckdb + + +namespace duckdb { + +enum QueryNodeType : uint8_t { + SELECT_NODE = 1, + SET_OPERATION_NODE = 2, + BOUND_SUBQUERY_NODE = 3, + RECURSIVE_CTE_NODE = 4 +}; + +struct CommonTableExpressionInfo; + +class CommonTableExpressionMap { +public: + CommonTableExpressionMap(); + + unordered_map> map; + +public: + string ToString() const; + CommonTableExpressionMap Copy() const; +}; + +class QueryNode { +public: + explicit QueryNode(QueryNodeType type) : type(type) { + } + virtual ~QueryNode() { + } + + //! The type of the query node, either SetOperation or Select + QueryNodeType type; + //! The set of result modifiers associated with this query node + vector> modifiers; + //! CTEs (used by SelectNode and SetOperationNode) + CommonTableExpressionMap cte_map; + + virtual const vector> &GetSelectList() const = 0; + +public: + //! Convert the query node to a string + virtual string ToString() const = 0; + + virtual bool Equals(const QueryNode *other) const; + + //! Create a copy of this QueryNode + virtual unique_ptr Copy() const = 0; + //! Serializes a QueryNode to a stand-alone binary blob + DUCKDB_API void Serialize(Serializer &serializer) const; + //! Serializes a QueryNode to a stand-alone binary blob + DUCKDB_API virtual void Serialize(FieldWriter &writer) const = 0; + //! Deserializes a blob back into a QueryNode + DUCKDB_API static unique_ptr Deserialize(Deserializer &source); + + string ResultModifiersToString() const; + +protected: + //! Copy base QueryNode properties from another expression to this one, + //! used in Copy method + void CopyProperties(QueryNode &other) const; +}; + +} // namespace duckdb + + + + +namespace duckdb { +class BoundResultModifier; +class BoundSelectNode; +class ClientContext; +class ExpressionBinder; +class LimitModifier; +class OrderBinder; +class TableCatalogEntry; +class ViewCatalogEntry; +class TableMacroCatalogEntry; + +struct CreateInfo; +struct BoundCreateTableInfo; +struct BoundCreateFunctionInfo; +struct CommonTableExpressionInfo; +struct BoundParameterMap; + +enum class BindingMode : uint8_t { STANDARD_BINDING, EXTRACT_NAMES }; + +struct CorrelatedColumnInfo { + ColumnBinding binding; + LogicalType type; + string name; + idx_t depth; + + CorrelatedColumnInfo(ColumnBinding binding, LogicalType type_p, string name_p, idx_t depth) + : binding(binding), type(move(type_p)), name(move(name_p)), depth(depth) { + } + explicit CorrelatedColumnInfo(BoundColumnRefExpression &expr) + : CorrelatedColumnInfo(expr.binding, expr.return_type, expr.GetName(), expr.depth) { + } + + bool operator==(const CorrelatedColumnInfo &rhs) const { + return binding == rhs.binding; + } +}; + +//! Bind the parsed query tree to the actual columns present in the catalog. +/*! + The binder is responsible for binding tables and columns to actual physical + tables and columns in the catalog. In the process, it also resolves types of + all expressions. +*/ +class Binder : public std::enable_shared_from_this { + friend class ExpressionBinder; + friend class SelectBinder; + friend class RecursiveSubqueryPlanner; + +public: + static shared_ptr CreateBinder(ClientContext &context, Binder *parent = nullptr, bool inherit_ctes = true); + + //! The client context + ClientContext &context; + //! A mapping of names to common table expressions + case_insensitive_map_t CTE_bindings; + //! The CTEs that have already been bound + unordered_set bound_ctes; + //! The bind context + BindContext bind_context; + //! The set of correlated columns bound by this binder (FIXME: this should probably be an unordered_set and not a + //! vector) + vector correlated_columns; + //! The set of parameter expressions bound by this binder + BoundParameterMap *parameters; + //! Statement properties + StatementProperties properties; + //! The alias for the currently processing subquery, if it exists + string alias; + //! Macro parameter bindings (if any) + DummyBinding *macro_binding = nullptr; + //! The intermediate lambda bindings to bind nested lambdas (if any) + vector *lambda_bindings = nullptr; + +public: + BoundStatement Bind(SQLStatement &statement); + BoundStatement Bind(QueryNode &node); + + unique_ptr BindCreateTableInfo(unique_ptr info); + void BindCreateViewInfo(CreateViewInfo &base); + SchemaCatalogEntry *BindSchema(CreateInfo &info); + SchemaCatalogEntry *BindCreateFunctionInfo(CreateInfo &info); + + //! Check usage, and cast named parameters to their types + static void BindNamedParameters(named_parameter_type_map_t &types, named_parameter_map_t &values, + QueryErrorContext &error_context, string &func_name); + + unique_ptr Bind(TableRef &ref); + unique_ptr CreatePlan(BoundTableRef &ref); -enum class SampleMethod : uint8_t { SYSTEM_SAMPLE = 0, BERNOULLI_SAMPLE = 1, RESERVOIR_SAMPLE = 2 }; + //! Generates an unused index for a table + idx_t GenerateTableIndex(); -string SampleMethodToString(SampleMethod method); + //! Add a common table expression to the binder + void AddCTE(const string &name, CommonTableExpressionInfo *cte); + //! Find a common table expression by name; returns nullptr if none exists + CommonTableExpressionInfo *FindCTE(const string &name, bool skip = false); -struct SampleOptions { - Value sample_size; - bool is_percentage; - SampleMethod method; - int64_t seed = -1; + bool CTEIsAlreadyBound(CommonTableExpressionInfo *cte); - unique_ptr Copy(); - void Serialize(Serializer &serializer); - static unique_ptr Deserialize(Deserializer &source); - static bool Equals(SampleOptions *a, SampleOptions *b); -}; + //! Add the view to the set of currently bound views - used for detecting recursive view definitions + void AddBoundView(ViewCatalogEntry *view); -} // namespace duckdb + void PushExpressionBinder(ExpressionBinder *binder); + void PopExpressionBinder(); + void SetActiveBinder(ExpressionBinder *binder); + ExpressionBinder *GetActiveBinder(); + bool HasActiveBinder(); + vector &GetActiveBinders(); -namespace duckdb { -class Deserializer; -class Serializer; + void MergeCorrelatedColumns(vector &other); + //! Add a correlated column to this binder (if it does not exist) + void AddCorrelatedColumn(const CorrelatedColumnInfo &info); -//! Represents a generic expression that returns a table. -class TableRef { -public: - explicit TableRef(TableReferenceType type) : type(type) { + string FormatError(ParsedExpression &expr_context, const string &message); + string FormatError(TableRef &ref_context, const string &message); + + string FormatErrorRecursive(idx_t query_location, const string &message, vector &values); + template + string FormatErrorRecursive(idx_t query_location, const string &msg, vector &values, T param, + Args... params) { + values.push_back(ExceptionFormatValue::CreateFormatValue(param)); + return FormatErrorRecursive(query_location, msg, values, params...); } - virtual ~TableRef() { + + template + string FormatError(idx_t query_location, const string &msg, Args... params) { + vector values; + return FormatErrorRecursive(query_location, msg, values, params...); } - TableReferenceType type; - string alias; - //! Sample options (if any) - unique_ptr sample; - //! The location in the query (if any) - idx_t query_location = DConstants::INVALID_INDEX; + static void BindLogicalType(ClientContext &context, LogicalType &type, const string &schema = ""); -public: - //! Convert the object to a string - virtual string ToString() const = 0; - string BaseToString(string result) const; - string BaseToString(string result, const vector &column_name_alias) const; - void Print(); + bool HasMatchingBinding(const string &table_name, const string &column_name, string &error_message); + bool HasMatchingBinding(const string &schema_name, const string &table_name, const string &column_name, + string &error_message); - virtual bool Equals(const TableRef *other) const; + void SetBindingMode(BindingMode mode); + BindingMode GetBindingMode(); + void AddTableName(string table_name); + const unordered_set &GetTableNames(); - virtual unique_ptr Copy() = 0; + void SetCanContainNulls(bool can_contain_nulls); - //! Serializes a TableRef to a stand-alone binary blob - DUCKDB_API void Serialize(Serializer &serializer) const; - //! Serializes a TableRef to a stand-alone binary blob - DUCKDB_API virtual void Serialize(FieldWriter &writer) const = 0; - //! Deserializes a blob back into a TableRef - DUCKDB_API static unique_ptr Deserialize(Deserializer &source); +private: + //! The parent binder (if any) + shared_ptr parent; + //! The vector of active binders + vector active_binders; + //! The count of bound_tables + idx_t bound_tables; + //! Whether or not the binder has any unplanned subqueries that still need to be planned + bool has_unplanned_subqueries = false; + //! Whether or not subqueries should be planned already + bool plan_subquery = true; + //! Whether CTEs should reference the parent binder (if it exists) + bool inherit_ctes = true; + //! Whether or not the binder can contain NULLs as the root of expressions + bool can_contain_nulls = false; + //! The root statement of the query that is currently being parsed + SQLStatement *root_statement = nullptr; + //! Binding mode + BindingMode mode = BindingMode::STANDARD_BINDING; + //! Table names extracted for BindingMode::EXTRACT_NAMES + unordered_set table_names; + //! The set of bound views + unordered_set bound_views; - //! Copy the properties of this table ref to the target - void CopyProperties(TableRef &target) const; -}; -} // namespace duckdb +private: + //! Bind the expressions of generated columns to check for errors + void BindGeneratedColumns(BoundCreateTableInfo &info); + //! Bind the default values of the columns of a table + void BindDefaultValues(vector &columns, vector> &bound_defaults); + //! Bind a limit value (LIMIT or OFFSET) + unique_ptr BindDelimiter(ClientContext &context, OrderBinder &order_binder, + unique_ptr delimiter, const LogicalType &type, + Value &delimiter_value); + //! Move correlated expressions from the child binder to this binder + void MoveCorrelatedExpressions(Binder &other); -namespace duckdb { + BoundStatement Bind(SelectStatement &stmt); + BoundStatement Bind(InsertStatement &stmt); + BoundStatement Bind(CopyStatement &stmt); + BoundStatement Bind(DeleteStatement &stmt); + BoundStatement Bind(UpdateStatement &stmt); + BoundStatement Bind(CreateStatement &stmt); + BoundStatement Bind(DropStatement &stmt); + BoundStatement Bind(AlterStatement &stmt); + BoundStatement Bind(PrepareStatement &stmt); + BoundStatement Bind(ExecuteStatement &stmt); + BoundStatement Bind(TransactionStatement &stmt); + BoundStatement Bind(PragmaStatement &stmt); + BoundStatement Bind(ExplainStatement &stmt); + BoundStatement Bind(VacuumStatement &stmt); + BoundStatement Bind(RelationStatement &stmt); + BoundStatement Bind(ShowStatement &stmt); + BoundStatement Bind(CallStatement &stmt); + BoundStatement Bind(ExportStatement &stmt); + BoundStatement Bind(ExtensionStatement &stmt); + BoundStatement Bind(SetStatement &stmt); + BoundStatement Bind(LoadStatement &stmt); + BoundStatement Bind(LogicalPlanStatement &stmt); -class QueryNode; + BoundStatement BindReturning(vector> returning_list, TableCatalogEntry *table, + idx_t update_table_index, unique_ptr child_operator, + BoundStatement result); -//! SelectStatement is a typical SELECT clause -class SelectStatement : public SQLStatement { -public: - SelectStatement() : SQLStatement(StatementType::SELECT_STATEMENT) { - } + unique_ptr BindTableMacro(FunctionExpression &function, TableMacroCatalogEntry *macro_func, idx_t depth); - //! The main query node - unique_ptr node; + unique_ptr BindNode(SelectNode &node); + unique_ptr BindNode(SetOperationNode &node); + unique_ptr BindNode(RecursiveCTENode &node); + unique_ptr BindNode(QueryNode &node); -protected: - SelectStatement(const SelectStatement &other); + unique_ptr VisitQueryNode(BoundQueryNode &node, unique_ptr root); + unique_ptr CreatePlan(BoundRecursiveCTENode &node); + unique_ptr CreatePlan(BoundSelectNode &statement); + unique_ptr CreatePlan(BoundSetOperationNode &node); + unique_ptr CreatePlan(BoundQueryNode &node); -public: - //! Convert the SELECT statement to a string - string ToString() const override; - //! Create a copy of this SelectStatement - unique_ptr Copy() const override; - //! Serializes a SelectStatement to a stand-alone binary blob - void Serialize(Serializer &serializer) const; - //! Deserializes a blob back into a SelectStatement, returns nullptr if - //! deserialization is not possible - static unique_ptr Deserialize(Deserializer &source); - //! Whether or not the statements are equivalent - bool Equals(const SQLStatement *other) const; -}; -} // namespace duckdb + unique_ptr Bind(BaseTableRef &ref); + unique_ptr Bind(CrossProductRef &ref); + unique_ptr Bind(JoinRef &ref); + unique_ptr Bind(SubqueryRef &ref, CommonTableExpressionInfo *cte = nullptr); + unique_ptr Bind(TableFunctionRef &ref); + unique_ptr Bind(EmptyTableRef &ref); + unique_ptr Bind(ExpressionListRef &ref); + bool BindTableFunctionParameters(TableFunctionCatalogEntry &table_function, + vector> &expressions, vector &arguments, + vector ¶meters, named_parameter_map_t &named_parameters, + unique_ptr &subquery, string &error); + bool BindTableInTableOutFunction(vector> &expressions, + unique_ptr &subquery, string &error); + unique_ptr BindTableFunction(TableFunction &function, vector parameters); + unique_ptr + BindTableFunctionInternal(TableFunction &table_function, const string &function_name, vector parameters, + named_parameter_map_t named_parameters, vector input_table_types, + vector input_table_names, const vector &column_name_alias, + unique_ptr external_dependency); -namespace duckdb { + unique_ptr CreatePlan(BoundBaseTableRef &ref); + unique_ptr CreatePlan(BoundCrossProductRef &ref); + unique_ptr CreatePlan(BoundJoinRef &ref); + unique_ptr CreatePlan(BoundSubqueryRef &ref); + unique_ptr CreatePlan(BoundTableFunction &ref); + unique_ptr CreatePlan(BoundEmptyTableRef &ref); + unique_ptr CreatePlan(BoundExpressionListRef &ref); + unique_ptr CreatePlan(BoundCTERef &ref); -class SelectStatement; + BoundStatement BindCopyTo(CopyStatement &stmt); + BoundStatement BindCopyFrom(CopyStatement &stmt); -struct CommonTableExpressionInfo { - vector aliases; - unique_ptr query; -}; + void BindModifiers(OrderBinder &order_binder, QueryNode &statement, BoundQueryNode &result); + void BindModifierTypes(BoundQueryNode &result, const vector &sql_types, idx_t projection_index); -} // namespace duckdb + BoundStatement BindSummarize(ShowStatement &stmt); + unique_ptr BindLimit(OrderBinder &order_binder, LimitModifier &limit_mod); + unique_ptr BindLimitPercent(OrderBinder &order_binder, LimitPercentModifier &limit_mod); + unique_ptr BindOrderExpression(OrderBinder &order_binder, unique_ptr expr); + unique_ptr PlanFilter(unique_ptr condition, unique_ptr root); -namespace duckdb { + void PlanSubqueries(unique_ptr *expr, unique_ptr *root); + unique_ptr PlanSubquery(BoundSubqueryExpression &expr, unique_ptr &root); -enum QueryNodeType : uint8_t { - SELECT_NODE = 1, - SET_OPERATION_NODE = 2, - BOUND_SUBQUERY_NODE = 3, - RECURSIVE_CTE_NODE = 4 -}; + unique_ptr CastLogicalOperatorToTypes(vector &source_types, + vector &target_types, + unique_ptr op); -class QueryNode { -public: - explicit QueryNode(QueryNodeType type) : type(type) { - } - virtual ~QueryNode() { - } + string FindBinding(const string &using_column, const string &join_side); + bool TryFindBinding(const string &using_column, const string &join_side, string &result); - //! The type of the query node, either SetOperation or Select - QueryNodeType type; - //! The set of result modifiers associated with this query node - vector> modifiers; - //! CTEs (used by SelectNode and SetOperationNode) - unordered_map> cte_map; + void AddUsingBindingSet(unique_ptr set); + string RetrieveUsingBinding(Binder ¤t_binder, UsingColumnSet *current_set, const string &column_name, + const string &join_side, UsingColumnSet *new_set); - virtual const vector> &GetSelectList() const = 0; + void AddCTEMap(CommonTableExpressionMap &cte_map); public: - //! Convert the query node to a string - virtual string ToString() const = 0; + // This should really be a private constructor, but make_shared does not allow it... + // If you are thinking about calling this, you should probably call Binder::CreateBinder + Binder(bool I_know_what_I_am_doing, ClientContext &context, shared_ptr parent, bool inherit_ctes); +}; + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/planner/bound_query_node.hpp +// +// +//===----------------------------------------------------------------------===// - virtual bool Equals(const QueryNode *other) const; - //! Create a copy of this QueryNode - virtual unique_ptr Copy() const = 0; - //! Serializes a QueryNode to a stand-alone binary blob - DUCKDB_API void Serialize(Serializer &serializer) const; - //! Serializes a QueryNode to a stand-alone binary blob - DUCKDB_API virtual void Serialize(FieldWriter &writer) const = 0; - //! Deserializes a blob back into a QueryNode - DUCKDB_API static unique_ptr Deserialize(Deserializer &source); - string CTEToString() const; - string ResultModifiersToString() const; -protected: - //! Copy base QueryNode properties from another expression to this one, - //! used in Copy method - void CopyProperties(QueryNode &other) const; -}; -} // namespace duckdb namespace duckdb { @@ -14475,6 +16852,9 @@ class BoundSubqueryExpression : public Expression { unique_ptr Copy() override; bool PropagatesNullValues() const override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -14507,6 +16887,9 @@ class BoundUnnestExpression : public Expression { bool Equals(const BaseExpression *other) const override; unique_ptr Copy() override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -14774,6 +17157,9 @@ class BoundWindowExpression : public Expression { bool Equals(const BaseExpression *other) const override; unique_ptr Copy() override; + + void Serialize(FieldWriter &writer) const override; + static unique_ptr Deserialize(ExpressionDeserializationState &state, FieldReader &reader); }; } // namespace duckdb @@ -14827,7 +17213,7 @@ struct IndexScanState { } }; -typedef unordered_map> buffer_handle_set_t; +typedef unordered_map buffer_handle_set_t; struct ColumnScanState { //! The column segment that is currently being scanned @@ -14859,6 +17245,8 @@ struct ColumnFetchState { buffer_handle_set_t handles; //! Any child states of the fetch vector> child_states; + + BufferHandle &GetOrInsertHandle(ColumnSegment &segment); }; struct LocalScanState { @@ -14880,7 +17268,7 @@ struct LocalScanState { class RowGroupScanState { public: - RowGroupScanState(TableScanState &parent_p) : parent(parent_p), vector_index(0), max_row(0) { + RowGroupScanState(TableScanState &parent_p) : parent(parent_p), row_group(nullptr), vector_index(0), max_row(0) { } //! The parent scan state @@ -14934,6 +17322,8 @@ class LocalTableStorage : public std::enable_shared_from_this ~LocalTableStorage(); DataTable &table; + + Allocator &allocator; //! The main chunk collection holding the data ChunkCollection collection; //! The set of unique indexes @@ -15000,6 +17390,7 @@ class LocalStorage { void ChangeType(DataTable *old_dt, DataTable *new_dt, idx_t changed_idx, const LogicalType &target_type, const vector &bound_columns, Expression &cast_expr); + void MoveStorage(DataTable *old_dt, DataTable *new_dt); void FetchChunk(DataTable *table, Vector &row_ids, idx_t count, DataChunk &chunk); vector> &GetIndexes(DataTable *table); @@ -15041,11 +17432,7 @@ struct UpdateInfo; class Transaction { public: Transaction(weak_ptr context, transaction_t start_time, transaction_t transaction_id, - timestamp_t start_timestamp, idx_t catalog_version) - : context(move(context)), start_time(start_time), transaction_id(transaction_id), commit_id(0), - highest_active_query(0), active_query(MAXIMUM_QUERY_ID), start_timestamp(start_timestamp), - catalog_version(catalog_version), storage(*this), is_invalidated(false) { - } + timestamp_t start_timestamp, idx_t catalog_version); weak_ptr context; //! The start timestamp of this transaction @@ -15357,6 +17744,7 @@ namespace duckdb { using std::deque; } + //===----------------------------------------------------------------------===// // DuckDB // @@ -15598,6 +17986,7 @@ typedef struct { typedef void *duckdb_database; typedef void *duckdb_connection; typedef void *duckdb_prepared_statement; +typedef void *duckdb_pending_result; typedef void *duckdb_appender; typedef void *duckdb_arrow; typedef void *duckdb_config; @@ -15609,6 +17998,11 @@ typedef void *duckdb_vector; typedef void *duckdb_value; typedef enum { DuckDBSuccess = 0, DuckDBError = 1 } duckdb_state; +typedef enum { + DUCKDB_PENDING_RESULT_READY = 0, + DUCKDB_PENDING_RESULT_NOT_READY = 1, + DUCKDB_PENDING_ERROR = 2 +} duckdb_pending_state; //===--------------------------------------------------------------------===// // Open/Connect @@ -15857,7 +18251,7 @@ Returns the error message contained within the result. The error is only set if The result of this function must not be freed. It will be cleaned up when `duckdb_destroy_result` is called. -* result: The result object to fetch the nullmask from. +* result: The result object to fetch the error from. * returns: The error of the result. */ DUCKDB_API const char *duckdb_result_error(duckdb_result *result); @@ -16184,6 +18578,11 @@ Returns `DUCKDB_TYPE_INVALID` if the parameter index is out of range or the stat */ DUCKDB_API duckdb_type duckdb_param_type(duckdb_prepared_statement prepared_statement, idx_t param_idx); +/*! +Clear the params bind to the prepared statement. +*/ +DUCKDB_API duckdb_state duckdb_clear_bindings(duckdb_prepared_statement prepared_statement); + /*! Binds a bool value to the prepared statement at the specified index. */ @@ -16315,6 +18714,67 @@ Executes the prepared statement with the given bound parameters, and returns an DUCKDB_API duckdb_state duckdb_execute_prepared_arrow(duckdb_prepared_statement prepared_statement, duckdb_arrow *out_result); +//===--------------------------------------------------------------------===// +// Pending Result Interface +//===--------------------------------------------------------------------===// +/*! +Executes the prepared statement with the given bound parameters, and returns a pending result. +The pending result represents an intermediate structure for a query that is not yet fully executed. +The pending result can be used to incrementally execute a query, returning control to the client between tasks. + +Note that after calling `duckdb_pending_prepared`, the pending result should always be destroyed using +`duckdb_destroy_pending`, even if this function returns DuckDBError. + +* prepared_statement: The prepared statement to execute. +* out_result: The pending query result. +* returns: `DuckDBSuccess` on success or `DuckDBError` on failure. +*/ +DUCKDB_API duckdb_state duckdb_pending_prepared(duckdb_prepared_statement prepared_statement, + duckdb_pending_result *out_result); + +/*! +Closes the pending result and de-allocates all memory allocated for the result. + +* pending_result: The pending result to destroy. +*/ +DUCKDB_API void duckdb_destroy_pending(duckdb_pending_result *pending_result); + +/*! +Returns the error message contained within the pending result. + +The result of this function must not be freed. It will be cleaned up when `duckdb_destroy_pending` is called. + +* result: The pending result to fetch the error from. +* returns: The error of the pending result. +*/ +DUCKDB_API const char *duckdb_pending_error(duckdb_pending_result pending_result); + +/*! +Executes a single task within the query, returning whether or not the query is ready. + +If this returns DUCKDB_PENDING_RESULT_READY, the duckdb_execute_pending function can be called to obtain the result. +If this returns DUCKDB_PENDING_RESULT_NOT_READY, the duckdb_pending_execute_task function should be called again. +If this returns DUCKDB_PENDING_ERROR, an error occurred during execution. + +The error message can be obtained by calling duckdb_pending_error on the pending_result. + +* pending_result: The pending result to execute a task within.. +* returns: The state of the pending result after the execution. +*/ +DUCKDB_API duckdb_pending_state duckdb_pending_execute_task(duckdb_pending_result pending_result); + +/*! +Fully execute a pending query result, returning the final query result. + +If duckdb_pending_execute_task has been called until DUCKDB_PENDING_RESULT_READY was returned, this will return fast. +Otherwise, all remaining tasks must be executed first. + +* pending_result: The pending result to execute. +* out_result: The result object. +* returns: `DuckDBSuccess` on success or `DuckDBError` on failure. +*/ +DUCKDB_API duckdb_state duckdb_execute_pending(duckdb_pending_result pending_result, duckdb_result *out_result); + //===--------------------------------------------------------------------===// // Value Interface //===--------------------------------------------------------------------===// @@ -16908,6 +19368,14 @@ Sets the user-provided bind data in the bind object. This object can be retrieve */ DUCKDB_API void duckdb_bind_set_bind_data(duckdb_bind_info info, void *bind_data, duckdb_delete_callback_t destroy); +/*! +Sets the cardinality estimate for the table function, used for optimization. + +* info: The bind data object. +* is_exact: Whether or not the cardinality estimate is exact, or an approximation +*/ +DUCKDB_API void duckdb_bind_set_cardinality(duckdb_bind_info info, idx_t cardinality, bool is_exact); + /*! Report that an error has occurred while calling bind. @@ -17331,6 +19799,8 @@ DUCKDB_API void duckdb_destroy_arrow(duckdb_arrow *result); //===--------------------------------------------------------------------===// // Threading Information //===--------------------------------------------------------------------===// +typedef void *duckdb_task_state; + /*! Execute DuckDB tasks on this thread. @@ -17341,6 +19811,66 @@ Will return after `max_tasks` have been executed, or if there are no more tasks */ DUCKDB_API void duckdb_execute_tasks(duckdb_database database, idx_t max_tasks); +/*! +Creates a task state that can be used with duckdb_execute_tasks_state to execute tasks until + duckdb_finish_execution is called on the state. + +duckdb_destroy_state should be called on the result in order to free memory. + +* database: The database object to create the task state for +* returns: The task state that can be used with duckdb_execute_tasks_state. +*/ +DUCKDB_API duckdb_task_state duckdb_create_task_state(duckdb_database database); + +/*! +Execute DuckDB tasks on this thread. + +The thread will keep on executing tasks forever, until duckdb_finish_execution is called on the state. +Multiple threads can share the same duckdb_task_state. + +* state: The task state of the executor +*/ +DUCKDB_API void duckdb_execute_tasks_state(duckdb_task_state state); + +/*! +Execute DuckDB tasks on this thread. + +The thread will keep on executing tasks until either duckdb_finish_execution is called on the state, +max_tasks tasks have been executed or there are no more tasks to be executed. + +Multiple threads can share the same duckdb_task_state. + +* state: The task state of the executor +* max_tasks: The maximum amount of tasks to execute +* returns: The amount of tasks that have actually been executed +*/ +DUCKDB_API idx_t duckdb_execute_n_tasks_state(duckdb_task_state state, idx_t max_tasks); + +/*! +Finish execution on a specific task. + +* state: The task state to finish execution +*/ +DUCKDB_API void duckdb_finish_execution(duckdb_task_state state); + +/*! +Check if the provided duckdb_task_state has finished execution + +* state: The task state to inspect +* returns: Whether or not duckdb_finish_execution has been called on the task state +*/ +DUCKDB_API bool duckdb_task_state_is_finished(duckdb_task_state state); + +/*! +Destroys the task state returned from duckdb_create_task_state. + +Note that this should not be called while there is an active duckdb_execute_tasks_state running +on the task state. + +* state: The task state to clean up +*/ +DUCKDB_API void duckdb_destroy_task_state(duckdb_task_state state); + #ifdef __cplusplus } #endif @@ -17434,6 +19964,7 @@ class ProgressBar { + //===----------------------------------------------------------------------===// // DuckDB // @@ -17488,6 +20019,7 @@ class StreamQueryResult : public QueryResult { }; } // namespace duckdb + //===----------------------------------------------------------------------===// // DuckDB // @@ -17617,16 +20149,22 @@ typedef std::function(ClientContext &context get_result_collector_t; struct ClientConfig { + //! The home directory used by the system (if any) + string home_directory; //! If the query profiler is enabled or not. bool enable_profiler = false; //! If detailed query profiling is enabled bool enable_detailed_profiling = false; - //! The format to automatically print query profiling information in (default: disabled) - ProfilerPrintFormat profiler_print_format = ProfilerPrintFormat::NONE; + //! The format to print query profiling information in (default: query_tree), if enabled. + ProfilerPrintFormat profiler_print_format = ProfilerPrintFormat::QUERY_TREE; //! The file to save query profiling information to, instead of printing it to the console //! (empty = print to console) string profiler_save_location; + //! Allows suppressing profiler output, even if enabled. We turn on the profiler on all test runs but don't want + //! to output anything + bool emit_profiler_output = true; + //! If the progress bar is enabled or not. bool enable_progress_bar = false; //! If the print of the progress bar is enabled @@ -17640,8 +20178,12 @@ struct ClientConfig { //! The maximum expression depth limit in the parser idx_t max_expression_depth = 1000; - // Whether or not aggressive query verification is enabled + //! Whether or not aggressive query verification is enabled bool query_verification_enabled = false; + //! Whether or not verification of external operators is enabled, used for testing + bool verify_external = false; + //! Whether or not we should verify the serializer + bool verify_serializer = false; //! Enable the running of optimizers bool enable_optimizer = true; //! Force parallelism of small tables, used for testing @@ -17668,39 +20210,27 @@ struct ClientConfig { public: static ClientConfig &GetConfig(ClientContext &context); + static const ClientConfig &GetConfig(const ClientContext &context); static string ExtractTimezoneFromConfig(ClientConfig &config); -}; - -} // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/main/external_dependencies.hpp -// -// -//===----------------------------------------------------------------------===// + string ExtractTimezone() const; + bool AnyVerification() { + return query_verification_enabled || verify_external || verify_serializer; + } +}; +} // namespace duckdb -namespace duckdb { -enum ExternalDependenciesType { PYTHON_DEPENDENCY }; -class ExternalDependency { -public: - explicit ExternalDependency(ExternalDependenciesType type_p) : type(type_p) {}; - virtual ~ExternalDependency() {}; - ExternalDependenciesType type; -}; -} // namespace duckdb namespace duckdb { class Appender; class Catalog; class CatalogSearchPath; -class ChunkCollection; +class ColumnDataCollection; class DatabaseInstance; class FileOpener; class LogicalOperator; @@ -17778,7 +20308,7 @@ class ClientContext : public std::enable_shared_from_this { //! Get the table info of a specific table, or nullptr if it cannot be found DUCKDB_API unique_ptr TableInfo(const string &schema_name, const string &table_name); //! Appends a DataChunk to the specified table. Returns whether or not the append was successful. - DUCKDB_API void Append(TableDescription &description, ChunkCollection &collection); + DUCKDB_API void Append(TableDescription &description, ColumnDataCollection &collection); //! Try to bind a relation in the current client context; either throws an exception or fills the result_columns //! list with the set of returned columns DUCKDB_API void TryBindRelation(Relation &relation, vector &result_columns); @@ -17830,7 +20360,7 @@ class ClientContext : public std::enable_shared_from_this { DUCKDB_API bool TryGetCurrentSetting(const std::string &key, Value &result); //! Returns the parser options for this client context - DUCKDB_API ParserOptions GetParserOptions(); + DUCKDB_API ParserOptions GetParserOptions() const; DUCKDB_API unique_ptr Fetch(ClientContextLock &lock, StreamQueryResult &result); @@ -17846,10 +20376,12 @@ class ClientContext : public std::enable_shared_from_this { //! Fetch a list of table names that are required for a given query DUCKDB_API unordered_set GetTableNames(const string &query); + DUCKDB_API ClientProperties GetClientProperties() const; + private: //! Parse statements and resolve pragmas from a query bool ParseStatements(ClientContextLock &lock, const string &query, vector> &result, - string &error); + PreservedError &error); //! Issues a query to the database and returns a Pending Query Result unique_ptr PendingQueryInternal(ClientContextLock &lock, unique_ptr statement, PendingQueryParameters parameters, bool verify = true); @@ -17859,7 +20391,7 @@ class ClientContext : public std::enable_shared_from_this { vector> ParseStatementsInternal(ClientContextLock &lock, const string &query); //! Perform aggressive query verification of a SELECT statement. Only called when query_verification_enabled is //! true. - string VerifyQuery(ClientContextLock &lock, const string &query, unique_ptr statement); + PreservedError VerifyQuery(ClientContextLock &lock, const string &query, unique_ptr statement); void InitialCleanup(ClientContextLock &lock); //! Internal clean up, does not lock. Caller must hold the context_lock. @@ -17891,11 +20423,9 @@ class ClientContext : public std::enable_shared_from_this { unique_ptr LockContext(); - bool UpdateFunctionInfoFromEntry(ScalarFunctionCatalogEntry *existing_function, CreateScalarFunctionInfo *new_info); - void BeginTransactionInternal(ClientContextLock &lock, bool requires_valid_transaction); void BeginQueryInternal(ClientContextLock &lock, const string &query); - string EndQueryInternal(ClientContextLock &lock, bool success, bool invalidate_transaction); + PreservedError EndQueryInternal(ClientContextLock &lock, bool success, bool invalidate_transaction); PendingExecutionResult ExecuteTaskInternal(ClientContextLock &lock, PendingQueryResult &result); @@ -17937,7 +20467,7 @@ class ClientContextWrapper { shared_ptr GetContext() { auto actual_context = client_context.lock(); if (!actual_context) { - throw std::runtime_error("This connection is closed"); + throw ConnectionException("Connection has already been closed"); } return actual_context; } @@ -18086,9 +20616,10 @@ class Relation : public std::enable_shared_from_this { + namespace duckdb { -class ChunkCollection; +class ColumnDataCollection; class ClientContext; class DatabaseInstance; @@ -18171,8 +20702,8 @@ class Connection { //! Appends a DataChunk to the specified table DUCKDB_API void Append(TableDescription &description, DataChunk &chunk); - //! Appends a ChunkCollection to the specified table - DUCKDB_API void Append(TableDescription &description, ChunkCollection &collection); + //! Appends a ColumnDataCollection to the specified table + DUCKDB_API void Append(TableDescription &description, ColumnDataCollection &collection); //! Returns a relation that produces a table from this connection DUCKDB_API shared_ptr Table(const string &tname); @@ -18206,6 +20737,7 @@ class Connection { DUCKDB_API void Rollback(); DUCKDB_API void SetAutoCommit(bool auto_commit); DUCKDB_API bool IsAutoCommit(); + DUCKDB_API bool HasActiveTransaction(); //! Fetch a list of table names that are required for a given query DUCKDB_API unordered_set GetTableNames(const string &query); @@ -18293,113 +20825,23 @@ class Connection { // // duckdb/main/database.hpp // -// -//===----------------------------------------------------------------------===// - - - - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/main/config.hpp -// -// -//===----------------------------------------------------------------------===// - - - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/allocator.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - -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; - } - idx_t GetSize() const { - return allocated_size; - } - void Reset(); - -private: - Allocator &allocator; - data_ptr_t pointer; - idx_t allocated_size; -}; - -class Allocator { -public: - DUCKDB_API Allocator(); - DUCKDB_API Allocator(allocate_function_ptr_t allocate_function_p, free_function_ptr_t free_function_p, - reallocate_function_ptr_t reallocate_function_p, - unique_ptr private_data); - - DUCKDB_API Allocator &operator=(Allocator &&allocator) noexcept = default; - - 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 Allocate(idx_t size) { - return make_unique(*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 private_data; -}; -} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/main/config.hpp +// +// +//===----------------------------------------------------------------------===// + + + @@ -18477,7 +20919,8 @@ enum class OptimizerType : uint32_t { COMMON_AGGREGATE, COLUMN_LIFETIME, TOP_N, - REORDER_FILTER + REORDER_FILTER, + EXTENSION }; string OptimizerTypeToString(OptimizerType type); @@ -18533,6 +20976,136 @@ enum class SetScope : uint8_t { } // namespace duckdb +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/parser_extension.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + + +namespace duckdb { + +//! The ParserExtensionInfo holds static information relevant to the parser extension +//! It is made available in the parse_function, and will be kept alive as long as the database system is kept alive +struct ParserExtensionInfo { + DUCKDB_API virtual ~ParserExtensionInfo() { + } +}; + +//===--------------------------------------------------------------------===// +// Parse +//===--------------------------------------------------------------------===// +enum class ParserExtensionResultType : uint8_t { PARSE_SUCCESSFUL, DISPLAY_ORIGINAL_ERROR, DISPLAY_EXTENSION_ERROR }; + +//! The ParserExtensionParseData holds the result of a successful parse step +//! It will be passed along to the subsequent plan function +struct ParserExtensionParseData { + DUCKDB_API virtual ~ParserExtensionParseData() { + } + + virtual unique_ptr Copy() const = 0; +}; + +struct ParserExtensionParseResult { + ParserExtensionParseResult() : type(ParserExtensionResultType::DISPLAY_ORIGINAL_ERROR) { + } + ParserExtensionParseResult(string error_p) + : type(ParserExtensionResultType::DISPLAY_EXTENSION_ERROR), error(move(error_p)) { + } + ParserExtensionParseResult(unique_ptr parse_data_p) + : type(ParserExtensionResultType::PARSE_SUCCESSFUL), parse_data(move(parse_data_p)) { + } + + //! Whether or not parsing was successful + ParserExtensionResultType type; + //! The parse data (if successful) + unique_ptr parse_data; + //! The error message (if unsuccessful) + string error; +}; + +typedef ParserExtensionParseResult (*parse_function_t)(ParserExtensionInfo *info, const string &query); +//===--------------------------------------------------------------------===// +// Plan +//===--------------------------------------------------------------------===// +struct ParserExtensionPlanResult { + //! The table function to execute + TableFunction function; + //! Parameters to the function + vector parameters; + //! Whether or not the statement is read_only (i.e. can be executed in a read_only database) + bool read_only = false; + //! Whether or not the statement requires a valid transaction to be executed + bool requires_valid_transaction = true; + //! What type of result set the statement returns + StatementReturnType return_type = StatementReturnType::NOTHING; +}; + +typedef ParserExtensionPlanResult (*plan_function_t)(ParserExtensionInfo *info, ClientContext &context, + unique_ptr parse_data); + +//===--------------------------------------------------------------------===// +// ParserExtension +//===--------------------------------------------------------------------===// +class ParserExtension { +public: + //! The parse function of the parser extension. + //! Takes a query string as input and returns ParserExtensionParseData (on success) or an error + parse_function_t parse_function; + + //! The plan function of the parser extension + //! Takes as input the result of the parse_function, and outputs various properties of the resulting plan + plan_function_t plan_function; + + //! Additional parser info passed to the parse function + shared_ptr parser_info; +}; + +} // namespace duckdb + +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/parser/parser_extension.hpp +// +// +//===----------------------------------------------------------------------===// + + + + + + +namespace duckdb { + +//! The OptimizerExtensionInfo holds static information relevant to the optimizer extension +struct OptimizerExtensionInfo { + DUCKDB_API virtual ~OptimizerExtensionInfo() { + } +}; + +typedef void (*optimize_function_t)(ClientContext &context, OptimizerExtensionInfo *info, + unique_ptr &plan); + +class OptimizerExtension { +public: + //! The parse function of the parser extension. + //! Takes a query string as input and returns ParserExtensionParseData (on success) or an error + optimize_function_t optimize_function; + + //! Additional parser info passed to the parse function + shared_ptr optimizer_info; +}; + +} // namespace duckdb + namespace duckdb { class ClientContext; @@ -18576,27 +21149,15 @@ struct ExtensionOption { set_option_callback_t set_function; }; -struct DBConfig { - friend class DatabaseInstance; - friend class StorageManager; - -public: - DUCKDB_API DBConfig(); - DUCKDB_API ~DBConfig(); - +struct DBConfigOptions { //! Access mode of the database (AUTOMATIC, READ_ONLY or READ_WRITE) AccessMode access_mode = AccessMode::AUTOMATIC; - //! The allocator used by the system - Allocator allocator; - // Checkpoint when WAL reaches this size (default: 16MB) + //! Checkpoint when WAL reaches this size (default: 16MB) idx_t checkpoint_wal_size = 1 << 24; //! Whether or not to use Direct IO, bypassing operating system buffers bool use_direct_io = false; //! Whether extensions should be loaded on start-up bool load_extensions = true; - //! The FileSystem to use, can be overwritten to allow for injecting custom file systems for testing purposes (e.g. - //! RamFS or something similar) - unique_ptr file_system; //! The maximum memory used by the database system (in bytes). Default: 80% of System available memory idx_t maximum_memory = (idx_t)-1; //! The maximum amount of CPU threads used by the database system. Default: all available. @@ -18623,8 +21184,6 @@ struct DBConfig { bool checkpoint_on_shutdown = true; //! Debug flag that decides when a checkpoing should be aborted. Only used for testing purposes. CheckpointAbort checkpoint_abort = CheckpointAbort::NO_ABORT; - //! Replacement table scans are automatically attempted when a table name cannot be found in the schema - vector replacement_scans; //! Initialize the database with the standard set of DuckDB functions //! You should probably not touch this unless you know what you are doing bool initialize_default_database = true; @@ -18638,11 +21197,34 @@ struct DBConfig { WindowAggregationMode window_mode = WindowAggregationMode::WINDOW; //! Whether or not preserving insertion order should be preserved bool preserve_insertion_order = true; + //! Database configuration variables as controlled by SET + case_insensitive_map_t set_variables; + //! Whether unsigned extensions should be loaded + bool allow_unsigned_extensions = false; +}; +struct DBConfig { + friend class DatabaseInstance; + friend class StorageManager; + +public: + DUCKDB_API DBConfig(); + DUCKDB_API ~DBConfig(); + //! Replacement table scans are automatically attempted when a table name cannot be found in the schema + vector replacement_scans; //! Extra parameters that can be SET for loaded extensions case_insensitive_map_t extension_parameters; - //! Database configuration variables as controlled by SET - case_insensitive_map_t set_variables; + //! The FileSystem to use, can be overwritten to allow for injecting custom file systems for testing purposes (e.g. + //! RamFS or something similar) + unique_ptr file_system; + //! The allocator used by the system + unique_ptr allocator; + //! Database configuration options + DBConfigOptions options; + + //! Extensions made to the parser + vector parser_extensions; + vector optimizer_extensions; DUCKDB_API void AddExtensionOption(string name, string description, LogicalType parameter, set_option_callback_t function = nullptr); @@ -18650,6 +21232,8 @@ struct DBConfig { public: DUCKDB_API static DBConfig &GetConfig(ClientContext &context); DUCKDB_API static DBConfig &GetConfig(DatabaseInstance &db); + DUCKDB_API static const DBConfig &GetConfig(const ClientContext &context); + DUCKDB_API static const DBConfig &GetConfig(const DatabaseInstance &db); DUCKDB_API static vector GetOptions(); DUCKDB_API static idx_t GetOptionCount(); @@ -18700,6 +21284,7 @@ class Extension { } // namespace duckdb + namespace duckdb { class StorageManager; class Catalog; @@ -18726,11 +21311,17 @@ class DatabaseInstance : public std::enable_shared_from_this { DUCKDB_API TaskScheduler &GetScheduler(); DUCKDB_API ObjectCache &GetObjectCache(); DUCKDB_API ConnectionManager &GetConnectionManager(); + DUCKDB_API void Invalidate(); + DUCKDB_API bool IsInvalidated(); idx_t NumberOfThreads(); DUCKDB_API static DatabaseInstance &GetDatabase(ClientContext &context); + DUCKDB_API const unordered_set &LoadedExtensions(); + + DUCKDB_API bool TryGetCurrentSetting(const std::string &key, Value &result); + private: void Initialize(const char *path, DBConfig *config); @@ -18744,6 +21335,8 @@ class DatabaseInstance : public std::enable_shared_from_this { unique_ptr object_cache; unique_ptr connection_manager; unordered_set loaded_extensions; + //! Set to true if a fatal exception has occurred + bool is_invalidated = false; }; //! The database object. This object holds the catalog and all the @@ -18842,6 +21435,7 @@ ExternC const PfnDliHook __pfnDliFailureHook2 = duckdb_dllimport_delay_hook; } #endif #endif + //===----------------------------------------------------------------------===// // DuckDB // @@ -18862,6 +21456,10 @@ namespace duckdb { //! The Date class is a static class that holds helper functions for the Date type. class Date { public: + static const char *PINF; // NOLINT + static const char *NINF; // NOLINT + static const char *EPOCH; // NOLINT + static const string_t MONTH_NAMES[12]; static const string_t MONTH_NAMES_ABBREVIATED[12]; static const string_t DAY_NAMES[7]; @@ -19002,32 +21600,32 @@ class Blob { public: //! Returns the string size of a blob -> string conversion - static idx_t GetStringSize(string_t blob); + DUCKDB_API static idx_t GetStringSize(string_t blob); //! Converts a blob to a string, writing the output to the designated output string. //! The string needs to have space for at least GetStringSize(blob) bytes. - static void ToString(string_t blob, char *output); + DUCKDB_API static void ToString(string_t blob, char *output); //! Convert a blob object to a string - static string ToString(string_t blob); + DUCKDB_API static string ToString(string_t blob); //! Returns the blob size of a string -> blob conversion - static bool TryGetBlobSize(string_t str, idx_t &result_size, string *error_message); - static idx_t GetBlobSize(string_t str); + DUCKDB_API static bool TryGetBlobSize(string_t str, idx_t &result_size, string *error_message); + DUCKDB_API static idx_t GetBlobSize(string_t str); //! Convert a string to a blob. This function should ONLY be called after calling GetBlobSize, since it does NOT //! perform data validation. - static void ToBlob(string_t str, data_ptr_t output); + DUCKDB_API static void ToBlob(string_t str, data_ptr_t output); //! Convert a string object to a blob - static string ToBlob(string_t str); + DUCKDB_API static string ToBlob(string_t str); // base 64 conversion functions //! Returns the string size of a blob -> base64 conversion - static idx_t ToBase64Size(string_t blob); + DUCKDB_API static idx_t ToBase64Size(string_t blob); //! Converts a blob to a base64 string, output should have space for at least ToBase64Size(blob) bytes - static void ToBase64(string_t blob, char *output); + DUCKDB_API static void ToBase64(string_t blob, char *output); //! Returns the string size of a base64 string -> blob conversion - static idx_t FromBase64Size(string_t str); + DUCKDB_API static idx_t FromBase64Size(string_t str); //! Converts a base64 string to a blob, output should have space for at least FromBase64Size(blob) bytes - static void FromBase64(string_t str, data_ptr_t output, idx_t output_size); + DUCKDB_API static void FromBase64(string_t str, data_ptr_t output, idx_t output_size); }; } // namespace duckdb //===----------------------------------------------------------------------===// @@ -19044,20 +21642,43 @@ class Blob { namespace duckdb { +template +struct DecimalWidth {}; + +template <> +struct DecimalWidth { + static constexpr uint8_t max = 4; +}; + +template <> +struct DecimalWidth { + static constexpr uint8_t max = 9; +}; + +template <> +struct DecimalWidth { + static constexpr uint8_t max = 18; +}; + +template <> +struct DecimalWidth { + static constexpr uint8_t max = 38; +}; + //! The Decimal class is a static class that holds helper functions for the Decimal type 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_INT16 = DecimalWidth::max; + static constexpr uint8_t MAX_WIDTH_INT32 = DecimalWidth::max; + static constexpr uint8_t MAX_WIDTH_INT64 = DecimalWidth::max; + static constexpr uint8_t MAX_WIDTH_INT128 = DecimalWidth::max; 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); + static string ToString(int16_t value, uint8_t width, uint8_t scale); + static string ToString(int32_t value, uint8_t width, uint8_t scale); + static string ToString(int64_t value, uint8_t width, uint8_t scale); + static string ToString(hugeint_t value, uint8_t width, uint8_t scale); }; } // namespace duckdb //===----------------------------------------------------------------------===// @@ -19074,6 +21695,8 @@ class Decimal { namespace duckdb { +class ClientContext; +struct RandomEngine; //! The UUID class contains static operations for the UUID type class UUID { @@ -19088,6 +21711,10 @@ class UUID { //! Convert a hugeint object to a uuid style string static void ToString(hugeint_t input, char *buf); + //! Convert a hugeint object to a uuid style string + static hugeint_t GenerateRandomUUID(RandomEngine &engine); + static hugeint_t GenerateRandomUUID(); + //! Convert a hugeint object to a uuid style string static string ToString(hugeint_t input) { char buff[STRING_SIZE]; @@ -19221,55 +21848,6 @@ class Time { static bool TryConvertInternal(const char *buf, idx_t len, idx_t &pos, dtime_t &result, bool strict); }; -} // namespace duckdb -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/common/serializer/buffered_serializer.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - -namespace duckdb { - -#define SERIALIZER_DEFAULT_SIZE 1024 - -struct BinaryData { - unique_ptr data; - idx_t size; -}; - -class BufferedSerializer : public Serializer { -public: - //! Serializes to a buffer allocated by the serializer, will expand when - //! writing past the initial threshold - explicit BufferedSerializer(idx_t maximum_size = SERIALIZER_DEFAULT_SIZE); - //! Serializes to a provided (owned) data pointer - BufferedSerializer(unique_ptr 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; - - //! Retrieves the data after the writing has been completed - BinaryData GetData() { - return std::move(blob); - } - - void Reset() { - blob.size = 0; - } -}; - } // namespace duckdb //===----------------------------------------------------------------------===// // DuckDB @@ -19285,9 +21863,9 @@ class BufferedSerializer : public Serializer { - namespace duckdb { +class ColumnDataCollection; class ClientContext; class DuckDB; class TableCatalogEntry; @@ -19296,21 +21874,22 @@ class Connection; //! The Appender class can be used to append elements to a table. class BaseAppender { protected: - //! The amount of chunks that will be gathered in the chunk collection before flushing - static constexpr const idx_t FLUSH_COUNT = 100; + //! The amount of tuples that will be gathered in the column data collection before flushing + static constexpr const idx_t FLUSH_COUNT = STANDARD_VECTOR_SIZE * 100; + Allocator &allocator; //! The append types vector types; //! The buffered data for the append - ChunkCollection collection; + unique_ptr collection; //! Internal chunk used for appends - unique_ptr chunk; + DataChunk chunk; //! The current column to append to idx_t column = 0; public: - DUCKDB_API BaseAppender(); - DUCKDB_API BaseAppender(vector types); + DUCKDB_API BaseAppender(Allocator &allocator); + DUCKDB_API BaseAppender(Allocator &allocator, vector types); DUCKDB_API virtual ~BaseAppender(); //! Begins a new row append, after calling this the other AppendX() functions @@ -19350,7 +21929,7 @@ class BaseAppender { protected: void Destructor(); - virtual void FlushInternal(ChunkCollection &collection) = 0; + virtual void FlushInternal(ColumnDataCollection &collection) = 0; void InitializeChunk(); void FlushChunk(); @@ -19384,7 +21963,7 @@ class Appender : public BaseAppender { DUCKDB_API ~Appender() override; protected: - void FlushInternal(ChunkCollection &collection) override; + void FlushInternal(ColumnDataCollection &collection) override; }; class InternalAppender : public BaseAppender { @@ -19398,7 +21977,7 @@ class InternalAppender : public BaseAppender { DUCKDB_API ~InternalAppender() override; protected: - void FlushInternal(ChunkCollection &collection) override; + void FlushInternal(ColumnDataCollection &collection) override; }; template <> @@ -19477,84 +22056,40 @@ struct CreateFunctionInfo : public CreateInfo { //! Function name string name; -}; - -} // namespace duckdb - -//===----------------------------------------------------------------------===// -// DuckDB -// -// duckdb/function/function_set.hpp -// -// -//===----------------------------------------------------------------------===// - - - - - - - -namespace duckdb { - -template -class FunctionSet { -public: - explicit FunctionSet(string name) : name(name) { - } - - //! The name of the function set - string name; - //! The set of functions - vector functions; - -public: - void AddFunction(T function) { - function.name = name; - functions.push_back(function); - } -}; - -class ScalarFunctionSet : public FunctionSet { -public: - explicit ScalarFunctionSet(string name) : FunctionSet(move(name)) { - } -}; - -class AggregateFunctionSet : public FunctionSet { -public: - explicit AggregateFunctionSet(string name) : FunctionSet(move(name)) { - } -}; -class TableFunctionSet : public FunctionSet { -public: - explicit TableFunctionSet(string name) : FunctionSet(move(name)) { +protected: + void SerializeInternal(Serializer &serializer) const override { + serializer.WriteString(name); } }; } // namespace duckdb + 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), functions(function.name) { + name = function.name; + functions.AddFunction(move(function)); } - explicit CreateTableFunctionInfo(TableFunction function) : CreateFunctionInfo(CatalogType::TABLE_FUNCTION_ENTRY) { - this->name = function.name; - functions.push_back(move(function)); + explicit CreateTableFunctionInfo(TableFunctionSet set) + : CreateFunctionInfo(CatalogType::TABLE_FUNCTION_ENTRY), functions(move(set)) { + name = functions.name; + for (auto &func : functions.functions) { + func.name = functions.name; + } } //! The table functions - vector functions; + TableFunctionSet functions; public: unique_ptr Copy() const override { TableFunctionSet set(name); - set.functions = functions; + set.functions = functions.functions; auto result = make_unique(move(set)); CopyProperties(*result); return move(result); @@ -19653,15 +22188,20 @@ struct GlobalFunctionData { typedef unique_ptr (*copy_to_bind_t)(ClientContext &context, CopyInfo &info, vector &names, vector &sql_types); -typedef unique_ptr (*copy_to_initialize_local_t)(ClientContext &context, FunctionData &bind_data); +typedef unique_ptr (*copy_to_initialize_local_t)(ExecutionContext &context, FunctionData &bind_data); typedef unique_ptr (*copy_to_initialize_global_t)(ClientContext &context, FunctionData &bind_data, const string &file_path); -typedef void (*copy_to_sink_t)(ClientContext &context, FunctionData &bind_data, GlobalFunctionData &gstate, +typedef void (*copy_to_sink_t)(ExecutionContext &context, FunctionData &bind_data, GlobalFunctionData &gstate, LocalFunctionData &lstate, DataChunk &input); -typedef void (*copy_to_combine_t)(ClientContext &context, FunctionData &bind_data, GlobalFunctionData &gstate, +typedef void (*copy_to_combine_t)(ExecutionContext &context, FunctionData &bind_data, GlobalFunctionData &gstate, LocalFunctionData &lstate); typedef void (*copy_to_finalize_t)(ClientContext &context, FunctionData &bind_data, GlobalFunctionData &gstate); +typedef void (*copy_to_serialize_t)(FieldWriter &writer, const FunctionData &bind_data, const CopyFunction &function); + +typedef unique_ptr (*copy_to_deserialize_t)(ClientContext &context, FieldReader &reader, + CopyFunction &function); + typedef unique_ptr (*copy_from_bind_t)(ClientContext &context, CopyInfo &info, vector &expected_names, vector &expected_types); @@ -19670,7 +22210,8 @@ 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_sink(nullptr), copy_to_combine(nullptr), copy_to_finalize(nullptr), serialize(nullptr), + deserialize(nullptr), copy_from_bind(nullptr) { } copy_to_bind_t copy_to_bind; @@ -19680,6 +22221,9 @@ class CopyFunction : public Function { copy_to_combine_t copy_to_combine; copy_to_finalize_t copy_to_finalize; + copy_to_serialize_t serialize; + copy_to_deserialize_t deserialize; + copy_from_bind_t copy_from_bind; TableFunction copy_from_function; @@ -19702,6 +22246,11 @@ struct CreateCopyFunctionInfo : public CreateInfo { //! The table function CopyFunction function; +protected: + void SerializeInternal(Serializer &) const override { + throw NotImplementedException("Cannot serialize '%s'", CatalogTypeToString(type)); + } + public: unique_ptr Copy() const override { auto result = make_unique(function); diff --git a/libduckdb-sys/upgrade.sh b/libduckdb-sys/upgrade.sh index 59b722b8..e70a66e9 100755 --- a/libduckdb-sys/upgrade.sh +++ b/libduckdb-sys/upgrade.sh @@ -10,7 +10,7 @@ export DUCKDB_LIB_DIR="$SCRIPT_DIR/duckdb" export DU_INCLUDE_DIR="$DUCKDB_LIB_DIR" # Download and extract amalgamation -DUCKDB_VERSION=v0.4.0 +DUCKDB_VERSION=v0.5.0 wget -T 20 "https://github.com/duckdb/duckdb/releases/download/$DUCKDB_VERSION/libduckdb-src.zip" unzip -o libduckdb-src.zip -d duckdb rm -f libduckdb-src.zip diff --git a/src/cache.rs b/src/cache.rs index 65543d9f..fed9a966 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -280,20 +280,13 @@ mod test { "#, )?; - let sql = "SELECT x FROM foo"; + let sql = "SELECT * FROM foo"; { let mut stmt = db.prepare_cached(sql)?; assert_eq!(Ok(Some(1i32)), stmt.query([])?.map(|r| r.get(0)).next()); } - let sql_cannot_cache = "SELECT * FROM foo"; - - { - let mut stmt = db.prepare_cached(sql_cannot_cache)?; - assert_eq!(Ok(Some(1i32)), stmt.query([])?.map(|r| r.get(0)).next()); - } - db.execute_batch( r#" ALTER TABLE foo ADD COLUMN y INT; @@ -301,16 +294,13 @@ mod test { "#, )?; - { - let mut stmt = db.prepare_cached(sql)?; - assert_eq!(Ok(Some(1i32)), stmt.query([])?.map(|r| r.get(0)).next()); - } - { // Rebinding statement after catalog change resulted in change of types - let mut stmt = db.prepare_cached(sql_cannot_cache)?; - let result = stmt.query([]); - assert!(result.is_err()); + let mut stmt = db.prepare_cached(sql)?; + assert_eq!( + Ok(Some((1i32, 2i32))), + stmt.query([])?.map(|r| <(i32, i32)>::try_from(r)).next() + ); } Ok(()) } diff --git a/src/types/to_sql.rs b/src/types/to_sql.rs index 15d9fe63..b3d9459e 100644 --- a/src/types/to_sql.rs +++ b/src/types/to_sql.rs @@ -328,8 +328,8 @@ mod test { let id_vec = id.as_bytes().to_vec(); db.execute("INSERT INTO foo (id, label) VALUES (?, ?)", params![id_vec, "target"])?; - let mut stmt = db.prepare("SELECT id, label FROM foo WHERE id = ?")?; - let mut rows = stmt.query(params![id_vec])?; + let mut stmt = db.prepare("SELECT id, label FROM foo")?; + let mut rows = stmt.query([])?; let row = rows.next()?.unwrap(); let found_id: Uuid = row.get_unwrap(0); let found_label: String = row.get_unwrap(1);