mirror of
https://github.com/grafana/grafana.git
synced 2025-07-29 23:22:32 +08:00
SQL Expressions: Re-implement feature using go-mysql-server (#99521)
* Under feature flag `sqlExpressions` and is experimental * Excluded from arm32 * Will not work with the Query Service yet * Does not have limits in place yet * Does not working with alerting yet * Currently requires "prepare time series" Transform for time series viz --------- Co-authored-by: Sam Jewell <sam.jewell@grafana.com>
This commit is contained in:
@ -3,214 +3,131 @@ package sql
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := "select * from foo"
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
func TestTablesList(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
sql string
|
||||
expected []string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "simple select",
|
||||
sql: "select * from foo",
|
||||
expected: []string{"foo"},
|
||||
},
|
||||
{
|
||||
name: "select with comma",
|
||||
sql: "select * from foo,bar",
|
||||
expected: []string{"bar", "foo"},
|
||||
},
|
||||
{
|
||||
name: "select with multiple commas",
|
||||
sql: "select * from foo,bar,baz",
|
||||
expected: []string{"bar", "baz", "foo"},
|
||||
},
|
||||
{
|
||||
name: "no table",
|
||||
sql: "select 1 as 'n'",
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
name: "json array",
|
||||
sql: "SELECT JSON_ARRAY(1, 2, 3) AS array_value",
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
name: "json extract",
|
||||
sql: "SELECT JSON_EXTRACT(JSON_ARRAY(1, 2, 3), '$[0]') AS first_element;",
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
name: "json int array",
|
||||
sql: "SELECT JSON_ARRAY(3, 2, 1) AS int_array;",
|
||||
expected: []string{},
|
||||
},
|
||||
{
|
||||
name: "subquery",
|
||||
sql: "select * from (select * from people limit 1) AS subquery",
|
||||
expected: []string{"people"},
|
||||
},
|
||||
{
|
||||
name: "join",
|
||||
sql: `select * from A
|
||||
JOIN B ON A.name = B.name
|
||||
LIMIT 10`,
|
||||
expected: []string{"A", "B"},
|
||||
},
|
||||
{
|
||||
name: "right join",
|
||||
sql: `select * from A
|
||||
RIGHT JOIN B ON A.name = B.name
|
||||
LIMIT 10`,
|
||||
expected: []string{"A", "B"},
|
||||
},
|
||||
{
|
||||
name: "alias with join",
|
||||
sql: `select * from A as X
|
||||
RIGHT JOIN B ON A.name = X.name
|
||||
LIMIT 10`,
|
||||
expected: []string{"A", "B"},
|
||||
},
|
||||
{
|
||||
name: "alias",
|
||||
sql: "select * from A as X LIMIT 10",
|
||||
expected: []string{"A"},
|
||||
},
|
||||
{
|
||||
name: "error case",
|
||||
sql: "select * from zzz aaa zzz",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "parens",
|
||||
sql: `SELECT t1.Col1,
|
||||
t2.Col1,
|
||||
t3.Col1
|
||||
FROM table1 AS t1
|
||||
LEFT JOIN (
|
||||
table2 AS t2
|
||||
INNER JOIN table3 AS t3 ON t3.Col1 = t2.Col1
|
||||
) ON t2.Col1 = t1.Col1;`,
|
||||
expected: []string{"table1", "table2", "table3"},
|
||||
},
|
||||
{
|
||||
name: "with clause",
|
||||
sql: `WITH top_products AS (
|
||||
SELECT * FROM products
|
||||
ORDER BY price DESC
|
||||
LIMIT 5
|
||||
)
|
||||
SELECT name, price
|
||||
FROM top_products;`,
|
||||
expected: []string{"products", "top_products"},
|
||||
},
|
||||
{
|
||||
name: "with quote",
|
||||
sql: "select *,'junk' from foo",
|
||||
expected: []string{"foo"},
|
||||
},
|
||||
{
|
||||
name: "with quote 2",
|
||||
sql: "SELECT json_serialize_sql('SELECT 1')",
|
||||
expected: []string{},
|
||||
},
|
||||
}
|
||||
|
||||
assert.Equal(t, "foo", tables[0])
|
||||
}
|
||||
|
||||
func TestParseWithComma(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := "select * from foo,bar"
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "bar", tables[0])
|
||||
assert.Equal(t, "foo", tables[1])
|
||||
}
|
||||
|
||||
func TestParseWithCommas(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := "select * from foo,bar,baz"
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "bar", tables[0])
|
||||
assert.Equal(t, "baz", tables[1])
|
||||
assert.Equal(t, "foo", tables[2])
|
||||
}
|
||||
|
||||
func TestArray(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := "SELECT array_value(1, 2, 3)"
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 0, len(tables))
|
||||
}
|
||||
|
||||
func TestArray2(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := "SELECT array_value(1, 2, 3)[2]"
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 0, len(tables))
|
||||
}
|
||||
|
||||
func TestXxx(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := "SELECT [3, 2, 1]::INT[3];"
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 0, len(tables))
|
||||
}
|
||||
|
||||
func TestParseSubquery(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := "select * from (select * from people limit 1)"
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 1, len(tables))
|
||||
assert.Equal(t, "people", tables[0])
|
||||
}
|
||||
|
||||
func TestJoin(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := `select * from A
|
||||
JOIN B ON A.name = B.name
|
||||
LIMIT 10`
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 2, len(tables))
|
||||
assert.Equal(t, "A", tables[0])
|
||||
assert.Equal(t, "B", tables[1])
|
||||
}
|
||||
|
||||
func TestRightJoin(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := `select * from A
|
||||
RIGHT JOIN B ON A.name = B.name
|
||||
LIMIT 10`
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 2, len(tables))
|
||||
assert.Equal(t, "A", tables[0])
|
||||
assert.Equal(t, "B", tables[1])
|
||||
}
|
||||
|
||||
func TestAliasWithJoin(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := `select * from A as X
|
||||
RIGHT JOIN B ON A.name = X.name
|
||||
LIMIT 10`
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 2, len(tables))
|
||||
assert.Equal(t, "A", tables[0])
|
||||
assert.Equal(t, "B", tables[1])
|
||||
}
|
||||
|
||||
func TestAlias(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := `select * from A as X LIMIT 10`
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 1, len(tables))
|
||||
assert.Equal(t, "A", tables[0])
|
||||
}
|
||||
|
||||
func TestError(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := `select * from zzz aaa zzz`
|
||||
_, err := TablesList((sql))
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestParens(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := `SELECT t1.Col1,
|
||||
t2.Col1,
|
||||
t3.Col1
|
||||
FROM table1 AS t1
|
||||
LEFT JOIN (
|
||||
table2 AS t2
|
||||
INNER JOIN table3 AS t3 ON t3.Col1 = t2.Col1
|
||||
) ON t2.Col1 = t1.Col1;`
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 3, len(tables))
|
||||
assert.Equal(t, "table1", tables[0])
|
||||
assert.Equal(t, "table2", tables[1])
|
||||
assert.Equal(t, "table3", tables[2])
|
||||
}
|
||||
|
||||
func TestWith(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := `WITH
|
||||
|
||||
current_month AS (
|
||||
select
|
||||
distinct "Month(ISO)" as mth
|
||||
from A
|
||||
ORDER BY mth DESC
|
||||
LIMIT 1
|
||||
),
|
||||
|
||||
last_month_bill AS (
|
||||
select
|
||||
CAST (
|
||||
sum(
|
||||
CAST(BillableSeries AS INTEGER)
|
||||
) AS INTEGER
|
||||
) AS BillableSeries,
|
||||
"Month(ISO)",
|
||||
label_namespace
|
||||
-- , B.activeseries_count
|
||||
from A
|
||||
JOIN current_month
|
||||
ON current_month.mth = A."Month(ISO)"
|
||||
JOIN B
|
||||
ON B.namespace = A.label_namespace
|
||||
GROUP BY
|
||||
label_namespace,
|
||||
"Month(ISO)"
|
||||
ORDER BY BillableSeries DESC
|
||||
)
|
||||
|
||||
SELECT
|
||||
last_month_bill.*,
|
||||
BEE.activeseries_count
|
||||
FROM last_month_bill
|
||||
JOIN BEE
|
||||
ON BEE.namespace = last_month_bill.label_namespace`
|
||||
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 5, len(tables))
|
||||
assert.Equal(t, "A", tables[0])
|
||||
assert.Equal(t, "B", tables[1])
|
||||
assert.Equal(t, "BEE", tables[2])
|
||||
}
|
||||
|
||||
func TestWithQuote(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := "select *,'junk' from foo"
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, "foo", tables[0])
|
||||
}
|
||||
|
||||
func TestWithQuote2(t *testing.T) {
|
||||
t.Skip()
|
||||
sql := "SELECT json_serialize_sql('SELECT 1')"
|
||||
tables, err := TablesList((sql))
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 0, len(tables))
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
tables, err := TablesList(tc.sql)
|
||||
if tc.expectError {
|
||||
require.NotNil(t, err, "expected error for SQL: %s", tc.sql)
|
||||
} else {
|
||||
require.Nil(t, err, "unexpected error for SQL: %s", tc.sql)
|
||||
require.Equal(t, tc.expected, tables, "mismatched tables for SQL: %s", tc.sql)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user