vesoft-inc/nebula-go

ExecuteWithParameter 支持点插入吗?

minxinqing opened this issue · 3 comments

使用ExecuteWithParameter插入点, 报错。
代码如下:

guild_vid := "guild_11"
params := make(map[string]interface{})
params["p2"] = 111

nGql := fmt.Sprintf(`INSERT VERTEX guild (code) VALUES "%s":($p2);`, guild_vid)

resultSet, err := session.ExecuteWithParameter(nGql, params)

报错如下:

ErrorMsg: Storage Error: The data type does not meet the requirements. Use the correct type of data.

schame如下:

CREATE TAG IF NOT EXISTS guild (
	code int NOT NULL DEFAULT 0 COMMENT '',
	open_id int NOT NULL DEFAULT 0 COMMENT '',
	custom_id string NOT NULL DEFAULT '' COMMENT '',
	name string NOT NULL DEFAULT '' COMMENT '',
	status int NOT NULL DEFAULT 0 COMMENT ''
)
COMMENT = 'xxx';

Hi!
Found the similar problem when trying to INSERT VERTEX data into database.

I'm using docker nebula installation - everything is of v3.4.0
nebula-go is also v3.4.0

The example code to reproduce is the following:

package main

import (
	"fmt"
	"sync"

	nebulago "github.com/vesoft-inc/nebula-go/v3"
)

const (
	address = "127.0.0.1"
	// The default port of NebulaGraph 2.x is 9669.
	// 3699 is only for testing.
	port     = 9669
	username = "root"
	password = "nebula"
)

// Initialize logger
var log = nebulago.DefaultLogger{}

func main() {
	hostAddress := nebulago.HostAddress{Host: address, Port: port}
	hostList := []nebulago.HostAddress{hostAddress}
	// Create configs for connection pool using default values
	testPoolConfig := nebulago.GetDefaultConf()

	// Initialize connection pool
	pool, err := nebulago.NewConnectionPool(hostList, testPoolConfig, log)
	if err != nil {
		log.Fatal(fmt.Sprintf("Fail to initialize the connection pool, host: %s, port: %d, %s", address, port, err.Error()))
	}
	// Close all connections in the pool
	defer pool.Close()
	// Create session and send query in go routine
	var wg sync.WaitGroup
	wg.Add(1)
	go func(wg *sync.WaitGroup) {
		defer wg.Done()
		// Create session
		session, err := pool.GetSession(username, password)
		if err != nil {
			log.Fatal(fmt.Sprintf("Fail to create a new session from connection pool, username: %s, password: %s, %s",
				username, password, err.Error()))
		}
		// Release session and return connection back to connection pool
		defer session.Release()

		checkResultSet := func(prefix string, res *nebulago.ResultSet) {
			if !res.IsSucceed() {
				log.Fatal(fmt.Sprintf("%s, ErrorCode: %v, ErrorMsg: %s", prefix, res.GetErrorCode(), res.GetErrorMsg()))
			}
		}

		query := "CREATE SPACE IF NOT EXISTS topology(partition_num=5, replica_factor=1, vid_type=fixed_string(50)); USE topology; CREATE TAG IF NOT EXISTS TEST(testField string);"
		resultSet, err := session.Execute(query)
		if err != nil {
			fmt.Print(err.Error())
			return
		}
		checkResultSet(query, resultSet)

		params := make(map[string]interface{})
		params["p1"] = "hello"

		insertQuery := "INSERT VERTEX TEST(testField) VALUES 'test':($p1)"
		resultSet, err = session.ExecuteWithParameter(insertQuery, params)
		if err != nil {
			fmt.Print(err.Error())
			return
		}
		checkResultSet(insertQuery, resultSet)

	}(&wg)
	wg.Wait()

	fmt.Print("\n")
	log.Info("Nebula Go Parameter Example Finished")
}

I used https://github.com/vesoft-inc/nebula-go/blob/master/examples/parameter_example/parameter_example.go as a base for my example

So, I am creating space topology, afterwards creating simple tag CREATE TAG IF NOT EXISTS TEST(testField string);
And trying to INSERT data with the parametrised query: INSERT VERTEX TEST(testField) VALUES 'test':($p1)

As a result I receive the following error:

[FATAL] INSERT VERTEX TEST(testField) VALUES 'test':($p1), ErrorCode: -1005, ErrorMsg: Storage Error: The data type does not meet the requirements. Use the correct type of data.

Logs in graphd says the following:

E20230208 12:14:03.558832    19 StorageAccessExecutor.h:40] InsertVerticesExecutor failed, error E_DATA_TYPE_MISMATCH, part 2
E20230208 12:14:03.560662    19 QueryInstance.cpp:151] Storage Error: The data type does not meet the requirements. Use the correct type of data., query: INSERT VERTEX TEST(testField) VALUES 'test':($p1)

It seems that we can always create query as a concatenation of strings:

 query := "INSERT VERTEX TEST(testField) VALUES 'test':('" + "HELLO" + "')"

But this pattern makes the code really messy (especially when we have lots of parameters) and vulnerable to SQL Injections. Plus it slows the overall query performance, because we need to construct new query for every new portion of data (in context of using batching for queries), instead of doing it once and justing filling in values.

Appreciate any help!

@minxinqing @MeneTelk0 Thanks for finding this problem.
Fixed in vesoft-inc/nebula#5328.

这个 issue 超过一个月没有更新内容了,这边先行关闭了。如果你有任何更新的内容,可以再打开这个 issue 哈。

谢谢你的反馈 😊