Skip to content

Commit

Permalink
Support int2vector and oidvector types used in system catalogs
Browse files Browse the repository at this point in the history
  • Loading branch information
sad-spirit committed Jun 19, 2024
1 parent b32a1cf commit 115f724
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 10 deletions.
3 changes: 3 additions & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## [Unreleased]

### Added
* `IntegerVectorConverter` for `int2vector` and `oidvector` types used in system catalogs

### Fixed
* String representations of arrays which include dimensions (e.g. `[0:0]={1}`) are now supported
(see issue #12). An exception will be thrown if the structure of the resultant array does not match
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,37 +150,39 @@ public function __construct()
['json', 'jsonb']
);

$this->registerConverter(function () {
$this->registerConverter(static function () {
return new containers\RangeConverter(new IntegerConverter());
}, ['int4range', 'int8range']);
$this->registerConverter(function () {
$this->registerConverter(static function () {
return new containers\RangeConverter(new NumericConverter());
}, 'numrange');
$this->registerConverter(function () {
$this->registerConverter(static function () {
return new containers\RangeConverter(new datetime\DateConverter());
}, 'daterange');
$this->registerConverter(function () {
$this->registerConverter(static function () {
return new containers\RangeConverter(new datetime\TimeStampConverter());
}, 'tsrange');
$this->registerConverter(function () {
$this->registerConverter(static function () {
return new containers\RangeConverter(new datetime\TimeStampTzConverter());
}, 'tstzrange');

$this->registerConverter(function () {
$this->registerConverter(static function () {
return new containers\MultiRangeConverter(new IntegerConverter());
}, ['int4multirange', 'int8multirange']);
$this->registerConverter(function () {
$this->registerConverter(static function () {
return new containers\MultiRangeConverter(new NumericConverter());
}, 'nummultirange');
$this->registerConverter(function () {
$this->registerConverter(static function () {
return new containers\MultiRangeConverter(new datetime\DateConverter());
}, 'datemultirange');
$this->registerConverter(function () {
$this->registerConverter(static function () {
return new containers\MultiRangeConverter(new datetime\TimeStampConverter());
}, 'tsmultirange');
$this->registerConverter(function () {
$this->registerConverter(static function () {
return new containers\MultiRangeConverter(new datetime\TimeStampTzConverter());
}, 'tstzmultirange');

$this->registerConverter(containers\IntegerVectorConverter::class, ['int2vector', 'oidvector']);
}

public function setOIDMapper(TypeOIDMapper $mapper): void
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

/**
* Converter of complex PostgreSQL types and an OO wrapper for PHP's pgsql extension
*
* LICENSE
*
* This source file is subject to BSD 2-Clause License that is bundled
* with this package in the file LICENSE and available at the URL
* https://raw.githubusercontent.com/sad-spirit/pg-wrapper/master/LICENSE
*
* @package sad_spirit\pg_wrapper
* @copyright 2014-2024 Alexey Borzov
* @author Alexey Borzov <avb@php.net>
* @license https://opensource.org/licenses/BSD-2-Clause BSD 2-Clause license
* @link https://github.com/sad-spirit/pg-wrapper
*/

declare(strict_types=1);

namespace sad_spirit\pg_wrapper\converters\containers;

use sad_spirit\pg_wrapper\converters\ContainerConverter;
use sad_spirit\pg_wrapper\converters\IntegerConverter;
use sad_spirit\pg_wrapper\exceptions\TypeConversionException;

/**
* Converter for int2vector and oidvector types used in system catalogs
*
* NB: we do not implement ConnectionAware here as (currently) input routines in Postgres 16+ do not accept
* special numeric literals
*/
class IntegerVectorConverter extends ContainerConverter
{
/** @var IntegerConverter */
private $integerConverter;

public function __construct()
{
$this->integerConverter = new IntegerConverter();
}

protected function outputNotNull($value): string
{
if (!\is_array($value)) {
throw TypeConversionException::unexpectedValue($this, 'output', 'array', $value);
}

return \implode(' ', \array_map(function ($v) {
return $this->integerConverter->outputNotNull($v);
}, $value));
}

protected function parseInput(string $native, int &$pos)
{
$values = [];

while (null !== $this->nextChar($native, $pos)) {
$length = \strcspn($native, " \n\r\t", $pos);
$values[] = $this->integerConverter->input(\substr($native, $pos, $length));
$pos += $length;
}

return $values;
}

public function dimensions(): int
{
return 1;
}
}
63 changes: 63 additions & 0 deletions tests/converters/IntegerVectorConverterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

/**
* Converter of complex PostgreSQL types and an OO wrapper for PHP's pgsql extension
*
* LICENSE
*
* This source file is subject to BSD 2-Clause License that is bundled
* with this package in the file LICENSE and available at the URL
* https://raw.githubusercontent.com/sad-spirit/pg-wrapper/master/LICENSE
*
* @package sad_spirit\pg_wrapper
* @copyright 2014-2024 Alexey Borzov
* @author Alexey Borzov <avb@php.net>
* @license https://opensource.org/licenses/BSD-2-Clause BSD 2-Clause license
* @link https://github.com/sad-spirit/pg-wrapper
*/

declare(strict_types=1);

namespace sad_spirit\pg_wrapper\tests\converters;

use sad_spirit\pg_wrapper\converters\containers\IntegerVectorConverter;
use sad_spirit\pg_wrapper\exceptions\TypeConversionException;

/**
* Unit test for int2vector / oidvector type converter
*
* @extends TypeConverterTestCase<IntegerVectorConverter>
*/
class IntegerVectorConverterTest extends TypeConverterTestCase
{
protected function setUp(): void
{
$this->converter = new IntegerVectorConverter();
}

public function valuesBoth(): array
{
return [
[null, null],
['', []],
['1', [1]],
['1 2', [1, 2]]
];
}

public function valuesFrom(): array
{
return [
[' 1 2 ', [1, 2]],
['1 foo', new TypeConversionException()]
];
}

public function valuesTo(): array
{
return [
[new TypeConversionException(), [1, 'foo']],
[new TypeConversionException(), [1, null]]
];
}
}

0 comments on commit 115f724

Please sign in to comment.