Make DB migrations fully automatic

This commit is contained in:
Bernd Bestel 2017-04-21 11:52:24 +02:00
parent fe8a6d96e4
commit d628f9b3ca
5 changed files with 91 additions and 61 deletions

View File

@ -6,17 +6,21 @@ class Grocy
/** /**
* @return PDO * @return PDO
*/ */
public static function GetDbConnectionRaw() public static function GetDbConnectionRaw($doMigrations = false)
{ {
if ($doMigrations === true)
{
self::$DbConnectionRaw = null;
}
if (self::$DbConnectionRaw == null) if (self::$DbConnectionRaw == null)
{ {
$newDb = !file_exists(__DIR__ . '/data/grocy.db');
$pdo = new PDO('sqlite:' . __DIR__ . '/data/grocy.db'); $pdo = new PDO('sqlite:' . __DIR__ . '/data/grocy.db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if ($newDb) if ($doMigrations === true)
{ {
$pdo->exec("CREATE TABLE migrations (migration INTEGER NOT NULL UNIQUE, execution_time_timestamp DATETIME DEFAULT (datetime('now', 'localtime')), PRIMARY KEY(migration)) WITHOUT ROWID"); Grocy::ExecuteDbStatement($pdo, "CREATE TABLE IF NOT EXISTS migrations (migration INTEGER NOT NULL UNIQUE, execution_time_timestamp DATETIME DEFAULT (datetime('now', 'localtime')), PRIMARY KEY(migration)) WITHOUT ROWID");
GrocyDbMigrator::MigrateDb($pdo); GrocyDbMigrator::MigrateDb($pdo);
if (self::IsDemoInstallation()) if (self::IsDemoInstallation())
@ -35,16 +39,41 @@ class Grocy
/** /**
* @return LessQL\Database * @return LessQL\Database
*/ */
public static function GetDbConnection() public static function GetDbConnection($doMigrations = false)
{ {
if ($doMigrations === true)
{
self::$DbConnection = null;
}
if (self::$DbConnection == null) if (self::$DbConnection == null)
{ {
self::$DbConnection = new LessQL\Database(self::GetDbConnectionRaw()); self::$DbConnection = new LessQL\Database(self::GetDbConnectionRaw($doMigrations));
} }
return self::$DbConnection; return self::$DbConnection;
} }
public static function ExecuteDbStatement(PDO $pdo, string $sql)
{
if ($pdo->exec(utf8_encode($sql)) === false)
{
throw new Exception($pdo->errorInfo());
}
return true;
}
public static function ExecuteDbQuery(PDO $pdo, string $sql)
{
if (self::ExecuteDbStatement($pdo, $sql) === true)
{
return $pdo->query(utf8_encode($sql));
}
return false;
}
public static function IsDemoInstallation() public static function IsDemoInstallation()
{ {
return file_exists(__DIR__ . '/data/demo.txt'); return file_exists(__DIR__ . '/data/demo.txt');

View File

@ -75,14 +75,11 @@ class GrocyDbMigrator
private static function ExecuteMigrationWhenNeeded(PDO $pdo, int $migrationId, string $sql) private static function ExecuteMigrationWhenNeeded(PDO $pdo, int $migrationId, string $sql)
{ {
if ($pdo->query("SELECT COUNT(*) FROM migrations WHERE migration = $migrationId")->fetchColumn() == 0) $rowCount = Grocy::ExecuteDbQuery($pdo, 'SELECT COUNT(*) FROM migrations WHERE migration = ' . $migrationId)->fetchColumn();
if (intval($rowCount) === 0)
{ {
if ($pdo->exec(utf8_encode($sql)) === false) Grocy::ExecuteDbStatement($pdo, $sql);
{ Grocy::ExecuteDbStatement($pdo, 'INSERT INTO migrations (migration) VALUES (' . $migrationId . ')');
throw new Exception($pdo->errorInfo());
}
$pdo->exec('INSERT INTO migrations (migration) VALUES (' . $migrationId . ')');
} }
} }
} }

View File

@ -3,6 +3,9 @@
class GrocyDemoDataGenerator class GrocyDemoDataGenerator
{ {
public static function PopulateDemoData(PDO $pdo) public static function PopulateDemoData(PDO $pdo)
{
$rowCount = Grocy::ExecuteDbQuery($pdo, 'SELECT COUNT(*) FROM migrations WHERE migration = -1')->fetchColumn();
if (intval($rowCount) === 0)
{ {
$sql = " $sql = "
UPDATE locations SET name = 'Vorratskammer', description = '' WHERE id = 1; UPDATE locations SET name = 'Vorratskammer', description = '' WHERE id = 1;
@ -31,12 +34,11 @@ class GrocyDemoDataGenerator
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Gurke', 4, 1, 1, 1); --13 INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Gurke', 4, 1, 1, 1); --13
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Radieschen', 4, 6, 6, 1); --14 INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Radieschen', 4, 6, 6, 1); --14
INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Tomate', 4, 1, 1, 1); --15 INSERT INTO products (name, location_id, qu_id_purchase, qu_id_stock, qu_factor_purchase_to_stock) VALUES ('Tomate', 4, 1, 1, 1); --15
INSERT INTO migrations (migration) VALUES (-1);
"; ";
if ($pdo->exec(utf8_encode($sql)) === false) Grocy::ExecuteDbStatement($pdo, $sql);
{
throw new Exception($pdo->errorInfo());
}
GrocyLogicStock::AddProduct(3, 5, date('Y-m-d', strtotime('+180 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); GrocyLogicStock::AddProduct(3, 5, date('Y-m-d', strtotime('+180 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE);
GrocyLogicStock::AddProduct(4, 5, date('Y-m-d', strtotime('+180 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); GrocyLogicStock::AddProduct(4, 5, date('Y-m-d', strtotime('+180 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE);
@ -52,4 +54,5 @@ class GrocyDemoDataGenerator
GrocyLogicStock::AddProduct(14, 5, date('Y-m-d', strtotime('+2 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); GrocyLogicStock::AddProduct(14, 5, date('Y-m-d', strtotime('+2 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE);
GrocyLogicStock::AddProduct(15, 5, date('Y-m-d', strtotime('-2 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE); GrocyLogicStock::AddProduct(15, 5, date('Y-m-d', strtotime('-2 days')), GrocyLogicStock::TRANSACTION_TYPE_PURCHASE);
} }
}
} }

View File

@ -8,8 +8,7 @@ class GrocyLogicStock
public static function GetCurrentStock() public static function GetCurrentStock()
{ {
$db = Grocy::GetDbConnectionRaw(); return Grocy::ExecuteDbQuery(Grocy::GetDbConnectionRaw(), 'SELECT product_id, SUM(amount) AS amount, MIN(best_before_date) AS best_before_date from stock GROUP BY product_id ORDER BY MIN(best_before_date) ASC')->fetchAll(PDO::FETCH_OBJ);
return $db->query('SELECT product_id, SUM(amount) AS amount, MIN(best_before_date) AS best_before_date from stock GROUP BY product_id ORDER BY MIN(best_before_date) ASC')->fetchAll(PDO::FETCH_OBJ);
} }
public static function GetProductDetails(int $productId) public static function GetProductDetails(int $productId)

View File

@ -36,6 +36,8 @@ $db = Grocy::GetDbConnection();
$app->get('/', function(Request $request, Response $response) use($db) $app->get('/', function(Request $request, Response $response) use($db)
{ {
$db = Grocy::GetDbConnection(true); //For database schema migration
return $this->renderer->render($response, '/layout.php', [ return $this->renderer->render($response, '/layout.php', [
'title' => 'Dashboard', 'title' => 'Dashboard',
'contentPage' => 'dashboard.php', 'contentPage' => 'dashboard.php',
@ -167,7 +169,7 @@ $app->get('/quantityunit/{quantityunitId}', function(Request $request, Response
} }
}); });
$app->group('/api', function() use($db, $app) $app->group('/api', function() use($db)
{ {
$this->get('/get-objects/{entity}', function(Request $request, Response $response, $args) use($db) $this->get('/get-objects/{entity}', function(Request $request, Response $response, $args) use($db)
{ {