diff --git a/libraries/TableSearch.class.php b/libraries/TableSearch.class.php index d2521c064b..a3b2b2ff13 100644 --- a/libraries/TableSearch.class.php +++ b/libraries/TableSearch.class.php @@ -101,7 +101,7 @@ class PMA_TableSearch $this->_columnCollations = array(); $this->_geomColumnFlag = false; $this->_foreigners = array(); - + // Loads table's information $this->_loadTableInfo($this->_db, $this->_table); } @@ -408,5 +408,790 @@ EOT; } return $str; } + + /** + * Return the where clause in case column's type is ENUM. + * + * @param mixed $criteriaValues Search criteria input + * @param string $func_type Search fucntion/operator + * + * @return string part of where clause. + */ + private function _getEnumWhereClause($criteriaValues, $func_type) + { + $where = ''; + if (! empty($criteriaValues)) { + if (! is_array($criteriaValues)) { + $criteriaValues = explode(',', $criteriaValues); + } + $enum_selected_count = count($criteriaValues); + if ($func_type == '=' && $enum_selected_count > 1) { + $func_type = 'IN'; + $parens_open = '('; + $parens_close = ')'; + + } elseif ($func_type == '!=' && $enum_selected_count > 1) { + $func_type = 'NOT IN'; + $parens_open = '('; + $parens_close = ')'; + + } else { + $parens_open = ''; + $parens_close = ''; + } + $enum_where = '\'' . PMA_sqlAddslashes($criteriaValues[0]) . '\''; + for ($e = 1; $e < $enum_selected_count; $e++) { + $enum_where .= ', \'' . PMA_sqlAddslashes($criteriaValues[$e]) + . '\''; + } + + $where = ' ' . $func_type . ' ' . $parens_open + . $enum_where . $parens_close; + } + return $where; + } + + /** + * Return the where clause for a geometrical column. + * + * @param mixed $criteriaValues Search criteria input + * @param string $names Name of the column on which search is submitted + * @param string $func_type Search fucntion/operator + * @param bool $geom_func Whether geometry functions should be applied + * + * @return string part of where clause. + */ + private function _getGeomWhereClause($criteriaValues, $names, $func_type, $geom_func = null) + { + $geom_unary_functions = array( + 'IsEmpty' => 1, + 'IsSimple' => 1, + 'IsRing' => 1, + 'IsClosed' => 1, + ); + $where = ''; + + // Get details about the geometry fucntions + $geom_funcs = PMA_getGISFunctions($types, true, false); + // New output type is the output type of the function being applied + $types = $geom_funcs[$geom_func]['type']; + + // If the function takes a single parameter + if ($geom_funcs[$geom_func]['params'] == 1) { + $backquoted_name = $geom_func . '(' . PMA_backquote($names) . ')'; + } else { + // If the function takes two parameters + // create gis data from the criteria input + $gis_data = PMA_createGISData($criteriaValues); + $where = $geom_func . '(' . PMA_backquote($names) . ',' . $gis_data . ')'; + return $where; + } + + // If the where clause is something like 'IsEmpty(`spatial_col_name`)' + if (isset($geom_unary_functions[$geom_func]) && trim($criteriaValues) == '') { + $where = $backquoted_name; + + } elseif (in_array($types, PMA_getGISDatatypes()) && ! empty($criteriaValues)) { + // create gis data from the criteria input + $gis_data = PMA_createGISData($criteriaValues); + $where = $backquoted_name . ' ' . $func_type . ' ' . $gis_data; + } + return $where; + } + + /** + * Return the where clause for query generation based on the inputs provided. + * + * @param mixed $criteriaValues Search criteria input + * @param string $names Name of the column on which search is submitted + * @param string $types Type of the field + * @param string $collations Field collation + * @param string $func_type Search fucntion/operator + * @param bool $unaryFlag Whether operator unary or not + * @param bool $geom_func Whether geometry functions should be applied + * + * @return string generated where clause. + */ + private function _getWhereClause($criteriaValues, $names, $types, $collations, + $func_type, $unaryFlag, $geom_func = null + ) { + // If geometry function is set + if ($geom_func != null && trim($geom_func) != '') { + return _getGeomWhereClause($criteriaValues, $names, $func_type, $geom_func); + } + + $backquoted_name = PMA_backquote($names); + $where = ''; + if ($unaryFlag) { + $criteriaValues = ''; + $where = $backquoted_name . ' ' . $func_type; + + } elseif (strncasecmp($types, 'enum', 4) == 0) { + $where = $backquoted_name; + $where .= _getEnumWhereClause($criteriaValues, $func_type); + + } elseif ($criteriaValues != '') { + // For these types we quote the value. Even if it's another type (like INT), + // for a LIKE we always quote the value. MySQL converts strings to numbers + // and numbers to strings as necessary during the comparison + if (preg_match('@char|binary|blob|text|set|date|time|year@i', $types) + || strpos(' ' . $func_type, 'LIKE') + ) { + $quot = '\''; + } else { + $quot = ''; + } + + // LIKE %...% + if ($func_type == 'LIKE %...%') { + $func_type = 'LIKE'; + $criteriaValues = '%' . $criteriaValues . '%'; + } + if ($func_type == 'REGEXP ^...$') { + $func_type = 'REGEXP'; + $criteriaValues = '^' . $criteriaValues . '$'; + } + + if ($func_type == 'IN (...)' + || $func_type == 'NOT IN (...)' + || $func_type == 'BETWEEN' + || $func_type == 'NOT BETWEEN' + ) { + $func_type = str_replace(' (...)', '', $func_type); + + // quote values one by one + $values = explode(',', $criteriaValues); + foreach ($values as &$value) { + $value = $quot . PMA_sqlAddslashes(trim($value)) . $quot; + } + + if ($func_type == 'BETWEEN' || $func_type == 'NOT BETWEEN') { + $where = $backquoted_name . ' ' . $func_type . ' ' + . (isset($values[0]) ? $values[0] : '') + . ' AND ' . (isset($values[1]) ? $values[1] : ''); + } else { + $where = $backquoted_name . ' ' . $func_type + . ' (' . implode(',', $values) . ')'; + } + } else { + $where = $backquoted_name . ' ' . $func_type . ' ' + . $quot . PMA_sqlAddslashes($criteriaValues) . $quot; + } + } // end if + + return $where; + } + + /** + * Builds the sql search query from the post parameters + * + * @return string the generated SQL query + */ + public function _buildSqlQuery() + { + $sql_query = 'SELECT '; + + // If only distinct values are needed + $is_distinct = (isset($_POST['distinct'])) ? 'true' : 'false'; + if ($is_distinct == 'true') { + $sql_query .= 'DISTINCT '; + } + + // if all column names were selected to display, we do a 'SELECT *' + // (more efficient and this helps prevent a problem in IE + // if one of the rows is edited and we come back to the Select results) + if (isset($_POST['zoom_submit'])) { + $sql_query .= '* '; + } else { + $sql_query .= (count($_POST['columnsToDisplay']) + == count($_POST['criteriaColumnNames']) + ? '* ' + : implode(', ', PMA_backquote($_POST['columnsToDisplay']))); + } // end if + + $sql_query .= ' FROM ' . PMA_backquote($_POST['table']); + $whereClause = _generateWhereClause(); + $sql_query .= $whereClause; + + // if the search results are to be ordered + if (isset($_POST['orderByColumn']) && $_POST['orderByColumn'] != '--nil--') { + $sql_query .= ' ORDER BY ' . PMA_backquote($_POST['orderByColumn']) + . ' ' . $_POST['order']; + } // end if + return $sql_query; + } + + /** + * Generates the where clause for the SQL search query to be executed + * + * @return string the generated where clause + */ + private function _generateWhereClause() + { + $fullWhereClause = ''; + + if (isset($_POST['customWhereClause']) && trim($_POST['customWhereClause']) != '') { + $fullWhereClause .= ' WHERE ' . $_POST['customWhereClause']; + return $fullWhereClause; + } + + // If there are no search criteria set, return + if (! array_filter($_POST['criteriaValues'])) { + return $fullWhereClause; + } + + // else continue to form the where clause from column criteria values + $fullWhereClause = $charsets = array(); + reset($_POST['criteriaColumnOperators']); + while (list($column_index, $operator) = each($_POST['criteriaColumnOperators'])) { + list($charsets[$column_index]) = explode( + '_', $_POST['criteriaColumnCollations'][$column_index] + ); + $unaryFlag = $GLOBALS['PMA_Types']->isUnaryOperator($operator); + $tmp_geom_func = isset($geom_func[$column_index]) + ? $geom_func[$column_index] : null; + + $whereClause = _getWhereClause( + $_POST['criteriaValues'][$column_index], + $_POST['criteriaColumnNames'][$column_index], + $_POST['criteriaColumnTypes'][$column_index], + $_POST['criteriaColumnCollations'][$column_index], $operator, $unaryFlag, + $tmp_geom_func + ); + + if ($whereClause) { + $fullWhereClause[] = $whereClause; + } + } // end while + + if ($fullWhereClause) { + $fullWhereClause = ' WHERE ' . implode(' AND ', $fullWhereClause); + } + return $fullWhereClause; + } + + /** + * Generates HTML for a geometrical function column to be displayed in table + * search selection form + * + * @param integer $column_index index of current column in $columnTypes array + * + * @return string the generated HTML + */ + private function _getGeomFuncHtml($column_index) + { + $html_output = ''; + // return if geometrical column is not present + if (! $this->_geomColumnFlag) { + return $html_output; + } + + /** + * Displays 'Function' column if it is present + */ + $html_output .= '
| '; + $html_output .= ' | '; + $html_output .= ' |
| '; + $html_output .= ' | '; + $html_output .= ''; + $html_output .= ' |