LeechCraft  0.6.70-15082-g543737046d
Modular cross-platform feature rich live environment.
migrate.h
Go to the documentation of this file.
1 /**********************************************************************
2  * LeechCraft - modular cross-platform feature rich internet client.
3  * Copyright (C) 2006-2014 Georg Rudoy
4  *
5  * Distributed under the Boost Software License, Version 1.0.
6  * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7  **********************************************************************/
8 
9 #pragma once
10 
11 #include "util/db/oral/oral.h"
12 
13 namespace LC
14 {
15 namespace Util
16 {
17 namespace oral
18 {
19  namespace detail
20  {
21  bool MatchesSchema (const QString& baseName, const QString& schema, QSqlDatabase& db)
22  {
23  auto result = Util::RunTextQuery (db,
24  QString { "SELECT sql FROM sqlite_master WHERE type = 'table' AND name = '%1'" }
25  .arg (baseName));
26  if (!result.next ())
27  return true;
28 
29  const auto& existingDDL = result.value (0).toString ();
30 
31  auto figureOutFields = [] (const QString& str)
32  {
33  auto firstOpen = str.indexOf ('(');
34  auto lastClose = str.lastIndexOf (')');
35  return str.midRef (firstOpen, lastClose - firstOpen);
36  };
37  auto existing = figureOutFields (existingDDL);
38  auto suggested = figureOutFields (schema);
39  return existing == suggested;
40  }
41  }
42 
43  template<typename Record, typename ImplFactory = SQLiteImplFactory>
44  void Migrate (QSqlDatabase& db)
45  {
46  const auto& baseName = Record::ClassName ();
47 
48  const auto& thisName = "copy" + baseName;
49  const auto& schema = detail::AdaptCreateTable<ImplFactory, Record> (detail::BuildCachedFieldsData<Record> (thisName));
50 
51  if (detail::MatchesSchema (baseName, schema, db))
52  {
53  qDebug () << Q_FUNC_INFO
54  << "not migrating"
55  << db.connectionName ();
56  return;
57  }
58 
59  qDebug () << Q_FUNC_INFO
60  << "migrating"
61  << db.connectionName ();
62 
63  Util::DBLock lock { db };
64  lock.Init ();
65 
66  Util::RunTextQuery (db, schema);
67 
68  const auto& fields = detail::GetFieldsNames<Record> {} ().join (", ");
69 
71  QString { "INSERT INTO %2 (%1) SELECT %1 FROM %3;" }
72  .arg (fields)
73  .arg (thisName)
74  .arg (baseName));
75 
77  QString { "DROP TABLE %1;" }
78  .arg (baseName));
80  QString { "ALTER TABLE %1 RENAME TO %2;" }
81  .arg (thisName)
82  .arg (baseName));
83 
84  lock.Good ();
85  }
86 }
87 }
88 }
LC::Util::oral::Migrate
void Migrate(QSqlDatabase &db)
Definition: migrate.h:62
LC::Util::oral::sph::fields
constexpr detail::MemberPtrs< Ptrs... > fields
Definition: oral.h:955
LC::Util::DBLock::Init
UTIL_DB_API void Init()
Initializes the transaction.
Definition: dblock.cpp:51
LC::Util::RunTextQuery
QSqlQuery RunTextQuery(const QSqlDatabase &db, const QString &text)
Runs the given query text on the given db.
Definition: util.cpp:24
LC
Definition: constants.h:14
LC::Util::oral::detail::MatchesSchema
bool MatchesSchema(const QString &baseName, const QString &schema, QSqlDatabase &db)
Definition: migrate.h:45
oral.h
LC::Util::DBLock
Provides database transaction lock.
Definition: dblock.h:41