Skip to content

Commit f60e81c

Browse files
committed
add support for Self and Kind fields in response from getDbRecord/s
1 parent 2c3bcbe commit f60e81c

File tree

4 files changed

+59
-30
lines changed

4 files changed

+59
-30
lines changed

cx_test.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ func (cx *testContext) bump() {
4646
// assertEqual() fails the test unless exp and act are equal.
4747
func (cx *testContext) assertEqual(exp interface{}, act interface{}, msg string) bool {
4848
if exp != act {
49-
cx.Errorf(`*** Assertion Failed: %s, got (%T)<%v>; expected (%T)<%v>`,
50-
msg, act, act, exp, exp)
49+
cx.Errorf(`*** Assertion Failed: %s
50+
expected: (%T)<%v>
51+
got: (%T)<%v>`,
52+
msg, exp, exp, act, act)
5153
return false
5254
}
5355
return true
@@ -56,8 +58,10 @@ func (cx *testContext) assertEqual(exp interface{}, act interface{}, msg string)
5658
// assertEqualObj() fails the test unless exp and act are deeply equal.
5759
func (cx *testContext) assertEqualObj(exp interface{}, act interface{}, msg string) bool {
5860
if !reflect.DeepEqual(exp, act) {
59-
cx.Errorf(`assertion failed: %s, got <%s>; expected <%s>`,
60-
msg, act, exp)
61+
cx.Errorf(`assertion failed: %s
62+
expected: <%s>
63+
got: <%s>`,
64+
msg, exp, act)
6165
return false
6266
}
6367
return true

handlers.go

+30-12
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"strconv"
77
"bytes"
88
"net/http"
9+
"net/url"
910
"encoding/json"
1011
"database/sql"
1112
)
@@ -77,7 +78,7 @@ func getDbRecordsHandler(harg *apiHandlerArg) apiHandlerRet {
7778
return errorRet(badStat, err, "after fetchParams")
7879
}
7980

80-
return getCommon(params)
81+
return getCommon(harg.req.URL, params)
8182
}
8283

8384
// getDbRecordHandler() handles GET requests on /db/_table/{table_name}/{id} .
@@ -90,7 +91,7 @@ func getDbRecordHandler(harg *apiHandlerArg) apiHandlerRet {
9091
params["limit"] = strconv.Itoa(1)
9192
params["offset"] = strconv.Itoa(0)
9293

93-
return getCommon(params)
94+
return getCommon(harg.req.URL, params)
9495
}
9596

9697
// updateDbRecordsHandler() handles PATCH requests on /db/_table/{table_name} .
@@ -180,7 +181,7 @@ func tablesQuery(tabName string,
180181

181182
idlist := []interface{}{}
182183
qstring := fmt.Sprintf("select %s from %s", fieldName, tabName)
183-
result, err := runQuery(db, qstring, idlist)
184+
result, err := runQuery(db, nil, qstring, idlist)
184185
if err != nil {
185186
return errorRet(badStat, err, "after runQuery")
186187
}
@@ -203,7 +204,7 @@ func schemaQuery(tabName string,
203204
idlist := []interface{}{}
204205
qstring := fmt.Sprintf(`select %s from %s where %s = "%s"`,
205206
fieldName, tabName, selector, item)
206-
result, err := runQuery(db, qstring, idlist)
207+
result, err := runQuery(db, nil, qstring, idlist)
207208
if err != nil {
208209
return errorRet(badStat, err, "after runQuery")
209210
}
@@ -245,9 +246,9 @@ func mkSQLRow(N int) []interface{} {
245246

246247
// queryErrorRet() passes thru the first 2 args (ret and err),
247248
// while logging the third argument (dmsg).
248-
func queryErrorRet(ret []*KVRecord,
249+
func queryErrorRet(ret []*KVResponse,
249250
err error,
250-
dmsg string) ([]*KVRecord, error) {
251+
dmsg string) ([]*KVResponse, error) {
251252
if dmsg != "" {
252253
log.Debugf("queryErrorRet [%s], %s", err, dmsg)
253254
}
@@ -257,12 +258,13 @@ func queryErrorRet(ret []*KVRecord,
257258
// runQuery() does a select query using the given query string.
258259
// the return value is a list of the retrieved records.
259260
func runQuery(db dbType,
261+
u *url.URL,
260262
qstring string,
261-
ivals []interface{}) ([]*KVRecord, error) {
263+
ivals []interface{}) ([]*KVResponse, error) {
262264
log.Debugf("query = %s", qstring)
263265
log.Debugf("ivals = %s", ivals)
264266

265-
ret := make([]*KVRecord, 0, 1)
267+
ret := make([]*KVResponse, 0, 1)
266268

267269
rows, err := db.handle.Query(qstring, ivals...)
268270
if err != nil {
@@ -279,6 +281,7 @@ func runQuery(db dbType,
279281
log.Debugf("cols = %s", cols)
280282
ncols := len(cols)
281283

284+
i := 0
282285
for rows.Next() {
283286
vals := mkSQLRow(ncols)
284287
err = rows.Scan(vals...)
@@ -290,11 +293,16 @@ func runQuery(db dbType,
290293
if err != nil {
291294
return queryErrorRet(ret, err, "failure after convValues")
292295
}
293-
kvrow := KVRecord{Keys: cols, Values: vals}
296+
kvrow := KVResponse{Keys: cols,
297+
Values: vals,
298+
Kind: "KVResponse",
299+
Self: mkSelf(u, ivals, i),
300+
}
294301
ret = append(ret, &kvrow)
295302
if len(ret) >= maxRecs { // safety check
296303
break
297304
}
305+
i++
298306
}
299307

300308
err = rows.Err()
@@ -526,9 +534,9 @@ func mkSelectString(params map[string]string) (string, []interface{}) {
526534
}
527535

528536
// getCommon() is common code for selection APIs.
529-
func getCommon(params map[string]string) apiHandlerRet {
537+
func getCommon(u *url.URL, params map[string]string) apiHandlerRet {
530538
qstring, idlist := mkSelectString(params)
531-
result, err := runQuery(db, qstring, idlist)
539+
result, err := runQuery(db, u, qstring, idlist)
532540
if err != nil {
533541
return errorRet(badStat, err, "after runQuery")
534542
}
@@ -560,7 +568,7 @@ func updateCommon(harg *apiHandlerArg, params map[string]string) apiHandlerRet {
560568

561569
// convTableNames() converts the return format from runQuery()
562570
// into a simple list of names.
563-
func convTableNames(result []*KVRecord) ([]string, error) {
571+
func convTableNames(result []*KVResponse) ([]string, error) {
564572
// convert from query format to simple list of names
565573
ret := make([]string, len(result))
566574
for i, row := range result {
@@ -689,3 +697,13 @@ func execN(db dbType, cmdList ...*xCmd) error {
689697
}
690698
return tx.Commit()
691699
}
700+
701+
// mkSelf() returns a string for the self field of a KVResponse.
702+
func mkSelf(u *url.URL, idlist []interface{}, i int) string {
703+
if u == nil || i >= len(idlist) {
704+
log.Debugf("mkSelf: idlist=%s, i=%d", idlist, i)
705+
return "??"
706+
}
707+
id, _ := idlist[i].(int64)
708+
return fmt.Sprintf("%s://%s%s/%d", u.Scheme, u.Host, u.Path, id)
709+
}

handlers_test.go

+11-11
Original file line numberDiff line numberDiff line change
@@ -428,9 +428,9 @@ var convTableNames_Tab = []convTableNames_TC {
428428

429429
// mimicTableNamesQuery() returns an object that mimics the return from
430430
// the query to the "_tables_" table.
431-
func mimicTableNamesQuery(names []string) []*KVRecord {
431+
func mimicTableNamesQuery(names []string) []*KVResponse {
432432
N := len(names)
433-
ret := make([]*KVRecord, N)
433+
ret := make([]*KVResponse, N)
434434
for i := 0; i < N; i++ {
435435
Keys := []string{"name"}
436436
val := names[i]
@@ -442,7 +442,7 @@ func mimicTableNamesQuery(names []string) []*KVRecord {
442442
ival = interface{}(val)
443443
}
444444
Values := []interface{}{ival}
445-
ret[i] = &KVRecord{Keys, Values}
445+
ret[i] = &KVResponse{Keys, Values, "KVResponse", ""}
446446
}
447447
return ret
448448
}
@@ -1366,18 +1366,18 @@ var getDbRecordHandler_Tab = []apiCall_TC {
13661366
{"setup: create table xxxget",
13671367
createDbTableHandler,
13681368
http.MethodPost,
1369-
`/db/_schema/ABC|table_name=xxxget||`+users_schema,
1369+
`/db/_schema/xxxget|table_name=xxxget||`+users_schema,
13701370
http.StatusCreated, noCheck},
13711371
{"setup: create db record 1",
13721372
createDbRecordsHandler,
13731373
http.MethodPost,
1374-
`/db/_table/tabname|table_name=xxxget||{"Records":[{"Keys":["uri","name"],"Values":["uri-a","name-a"]}]}`,
1374+
`/db/_table/xxxget|table_name=xxxget||{"Records":[{"Keys":["uri","name"],"Values":["uri-a","name-a"]}]}`,
13751375
http.StatusCreated, noCheck},
13761376
{"get db record 1",
13771377
getDbRecordHandler,
13781378
http.MethodGet,
1379-
`/db/_table/tabname|table_name=xxxget&id=1`,
1380-
http.StatusOK, `{"Records":[{"Keys":["id","uri","name"],"Values":["1","uri-a","name-a"]}]}`},
1379+
`http://localhost/db/_table/xxxget|table_name=xxxget&id=1`,
1380+
http.StatusOK, `{"Records":[{"Keys":["id","uri","name"],"Values":["1","uri-a","name-a"],"Kind":"KVResponse","Self":"http://localhost/db/_table/xxxget/1"}]}`},
13811381
{"teardown: delete table xxxget",
13821382
deleteDbTableHandler,
13831383
http.MethodDelete,
@@ -1405,19 +1405,19 @@ var getDbRecordsHandler_Tab = []apiCall_TC {
14051405
{"setup: create db record 1",
14061406
createDbRecordsHandler,
14071407
http.MethodPost,
1408-
`/db/_table/tabname|table_name=xxxget||{"Records":[{"Keys":["name","uri"],"Values":["name-a","uri-a"]}]}`,
1408+
`/db/_table/xxxget|table_name=xxxget||{"Records":[{"Keys":["name","uri"],"Values":["name-a","uri-a"]}]}`,
14091409
http.StatusCreated, noCheck},
14101410
{"setup: create db record 2",
14111411
createDbRecordsHandler,
14121412
http.MethodPost,
1413-
`/db/_table/tabname|table_name=xxxget||{"Records":[{"Keys":["uri","name"],"Values":["uri-b","name-b"]}]}`,
1413+
`/db/_table/xxxget|table_name=xxxget||{"Records":[{"Keys":["uri","name"],"Values":["uri-b","name-b"]}]}`,
14141414
http.StatusCreated, noCheck},
14151415
{"get db records 1,2",
14161416
getDbRecordsHandler,
14171417
http.MethodGet,
1418-
`/db/_table/tabname|table_name=xxxget&ids=1,2`,
1418+
`http://localhost/db/_table/xxxget|table_name=xxxget|ids=1,2`,
14191419
http.StatusOK,
1420-
`{"Records":[{"Keys":["id","uri","name"],"Values":["1","uri-a","name-a"]},{"Keys":["id","uri","name"],"Values":["2","uri-b","name-b"]}]}`},
1420+
`{"Records":[{"Keys":["id","uri","name"],"Values":["1","uri-a","name-a"],"Kind":"KVResponse","Self":"http://localhost/db/_table/xxxget/1"},{"Keys":["id","uri","name"],"Values":["2","uri-b","name-b"],"Kind":"KVResponse","Self":"http://localhost/db/_table/xxxget/2"}]}`},
14211421
{"teardown: delete table xxxget",
14221422
deleteDbTableHandler,
14231423
http.MethodDelete,

records.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,27 @@ type ErrorResponse struct {
1313
Message string
1414
}
1515

16+
// KVRecord represents record data in requests, used in multiple APIs.
17+
type KVRecord struct {
18+
Keys []string
19+
Values []interface{}
20+
}
21+
1622
// BodyRecord is the body data for APIs that create or update database records.
1723
type BodyRecord struct {
1824
Records []KVRecord
1925
}
2026

21-
// KVRecord represents record data in requests, used in multiple APIs.
22-
type KVRecord struct {
27+
type KVResponse struct {
2328
Keys []string
2429
Values []interface{}
30+
Kind string
31+
Self string
2532
}
2633

2734
// RecordsResponse is the type for multiple get*Record* APIs.
2835
type RecordsResponse struct {
29-
Records []*KVRecord
36+
Records []*KVResponse
3037
}
3138

3239
// IdsResponse is the type returned by createDbRecords .

0 commit comments

Comments
 (0)