diff --git a/dibi/drivers/DibiPdoDriver.php b/dibi/drivers/DibiPdoDriver.php index f049c011..4bbde339 100644 --- a/dibi/drivers/DibiPdoDriver.php +++ b/dibi/drivers/DibiPdoDriver.php @@ -38,6 +38,9 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver /** @var string */ private $driverName; + /** @var string */ + private $serverVersion; + /** * @throws DibiNotSupportedException @@ -75,6 +78,7 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver } $this->driverName = $this->connection->getAttribute(PDO::ATTR_DRIVER_NAME); + $this->serverVersion = $this->connection->getAttribute(PDO::ATTR_SERVER_VERSION); } @@ -396,10 +400,19 @@ class DibiPdoDriver extends DibiObject implements IDibiDriver, IDibiResultDriver } break; - case 'odbc': - case 'dblib': case 'mssql': case 'sqlsrv': + case 'dblib': + if (version_compare($this->serverVersion, '11.0') >= 0) { + if ($offset >= 0 || $limit >= 0) { + $sql .= ' OFFSET ' . (int) $offset . ' ROWS' + . ($limit > 0 ? ' FETCH NEXT ' . (int) $limit . ' ROWS ONLY' : ''); + } + break; + } + // intentionally break omitted + + case 'odbc': if ($offset < 1) { $sql = 'SELECT TOP ' . (int) $limit . ' * FROM (' . $sql . ') t'; break; diff --git a/tests/dibi/PdoMssql.limits.phpt b/tests/dibi/PdoMssql.limits.phpt new file mode 100644 index 00000000..e12e66cd --- /dev/null +++ b/tests/dibi/PdoMssql.limits.phpt @@ -0,0 +1,80 @@ +getDriver()->getResource()->getAttribute(PDO::ATTR_SERVER_VERSION); + + // MsSQL2012+ + if(version_compare($version, '11.0') >= 0) { + // Limit and offset + Assert::same( + 'SELECT 1 OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY', + $conn->translate('SELECT 1 %ofs %lmt', 10, 10) + ); + + // Limit only + Assert::same( + 'SELECT 1 OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY', + $conn->translate('SELECT 1 %lmt', 10) + ); + + // Offset only + Assert::same( + 'SELECT 1 OFFSET 10 ROWS', + $conn->translate('SELECT 1 %ofs', 10) + ); + + // Offset invalid + Assert::same( + 'SELECT 1', + $conn->translate('SELECT 1 %ofs', -10) + ); + + // Limit invalid + Assert::same( + 'SELECT 1', + $conn->translate('SELECT 1 %lmt', -10) + ); + + // Limit invalid, offset valid + Assert::same( + 'SELECT 1', + $conn->translate('SELECT 1 %ofs %lmt', 10, -10) + ); + + // Limit valid, offset invalid + Assert::same( + 'SELECT 1', + $conn->translate('SELECT 1 %ofs %lmt', -10, 10) + ); + } else { + Assert::same( + 'SELECT TOP 1 * FROM (SELECT 1) t', + $conn->translate('SELECT 1 %lmt', 1) + ); + + Assert::same( + 'SELECT 1', + $conn->translate('SELECT 1 %lmt', -10) + ); + + Assert::exception( + $conn->translate('SELECT 1 %ofs %lmt', 10, 10), + 'DibiNotSupportedException' + ); + } +}; + +$conn = new DibiConnection($config); +$tests($conn);