325 lines
10 KiB
Go
325 lines
10 KiB
Go
package q
|
|
|
|
import (
|
|
"fmt"
|
|
"testing"
|
|
)
|
|
|
|
type ParsingTest struct {
|
|
input string
|
|
expected Query
|
|
}
|
|
|
|
func TestParseSelectStatement_StateMachine(t *testing.T) {
|
|
var testSqlStatements = []ParsingTest{
|
|
{
|
|
input: "SELECT * FROM users WHERE age >= 30",
|
|
expected: &Select{
|
|
Type: SELECT,
|
|
Table: Table{Name: "users"},
|
|
IsWildcard: true,
|
|
Conditionals: []Conditional{
|
|
{
|
|
Key: "age",
|
|
Operator: ">=",
|
|
Value: "30",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
input: "SELECT CustomerName, City FROM Customers",
|
|
expected: &Select{
|
|
Type: SELECT,
|
|
Table: Table{Name: "Customers"},
|
|
IsWildcard: false,
|
|
Columns: []Column{
|
|
{
|
|
Name: "CustomerName",
|
|
},
|
|
{
|
|
Name: "City",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
input: "SELECT CustomerName AS Customer, City AS town FROM Customers AS People",
|
|
expected: &Select{
|
|
Type: SELECT,
|
|
Table: Table{Name: "Customers", Alias: "People"},
|
|
IsWildcard: false,
|
|
Columns: []Column{
|
|
{
|
|
Name: "CustomerName",
|
|
Alias: "Customer",
|
|
},
|
|
{
|
|
Name: "City",
|
|
Alias: "town",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
input: "SELECT * FROM Orders ORDER BY StreetNumber, CountryCode;",
|
|
expected: &Select{
|
|
Type: SELECT,
|
|
Table: Table{Name: "Orders"},
|
|
IsWildcard: true,
|
|
OrderBys: []OrderBy{
|
|
{
|
|
Key: "StreetNumber",
|
|
},
|
|
{
|
|
Key: "CountryCode",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
input: "SELECT * FROM ZipCodes ORDER BY Code ASC, StateName DESC",
|
|
expected: &Select{
|
|
Type: SELECT,
|
|
Table: Table{Name: "ZipCodes"},
|
|
IsWildcard: true,
|
|
OrderBys: []OrderBy{
|
|
{
|
|
Key: "Code",
|
|
IsDescend: false,
|
|
},
|
|
{
|
|
Key: "StateName",
|
|
IsDescend: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
input: "SELECT id, streetNumber AS streetNum, streetName, city, state FROM Addresses WHERE state = 'AL' AND zip > 9000 OR zip <= 12000 ORDER BY zip DESC, streetNumber",
|
|
expected: &Select{
|
|
Type: SELECT,
|
|
Table: Table{Name: "Addresses"},
|
|
IsWildcard: false,
|
|
Columns: []Column{
|
|
{
|
|
Name: "id",
|
|
},
|
|
{
|
|
Name: "streetNumber",
|
|
Alias: "streetNum",
|
|
},
|
|
{
|
|
Name: "streetName",
|
|
},
|
|
{
|
|
Name: "city",
|
|
},
|
|
{
|
|
Name: "state",
|
|
},
|
|
},
|
|
Conditionals: []Conditional{
|
|
{
|
|
Key: "state",
|
|
Operator: "=",
|
|
Value: "'AL'",
|
|
},
|
|
{
|
|
Key: "zip",
|
|
Operator: ">",
|
|
Value: "9000",
|
|
Extension: "AND",
|
|
},
|
|
{
|
|
Key: "zip",
|
|
Operator: "<=",
|
|
Value: "12000",
|
|
Extension: "OR",
|
|
},
|
|
},
|
|
OrderBys: []OrderBy{
|
|
{
|
|
Key: "zip",
|
|
IsDescend: true,
|
|
},
|
|
{
|
|
Key: "streetNumber",
|
|
IsDescend: false,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
input: "SELECT ProductID, ProductName, CategoryName FROM Products INNER JOIN Categories ON Products.CategoryID = Categories.CategoryID AND Products.SupplierID = Categories.SupplierID LEFT JOIN Stores ON Products.StoreID = Stores.ID ;",
|
|
expected: &Select{
|
|
Type: SELECT,
|
|
Table: Table{Name: "Products"},
|
|
Columns: []Column{
|
|
{Name: "ProductID"},
|
|
{Name: "ProductName"},
|
|
{Name: "CategoryName"},
|
|
},
|
|
Joins: []Join{
|
|
{
|
|
Type: INNER,
|
|
MainTable: Table{
|
|
Name: "Products",
|
|
},
|
|
JoiningTable: Table{
|
|
Name: "Categories",
|
|
},
|
|
Ons: []Conditional{
|
|
{
|
|
Key: "Products.CategoryID",
|
|
Operator: "=",
|
|
Value: "Categories.CategoryID",
|
|
},
|
|
{
|
|
Key: "Products.SupplierID",
|
|
Operator: "=",
|
|
Value: "Categories.SupplierID",
|
|
Extension: "AND",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
Type: LEFT,
|
|
MainTable: Table{
|
|
Name: "Products",
|
|
},
|
|
JoiningTable: Table{
|
|
Name: "Stores",
|
|
},
|
|
Ons: []Conditional{
|
|
{
|
|
Key: "Products.StoreID",
|
|
Operator: "=",
|
|
Value: "Stores.ID",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, sql := range testSqlStatements {
|
|
testName := fmt.Sprintf("%s", sql.input)
|
|
expected := sql.expected.(*Select)
|
|
|
|
t.Run(testName, func(t *testing.T) {
|
|
answer, err := Parse(sql.input)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
answerAsSelect := answer.(*Select)
|
|
|
|
if answerAsSelect.Type != expected.Type {
|
|
t.Errorf("got %d for Select.Type, expected %d", answerAsSelect.Type, expected.Type)
|
|
}
|
|
if answerAsSelect.IsWildcard != expected.IsWildcard {
|
|
t.Errorf("got %#v for Select.IsWildcard, expected %#v", answerAsSelect.IsWildcard, expected.IsWildcard)
|
|
}
|
|
if answerAsSelect.Table.Name != expected.Table.Name {
|
|
t.Errorf("got %s for Select.Table.Name, expected %s", answerAsSelect.Table.Name, expected.Table.Name)
|
|
}
|
|
if answerAsSelect.Table.Alias != expected.Table.Alias {
|
|
t.Errorf("got %s for Select.Table.Alias, expected %s", answerAsSelect.Table.Alias, expected.Table.Alias)
|
|
}
|
|
|
|
if len(answerAsSelect.Columns) != len(expected.Columns) {
|
|
t.Errorf("got %d number of columns for Select.Columns, expected %d", len(answerAsSelect.Columns), len(expected.Columns))
|
|
} else {
|
|
for i, expectedColumn := range expected.Columns {
|
|
if expectedColumn.Name != answerAsSelect.Columns[i].Name {
|
|
t.Errorf("got %s for Select.Column[%d].Name, expected %s", answerAsSelect.Columns[i].Name, i, expectedColumn.Name)
|
|
}
|
|
if expectedColumn.Alias != answerAsSelect.Columns[i].Alias {
|
|
t.Errorf("got %s for Select.Column[%d].Alias, expected %s", answerAsSelect.Columns[i].Alias, i, expectedColumn.Alias)
|
|
}
|
|
if expectedColumn.AggregateFunction != answerAsSelect.Columns[i].AggregateFunction {
|
|
t.Errorf("got %d for Select.Column[%d].AggregateFunction, expected %d", answerAsSelect.Columns[i].AggregateFunction, i, expectedColumn.AggregateFunction)
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(answerAsSelect.Conditionals) != len(expected.Conditionals) {
|
|
t.Errorf("got %d number of conditionals for Select.Conditionals, expected %d", len(answerAsSelect.Conditionals), len(expected.Conditionals))
|
|
} else {
|
|
for i, expectedCondition := range expected.Conditionals {
|
|
if expectedCondition.Key != answerAsSelect.Conditionals[i].Key {
|
|
t.Errorf("got %s for Select.Conditionals[%d].Key, expected %s", answerAsSelect.Conditionals[i].Key, i, expectedCondition.Key)
|
|
}
|
|
if expectedCondition.Operator != answerAsSelect.Conditionals[i].Operator {
|
|
t.Errorf("got %s for Select.Conditionals[%d].Operator, expected %s", answerAsSelect.Conditionals[i].Operator, i, expectedCondition.Operator)
|
|
}
|
|
if expectedCondition.Value != answerAsSelect.Conditionals[i].Value {
|
|
t.Errorf("got %s for Select.Conditionals[%d].Value, expected %s", answerAsSelect.Conditionals[i].Value, i, expectedCondition.Value)
|
|
}
|
|
if expectedCondition.Extension != answerAsSelect.Conditionals[i].Extension {
|
|
t.Errorf("got %s for Select.Conditionals[%d].Extension, expected %s", answerAsSelect.Conditionals[i].Extension, i, expectedCondition.Extension)
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(answerAsSelect.OrderBys) != len(expected.OrderBys) {
|
|
t.Errorf("got %d number of orderBys for Select.OrderBys, expected %d", len(answerAsSelect.OrderBys), len(expected.OrderBys))
|
|
} else {
|
|
for i, expectedOrderBy := range expected.OrderBys {
|
|
if expectedOrderBy.Key != answerAsSelect.OrderBys[i].Key {
|
|
t.Errorf("got %s for Select.OrderBys[%d].Key, expected %s", answerAsSelect.OrderBys[i].Key, i, expectedOrderBy.Key)
|
|
}
|
|
if expectedOrderBy.IsDescend != answerAsSelect.OrderBys[i].IsDescend {
|
|
t.Errorf("got %#v for Select.OrderBys[%d].IsDescend, expected %#v", answerAsSelect.OrderBys[i].IsDescend, i, expectedOrderBy.IsDescend)
|
|
}
|
|
}
|
|
}
|
|
|
|
if len(answerAsSelect.Joins) != len(expected.Joins) {
|
|
t.Errorf("got %d number of joins for Select.Joinss, expected %d", len(answerAsSelect.Joins), len(expected.Joins))
|
|
} else {
|
|
for i, expectedJoin := range expected.Joins {
|
|
if answerAsSelect.Joins[i].Type != expectedJoin.Type {
|
|
t.Errorf("got %d for Select.Joins[%d].Type, expected %d", answerAsSelect.Joins[i].Type, i, expectedJoin.Type)
|
|
}
|
|
if answerAsSelect.Joins[i].MainTable.Name != expectedJoin.MainTable.Name {
|
|
t.Errorf("got %s for Select.Joins[%d].MainTable.Name, expected %s", answerAsSelect.Joins[i].MainTable.Name, i, expectedJoin.MainTable.Name)
|
|
}
|
|
if answerAsSelect.Joins[i].MainTable.Alias != expectedJoin.MainTable.Alias {
|
|
t.Errorf("got %s for Select.Joins[%d].MainTable.Alias, expected %s", answerAsSelect.Joins[i].MainTable.Alias, i, expectedJoin.MainTable.Alias)
|
|
}
|
|
if answerAsSelect.Joins[i].JoiningTable.Name != expectedJoin.JoiningTable.Name {
|
|
t.Errorf("got %s for Select.Joins[%d].JoiningTable.Name, expected %s", answerAsSelect.Joins[i].JoiningTable.Name, i, expectedJoin.JoiningTable.Name)
|
|
}
|
|
if answerAsSelect.Joins[i].JoiningTable.Alias != expectedJoin.JoiningTable.Alias {
|
|
t.Errorf("got %s for Select.Joins[%d].JoiningTable.Alias, expected %s", answerAsSelect.Joins[i].JoiningTable.Alias, i, expectedJoin.JoiningTable.Alias)
|
|
}
|
|
|
|
if len(answerAsSelect.Joins[i].Ons) != len(expectedJoin.Ons) {
|
|
t.Errorf("got %d number of ons for Select.Joins.Ons, expected %d", len(answerAsSelect.Joins[i].Ons), len(expectedJoin.Ons))
|
|
} else {
|
|
for on_i, expectedCondition := range expected.Joins[i].Ons {
|
|
if expectedCondition.Key != answerAsSelect.Joins[i].Ons[on_i].Key {
|
|
t.Errorf("got %s for Select.Conditionals[%d].Key, expected %s", answerAsSelect.Joins[i].Ons[on_i].Key, on_i, expectedCondition.Key)
|
|
}
|
|
if expectedCondition.Operator != answerAsSelect.Joins[i].Ons[on_i].Operator {
|
|
t.Errorf("got %s for Select.Conditionals[%d].Operator, expected %s", answerAsSelect.Joins[i].Ons[on_i].Operator, on_i, expectedCondition.Operator)
|
|
}
|
|
if expectedCondition.Value != answerAsSelect.Joins[i].Ons[on_i].Value {
|
|
t.Errorf("got %s for Select.Conditionals[%d].Value, expected %s", answerAsSelect.Joins[i].Ons[on_i].Value, on_i, expectedCondition.Value)
|
|
}
|
|
if expectedCondition.Extension != answerAsSelect.Joins[i].Ons[on_i].Extension {
|
|
t.Errorf("got %s for Select.Conditionals[%d].Extension, expected %s", answerAsSelect.Joins[i].Ons[on_i].Extension, on_i, expectedCondition.Extension)
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|