You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

467 lines
12 KiB

  1. // Copyright 2018 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. // +build go1.7
  15. package spanner
  16. import (
  17. "reflect"
  18. "testing"
  19. "time"
  20. "cloud.google.com/go/civil"
  21. proto "github.com/golang/protobuf/proto"
  22. proto3 "github.com/golang/protobuf/ptypes/struct"
  23. "golang.org/x/net/context"
  24. sppb "google.golang.org/genproto/googleapis/spanner/v1"
  25. )
  26. func TestEncodeStructValueDynamicStructs(t *testing.T) {
  27. dynStructType := reflect.StructOf([]reflect.StructField{
  28. {Name: "A", Type: reflect.TypeOf(0), Tag: `spanner:"a"`},
  29. {Name: "B", Type: reflect.TypeOf(""), Tag: `spanner:"b"`},
  30. })
  31. dynNullableStructType := reflect.PtrTo(dynStructType)
  32. dynStructArrType := reflect.SliceOf(dynStructType)
  33. dynNullableStructArrType := reflect.SliceOf(dynNullableStructType)
  34. dynStructValue := reflect.New(dynStructType)
  35. dynStructValue.Elem().Field(0).SetInt(10)
  36. dynStructValue.Elem().Field(1).SetString("abc")
  37. dynStructArrValue := reflect.MakeSlice(dynNullableStructArrType, 2, 2)
  38. dynStructArrValue.Index(0).Set(reflect.Zero(dynNullableStructType))
  39. dynStructArrValue.Index(1).Set(dynStructValue)
  40. structProtoType := structType(
  41. mkField("a", intType()),
  42. mkField("b", stringType()))
  43. arrProtoType := listType(structProtoType)
  44. for _, test := range []encodeTest{
  45. {
  46. "Dynanic non-NULL struct value.",
  47. dynStructValue.Elem().Interface(),
  48. listProto(intProto(10), stringProto("abc")),
  49. structProtoType,
  50. },
  51. {
  52. "Dynanic NULL struct value.",
  53. reflect.Zero(dynNullableStructType).Interface(),
  54. nullProto(),
  55. structProtoType,
  56. },
  57. {
  58. "Empty array of dynamic structs.",
  59. reflect.MakeSlice(dynStructArrType, 0, 0).Interface(),
  60. listProto([]*proto3.Value{}...),
  61. arrProtoType,
  62. },
  63. {
  64. "NULL array of non-NULL-able dynamic structs.",
  65. reflect.Zero(dynStructArrType).Interface(),
  66. nullProto(),
  67. arrProtoType,
  68. },
  69. {
  70. "NULL array of NULL-able(nil) dynamic structs.",
  71. reflect.Zero(dynNullableStructArrType).Interface(),
  72. nullProto(),
  73. arrProtoType,
  74. },
  75. {
  76. "Array containing NULL(nil) dynamic-typed struct elements.",
  77. dynStructArrValue.Interface(),
  78. listProto(
  79. nullProto(),
  80. listProto(intProto(10), stringProto("abc"))),
  81. arrProtoType,
  82. },
  83. } {
  84. encodeStructValue(test, t)
  85. }
  86. }
  87. func TestEncodeStructValueEmptyStruct(t *testing.T) {
  88. emptyListValue := listProto([]*proto3.Value{}...)
  89. emptyStructType := structType([]*sppb.StructType_Field{}...)
  90. emptyStruct := struct{}{}
  91. nullEmptyStruct := (*struct{})(nil)
  92. dynamicEmptyStructType := reflect.StructOf(make([]reflect.StructField, 0, 0))
  93. dynamicStructArrType := reflect.SliceOf(reflect.PtrTo((dynamicEmptyStructType)))
  94. dynamicEmptyStruct := reflect.New(dynamicEmptyStructType)
  95. dynamicNullEmptyStruct := reflect.Zero(reflect.PtrTo(dynamicEmptyStructType))
  96. dynamicStructArrValue := reflect.MakeSlice(dynamicStructArrType, 2, 2)
  97. dynamicStructArrValue.Index(0).Set(dynamicNullEmptyStruct)
  98. dynamicStructArrValue.Index(1).Set(dynamicEmptyStruct)
  99. for _, test := range []encodeTest{
  100. {
  101. "Go empty struct.",
  102. emptyStruct,
  103. emptyListValue,
  104. emptyStructType,
  105. },
  106. {
  107. "Dynamic empty struct.",
  108. dynamicEmptyStruct.Interface(),
  109. emptyListValue,
  110. emptyStructType,
  111. },
  112. {
  113. "Go NULL empty struct.",
  114. nullEmptyStruct,
  115. nullProto(),
  116. emptyStructType,
  117. },
  118. {
  119. "Dynamic NULL empty struct.",
  120. dynamicNullEmptyStruct.Interface(),
  121. nullProto(),
  122. emptyStructType,
  123. },
  124. {
  125. "Non-empty array of dynamic NULL and non-NULL empty structs.",
  126. dynamicStructArrValue.Interface(),
  127. listProto(nullProto(), emptyListValue),
  128. listType(emptyStructType),
  129. },
  130. {
  131. "Non-empty array of nullable empty structs.",
  132. []*struct{}{nullEmptyStruct, &emptyStruct},
  133. listProto(nullProto(), emptyListValue),
  134. listType(emptyStructType),
  135. },
  136. {
  137. "Empty array of empty struct.",
  138. []struct{}{},
  139. emptyListValue,
  140. listType(emptyStructType),
  141. },
  142. {
  143. "Null array of empty structs.",
  144. []struct{}(nil),
  145. nullProto(),
  146. listType(emptyStructType),
  147. },
  148. } {
  149. encodeStructValue(test, t)
  150. }
  151. }
  152. func TestEncodeStructValueMixedStructTypes(t *testing.T) {
  153. type staticStruct struct {
  154. F int `spanner:"fStatic"`
  155. }
  156. s1 := staticStruct{10}
  157. s2 := (*staticStruct)(nil)
  158. var f float64
  159. dynStructType := reflect.StructOf([]reflect.StructField{
  160. {Name: "A", Type: reflect.TypeOf(f), Tag: `spanner:"fDynamic"`},
  161. })
  162. s3 := reflect.New(dynStructType)
  163. s3.Elem().Field(0).SetFloat(3.14)
  164. for _, test := range []encodeTest{
  165. {
  166. "'struct' with static and dynamic *struct, []*struct, []struct fields",
  167. struct {
  168. A []staticStruct
  169. B []*staticStruct
  170. C interface{}
  171. }{
  172. []staticStruct{s1, s1},
  173. []*staticStruct{&s1, s2},
  174. s3.Interface(),
  175. },
  176. listProto(
  177. listProto(listProto(intProto(10)), listProto(intProto(10))),
  178. listProto(listProto(intProto(10)), nullProto()),
  179. listProto(floatProto(3.14))),
  180. structType(
  181. mkField("A", listType(structType(mkField("fStatic", intType())))),
  182. mkField("B", listType(structType(mkField("fStatic", intType())))),
  183. mkField("C", structType(mkField("fDynamic", floatType())))),
  184. },
  185. } {
  186. encodeStructValue(test, t)
  187. }
  188. }
  189. func TestBindParamsDynamic(t *testing.T) {
  190. // Verify Statement.bindParams generates correct values and types.
  191. st := Statement{
  192. SQL: "SELECT id from t_foo WHERE col = @var",
  193. Params: map[string]interface{}{"var": nil},
  194. }
  195. want := &sppb.ExecuteSqlRequest{
  196. Params: &proto3.Struct{
  197. Fields: map[string]*proto3.Value{"var": nil},
  198. },
  199. ParamTypes: map[string]*sppb.Type{"var": nil},
  200. }
  201. var (
  202. t1, _ = time.Parse(time.RFC3339Nano, "2016-11-15T15:04:05.999999999Z")
  203. // Boundaries
  204. t2, _ = time.Parse(time.RFC3339Nano, "0001-01-01T00:00:00.000000000Z")
  205. )
  206. dynamicStructType := reflect.StructOf([]reflect.StructField{
  207. {Name: "A", Type: reflect.TypeOf(t1), Tag: `spanner:"field"`},
  208. {Name: "B", Type: reflect.TypeOf(3.14), Tag: `spanner:""`},
  209. })
  210. dynamicStructArrType := reflect.SliceOf(reflect.PtrTo(dynamicStructType))
  211. dynamicEmptyStructType := reflect.StructOf(make([]reflect.StructField, 0, 0))
  212. dynamicStructTypeProto := structType(
  213. mkField("field", timeType()),
  214. mkField("", floatType()))
  215. s3 := reflect.New(dynamicStructType)
  216. s3.Elem().Field(0).Set(reflect.ValueOf(t1))
  217. s3.Elem().Field(1).SetFloat(1.4)
  218. s4 := reflect.New(dynamicStructType)
  219. s4.Elem().Field(0).Set(reflect.ValueOf(t2))
  220. s4.Elem().Field(1).SetFloat(-13.3)
  221. dynamicStructArrayVal := reflect.MakeSlice(dynamicStructArrType, 2, 2)
  222. dynamicStructArrayVal.Index(0).Set(s3)
  223. dynamicStructArrayVal.Index(1).Set(s4)
  224. for i, test := range []struct {
  225. val interface{}
  226. wantField *proto3.Value
  227. wantType *sppb.Type
  228. }{
  229. {
  230. s3.Interface(),
  231. listProto(timeProto(t1), floatProto(1.4)),
  232. structType(
  233. mkField("field", timeType()),
  234. mkField("", floatType())),
  235. },
  236. {
  237. reflect.Zero(reflect.PtrTo(dynamicEmptyStructType)).Interface(),
  238. nullProto(),
  239. structType([]*sppb.StructType_Field{}...),
  240. },
  241. {
  242. dynamicStructArrayVal.Interface(),
  243. listProto(
  244. listProto(timeProto(t1), floatProto(1.4)),
  245. listProto(timeProto(t2), floatProto(-13.3))),
  246. listType(dynamicStructTypeProto),
  247. },
  248. {
  249. []*struct {
  250. F1 time.Time `spanner:"field"`
  251. F2 float64 `spanner:""`
  252. }{
  253. nil,
  254. {t1, 1.4},
  255. },
  256. listProto(
  257. nullProto(),
  258. listProto(timeProto(t1), floatProto(1.4))),
  259. listType(dynamicStructTypeProto),
  260. },
  261. } {
  262. st.Params["var"] = test.val
  263. want.Params.Fields["var"] = test.wantField
  264. want.ParamTypes["var"] = test.wantType
  265. got := &sppb.ExecuteSqlRequest{}
  266. if err := st.bindParams(got); err != nil || !proto.Equal(got, want) {
  267. // handle NaN
  268. if test.wantType.Code == floatType().Code && proto.MarshalTextString(got) == proto.MarshalTextString(want) {
  269. continue
  270. }
  271. t.Errorf("#%d: bind result: \n(%v, %v)\nwant\n(%v, %v)\n", i, got, err, want, nil)
  272. }
  273. }
  274. }
  275. func TestStructParametersBind(t *testing.T) {
  276. t.Parallel()
  277. ctx := context.Background()
  278. client, _, tearDown := prepare(ctx, t, nil)
  279. defer tearDown()
  280. type tRow []interface{}
  281. type tRows []struct{ trow tRow }
  282. type allFields struct {
  283. Stringf string
  284. Intf int
  285. Boolf bool
  286. Floatf float64
  287. Bytef []byte
  288. Timef time.Time
  289. Datef civil.Date
  290. }
  291. allColumns := []string{
  292. "Stringf",
  293. "Intf",
  294. "Boolf",
  295. "Floatf",
  296. "Bytef",
  297. "Timef",
  298. "Datef",
  299. }
  300. s1 := allFields{"abc", 300, false, 3.45, []byte("foo"), t1, d1}
  301. s2 := allFields{"def", -300, false, -3.45, []byte("bar"), t2, d2}
  302. dynamicStructType := reflect.StructOf([]reflect.StructField{
  303. {Name: "A", Type: reflect.TypeOf(t1), Tag: `spanner:"ff1"`},
  304. })
  305. s3 := reflect.New(dynamicStructType)
  306. s3.Elem().Field(0).Set(reflect.ValueOf(t1))
  307. for i, test := range []struct {
  308. param interface{}
  309. sql string
  310. cols []string
  311. trows tRows
  312. }{
  313. // Struct value.
  314. {
  315. s1,
  316. "SELECT" +
  317. " @p.Stringf," +
  318. " @p.Intf," +
  319. " @p.Boolf," +
  320. " @p.Floatf," +
  321. " @p.Bytef," +
  322. " @p.Timef," +
  323. " @p.Datef",
  324. allColumns,
  325. tRows{
  326. {tRow{"abc", 300, false, 3.45, []byte("foo"), t1, d1}},
  327. },
  328. },
  329. // Array of struct value.
  330. {
  331. []allFields{s1, s2},
  332. "SELECT * FROM UNNEST(@p)",
  333. allColumns,
  334. tRows{
  335. {tRow{"abc", 300, false, 3.45, []byte("foo"), t1, d1}},
  336. {tRow{"def", -300, false, -3.45, []byte("bar"), t2, d2}},
  337. },
  338. },
  339. // Null struct.
  340. {
  341. (*allFields)(nil),
  342. "SELECT @p IS NULL",
  343. []string{""},
  344. tRows{
  345. {tRow{true}},
  346. },
  347. },
  348. // Null Array of struct.
  349. {
  350. []allFields(nil),
  351. "SELECT @p IS NULL",
  352. []string{""},
  353. tRows{
  354. {tRow{true}},
  355. },
  356. },
  357. // Empty struct.
  358. {
  359. struct{}{},
  360. "SELECT @p IS NULL ",
  361. []string{""},
  362. tRows{
  363. {tRow{false}},
  364. },
  365. },
  366. // Empty array of struct.
  367. {
  368. []allFields{},
  369. "SELECT * FROM UNNEST(@p) ",
  370. allColumns,
  371. tRows{},
  372. },
  373. // Struct with duplicate fields.
  374. {
  375. struct {
  376. A int `spanner:"field"`
  377. B int `spanner:"field"`
  378. }{10, 20},
  379. "SELECT * FROM UNNEST([@p]) ",
  380. []string{"field", "field"},
  381. tRows{
  382. {tRow{10, 20}},
  383. },
  384. },
  385. // Struct with unnamed fields.
  386. {
  387. struct {
  388. A string `spanner:""`
  389. }{"hello"},
  390. "SELECT * FROM UNNEST([@p]) ",
  391. []string{""},
  392. tRows{
  393. {tRow{"hello"}},
  394. },
  395. },
  396. // Mixed struct.
  397. {
  398. struct {
  399. DynamicStructField interface{} `spanner:"f1"`
  400. ArrayStructField []*allFields `spanner:"f2"`
  401. }{
  402. DynamicStructField: s3.Interface(),
  403. ArrayStructField: []*allFields{nil},
  404. },
  405. "SELECT @p.f1.ff1, ARRAY_LENGTH(@p.f2), @p.f2[OFFSET(0)] IS NULL ",
  406. []string{"ff1", "", ""},
  407. tRows{
  408. {tRow{t1, 1, true}},
  409. },
  410. },
  411. } {
  412. iter := client.Single().Query(ctx, Statement{
  413. SQL: test.sql,
  414. Params: map[string]interface{}{"p": test.param},
  415. })
  416. var gotRows []*Row
  417. err := iter.Do(func(r *Row) error {
  418. gotRows = append(gotRows, r)
  419. return nil
  420. })
  421. if err != nil {
  422. t.Errorf("Failed to execute test case %d, error: %v", i, err)
  423. }
  424. var wantRows []*Row
  425. for j, row := range test.trows {
  426. r, err := NewRow(test.cols, row.trow)
  427. if err != nil {
  428. t.Errorf("Invalid row %d in test case %d", j, i)
  429. }
  430. wantRows = append(wantRows, r)
  431. }
  432. if !testEqual(gotRows, wantRows) {
  433. t.Errorf("%d: Want result %v, got result %v", i, wantRows, gotRows)
  434. }
  435. }
  436. }