Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ArrayConverter parseInput exception #12

Closed
polyaklaci opened this issue Jun 14, 2024 · 4 comments
Closed

ArrayConverter parseInput exception #12

polyaklaci opened this issue Jun 14, 2024 · 4 comments
Assignees
Labels

Comments

@polyaklaci
Copy link

Hi,

First of all I like to thank you for your work and your code, I like it and I use it in my projects.

The Issue:
I use PostgreSQL metadata parsing in one of my projects, and one of the queries I use contains an array field in the result set. The query is:

SELECT ic.relname AS index_name, tn.nspname AS table_schema, tc.relname AS table_name,
i.indkey::integer[] AS columns, pg_get_indexdef(i.indexrelid, 0, true) AS definition,
i.indisunique AS is_unique FROM pg_index i
JOIN pg_class ic ON ic.oid = i.indexrelid
JOIN pg_class tc ON tc.oid = i.indrelid
JOIN pg_namespace tn ON tn.oid = tc.relnamespace
WHERE i.indisprimary = false AND tn.nspname NOT IN ('information_schema', 'pg_catalog')
ORDER BY table_schema, table_name, index_name

You can execute it on any Postgres database (it reads meta tables).

When I try to access the result set, I got an exception from the ArrayConverter:

Fatal error: Uncaught sad_spirit\pg_wrapper\exceptions\TypeConversionException: sad_spirit\pg_wrapper\converters\containers\ArrayConverter::input(): error parsing database value: unexpected input '>>HERE>>[0:0]={5}' at position 0, expecting '{' in D:\htdocs\vendor\sad_spirit\pg_wrapper\src\sad_spirit\pg_wrapper\exceptions\TypeConversionException.php:46
Stack trace:
#0 D:\htdocs\vendor\sad_spirit\pg_wrapper\src\sad_spirit\pg_wrapper\converters\BaseConverter.php(88): sad_spirit\pg_wrapper\exceptions\TypeConversionException::parsingFailed(Object(sad_spirit\pg_wrapper\converters\containers\ArrayConverter), ''{'', '[0:0]={5}', 0)
#1 D:\htdocs\vendor\sad_spirit\pg_wrapper\src\sad_spirit\pg_wrapper\converters\containers\ArrayConverter.php(210): sad_spirit\pg_wrapper\converters\BaseConverter->expectChar('[0:0]={5}', 0, '{')
#2 D:\htdocs\vendor\sad_spirit\pg_wrapper\src\sad_spirit\pg_wrapper\converters\ContainerConverter.php(33): sad_spirit\pg_wrapper\converters\containers\ArrayConverter->parseInput('[0:0]={5}', 0)
#3 D:\htdocs\vendor\sad_spirit\pg_wrapper\src\sad_spirit\pg_wrapper\converters\BaseConverter.php(35): sad_spirit\pg_wrapper\converters\ContainerConverter->inputNotNull('[0:0]={5}')
#4 D:\htdocs\vendor\sad_spirit\pg_wrapper\src\sad_spirit\pg_wrapper\ResultSet.php(592): sad_spirit\pg_wrapper\converters\BaseConverter->input('[0:0]={5}')
#5 D:\htdocs\vendor\sad_spirit\pg_wrapper\src\sad_spirit\pg_wrapper\ResultSet.php(443): sad_spirit\pg_wrapper\ResultSet->read(0, 1)

The problem is, that the ArrayConverter parseInput expects a leading "{" in the array value (e.g.: "{5}"), but it starts with the dimensions (e.g.: "[0:0]={5}"), so the parsing will fail and exception is throwed. I just "hack" the original code, and it works, but I'm not sure this is the proper way to handle this.

Original code from ArrayConverter.php:

protected function parseInput(string $native, int &$pos): array
{
    $result = [];
    $this->expectChar($native, $pos, '{'); // Leading "{".

Modified code (no exception and works fine):

protected function parseInput(string $native, int &$pos): array
{
    $result = [];
    // --- PL --- hack for dimensional array result, e.g. [0:0]={3}
    if( $native !='' && $pos == 0 && substr($native,0,1) == '[' )
         $pos = strpos($native, '{');

    $this->expectChar($native, $pos, '{'); // Leading "{".
@sad-spirit sad-spirit added the bug label Jun 15, 2024
@sad-spirit sad-spirit self-assigned this Jun 15, 2024
@sad-spirit
Copy link
Owner

Looks like this syntax is documented here: https://www.postgresql.org/docs/current/arrays.html#ARRAYS-IO

indkey column is of (legacy undocumented) type int2vector, it produces a 0-based array when converted to integer[], which is then output with dimensions.

I just "hack" the original code, and it works, but I'm not sure this is the proper way to handle this.

The proper way would be at least to parse the dimensions and, probably, to generate PHP arrays using the same keys. I'll see what I can do.

Another problem is that we always use a comma as an array delimiter, but the array representation can use a different one, as documented on the page linked above (it is pg_type.typdelim column). Should probably address that as well.

@sad-spirit
Copy link
Owner

NB: It won't be hard to also support int2vector and oidvector directly, these are pretty simple to parse.

@sad-spirit
Copy link
Owner

Fixed in release 2.4.1

Thanks for your report! Having no bug reports for a long time makes one wonder whether the package is so bug free or just isn't used by anyone. 🤣

@polyaklaci
Copy link
Author

Thanks for the quick fix/improvement. Regarding the bug-freeness: I don't know how many people use this wrapper, but the code is high quality, so it's probably very close to "bug-free" :) Thanks again...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants