Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix sorting for number based custom fields
For types numeric, float, and dates
- Make nulls appear last in the ordered result.
- Cast the values to sort them numerically.

Fixes: #23260, #6872
  • Loading branch information
cproensa authored and dregad committed Oct 7, 2017
1 parent 9d24d04 commit dc68e44
Showing 1 changed file with 40 additions and 2 deletions.
42 changes: 40 additions & 2 deletions core/filter_api.php
Expand Up @@ -1112,9 +1112,47 @@ function filter_get_query_sort_data( array &$p_filter, $p_show_sticky, array $p_
continue;
}

$t_field_alias = 'cf_sortfield_' . $t_custom_field_id;
$t_sort_col = $t_table_name . '.' . $t_value_field;

# which types need special type cast
switch( $t_def['type'] ) {
case CUSTOM_FIELD_TYPE_FLOAT:
# mysql can't cast to float, use alternative syntax
$t_sort_expr = db_is_mysql() ? $t_sort_col . '+0.0' : 'CAST(' . $t_sort_col . ' AS FLOAT)';
break;
case CUSTOM_FIELD_TYPE_DATE:
case CUSTOM_FIELD_TYPE_NUMERIC:
$t_sort_expr = 'CAST(' . $t_sort_col . ' AS DECIMAL)';
break;
default: # no cast needed
$t_sort_expr = $t_sort_col;
}

# which types need special treatment for null sorting
switch( $t_def['type'] ) {
case CUSTOM_FIELD_TYPE_DATE:
case CUSTOM_FIELD_TYPE_NUMERIC:
case CUSTOM_FIELD_TYPE_FLOAT:
$t_null_last = true;
break;
default:
$t_null_last = false;
}

if( $t_null_last ) {
$t_null_expr = 'CASE WHEN NULLIF(' . $t_sort_col . ', \'\') IS NULL THEN 1 ELSE 0 END';
$t_clause_for_select = $t_null_expr . ' AS ' . $t_field_alias . '_null';
$t_clause_for_select .= ', ' . $t_sort_expr . ' AS ' . $t_field_alias;
$t_clause_for_order = $t_field_alias . '_null ASC, ' . $t_field_alias . ' ' . $c_dir;
} else {
$t_clause_for_select = $t_sort_expr . ' AS ' . $t_field_alias;
$t_clause_for_order = $t_field_alias . ' ' . $c_dir;
}

# Note: pgsql needs the sort expression to appear as member of the "select distinct"
$p_query_clauses['select'][] = $t_table_name . '.' . $t_value_field;
$p_query_clauses['order'][] = $t_table_name . '.' . $t_value_field . ' ' . $c_dir;
$p_query_clauses['select'][] = $t_clause_for_select;
$p_query_clauses['order'][] = $t_clause_for_order;

# if sorting by plugin columns
} else if( column_is_plugin_column( $c_sort ) ) {
Expand Down

0 comments on commit dc68e44

Please sign in to comment.