Skip to content

Commit

Permalink
Connection: support DSN url, replicas+primary, driverClass, defaultTa…
Browse files Browse the repository at this point in the history
…bleOptions, keepReplica, sessionMode, wrapperClass
  • Loading branch information
f3l1x committed Dec 13, 2024
1 parent 266966e commit 5b6630b
Show file tree
Hide file tree
Showing 8 changed files with 316 additions and 64 deletions.
77 changes: 55 additions & 22 deletions .docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,7 @@ nettrine.dbal:
connections:
default:
driver: pdo_pgsql
host: localhost
port: 5432
user: root
password: root
charset: utf8
dbname: nettrine
url: "postgresql://user:password@localhost:5432/dbname"
```

**PostgreSQL**
Expand All @@ -58,10 +53,7 @@ nettrine.dbal:
connections:
default:
driver: pdo_pgsql
host: localhost
port: 5432
user: root
password: root
url: "postgresql://user:password@localhost:5432/dbname"
```

**MySQL / MariaDB**
Expand All @@ -71,10 +63,7 @@ nettrine.dbal:
connections:
default:
driver: mysqli
host: localhost
port: 3306
user: root
password: root
url: "mysql://user:passoword@localhost:3306/dbname"
```

**SQLite**
Expand All @@ -84,9 +73,7 @@ nettrine.dbal:
connections:
default:
driver: pdo_sqlite
password: test
user: test
path: ":memory:"
url: "sqlite:///:memory:"
```

