Skip to content

Commit

Permalink
Add more tests on query
Browse files Browse the repository at this point in the history
  • Loading branch information
rnixik committed Jul 17, 2018
1 parent 1fe3b8a commit 678d88a
Show file tree
Hide file tree
Showing 4 changed files with 262 additions and 76 deletions.
25 changes: 8 additions & 17 deletions query.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"database/sql"
"fmt"
"github.com/jmoiron/sqlx"
"log"
"strings"
)

Expand Down Expand Up @@ -53,20 +52,20 @@ type dbConnector func(conset *ConnectionSettings) (db *sqlx.DB, err error)
func (q *Query) QueryResult(dbConnect dbConnector, conset *ConnectionSettings, writer DataWriter) (err error) {
db, err := dbConnect(conset)
if err != nil {
log.Fatal(err)
return err
}

var query string
for i, qt := range q.tables {
if i == 0 {
query, err = q.toSqlForSingleTable(qt)
query = q.toSqlForSingleTable(qt)
} else {
query, err = q.toSqlForRelation(qt)
}
if err != nil {
return
}
fmt.Println(query)
//fmt.Println(query)
resultsMaps, err := dbSelect(db, query, q.primaryInterval[0], q.primaryInterval[1])
if err != nil {
return err
Expand Down Expand Up @@ -100,11 +99,11 @@ func dbSelect(db *sqlx.DB, query string, args ...interface{}) (resultsMaps []*ma
return resultsMaps, nil
}

func (q *Query) toSqlForSingleTable(qt *QueryTable) (str string, err error) {
func (q *Query) toSqlForSingleTable(qt *QueryTable) (str string) {
str = "SELECT " + qt.sqlPartForSelectColumns() + "\n"
str += "FROM " + sqlTable(qt.name) + "\n"
str += "WHERE " + sqlTableAndColumn(qt.name, qt.columns[0]) + " BETWEEN ? AND ?"
return str, nil
return str
}

func (q *Query) toSqlForRelation(qt *QueryTable) (str string, err error) {
Expand All @@ -129,9 +128,10 @@ func (q *Query) toDDL(db *sqlx.DB) (ddl string, err error) {
if err != nil {
return "", err
}
fmt.Printf("%s\n", tableDDL)
//fmt.Printf("%s\n", tableDDL)
ddl += tableDDL
}
return "", nil
return ddl, nil
}

func getTableDescription(db *sqlx.DB, tableName string) (tableDescribtion []TableColumnDDL, err error) {
Expand Down Expand Up @@ -294,12 +294,3 @@ func findRelation(relations []*QueryRelation, tableName string, tableColumn stri
}
return
}

func contains(haystack []string, needle string) bool {
for _, a := range haystack {
if a == needle {
return true
}
}
return false
}
272 changes: 213 additions & 59 deletions query_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"database/sql"
"fmt"
"github.com/jmoiron/sqlx"
"gopkg.in/DATA-DOG/go-sqlmock.v1"
Expand All @@ -21,6 +22,13 @@ var typicalQuery = &Query{
primaryInterval: []int64{1000, 2000},
}

type EmptyWriter struct {
}

func (w *EmptyWriter) Write(_ []*map[string]interface{}) (err error) {
return nil
}

func TestQueryResult(t *testing.T) {
mockDB, mock, err := sqlmock.New()
if err != nil {
Expand Down Expand Up @@ -60,13 +68,69 @@ func TestQueryResult(t *testing.T) {
sqlmock.NewRows([]string{"Field", "Type", "Null", "Key", "Default", "Extra"}).AddRow("station_id", "bigint(20)", "NO", "PRI", nil, ""),
)

err = typicalQuery.QueryResult(dbConnectMock, &ConnectionSettings{}, &SimpleWriter{})
err = typicalQuery.QueryResult(dbConnectMock, &ConnectionSettings{}, &EmptyWriter{})
if err != nil {
t.Errorf("Unexpected error: %s", err)
return
}
}

func TestQueryResultConnectionError(t *testing.T) {
dbConnect := func(conset *ConnectionSettings) (db *sqlx.DB, err error) {
return nil, fmt.Errorf("Some DB error")
}
err := typicalQuery.QueryResult(dbConnect, &ConnectionSettings{}, &SimpleWriter{})
if err == nil {
t.Errorf("Expected error, but got nil")
return
}
}

func TestQueryResultQueryError(t *testing.T) {
mockDB, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
defer mockDB.Close()
sqlxDB := sqlx.NewDb(mockDB, "sqlmock")

dbConnectMock := func(conset *ConnectionSettings) (db *sqlx.DB, err error) {
return sqlxDB, nil
}

mock.ExpectQuery("SELECT (.+) FROM `routes` WHERE `routes`.`id` BETWEEN \\? AND \\?").
WithArgs(1000, 2000).
WillReturnError(fmt.Errorf("Some error"))

err = typicalQuery.QueryResult(dbConnectMock, &ConnectionSettings{}, &EmptyWriter{})
if err == nil {
t.Errorf("Expected error, but got nil")
return
}
}

func TestQueryResultDDLError(t *testing.T) {
mockDB, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("an error '%s' was not expected when opening a stub database connection", err)
}
defer mockDB.Close()
sqlxDB := sqlx.NewDb(mockDB, "sqlmock")

dbConnectMock := func(conset *ConnectionSettings) (db *sqlx.DB, err error) {
return sqlxDB, nil
}

mock.ExpectQuery("DESCRIBE `routes`").
WillReturnError(fmt.Errorf("Some error"))

err = typicalQuery.QueryResult(dbConnectMock, &ConnectionSettings{}, &EmptyWriter{})
if err == nil {
t.Errorf("Expected error, but got nil")
return
}
}

func TestDbSelect(t *testing.T) {
mockDB, mock, err := sqlmock.New()
if err != nil {
Expand Down Expand Up @@ -98,7 +162,8 @@ func TestDbSelect(t *testing.T) {
}

mock.ExpectQuery("SELECT (.+) FROM some_table WHERE id BETWEEN \\? AND \\?").
WithArgs(10, 20).WillReturnError(fmt.Errorf("Some error"))
WithArgs(10, 20).
WillReturnError(fmt.Errorf("Some error"))

_, err = dbSelect(sqlxDB, "SELECT id, name FROM some_table WHERE id BETWEEN ? AND ?", 10, 20)
if err == nil {
Expand All @@ -107,6 +172,146 @@ func TestDbSelect(t *testing.T) {
}
}

func TestToSqlForSingleTable(t *testing.T) {
sql := typicalQuery.toSqlForSingleTable(typicalQuery.tables[0])
expected := "SELECT `routes`.`id`, `routes`.`name`\n" +
"FROM `routes`\n" +
"WHERE `routes`.`id` BETWEEN ? AND ?"
if sql != expected {
t.Errorf("EXP:\n%s\nGOT:\n%s\n", expected, sql)
}
}

func TestToSqlForRelation(t *testing.T) {
sql, _ := typicalQuery.toSqlForRelation(typicalQuery.tables[1])
expected := "SELECT `stations`.`id`, `stations`.`sname`\n" +
"FROM `stations`\n" +
"WHERE `stations`.`id` IN\n" +
"(\n" +
"SELECT `stations_for_routes`.`station_id`\n" +
"FROM `routes`, `stations_for_routes`\n" +
"WHERE (`routes`.`id` BETWEEN ? AND ?) AND (`routes`.`id` = `stations_for_routes`.`route_id`)\n" +
")"
if sql != expected {
t.Errorf("EXP:\n%s\nGOT:\n%s\n", expected, sql)
}

sql2, err := typicalQuery.toSqlForRelation(typicalQuery.tables[0])
if err == nil {
t.Errorf("Expected error, but got query: %s", sql2)
}
}

func TestToDDLError(t *testing.T) {
mockDB, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("An error '%s' was not expected when opening a stub database connection", err)
}
defer mockDB.Close()
sqlxDB := sqlx.NewDb(mockDB, "sqlmock")

mock.ExpectQuery("DESCRIBE `routes`").
WillReturnError(fmt.Errorf("Some error"))

_, err = typicalQuery.toDDL(sqlxDB)
if err == nil {
t.Errorf("Expected error, but got nil")
return
}
}

func TestToDDLError2(t *testing.T) {
mockDB, mock, err := sqlmock.New()
if err != nil {
t.Fatalf("An error '%s' was not expected when opening a stub database connection", err)
}
defer mockDB.Close()
sqlxDB := sqlx.NewDb(mockDB, "sqlmock")

mock.ExpectQuery("DESCRIBE `routes`").
WillReturnRows(
sqlmock.NewRows([]string{"Field", "Type", "Null", "Key", "Default", "Extra"}).AddRow("OTHER_FIELD", "bigint(20)", "NO", "PRI", nil, ""),
)

_, err = typicalQuery.toDDL(sqlxDB)
if err == nil {
t.Errorf("Expected error, but got nil")
return
}
}

func TestMakeDDLFromTableDescriptionError(t *testing.T) {
_, err := makeDDLFromTableDescription("", []TableColumnDDL{}, []string{}, []*QueryRelation{})
if err == nil {
t.Errorf("Expected error, but got nil")
return
}
}

func TestMakeDDLFromTableDescription(t *testing.T) {
tableDescribtion := []TableColumnDDL{
TableColumnDDL{"id", "bigint(20)", "NO", "PRI", sql.NullString{"", false}, ""},
TableColumnDDL{"id2", "bigint(20)", "YES", "MUL", sql.NullString{"", true}, ""},
TableColumnDDL{"id3", "bigint(20)", "YES", "UNI", sql.NullString{"0", true}, ""},
TableColumnDDL{"id4", "varchar(255)", "YES", "PRI", sql.NullString{"", false}, ""},
}

relations := []*QueryRelation{
&QueryRelation{"some_table", "id2", "other_table", "id"},
}

ddl, err := makeDDLFromTableDescription("some_table", tableDescribtion, []string{"id", "id2", "id3", "no"}, relations)
if err != nil {
t.Errorf("Unexpected error: %s", err)
return
}
expectedDDL := "CREATE TABLE `some_table` (\n" +
" `id` bigint(20) NOT NULL,\n" +
" `id2` bigint(20) NULL DEFAULT '',\n" +
" `id3` bigint(20) NULL DEFAULT '0',\n" +
" PRIMARY KEY (`id`),\n" +
" INDEX `id2` (`id2`),\n" +
" UNIQUE INDEX `id3` (`id3`),\n" +
" CONSTRAINT `id2` FOREIGN KEY (`id`) REFERENCES `other_table` (`id`) ON DELETE CASCADE\n" +
");"
if ddl != expectedDDL {
t.Errorf("Expected DDL\n%s\nGOT:\n%s\n", expectedDDL, ddl)
return
}
}

func TestTqlPartForSelectColumns(t *testing.T) {
sql := typicalQuery.tables[0].sqlPartForSelectColumns()
expected := "`routes`.`id`, `routes`.`name`"
if sql != expected {
t.Errorf("EXPECTED '%s' GOT '%s'", expected, sql)
}
}

func TestSqlTable(t *testing.T) {
sql := sqlTable("some_table")
expected := "`some_table`"
if sql != expected {
t.Errorf("EXPECTED '%s' GOT '%s'", expected, sql)
}
}

func TestSqlColumn(t *testing.T) {
sql := sqlColumn("some_column")
expected := "`some_column`"
if sql != expected {
t.Errorf("EXPECTED '%s' GOT '%s'", expected, sql)
}
}

func TestSqlTableAndColumn(t *testing.T) {
sql := sqlTableAndColumn("some_table", "some_column")
expected := "`some_table`.`some_column`"
if sql != expected {
t.Errorf("EXPECTED '%s' GOT '%s'", expected, sql)
}
}

type testToSqlSubQueryForRelationInput struct {
query *Query
mainTable *QueryTable
Expand Down Expand Up @@ -183,64 +388,13 @@ func convertQueryToString(q *Query) string {
)
}

func TestSqlTable(t *testing.T) {
sql := sqlTable("some_table")
expected := "`some_table`"
if sql != expected {
t.Errorf("EXPECTED '%s' GOT '%s'", expected, sql)
}
}

func TestSqlColumn(t *testing.T) {
sql := sqlColumn("some_column")
expected := "`some_column`"
if sql != expected {
t.Errorf("EXPECTED '%s' GOT '%s'", expected, sql)
}
}

func TestSqlTableAndColumn(t *testing.T) {
sql := sqlTableAndColumn("some_table", "some_column")
expected := "`some_table`.`some_column`"
if sql != expected {
t.Errorf("EXPECTED '%s' GOT '%s'", expected, sql)
}
}

func TestTqlPartForSelectColumns(t *testing.T) {
sql := typicalQuery.tables[0].sqlPartForSelectColumns()
expected := "`routes`.`id`, `routes`.`name`"
if sql != expected {
t.Errorf("EXPECTED '%s' GOT '%s'", expected, sql)
}
}

func TestToSqlForRelation(t *testing.T) {
sql, _ := typicalQuery.toSqlForRelation(typicalQuery.tables[1])
expected := "SELECT `stations`.`id`, `stations`.`sname`\n" +
"FROM `stations`\n" +
"WHERE `stations`.`id` IN\n" +
"(\n" +
"SELECT `stations_for_routes`.`station_id`\n" +
"FROM `routes`, `stations_for_routes`\n" +
"WHERE (`routes`.`id` BETWEEN ? AND ?) AND (`routes`.`id` = `stations_for_routes`.`route_id`)\n" +
")"
if sql != expected {
t.Errorf("EXP:\n%s\nGOT:\n%s\n", expected, sql)
func TestFindRelationError(t *testing.T) {
relations := []*QueryRelation{
&QueryRelation{"some_table", "id2", "other_table", "id"},
}

sql2, err := typicalQuery.toSqlForRelation(typicalQuery.tables[0])
_, _, err := findRelation(relations, "other_table", "other_column")
if err == nil {
t.Errorf("Expected error, but got query: %s", sql2)
}
}

func TestToSqlForSingleTable(t *testing.T) {
sql, _ := typicalQuery.toSqlForSingleTable(typicalQuery.tables[0])
expected := "SELECT `routes`.`id`, `routes`.`name`\n" +
"FROM `routes`\n" +
"WHERE `routes`.`id` BETWEEN ? AND ?"
if sql != expected {
t.Errorf("EXP:\n%s\nGOT:\n%s\n", expected, sql)
t.Errorf("Expected error, but got nil")
return
}
}
Loading

0 comments on commit 678d88a

Please sign in to comment.