Bugfix: dataBaseUpgrade always runs on sqlite and pgsql

And split the db schema data into seperate class
This commit is contained in:
the-djmaze 2024-01-17 00:12:01 +01:00
parent e965d58de0
commit b89a1b309c
4 changed files with 268 additions and 230 deletions

View file

@ -257,51 +257,7 @@ abstract class Base
$oPdo = $this->getPDO();
if ($oPdo) {
$aQ = array();
switch ($this->sDbType)
{
case 'mysql':
$aQ[] = 'CREATE TABLE IF NOT EXISTS rainloop_system (
sys_name varchar(64) NOT NULL,
value_int int UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (sys_name)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;';
$aQ[] = 'CREATE TABLE IF NOT EXISTS rainloop_users (
id_user int UNSIGNED NOT NULL AUTO_INCREMENT,
rl_email varchar(254) NOT NULL,
PRIMARY KEY (id_user),
UNIQUE KEY ui_rainloop_users_email (rl_email)
);';
break;
case 'pgsql':
$aQ[] = 'CREATE TABLE rainloop_system (
sys_name varchar(50) NOT NULL,
value_int integer NOT NULL DEFAULT 0
);';
$aQ[] = 'CREATE INDEX sys_name_rainloop_system_index ON rainloop_system (sys_name);';
$aQ[] = 'CREATE SEQUENCE id_user START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;';
$aQ[] = 'CREATE TABLE rainloop_users (
id_user integer DEFAULT nextval(\'id_user\'::text) PRIMARY KEY,
rl_email varchar(254) NOT NULL DEFAULT \'\'
);';
$aQ[] = 'CREATE INDEX rl_email_rainloop_users_index ON rainloop_users (rl_email);';
break;
case 'sqlite':
$aQ[] = 'CREATE TABLE rainloop_system (
sys_name text NOT NULL,
value_int integer NOT NULL DEFAULT 0
);';
$aQ[] = 'CREATE UNIQUE INDEX ui_rainloop_system_sys_name ON rainloop_system (sys_name);';
$aQ[] = 'CREATE TABLE rainloop_users (
id_user integer NOT NULL PRIMARY KEY,
rl_email text NOT NULL DEFAULT \'\'
);';
$aQ[] = 'CREATE INDEX rl_email_rainloop_users_index ON rainloop_users (rl_email);';
break;
}
$aQ = Schema::getForDbType($this->sDbType);
if (\count($aQ)) {
try
{
@ -352,41 +308,36 @@ rl_email text NOT NULL DEFAULT \'\'
$bResult = false;
if (\is_int($iFromVersion) && 0 <= $iFromVersion) {
$oPdo = false;
foreach ($aData as $iVersion => $aQuery) {
if (0 === \count($aQuery)) {
continue;
}
if (!$oPdo) {
$oPdo = $this->getPDO();
$bResult = true;
}
if ($iFromVersion < $iVersion && $oPdo) {
try
{
foreach ($aQuery as $sQuery) {
$this->writeLog($sQuery);
$bExec = $oPdo->exec($sQuery);
if (false === $bExec) {
$this->writeLog('Result: false');
$bResult = false;
if ($iFromVersion < $iVersion) {
if (\count($aQuery)) {
if (!$oPdo) {
$oPdo = $this->getPDO();
$bResult = true;
}
if ($oPdo) {
try
{
foreach ($aQuery as $sQuery) {
$this->writeLog($sQuery);
$bExec = $oPdo->exec($sQuery);
if (false === $bExec) {
$this->writeLog('Result: false');
$bResult = false;
break;
}
}
}
catch (\Throwable $oException)
{
$this->writeLog($oException);
throw $oException;
}
if (!$bResult) {
break;
}
}
}
catch (\Throwable $oException)
{
$this->writeLog($oException);
throw $oException;
}
if (!$bResult) {
break;
}
$this->setVersion($sName, $iVersion);
}
}

View file

@ -0,0 +1,68 @@
<?php
namespace RainLoop\Pdo;
abstract class Schema
{
public static function mysql() : array
{
return [
'CREATE TABLE IF NOT EXISTS rainloop_system (
sys_name varchar(64) NOT NULL,
value_int int UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (sys_name)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;',
'CREATE TABLE IF NOT EXISTS rainloop_users (
id_user int UNSIGNED NOT NULL AUTO_INCREMENT,
rl_email varchar(254) NOT NULL,
PRIMARY KEY (id_user),
UNIQUE KEY ui_rainloop_users_email (rl_email)
);'
];
}
public static function pgsql() : array
{
return [
'CREATE TABLE rainloop_system (
sys_name varchar(50) NOT NULL,
value_int integer NOT NULL DEFAULT 0
);',
'CREATE INDEX sys_name_rainloop_system_index ON rainloop_system (sys_name);',
'CREATE SEQUENCE id_user START WITH 1 INCREMENT BY 1 NO MAXVALUE NO MINVALUE CACHE 1;',
'CREATE TABLE rainloop_users (
id_user integer DEFAULT nextval(\'id_user\'::text) PRIMARY KEY,
rl_email varchar(254) NOT NULL DEFAULT \'\'
);',
'CREATE INDEX rl_email_rainloop_users_index ON rainloop_users (rl_email);'
];
}
public static function sqlite() : array
{
return [
'CREATE TABLE rainloop_system (
sys_name text NOT NULL,
value_int integer NOT NULL DEFAULT 0
);',
'CREATE UNIQUE INDEX ui_rainloop_system_sys_name ON rainloop_system (sys_name);',
'CREATE TABLE rainloop_users (
id_user integer NOT NULL PRIMARY KEY,
rl_email text NOT NULL DEFAULT \'\'
);',
'CREATE INDEX rl_email_rainloop_users_index ON rainloop_users (rl_email);'
];
}
public static function getForDbType(string $sDbType) : array
{
switch ($sDbType)
{
case 'mysql':
case 'pgsql':
case 'sqlite':
return static::{$sDbType}();
}
return [];
}
}

View file

@ -1082,127 +1082,6 @@ class PdoAddressBook
return $sResult;
}
private function getInitialTablesArray(string $sDbType) : array
{
switch ($sDbType) {
case 'mysql':
$sInitial = <<<MYSQLINITIAL
CREATE TABLE IF NOT EXISTS rainloop_ab_contacts (
id_contact bigint UNSIGNED NOT NULL AUTO_INCREMENT,
id_contact_str varchar(128) NOT NULL DEFAULT '',
id_user int UNSIGNED NOT NULL,
display varchar(255) NOT NULL DEFAULT '',
changed int UNSIGNED NOT NULL DEFAULT 0,
deleted tinyint UNSIGNED NOT NULL DEFAULT 0,
etag varchar(128) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '',
PRIMARY KEY(id_contact),
INDEX id_user_rainloop_ab_contacts_index (id_user)
) ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS rainloop_ab_properties (
id_prop bigint UNSIGNED NOT NULL AUTO_INCREMENT,
id_contact bigint UNSIGNED NOT NULL,
id_user int UNSIGNED NOT NULL,
prop_type tinyint UNSIGNED NOT NULL,
prop_type_str varchar(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '',
prop_value MEDIUMTEXT NOT NULL,
prop_value_custom MEDIUMTEXT NOT NULL,
prop_frec int UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY(id_prop),
INDEX id_user_rainloop_ab_properties_index (id_user),
INDEX id_user_id_contact_rainloop_ab_properties_index (id_user, id_contact),
INDEX id_contact_prop_type_rainloop_ab_properties_index (id_contact, prop_type)
) ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
MYSQLINITIAL;
break;
case 'pgsql':
$sInitial = <<<POSTGRESINITIAL
CREATE TABLE rainloop_ab_contacts (
id_contact bigserial PRIMARY KEY,
id_contact_str varchar(128) NOT NULL DEFAULT '',
id_user integer NOT NULL,
display varchar(255) NOT NULL DEFAULT '',
changed integer NOT NULL default 0,
deleted integer NOT NULL default 0,
etag varchar(128) NOT NULL DEFAULT ''
);
CREATE INDEX id_user_rainloop_ab_contacts_index ON rainloop_ab_contacts (id_user);
CREATE TABLE rainloop_ab_properties (
id_prop bigserial PRIMARY KEY,
id_contact integer NOT NULL,
id_user integer NOT NULL,
prop_type integer NOT NULL,
prop_type_str varchar(255) NOT NULL DEFAULT '',
prop_value text NOT NULL DEFAULT '',
prop_value_custom text NOT NULL DEFAULT '',
prop_frec integer NOT NULL default 0
);
CREATE INDEX id_user_rainloop_ab_properties_index ON rainloop_ab_properties (id_user);
CREATE INDEX id_user_id_contact_rainloop_ab_properties_index ON rainloop_ab_properties (id_user, id_contact);
POSTGRESINITIAL;
break;
case 'sqlite':
$sInitial = <<<SQLITEINITIAL
CREATE TABLE rainloop_ab_contacts (
id_contact integer NOT NULL PRIMARY KEY,
id_contact_str text NOT NULL DEFAULT '',
id_user integer NOT NULL,
display text NOT NULL DEFAULT '',
changed integer NOT NULL DEFAULT 0,
deleted integer NOT NULL DEFAULT 0,
etag text NOT NULL DEFAULT ''
);
CREATE INDEX id_user_rainloop_ab_contacts_index ON rainloop_ab_contacts (id_user);
CREATE TABLE rainloop_ab_properties (
id_prop integer NOT NULL PRIMARY KEY,
id_contact integer NOT NULL,
id_user integer NOT NULL,
prop_type integer NOT NULL,
prop_type_str text NOT NULL DEFAULT '',
prop_value text NOT NULL DEFAULT '',
prop_value_custom text NOT NULL DEFAULT '',
prop_frec integer NOT NULL DEFAULT 0
);
CREATE INDEX id_user_rainloop_ab_properties_index ON rainloop_ab_properties (id_user);
CREATE INDEX id_user_id_contact_rainloop_ab_properties_index ON rainloop_ab_properties (id_user, id_contact);
SQLITEINITIAL;
break;
}
$aResult = array();
if (\strlen($sInitial)) {
$aList = \explode(';', \trim($sInitial));
foreach ($aList as $sV) {
$sV = \trim($sV);
if (\strlen($sV)) {
$aResult[] = $sV;
}
}
}
return $aResult;
}
private function SyncDatabase() : bool
{
static $mCache = null;
@ -1213,42 +1092,12 @@ SQLITEINITIAL;
$mCache = false;
switch ($this->settings->driver) {
case 'mysql':
$mCache = $this->dataBaseUpgrade($this->settings->driver.'-ab-version', array(
1 => $this->getInitialTablesArray($this->settings->driver),
2 => array(
'ALTER TABLE rainloop_ab_properties ADD prop_value_lower MEDIUMTEXT NOT NULL AFTER prop_value_custom;'
),
3 => array(
'ALTER TABLE rainloop_ab_properties CHANGE prop_value prop_value MEDIUMTEXT NOT NULL;',
'ALTER TABLE rainloop_ab_properties CHANGE prop_value_custom prop_value_custom MEDIUMTEXT NOT NULL;',
'ALTER TABLE rainloop_ab_properties CHANGE prop_value_lower prop_value_lower MEDIUMTEXT NOT NULL;'
),
4 => array(
'ALTER TABLE rainloop_ab_properties CHANGE prop_value prop_value MEDIUMTEXT NOT NULL;',
'ALTER TABLE rainloop_ab_properties CHANGE prop_value_custom prop_value_custom MEDIUMTEXT NOT NULL;',
'ALTER TABLE rainloop_ab_properties CHANGE prop_value_lower prop_value_lower MEDIUMTEXT NOT NULL;'
)
));
break;
case 'pgsql':
$mCache = $this->dataBaseUpgrade($this->settings->driver.'-ab-version', array(
1 => $this->getInitialTablesArray($this->settings->driver),
2 => array(
'ALTER TABLE rainloop_ab_properties ADD prop_value_lower text NOT NULL DEFAULT \'\';'
),
3 => array(),
4 => array()
));
break;
case 'sqlite':
$mCache = $this->dataBaseUpgrade($this->settings->driver.'-ab-version', array(
1 => $this->getInitialTablesArray($this->settings->driver),
2 => array(
'ALTER TABLE rainloop_ab_properties ADD prop_value_lower text NOT NULL DEFAULT \'\';'
),
3 => array(),
4 => array()
));
$mCache = $this->dataBaseUpgrade(
$this->settings->driver.'-ab-version',
PdoSchema::getForDbType($this->settings->driver)
);
break;
}

View file

@ -0,0 +1,170 @@
<?php
namespace RainLoop\Providers\AddressBook;
abstract class PdoSchema
{
public static function mysql() : string
{
return <<<MYSQLINITIAL
CREATE TABLE IF NOT EXISTS rainloop_ab_contacts (
id_contact bigint UNSIGNED NOT NULL AUTO_INCREMENT,
id_contact_str varchar(128) NOT NULL DEFAULT '',
id_user int UNSIGNED NOT NULL,
display varchar(255) NOT NULL DEFAULT '',
changed int UNSIGNED NOT NULL DEFAULT 0,
deleted tinyint UNSIGNED NOT NULL DEFAULT 0,
etag varchar(128) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '',
PRIMARY KEY(id_contact),
INDEX id_user_rainloop_ab_contacts_index (id_user)
) ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE TABLE IF NOT EXISTS rainloop_ab_properties (
id_prop bigint UNSIGNED NOT NULL AUTO_INCREMENT,
id_contact bigint UNSIGNED NOT NULL,
id_user int UNSIGNED NOT NULL,
prop_type tinyint UNSIGNED NOT NULL,
prop_type_str varchar(255) CHARACTER SET ascii COLLATE ascii_general_ci NOT NULL DEFAULT '',
prop_value MEDIUMTEXT NOT NULL,
prop_value_custom MEDIUMTEXT NOT NULL,
prop_frec int UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY(id_prop),
INDEX id_user_rainloop_ab_properties_index (id_user),
INDEX id_user_id_contact_rainloop_ab_properties_index (id_user, id_contact),
INDEX id_contact_prop_type_rainloop_ab_properties_index (id_contact, prop_type)
) ENGINE=INNODB CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
MYSQLINITIAL;
}
public static function pgsql() : string
{
return <<<POSTGRESINITIAL
CREATE TABLE rainloop_ab_contacts (
id_contact bigserial PRIMARY KEY,
id_contact_str varchar(128) NOT NULL DEFAULT '',
id_user integer NOT NULL,
display varchar(255) NOT NULL DEFAULT '',
changed integer NOT NULL default 0,
deleted integer NOT NULL default 0,
etag varchar(128) NOT NULL DEFAULT ''
);
CREATE INDEX id_user_rainloop_ab_contacts_index ON rainloop_ab_contacts (id_user);
CREATE TABLE rainloop_ab_properties (
id_prop bigserial PRIMARY KEY,
id_contact integer NOT NULL,
id_user integer NOT NULL,
prop_type integer NOT NULL,
prop_type_str varchar(255) NOT NULL DEFAULT '',
prop_value text NOT NULL DEFAULT '',
prop_value_custom text NOT NULL DEFAULT '',
prop_frec integer NOT NULL default 0
);
CREATE INDEX id_user_rainloop_ab_properties_index ON rainloop_ab_properties (id_user);
CREATE INDEX id_user_id_contact_rainloop_ab_properties_index ON rainloop_ab_properties (id_user, id_contact);
POSTGRESINITIAL;
}
public static function sqlite() : string
{
return <<<SQLITEINITIAL
CREATE TABLE rainloop_ab_contacts (
id_contact integer NOT NULL PRIMARY KEY,
id_contact_str text NOT NULL DEFAULT '',
id_user integer NOT NULL,
display text NOT NULL DEFAULT '',
changed integer NOT NULL DEFAULT 0,
deleted integer NOT NULL DEFAULT 0,
etag text NOT NULL DEFAULT ''
);
CREATE INDEX id_user_rainloop_ab_contacts_index ON rainloop_ab_contacts (id_user);
CREATE TABLE rainloop_ab_properties (
id_prop integer NOT NULL PRIMARY KEY,
id_contact integer NOT NULL,
id_user integer NOT NULL,
prop_type integer NOT NULL,
prop_type_str text NOT NULL DEFAULT '',
prop_value text NOT NULL DEFAULT '',
prop_value_custom text NOT NULL DEFAULT '',
prop_frec integer NOT NULL DEFAULT 0
);
CREATE INDEX id_user_rainloop_ab_properties_index ON rainloop_ab_properties (id_user);
CREATE INDEX id_user_id_contact_rainloop_ab_properties_index ON rainloop_ab_properties (id_user, id_contact);
SQLITEINITIAL;
}
public static function getForDbType(string $sDbType) : array
{
$aVersions = [];
switch ($sDbType)
{
case 'mysql':
$aVersions = [
1 => [],
2 => [
'ALTER TABLE rainloop_ab_properties ADD prop_value_lower MEDIUMTEXT NOT NULL AFTER prop_value_custom;'
],
3 => [
'ALTER TABLE rainloop_ab_properties CHANGE prop_value prop_value MEDIUMTEXT NOT NULL;',
'ALTER TABLE rainloop_ab_properties CHANGE prop_value_custom prop_value_custom MEDIUMTEXT NOT NULL;',
'ALTER TABLE rainloop_ab_properties CHANGE prop_value_lower prop_value_lower MEDIUMTEXT NOT NULL;'
],
4 => [
'ALTER TABLE rainloop_ab_properties CHANGE prop_value prop_value MEDIUMTEXT NOT NULL;',
'ALTER TABLE rainloop_ab_properties CHANGE prop_value_custom prop_value_custom MEDIUMTEXT NOT NULL;',
'ALTER TABLE rainloop_ab_properties CHANGE prop_value_lower prop_value_lower MEDIUMTEXT NOT NULL;'
]
];
break;
case 'pgsql':
$aVersions = [
1 => [],
2 => [
'ALTER TABLE rainloop_ab_properties ADD prop_value_lower text NOT NULL DEFAULT \'\';'
]
];
break;
case 'sqlite':
$aVersions = [
1 => [],
2 => [
'ALTER TABLE rainloop_ab_properties ADD prop_value_lower text NOT NULL DEFAULT \'\';'
]
];
$sInitial = static::{$sDbType}();
break;
}
if ($aVersions) {
$aList = \explode(';', \trim(static::{$sDbType}()));
foreach ($aList as $sV) {
$sV = \trim($sV);
if (\strlen($sV)) {
$aVersions[1][] = $sV;
}
}
}
return $aVersions;
}
}