diff --git a/libraries/joomla/database/query/sqlsrv.php b/libraries/joomla/database/query/sqlsrv.php index 46ff6ddaf056c..a83c044490972 100644 --- a/libraries/joomla/database/query/sqlsrv.php +++ b/libraries/joomla/database/query/sqlsrv.php @@ -356,4 +356,98 @@ public function setLimit($limit = 0, $offset = 0) return $this; } + + /** + * Add a grouping column to the GROUP clause of the query. + * + * Usage: + * $query->group('id'); + * + * @param mixed $columns A string or array of ordering columns. + * + * @return JDatabaseQuery Returns this object to allow chaining. + * + * @since 11.1 + */ + public function group($columns) + { + if (!is_array($columns)) + { + // Transform $columns into an array for filtering purposes + $columns = explode(",", str_replace(" ", "", $columns)); + } + + // Get the _formatted_ FROM string and remove everything except `table AS alias` + $fromStr = str_replace(array("[","]"), "", str_replace("#__", $this->db->getPrefix(), str_replace("FROM ", "", (string) $this->from))); + + // Start setting up an array of alias => table + list($table, $alias) = preg_split("/\sAS\s/i", $fromStr); + $tmpCols = $this->db->getTableColumns(trim($table)); + $cols = array(); + foreach ($tmpCols as $name => $type) + { + $cols[] = $alias . "." . $name; + } + + // Now we need to get all tables from any joins + // Go through all joins and add them to the tables array + $joins = array(); + foreach ((array) $this->join as $join) + { + $joinTbl = str_replace("#__", $this->db->getPrefix(), str_replace("]", "", preg_replace("/.*(#.+\sAS\s[^\s]*).*/i", "$1", (string) $join))); + list($table, $alias) = preg_split("/\sAS\s/i", $joinTbl); + $tmpCols = $this->db->getTableColumns(trim($table)); + foreach ($tmpCols as $name => $tmpColType) + { + array_push($cols, $alias . "." . $name); + } + } + + $selectStr = str_replace("SELECT ", "", (string) $this->select); + + // Remove any functions (e.g. COUNT(), SUM(), CONCAT()) + $selectCols = preg_replace("/([^,]*\([^\)]*\)[^,]*,?)/", "", $selectStr); + + // Remove any "as alias" statements + $selectCols = preg_replace("/(\sas\s[^,]*)/i", "", $selectCols); + + // Remove any non-table column names, e.g. '2' + $selectCols = preg_replace("/\'[^\']*/", "", $selectCols); + + // Remove any extra commas + $selectCols = preg_replace("/,{2,}/", ",", $selectCols); + + // Remove any trailing commas and all whitespaces + $selectCols = trim(str_replace(" ", "", preg_replace("/,?$/", "", $selectCols))); + + // Get an array to compare against + $selectCols = explode(",", $selectCols); + + // Find all alias.* and fill with proper table column names + foreach ($selectCols as $key => $aliasColName) + { + if (preg_match("/.+\*/", $aliasColName, $match)) + { + + // Grab the table alias minus the .* + $aliasStar = preg_replace("/(.+)\.\*/", "$1", $aliasColName); + + // Unset the array key + unset($selectCols[$key]); + + // Get the table name + $tableColumns = preg_grep("/{$aliasStar}\.+/", $cols); + $columns = array_merge($columns, $tableColumns); + } + } + + $columns = array_unique(array_merge($columns, $selectCols)); + $columns = implode(",", $columns); + + // Recreate it every time, to ensure we have checked _all_ select statements + // Each and every god damn time + $this->group = new JDatabaseQueryElement('GROUP BY', $columns); + + return $this; + } }