Skip to content

Commit

Permalink
Experimental Oracle SqlServer support (CFM-106)
Browse files Browse the repository at this point in the history
  • Loading branch information
Benn Oshrin committed Apr 7, 2024
1 parent 5c2b72e commit 073a2da
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 6 deletions.
17 changes: 14 additions & 3 deletions app/plugins/CoreServer/resources/locales/en_US/core_server.po
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,18 @@ msgstr "MS SQL Server"
msgid "enumeration.RdbmsTypeEnum.MY"
msgstr "MySQL"

# XXX Not yet supported
#msgid "enumeration.RdbmsTypeEnum.OR"
#msgstr "Oracle"
msgid "enumeration.RdbmsTypeEnum.OR"
msgstr "Oracle"

msgid "enumeration.RdbmsTypeEnum.PG"
msgstr "Postgres"

msgid "error.SqlServers.oracle.enabled"
msgstr "Oracle support is not enabled"

msgid "error.SqlServers.oracle.plugin"
msgstr "OracleClient plugin is not loaded"

msgid "field.SqlServers.databas"
msgstr "Database Name"

Expand All @@ -54,5 +59,11 @@ msgstr "Hostname"
msgid "field.SqlServers.password"
msgstr "Password"

msgid "field.SqlServers.port"
msgstr "Port"

msgid "field.SqlServers.port.desc"
msgstr "Specify the port only if a non-standard port number is in use"

msgid "field.SqlServers.type"
msgstr "RDBMS Type"
13 changes: 13 additions & 0 deletions app/plugins/CoreServer/src/CoreServerPlugin.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@ class CoreServerPlugin extends BasePlugin
*/
public function bootstrap(PluginApplicationInterface $app): void
{
try {
// Load the OracleDriver plugin if Oracle support is enabled. We require
// the enable flag so we don't have to try loading the plugin on every
// page load when most deployments aren't going to have it.
$oracleEnabled = \Cake\Core\Configure::read('registry.database.oracle.enable');

if($oracleEnabled === true) {
$app->addPlugin(\CakeDC\OracleDriver\Plugin::class, ['bootstrap' => true]);
}
}
catch(\Error $e) {
debug($e);
}
}

/**
Expand Down
4 changes: 1 addition & 3 deletions app/plugins/CoreServer/src/Lib/Enum/RdbmsTypeEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,7 @@ class RdbmsTypeEnum extends StandardEnum {
// This currently aligns with Cake supported servers
const MariaDB = 'MA';
const MySQL = 'MY';
// XXX Oracle requires a community plugin: https://github.com/CakeDC/cakephp-oracle-driver
// We could maybe ship with this?
// const Oracle = 'OR';
const Oracle = 'OR';
const Postgres = 'PG';
const SQLite = 'LT';
const SqlServer = 'MS';
Expand Down
80 changes: 80 additions & 0 deletions app/plugins/CoreServer/src/Model/Table/SqlServersTable.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

namespace CoreServer\Model\Table;

use Cake\Core\Plugin;
use Cake\Datasource\ConnectionManager;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
Expand Down Expand Up @@ -93,6 +94,24 @@ public function initialize(array $config): void {
]);
}

/**
* Define business rules.
*
* @since COmanage Registry v5.0.0
* @param RulesChecker $rules RulesChecker object
* @return RulesChecker
*/

public function buildRules(RulesChecker $rules): RulesChecker {
// This is not an Application Rule per se, but the Oracle plugin must
// be enabled if the Server Type is set to Oracle.
$rules->add([$this, 'ruleOracleEnabled'],
'oracleEnabled',
['errorField' => 'type']);

return $rules;
}

