Skip to content

Commit

Permalink
Merge pull request #9651 from Mytherin/getenv
Browse files Browse the repository at this point in the history
Add "getenv" function to shell which can be used to read environment variables, and allow functions to be used in SET statements/PRAGMA statements
  • Loading branch information
Mytherin committed Nov 13, 2023
2 parents 0284805 + 26f1ff6 commit 754991b
Show file tree
Hide file tree
Showing 32 changed files with 12,293 additions and 12,400 deletions.
4 changes: 2 additions & 2 deletions src/execution/operator/helper/physical_pragma.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ namespace duckdb {
SourceResultType PhysicalPragma::GetData(ExecutionContext &context, DataChunk &chunk,
OperatorSourceInput &input) const {
auto &client = context.client;
FunctionParameters parameters {info.parameters, info.named_parameters};
function.function(client, parameters);
FunctionParameters parameters {info->parameters, info->named_parameters};
info->function.function(client, parameters);

return SourceResultType::FINISHED;
}
Expand Down
2 changes: 1 addition & 1 deletion src/execution/physical_plan/plan_pragma.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
namespace duckdb {

unique_ptr<PhysicalOperator> PhysicalPlanGenerator::CreatePlan(LogicalPragma &op) {
return make_uniq<PhysicalPragma>(op.function, op.info, op.estimated_cardinality);
return make_uniq<PhysicalPragma>(std::move(op.info), op.estimated_cardinality);
}

} // namespace duckdb
9 changes: 5 additions & 4 deletions src/function/function_binder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,9 +163,10 @@ idx_t FunctionBinder::BindFunction(const string &name, TableFunctionSet &functio
return BindFunctionFromArguments(name, functions, arguments, error);
}

idx_t FunctionBinder::BindFunction(const string &name, PragmaFunctionSet &functions, PragmaInfo &info, string &error) {
idx_t FunctionBinder::BindFunction(const string &name, PragmaFunctionSet &functions, vector<Value> &parameters,
string &error) {
vector<LogicalType> types;
for (auto &value : info.parameters) {
for (auto &value : parameters) {
types.push_back(value.type());
}
idx_t entry = BindFunctionFromArguments(name, functions, types, error);
Expand All @@ -174,10 +175,10 @@ idx_t FunctionBinder::BindFunction(const string &name, PragmaFunctionSet &functi
}
auto candidate_function = functions.GetFunctionByOffset(entry);
// cast the input parameters
for (idx_t i = 0; i < info.parameters.size(); i++) {
for (idx_t i = 0; i < parameters.size(); i++) {
auto target_type =
i < candidate_function.arguments.size() ? candidate_function.arguments[i] : candidate_function.varargs;
info.parameters[i] = info.parameters[i].CastAs(context, target_type);
parameters[i] = parameters[i].CastAs(context, target_type);
}
return entry;
}
Expand Down
11 changes: 4 additions & 7 deletions src/include/duckdb/execution/operator/helper/physical_pragma.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
#pragma once

#include "duckdb/execution/physical_operator.hpp"
#include "duckdb/parser/parsed_data/pragma_info.hpp"
#include "duckdb/function/pragma_function.hpp"
#include "duckdb/parser/parsed_data/bound_pragma_info.hpp"

namespace duckdb {

Expand All @@ -20,15 +19,13 @@ class PhysicalPragma : public PhysicalOperator {
static constexpr const PhysicalOperatorType TYPE = PhysicalOperatorType::PRAGMA;

public:
PhysicalPragma(PragmaFunction function_p, PragmaInfo info_p, idx_t estimated_cardinality)
PhysicalPragma(unique_ptr<BoundPragmaInfo> info_p, idx_t estimated_cardinality)
: PhysicalOperator(PhysicalOperatorType::PRAGMA, {LogicalType::BOOLEAN}, estimated_cardinality),
function(std::move(function_p)), info(std::move(info_p)) {
info(std::move(info_p)) {
}

//! The pragma function to call
PragmaFunction function;
//! The context of the call
PragmaInfo info;
unique_ptr<BoundPragmaInfo> info;

public:
// Source interface
Expand Down
3 changes: 2 additions & 1 deletion src/include/duckdb/function/function_binder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ class FunctionBinder {
DUCKDB_API idx_t BindFunction(const string &name, TableFunctionSet &functions,
vector<unique_ptr<Expression>> &arguments, string &error);
//! Bind a pragma function from the set of functions and input arguments
DUCKDB_API idx_t BindFunction(const string &name, PragmaFunctionSet &functions, PragmaInfo &info, string &error);
DUCKDB_API idx_t BindFunction(const string &name, PragmaFunctionSet &functions, vector<Value> &parameters,
string &error);

DUCKDB_API unique_ptr<Expression> BindScalarFunction(const string &schema, const string &name,
vector<unique_ptr<Expression>> children, string &error,
Expand Down
29 changes: 29 additions & 0 deletions src/include/duckdb/parser/parsed_data/bound_pragma_info.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//===----------------------------------------------------------------------===//
// DuckDB
//
// duckdb/parser/parsed_data/bound_pragma_info.hpp
//
//
//===----------------------------------------------------------------------===//

#pragma once

#include "duckdb/parser/parsed_data/pragma_info.hpp"
#include "duckdb/function/pragma_function.hpp"

namespace duckdb {

struct BoundPragmaInfo {
BoundPragmaInfo(PragmaFunction function_p, vector<Value> parameters_p, named_parameter_map_t named_parameters_p)
: function(std::move(function_p)), parameters(std::move(parameters_p)),
named_parameters(std::move(named_parameters_p)) {
}

PragmaFunction function;
//! Parameter list (if any)
vector<Value> parameters;
//! Named parameter list (if any)
named_parameter_map_t named_parameters;
};

} // namespace duckdb
12 changes: 8 additions & 4 deletions src/include/duckdb/parser/parsed_data/pragma_info.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,20 @@ struct PragmaInfo : public ParseInfo {
//! Name of the PRAGMA statement
string name;
//! Parameter list (if any)
vector<Value> parameters;
vector<unique_ptr<ParsedExpression>> parameters;
//! Named parameter list (if any)
named_parameter_map_t named_parameters;
case_insensitive_map_t<unique_ptr<ParsedExpression>> named_parameters;

public:
unique_ptr<PragmaInfo> Copy() const {
auto result = make_uniq<PragmaInfo>();
result->name = name;
result->parameters = parameters;
result->named_parameters = named_parameters;
for (auto &param : parameters) {
result->parameters.push_back(param->Copy());
}
for (auto &entry : named_parameters) {
result->named_parameters.insert(make_pair(entry.first, entry.second->Copy()));
}
return result;
}

Expand Down
7 changes: 4 additions & 3 deletions src/include/duckdb/parser/statement/set_statement.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "duckdb/common/enums/set_type.hpp"
#include "duckdb/parser/sql_statement.hpp"
#include "duckdb/common/types/value.hpp"
#include "duckdb/parser/parsed_expression.hpp"

namespace duckdb {

Expand All @@ -34,16 +35,16 @@ class SetStatement : public SQLStatement {

class SetVariableStatement : public SetStatement {
public:
SetVariableStatement(std::string name_p, Value value_p, SetScope scope_p);
SetVariableStatement(std::string name_p, unique_ptr<ParsedExpression> value_p, SetScope scope_p);

protected:
SetVariableStatement(const SetVariableStatement &other) = default;
SetVariableStatement(const SetVariableStatement &other);

public:
unique_ptr<SQLStatement> Copy() const override;

public:
Value value;
unique_ptr<ParsedExpression> value;
};

class ResetVariableStatement : public SetStatement {
Expand Down
2 changes: 2 additions & 0 deletions src/include/duckdb/planner/binder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct BoundCreateTableInfo;
struct BoundCreateFunctionInfo;
struct CommonTableExpressionInfo;
struct BoundParameterMap;
struct BoundPragmaInfo;

enum class BindingMode : uint8_t { STANDARD_BINDING, EXTRACT_NAMES };

Expand Down Expand Up @@ -120,6 +121,7 @@ class Binder : public std::enable_shared_from_this<Binder> {
//! 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<BoundPragmaInfo> BindPragma(PragmaInfo &info, QueryErrorContext error_context);

unique_ptr<BoundTableRef> Bind(TableRef &ref);
unique_ptr<LogicalOperator> CreatePlan(BoundTableRef &ref);
Expand Down
13 changes: 4 additions & 9 deletions src/include/duckdb/planner/operator/logical_pragma.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@

#pragma once

#include "duckdb/function/pragma_function.hpp"
#include "duckdb/parser/parsed_data/pragma_info.hpp"
#include "duckdb/planner/logical_operator.hpp"
#include "duckdb/parser/parsed_data/bound_pragma_info.hpp"

namespace duckdb {

Expand All @@ -20,15 +19,11 @@ class LogicalPragma : public LogicalOperator {
static constexpr const LogicalOperatorType TYPE = LogicalOperatorType::LOGICAL_PRAGMA;

public:
LogicalPragma(PragmaFunction function_p, PragmaInfo info_p)
: LogicalOperator(LogicalOperatorType::LOGICAL_PRAGMA), function(std::move(function_p)),
info(std::move(info_p)) {
LogicalPragma(unique_ptr<BoundPragmaInfo> info_p)
: LogicalOperator(LogicalOperatorType::LOGICAL_PRAGMA), info(std::move(info_p)) {
}

//! The pragma function to call
PragmaFunction function;
//! The context of the call
PragmaInfo info;
unique_ptr<BoundPragmaInfo> info;

public:
idx_t EstimateCardinality(ClientContext &context) override;
Expand Down
2 changes: 1 addition & 1 deletion src/include/duckdb/planner/pragma_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class PragmaHandler {
private:
//! Handles a pragma statement, returns whether the statement was expanded, if it was expanded the 'resulting_query'
//! contains the statement(s) to replace the current one
bool HandlePragma(SQLStatement *statement, string &resulting_query);
bool HandlePragma(SQLStatement &statement, string &resulting_query);

void HandlePragmaStatementsInternal(vector<unique_ptr<SQLStatement>> &statements);
};
Expand Down
4 changes: 2 additions & 2 deletions src/include/duckdb/storage/serialization/parse_info.json
Original file line number Diff line number Diff line change
Expand Up @@ -452,12 +452,12 @@
{
"id": 201,
"name": "parameters",
"type": "vector<Value>"
"type": "vector<ParsedExpression*>"
},
{
"id": 202,
"name": "named_parameters",
"type": "named_parameter_map_t"
"type": "case_insensitive_map_t<ParsedExpression*>"
}
]
},
Expand Down
6 changes: 5 additions & 1 deletion src/parser/statement/set_statement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ unique_ptr<SQLStatement> SetStatement::Copy() const {

// Set Variable

SetVariableStatement::SetVariableStatement(std::string name_p, Value value_p, SetScope scope_p)
SetVariableStatement::SetVariableStatement(std::string name_p, unique_ptr<ParsedExpression> value_p, SetScope scope_p)
: SetStatement(std::move(name_p), scope_p, SetType::SET), value(std::move(value_p)) {
}

SetVariableStatement::SetVariableStatement(const SetVariableStatement &other)
: SetVariableStatement(other.name, other.value->Copy(), other.scope) {
}

unique_ptr<SQLStatement> SetVariableStatement::Copy() const {
return unique_ptr<SetVariableStatement>(new SetVariableStatement(*this));
}
Expand Down
3 changes: 2 additions & 1 deletion src/parser/transform/statement/transform_import.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#include "duckdb/parser/statement/pragma_statement.hpp"
#include "duckdb/parser/transformer.hpp"
#include "duckdb/parser/expression/constant_expression.hpp"

namespace duckdb {

unique_ptr<PragmaStatement> Transformer::TransformImport(duckdb_libpgquery::PGImportStmt &stmt) {
auto result = make_uniq<PragmaStatement>();
result->info->name = "import_database";
result->info->parameters.emplace_back(stmt.filename);
result->info->parameters.emplace_back(make_uniq<ConstantExpression>(Value(stmt.filename)));
return result;
}

Expand Down
20 changes: 6 additions & 14 deletions src/parser/transform/statement/transform_pragma.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,16 @@ unique_ptr<SQLStatement> Transformer::TransformPragma(duckdb_libpgquery::PGPragm
throw ParserException("Named parameter requires a column reference on the LHS");
}
auto &columnref = comp.left->Cast<ColumnRefExpression>();

Value rhs_value;
if (!Transformer::ConstructConstantFromExpression(*comp.right, rhs_value)) {
throw ParserException("Named parameter requires a constant on the RHS");
}

info.named_parameters[columnref.GetName()] = rhs_value;
} else if (node->type == duckdb_libpgquery::T_PGAConst) {
auto constant = TransformConstant(*PGPointerCast<duckdb_libpgquery::PGAConst>(node.get()));
info.parameters.push_back((constant->Cast<ConstantExpression>()).value);
info.named_parameters.insert(make_pair(columnref.GetName(), std::move(comp.right)));
} else if (expr->type == ExpressionType::COLUMN_REF) {
auto &colref = expr->Cast<ColumnRefExpression>();
if (!colref.IsQualified()) {
info.parameters.emplace_back(colref.GetColumnName());
info.parameters.emplace_back(make_uniq<ConstantExpression>(Value(colref.GetColumnName())));
} else {
info.parameters.emplace_back(expr->ToString());
info.parameters.emplace_back(make_uniq<ConstantExpression>(Value(expr->ToString())));
}
} else {
info.parameters.emplace_back(expr->ToString());
info.parameters.emplace_back(std::move(expr));
}
}
}
Expand All @@ -71,7 +62,8 @@ unique_ptr<SQLStatement> Transformer::TransformPragma(duckdb_libpgquery::PGPragm
if (sqlite_compat_pragmas.find(info.name) != sqlite_compat_pragmas.end()) {
break;
}
auto set_statement = make_uniq<SetVariableStatement>(info.name, info.parameters[0], SetScope::AUTOMATIC);
auto set_statement =
make_uniq<SetVariableStatement>(info.name, std::move(info.parameters[0]), SetScope::AUTOMATIC);
return std::move(set_statement);
}
case duckdb_libpgquery::PG_PRAGMA_TYPE_CALL:
Expand Down
23 changes: 18 additions & 5 deletions src/parser/transform/statement/transform_set.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "duckdb/parser/transformer.hpp"
#include "duckdb/parser/expression/constant_expression.hpp"
#include "duckdb/parser/expression/columnref_expression.hpp"

namespace duckdb {

Expand Down Expand Up @@ -48,11 +49,23 @@ unique_ptr<SetStatement> Transformer::TransformSetVariable(duckdb_libpgquery::PG
throw ParserException("SET needs a single scalar value parameter");
}
D_ASSERT(stmt.args->head && stmt.args->head->data.ptr_value);
auto const_val = PGPointerCast<duckdb_libpgquery::PGAConst>(stmt.args->head->data.ptr_value);
D_ASSERT(const_val->type == duckdb_libpgquery::T_PGAConst);

auto value = TransformValue(const_val->val)->value;
return make_uniq<SetVariableStatement>(name, value, ToSetScope(stmt.scope));
auto const_val = PGPointerCast<duckdb_libpgquery::PGNode>(stmt.args->head->data.ptr_value);
auto expr = TransformExpression(const_val);
if (expr->type == ExpressionType::COLUMN_REF) {
auto &colref = expr->Cast<ColumnRefExpression>();
Value val;
if (!colref.IsQualified()) {
val = Value(colref.GetColumnName());
} else {
val = Value(expr->ToString());
}
expr = make_uniq<ConstantExpression>(std::move(val));
}
if (expr->type == ExpressionType::VALUE_DEFAULT) {
// set to default = reset
return make_uniq<ResetVariableStatement>(name, ToSetScope(stmt.scope));
}
return make_uniq<SetVariableStatement>(name, std::move(expr), ToSetScope(stmt.scope));
}

unique_ptr<SetStatement> Transformer::TransformResetVariable(duckdb_libpgquery::PGVariableSetStmt &stmt) {
Expand Down
3 changes: 2 additions & 1 deletion src/parser/transform/statement/transform_show.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "duckdb/parser/query_node/select_node.hpp"
#include "duckdb/parser/expression/star_expression.hpp"
#include "duckdb/parser/tableref/basetableref.hpp"
#include "duckdb/parser/expression/constant_expression.hpp"

namespace duckdb {

Expand All @@ -21,7 +22,7 @@ static void TransformShowName(unique_ptr<PragmaStatement> &result, const string
} else {
// show one specific table
info.name = "show";
info.parameters.emplace_back(name);
info.parameters.emplace_back(make_uniq<ConstantExpression>(Value(name)));
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/parser/transform/statement/transform_use.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "duckdb/parser/transformer.hpp"
#include "duckdb/parser/statement/set_statement.hpp"
#include "duckdb/parser/expression/constant_expression.hpp"

namespace duckdb {

Expand All @@ -14,7 +15,8 @@ unique_ptr<SetStatement> Transformer::TransformUse(duckdb_libpgquery::PGUseStmt
} else {
name = qualified_name.schema + "." + qualified_name.name;
}
return make_uniq<SetVariableStatement>("schema", std::move(name), SetScope::AUTOMATIC);
auto name_expr = make_uniq<ConstantExpression>(Value(name));
return make_uniq<SetVariableStatement>("schema", std::move(name_expr), SetScope::AUTOMATIC);
}

} // namespace duckdb
Loading

0 comments on commit 754991b

Please sign in to comment.