Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
4a03d6f
DBAL3: Update to `doctrine/dbal` version 3
amotl Nov 24, 2022
cf2ca79
DBAL3: Adjust interfaces and autoloading to match implementation
amotl May 5, 2023
5bfc306
DBAL3: Start populating PDOConnection, detouring from PDOCrateDB
amotl May 5, 2023
9cf0a19
DBAL3: Code-style fixes
amotl May 5, 2023
832226c
DBAL3: Making actual progress
amotl Nov 14, 2025
dbc307d
DBAL3: Apply suggestions by CodeRabbit, and more copy editing
amotl Nov 14, 2025
8d8e25f
DBAL3: Minor wording updates
amotl Nov 14, 2025
40283de
DBAL3: More copy editing with CodeRabbit
amotl Nov 14, 2025
1038d06
Chore: Switch linter/formatter to PHP Coding Standards Fixer
amotl Nov 14, 2025
40429d1
DBAL3: Rename more symbols
JulianMar Nov 16, 2025
fe34cf7
DBAL3: Towards DBAL4
JulianMar Nov 16, 2025
4b72137
DBAL3: Implement suggestions by CodeRabbit
amotl Nov 16, 2025
32c556a
DBAL3: More generic type hinting
JulianMar Nov 16, 2025
8bf6a95
Chore: Naming things `s/TestCase/Test/`
amotl Nov 16, 2025
e15924c
Chore: Implement suggestions by CodeRabbit
amotl Nov 18, 2025
ec6eef9
DBAL3: Use `Doctrine\DBAL\Driver\PDO\Exception` instead of copying
amotl Nov 19, 2025
05f85d5
DBAL3: At `lastInsertId`, catch `PDOException` and wrap into `DBAL` one
amotl Nov 19, 2025
24d1767
DBAL3: Clarify remark about differences of the new DBAL3 Type API
amotl Nov 19, 2025
b07a4a4
DBAL3: Remove comment about `wrapperClass`
amotl Nov 19, 2025
ee38c2f
Tests: Adjust skip messages instead of blatantly using `ALTER TABLE`
amotl Nov 19, 2025
425f4ee
DBAL3: Implement suggestions by CodeRabbit
amotl Nov 19, 2025
9732bf6
DBAL3: Use CrateDB 5.0.0 in `getServerVersion` to select modern dialect
amotl Nov 19, 2025
b8a9929
DBAL3: Implement suggestions by CodeRabbit
amotl Nov 19, 2025
2e7eb41
Connection: Make statement class registration more compliant with PDO
amotl Nov 20, 2025
b4b6870
Use `TransactionIsolationLevel::READ_UNCOMMITTED` as new default
amotl Nov 20, 2025
d920f69
Forward beginTransaction, commit, rollBack to PDO driver
amotl Nov 20, 2025
27efef8
DBAL3: Implement `getServerVersion()`, forwarding to `PDOCrateDB`
amotl Nov 20, 2025
cf37370
Example: Update procedure how to properly select the platform
amotl Nov 20, 2025
6425cc4
Documentation: Educate about CrateDB and eventual consistency vs. ACID
amotl Nov 21, 2025
8df8f90
Documentation: Make example program independent of `CratePlatform4`
amotl Nov 21, 2025
07e207a
DBAL3: Remove `assert($result !== false)` in `PDOConnection.exec()`
amotl Nov 24, 2025
27294b0
DBAL3: Apply optimization to `PDOConnection.query()` by CodeRabbit
amotl Nov 24, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
.project
.vagrant
.phpunit.result.cache
*.cache
*-console.log
.crate-docs
/composer.lock
Expand Down
28 changes: 28 additions & 0 deletions .php-cs-fixer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
// PHP Coding Standards Fixer
// https://cs.symfony.com/
// https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/blob/master/doc/config.rst

$finder = (new PhpCsFixer\Finder())
->in(__DIR__)
->exclude('build')
->exclude('vendor')
;

return (new PhpCsFixer\Config())
->setUnsupportedPhpVersionAllowed(true)
->setRules([
// '@auto' => true,
// '@PHP7x3Migration' => true,
// '@PSR1' => true,
// '@PSR2' => true,
// '@PSR12' => true,
// '@Symfony' => true,
// 'array_syntax' => ['syntax' => 'short'],
'ordered_imports' => true,
// 'strict_param' => true,
])
->setFinder($finder)
;

?>
3 changes: 3 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ CHANGES for crate-dbal
Unreleased
==========

- Added support for Doctrine DBAL 3, dropped support for Doctrine DBAL 2.
- Made `TransactionIsolationLevel::READ_UNCOMMITTED` the new default.

2025/11/13 4.0.3
================

