Skip to content

Commit

Permalink
Refactoring, also Schema Generator recognized db-engnine.
Browse files Browse the repository at this point in the history
  • Loading branch information
msyk committed Nov 25, 2023
1 parent 0ea1bf9 commit 775c349
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 32 deletions.
File renamed without changes.
3 changes: 2 additions & 1 deletion params.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
// In case of MySQL, the following account is convenient for generating schema.
//$dbUser = 'root';
//$dbPassword = '';
//$dbDSN = 'mysql:host=127.0.0.1;dbname=test_db2;charset=utf8mb4';
//$dbDSN = 'mysql:host=127.0.0.1;dbname=test_db3;charset=utf8mb4';
//$dbDSN = 'pgsql:host=localhost;port=5432;dbname=test_db4';
// The generated db user is going to replace below.
//$dbUser = 'webuser';
//$dbPassword = '<Bhc)"){3*e3o:cYdhN-';
Expand Down
4 changes: 2 additions & 2 deletions samples/Sample_invoice/include_PostgreSQL.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
),
array(
'db-class' => 'PDO',
'dsn' => 'pgsql:host=localhost;port=5432;dbname=test_db',
'dsn' => 'pgsql:host=localhost;port=5432;dbname=test_db3',
),
false
2
);
5 changes: 5 additions & 0 deletions samples/Sample_invoice/invoice_PostgreSQL.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
<title>INTER-Mediator - Sample - Client-Side Calculation/PostgreSQL</title>
<link rel="stylesheet" type="text/css" href="invoice.css">
<script type="text/javascript" src="include_PostgreSQL.php"></script>
<script>
INTERMediatorOnPage.doBeforeConstruct = function () {
INTERMediatorLog.suppressDebugMessageOnPage = true;
};
</script>
</head>
<body>
<header>
Expand Down
29 changes: 21 additions & 8 deletions src/php/DB/Generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ class Generator
*/
private ?array $options;

private array $supportDB = ["mysql",/* "pgsql" */];

