Improved code generation for functions and procedures.

alter statements for configuration settings
alter statement for owner
This commit is contained in:
eelke 2018-12-23 19:45:04 +01:00
parent fc58acb252
commit 54d4dfface
5 changed files with 145 additions and 69 deletions

View file

@ -91,9 +91,44 @@ void operator<<(ProcKind &s, const Pgsql::Value &v)
case 'w':
s = ProcKind::Window;
break;
default:
throw std::runtime_error("Unexpected value for ProcKind");
}
}
void operator<<(ParallelMode &s, const Pgsql::Value &v)
{
const char *c = v.c_str();
switch (*c) {
case 'u':
s = ParallelMode::Unsafe;
break;
case 'r':
s = ParallelMode::Restricted;
break;
case 's':
s = ParallelMode::Safe;
break;
default:
throw std::runtime_error("Unexpected value for ParallelMode");
}
}
QString parallelModeToSql(ParallelMode pm, bool explicit_unsafe)
{
switch (pm) {
case ParallelMode::Unsafe:
return explicit_unsafe ? "PARALLEL UNSAFE" : "";
case ParallelMode::Restricted:
return "PARALLEL RESTRICTED";
case ParallelMode::Safe:
return "PARALLEL SAFE";
default:
throw std::runtime_error("Unexpected value for pm in parallelModeToSql");
}
}
void PgProc::setArgs(
std::vector<Oid> argtypes,
std::vector<Oid> allargtypes,
@ -210,89 +245,106 @@ QString PgProc::argSigList(const bool forScript) const
}
QString PgProc::createSql() const
const QString& PgProc::createSql() const
{
if (createSqlCache.isEmpty()) {
QString sql;
//wxString qtName = GetQuotedFullIdentifier() + wxT("(") + GetArgListWithNames(true) + wxT(")");
QString quoted_name = QString("%1(%2)").arg(fullyQualifiedQuotedObjectName(), argListWithNames(true));
// wxString qtSig = GetQuotedFullIdentifier() + wxT("(") + GetArgSigList() + wxT(")");
QString quoted_sig = QString("%1(%2)").arg(fullyQualifiedQuotedObjectName(), argSigList());
auto&& types = catalog().types();
QString return_type = types->getByKey(rettype)->objectName();
sql = QString("-- Function: %1\n\n"
"-- DROP FUNCTION %1;\n\n"
"CREATE OR REPLACE FUNCTION %2\n"
" RETURNS %3 AS\n"
).arg(quoted_sig, quoted_name, return_type);
// if (GetLanguage().IsSameAs(wxT("C"), false))
// {
// sql += qtDbString(GetBin()) + wxT(", ") + qtDbString(GetSource());
// }
// else
// {
// if (GetConnection()->BackendMinimumVersion(7, 5))
// sql += qtDbStringDollar(GetSource());
// else
// sql += qtDbString(GetSource());
// }
QString language;
{
auto l = catalog().languages()->getByKey(lang);
if (l)
language = l->objectName();
if (isAggregate()) {
/// \todo Support for aggregates
createSqlCache = "-- aggregates not supported yet\n";
return createSqlCache;
}
if (language == "c") {
QString quoted_name = QString("%1(%2)").arg(fullyQualifiedQuotedObjectName(), argListWithNames(true));
QString quoted_sig = QString("%1(%2)").arg(fullyQualifiedQuotedObjectName(), argSigList());
if (isProcedure()) {
// P CREATE [ OR REPLACE ] PROCEDURE
// name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
sql = QString("-- Procedure: %1\n\n"
"-- DROP PROCEDURE %1;\n\n"
"CREATE OR REPLACE PROCEDURE %2\n"
).arg(quoted_sig, quoted_name);
}
else {
// all other kinds are functions
// F CREATE [ OR REPLACE ] FUNCTION
// name ( [ [ argmode ] [ argname ] argtype [ { DEFAULT | = } default_expr ] [, ...] ] )
// F [ RETURNS rettype
/// \todo F | RETURNS TABLE ( column_name column_type [, ...] ) ]
auto&& types = catalog().types();
QString return_type = types->getByKey(rettype)->objectName();
sql = QString("-- Function: %1\n\n"
"-- DROP FUNCTION %1;\n\n"
"CREATE OR REPLACE FUNCTION %2\n"
" RETURNS %3"
).arg(quoted_sig, quoted_name, return_type);
}
sql += " AS\n";
auto language = catalog().languages()->getByKey(lang);
BOOST_ASSERT(language != nullptr);
if (language->isC()) {
// | AS 'obj_file', 'link_symbol'
sql += escapeLiteral(bin) % ", " % escapeLiteral(src);
}
else {
// | AS 'definition'
sql += dollarQuoteString(src);
}
// sql += wxT("\n LANGUAGE ") + GetLanguage() + wxT(" ");
sql += "\n LANGUAGE " % language % " ";
// if (GetConnection()->BackendMinimumVersion(8, 4) && GetIsWindow())
// sql += wxT("WINDOW ");
// { LANGUAGE lang_name
sql += "\n LANGUAGE " % language->quotedObjectName();
/// \todo | TRANSFORM { FOR TYPE type_name } [, ... ]
// | WINDOW
if (isWindow())
sql += "WINDOW ";
// sql += GetVolatility();
sql += volatility();
sql += " WINDOW";
if (!isProcedure()) {
// F | IMMUTABLE | STABLE | VOLATILE | [ NOT ] LEAKPROOF
sql += " " % volatility();
if (leakproof)
sql += " LEAKPROOF";
// F | CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT
// CALLED ON NULL INPUT is the default so we never specify this
// RETURNS NULL ON NULL INPUT is an alias for STRICT so we use STRICT
if (isstrict)
sql += " STRICT"
;
/// \todo F | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
// if (GetSecureDefiner())
// sql += wxT(" SECURITY DEFINER");
// F | PARALLEL { UNSAFE | RESTRICTED | SAFE }
sql += " " % parallelModeToSql(parallel);
// F | COST execution_cost
sql += QString("\n COST %1").arg(static_cast<double>(cost));
// F | ROWS result_rows
if (retset)
sql += QString("n ROWS %1").arg(static_cast<double>(rows));
}
if (leakproof)
sql += " LEAKPROOF";
if (isstrict)
sql += " STRICT";
// if (GetSecureDefiner())
// sql += wxT(" SECURITY DEFINER");
sql += QString("\n COST %1").arg(cost);
if (retset)
sql += QString("n ROWS %1").arg(rows);
sql += ";";
// if (!sql.Strip(wxString::both).EndsWith(wxT(";")))
// sql += wxT(";");
// size_t i;
// for (i = 0 ; i < configList.GetCount() ; i++)
// {
// if (configList.Item(i).BeforeFirst('=') != wxT("search_path") &&
// configList.Item(i).BeforeFirst('=') != wxT("temp_tablespaces"))
// sql += wxT("\nALTER FUNCTION ") + qtSig
// + wxT(" SET ") + configList.Item(i).BeforeFirst('=') + wxT("='") + configList.Item(i).AfterFirst('=') + wxT("';\n");
// else
// sql += wxT("\nALTER FUNCTION ") + qtSig
// + wxT(" SET ") + configList.Item(i).BeforeFirst('=') + wxT("=") + configList.Item(i).AfterFirst('=') + wxT(";\n");
// }
// | SET configuration_parameter { TO value | = value | FROM CURRENT }
for (auto&& cfg : config) {
auto before = cfg.section('=', 0, 0); // before first =
auto after = cfg.section('=', 1, -1); // everything after first =
if (before != "search_path" && before != "temp_tablespaces")
sql += QString("\nALTER FUNCTION %1 SET %2 TO '%3'").arg(quoted_sig, before, after);
else
sql += QString("\nALTER FUNCTION %1 SET %2 TO %3").arg(quoted_sig, before, after);
}
// sql += wxT("\n")
// + GetOwnerSql(8, 0, wxT("FUNCTION ") + qtSig)
// + GetGrant(wxT("X"), wxT("FUNCTION ") + qtSig);
sql += alterOwnerSql("FUNCTION " + quoted_sig);
// if (!GetComment().IsNull())
// {
// sql += wxT("COMMENT ON FUNCTION ") + qtSig