Skip to content

Commit bda05d2

Browse files
authored
Support for namespaces in requests (on-premise only) (#20)
On-premise only: added support for default namespace in config and namespace in requests.
1 parent b5e831f commit bda05d2

File tree

7 files changed

+442
-25
lines changed

7 files changed

+442
-25
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
1212
with Instance Principals:
1313
* NewSignatureProviderWithInstancePrincipalDelegation
1414
* NewSignatureProviderWithInstancePrincipalDelegationFromFile
15+
- On-premise only: added support for default namespace in config and
16+
namespace in requests.
1517

1618
### Changed
1719
- Updated yaml.v2 to 2.4.0

internal/test/nosql_testsuite.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ func (suite *NoSQLTestSuite) GetNsTableName(ns, table string) string {
143143
}
144144

145145
// DropTable drops the table.
146-
func (suite *NoSQLTestSuite) DropTable(table string, dropIfExists bool) {
146+
func (suite *NoSQLTestSuite) DropTableWithNamespace(table string, dropIfExists bool, namespace string) {
147147
var stmt string
148148
if dropIfExists {
149149
stmt = "DROP TABLE IF EXISTS " + table
@@ -153,36 +153,61 @@ func (suite *NoSQLTestSuite) DropTable(table string, dropIfExists bool) {
153153

154154
req := &nosqldb.TableRequest{
155155
Statement: stmt,
156+
Namespace: namespace,
156157
}
157158

158159
// BUG(zehliu): DoTableRequestAndWait does not seem to work for MiniCloud.
159160
_, err := suite.Client.DoTableRequestAndWait(req, 30*time.Second, time.Second)
160161
suite.Require().NoErrorf(err, "%q: got error %v.", stmt, err)
161162
}
162163

164+
// DropTable drops the table.
165+
func (suite *NoSQLTestSuite) DropTable(table string, dropIfExists bool) {
166+
suite.DropTableWithNamespace(table, dropIfExists, "")
167+
}
168+
163169
// ExecuteDDL executes the specified DDL statement using a SystemRequest.
164170
func (suite *NoSQLTestSuite) ExecuteDDL(stmt string) {
165171
_, err := suite.Client.DoSystemRequestAndWait(stmt, 30*time.Second, time.Second)
166172
suite.Require().NoErrorf(err, "failed to execute %q, got error %v.", stmt, err)
167173
}
168174

169175
// ExecuteTableDDL executes the specified DDL statement using a TableRequest.
170-
func (suite *NoSQLTestSuite) ExecuteTableDDL(stmt string) {
171-
req := &nosqldb.TableRequest{Statement: stmt}
176+
func (suite *NoSQLTestSuite) ExecuteTableDDLWithNamespace(stmt string, namespace string) {
177+
req := &nosqldb.TableRequest{Statement: stmt, Namespace: namespace}
172178
_, err := suite.Client.DoTableRequestAndWait(req, 30*time.Second, time.Second)
173179
suite.Require().NoErrorf(err, "failed to execute %q, got error %v.", stmt, err)
174180
}
175181

182+
func (suite *NoSQLTestSuite) ExecuteTableDDL(stmt string) {
183+
suite.ExecuteTableDDLWithNamespace(stmt, "")
184+
}
185+
176186
// ExecuteQueryStmt executes the query statement.
177187
func (suite *NoSQLTestSuite) ExecuteQueryStmt(stmt string) ([]*types.MapValue, error) {
178188
return suite.ExecuteQueryRequest(&nosqldb.QueryRequest{Statement: stmt})
179189
}
180190

191+
// ExecuteQueryStmtWithNamespace executes the query statement in given namespace
192+
func (suite *NoSQLTestSuite) ExecuteQueryStmtWithNamespace(stmt string, namespace string) ([]*types.MapValue, error) {
193+
return suite.ExecuteQueryRequest(&nosqldb.QueryRequest{Statement: stmt, Namespace: namespace})
194+
}
195+
181196
// ExecuteQueryRequest executes the query request.
182197
func (suite *NoSQLTestSuite) ExecuteQueryRequest(queryReq *nosqldb.QueryRequest) ([]*types.MapValue, error) {
183198
return ExecuteQueryRequest(suite.Client, queryReq)
184199
}
185200

201+
// DoQueryWithNamespace executes the query statement in given namespace and
202+
// expects a given number of rows returned
203+
func (suite *NoSQLTestSuite) DoQueryWithNamespace(stmt string, namespace string, expRows int) {
204+
res, err := suite.ExecuteQueryRequest(&nosqldb.QueryRequest{Statement: stmt, Namespace: namespace})
205+
if suite.NoErrorf(err, "Unexpected error running query: %v", err) {
206+
suite.Equalf(expRows, len(res), "wrong number of rows returned from query")
207+
}
208+
}
209+
210+
// ExecuteQueryRequest executes the query request.
186211
// AddToTables adds the specified table into a table list, in which all tables
187212
// would be dropped on TearDownSuite if DropTablesOnTearDown is specified in test configuration.
188213
func (suite *NoSQLTestSuite) AddToTables(table string) {

nosqldb/client.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1052,6 +1052,10 @@ func (c *Client) doExecute(ctx context.Context, req Request, data []byte, serial
10521052
httpReq.Header.Set("Accept", "application/octet-stream")
10531053
httpReq.Header.Set("Connection", "keep-alive")
10541054
httpReq.Header.Set("User-Agent", sdkutil.UserAgent())
1055+
namespace := req.getNamespace()
1056+
if namespace != "" {
1057+
httpReq.Header.Add("x-nosql-default-ns", namespace)
1058+
}
10551059

10561060
// The authorization string could be empty when the client connects to a
10571061
// non-secure on-premise NoSQL database server over database proxy.

nosqldb/config.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ type Config struct {
9898
// This is only used for on-premise NoSQL server that configured with security.
9999
Password []byte `json:"password,omitempty"`
100100

101-
// Configurations for requests.
101+
// Default Configurations for requests.
102102
RequestConfig `json:"requestConfig,omitempty"`
103103

104104
// Configurations for HTTP client.
@@ -408,6 +408,13 @@ type RequestConfig struct {
408408
// include GetRequest and QueryRequest.
409409
// If set, it must be either types.Eventual or types.Absolute.
410410
Consistency types.Consistency `json:"consistency,omitempty"`
411+
412+
// Namespace is used on-premises only. It defines a namespace to use
413+
// for the request if it is not specified in the request struct itself or
414+
// in an SQL DDL/Query using the 'namespace:tablename' format.
415+
// This is only available with on-premises installations using NoSQL
416+
// Server versions 23.3 and above.
417+
Namespace string `json:"namespace,omitempty"`
411418
}
412419

413420
// DefaultRequestTimeout returns the default timeout value for requests.
@@ -451,6 +458,18 @@ func (r *RequestConfig) DefaultConsistency() types.Consistency {
451458
return r.Consistency
452459
}
453460

461+
// DefaultNamespace is used on-premises only. It defines a namespace to use
462+
// for the request if it is not specified in the request struct itself or
463+
// in an SQL DDL/Query using the 'namespace:tablename' format.
464+
// This is only available with on-premises installations using NoSQL
465+
// Server versions 23.3 and above.
466+
func (r *RequestConfig) DefaultNamespace() string {
467+
if r == nil {
468+
return ""
469+
}
470+
return r.Namespace
471+
}
472+
454473
// LoggingConfig represents logging configurations.
455474
type LoggingConfig struct {
456475

nosqldb/onprem_ops_test.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,144 @@ func (suite *OnPremTestSuite) TestNamespacesOp() {
8686
suite.doDDLTest("drop namespace NSABC", nosqlerr.NoError)
8787
}
8888

89+
// TestNamespacesOp tests create, drop and show namespaces operations.
90+
func (suite *OnPremTestSuite) TestDefaultNamespaces() {
91+
92+
// this only works with versions of KV with default namespace support
93+
if suite.Config.Version <= "22.3.31" {
94+
return
95+
}
96+
97+
suite.Client.RequestConfig.Namespace = "mydns"
98+
suite.doDDLTest("create namespace mydns", nosqlerr.NoError)
99+
100+
// parent in mydns
101+
stmt := "create table parent(sid integer, id integer, name string, " +
102+
"salary long, primary key(SHARD(sid), id))"
103+
suite.CreateTable(stmt, nil)
104+
105+
// child in mydns
106+
stmt = "create table parent.child(cid integer, cname string, " +
107+
"primary key(cid))"
108+
suite.CreateTable(stmt, nil)
109+
110+
// test ListTables with default namespace: should return just myns
111+
req := &nosqldb.ListTablesRequest{}
112+
res, err := suite.Client.ListTables(req)
113+
if suite.NoErrorf(err, "ListTables failed: %v", err) {
114+
suite.Equalf(2, len(res.Tables), "unexpected number of tables returned")
115+
}
116+
117+
// test ListTables with explicit namespace
118+
req = &nosqldb.ListTablesRequest{Namespace: "mydns"}
119+
res, err = suite.Client.ListTables(req)
120+
if suite.NoErrorf(err, "ListTables failed: %v", err) {
121+
suite.Equalf(2, len(res.Tables), "unexpected number of tables returned")
122+
}
123+
124+
// test ListTables with explicit invalid
125+
req = &nosqldb.ListTablesRequest{Namespace: "invalid"}
126+
res, err = suite.Client.ListTables(req)
127+
if suite.NoErrorf(err, "ListTables failed: %v", err) {
128+
suite.Equalf(0, len(res.Tables), "expected zero tables returned for invalid namespace")
129+
}
130+
131+
suite.Client.RequestConfig.Namespace = ""
132+
133+
// test ListTables with no namespace: should return all
134+
req = &nosqldb.ListTablesRequest{}
135+
res, err = suite.Client.ListTables(req)
136+
if suite.NoErrorf(err, "ListTables failed: %v", err) {
137+
// should have more than 2 tables listed
138+
if len(res.Tables) <= 2 {
139+
suite.Fail("Expected more than 2 tables, got %d", len(res.Tables))
140+
}
141+
}
142+
143+
suite.Client.RequestConfig.Namespace = "mydns"
144+
145+
// put data in both tables
146+
for i:=0; i<10; i++ {
147+
value := &types.MapValue{}
148+
value.Put("id", i).Put("name", "pname")
149+
value.Put("sid", i).Put("salary", i*1000)
150+
putReq := &nosqldb.PutRequest{
151+
TableName: "parent",
152+
Value: value,
153+
}
154+
//putRes, err := suite.Client.Put(putReq)
155+
_, err := suite.Client.Put(putReq)
156+
suite.NoErrorf(err, "Parent put failed: %v", err)
157+
for j:=0; j<10; j++ {
158+
value.Put("cid", j).Put("cname", fmt.Sprintf("cname%d", j))
159+
putReq.TableName = "parent.child"
160+
putReq.Value = value
161+
//putRes, err = suite.Client.Put(putReq)
162+
_, err = suite.Client.Put(putReq)
163+
suite.NoErrorf(err, "Child put failed: %v", err)
164+
}
165+
}
166+
167+
// get parent
168+
key := types.ToMapValue("id", 1).Put("sid", 1)
169+
getReq := &nosqldb.GetRequest{TableName: "parent", Key: key}
170+
_, err = suite.Client.Get(getReq)
171+
suite.NoErrorf(err, "Error trying to get record from parent: %v", err)
172+
173+
// get child
174+
key = types.ToMapValue("id", 1).Put("sid", 1).Put("cid", 1)
175+
getReq = &nosqldb.GetRequest{TableName: "parent.child", Key: key}
176+
_, err = suite.Client.Get(getReq)
177+
suite.NoErrorf(err, "Error trying to get record from child: %v", err)
178+
179+
// same ops should fail with no default namespace
180+
suite.Client.RequestConfig.Namespace = ""
181+
// get parent
182+
key = types.ToMapValue("id", 1).Put("sid", 1)
183+
getReq = &nosqldb.GetRequest{TableName: "parent", Key: key}
184+
_, err = suite.Client.Get(getReq)
185+
suite.Errorf(err, "Expected error trying to get record from parent, got none")
186+
187+
// get child
188+
key = types.ToMapValue("id", 1).Put("sid", 1).Put("cid", 1)
189+
getReq = &nosqldb.GetRequest{TableName: "parent.child", Key: key}
190+
_, err = suite.Client.Get(getReq)
191+
suite.Errorf(err, "Expected error trying to get record from child, got none")
192+
193+
// verify namespace in tablename overrides default
194+
key = types.ToMapValue("id", 1).Put("sid", 1).Put("cid", 1)
195+
getReq = &nosqldb.GetRequest{TableName: "mydns:parent.child", Key: key, Namespace: "invalid"}
196+
_, err = suite.Client.Get(getReq)
197+
suite.NoErrorf(err, "Error trying to get record from child: %v", err)
198+
199+
200+
// query parent
201+
stmt = "select * from parent"
202+
suite.Client.RequestConfig.Namespace = "mydns"
203+
suite.DoQueryWithNamespace(stmt, "", 10)
204+
suite.Client.RequestConfig.Namespace = "invalid"
205+
suite.DoQueryWithNamespace(stmt, "mydns", 10)
206+
207+
// query child
208+
stmt = "select * from parent.child"
209+
suite.Client.RequestConfig.Namespace = "mydns"
210+
suite.DoQueryWithNamespace(stmt, "", 100)
211+
suite.Client.RequestConfig.Namespace = "invalid"
212+
suite.DoQueryWithNamespace(stmt, "mydns", 100)
213+
214+
// test complex query (exercises internal request copying)
215+
suite.Client.RequestConfig.Namespace = ""
216+
stmt = "select sid, count(*) as cnt, sum(salary) as sum " +
217+
"from parent group by sid";
218+
suite.DoQueryWithNamespace(stmt, "mydns", 10)
219+
220+
// drop table with namespace in request
221+
suite.DropTableWithNamespace("parent.child", false, "mydns")
222+
223+
// drop namespace - use cascade to remove tables
224+
suite.doDDLTest("drop namespace mydns cascade", nosqlerr.NoError)
225+
}
226+
89227
// TestUserRolesOp tests create/drop/show/list users, create/drop/show/list roles
90228
// and grant/revoke roles operations.
91229
//

0 commit comments

Comments
 (0)