Overview of triggers extended with function name and arguments.
Did a lot of refactoring on the catalog to keep things clean.
This commit is contained in:
parent
35813ae926
commit
fcb191f2cc
44 changed files with 797 additions and 404 deletions
|
|
@ -13,7 +13,182 @@
|
|||
#include "PgNamespaceContainer.h"
|
||||
#include "PgDatabaseCatalog.h"
|
||||
|
||||
//inline QString u16(char16_t *utf16)
|
||||
namespace {
|
||||
|
||||
QString escapeInternal(const QString &input, bool as_ident)
|
||||
{
|
||||
int num_quotes = 0; /* single or double, depending on as_ident */
|
||||
int num_backslashes = 0;
|
||||
QChar quote_char = as_ident ? '"' : '\'';
|
||||
// Doorloop input
|
||||
// tel quotes
|
||||
// tel backslashes
|
||||
const int len = input.length();
|
||||
for (int idx = 0; idx < len; ++idx) {
|
||||
QChar c = input[idx];
|
||||
if (c == quote_char)
|
||||
++num_quotes;
|
||||
else if (c == '\\')
|
||||
++num_backslashes;
|
||||
}
|
||||
|
||||
int output_size = len + num_quotes + 2; // + 2 for the quotes
|
||||
if (!as_ident && num_backslashes > 0)
|
||||
output_size += num_backslashes + 2; // +2 so whe can add the " E"
|
||||
QString output;
|
||||
output.reserve(output_size);
|
||||
if (!as_ident && num_backslashes > 0)
|
||||
output += " E";
|
||||
|
||||
output += quote_char;
|
||||
if (num_quotes == 0 && (num_backslashes == 0 || as_ident)) {
|
||||
output += input;
|
||||
}
|
||||
else {
|
||||
for (int idx = 0; idx < len; ++idx) {
|
||||
QChar c = input[idx];
|
||||
output += c;
|
||||
if (c == quote_char || (!as_ident && c == '\\'))
|
||||
output += c;
|
||||
}
|
||||
}
|
||||
output += quote_char;
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QString escapeIdent(const QString &input)
|
||||
{
|
||||
return escapeInternal(input, true);
|
||||
}
|
||||
|
||||
QString escapeLiteral(const QString &input)
|
||||
{
|
||||
return escapeInternal(input, false);
|
||||
}
|
||||
|
||||
//char *
|
||||
//PQescapeInternal(PGconn *conn, const char *str, size_t len, bool as_ident)
|
||||
//{
|
||||
// const char *s;
|
||||
// char *result;
|
||||
// char *rp;
|
||||
// int num_quotes = 0; /* single or double, depending on as_ident */
|
||||
// int num_backslashes = 0;
|
||||
// int input_len;
|
||||
// int result_size;
|
||||
// char quote_char = as_ident ? '"' : '\'';
|
||||
|
||||
//// /* We must have a connection, else fail immediately. */
|
||||
//// if (!conn)
|
||||
//// return NULL;
|
||||
|
||||
// /* Scan the string for characters that must be escaped. */
|
||||
// for (s = str; (s - str) < len && *s != '\0'; ++s)
|
||||
// {
|
||||
// if (*s == quote_char)
|
||||
// ++num_quotes;
|
||||
// else if (*s == '\\')
|
||||
// ++num_backslashes;
|
||||
// else if (IS_HIGHBIT_SET(*s))
|
||||
// {
|
||||
// int charlen;
|
||||
|
||||
// /* Slow path for possible multibyte characters */
|
||||
// charlen = pg_encoding_mblen(conn->client_encoding, s);
|
||||
|
||||
// /* Multibyte character overruns allowable length. */
|
||||
// if ((s - str) + charlen > len || memchr(s, 0, charlen) != NULL)
|
||||
// {
|
||||
// printfPQExpBuffer(&conn->errorMessage,
|
||||
// libpq_gettext("incomplete multibyte character\n"));
|
||||
// return NULL;
|
||||
// }
|
||||
|
||||
// /* Adjust s, bearing in mind that for loop will increment it. */
|
||||
// s += charlen - 1;
|
||||
// }
|
||||
// }
|
||||
|
||||
// /* Allocate output buffer. */
|
||||
// input_len = s - str;
|
||||
// result_size = input_len + num_quotes + 3; /* two quotes, plus a NUL */
|
||||
// if (!as_ident && num_backslashes > 0)
|
||||
// result_size += num_backslashes + 2;
|
||||
// result = rp = (char *) malloc(result_size);
|
||||
// if (rp == NULL)
|
||||
// {
|
||||
// printfPQExpBuffer(&conn->errorMessage,
|
||||
// libpq_gettext("out of memory\n"));
|
||||
// return NULL;
|
||||
// }
|
||||
|
||||
// /*
|
||||
// * If we are escaping a literal that contains backslashes, we use the
|
||||
// * escape string syntax so that the result is correct under either value
|
||||
// * of standard_conforming_strings. We also emit a leading space in this
|
||||
// * case, to guard against the possibility that the result might be
|
||||
// * interpolated immediately following an identifier.
|
||||
// */
|
||||
// if (!as_ident && num_backslashes > 0)
|
||||
// {
|
||||
// *rp++ = ' ';
|
||||
// *rp++ = 'E';1
|
||||
// }
|
||||
|
||||
// /* Opening quote. */
|
||||
// *rp++ = quote_char;
|
||||
|
||||
// /*
|
||||
// * Use fast path if possible.
|
||||
// *
|
||||
// * We've already verified that the input string is well-formed in the
|
||||
// * current encoding. If it contains no quotes and, in the case of
|
||||
// * literal-escaping, no backslashes, then we can just copy it directly to
|
||||
// * the output buffer, adding the necessary quotes.
|
||||
// *
|
||||
// * If not, we must rescan the input and process each character
|
||||
// * individually.
|
||||
// */
|
||||
// if (num_quotes == 0 && (num_backslashes == 0 || as_ident))
|
||||
// {
|
||||
// memcpy(rp, str, input_len);
|
||||
// rp += input_len;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// for (s = str; s - str < input_len; ++s)
|
||||
// {
|
||||
// if (*s == quote_char || (!as_ident && *s == '\\'))
|
||||
// {
|
||||
// *rp++ = *s;
|
||||
// *rp++ = *s;
|
||||
// }
|
||||
// else if (!IS_HIGHBIT_SET(*s))
|
||||
// *rp++ = *s;
|
||||
// else
|
||||
// {
|
||||
// int i = pg_encoding_mblen(conn->client_encoding, s);
|
||||
|
||||
// while (1)
|
||||
// {
|
||||
// *rp++ = *s;
|
||||
// if (--i == 0)
|
||||
// break;
|
||||
// ++s; /* for loop will provide the final increment */
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// /* Closing quote and terminating NUL. */
|
||||
// *rp++ = quote_char;
|
||||
// *rp = '\0';
|
||||
|
||||
// return result;
|
||||
//}
|
||||
|
||||
|
||||
bool identNeedsQuotes(QString ident)
|
||||
{
|
||||
|
|
@ -66,7 +241,7 @@ QString genFQTableName(const PgDatabaseCatalog &catalog, const PgClass &cls)
|
|||
{
|
||||
auto ns = catalog.namespaces()->getByKey(cls.relnamespace);
|
||||
|
||||
return genSchemaPrefix(ns) % quoteIdent(cls.name);
|
||||
return genSchemaPrefix(*ns) % quoteIdent(cls.name);
|
||||
}
|
||||
|
||||
QString genAlterTable(const PgDatabaseCatalog &catalog, const PgClass &cls)
|
||||
|
|
@ -76,8 +251,8 @@ QString genAlterTable(const PgDatabaseCatalog &catalog, const PgClass &cls)
|
|||
|
||||
QString getDropConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstraint &constraint)
|
||||
{
|
||||
PgClass cls = catalog.classes()->getByKey(constraint.relid);
|
||||
return genAlterTable(catalog, cls) % " DROP CONSTRAINT " % quoteIdent(constraint.name) % ";";
|
||||
const PgClass *cls = catalog.classes()->getByKey(constraint.relid);
|
||||
return genAlterTable(catalog, *cls) % " DROP CONSTRAINT " % quoteIdent(constraint.name) % ";";
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -101,7 +276,7 @@ QString getColumnNameList(const PgDatabaseCatalog &catalog, Oid relid, const Sma
|
|||
|
||||
const auto ac = catalog.attributes();
|
||||
for (auto an : attnums) {
|
||||
result.add(ac->getByKey({ relid, an }).name);
|
||||
result.add(ac->getByKey({ relid, an })->name);
|
||||
}
|
||||
return result.str();
|
||||
}
|
||||
|
|
@ -109,7 +284,7 @@ QString getColumnNameList(const PgDatabaseCatalog &catalog, Oid relid, const Sma
|
|||
QString getForeignKeyConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstraint &constraint)
|
||||
{
|
||||
//PgClass cls = catalog.classes()->getByKey(constraint.relid);
|
||||
PgClass fcls = catalog.classes()->getByKey(constraint.frelid);
|
||||
const PgClass *fcls = catalog.classes()->getByKey(constraint.frelid);
|
||||
QString deferrable;
|
||||
QString validated;
|
||||
if (!constraint.validated)
|
||||
|
|
@ -120,7 +295,7 @@ QString getForeignKeyConstraintDefinition(const PgDatabaseCatalog &catalog, cons
|
|||
|
||||
return "\n FOREIGN KEY ("
|
||||
% getColumnNameList(catalog, constraint.relid, constraint.key) % ")\n REFERENCES "
|
||||
% genFQTableName(catalog, fcls) % " ("
|
||||
% genFQTableName(catalog, *fcls) % " ("
|
||||
% getColumnNameList(catalog, constraint.frelid, constraint.fkey) % ")\n MATCH "
|
||||
% ForeignKeyMatchToString(constraint.fmatchtype)
|
||||
% " ON UPDATE " % ForeignKeyActionToString(constraint.fupdtype)
|
||||
|
|
@ -130,7 +305,7 @@ QString getForeignKeyConstraintDefinition(const PgDatabaseCatalog &catalog, cons
|
|||
|
||||
QString getForeignKeyConstraintReferences(const PgDatabaseCatalog &catalog, const PgConstraint &constraint)
|
||||
{
|
||||
PgClass fcls = catalog.classes()->getByKey(constraint.frelid);
|
||||
const PgClass *fcls = catalog.classes()->getByKey(constraint.frelid);
|
||||
QString deferrable;
|
||||
QString validated;
|
||||
if (!constraint.validated)
|
||||
|
|
@ -140,7 +315,7 @@ QString getForeignKeyConstraintReferences(const PgDatabaseCatalog &catalog, cons
|
|||
}
|
||||
|
||||
return "REFERENCES "
|
||||
% genFQTableName(catalog, fcls) % " ("
|
||||
% genFQTableName(catalog, *fcls) % " ("
|
||||
% getColumnNameList(catalog, constraint.frelid, constraint.fkey) % ") MATCH "
|
||||
% ForeignKeyMatchToString(constraint.fmatchtype)
|
||||
% " ON UPDATE " % ForeignKeyActionToString(constraint.fupdtype)
|
||||
|
|
@ -152,7 +327,7 @@ QString getForeignKeyConstraintReferences(const PgDatabaseCatalog &catalog, cons
|
|||
|
||||
QString getForeignKeyConstraintReferencesShort(const PgDatabaseCatalog &catalog, const PgConstraint &constraint)
|
||||
{
|
||||
PgClass fcls = catalog.classes()->getByKey(constraint.frelid);
|
||||
const PgClass *fcls = catalog.classes()->getByKey(constraint.frelid);
|
||||
QString deferrable;
|
||||
QString validated;
|
||||
if (!constraint.validated)
|
||||
|
|
@ -164,7 +339,7 @@ QString getForeignKeyConstraintReferencesShort(const PgDatabaseCatalog &catalog,
|
|||
QString on_delete = constraint.fdeltype == ForeignKeyAction::NoAction ? QString() : " ON DELETE " % ForeignKeyActionToString(constraint.fdeltype);
|
||||
QString match_type = constraint.fmatchtype == ForeignKeyMatch::Simple ? QString() : " MATCH " % ForeignKeyMatchToString(constraint.fmatchtype);
|
||||
|
||||
return genFQTableName(catalog, fcls) % " ("
|
||||
return genFQTableName(catalog, *fcls) % " ("
|
||||
% getColumnNameList(catalog, constraint.frelid, constraint.fkey) % ")"
|
||||
% match_type
|
||||
% on_update
|
||||
|
|
@ -191,10 +366,10 @@ QString getUniqueConstraintDefinition(const PgDatabaseCatalog &catalog, const Pg
|
|||
|
||||
QString getConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstraint &constraint)
|
||||
{
|
||||
PgClass cls = catalog.classes()->getByKey(constraint.relid);
|
||||
const PgClass *cls = catalog.classes()->getByKey(constraint.relid);
|
||||
// return genAlterTable(catalog, cls) % " ADD CONSTRAINT "
|
||||
// % quoteIdent(constraint.name) % " " % constraint.definition % ";";
|
||||
QString result = genAlterTable(catalog, cls) % "\n ADD CONSTRAINT "
|
||||
QString result = genAlterTable(catalog, *cls) % "\n ADD CONSTRAINT "
|
||||
% quoteIdent(constraint.name);
|
||||
switch (constraint.type) {
|
||||
case ConstraintType::ForeignKey:
|
||||
|
|
@ -216,8 +391,8 @@ QString getConstraintDefinition(const PgDatabaseCatalog &catalog, const PgConstr
|
|||
|
||||
QString getIndexDefinition(const PgDatabaseCatalog &catalog, const PgIndex &index)
|
||||
{
|
||||
PgClass table_class = catalog.classes()->getByKey(index.relid);
|
||||
PgClass index_class = catalog.classes()->getByKey(index.indexrelid);
|
||||
// const PgClass *table_class = catalog.classes()->getByKey(index.relid);
|
||||
// const PgClass *index_class = catalog.classes()->getByKey(index.indexrelid);
|
||||
|
||||
|
||||
return index.definition + ";";
|
||||
|
|
@ -267,8 +442,8 @@ QString getIndexDefinition(const PgDatabaseCatalog &catalog, const PgIndex &inde
|
|||
|
||||
QString getDropIndexDefinition(const PgDatabaseCatalog &catalog, const PgIndex &index)
|
||||
{
|
||||
PgClass table_class = catalog.classes()->getByKey(index.relid);
|
||||
PgClass index_class = catalog.classes()->getByKey(index.indexrelid);
|
||||
// const PgClass *table_class = catalog.classes()->getByKey(index.relid);
|
||||
// const PgClass *index_class = catalog.classes()->getByKey(index.indexrelid);
|
||||
|
||||
QString result;
|
||||
result = "DROP INDEX "
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue