1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 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 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
|
#include "viewmodifier.h"
#include "common/utils_sql.h"
#include "parser/parser.h"
#include "schemaresolver.h"
#include "selectresolver.h"
#include "parser/ast/sqlitecreatetrigger.h"
#include "common/unused.h"
ViewModifier::ViewModifier(Db* db, const QString& view) :
ViewModifier(db, "main", view)
{
}
ViewModifier::ViewModifier(Db* db, const QString& database, const QString& view) :
db(db), database(database), view(view)
{
}
void ViewModifier::alterView(const QString& newView)
{
Parser parser;
if (!parser.parse(newView) || parser.getQueries().size() == 0)
{
errors << QObject::tr("Could not parse DDL of the view to be created. Details: %1").arg(parser.getErrorString());
return;
}
SqliteQueryPtr query = parser.getQueries().first();
createView = query.dynamicCast<SqliteCreateView>();
if (!createView)
{
errors << QObject::tr("Parsed query is not CREATE VIEW. It's: %1").arg(sqliteQueryTypeToString(query->queryType));
return;
}
alterView(createView);
}
void ViewModifier::alterView(SqliteCreateViewPtr newView)
{
createView = newView;
addMandatorySql(QString("DROP VIEW %1").arg(wrapObjIfNeeded(view)));
addMandatorySql(newView->detokenize());
collectNewColumns();
handleTriggers();
// TODO handle other views selecting from this view
}
void ViewModifier::handleTriggers()
{
SchemaResolver resolver(db);
QList<SqliteCreateTriggerPtr> triggers = resolver.getParsedTriggersForView(view, true);
for (SqliteCreateTriggerPtr trigger : triggers)
{
addOptionalSql(QString("DROP TRIGGER %1").arg(wrapObjIfNeeded(trigger->trigger)));
if (!handleNewColumns(trigger))
continue;
addOptionalSql(trigger->detokenize());
}
}
bool ViewModifier::handleNewColumns(SqliteCreateTriggerPtr trigger)
{
UNUSED(trigger);
// TODO update all occurances of columns in "UPDATE OF" and statements inside, just like it would be done in TableModifier.
return true;
}
void ViewModifier::collectNewColumns()
{
SelectResolver resolver(db, createView->select->detokenize());
QList<QList<SelectResolver::Column> > multiColumns = resolver.resolve(createView->select);
if (multiColumns.size() < 1)
{
warnings << QObject::tr("SQLiteStudio was unable to resolve columns returned by the new view, "
"therefore it won't be able to tell which triggers might fail during the recreation process.");
return;
}
for (const SelectResolver::Column& col : multiColumns.first())
newColumns << col.column;
}
void ViewModifier::addMandatorySql(const QString& sql)
{
sqls << sql;
sqlMandatoryFlags << true;
}
void ViewModifier::addOptionalSql(const QString& sql)
{
sqls << sql;
sqlMandatoryFlags << false;
}
QStringList ViewModifier::generateSqls() const
{
return sqls;
}
QList<bool> ViewModifier::getMandatoryFlags() const
{
return sqlMandatoryFlags;
}
QStringList ViewModifier::getWarnings() const
{
return warnings;
}
QStringList ViewModifier::getErrors() const
{
return errors;
}
bool ViewModifier::hasMessages() const
{
return errors.size() > 0 || warnings.size() > 0;
}
|