diff --git a/src/Dibi/Connection.php b/src/Dibi/Connection.php index f28c1dd3..c37875e4 100644 --- a/src/Dibi/Connection.php +++ b/src/Dibi/Connection.php @@ -365,7 +365,7 @@ class Connection if ($id < 1) { throw new Exception('Cannot retrieve last generated ID.'); } - return (int) $id; + return Helpers::intVal($id); } diff --git a/src/Dibi/DataSource.php b/src/Dibi/DataSource.php index de0a4c89..d9f10218 100644 --- a/src/Dibi/DataSource.php +++ b/src/Dibi/DataSource.php @@ -283,9 +283,9 @@ FROM %SQL', $this->sql, ' { if ($this->count === null) { $this->count = $this->conds || $this->offset || $this->limit - ? (int) $this->connection->nativeQuery( + ? Helpers::intVal($this->connection->nativeQuery( 'SELECT COUNT(*) FROM (' . $this->__toString() . ') t' - )->fetchSingle() + )->fetchSingle()) : $this->getTotalCount(); } return $this->count; @@ -299,9 +299,9 @@ FROM %SQL', $this->sql, ' public function getTotalCount() { if ($this->totalCount === null) { - $this->totalCount = (int) $this->connection->nativeQuery( + $this->totalCount = Helpers::intVal($this->connection->nativeQuery( 'SELECT COUNT(*) FROM ' . $this->sql - )->fetchSingle(); + )->fetchSingle()); } return $this->totalCount; } diff --git a/src/Dibi/Drivers/FirebirdDriver.php b/src/Dibi/Drivers/FirebirdDriver.php index 4d65f18b..84fa31c5 100644 --- a/src/Dibi/Drivers/FirebirdDriver.php +++ b/src/Dibi/Drivers/FirebirdDriver.php @@ -359,7 +359,9 @@ class FirebirdDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector { if ($limit > 0 || $offset > 0) { // http://www.firebirdsql.org/refdocs/langrefupd20-select.html - $sql = 'SELECT ' . ($limit > 0 ? 'FIRST ' . (int) $limit : '') . ($offset > 0 ? ' SKIP ' . (int) $offset : '') . ' * FROM (' . $sql . ')'; + $sql = 'SELECT ' . ($limit > 0 ? 'FIRST ' . Dibi\Helpers::intVal($limit) : '') + . ($offset > 0 ? ' SKIP ' . Dibi\Helpers::intVal($offset) : '') + . ' * FROM (' . $sql . ')'; } } diff --git a/src/Dibi/Drivers/MsSqlDriver.php b/src/Dibi/Drivers/MsSqlDriver.php index 4962f8ba..37f07e7e 100644 --- a/src/Dibi/Drivers/MsSqlDriver.php +++ b/src/Dibi/Drivers/MsSqlDriver.php @@ -315,7 +315,7 @@ class MsSqlDriver implements Dibi\Driver, Dibi\ResultDriver throw new Dibi\NotSupportedException('Negative offset or limit.'); } elseif ($limit !== null) { - $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t'; + $sql = 'SELECT TOP ' . Dibi\Helpers::intVal($limit) . ' * FROM (' . $sql . ') t'; } } diff --git a/src/Dibi/Drivers/MsSqlReflector.php b/src/Dibi/Drivers/MsSqlReflector.php index 83784b4e..24dbf4ab 100644 --- a/src/Dibi/Drivers/MsSqlReflector.php +++ b/src/Dibi/Drivers/MsSqlReflector.php @@ -69,12 +69,12 @@ class MsSqlReflector implements Dibi\Reflector if (!is_array($row) || count($row) < 1) { if ($fallback) { $row = $this->driver->query("SELECT COUNT(*) FROM {$this->driver->escapeIdentifier($table)}")->fetch(false); - $count = (int) ($row[0]); + $count = Dibi\Helpers::intVal($row[0]); } else { $count = false; } } else { - $count = (int) ($row[0]); + $count = Dibi\Helpers::intVal($row[0]); } return $count; diff --git a/src/Dibi/Drivers/MySqlDriver.php b/src/Dibi/Drivers/MySqlDriver.php index 629a7541..7d6dcd06 100644 --- a/src/Dibi/Drivers/MySqlDriver.php +++ b/src/Dibi/Drivers/MySqlDriver.php @@ -397,8 +397,8 @@ class MySqlDriver implements Dibi\Driver, Dibi\ResultDriver } elseif ($limit !== null || $offset) { // see http://dev.mysql.com/doc/refman/5.0/en/select.html - $sql .= ' LIMIT ' . ($limit === null ? '18446744073709551615' : (int) $limit) - . ($offset ? ' OFFSET ' . (int) $offset : ''); + $sql .= ' LIMIT ' . ($limit === null ? '18446744073709551615' : Dibi\Helpers::intVal($limit)) + . ($offset ? ' OFFSET ' . Dibi\Helpers::intVal($offset) : ''); } } diff --git a/src/Dibi/Drivers/MySqliDriver.php b/src/Dibi/Drivers/MySqliDriver.php index cd06fa18..34af4fbd 100644 --- a/src/Dibi/Drivers/MySqliDriver.php +++ b/src/Dibi/Drivers/MySqliDriver.php @@ -405,8 +405,8 @@ class MySqliDriver implements Dibi\Driver, Dibi\ResultDriver } elseif ($limit !== null || $offset) { // see http://dev.mysql.com/doc/refman/5.0/en/select.html - $sql .= ' LIMIT ' . ($limit === null ? '18446744073709551615' : (int) $limit) - . ($offset ? ' OFFSET ' . (int) $offset : ''); + $sql .= ' LIMIT ' . ($limit === null ? '18446744073709551615' : Dibi\Helpers::intVal($limit)) + . ($offset ? ' OFFSET ' . Dibi\Helpers::intVal($offset) : ''); } } diff --git a/src/Dibi/Drivers/OdbcDriver.php b/src/Dibi/Drivers/OdbcDriver.php index 52a93350..6ba663d5 100644 --- a/src/Dibi/Drivers/OdbcDriver.php +++ b/src/Dibi/Drivers/OdbcDriver.php @@ -339,7 +339,7 @@ class OdbcDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector throw new Dibi\NotSupportedException('Negative offset or limit.'); } elseif ($limit !== null) { - $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t'; + $sql = 'SELECT TOP ' . Dibi\Helpers::intVal($limit) . ' * FROM (' . $sql . ') t'; } } diff --git a/src/Dibi/Drivers/OracleDriver.php b/src/Dibi/Drivers/OracleDriver.php index 6e9ead9c..598799fe 100644 --- a/src/Dibi/Drivers/OracleDriver.php +++ b/src/Dibi/Drivers/OracleDriver.php @@ -170,7 +170,7 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector public function getInsertId($sequence) { $row = $this->query("SELECT $sequence.CURRVAL AS ID FROM DUAL")->fetch(true); - return isset($row['ID']) ? (int) $row['ID'] : false; + return isset($row['ID']) ? Dibi\Helpers::intVal($row['ID']) : false; } @@ -374,10 +374,10 @@ class OracleDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector // see http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html $sql = 'SELECT * FROM (SELECT t.*, ROWNUM AS "__rnum" FROM (' . $sql . ') t ' . ($limit !== null ? 'WHERE ROWNUM <= ' . ((int) $offset + (int) $limit) : '') - . ') WHERE "__rnum" > ' . (int) $offset; + . ') WHERE "__rnum" > ' . $offset; } elseif ($limit !== null) { - $sql = 'SELECT * FROM (' . $sql . ') WHERE ROWNUM <= ' . (int) $limit; + $sql = 'SELECT * FROM (' . $sql . ') WHERE ROWNUM <= ' . Dibi\Helpers::intVal($limit); } } diff --git a/src/Dibi/Drivers/PdoDriver.php b/src/Dibi/Drivers/PdoDriver.php index c2cbddf2..73375610 100644 --- a/src/Dibi/Drivers/PdoDriver.php +++ b/src/Dibi/Drivers/PdoDriver.php @@ -429,24 +429,24 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver case 'mysql': if ($limit !== null || $offset) { // see http://dev.mysql.com/doc/refman/5.0/en/select.html - $sql .= ' LIMIT ' . ($limit === null ? '18446744073709551615' : (int) $limit) - . ($offset ? ' OFFSET ' . (int) $offset : ''); + $sql .= ' LIMIT ' . ($limit === null ? '18446744073709551615' : Dibi\Helpers::intVal($limit)) + . ($offset ? ' OFFSET ' . Dibi\Helpers::intVal($offset) : ''); } break; case 'pgsql': if ($limit !== null) { - $sql .= ' LIMIT ' . (int) $limit; + $sql .= ' LIMIT ' . Dibi\Helpers::intVal($limit); } if ($offset) { - $sql .= ' OFFSET ' . (int) $offset; + $sql .= ' OFFSET ' . Dibi\Helpers::intVal($offset); } break; case 'sqlite': if ($limit !== null || $offset) { - $sql .= ' LIMIT ' . ($limit === null ? '-1' : (int) $limit) - . ($offset ? ' OFFSET ' . (int) $offset : ''); + $sql .= ' LIMIT ' . ($limit === null ? '-1' : Dibi\Helpers::intVal($limit)) + . ($offset ? ' OFFSET ' . Dibi\Helpers::intVal($offset) : ''); } break; @@ -455,10 +455,10 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver // see http://www.oracle.com/technology/oramag/oracle/06-sep/o56asktom.html $sql = 'SELECT * FROM (SELECT t.*, ROWNUM AS "__rnum" FROM (' . $sql . ') t ' . ($limit !== null ? 'WHERE ROWNUM <= ' . ((int) $offset + (int) $limit) : '') - . ') WHERE "__rnum" > ' . (int) $offset; + . ') WHERE "__rnum" > ' . $offset; } elseif ($limit !== null) { - $sql = 'SELECT * FROM (' . $sql . ') WHERE ROWNUM <= ' . (int) $limit; + $sql = 'SELECT * FROM (' . $sql . ') WHERE ROWNUM <= ' . Dibi\Helpers::intVal($limit); } break; @@ -480,7 +480,7 @@ class PdoDriver implements Dibi\Driver, Dibi\ResultDriver throw new Dibi\NotSupportedException('Offset is not supported by this database.'); } elseif ($limit !== null) { - $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t'; + $sql = 'SELECT TOP ' . Dibi\Helpers::intVal($limit) . ' * FROM (' . $sql . ') t'; break; } // break omitted diff --git a/src/Dibi/Drivers/PostgreDriver.php b/src/Dibi/Drivers/PostgreDriver.php index ccf6150a..ef4d2d93 100644 --- a/src/Dibi/Drivers/PostgreDriver.php +++ b/src/Dibi/Drivers/PostgreDriver.php @@ -412,10 +412,10 @@ class PostgreDriver implements Dibi\Driver, Dibi\ResultDriver, Dibi\Reflector throw new Dibi\NotSupportedException('Negative offset or limit.'); } if ($limit !== null) { - $sql .= ' LIMIT ' . (int) $limit; + $sql .= ' LIMIT ' . Dibi\Helpers::intVal($limit); } if ($offset) { - $sql .= ' OFFSET ' . (int) $offset; + $sql .= ' OFFSET ' . Dibi\Helpers::intVal($offset); } } diff --git a/src/Dibi/Drivers/Sqlite3Driver.php b/src/Dibi/Drivers/Sqlite3Driver.php index f59bae27..203ca1fa 100644 --- a/src/Dibi/Drivers/Sqlite3Driver.php +++ b/src/Dibi/Drivers/Sqlite3Driver.php @@ -358,8 +358,8 @@ class Sqlite3Driver implements Dibi\Driver, Dibi\ResultDriver throw new Dibi\NotSupportedException('Negative offset or limit.'); } elseif ($limit !== null || $offset) { - $sql .= ' LIMIT ' . ($limit === null ? '-1' : (int) $limit) - . ($offset ? ' OFFSET ' . (int) $offset : ''); + $sql .= ' LIMIT ' . ($limit === null ? '-1' : Dibi\Helpers::intVal($limit)) + . ($offset ? ' OFFSET ' . Dibi\Helpers::intVal($offset) : ''); } } diff --git a/src/Dibi/Fluent.php b/src/Dibi/Fluent.php index cc0f0805..e0ae70a5 100644 --- a/src/Dibi/Fluent.php +++ b/src/Dibi/Fluent.php @@ -408,9 +408,9 @@ class Fluent implements IDataSource */ public function count() { - return (int) $this->query([ + return Helpers::intVal($this->query([ 'SELECT COUNT(*) FROM (%ex', $this->_export(), ') [data]', - ])->fetchSingle(); + ])->fetchSingle()); } diff --git a/src/Dibi/Helpers.php b/src/Dibi/Helpers.php index ea429d82..c2b094d3 100644 --- a/src/Dibi/Helpers.php +++ b/src/Dibi/Helpers.php @@ -282,4 +282,21 @@ class Helpers fclose($handle); return $count; } + + + /** + * @internal + * @return string|int + */ + public static function intVal($value) + { + if (is_int($value)) { + return $value; + } elseif (is_string($value) && preg_match('#-?\d++\z#A', $value)) { + // support for long numbers - keep them unchanged + return is_float($number = $value * 1) ? $value : $number; + } else { + throw new Exception("Expected number, '$value' given."); + } + } } diff --git a/src/Dibi/Result.php b/src/Dibi/Result.php index e311115b..9be89174 100644 --- a/src/Dibi/Result.php +++ b/src/Dibi/Result.php @@ -111,7 +111,9 @@ class Result implements IDataSource */ final public function seek($row) { - return ($row !== 0 || $this->fetched) ? (bool) $this->getResultDriver()->seek($row) : true; + return ($row != 0 || $this->fetched) // intentionally == + ? (bool) $this->getResultDriver()->seek($row) + : true; } @@ -227,8 +229,8 @@ class Result implements IDataSource */ final public function fetchAll($offset = null, $limit = null) { - $limit = $limit === null ? -1 : (int) $limit; - $this->seek((int) $offset); + $limit = $limit === null ? -1 : Helpers::intVal($limit); + $this->seek($offset); $row = $this->fetch(); if (!$row) { return []; // empty result set diff --git a/src/Dibi/Translator.php b/src/Dibi/Translator.php index d2725eaa..c1e07025 100644 --- a/src/Dibi/Translator.php +++ b/src/Dibi/Translator.php @@ -538,7 +538,7 @@ final class Translator } elseif ($this->comment) { return "(limit $arg)"; } else { - $this->limit = (int) $arg; + $this->limit = Helpers::intVal($arg); } return ''; @@ -548,7 +548,7 @@ final class Translator } elseif ($this->comment) { return "(offset $arg)"; } else { - $this->offset = (int) $arg; + $this->offset = Helpers::intVal($arg); } return ''; diff --git a/tests/dibi/Fluent.select.phpt b/tests/dibi/Fluent.select.phpt index 45a85eca..4e56f5f2 100644 --- a/tests/dibi/Fluent.select.phpt +++ b/tests/dibi/Fluent.select.phpt @@ -142,10 +142,9 @@ if ($config['system'] === 'mysql') { ->limit(' 1; DROP TABLE users') ->offset(' 1; DROP TABLE users'); - Assert::same( - reformat(' SELECT * LIMIT 1 OFFSET 1'), - (string) $fluent - ); + Assert::error(function () use ($fluent) { + (string) $fluent; + }, E_USER_ERROR, "Expected number, ' 1; DROP TABLE users' given."); } diff --git a/tests/dibi/Helpers.intVal().phpt b/tests/dibi/Helpers.intVal().phpt new file mode 100644 index 00000000..d2fdc291 --- /dev/null +++ b/tests/dibi/Helpers.intVal().phpt @@ -0,0 +1,25 @@ +