/**
* Establish a connection (via Cake's ConnectionManager) to the specified SQL server.
*
Expand All @@ -115,6 +134,7 @@ public function connect(int $serverId, string $name): bool {
$dbmap = [
RdbmsTypeEnum::MariaDB => 'Mysql',
RdbmsTypeEnum::MySQL => 'Mysql',
RdbmsTypeEnum::Oracle => 'Oracle',
RdbmsTypeEnum::Postgres => 'Postgres',
RdbmsTypeEnum::SQLite => 'Sqlite',
RdbmsTypeEnum::SqlServer => 'Sqlserver'
Expand All @@ -133,6 +153,34 @@ public function connect(int $serverId, string $name): bool {
'timezone' => 'UTC'
];

if(!empty($server->sql_server->port) && is_numeric($server->sql_server->port)) {
$dbconfig['port'] = $server->sql_server->port;
}

if($server->sql_server->type == RdbmsTypeEnum::Oracle) {
$oracleEnabled = \Cake\Core\Configure::read('registry.database.oracle.enable');

if($oracleEnabled) {
// We don't test that the plugin is available here, an error should be thrown
// when we try to connect.

$dbconfig['className'] = 'CakeDC\OracleDriver\Database\OracleConnection';
$dbconfig['driver'] = 'CakeDC\OracleDriver\Database\Driver\OracleOCI'; # For OCI8

// Use 'CakeDC\\OracleDriver\\Database\\Driver\\OraclePDO' for PDO_OCI, but CakeDC
// recommends OCI8
// The plugin documentation says certain features are enabled at v12, so we hard
// code that version to simplify configuration. As of this writing, Oracle 11g
// is the oldest supported version, but 12c dates back to July 2013, so it seems
// reasonable to require v12 (at least for now). Note Oracle changed their release
// numbers to be based on calendar years, retroactively assigning 18c (12.2.0.2)
// and 19c (12.2.0.3), so this approach should work at least for those versions.
// Since semantic versioning is not being used, it's unclear when backwards
// incompatible changes might be introduced, or if the CakeDC plugin even cares.
$dbconfig['server_version'] = 12;
}
}

// We need to drop the existing configuration before we can reconfigure it
ConnectionManager::drop($name);

Expand All @@ -141,6 +189,33 @@ public function connect(int $serverId, string $name): bool {
return true;
}

/**
* Application Rule to determine if Oracle is enabled (if selected).
*
* @since COmanage Registyr v5.0.0
* @param Entity $entity Entity to be validated
* @param array $options Application rule options
* @return mixed true if the Rule check passes, or an error string otherwise
*/

public function ruleOracleEnabled($entity, $options) {
if($entity->type == RdbmsTypeEnum::Oracle) {
$oracleEnabled = \Cake\Core\Configure::read('registry.database.oracle.enable');

if(!$oracleEnabled) {
return __d('core_server', 'error.SqlServers.oracle.enabled');
}

$pluginLoaded = Plugin::isLoaded('OracleDriver');

if(!$pluginLoaded) {
return __d('core_server', 'error.SqlServers.oracle.plugin');
}
}

return true;
}

/**
* Set validation rules.
*
Expand All @@ -164,6 +239,11 @@ public function validationDefault(Validator $validator): Validator {

$this->registerStringValidation($validator, $schema, 'hostname', true);

$validator->add('port', [
'content' => ['rule' => 'isInteger']
]);
$validator->allowEmptyString('port');

$this->registerStringValidation($validator, $schema, 'databas', true);

$this->registerStringValidation($validator, $schema, 'username', false);
Expand Down
1 change: 1 addition & 0 deletions app/plugins/CoreServer/src/config/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"server_id": {},
"type": { "type": "string", "size": 2 },
"hostname": { "type": "string", "size": 128 },
"port": { "type": "integer" },
"databas": { "type": "string", "size": 128 },
"username": { "type": "string", "size": 128 },
"password": { "type": "string", "size": 80 }
Expand Down
2 changes: 2 additions & 0 deletions app/plugins/CoreServer/templates/SqlServers/fields.inc
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ if($vv_action == 'edit') {

print $this->Field->control('hostname');

print $this->Field->control('port');

print $this->Field->control('databas');

print $this->Field->control('username');
Expand Down

0 comments on commit 073a2da

Please sign in to comment.