From 712960df1826305def34df4b6dd5c4343b8ec09d Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Thu, 9 May 2019 20:35:52 +0100 Subject: Create mock databases in a temporary directory Requires v9.3 server for COPY ... TO PROGRAM ... support, which is used to get the server to create a directory with suitable permissions. This directory is created in the system temporary directory and used as the default tablespace for the mock database. --- libpqpp/pq-mock.cpp | 44 +++++++++++++++++++++++++++++++++++++++++--- libpqpp/pq-mock.h | 3 +++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/libpqpp/pq-mock.cpp b/libpqpp/pq-mock.cpp index 99128c3..499d839 100644 --- a/libpqpp/pq-mock.cpp +++ b/libpqpp/pq-mock.cpp @@ -12,11 +12,18 @@ namespace PQ { Mock::Mock(const std::string & masterdb, const std::string & name, const std::vector & ss) : MockServerDatabase(masterdb, name, "postgresql"), + tablespacePath(std::filesystem::temp_directory_path() / testDbName), serverVersion(std::static_pointer_cast(master)->serverVersion()) { - CreateNewDatabase(); - PlaySchemaScripts(ss); - SetTablesToUnlogged(); + try { + CreateNewDatabase(); + PlaySchemaScripts(ss); + SetTablesToUnlogged(); + } + catch (...) { + DropDatabase(); + throw; + } } AdHocFormatter(MockConnStr, "user=postgres dbname=%?"); @@ -66,6 +73,33 @@ Mock::~Mock() Mock::DropDatabase(); } +bool +Mock::hasCopyToProgram() const +{ + // v9.3 server required to use COPY ... TO PROGRAM ... + return (serverVersion >= 90300); +} + +AdHocFormatter(MockCreateTablespaceDir, "COPY (SELECT 1) TO PROGRAM 'mkdir -p %?'"); +AdHocFormatter(MockCreateTablespace, "CREATE TABLESPACE %? LOCATION '%?'"); +AdHocFormatter(MockCreateDatabase, "CREATE DATABASE %? TABLESPACE %?"); +AdHocFormatter(MockDropTablespace, "DROP TABLESPACE IF EXISTS %?"); +AdHocFormatter(MockDropTablespaceDir, "COPY (SELECT 1) TO PROGRAM 'rm -rf %?'"); + +void +Mock::CreateNewDatabase() const +{ + if (hasCopyToProgram()) { + DropDatabase(); + master->execute(MockCreateTablespaceDir::get(tablespacePath)); + master->execute(MockCreateTablespace::get(testDbName, tablespacePath.string())); + master->execute(MockCreateDatabase::get(testDbName, testDbName)); + } + else { + MockServerDatabase::CreateNewDatabase(); + } +} + void Mock::DropDatabase() const { @@ -73,6 +107,10 @@ Mock::DropDatabase() const t->bindParamS(0, testDbName); t->execute(); MockServerDatabase::DropDatabase(); + if (hasCopyToProgram()) { + master->execute(MockDropTablespace::get(testDbName)); + master->execute(MockDropTablespaceDir::get(tablespacePath)); + } } } diff --git a/libpqpp/pq-mock.h b/libpqpp/pq-mock.h index c802080..b5f4f24 100644 --- a/libpqpp/pq-mock.h +++ b/libpqpp/pq-mock.h @@ -15,8 +15,11 @@ namespace PQ { DB::ConnectionPtr openConnection() const override; protected: + void CreateNewDatabase() const override; void DropDatabase() const override; void SetTablesToUnlogged() const; + bool hasCopyToProgram() const; + const std::filesystem::path tablespacePath; const int serverVersion; }; } -- cgit v1.2.3