Skip to content

Commit c9ce9fd

Browse files
committed
Do not attempt to parse int2vector and oidvector
Fixes #68
1 parent 48ee97e commit c9ce9fd

File tree

3 files changed

+39
-22
lines changed

3 files changed

+39
-22
lines changed

src/Internal/PgSqlHandle.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public function __construct(
175175
*/
176176
private static function fetchTypes(\PgSql\Connection $handle): array
177177
{
178-
$result = \pg_query($handle, "SELECT t.oid, t.typcategory, t.typdelim, t.typelem
178+
$result = \pg_query($handle, "SELECT t.oid, t.typcategory, t.typname, t.typdelim, t.typelem
179179
FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON t.typnamespace=n.oid
180180
WHERE t.typisdefined AND n.nspname IN ('pg_catalog', 'public') ORDER BY t.oid");
181181

@@ -185,10 +185,18 @@ private static function fetchTypes(\PgSql\Connection $handle): array
185185

186186
$types = [];
187187
while ($row = \pg_fetch_array($result, mode: \PGSQL_NUM)) {
188-
[$oid, $type, $delimiter, $element] = $row;
189-
\assert(\is_numeric($oid) && \is_numeric($element), "OID and element type expected to be integers");
190-
\assert(\is_string($type) && \is_string($delimiter), "Unexpected types in type catalog query results");
191-
$types[(int) $oid] = new PgSqlType($type, $delimiter, (int) $element);
188+
[$oid, $typeCategory, $typeName, $delimiter, $element] = $row;
189+
190+
\assert(
191+
\is_numeric($oid) && \is_numeric($element),
192+
"OID and element type expected to be integers",
193+
);
194+
\assert(
195+
\is_string($typeCategory) && \is_string($typeName) && \is_string($delimiter),
196+
"Unexpected types in type catalog query results",
197+
);
198+
199+
$types[(int) $oid] = new PgSqlType($typeCategory, $typeName, $delimiter, (int) $element);
192200
}
193201

194202
return $types;

src/Internal/PgSqlResultIterator.php

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -81,23 +81,31 @@ private function cast(int $oid, ?string $value): array|bool|int|float|string|nul
8181

8282
$type = $this->types[$oid] ?? PgSqlType::getDefaultType();
8383

84-
return match ($type->type) {
85-
'A' => ArrayParser::parse( // Array
86-
$value,
87-
fn (string $data) => $this->cast($type->element, $data),
88-
$type->delimiter,
89-
),
90-
'B' => $value === 't', // Boolean
91-
'N' => match ($oid) { // Numeric
92-
700, 701 => (float) $value, // "float4" and "float8" to float
93-
1700 => $value, // Return "numeric" as string to retain precision
94-
790 => $value, // "money" includes currency symbol as string
95-
default => (int) $value, // All other numeric types cast to an integer
84+
return match ($type->category) {
85+
'A' => match ($type->name) { // Array
86+
'int2vector', 'oidvector' => $value, // Deprecated array types
87+
default => ArrayParser::parse(
88+
$value,
89+
fn (string $data) => $this->cast($type->element, $data),
90+
$type->delimiter,
91+
),
9692
},
97-
default => match ($oid) { // String
98-
17 => \pg_unescape_bytea($value),
99-
default => $value, // Return a string for all other types
93+
'B' => match ($value) {
94+
't' => true,
95+
'f' => false,
96+
default => throw new PostgresParseException('Unexpected value for boolean field: ' . $value),
97+
}, // Boolean
98+
'N' => match ($type->name) { // Numeric
99+
'float4', 'float8' => (float) $value,
100+
'int2', 'int4', 'oid' => (int) $value,
101+
'int8' => \PHP_INT_SIZE >= 8 ? (int) $value : $value, // String on 32-bit systems
102+
default => $value, // Return a string for all other numeric types
100103
},
104+
'U' => match ($type->name) {
105+
'bytea' => \pg_unescape_bytea($value),
106+
default => $value,
107+
},
108+
default => $value, // Return a string for all other types
101109
};
102110
}
103111
}

src/Internal/PgSqlType.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ final class PgSqlType
88
private static ?self $default = null;
99

1010
public function __construct(
11-
public readonly string $type,
11+
public readonly string $category,
12+
public readonly string $name,
1213
public readonly string $delimiter,
1314
public readonly int $element,
1415
) {
1516
}
1617

1718
public static function getDefaultType(): self
1819
{
19-
return self::$default ??= new self('S', ',', 0);
20+
return self::$default ??= new self('S', 'text', ',', 0);
2021
}
2122
}

0 commit comments

Comments
 (0)