Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: chrismeller/db
base: 23ea5792ed
...
head fork: chrismeller/db
compare: c0bc9e3c7f
Checking mergeability… Don't worry, you can still create the pull request.
  • 2 commits
  • 2 files changed
  • 0 commit comments
  • 1 contributor
Commits on Mar 27, 2012
Chris Meller Add optional aliases to the register_table capabilities, so you don't…
… have to use an inconveniently long name in all your queries.
f14a879
Chris Meller Add a new sql_t for DB2 connections - our LIMIT emulation wasn't work…
…ing when there was an ORDER BY clause, which you have to specifically pass in to the OVER() method.
c0bc9e3
Showing with 79 additions and 19 deletions.
  1. +19 −7 classes/db/connection.php
  2. +60 −12 classes/db/connection/odbc/db2.php
View
26 classes/db/connection.php
@@ -98,8 +98,8 @@ public function sql_t ( $query ) {
// replace any registered table names in the query
$replace = array();
- foreach ( $this->tables as $table ) {
- $replace[ '{' . $table . '}' ] = $this->table_prefix( $table );
+ foreach ( $this->tables as $alias => $table ) {
+ $replace[ '{' . $alias . '}' ] = $this->table_prefix( $table );
}
$query = str_replace( array_keys( $replace ), array_values( $replace ), $query );
@@ -108,15 +108,27 @@ public function sql_t ( $query ) {
}
- public function register_table ( $table ) {
+ public function register_table ( $alias, $table = null ) {
- if ( is_array( $table ) ) {
- foreach ( $table as $t ) {
- $this->register_table( $t );
+ if ( is_array( $alias ) ) {
+ foreach ( $alias as $a => $t ) {
+
+ // for a numeric array, assume no alias
+ if ( is_numeric( $a ) ) {
+ $a = $t;
+ $t = null;
+ }
+
+ $this->register_table( $a, $t );
}
}
+
+ // if there is no table, the alias is actually the table name - use it for both
+ if ( $table == null ) {
+ $table = $alias;
+ }
- $this->tables[ $table ] = $table;
+ $this->tables[ $alias ] = $table;
}
View
72 classes/db/connection/odbc/db2.php
@@ -3,32 +3,80 @@
namespace DB;
class DB_Connection_ODBC_DB2 extends DB_Connection_ODBC {
-
+
public function sql_t ( $query ) {
-
- // if there's an offset, we need a callback to replace it
+
+ // if there's an offset with an order by, we need a special callback to replace it
+ $query = preg_replace_callback( '/^(.*)\s+(ORDER BY\s+.*\s)LIMIT\s+(\d+),\s+(\d+)$/is', array( $this, 'replace_offset_order' ), $query );
+
+ // if there's an offset but no order by, we have a slightly simpler callback to replace it
$query = preg_replace_callback( '/^(.*)LIMIT\s+(\d+),\s+(\d+)$/is', array( $this, 'replace_offset' ), $query );
-
+
// if there's no offset, it's a simple replace
$query = preg_replace( '/LIMIT\s+(\d+)/ims', 'FETCH FIRST ${1} ROWS ONLY', $query );
$query = parent::sql_t( $query );
-
+
return $query;
-
+
}
-
+
public function replace_offset ( $matches ) {
-
+
+ // the matches should be:
+ // 1: the full query, missing its LIMIT clause
+ // 2: the LIMIT offset (ie: start)
+ // 3: the LIMIT row count (ie: stop + 1 )
+
$start = $matches[2];
$stop = $start + $matches[3] - 1;
-
+
$query = 'select * from ( select OFFSET_TEMP1.*, rownumber() OVER() as ROW_NUM FROM ( ' . $matches[1] . ' ) AS OFFSET_TEMP1 ) AS OFFSET_TEMP2 where ROW_NUM between ' . $start . ' and ' . $stop;
-
+
return $query;
-
+
}
-
+
+ public function replace_offset_order ( $matches ) {
+
+ // the matches should be:
+ // 1: the full query, missing its ORDER BY and LIMIT clauses
+ // 2: the ORDER BY clause
+ // 3: the LIMIT offset (ie: start)
+ // 4: the LIMIT row count (ie: stop + 1 )
+
+ // pull out our matches, for clarity
+ $query = $matches[1];
+ $order_by = $matches[2];
+ $offset = $matches[3];
+ $row_count = $matches[4];
+
+ // stop is the raw number of results we want to return, but the BETWEEN we translate into is inclusive, so we need to get one less record
+ $stop = $offset + ( $row_count - 1 );
+
+ // the order by was trimmed from our query, so make sure it gets put back where it belongs
+ $query = $query . ' ' . $order_by;
+
+ // build the full query
+ $full_query = <<<QUERY
+select
+ *
+from (
+ select
+ OFFSET_TEMP1.*,
+ rownumber() OVER( {$order_by} ) as ROW_NUM
+ from (
+ {$query}
+ ) as OFFSET_TEMP1
+) as OFFSET_TEMP2
+where
+ ROW_NUM between {$offset} and {$stop}
+QUERY;
+
+ return $full_query;
+
+ }
+
}
?>

No commit comments for this range

Something went wrong with that request. Please try again.