#include "tpcds_extension.hpp" #include "dsdgen.hpp" #include "duckdb/function/table_function.hpp" #include "duckdb/main/extension/extension_loader.hpp" #include "duckdb/parser/parser.hpp" #include "duckdb/parser/statement/select_statement.hpp" namespace duckdb { struct DSDGenFunctionData : public TableFunctionData { DSDGenFunctionData() { } bool finished = false; double sf = 0; string catalog = INVALID_CATALOG; string schema = DEFAULT_SCHEMA; string suffix; bool overwrite = false; bool keys = false; }; static duckdb::unique_ptr DsdgenBind(ClientContext &context, TableFunctionBindInput &input, vector &return_types, vector &names) { auto result = make_uniq(); for (auto &kv : input.named_parameters) { if (kv.second.IsNull()) { throw BinderException("Cannot use NULL as function argument"); } if (kv.first == "sf") { result->sf = kv.second.GetValue(); } else if (kv.first == "catalog") { result->catalog = StringValue::Get(kv.second); } else if (kv.first == "schema") { result->schema = StringValue::Get(kv.second); } else if (kv.first == "suffix") { result->suffix = StringValue::Get(kv.second); } else if (kv.first == "overwrite") { result->overwrite = kv.second.GetValue(); } else if (kv.first == "keys") { result->keys = kv.second.GetValue(); } } if (input.binder) { auto &catalog = Catalog::GetCatalog(context, result->catalog); auto &properties = input.binder->GetStatementProperties(); properties.RegisterDBModify(catalog, context); } return_types.emplace_back(LogicalType::BOOLEAN); names.emplace_back("Success"); return std::move(result); } static void DsdgenFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { auto &data = data_p.bind_data->CastNoConst(); if (data.finished) { return; } tpcds::DSDGenWrapper::CreateTPCDSSchema(context, data.catalog, data.schema, data.suffix, data.keys, data.overwrite); tpcds::DSDGenWrapper::DSDGen(data.sf, context, data.catalog, data.schema, data.suffix); data.finished = true; } struct TPCDSData : public GlobalTableFunctionState { TPCDSData() : offset(0) { } idx_t offset; }; unique_ptr TPCDSInit(ClientContext &context, TableFunctionInitInput &input) { auto result = make_uniq(); return std::move(result); } static duckdb::unique_ptr TPCDSQueryBind(ClientContext &context, TableFunctionBindInput &input, vector &return_types, vector &names) { names.emplace_back("query_nr"); return_types.emplace_back(LogicalType::INTEGER); names.emplace_back("query"); return_types.emplace_back(LogicalType::VARCHAR); return nullptr; } static void TPCDSQueryFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { auto &data = data_p.global_state->Cast(); idx_t tpcds_queries = tpcds::DSDGenWrapper::QueriesCount(); if (data.offset >= tpcds_queries) { // finished returning values return; } idx_t chunk_count = 0; while (data.offset < tpcds_queries && chunk_count < STANDARD_VECTOR_SIZE) { auto query = TpcdsExtension::GetQuery(data.offset + 1); // "query_nr", PhysicalType::INT32 output.SetValue(0, chunk_count, Value::INTEGER((int32_t)data.offset + 1)); // "query", PhysicalType::VARCHAR output.SetValue(1, chunk_count, Value(query)); data.offset++; chunk_count++; } output.SetCardinality(chunk_count); } static duckdb::unique_ptr TPCDSQueryAnswerBind(ClientContext &context, TableFunctionBindInput &input, vector &return_types, vector &names) { names.emplace_back("query_nr"); return_types.emplace_back(LogicalType::INTEGER); names.emplace_back("scale_factor"); return_types.emplace_back(LogicalType::DOUBLE); names.emplace_back("answer"); return_types.emplace_back(LogicalType::VARCHAR); return nullptr; } static void TPCDSQueryAnswerFunction(ClientContext &context, TableFunctionInput &data_p, DataChunk &output) { auto &data = data_p.global_state->Cast(); idx_t tpcds_queries = tpcds::DSDGenWrapper::QueriesCount(); vector scale_factors {1, 10}; idx_t total_answers = tpcds_queries * scale_factors.size(); if (data.offset >= total_answers) { // finished returning values return; } idx_t chunk_count = 0; while (data.offset < total_answers && chunk_count < STANDARD_VECTOR_SIZE) { idx_t cur_query = data.offset % tpcds_queries; idx_t cur_sf = data.offset / tpcds_queries; auto answer = TpcdsExtension::GetAnswer(scale_factors[cur_sf], cur_query + 1); // "query_nr", PhysicalType::INT32 output.SetValue(0, chunk_count, Value::INTEGER((int32_t)cur_query + 1)); // "scale_factor", PhysicalType::DOUBLE output.SetValue(1, chunk_count, Value::DOUBLE(scale_factors[cur_sf])); // "query", PhysicalType::VARCHAR output.SetValue(2, chunk_count, Value(answer)); data.offset++; chunk_count++; } output.SetCardinality(chunk_count); } static string PragmaTpcdsQuery(ClientContext &context, const FunctionParameters ¶meters) { auto index = parameters.values[0].GetValue(); return tpcds::DSDGenWrapper::GetQuery(index); } static void LoadInternal(ExtensionLoader &loader) { TableFunction dsdgen_func("dsdgen", {}, DsdgenFunction, DsdgenBind); dsdgen_func.named_parameters["sf"] = LogicalType::DOUBLE; dsdgen_func.named_parameters["overwrite"] = LogicalType::BOOLEAN; dsdgen_func.named_parameters["keys"] = LogicalType::BOOLEAN; dsdgen_func.named_parameters["catalog"] = LogicalType::VARCHAR; dsdgen_func.named_parameters["schema"] = LogicalType::VARCHAR; dsdgen_func.named_parameters["suffix"] = LogicalType::VARCHAR; loader.RegisterFunction(dsdgen_func); // create the TPCDS pragma that allows us to run the query auto tpcds_func = PragmaFunction::PragmaCall("tpcds", PragmaTpcdsQuery, {LogicalType::BIGINT}); loader.RegisterFunction(tpcds_func); // create the TPCDS_QUERIES function that returns the query TableFunction tpcds_query_func("tpcds_queries", {}, TPCDSQueryFunction, TPCDSQueryBind, TPCDSInit); loader.RegisterFunction(tpcds_query_func); // create the TPCDS_ANSWERS that returns the query result TableFunction tpcds_query_answer_func("tpcds_answers", {}, TPCDSQueryAnswerFunction, TPCDSQueryAnswerBind, TPCDSInit); loader.RegisterFunction(tpcds_query_answer_func); } void TpcdsExtension::Load(ExtensionLoader &loader) { LoadInternal(loader); } std::string TpcdsExtension::GetQuery(int query) { return tpcds::DSDGenWrapper::GetQuery(query); } std::string TpcdsExtension::GetAnswer(double sf, int query) { return tpcds::DSDGenWrapper::GetAnswer(sf, query); } std::string TpcdsExtension::Name() { return "tpcds"; } std::string TpcdsExtension::Version() const { #ifdef EXT_VERSION_TPCDS return EXT_VERSION_TPCDS; #else return ""; #endif } } // namespace duckdb extern "C" { DUCKDB_CPP_EXTENSION_ENTRY(tpcds, loader) { duckdb::LoadInternal(loader); } }