Skip to content

Add native_type to pdo_firebird::getColumnMeta() #6682

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

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

rstuart
Copy link

@rstuart rstuart commented Feb 11, 2021

Work done on pdo_firebird::getColumnMeta():

  • Verify column number so a bad column doesn't generate a SIG_SEGV.
  • Ensure the statement has been prepared.
  • Return native_type.
  • Add unit test for getColumnMeta()

I was advised no RFC was needed:
https://marc.info/?l=php-internals&m=161305450505181&w=2

- Verify column number so a bad column doesn't generate a SIG_SEGV.
- Ensure the statement has been prepared.
- Return native_type.
@cmb69
Copy link
Member

cmb69 commented Mar 10, 2021

@sim1984, you might be interested in this. :)

@sim1984
Copy link
Contributor

sim1984 commented Mar 10, 2021

This is a job well done. Thanks.

@diegosardina
Copy link

Could it be merged before 8.1.0alpha1?

@kamil-tekiela
Copy link
Member

@diegosardina Out of curiosity why do you need this?

To the author: why did you add native_type and param_type? What's the purpose? Where do these values come from?

@diegosardina
Copy link

@diegosardina Out of curiosity why do you need this?

Some ORM require getColumnMeta() support on the PDO side and Firebird missed it, until the recent work of nikic (Rewrite PDO result binding).
However also 'native_type' is needed for a complete support.

@kamil-tekiela
Copy link
Member

kamil-tekiela commented Apr 25, 2021

As far as I know, there's no consensus on what this experimental method should do. There's definitely no consensus on what native_type is or what should be the values. It's interesting that someone decided to add it. Maybe we should consider formalizing this method and implementing it properly, but for that, we need to know what is expected from it. FWIW I am not happy with adding more support for this method with strange values.

@diegosardina
Copy link

Being experimental getColumnMeta has been here for 15 years or more.
While I understand your concern (the documentation talks about PHP native type) native_type seems to be used to return the SQL type of the Database by other drivers (for example PostgreSQL's driver return INT4 for 4 byte sized integers).

At least there is a sort of unanimity in this (and at this point why put delay on the Firebird driver?)

What @nikic thinks about it? Since he wrote the whole of getColumnMeta for the Firebird driver

@kamil-tekiela
Copy link
Member

I'm not against that function in general, and in fact I was thinking of improving it, but I'd prefer to remove native_type completely as it is confusing and not implemented fully in any driver. The function is experimental for exactly that reason. There's no specification and no one agrees on what values it should return.

@diegosardina
Copy link

Removing it is not a wise decision since it would break lot of applications. Changing the documentation at this point is better, or rename it to sql_type and raise a deprecation notice for native_type.

[...] as it is confusing and not implemented fully in any driver

Agreed that name is confusing, but it seems that Mysql, Pgsql and Sqlite drivers implemented it by returning sql types

@ramsey
Copy link
Member

ramsey commented May 8, 2021

Could it be merged before 8.1.0alpha1?

Yes. We can merge it in time for 8.1. However, it sounds like @kamil-tekiela has concerns, so I'd like to make sure everyone is okay with this change before merging.

there's no consensus on what this experimental method should do

Should we have a wider discussion about getColumnMeta() on the mailing list? While I agree with @Girgias that this PR doesn't need an RFC itself, if it leads to building overall consensus on getColumnMeta(), that might require an RFC.

@ramsey ramsey added the Feature label May 8, 2021
@ramsey
Copy link
Member

ramsey commented May 8, 2021

I thought this sounded familiar. 😄

@kamil-tekiela is working on #6930, which is related to this.

@rstuart
Copy link
Author

rstuart commented Sep 25, 2021

@diegosardina Out of curiosity why do you need this?

To the author: why did you add native_type and param_type? What's the purpose? Where do these values come from?

Sorry, I missed this was directed at me.

Q: Why did you add. What's the purpose?

A: I don't like being tied to one SQL engine, and unfortunately the various SQL DB engines make that difficult. So I wrote a translation layer that sits on top of native drivers (like Sqlite) and PDO. It translates between syntax like 'limits' and 'rows' (both select the rows to return, some DB's use 'limits' and some user 'ROWS').

It also handles types. Date and Timestamp are by far the worst - it seems every SQL DB has their own way of representing them. My translation layer turns them all into PHP datetime objects. But you have to know when to do that, and one way of knowing is looking at the underlying column type. There are other types too - like 'bigint' that have similar problems.

Most SQL DB's have a way of extracting the underlying type - but if often requires additional SQL select's to do it, which can easily create a 2 or 3 fold read amplification, and it doesn't work for computed columns. The underlying C interface on the other hand must always return the type of each column in a query result because as is no other way to know it for for computed columns. All getColumnMeta() real does is expose this in a standardised way to PHP code.

Q: Where do these values come from?

native_type is what the name implies, the native type of the underlying column returned in the query. It has to be made available to the C interface, because it's how the SQL engine tells the C interface what the format of the buffer holding a row returned by a query. There is no standard of course - each SQL engine has it's own native types which generally correspond to their SQL column types, and consequently their own names for them. The values I used for native_type is the likely underlying Firebird SQL column type name, which is pretty much how all PDO's that implement the getColumnMeta() do it. That type name by definition will be different for different SQL DB's, because all of them add non-standard column types, which of course breaks code that's written with just SQL DB one in mind, which is why I have the translation layer.

param_type is PHP's own version of native_type - ie the type PHP decides to use to send the column to the PHP code (a string, float, or whatever). Unfortunately the translation from native_type to param_type loses information. For example, a native_type of datetime might be represented in the C interface as a ISO8601 string, so that is what the PHP param_type will be. However, PDO telling you it is gving you a string doesn't help when you want to know if it was a datetime.

One win for the translation layer is I tend to use SQLite for Unit tests because it's in-memory databases are so convenient, but then switch to something heavier for production.

@rstuart rstuart requested a review from SakiTakamachi as a code owner April 15, 2024 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
6 participants