Skip to content

Commit 1dfe3a9

Browse files
committed
tests: add SQL tests
Added SQL tests. Updated config.lua for creation the space for using SQL in tests. Added the check of Tarantool version to skip SQL tests if tarantool version < 2.0.0. Changed id of the test spaces with id=512 and id=514, cause if using SQL in tarantool there is no ability to set space id explicitly, so it gets created with id=512 by default and conflicts with already existing space with the same id. Added new dependency in go.sum, go.mod for using assert package. Added examples of using SQL queries in example_test.go for compiling the future documentation from sources. Follows up #62
1 parent 42fb875 commit 1dfe3a9

File tree

4 files changed

+671
-26
lines changed

4 files changed

+671
-26
lines changed

config.lua

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,25 @@ box.cfg{
66

77
box.once("init", function()
88
local s = box.schema.space.create('test', {
9-
id = 512,
9+
id = 517,
1010
if_not_exists = true,
1111
})
1212
s:create_index('primary', {type = 'tree', parts = {1, 'uint'}, if_not_exists = true})
1313

14+
local sp = box.schema.space.create('SQL_TEST', {
15+
id = 519,
16+
if_not_exists = true,
17+
format = {
18+
{name = "NAME0", type = "unsigned"},
19+
{name = "NAME1", type = "string"},
20+
{name = "NAME2", type = "string"},
21+
}
22+
})
23+
sp:create_index('primary', {type = 'tree', parts = {1, 'uint'}, if_not_exists = true})
24+
sp:insert{1, "test", "test"}
25+
1426
local st = box.schema.space.create('schematest', {
15-
id = 514,
27+
id = 516,
1628
temporary = true,
1729
if_not_exists = true,
1830
field_count = 7,
@@ -49,6 +61,10 @@ box.once("init", function()
4961
box.schema.user.grant('test', 'execute', 'universe')
5062
box.schema.user.grant('test', 'read,write', 'space', 'test')
5163
box.schema.user.grant('test', 'read,write', 'space', 'schematest')
64+
65+
-- grants for sql tests
66+
box.schema.user.grant('test', 'create,read,write,drop,alter', 'space')
67+
box.schema.user.grant('test', 'create', 'sequence')
5268
end)
5369

5470
local function func_name()

example_custom_unpacking_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func Example_customUnpacking() {
8787
log.Fatalf("Failed to connect: %s", err.Error())
8888
}
8989

90-
spaceNo := uint32(512)
90+
spaceNo := uint32(517)
9191
indexNo := uint32(0)
9292

9393
tuple := Tuple2{Cid: 777, Orig: "orig", Members: []Member{{"lol", "", 1}, {"wut", "", 3}}}

example_test.go

Lines changed: 137 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package tarantool_test
22

33
import (
44
"fmt"
5+
"github.com/tarantool/go-tarantool/test_helpers"
56
"time"
67

78
"github.com/tarantool/go-tarantool"
@@ -31,7 +32,8 @@ func ExampleConnection_Select() {
3132
conn.Replace(spaceNo, []interface{}{uint(1111), "hello", "world"})
3233
conn.Replace(spaceNo, []interface{}{uint(1112), "hallo", "werld"})
3334

34-
resp, err := conn.Select(512, 0, 0, 100, tarantool.IterEq, []interface{}{uint(1111)})
35+
resp, err := conn.Select(517, 0, 0, 100, tarantool.IterEq, []interface{}{uint(1111)})
36+
3537
if err != nil {
3638
fmt.Printf("error in select is %v", err)
3739
return
@@ -53,7 +55,9 @@ func ExampleConnection_SelectTyped() {
5355
conn := example_connect()
5456
defer conn.Close()
5557
var res []Tuple
56-
err := conn.SelectTyped(512, 0, 0, 100, tarantool.IterEq, tarantool.IntKey{1111}, &res)
58+
59+
err := conn.SelectTyped(517, 0, 0, 100, tarantool.IterEq, tarantool.IntKey{1111}, &res)
60+
5761
if err != nil {
5862
fmt.Printf("error in select is %v", err)
5963
return
@@ -73,6 +77,7 @@ func ExampleConnection_SelectTyped() {
7377
func ExampleConnection_SelectAsync() {
7478
conn := example_connect()
7579
defer conn.Close()
80+
spaceNo := uint32(517)
7681

7782
conn.Insert(spaceNo, []interface{}{uint(16), "test", "one"})
7883
conn.Insert(spaceNo, []interface{}{uint(17), "test", "one"})
@@ -320,12 +325,12 @@ func ExampleSchema() {
320325
}
321326

322327
space1 := schema.Spaces["test"]
323-
space2 := schema.SpacesById[514]
328+
space2 := schema.SpacesById[516]
324329
fmt.Printf("Space 1 ID %d %s\n", space1.Id, space1.Name)
325330
fmt.Printf("Space 2 ID %d %s\n", space2.Id, space2.Name)
326331
// Output:
327-
// Space 1 ID 512 test
328-
// Space 2 ID 514 schematest
332+
// Space 1 ID 517 test
333+
// Space 2 ID 516 schematest
329334
}
330335

331336
// Example demonstrates how to retrieve information with space schema.
@@ -344,7 +349,7 @@ func ExampleSpace() {
344349

345350
// Access Space objects by name or ID.
346351
space1 := schema.Spaces["test"]
347-
space2 := schema.SpacesById[514] // It's a map.
352+
space2 := schema.SpacesById[516] // It's a map.
348353
fmt.Printf("Space 1 ID %d %s %s\n", space1.Id, space1.Name, space1.Engine)
349354
fmt.Printf("Space 1 ID %d %t\n", space1.FieldsCount, space1.Temporary)
350355

@@ -365,10 +370,135 @@ func ExampleSpace() {
365370
fmt.Printf("SpaceField 2 %s %s\n", spaceField2.Name, spaceField2.Type)
366371

367372
// Output:
368-
// Space 1 ID 512 test memtx
373+
// Space 1 ID 517 test memtx
369374
// Space 1 ID 0 false
370375
// Index 0 primary
371376
// &{0 unsigned} &{2 string}
372377
// SpaceField 1 name0 unsigned
373378
// SpaceField 2 name3 unsigned
374379
}
380+
381+
// To use SQL to query a tarantool instance, call `Execute`.
382+
//
383+
// Pay attention that with different types of queries (DDL, DQL, DML etc.)
384+
// some fields of the response structure (`MetaData` and `InfoAutoincrementIds` in `SQLInfo`) may be nil.
385+
//
386+
// See the [protocol](https://www.tarantool.io/en/doc/latest/dev_guide/internals/box_protocol/#responses-for-sql)
387+
// explanation for details.
388+
func ExampleConnection_Execute() {
389+
// Tarantool supports SQL since version 2.0.0
390+
isLess, _ := test_helpers.IsTarantoolVersionLess(2, 0, 0)
391+
if isLess {
392+
return
393+
}
394+
server := "127.0.0.1:3013"
395+
opts := tarantool.Opts{
396+
Timeout: 500 * time.Millisecond,
397+
Reconnect: 1 * time.Second,
398+
MaxReconnects: 3,
399+
User: "test",
400+
Pass: "test",
401+
}
402+
client, err := tarantool.Connect(server, opts)
403+
if err != nil {
404+
fmt.Printf("Failed to connect: %s", err.Error())
405+
}
406+
407+
resp, err := client.Execute("CREATE TABLE SQL_TEST (id INTEGER PRIMARY KEY, name STRING)", []interface{}{})
408+
fmt.Println("Execute")
409+
fmt.Println("Error", err)
410+
fmt.Println("Code", resp.Code)
411+
fmt.Println("Data", resp.Data)
412+
fmt.Println("MetaData", resp.MetaData)
413+
fmt.Println("SQL Info", resp.SQLInfo)
414+
415+
// there are 4 options to pass named parameters to an SQL query
416+
// the simple map:
417+
sqlBind1 := map[string]interface{}{
418+
"id": 1,
419+
"name": "test",
420+
}
421+
422+
// any type of structure
423+
sqlBind2 := struct {
424+
Id int
425+
Name string
426+
}{1, "test"}
427+
428+
// it is possible to use []tarantool.KeyValueBind
429+
sqlBind3 := []interface{}{
430+
tarantool.KeyValueBind{Key: "id", Value: 1},
431+
tarantool.KeyValueBind{Key: "name", Value: "test"},
432+
}
433+
434+
// or []interface{} slice with tarantool.KeyValueBind items inside
435+
sqlBind4 := []tarantool.KeyValueBind{
436+
{"id", 1},
437+
{"name", "test"},
438+
}
439+
440+
// the next usage
441+
resp, err = client.Execute("SELECT id FROM SQL_TEST WHERE id=:id AND name=:name", sqlBind1)
442+
fmt.Println("Execute")
443+
fmt.Println("Error", err)
444+
fmt.Println("Code", resp.Code)
445+
fmt.Println("Data", resp.Data)
446+
fmt.Println("MetaData", resp.MetaData)
447+
fmt.Println("SQL Info", resp.SQLInfo)
448+
449+
// the same as
450+
resp, err = client.Execute("SELECT id FROM SQL_TEST WHERE id=:id AND name=:name", sqlBind2)
451+
fmt.Println("Execute")
452+
fmt.Println("Error", err)
453+
fmt.Println("Code", resp.Code)
454+
fmt.Println("Data", resp.Data)
455+
fmt.Println("MetaData", resp.MetaData)
456+
fmt.Println("SQL Info", resp.SQLInfo)
457+
458+
// the same as
459+
resp, err = client.Execute("SELECT id FROM SQL_TEST WHERE id=:id AND name=:name", sqlBind3)
460+
fmt.Println("Execute")
461+
fmt.Println("Error", err)
462+
fmt.Println("Code", resp.Code)
463+
fmt.Println("Data", resp.Data)
464+
fmt.Println("MetaData", resp.MetaData)
465+
fmt.Println("SQL Info", resp.SQLInfo)
466+
467+
// the same as
468+
resp, err = client.Execute("SELECT id FROM SQL_TEST WHERE id=:id AND name=:name", sqlBind4)
469+
fmt.Println("Execute")
470+
fmt.Println("Error", err)
471+
fmt.Println("Code", resp.Code)
472+
fmt.Println("Data", resp.Data)
473+
fmt.Println("MetaData", resp.MetaData)
474+
fmt.Println("SQL Info", resp.SQLInfo)
475+
476+
// the way to pass positional arguments to an SQL query
477+
resp, err = client.Execute("SELECT id FROM SQL_TEST WHERE id=? AND name=?", []interface{}{2, "test"})
478+
fmt.Println("Execute")
479+
fmt.Println("Error", err)
480+
fmt.Println("Code", resp.Code)
481+
fmt.Println("Data", resp.Data)
482+
fmt.Println("MetaData", resp.MetaData)
483+
fmt.Println("SQL Info", resp.SQLInfo)
484+
485+
// the way to pass SQL expression with using custom packing/unpacking for a type
486+
var res []Tuple
487+
sqlInfo, metaData, err := client.ExecuteTyped("SELECT id, name, name FROM SQL_TEST WHERE id=?", []interface{}{2}, &res)
488+
fmt.Println("ExecuteTyped")
489+
fmt.Println("Error", err)
490+
fmt.Println("Data", res)
491+
fmt.Println("MetaData", metaData)
492+
fmt.Println("SQL Info", sqlInfo)
493+
494+
// for using different types of parameters (positioned/named), collect all items in []interface{}
495+
// all "named" items must be passed with tarantool.KeyValueBind{}
496+
resp, err = client.Execute("SELECT id FROM SQL_TEST WHERE id=:id AND name=?",
497+
[]interface{}{tarantool.KeyValueBind{"id", 1}, "test"})
498+
fmt.Println("Execute")
499+
fmt.Println("Error", err)
500+
fmt.Println("Code", resp.Code)
501+
fmt.Println("Data", resp.Data)
502+
fmt.Println("MetaData", resp.MetaData)
503+
fmt.Println("SQL Info", resp.SQLInfo)
504+
}

0 commit comments

Comments
 (0)