mirror of
https://github.com/grafana/grafana.git
synced 2025-08-02 01:15:46 +08:00
SQL Expressions: Add CASE/WHEN nodes and fixes (and test) for functions just added to allowlist (#102040)
* SQL Expressions: Add CASE/WHEN SQL nodes to allowlist * Fixed and test for functions added in #102011 * Add remaining functions to the test-case These are mostly aliases, so the LLM chose to omit them originally. But adding now for completeness * Fix ordering of allowed nodes
This commit is contained in:
@ -63,6 +63,9 @@ func allowedNode(node sqlparser.SQLNode) (b bool) {
|
|||||||
case sqlparser.BoolVal:
|
case sqlparser.BoolVal:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
case *sqlparser.CaseExpr, *sqlparser.When:
|
||||||
|
return
|
||||||
|
|
||||||
case sqlparser.ColIdent, *sqlparser.ColName, sqlparser.Columns:
|
case sqlparser.ColIdent, *sqlparser.ColName, sqlparser.Columns:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -75,7 +78,7 @@ func allowedNode(node sqlparser.SQLNode) (b bool) {
|
|||||||
case *sqlparser.ComparisonExpr:
|
case *sqlparser.ComparisonExpr:
|
||||||
return
|
return
|
||||||
|
|
||||||
case *sqlparser.ConvertExpr:
|
case *sqlparser.ConvertExpr, *sqlparser.ConvertType:
|
||||||
return
|
return
|
||||||
|
|
||||||
case sqlparser.GroupBy:
|
case sqlparser.GroupBy:
|
||||||
@ -84,6 +87,9 @@ func allowedNode(node sqlparser.SQLNode) (b bool) {
|
|||||||
case *sqlparser.IndexHints:
|
case *sqlparser.IndexHints:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
case *sqlparser.IntervalExpr:
|
||||||
|
return
|
||||||
|
|
||||||
case *sqlparser.Into:
|
case *sqlparser.Into:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -120,6 +126,9 @@ func allowedNode(node sqlparser.SQLNode) (b bool) {
|
|||||||
case sqlparser.TableName, sqlparser.TableExprs, sqlparser.TableIdent:
|
case sqlparser.TableName, sqlparser.TableExprs, sqlparser.TableIdent:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
case *sqlparser.TrimExpr:
|
||||||
|
return
|
||||||
|
|
||||||
case *sqlparser.With:
|
case *sqlparser.With:
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -165,7 +174,7 @@ func allowedFunction(f *sqlparser.FuncExpr) (b bool) {
|
|||||||
return
|
return
|
||||||
case "lower", "upper":
|
case "lower", "upper":
|
||||||
return
|
return
|
||||||
case "substring", "trim":
|
case "substring":
|
||||||
return
|
return
|
||||||
|
|
||||||
// Date functions
|
// Date functions
|
||||||
@ -183,7 +192,7 @@ func allowedFunction(f *sqlparser.FuncExpr) (b bool) {
|
|||||||
return
|
return
|
||||||
|
|
||||||
// Type conversion
|
// Type conversion
|
||||||
case "cast", "convert":
|
case "cast":
|
||||||
return
|
return
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -22,6 +22,16 @@ func TestAllowQuery(t *testing.T) {
|
|||||||
q: example_argo_commit_example,
|
q: example_argo_commit_example,
|
||||||
err: nil,
|
err: nil,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "case statement",
|
||||||
|
q: example_case_statement,
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "all allowed functions",
|
||||||
|
q: example_all_allowed_functions,
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
@ -109,3 +119,78 @@ FROM drone,
|
|||||||
argo_success,
|
argo_success,
|
||||||
argo_failure,
|
argo_failure,
|
||||||
workflows;`
|
workflows;`
|
||||||
|
|
||||||
|
var example_case_statement = `SELECT
|
||||||
|
value,
|
||||||
|
CASE
|
||||||
|
WHEN value > 100 THEN 'High'
|
||||||
|
WHEN value > 50 THEN 'Medium'
|
||||||
|
ELSE 'Low'
|
||||||
|
END AS category
|
||||||
|
FROM metrics`
|
||||||
|
|
||||||
|
var example_all_allowed_functions = `SELECT
|
||||||
|
-- Conditional functions
|
||||||
|
IF(value > 100, 'High', 'Low') AS conditional_if,
|
||||||
|
COALESCE(value, 0) AS conditional_coalesce,
|
||||||
|
IFNULL(value, 0) AS conditional_ifnull,
|
||||||
|
NULLIF(value, 0) AS conditional_nullif,
|
||||||
|
|
||||||
|
-- Aggregation functions
|
||||||
|
SUM(value) AS agg_sum,
|
||||||
|
AVG(value) AS agg_avg,
|
||||||
|
COUNT(*) AS agg_count,
|
||||||
|
MIN(value) AS agg_min,
|
||||||
|
MAX(value) AS agg_max,
|
||||||
|
STDDEV(value) AS agg_stddev,
|
||||||
|
STD(value) AS agg_std,
|
||||||
|
STDDEV_POP(value) AS agg_stddev_pop,
|
||||||
|
VARIANCE(value) AS agg_variance,
|
||||||
|
VAR_POP(value) AS agg_var_pop,
|
||||||
|
|
||||||
|
-- Mathematical functions
|
||||||
|
ABS(value) AS math_abs,
|
||||||
|
ROUND(value, 2) AS math_round,
|
||||||
|
FLOOR(value) AS math_floor,
|
||||||
|
CEILING(value) AS math_ceiling,
|
||||||
|
CEIL(value) AS math_ceil,
|
||||||
|
SQRT(ABS(value)) AS math_sqrt,
|
||||||
|
POW(value, 2) AS math_pow,
|
||||||
|
POWER(value, 2) AS math_power,
|
||||||
|
MOD(value, 10) AS math_mod,
|
||||||
|
LOG(value) AS math_log,
|
||||||
|
LOG10(value) AS math_log10,
|
||||||
|
EXP(value) AS math_exp,
|
||||||
|
SIGN(value) AS math_sign,
|
||||||
|
|
||||||
|
-- String functions
|
||||||
|
CONCAT('value: ', CAST(value AS CHAR)) AS str_concat,
|
||||||
|
LENGTH(name) AS str_length,
|
||||||
|
CHAR_LENGTH(name) AS str_char_length,
|
||||||
|
LOWER(name) AS str_lower,
|
||||||
|
UPPER(name) AS str_upper,
|
||||||
|
SUBSTRING(name, 1, 5) AS str_substring,
|
||||||
|
TRIM(name) AS str_trim,
|
||||||
|
|
||||||
|
-- Date functions
|
||||||
|
STR_TO_DATE('2023-01-01', '%Y-%m-%d') AS date_str_to_date,
|
||||||
|
DATE_FORMAT(NOW(), '%Y-%m-%d') AS date_format,
|
||||||
|
NOW() AS date_now,
|
||||||
|
CURDATE() AS date_curdate,
|
||||||
|
CURTIME() AS date_curtime,
|
||||||
|
DATE_ADD(created_at, INTERVAL 1 DAY) AS date_add,
|
||||||
|
DATE_SUB(created_at, INTERVAL 1 DAY) AS date_sub,
|
||||||
|
YEAR(created_at) AS date_year,
|
||||||
|
MONTH(created_at) AS date_month,
|
||||||
|
DAY(created_at) AS date_day,
|
||||||
|
WEEKDAY(created_at) AS date_weekday,
|
||||||
|
DATEDIFF(NOW(), created_at) AS date_datediff,
|
||||||
|
UNIX_TIMESTAMP(created_at) AS date_unix_timestamp,
|
||||||
|
FROM_UNIXTIME(1634567890) AS date_from_unixtime,
|
||||||
|
|
||||||
|
-- Type conversion
|
||||||
|
CAST(value AS CHAR) AS type_cast,
|
||||||
|
CONVERT(value, CHAR) AS type_convert
|
||||||
|
FROM metrics
|
||||||
|
GROUP BY name, value, created_at
|
||||||
|
LIMIT 10`
|
||||||
|
Reference in New Issue
Block a user