Codebase list golang-github-mattn-go-sqlite3-upstream / 3ccccfb
Support returning any from callbacks (#1046) Support returning any from callbacks Phil Eaton authored 1 year, 10 months ago GitHub committed 1 year, 10 months ago
3 changed file(s) with 88 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
352352 return nil
353353 }
354354
355 func callbackRetGeneric(ctx *C.sqlite3_context, v reflect.Value) error {
356 if v.IsNil() {
357 C.sqlite3_result_null(ctx)
358 return nil
359 }
360
361 cb, err := callbackRet(v.Elem().Type())
362 if err != nil {
363 return err
364 }
365
366 return cb(ctx, v.Elem())
367 }
368
355369 func callbackRet(typ reflect.Type) (callbackRetConverter, error) {
356370 switch typ.Kind() {
357371 case reflect.Interface:
359373 if typ.Implements(errorInterface) {
360374 return callbackRetNil, nil
361375 }
376
377 if typ.NumMethod() == 0 {
378 return callbackRetGeneric, nil
379 }
380
362381 fallthrough
363382 case reflect.Slice:
364383 if typ.Elem().Kind() != reflect.Uint8 {
101101 }
102102 }
103103 }
104
105 func TestCallbackReturnAny(t *testing.T) {
106 udf := func() interface{} {
107 return 1
108 }
109
110 typ := reflect.TypeOf(udf)
111 _, err := callbackRet(typ.Out(0))
112 if err != nil {
113 t.Errorf("Expected valid callback for any return type, got: %s", err)
114 }
115 }
14451445 if ret != test.sum {
14461446 t.Fatalf("Custom sum returned wrong value, got %d, want %d", ret, test.sum)
14471447 }
1448 }
1449 }
1450
1451 type mode struct {
1452 counts map[interface{}]int
1453 top interface{}
1454 topCount int
1455 }
1456
1457 func newMode() *mode {
1458 return &mode{
1459 counts: map[interface{}]int{},
1460 }
1461 }
1462
1463 func (m *mode) Step(x interface{}) {
1464 m.counts[x]++
1465 c := m.counts[x]
1466 if c > m.topCount {
1467 m.top = x
1468 m.topCount = c
1469 }
1470 }
1471
1472 func (m *mode) Done() interface{} {
1473 return m.top
1474 }
1475
1476 func TestAggregatorRegistration_GenericReturn(t *testing.T) {
1477 sql.Register("sqlite3_AggregatorRegistration_GenericReturn", &SQLiteDriver{
1478 ConnectHook: func(conn *SQLiteConn) error {
1479 return conn.RegisterAggregator("mode", newMode, true)
1480 },
1481 })
1482 db, err := sql.Open("sqlite3_AggregatorRegistration_GenericReturn", ":memory:")
1483 if err != nil {
1484 t.Fatal("Failed to open database:", err)
1485 }
1486 defer db.Close()
1487
1488 _, err = db.Exec("create table foo (department integer, profits integer)")
1489 if err != nil {
1490 t.Fatal("Failed to create table:", err)
1491 }
1492 _, err = db.Exec("insert into foo values (1, 10), (1, 20), (1, 45), (2, 42), (2, 115), (2, 20)")
1493 if err != nil {
1494 t.Fatal("Failed to insert records:", err)
1495 }
1496
1497 var mode int
1498 err = db.QueryRow("select mode(profits) from foo").Scan(&mode)
1499 if err != nil {
1500 t.Fatal("MODE query error:", err)
1501 }
1502
1503 if mode != 20 {
1504 t.Fatal("Got incorrect mode. Wanted 20, got: ", mode)
14481505 }
14491506 }
14501507