tags:

views:

598

answers:

5

I am using the PDO Database Abstraction library to make sure my code is portable. However, I now find that I need column information so I turned to the PDOStatement->getColumnMeta() method hoping it would be somewhat standardized - but from what I have found it actually seems open-ended.

For example, when calling that method from SQLite it seems you get one set of possible values:

http://gcov.php.net/PHP_5_3/lcov_html/pdo_sqlite/sqlite_statement.c.gcov.php

null
double
blob
string
integer
...

While a call from the MySQL database lists all kinds of other weird values: http://gcov.php.net/PHP_5_3/lcov_html/pdo_mysql/mysql_statement.c.gcov.php

var_string
longlong
newdecimal
geometry
...

I may be looking in the wrong place also, but I just can't find any useful data on what "native_type" values can be when it comes to switching around databases.

+1  A: 

PDO is not a database abstraction. It is "only" an unified access layer. If you switch to another database system you most likely have to change the code. Each (specific) database driver returns its own set of values and there's no "translation layer" for the driver:decl_type info in pdo beyond the native_type/pdo_type fields in the result of getColumnMeta()

VolkerK
Sorry, I built a database abstraction layer over PDO - that is what I was referring to. Anyway, it sounds like you are saying that the native_type/pdo_type fields ARE some how unified right? That there is a set number of types that can be returned?
Xeoncross
That would probably be pdo_type then. I.e. PDO::PARAM_BOOL,PDO::PARAM_NULL, ... see http://php.net/pdo.constants
VolkerK
I guess that you didn't see my comment above ;)
Xeoncross
sorry, you're right I haven't ;-)
VolkerK
+1  A: 

I thought that I could share what I have so far. Since native_type and pdo_type return such drastically different values - I am using the "len" to try to test for strings vs text since everything less than 255 is a var char, int, or boolean. Also, pdo_type only has 5 possible values.

//PDO data types
$types = array(
    PDO::PARAM_BOOL => 'bool',
    PDO::PARAM_NULL => 'null',
    PDO::PARAM_INT => 'int',
    PDO::PARAM_STR => 'string',
    PDO::PARAM_LOB => 'blob',
    PDO::PARAM_STMT => 'statement' //Not used right now
);

//Get meta
$column = $result->getColumnMeta(1);

//If the column lenght isn't set - default to ZERO
$column['len'] = isset($column['len']) ? $column['len'] : 0;

//HACK: If it is longer than 255 chars then it is a text area
if($column['len'] > 255) {
    $column['type'] = 'text';
} else {
    $column['type'] = $types[$column['pdo_type']];
}
Xeoncross
What's exactly the point of this? Currently e.g. you're returning "string" for a DATETIME in MySQL. And on the other hand a character(n) or character varying(n) can have an n>255 in postgresql. So _if_ (for what reason ever) this information was vital it wouldn't have been reliable (?)
VolkerK
Good points, like I said this whole question is about trying to find a reliable way to classify types. This was just one way I tried to do it.
Xeoncross
+2  A: 

This is one of those areas of PDO that was left intentionally undefined, in order to keep the abstraction light weight.

PDO does not define a standard representation of types for this method; each driver has it's own idea about what it can return here.

Wez Furlong
What a shame. Why would people use a standardized access layer that doesn't define any standards?
Xeoncross
+1  A: 

I had my hand in getting the behavior changed to more closely fit the documentation. You may want to refer to PHP Bug #46508.

Thanks for being another to mention this problem.
Xeoncross
A: 

One workaround I've come across would require that you use the table name as its own alias.

You can call getColumnMeta() and get a unique list of tables and for each table execute a 'DESCRIBE {table}' statement. Match up the column name with the ones from your result set to get the actual MySQL data type.

It worked for me and my needs anyway...

You mean, use the column name as it's own alias? That would be pretty archaic - but I guess that would work.
Xeoncross