Expand Down
16 changes: 9 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
"prefer-stable": true,
"require": {
"php": "^8.0|^8.1|^8.2|^8.3|^8.4|^8.5",
"doctrine/dbal": "^2",
"crate/crate-pdo": "^2",
"doctrine/dbal": "^3",
"crate/crate-pdo": "^2.2.4",
"ext-pdo": "*"
},
"autoload": {
Expand All @@ -27,12 +27,14 @@
},
"require-dev": {
"phpunit/phpunit": "^9.0",
"squizlabs/php_codesniffer": "^3.5"
"friendsofphp/php-cs-fixer": "^3.89"
},
"autoload-dev": {
"psr-0": {
"Crate\\Test": "test",
"Doctrine\\Tests": "vendor/doctrine/dbal/tests"
"Crate\\Test": "test"
},
"psr-4": {
"Doctrine\\DBAL\\Tests\\": "vendor/doctrine/dbal/tests"
}
},
"config": {
Expand All @@ -42,7 +44,7 @@
},
"scripts": {
"test": "XDEBUG_MODE=coverage phpunit --coverage-clover build/logs/clover.xml",
"check-style": "phpcs",
"fix-style": "phpcbf"
"check-style": "php-cs-fixer check",
"fix-style": "php-cs-fixer fix"
}
}
4 changes: 2 additions & 2 deletions docs/appendices/data-types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ Here's an example of how the ``MapType`` can be used:
$objDefinition = array(
'type' => MapType::STRICT,
'fields' => array(
new Column('id', Type::getType('integer'), array()),
new Column('name', Type::getType('string'), array()),
new Column('id', Type::getType('integer'), array()),
new Column('name', Type::getType('string'), array()),
),
);
$table->addColumn(
Expand Down
4 changes: 2 additions & 2 deletions docs/appendices/table-options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Example:

$options = [];
$options['sharding_shards'] = 5;
$myTable = new Table('my_table', [], [], [], 0, $options);
$myTable = new Table('my_table', [], [], [], [], $options);


Sharding Options
Expand Down Expand Up @@ -66,7 +66,7 @@ Example on how to adjust the replicas:
$options = [];
$options['table_options'] = [];
$options['table_options']['number_of_replicas'] = '2';
$myTable = new Table('my_table', [], [], [], 0, $options);
$myTable = new Table('my_table', [], [], [], [], $options);


.. _CrateDB CREATE TABLE Documentation: https://cratedb.com/docs/crate/reference/en/latest/sql/statements/create-table.html
Expand Down
18 changes: 16 additions & 2 deletions docs/connect.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,16 @@ If you plan to query CrateDB via DBAL, you can get a connection from the

.. code-block:: php

use Doctrine\DBAL\DriverManager;

$params = array(
'driverClass' => 'Crate\DBAL\Driver\PDOCrate\Driver',
'user' => 'crate',
'host' => 'localhost',
'port' => 4200
);
$connection = \Doctrine\DBAL\DriverManager::getConnection($params);
$schemaManager = $connection->getSchemaManager();
$connection = DriverManager::getConnection($params);
$schemaManager = $connection->createSchemaManager();

With these connection parameters, the ``DriverManager`` will attempt to
authenticate as ``crate`` with a CrateDB node listening on ``localhost:4200``.
Expand Down Expand Up @@ -84,6 +86,16 @@ Here's what we changed in the above example:
:ref:`data types <data-types>` appendix for more information about type
maps and column type definitions.

Eventual consistency
====================

Note that CrateDB is primarily an analytical database for big data, so it
implements `eventual consistency`_ and does not support traditional ACID
transactions.

Please use `REFRESH TABLE`_ for establishing read-after-write consistency
when applicable.

Next steps
==========

Expand All @@ -96,4 +108,6 @@ your setup process.
.. _Doctrine provided example: https://www.doctrine-project.org/projects/doctrine-orm/en/3.0/reference/configuration.html#obtaining-an-entitymanager
.. _Object-Relational Mapping: https://www.doctrine-project.org/projects/orm.html
.. _Doctrine ORM documentation: https://www.doctrine-project.org/projects/doctrine-orm/en/3.0/index.html
.. _eventual consistency: https://community.cratedb.com/t/fundamentals-of-eventual-consistency-in-cratedb/1235
.. _REFRESH TABLE: https://cratedb.com/docs/crate/reference/en/5.10/general/dql/refresh.html
.. _standard DBAL parameters: https://www.doctrine-project.org/projects/doctrine-dbal/en/3.0/reference/configuration.html
67 changes: 67 additions & 0 deletions examples/objects.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

/*
* Basic example program about handling CrateDB OBJECTs with Doctrine DBAL.
* https://github.com/crate/crate-dbal
*/
require __DIR__ . '/../vendor/autoload.php';

use Crate\DBAL\Driver\PDOCrate\Driver as CrateDBDriver;
use Crate\DBAL\Types\MapType;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Exception\TableNotFoundException;
use Doctrine\DBAL\Schema\Column;
use Doctrine\DBAL\Schema\Table;

use Doctrine\DBAL\Tools\DsnParser;
use Doctrine\DBAL\Types\Type;


// Register driver and select platform.
// Because DBAL can't connect to the database to determine its version dynamically,
// it is the obligation of the user to provide the CrateDB version number.
// Remark: Please let us know if you find a way how to set up more ergonomically.
// https://www.doctrine-project.org/projects/doctrine-dbal/en/3.10/reference/platforms.html
$driver = new CrateDBDriver();
$dsnParser = new DsnParser(["crate" => $driver::class]);
$driver->createDatabasePlatformForVersion('6.0.0');

// Create connection options from data source URL.
$options = $dsnParser->parse('crate://crate:crate@localhost:4200/');

// Connect to database.
$connection = DriverManager::getConnection($options);

// Define table schema.
$table = new Table('example');
$objDefinition = array(
'type' => MapType::STRICT,
'fields' => array(
new Column('id', Type::getType('integer'), array()),
new Column('name', Type::getType('string'), array()),
),
);
$table->addColumn(
'data',
MapType::NAME,
array('platformOptions' => $objDefinition),
);

// Provision database table.
$schemaManager = $connection->createSchemaManager();
try {
$schemaManager->dropTable($table->getName());
} catch (TableNotFoundException) {
}
$schemaManager->createTable($table);

// Insert data.
$connection->insert('example', array('data' => array('id' => 42, 'name' => 'foo')), array('data' => 'map'));
$connection->insert('example', array('data' => array('id' => 43, 'name' => 'bar')), array('data' => 'map'));
$connection->executeStatement('REFRESH TABLE example');

// Query data.
$result = $connection->executeQuery('SELECT * FROM example');
print_r($result->fetchAllAssociative());

?>
124 changes: 120 additions & 4 deletions src/Crate/DBAL/Driver/PDOCrate/CrateStatement.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

/**
* Licensed to CRATE Technology GmbH("Crate") under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
Expand All @@ -22,14 +23,129 @@

namespace Crate\DBAL\Driver\PDOCrate;

use Doctrine\DBAL\Driver\PDOStatementImplementations;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Crate\PDO\PDOInterface;
use Crate\PDO\PDOStatement;
use Doctrine\DBAL\Driver\PDO\Exception;
use Doctrine\DBAL\Driver\Result as ResultInterface;
use Doctrine\DBAL\Driver\Statement as StatementInterface;
use Doctrine\DBAL\ParameterType;
use Doctrine\Deprecations\Deprecation;
use PDO;
use PDOException;

/**
* @internal
*/
class CrateStatement extends PDOStatement implements StatementInterface
final class CrateStatement implements StatementInterface
{
use PDOStatementImplementations;
private PDOInterface $pdo;
private PDOStatement $stmt;

/**
* @param string $sql
* @param array<string,mixed> $options
*/
public function __construct(PDOInterface $pdo, $sql, $options = [])
{
$this->pdo = $pdo;
$this->stmt = $pdo->prepare($sql, $options);
}

/**
* {@inheritDoc}
*/
public function execute($params = null): ResultInterface
{

if ($params !== null) {
Deprecation::trigger(
'doctrine/dbal',
'https://github.com/doctrine/dbal/pull/5556',
'Passing $params to Statement::execute() is deprecated. Bind parameters using'
. ' Statement::bindValue() instead.',
);
}
try {
$this->stmt->execute($params);
} catch (PDOException $exception) {
throw Exception::new($exception);
}
return new Result($this);
}

/**
* {@inheritDoc}
*/
public function columnCount(): int
{
return $this->stmt->columnCount();
}

/**
* {@inheritDoc}
*/
public function rowCount(): int
{
return $this->stmt->rowCount();
}

/**
* {@inheritDoc}
*/
public function bindValue($param, $value, $type = ParameterType::STRING): bool
{
return $this->stmt->bindValue($param, $value, $type);
}

/**
* @deprecated Use bindValue() instead.
* {@inheritDoc}
*/
public function bindParam($param, &$variable, $type = ParameterType::STRING, $length = null): bool
{
Deprecation::trigger(
'doctrine/dbal',
'https://github.com/doctrine/dbal/pull/5563',
'Statement::bindParam() was deprecated. Please use Statement::bindValue() instead.',
);
return $this->stmt->bindParam($param, $variable, $type, $length);
}

/**
* {@inheritDoc}
*/
public function fetch(
$fetch_style = PDO::FETCH_ASSOC,
$cursor_orientation = PDO::FETCH_ORI_NEXT,
$cursor_offset = 0,
) {
return $this->stmt->fetch($fetch_style, $cursor_orientation, $cursor_offset);
}

public function fetchColumn($column_number = 0)
{
return $this->stmt->fetchColumn($column_number);
}

/**
* {@inheritDoc}
*/
public function closeCursor(): bool
{
try {
return $this->stmt->closeCursor();
} catch (PDOException $exception) {
throw Exception::new($exception);
}
}

/**
* Gets the wrapped CrateDB PDOStatement.
*
* @return PDOStatement
*/
public function getWrappedStatement(): PDOStatement
{
return $this->stmt;
}
}
Loading