mirror of
https://github.com/silverqx/TinyORM.git
synced 2026-04-28 20:50:23 -05:00
a6213a6a9d
Almost everything is implemented, possible to migrate up, down (rollback), migrate by steps (works for up/down too), reset, refresh, fresh, wipe database, showing status, installing migration table. Command line interface is superb, it supports ansi coloring, verbosity, no-interactive mode, force option, env option to select current env. It has enhanced ansi coloring (vt100 terminal) detection, when ansi or no-ansi option is not passed it can detect whether terminal supports coloring. Ansi coloring is disabled when redirection to file is detected (can be overridden by ansi/no-ansi options). Supports NO_COLOR env. variable (https://no-color.org/) and can detect the ConEmu, Hyper, and xterm on Windows. Carefully implemented help and list commands, list command can print supported commands by namespace. Advanced make migration command offers great command interface for creating migration classes, supports options for generating empty, create, or update migration classes. Unfinished make project command, will support creating qmake, qmake subproject, and cmake, cmake subproject projects. Later will be extracted to own executable tomproject.exe for rapidly generating a new TinyORM projects. Other implemented commands are env that prints current env. and inspire that displays an inspiring quote 😁. Verbose supports 5 levels quiet, normal, verbose, very verbose, and debug. Possibility to disable compilation of the tom command related code using TINYORM_DISABLE_TOM c macro, for the qmake exists disable_tom CONFIG option and for the CMake exist TOM configuration option. Confirmable interface that ask Y/N confirmation during migrate when env. == production, can be overridden by --force option. Whole tom terminal application supports or is implemented with UTF-8 support, also implemented UTF-16 output methods but they are not needed. Input also supports UTF-8, currently only Y/N input is needed by the Confirmation concern. All migrate commands also support the --pretend option and the --env option, when env. is production then tom asks confirmation to migrate, it can be overridden by the --force option. Added the tom example project, it is a complete command-line migration application, it uses migrations from the tests. Implementing this was really fun 🙃😎. - added 14 functional tests to test migrations up/down, stepping, installing migration table, refresh, reset on MySQL database - added unit test to check version number in tom.exe executable - new tom exception classes - created dozens of a new todo tasks 😂🤪, currently 348 todos 😎 - added some info messages to the qmake build about building features - in the debug build and with the -vvv option enable debugging of sql queries - enhanced RC and manifest file generation, allowed to pass a custom basename for a RC/manifest file as the 3. argument and a custom replace token for the CMake genex as the 4. argument - bugfix disabled #pragma code_page(65001) // UTF-8 in RC files, it messes up the © character Output of tom exe without arguments and options: Common options: --ansi Force ANSI output --no-ansi Disable ANSI output --env The environment the command should run under -h, --help Display help for the given command. When no command is given display help for the list command -n, --no-interaction Do not ask any interactive question -q, --quiet Do not output any message -V, --version Display this application version -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug Available commands: env Display the current framework environment help Display help for a command inspire Display an inspiring quote list List commands migrate Run the database migrations db db:wipe Drop all tables, views, and types make make:migration Create a new migration file make:project Create a new Tom application project migrate migrate:fresh Drop all tables and re-run all migrations migrate:install Create the migration repository migrate:refresh Rollback and re-run all migrations migrate:reset Rollback all database migrations migrate:rollback Rollback the last database migration migrate:status Show the status of each migration
586 lines
16 KiB
C++
586 lines
16 KiB
C++
#include <QCoreApplication>
|
|
#include <QtTest>
|
|
|
|
#include "tom/application.hpp"
|
|
#include "tom/commands/migrations/statuscommand.hpp"
|
|
|
|
#include "databases.hpp"
|
|
|
|
#include "migrations/2014_10_12_000000_create_posts_table.hpp"
|
|
#include "migrations/2014_10_12_100000_add_factor_column_to_posts_table.hpp"
|
|
#include "migrations/2014_10_12_200000_create_properties_table.hpp"
|
|
#include "migrations/2014_10_12_300000_create_phones_table.hpp"
|
|
|
|
using namespace Migrations; // NOLINT(google-build-using-namespace)
|
|
|
|
using TomApplication = Tom::Application;
|
|
|
|
using Tom::Commands::Migrations::StatusCommand;
|
|
|
|
using TestUtils::Databases;
|
|
|
|
class tst_Migrate : public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
public:
|
|
/*! Alias for the test output row. */
|
|
using StatusRow = StatusCommand::StatusRow;
|
|
/*! Type used for comparing results of the status command. */
|
|
using Status = std::vector<StatusRow>;
|
|
|
|
private slots:
|
|
void initTestCase();
|
|
void cleanup() const;
|
|
|
|
void reset() const;
|
|
|
|
void migrate() const;
|
|
void migrate_Step() const;
|
|
|
|
void rollback_OnMigrate() const;
|
|
void rollback_OnMigrateWithStep() const;
|
|
|
|
void rollback_Step_OnMigrate() const;
|
|
void rollback_Step_OnMigrateWithStep() const;
|
|
|
|
void refresh_OnMigrate() const;
|
|
void refresh_OnMigrateWithStep() const;
|
|
|
|
void refresh_Step() const;
|
|
void refresh_StepMigrate() const;
|
|
void refresh_Step_StepMigrate() const;
|
|
|
|
// NOLINTNEXTLINE(readability-redundant-access-specifiers)
|
|
private:
|
|
/*! Prepare arguments and invoke runCommand(). */
|
|
[[nodiscard]] int
|
|
invokeCommand(const QString &name, std::vector<const char *> &&arguments = {}) const;
|
|
/*! Create a tom application instance and invoke the given command. */
|
|
int runCommand(int &argc, const std::vector<const char *> &argv) const;
|
|
|
|
/*! Invoke the status command to obtain results. */
|
|
inline int invokeTestStatusCommand() const;
|
|
/*! Get result of the last status command. */
|
|
Status status() const;
|
|
/*! Create a status object for comparing with the result of the status(). */
|
|
Status createStatus(std::initializer_list<StatusRow> rows) const;
|
|
/*! Create a status object to be equal after complete rollback. */
|
|
Status createResetStatus() const;
|
|
|
|
/*! Connection name used in this test case. */
|
|
QString m_connection {};
|
|
};
|
|
|
|
/*! Alias for the test output row. */
|
|
using Status = tst_Migrate::Status;
|
|
/*! Type used for comparing results of the status command. */
|
|
using StatusRow = tst_Migrate::StatusRow;
|
|
|
|
/* Extracted common code to re-use. */
|
|
namespace
|
|
{
|
|
// Status
|
|
inline const auto *Yes = "Yes";
|
|
inline const auto *No = "No";
|
|
|
|
// Batches
|
|
inline const auto *s_1 = "1";
|
|
inline const auto *s_2 = "2";
|
|
inline const auto *s_3 = "3";
|
|
inline const auto *s_4 = "4";
|
|
|
|
// Migration names
|
|
inline const auto *
|
|
s_2014_10_12_000000_create_posts_table =
|
|
"2014_10_12_000000_create_posts_table";
|
|
inline const auto *
|
|
s_2014_10_12_100000_add_factor_column_to_posts_table =
|
|
"2014_10_12_100000_add_factor_column_to_posts_table";
|
|
inline const auto *
|
|
s_2014_10_12_200000_create_properties_table =
|
|
"2014_10_12_200000_create_properties_table";
|
|
inline const auto *
|
|
s_2014_10_12_300000_create_phones_table =
|
|
"2014_10_12_300000_create_phones_table";
|
|
|
|
// Fully migrated w/o --step
|
|
inline const std::initializer_list<StatusRow>
|
|
FullyMigrated = {
|
|
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
|
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_1},
|
|
{Yes, s_2014_10_12_200000_create_properties_table, s_1},
|
|
{Yes, s_2014_10_12_300000_create_phones_table, s_1},
|
|
};
|
|
|
|
// Fully migrated with --step
|
|
inline const std::initializer_list<StatusRow>
|
|
FullyStepMigrated = {
|
|
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
|
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_2},
|
|
{Yes, s_2014_10_12_200000_create_properties_table, s_3},
|
|
{Yes, s_2014_10_12_300000_create_phones_table, s_4},
|
|
};
|
|
|
|
} // namespace
|
|
|
|
/* private slots */
|
|
|
|
void tst_Migrate::initTestCase()
|
|
{
|
|
m_connection = Databases::createConnection(Databases::MYSQL);
|
|
|
|
if (m_connection.isEmpty())
|
|
QSKIP(QStringLiteral("%1 autotest skipped, environment variables "
|
|
"for '%2' connection have not been defined.")
|
|
.arg("tst_Migrate", Databases::MYSQL).toUtf8().constData(), );
|
|
|
|
/* Modify the migrate:status command to not output a status table to the console but
|
|
instead return a result as the vector, this vector is then used for comparing
|
|
results. */
|
|
TomApplication::enableInUnitTests();
|
|
}
|
|
|
|
void tst_Migrate::cleanup() const
|
|
{
|
|
/* All test methods need this except for two of them (reset and I don't remember
|
|
second), I will not implement special logic to skip this for these two methods. */
|
|
{
|
|
auto exitCode = invokeCommand("migrate:reset");
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createResetStatus(), status());
|
|
}
|
|
}
|
|
|
|
void tst_Migrate::reset() const
|
|
{
|
|
{
|
|
auto exitCode = invokeCommand("migrate:reset");
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createResetStatus(), status());
|
|
}
|
|
}
|
|
|
|
void tst_Migrate::migrate() const
|
|
{
|
|
{
|
|
auto exitCode = invokeCommand("migrate");
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyMigrated), status());
|
|
}
|
|
}
|
|
|
|
void tst_Migrate::migrate_Step() const
|
|
{
|
|
{
|
|
auto exitCode = invokeCommand("migrate", {"--step"});
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyStepMigrated), status());
|
|
}
|
|
}
|
|
|
|
void tst_Migrate::rollback_OnMigrate() const
|
|
{
|
|
{
|
|
auto exitCode = invokeCommand("migrate");
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyMigrated), status());
|
|
}
|
|
|
|
// rollback on previous migrate w/o --step
|
|
{
|
|
auto exitCode = invokeCommand("migrate:rollback");
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createResetStatus(), status());
|
|
}
|
|
}
|
|
|
|
void tst_Migrate::rollback_OnMigrateWithStep() const
|
|
{
|
|
{
|
|
auto exitCode = invokeCommand("migrate", {"--step"});
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyStepMigrated), status());
|
|
}
|
|
|
|
// rollback on previous migrate with --step
|
|
{
|
|
auto exitCode = invokeCommand("migrate:rollback");
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus({
|
|
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
|
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_2},
|
|
{Yes, s_2014_10_12_200000_create_properties_table, s_3},
|
|
{No, s_2014_10_12_300000_create_phones_table},
|
|
}), status());
|
|
}
|
|
}
|
|
|
|
void tst_Migrate::rollback_Step_OnMigrate() const
|
|
{
|
|
{
|
|
auto exitCode = invokeCommand("migrate");
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyMigrated), status());
|
|
}
|
|
|
|
// rollback on previous migrate w/o --step
|
|
{
|
|
auto exitCode = invokeCommand("migrate:rollback", {"--step=2"});
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus({
|
|
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
|
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_1},
|
|
{No, s_2014_10_12_200000_create_properties_table},
|
|
{No, s_2014_10_12_300000_create_phones_table},
|
|
}), status());
|
|
}
|
|
}
|
|
|
|
void tst_Migrate::rollback_Step_OnMigrateWithStep() const
|
|
{
|
|
{
|
|
auto exitCode = invokeCommand("migrate", {"--step"});
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyStepMigrated), status());
|
|
}
|
|
|
|
// rollback on previous migrate with --step
|
|
{
|
|
auto exitCode = invokeCommand("migrate:rollback", {"--step=2"});
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus({
|
|
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
|
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_2},
|
|
{No, s_2014_10_12_200000_create_properties_table},
|
|
{No, s_2014_10_12_300000_create_phones_table},
|
|
}), status());
|
|
}
|
|
}
|
|
|
|
void tst_Migrate::refresh_OnMigrate() const
|
|
{
|
|
{
|
|
auto exitCode = invokeCommand("migrate");
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyMigrated), status());
|
|
}
|
|
|
|
// refresh on previous migrate w/o --step
|
|
{
|
|
auto exitCode = invokeCommand("migrate:refresh");
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyMigrated), status());
|
|
}
|
|
}
|
|
|
|
void tst_Migrate::refresh_OnMigrateWithStep() const
|
|
{
|
|
{
|
|
auto exitCode = invokeCommand("migrate", {"--step"});
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyStepMigrated), status());
|
|
}
|
|
|
|
// refresh on previous migrate with --step
|
|
{
|
|
auto exitCode = invokeCommand("migrate:refresh");
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyMigrated), status());
|
|
}
|
|
}
|
|
|
|
void tst_Migrate::refresh_Step() const
|
|
{
|
|
{
|
|
auto exitCode = invokeCommand("migrate");
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyMigrated), status());
|
|
}
|
|
|
|
// refresh on previous migrate w/o --step
|
|
{
|
|
auto exitCode = invokeCommand("migrate:refresh", {"--step=2"});
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus({
|
|
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
|
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_1},
|
|
{Yes, s_2014_10_12_200000_create_properties_table, s_2},
|
|
{Yes, s_2014_10_12_300000_create_phones_table, s_2},
|
|
}), status());
|
|
}
|
|
}
|
|
|
|
void tst_Migrate::refresh_StepMigrate() const
|
|
{
|
|
{
|
|
auto exitCode = invokeCommand("migrate");
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyMigrated), status());
|
|
}
|
|
|
|
// refresh on previous migrate w/o --step
|
|
{
|
|
auto exitCode = invokeCommand("migrate:refresh", {"--step-migrate"});
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyStepMigrated), status());
|
|
}
|
|
}
|
|
|
|
void tst_Migrate::refresh_Step_StepMigrate() const
|
|
{
|
|
{
|
|
auto exitCode = invokeCommand("migrate");
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus(FullyMigrated), status());
|
|
}
|
|
|
|
// refresh on previous migrate w/o --step
|
|
{
|
|
auto exitCode = invokeCommand("migrate:refresh", {"--step=2", "--step-migrate"});
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
}
|
|
|
|
{
|
|
auto exitCode = invokeTestStatusCommand();
|
|
|
|
QVERIFY(exitCode == EXIT_SUCCESS);
|
|
QCOMPARE(createStatus({
|
|
{Yes, s_2014_10_12_000000_create_posts_table, s_1},
|
|
{Yes, s_2014_10_12_100000_add_factor_column_to_posts_table, s_1},
|
|
{Yes, s_2014_10_12_200000_create_properties_table, s_2},
|
|
{Yes, s_2014_10_12_300000_create_phones_table, s_3},
|
|
}), status());
|
|
}
|
|
}
|
|
|
|
/* private */
|
|
|
|
int tst_Migrate::invokeCommand(const QString &name,
|
|
std::vector<const char *> &&arguments) const
|
|
{
|
|
static const auto connectionTmpl = QStringLiteral("--database=%1");
|
|
|
|
// Prepare fake argc and argv
|
|
const auto nameArr = name.toUtf8();
|
|
// FUTURE tests tom, when the schema builder will support more db drivers, I can run it on all supported connections, code will look like in the tst_querybuilder.cpp, then I will fetch connection name in every test method using QFETCH_GLOBAL() and I will pass this connection name to the invokeCommand(), so I will discard m_connection and will use method parameter connection here silverqx
|
|
/* Schema builder is implemented only for the MySQL driver, so I can use m_connection
|
|
here as the default connection. */
|
|
// DB connection to use
|
|
const auto connectionArr = connectionTmpl.arg(m_connection).toUtf8();
|
|
|
|
std::vector<const char *> argv {
|
|
#ifdef _WIN32
|
|
"tom.exe",
|
|
#else
|
|
"tom",
|
|
#endif
|
|
nameArr.constData(),
|
|
connectionArr.constData(),
|
|
};
|
|
std::ranges::move(arguments, std::back_inserter(argv));
|
|
|
|
int argc = static_cast<int>(argv.size());
|
|
|
|
return runCommand(argc, argv);
|
|
}
|
|
|
|
int tst_Migrate::runCommand(int &argc, const std::vector<const char *> &argv) const
|
|
{
|
|
try {
|
|
// env. should be always development so passed {} for env. name
|
|
return TomApplication(argc, const_cast<char **>(argv.data()),
|
|
Databases::manager(), {})
|
|
.migrations<
|
|
_2014_10_12_000000_create_posts_table,
|
|
_2014_10_12_100000_add_factor_column_to_posts_table,
|
|
_2014_10_12_200000_create_properties_table,
|
|
_2014_10_12_300000_create_phones_table>()
|
|
// Fire it up 🔥🚀✨
|
|
.runWithArguments({argv.cbegin(), argv.cend()});
|
|
|
|
} catch (const std::exception &e) {
|
|
|
|
TomApplication::logException(e, true);
|
|
}
|
|
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
int tst_Migrate::invokeTestStatusCommand() const
|
|
{
|
|
return invokeCommand("migrate:status");
|
|
}
|
|
|
|
Status tst_Migrate::status() const
|
|
{
|
|
return TomApplication::status();
|
|
}
|
|
|
|
Status tst_Migrate::createStatus(std::initializer_list<StatusRow> rows) const
|
|
{
|
|
return Status({rows});
|
|
}
|
|
|
|
Status tst_Migrate::createResetStatus() const
|
|
{
|
|
return Status({
|
|
{No, s_2014_10_12_000000_create_posts_table},
|
|
{No, s_2014_10_12_100000_add_factor_column_to_posts_table},
|
|
{No, s_2014_10_12_200000_create_properties_table},
|
|
{No, s_2014_10_12_300000_create_phones_table},
|
|
});
|
|
}
|
|
|
|
QTEST_MAIN(tst_Migrate)
|
|
|
|
#include "tst_migrate.moc"
|