### Advanced configuration
Expand All @@ -108,22 +95,28 @@ nettrine.dbal:
charset: <string>
connectstring: <string>
dbname: <string>
defaultTableOptions: <array<string, mixed>>
driver: <'pdo_sqlite', 'sqlite3', 'pdo_mysql', 'mysqli', 'pdo_pgsql', 'pgsql', 'pdo_oci', 'oci8', 'pdo_sqlsrv', 'sqlsrv', 'ibm_db2'>
driverClass: <string>
driverOptions: <array<string, mixed>>
exclusive: <string>
gssencmode: <string>
host: <string>
instancename: <string>
memory: <string>
keepReplica: <bool>
memory: <bool>
password: <string>
path: <string>
persistent: <string>
persistent: <bool>
pooled: <string>
port: <int>
primary: <connection-config>
protocol: <string>
replica: array<string, connection-config>
serverVersion: <string>
service: <string>
servicename: <string>
sessionMode: <int>
ssl_ca: <string>
ssl_capath: <string>
ssl_cert: <string>
Expand All @@ -135,7 +128,9 @@ nettrine.dbal:
sslmode: <string>
sslrootcert: <string>
unix_socket: <string>
url: <string>
user: <string>
wrapperClass: <string>
# Config
middlewares: array<string, <service|class-name>>
Expand All @@ -155,14 +150,20 @@ nettrine.dbal:
uuid: Ramsey\Uuid\Doctrine\UuidType
connections:
# Short DSN configuration
default:
driver: pdo_pgsql
url: "postgresql://user:password@localhost:5432/dbname?charset=utf8"
# Explicit configuration
second:
driver: pdo_pgsql
host: localhost
port: 5432
user: root
password: root
user: user
password: password
dbname: dbname
charset: utf8
dbname: nettrine
```

Supported drivers:
Expand All @@ -182,6 +183,38 @@ Supported drivers:
> [!TIP]
> Take a look at real **Nettrine DBAL** configuration example at [contributte/doctrine-project](https://github.com/contributte/doctrine-project/blob/f226bcf46b9bcce2f68961769a02e507936e4682/config/config.neon).
### Encoding

You can set encoding for your connection.

```neon
nettrine.dbal:
connections:
default:
charset: utf8
defaultTableOptions:
charset: utf8
collate: utf8_unicode_ci
```

### Replicas

Doctrine DBAL supports read replicas. You can define them in the configuration.

```neon
nettrine.dbal:
connections:
default:
driver: pdo_pgsql
wrapperClass: Doctrine\DBAL\Connections\PrimaryReadReplicaConnection
url: "postgresql://user:password@localhost:5432/table?charset=utf8&serverVersion=15.0"
replica:
read1:
url: "postgresql://user:password@read-db1:5432/table?charset=utf8"
read2:
url: "postgresql://user:password@read-db2:5432/table?charset=utf8"
```

### Caching

> [!TIP]
Expand Down
61 changes: 58 additions & 3 deletions src/DI/DbalExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Nettrine\DBAL\DI;

use Doctrine\DBAL\Tools\DsnParser;
use Nette\DI\CompilerExtension;
use Nette\DI\Definitions\Statement;
use Nette\PhpGenerator\ClassType;
Expand All @@ -21,26 +22,31 @@
* charset: string,
* connectstring: string,
* dbname: string,
* defaultTableOptions: array<string, mixed>,
* driver: string,
* driverClass: string,
* driverOptions: mixed[],
* exclusive: bool,
* gssencmode: string,
* host: string,
* instancename: string,
* keepReplica: bool,
* memory: bool,
* middlewares: array<string, string|array<string>|Statement>,
* password: string,
* path: string,
* persistent: bool,
* pooled: bool,
* port: int,
* primary: array<string, scalar>,
* protocol: string,
* resultCache: mixed,
* schemaAssetsFilter: mixed,
* schemaManagerFactory: mixed,
* serverVersion: string,
* service: bool,
* servicename: string,
* sessionMode: int,
* ssl_ca: string,
* ssl_capath: string,
* ssl_cert: string,
Expand All @@ -52,7 +58,8 @@
* sslmode: string,
* sslrootcert: string,
* unix_socket: string,
* user: string
* user: string,
* wrapperClass: string,
* }
*/
class DbalExtension extends CompilerExtension
Expand All @@ -61,6 +68,13 @@ class DbalExtension extends CompilerExtension
public const MIDDLEWARE_TAG = 'nettrine.dbal.middleware';
public const MIDDLEWARE_INTERNAL_TAG = 'nettrine.dbal.middleware.internal';
public const CONNECTION_TAG = 'nettrine.dbal.connection';
public const DSN_MAPPING = [
'mysql' => 'mysqli',
'mariadb' => 'mysqli',
'postgres' => 'pdo_pgsql',
'postgresql' => 'pdo_pgsql',
'sqlite' => 'pdo_sqlite',
];

/** @var AbstractPass[] */
protected array $passes = [];
Expand All @@ -79,6 +93,18 @@ public function getConfigSchema(): Schema
Expect::type(Statement::class)->required(),
);

$dsnTransformer = static function (mixed $connection) {
if (is_array($connection)) {
if (isset($connection['url'])) {
assert(is_string($connection['url']));
$params = (new DsnParser(self::DSN_MAPPING))->parse($connection['url']);
$connection = array_merge($connection, $params);
}
}

return $connection;
};

return Expect::structure([
'debug' => Expect::structure([
'panel' => Expect::bool(false),
Expand All @@ -92,12 +118,15 @@ public function getConfigSchema(): Schema
'charset' => Expect::string(),
'connectstring' => Expect::string(),
'dbname' => Expect::string(),
'driver' => Expect::anyOf('pdo_sqlite', 'sqlite3', 'pdo_mysql', 'mysqli', 'pdo_pgsql', 'pgsql', 'pdo_oci', 'oci8', 'pdo_sqlsrv', 'sqlsrv', 'ibm_db2'),
'defaultTableOptions' => Expect::arrayOf(Expect::mixed(), Expect::string()),
'driver' => Expect::anyOf('pdo_sqlite', 'sqlite3', 'pdo_mysql', 'mysqli', 'pdo_pgsql', 'pgsql', 'pdo_oci', 'oci8', 'pdo_sqlsrv', 'sqlsrv', 'ibm_db2')->required(),
'driverClass' => Expect::string(),
'driverOptions' => Expect::anyOf(Expect::null(), Expect::array()),
'exclusive' => Expect::bool(),
'gssencmode' => Expect::string(),
'host' => Expect::string(),
'instancename' => Expect::string(),
'keepReplica' => Expect::bool(),
'memory' => Expect::bool(),
'password' => Expect::string(),
'path' => Expect::string(),
Expand All @@ -108,6 +137,7 @@ public function getConfigSchema(): Schema
'serverVersion' => Expect::string(),
'service' => Expect::bool(),
'servicename' => Expect::string(),
'sessionMode' => Expect::int(),
'ssl_ca' => Expect::string(),
'ssl_capath' => Expect::string(),
'ssl_cert' => Expect::string(),
Expand All @@ -119,14 +149,39 @@ public function getConfigSchema(): Schema
'sslmode' => Expect::string(),
'sslrootcert' => Expect::string(),
'unix_socket' => Expect::string(),
'url' => Expect::string(),
'user' => Expect::string(),
'wrapperClass' => Expect::string(),
'replica' => Expect::arrayOf(
Expect::arrayOf(
Expect::scalar(),
Expect::string()
)->before($dsnTransformer),
Expect::string()->required()
),
'primary' => Expect::arrayOf(
Expect::scalar(),
Expect::string()
)->before($dsnTransformer),
// Configuration
'middlewares' => Expect::arrayOf($expectService, Expect::string()->required()),
'resultCache' => (clone $expectService),
'schemaAssetsFilter' => (clone $expectService),
'schemaManagerFactory' => (clone $expectService),
'autoCommit' => Expect::bool(true),
]),
])
->assert(
fn (stdClass $connection) => !(
$connection->url === null
&& $connection->host === null
&& $connection->port === null
&& $connection->path === null
&& $connection->user === null
&& $connection->password === null
),
'Configure DNS url or explicit host, port, user, password, dbname and others.'
)
->before($dsnTransformer),
Expect::string()->required(),
)->min(1)->required(),
]);
Expand Down
Loading

0 comments on commit 5b6630b

Please sign in to comment.