From 0424200ac653a7b9f47ba0d038b944730e445bdb Mon Sep 17 00:00:00 2001 From: David M Date: Sun, 9 Jul 2006 05:09:37 +0000 Subject: [PATCH] Short story: Oracle does not like sub queries that contain columns that have the same name Long story: Expanding the implicitly defined columns to explicitly defined columns lets us determine which columns we are actually grabbing. This lets us avoid the problem of having two columns having the same name even though one is implicit and the other is explicit. What does this mean? It means that when doing a limit on Oracle with an implicit column and a bunch of explicit columns, the explicit columns are the ones that "win". git-svn-id: file:///svn/phpbb/trunk@6159 89ea8834-ac86-4346-8a33-228a782c2dd0 --- phpBB/includes/db/oracle.php | 46 ++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/oracle.php index 464e6ad9de..499316ac80 100644 --- a/phpBB/includes/db/oracle.php +++ b/phpBB/includes/db/oracle.php @@ -155,6 +155,52 @@ class dbal_oracle extends dbal { $this->query_result = false; + // Any implicit columns exist? + if (strpos($query, '.*') !== false) + { + // This sucker does a few things for us. It grabs all the explicitly named columns and what tables are being used + preg_match('/SELECT (?:DISTINCT )?(.*?)FROM(.*?)(?:WHERE|(ORDER|GROUP) BY|$)/s', $query, $tables); + + // The prefixes of the explicit columns don't matter, they simply get in the way + preg_match_all('/\.(\w+)/', trim($tables[1]), $columns); + + // Flip lets us do an easy isset() call + $columns = array_flip($columns[1]); + + $table_data = trim($tables[2]); + + // Grab the implicitly named columns, they need expanding... + preg_match_all('/(\w)\.\*/', $query, $info); + + $cols = array(); + + foreach ($info[1] as $table_alias) + { + // We need to get the name of the aliased table + preg_match('/(\w+) ' . $table_alias . '/', $table_data, $table_name); + $table_name = $table_name[1]; + + $sql = "SELECT column_name + FROM all_tab_cols + WHERE table_name = '" . strtoupper($table_name) . "'"; + + $result = $this->sql_query($sql); + while ($row = $this->sql_fetchrow($result)) + { + if (!isset($columns[strtolower($row['column_name'])])) + { + $cols[] = $table_alias . '.' . strtolower($row['column_name']); + } + } + $this->sql_freeresult($result); + + // Remove the implicity .* with it's full expansion + $query = str_replace($table_alias . '.*', implode(', ', $cols), $query); + + unset($cols); + } + } + $query = 'SELECT * FROM (SELECT /*+ FIRST_ROWS */ rownum AS xrownum, a.* FROM (' . $query . ') a WHERE rownum <= ' . ($offset + $total) . ') WHERE xrownum >= ' . $offset; return $this->sql_query($query, $cache_ttl);