Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Database - normalize values #806

Closed
wants to merge 3 commits into from

3 participants

@juzna

Bug: database values are not properly normalized to valid php types.

When column in a mysql db is of type bit(1), it's then fetched as binary, i.e. \0 or \1, instead of booleans (false or true) - tested on PHP 5.3.16.
On PHP 5.4.7 numeric strings are returned ("0" or "1").

The biggest problem in 5.3 is that these binary strings evaluate to true in conditions! Thus if ($row->flag) always matches.

I don't know how to fix this atm, so at least attaching a simple test case. Suggestions or comments welcomed.

@juzna

The problem is probably in PDO, because PDOStatement::getColumnMeta doesn't return native_type for bit column:

Here is the output for long and bit columns:

array(7) {
   native_type => "LONG" (4)
   flags => array(0)
   table => "bittest" (7)
   name => "id" (2)
   len => 11
   precision => 0
   pdo_type => 2
}

array(6) {
   flags => array(1) [
      0 => "not_null" (8)
   ]
   table => "bittest" (7)
   name => "flag" (4)
   len => 1
   precision => 0
   pdo_type => 2
}
@juzna

It's probably PDO's problem - https://bugs.php.net/bug.php?id=63244

@enumag

Yeah it's a PDO bug. I know about it for a long time now. While you are at it could you please also fix tinyint? NDB returns a string instead of an integer for tinyint.

@enumag

By the way is there some other way to determine mysql type of a column except PDOStatement::getColumnMeta? I think that would be a better way to solve this.

@dg dg closed this in d88098f
@dg dg referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@dg dg referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@dg dg referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@dg dg referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@dg dg referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@dg dg referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@dg dg referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@dg dg referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
@dg dg referenced this pull request from a commit in nette/database
@dg dg Database: fixes in type detection & added tests [Closes nette/nette#806] 1ddf756
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
5 Nette/Database/Drivers/MySqlDriver.php
@@ -116,6 +116,11 @@ public function applyLimit(&$sql, $limit, $offset)
*/
public function normalizeRow($row, $statement)
{
+ foreach ($row as $key => $value) {
+ if ($value === "\0" || $value === "\1") {
+ $row[$key] = $value === "\0" ? '0' : '1';
+ }
+ }
return $row;
}
View
2  Nette/Database/Helpers.php
@@ -28,7 +28,7 @@ class Helpers
/** @var array */
public static $typePatterns = array(
'^_' => IReflection::FIELD_TEXT, // PostgreSQL arrays
- 'BYTEA|BLOB|BIN' => IReflection::FIELD_BINARY,
+ 'BYTEA|BLOB' => IReflection::FIELD_BINARY,
'TEXT|CHAR' => IReflection::FIELD_TEXT,
'YEAR|BYTE|COUNTER|SERIAL|INT|LONG' => IReflection::FIELD_INTEGER,
'CURRENCY|REAL|MONEY|FLOAT|DOUBLE|DECIMAL|NUMERIC|NUMBER' => IReflection::FIELD_FLOAT,
View
8 tests/Nette/Database/mysql-nette_test1.sql
@@ -78,4 +78,12 @@ INSERT INTO book_tag_alt (book_id, tag_id) VALUES (3, 22);
INSERT INTO book_tag_alt (book_id, tag_id) VALUES (3, 23);
INSERT INTO book_tag_alt (book_id, tag_id) VALUES (3, 24);
+DROP TABLE IF EXISTS bittest;
+CREATE TABLE bittest (
+ id int,
+ flag bit NOT NULL DEFAULT b'0'
+);
+INSERT INTO bittest (id, flag) VALUES (0, 0);
+INSERT INTO bittest (id, flag) VALUES (1, 1);
+
SET FOREIGN_KEY_CHECKS = 1;
View
24 tests/Nette/Database/normalize.phpt
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * Test: Nette\Database\Statement: normalize row converts database types properly to PHP types
+ *
+ * @author Jan Dolecek
+ * @package Nette\Database
+ * @multiple databases.ini
+ */
+
+require __DIR__ . '/connect.inc.php'; // create $connection
+
+Nette\Database\Helpers::loadFromFile($connection, __DIR__ . "/{$driverName}-nette_test1.sql");
+
+
+
+$res = $connection->query("SELECT * FROM bittest");
+$row = $res->fetch();
+Assert::same(0, $row->id);
+Assert::same("0", $row->flag);
+
+$row = $res->fetch();
+Assert::same(1, $row->id);
+Assert::same("1", $row->flag);
Something went wrong with that request. Please try again.