/**
* @param Proxy $proxy
*/
Expand Down Expand Up @@ -234,18 +236,16 @@ public function generate(): void
public function prepareDatabase(): void
{
try { // Establishing the connection with database
$this->link = new \PDO($this->generateDSN(), $this->generatorUser, $this->generatorPassword, []);
$this->link = new \PDO($this->generateDSN(true), $this->generatorUser, $this->generatorPassword, []);
if (!in_array($this->dsnElements['dbname'], $this->getDatabases())) {
$dbName = $this->dsnElements['dbname'];
$userName = "webuser";
$userEntity = "{$userName}@localhost";
$password = str_replace("'", "z", IMUtil::randomString(20));
$sql = $this->proxy->dbClass->handler->sqlCREATEDATABASECommand($dbName);
$sql .= $this->proxy->dbClass->handler->sqlCREATEUSERCommand($dbName, $userEntity, $password);
// Can't use $this->proxy->dbClass->handler here, because it's before initializing dbClass property.
//$sql = "CREATE DATABASE {$this->dsnElements['dbname']};";
$this->logger->setDebugMessage("[Schema Generator] Execute SQL:\n{$sql}", 2);
$result = $this->link->query($sql);
$result = $this->link->exec($sql);
if (!$result) {
throw (new \Exception("Failed in creating database."));
}
Expand All @@ -266,15 +266,16 @@ private function getDatabases(): array
{
$dbs = [];
try {
$sql = "SHOW DATABASES;";
$sql = $this->proxy->dbClass->handler->sqlLISTDATABASECommand();
$field = $this->proxy->dbClass->handler->sqlLISTDATABASEColumn();
$this->logger->setDebugMessage("[Schema Generator] {$sql}");
$result = $this->link->query($sql);
if ($result) {
foreach ($result->fetchAll(\PDO::FETCH_ASSOC) as $row) {
$dbs[] = $row['Database'];
$dbs[] = $row[$field];
}
}
//$this->logger->setDebugMessage("[Schema Generator] " . var_export($dbs, true), 2);
$this->logger->setDebugMessage("[Schema Generator] " . var_export($dbs, true), 2);
} catch (PDOException $ex) {
$this->logger->setErrorMessage('[Schema Generator] Connection Error: ' . $ex->getMessage());
}
Expand Down Expand Up @@ -304,9 +305,15 @@ private function parseDSN($dsn): void

/**
* @return string
* @throws \Exception
*/
public function generateDSN(): string
public function generateDSN($withInitDB = false): string
{
if(!in_array($this->dsnPrefix, $this->supportDB)){
$msg = "The database '{$this->dsnPrefix}' is NOT supported for Automatic Schema Generation.";
$this->logger->setWarningMessage($msg);
throw new \Exception($msg);
}
$dsn = '';
if (isset($this->dsnElements['unix_socket'])) {
$dsn = "{$this->dsnPrefix}:unix_socket={$this->dsnElements['unix_socket']}";
Expand All @@ -316,6 +323,12 @@ public function generateDSN(): string
$dsn .= ";port={$this->dsnElements['port']}";
}
}
if ($withInitDB && $this->dsnPrefix == 'pgsql') {
$initDB = Params::getParameterValue('dbInitalDBName', null);
if ($initDB) {
$dsn .= ";dbname={$initDB}";
}
}
return $dsn;
}

Expand Down
28 changes: 16 additions & 12 deletions src/php/DB/Proxy.php
Original file line number Diff line number Diff line change
Expand Up @@ -799,25 +799,29 @@ function initialize(?array $datasource, ?array $options, ?array $dbspec, ?int $d
$this->dbClass->setUpSharedObjects($this);
if ($isDBClassNull) {
if ($this->activateGenerator) { // In case of Generator activated
$originalDSN = $this->dbSettings->getDbSpecDSN();
$generator = new Generator($this);
$this->dbSettings->setDbSpecDSN($generator->generateDSN());
if (!$this->dbClass->setupConnection()) { // Connection without dbname
return false;
}
$this->dbClass->setupHandlers();
$generator->prepareDatabase(); // If the database doesn't exist, it's going to create here.
$this->dbSettings->setDbSpecDSN($originalDSN);
if (!$this->dbClass->setupConnection()) { // Recreating database connection
try {
$originalDSN = $this->dbSettings->getDbSpecDSN();
$this->logger->setDebugMessage("[Schema Generator]originalDSN " . var_export($originalDSN, true), 2);
$generator = new Generator($this);
$this->dbSettings->setDbSpecDSN($generator->generateDSN(true));
if (!$this->dbClass->setupConnection()) { // Connection without dbname
return false;
}
$this->dbClass->setupHandlers();
$generator->prepareDatabase(); // If the database doesn't exist, it's going to create here.
$this->dbSettings->setDbSpecDSN($originalDSN);
if (!$this->dbClass->setupConnection()) { // Recreating database connection
return false;
}
} catch (Exception $ex) { // Catching the exception within Generator class.
return false;
}
$this->dbClass->setupHandlers();
} else { // Here is normal operations for Database Class.
if (!$this->dbClass->setupConnection()) {
return false;
}
$this->dbClass->setupHandlers();
}
$this->dbClass->setupHandlers();
}
if (!Params::getParameterValue('prohibitDebugMode', false) && $debug) {
$this->logger->setDebugMode($debug);
Expand Down
17 changes: 8 additions & 9 deletions src/php/DB/Support/DB_PDO_Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ public abstract function sqlUPDATECommand(): string;
*/
public abstract function sqlINSERTCommand(string $tableRef, string $setClause): string;

public abstract function sqlLISTDATABASECommand(): string;

/**
* @return string The field name for database name in the result of database list
*/
public abstract function sqlLISTDATABASEColumn(): string;

/**
* @param string $tableRef
* @param string $setClause
Expand Down Expand Up @@ -196,15 +203,7 @@ public function sqlSELECTDATABASECommand(string $dbName): string
return "USE {$this->quotedEntityName($dbName)};\n";
}

public function sqlCREATEUSERCommand(string $dbName, string $userEntity, string $password): string
{
$quotedDB = $this->quotedEntityName($dbName);
$quotedUser = $this->quotedData($userEntity, "@");
$quotedPassword = $this->dbClassObj->link->quote($password);
return "CREATE USER IF NOT EXISTS {$quotedUser};\n"
. "GRANT SELECT, INSERT, DELETE, UPDATE, SHOW VIEW ON TABLE {$quotedDB}.* TO {$quotedUser};\n"
. "SET PASSWORD FOR {$quotedUser} = {$quotedPassword};\n";
}
public abstract function sqlCREATEUSERCommand(string $dbName, string $userEntity, string $password): string;

/**
* @param string $data
Expand Down
24 changes: 24 additions & 0 deletions src/php/DB/Support/DB_PDO_MySQL_Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -417,4 +417,28 @@ public function getLastInsertId(string $seqObject): ?string
}
return null;
}

public function sqlCREATEUSERCommand(string $dbName, string $userEntity, string $password): string
{
$quotedDB = $this->quotedEntityName($dbName);
$quotedUser = $this->quotedData($userEntity, "@");
$quotedPassword = $this->dbClassObj->link->quote($password);
return "CREATE USER IF NOT EXISTS {$quotedUser};\n"
. "GRANT SELECT, INSERT, DELETE, UPDATE, SHOW VIEW ON TABLE {$quotedDB}.* TO {$quotedUser};\n"
. "SET PASSWORD FOR {$quotedUser} = {$quotedPassword};\n";
}

/**
* @return string SQL command returns database list
*/
public function sqlLISTDATABASECommand(): string{
return "SHOW DATABASES;";
}

/**
* @return string The field name for database name in the result of database list
*/
public function sqlLISTDATABASEColumn(): string{
return "Database";
}
}
31 changes: 31 additions & 0 deletions src/php/DB/Support/DB_PDO_PostgreSQL_Handler.php
Original file line number Diff line number Diff line change
Expand Up @@ -355,4 +355,35 @@ public function getSQLNumericToLikeOpe($field, $value): string
{
return "CAST({$field} AS TEXT) LIKE {$value}";
}

public function sqlCREATEUSERCommand(string $dbName, string $userEntity, string $password): string
{
$quotedDB = $this->quotedEntityName($dbName);
$justUsername = explode("@", $userEntity)[0];
$quotedPassword = $this->dbClassObj->link->quote($password);
return
// "CREATE USER {$justUsername} PASSWORD {$quotedPassword};\n".
"DROP SCHEMA IF EXISTS {$quotedDB} CASCADE;"
. "CREATE SCHEMA {$quotedDB};"
. "SET search_path TO {$quotedDB},public;"
. "ALTER USER web SET search_path TO {$quotedDB},public;"
. "GRANT ALL PRIVILEGES ON SCHEMA {$quotedDB} TO {$justUsername};";
}

/**
* @return string SQL command returns database list
*/
public function sqlLISTDATABASECommand(): string
{
return "SELECT datname, datdba, encoding, datcollate, datctype FROM pg_database;";
}

/**
* @return string The field name for database name in the result of database list
*/
public function sqlLISTDATABASEColumn(): string
{
return "datname";
}

}

0 comments on commit 775c349

Please sign in to comment.