github.com/runner-mei/ql@v1.1.0/introspection_test.go (about)

     1  // Copyright 2014 The ql Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package ql
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"math/big"
    11  	//"reflect"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/cznic/mathutil"
    16  )
    17  
    18  type (
    19  	testSchema struct {
    20  		a  int8
    21  		ID int64
    22  		A  int8
    23  		b  int
    24  		B  int `ql:"-"`
    25  	}
    26  
    27  	testSchema2 struct{}
    28  
    29  	testSchema3 struct {
    30  		a  int8
    31  		ID uint64
    32  		A  int8
    33  		b  int
    34  		B  int `ql:"-"`
    35  		c  bool
    36  		C  bool `ql:"name cc"`
    37  	}
    38  
    39  	testSchema4 struct {
    40  		a  int8
    41  		ID int64 `ql:"name id"`
    42  		A  int8
    43  		b  int
    44  		B  int `ql:"-"`
    45  		c  bool
    46  		C  bool `ql:"name cc"`
    47  	}
    48  
    49  	testSchema5 struct {
    50  		I int `ql:"index x,uindex u"`
    51  	}
    52  
    53  	testSchema6 struct {
    54  		A string `ql:"index x"`
    55  	}
    56  
    57  	testSchema7 struct {
    58  		A int64
    59  		B string `ql:"uindex x"`
    60  		C bool
    61  	}
    62  
    63  	testSchema8 struct {
    64  		A bool
    65  		//B  int
    66  		C int8
    67  		D int16
    68  		E int32
    69  		F int64
    70  		//G  uint
    71  		H  uint8
    72  		I  uint16
    73  		J  uint32
    74  		K  uint64
    75  		L  float32
    76  		M  float64
    77  		N  complex64
    78  		O  complex128
    79  		P  []byte
    80  		Q  big.Int
    81  		R  big.Rat
    82  		S  string
    83  		T  time.Time
    84  		U  time.Duration
    85  		PA *bool
    86  		//PB *int
    87  		PC *int8
    88  		PD *int16
    89  		PE *int32
    90  		PF *int64
    91  		//PG *uint
    92  		PH *uint8
    93  		PI *uint16
    94  		PJ *uint32
    95  		PK *uint64
    96  		PL *float32
    97  		PM *float64
    98  		PN *complex64
    99  		PO *complex128
   100  		PP *[]byte
   101  		PQ *big.Int
   102  		PR *big.Rat
   103  		PS *string
   104  		PT *time.Time
   105  		PU *time.Duration
   106  	}
   107  
   108  	testSchema9 struct {
   109  		i              int
   110  		ID             int64  `ql:"index xID"`
   111  		Other          string `ql:"-"`
   112  		DepartmentName string `ql:"uindex xDepartmentName"`
   113  	}
   114  )
   115  
   116  const (
   117  	testSchemaSFFF = "begin transaction; create table if not exists testSchema (A int8); commit;"
   118  	testSchemaSFFT = "begin transaction; create table if not exists ql_testSchema (A int8); commit;"
   119  	testSchemaSFTF = "begin transaction; create table testSchema (A int8); commit;"
   120  	testSchemaSFTT = "begin transaction; create table ql_testSchema (A int8); commit;"
   121  	testSchemaSTFF = "create table if not exists testSchema (A int8)"
   122  	testSchemaSTFT = "create table if not exists ql_testSchema (A int8)"
   123  	testSchemaSTTF = "create table testSchema (A int8)"
   124  	testSchemaSTTT = "create table ql_testSchema (A int8)"
   125  	testSchema3S   = "begin transaction; create table if not exists testSchema3 (ID uint64, A int8, cc bool); commit;"
   126  	testSchema4S   = "begin transaction; create table if not exists testSchema4 (id int64, A int8, cc bool); commit;"
   127  	testSchema6S   = "create table testSchema6 (A string); create index x on testSchema6 (A);"
   128  	testSchema7S   = "begin transaction; create table testSchema7 (A int64, B string, C bool); create unique index x on testSchema7 (B); commit;"
   129  	testSchema8S   = `
   130  		begin transaction;
   131  			create table if not exists testSchema8 (
   132  				A  bool,
   133  				//B  int64,
   134  				C  int8,
   135  				D  int16,
   136  				E  int32,
   137  				F  int64,
   138  				//G  uint64,
   139  				H  uint8,
   140  				I  uint16,
   141  				J  uint32,
   142  				K  uint64,
   143  				L  float32,
   144  				M  float64,
   145  				N  complex64,
   146  				O  complex128,
   147  				P  blob,
   148  				Q  bigInt,
   149  				R  bigRat,
   150  				S  string,
   151  				T  time,
   152  				U  duration,
   153  				PA bool,
   154  				//PB int64,
   155  				PC int8,
   156  				PD int16,
   157  				PE int32,
   158  				PF int64,
   159  				//PG uint64,
   160  				PH uint8,
   161  				PI uint16,
   162  				PJ uint32,
   163  				PK uint64,
   164  				PL float32,
   165  				PM float64,
   166  				PN complex64,
   167  				PO complex128,
   168  				PP blob,
   169  				PQ bigInt,
   170  				PR bigRat,
   171  				PS string,
   172  				PT time,
   173  				PU  duration,
   174  			);
   175  		commit;`
   176  	testSchema9S = `
   177  		begin transaction;
   178  			create table if not exists testSchema9 (DepartmentName string);
   179  			create index if not exists xID on testSchema9 (id());
   180  			create unique index if not exists xDepartmentName on testSchema9 (DepartmentName);
   181  		commit;`
   182  )
   183  
   184  func TestSchema(t *testing.T) {
   185  	tab := []struct {
   186  		inst interface{}
   187  		name string
   188  		opts *SchemaOptions
   189  		err  bool
   190  		s    string
   191  	}{
   192  		// 0
   193  		{inst: nil, err: true},
   194  		{inst: interface{}(nil), err: true},
   195  		{testSchema{}, "", nil, false, testSchemaSFFF},
   196  		{testSchema{}, "", &SchemaOptions{}, false, testSchemaSFFF},
   197  		{testSchema{}, "", &SchemaOptions{KeepPrefix: true}, false, testSchemaSFFT},
   198  		// 5
   199  		{testSchema{}, "", &SchemaOptions{NoIfNotExists: true}, false, testSchemaSFTF},
   200  		{testSchema{}, "", &SchemaOptions{NoIfNotExists: true, KeepPrefix: true}, false, testSchemaSFTT},
   201  		{testSchema{}, "", &SchemaOptions{NoTransaction: true}, false, testSchemaSTFF},
   202  		{testSchema{}, "", &SchemaOptions{NoTransaction: true, KeepPrefix: true}, false, testSchemaSTFT},
   203  		{testSchema{}, "", &SchemaOptions{NoTransaction: true, NoIfNotExists: true}, false, testSchemaSTTF},
   204  		// 10
   205  		{testSchema{}, "", &SchemaOptions{NoTransaction: true, NoIfNotExists: true, KeepPrefix: true}, false, testSchemaSTTT},
   206  		{testSchema2{}, "", nil, true, ""},
   207  		{testSchema3{}, "", nil, false, testSchema3S},
   208  		{testSchema4{}, "", nil, false, testSchema4S},
   209  		{testSchema5{}, "", nil, true, ""},
   210  		// 15
   211  		{testSchema6{}, "", &SchemaOptions{NoTransaction: true, NoIfNotExists: true}, false, testSchema6S},
   212  		{testSchema7{}, "", &SchemaOptions{NoIfNotExists: true}, false, testSchema7S},
   213  		{testSchema8{}, "", nil, false, testSchema8S},
   214  		{&testSchema8{}, "", nil, false, testSchema8S},
   215  		{&testSchema9{}, "", nil, false, testSchema9S},
   216  	}
   217  
   218  	for iTest, test := range tab {
   219  		l, err := Schema(test.inst, test.name, test.opts)
   220  		if g, e := err != nil, test.err; g != e {
   221  			t.Fatal(iTest, g, e, err)
   222  		}
   223  
   224  		if err != nil {
   225  			t.Log(iTest, err)
   226  			continue
   227  		}
   228  
   229  		s, err := Compile(test.s)
   230  		if err != nil {
   231  			panic("internal error 055")
   232  		}
   233  
   234  		if g, e := l.String(), s.String(); g != e {
   235  			t.Fatalf("%d\n----\n%s\n----\n%s", iTest, g, e)
   236  		}
   237  	}
   238  }
   239  
   240  func ExampleSchema() {
   241  	type department struct {
   242  		a              int    // unexported -> ignored
   243  		ID             int64  `ql:"index xID"`
   244  		Other          string `xml:"-" ql:"-"` // ignored by QL tag
   245  		DepartmentName string `ql:"name Name, uindex xName" json:"foo"`
   246  		m              bool
   247  		HQ             int32
   248  		z              string
   249  	}
   250  
   251  	schema := MustSchema((*department)(nil), "", nil)
   252  	sel := MustCompile(`
   253  		SELECT * FROM __Table WHERE !hasPrefix(Name, "__") ORDER BY Name;
   254  		SELECT * FROM __Column WHERE !hasPrefix(TableName, "__") ORDER BY TableName, Ordinal;
   255  		SELECT * FROM __Index WHERE !hasPrefix(TableName, "__") ORDER BY Name, ColumnName;`,
   256  	)
   257  	fmt.Print(schema)
   258  
   259  	db, err := OpenMem()
   260  	if err != nil {
   261  		panic(err)
   262  	}
   263  
   264  	if _, _, err = db.Execute(NewRWCtx(), schema); err != nil {
   265  		panic(err)
   266  	}
   267  
   268  	rs, _, err := db.Execute(nil, sel)
   269  	if err != nil {
   270  		panic(err)
   271  	}
   272  
   273  	for _, rs := range rs {
   274  		fmt.Println("----")
   275  		if err = rs.Do(true, func(data []interface{}) (bool, error) {
   276  			fmt.Println(data)
   277  			return true, nil
   278  		}); err != nil {
   279  			panic(err)
   280  		}
   281  	}
   282  	// Output:
   283  	// BEGIN TRANSACTION;
   284  	// 	CREATE TABLE IF NOT EXISTS department (Name string, HQ int32);
   285  	// 	CREATE INDEX IF NOT EXISTS xID ON department (id());
   286  	// 	CREATE UNIQUE INDEX IF NOT EXISTS xName ON department (Name);
   287  	// COMMIT;
   288  	// ----
   289  	// [Name Schema]
   290  	// [department CREATE TABLE department (Name string, HQ int32);]
   291  	// ----
   292  	// [TableName Ordinal Name Type]
   293  	// [department 1 Name string]
   294  	// [department 2 HQ int32]
   295  	// ----
   296  	// [TableName ColumnName Name IsUnique]
   297  	// [department id() xID false]
   298  	// [department Name xName true]
   299  }
   300  
   301  func TestMarshal(t *testing.T) {
   302  	now := time.Now()
   303  	dur := time.Millisecond
   304  	schema8 := testSchema8{
   305  		A: true,
   306  		//B: 1,
   307  		C: 2,
   308  		D: 3,
   309  		E: 4,
   310  		F: 5,
   311  		//G: 6,
   312  		H: 7,
   313  		I: 8,
   314  		J: 9,
   315  		K: 10,
   316  		L: 11,
   317  		M: 12,
   318  		N: -1,
   319  		O: -2,
   320  		P: []byte("abc"),
   321  		Q: *big.NewInt(1),
   322  		R: *big.NewRat(3, 2),
   323  		S: "string",
   324  		T: now,
   325  		U: dur,
   326  	}
   327  	schema8.PA = &schema8.A
   328  	//schema8.PB = &schema8.B
   329  	schema8.PC = &schema8.C
   330  	schema8.PD = &schema8.D
   331  	schema8.PE = &schema8.E
   332  	schema8.PF = &schema8.F
   333  	//schema8.PG = &schema8.G
   334  	schema8.PH = &schema8.H
   335  	schema8.PI = &schema8.I
   336  	schema8.PJ = &schema8.J
   337  	schema8.PK = &schema8.K
   338  	schema8.PL = &schema8.L
   339  	schema8.PM = &schema8.M
   340  	schema8.PN = &schema8.N
   341  	schema8.PO = &schema8.O
   342  	schema8.PP = &schema8.P
   343  	schema8.PQ = &schema8.Q
   344  	schema8.PR = &schema8.R
   345  	schema8.PS = &schema8.S
   346  	schema8.PT = &schema8.T
   347  	schema8.PU = &schema8.U
   348  
   349  	type u int
   350  	tab := []struct {
   351  		inst interface{}
   352  		err  bool
   353  		r    []interface{}
   354  	}{
   355  		{42, true, nil},
   356  		{new(u), true, nil},
   357  		{testSchema8{}, false, []interface{}{
   358  			false,
   359  			//int64(0),
   360  			int8(0),
   361  			int16(0),
   362  			int32(0),
   363  			int64(0),
   364  			//uint64(0),
   365  			uint8(0),
   366  			uint16(0),
   367  			uint32(0),
   368  			uint64(0),
   369  			float32(0),
   370  			float64(0),
   371  			complex64(0),
   372  			complex128(0),
   373  			[]byte(nil),
   374  			big.Int{},
   375  			big.Rat{},
   376  			"",
   377  			time.Time{},
   378  			time.Duration(0),
   379  			nil,
   380  			//nil,
   381  			nil,
   382  			nil,
   383  			nil,
   384  			nil,
   385  			//nil,
   386  			nil,
   387  			nil,
   388  			nil,
   389  			nil,
   390  			nil,
   391  			nil,
   392  			nil,
   393  			nil,
   394  			nil,
   395  			nil,
   396  			nil,
   397  			nil,
   398  			nil,
   399  			nil,
   400  		}},
   401  		{&testSchema8{}, false, []interface{}{
   402  			false,
   403  			//int64(0),
   404  			int8(0),
   405  			int16(0),
   406  			int32(0),
   407  			int64(0),
   408  			//uint64(0),
   409  			uint8(0),
   410  			uint16(0),
   411  			uint32(0),
   412  			uint64(0),
   413  			float32(0),
   414  			float64(0),
   415  			complex64(0),
   416  			complex128(0),
   417  			[]byte(nil),
   418  			big.Int{},
   419  			big.Rat{},
   420  			"",
   421  			time.Time{},
   422  			time.Duration(0),
   423  			nil,
   424  			//nil,
   425  			nil,
   426  			nil,
   427  			nil,
   428  			nil,
   429  			//nil,
   430  			nil,
   431  			nil,
   432  			nil,
   433  			nil,
   434  			nil,
   435  			nil,
   436  			nil,
   437  			nil,
   438  			nil,
   439  			nil,
   440  			nil,
   441  			nil,
   442  			nil,
   443  			nil,
   444  		}},
   445  		{schema8, false, []interface{}{
   446  			true,
   447  			//int64(1),
   448  			int8(2),
   449  			int16(3),
   450  			int32(4),
   451  			int64(5),
   452  			//uint64(6),
   453  			uint8(7),
   454  			uint16(8),
   455  			uint32(9),
   456  			uint64(10),
   457  			float32(11),
   458  			float64(12),
   459  			complex64(-1),
   460  			complex128(-2),
   461  			[]byte("abc"),
   462  			*big.NewInt(1),
   463  			*big.NewRat(3, 2),
   464  			"string",
   465  			now,
   466  			dur,
   467  			true,
   468  			//int64(1),
   469  			int8(2),
   470  			int16(3),
   471  			int32(4),
   472  			int64(5),
   473  			//uint64(6),
   474  			uint8(7),
   475  			uint16(8),
   476  			uint32(9),
   477  			uint64(10),
   478  			float32(11),
   479  			float64(12),
   480  			complex64(-1),
   481  			complex128(-2),
   482  			[]byte("abc"),
   483  			*big.NewInt(1),
   484  			*big.NewRat(3, 2),
   485  			"string",
   486  			now,
   487  			dur,
   488  		}},
   489  		{&schema8, false, []interface{}{
   490  			true,
   491  			//int64(1),
   492  			int8(2),
   493  			int16(3),
   494  			int32(4),
   495  			int64(5),
   496  			//uint64(6),
   497  			uint8(7),
   498  			uint16(8),
   499  			uint32(9),
   500  			uint64(10),
   501  			float32(11),
   502  			float64(12),
   503  			complex64(-1),
   504  			complex128(-2),
   505  			[]byte("abc"),
   506  			*big.NewInt(1),
   507  			*big.NewRat(3, 2),
   508  			"string",
   509  			now,
   510  			dur,
   511  			true,
   512  			//int64(1),
   513  			int8(2),
   514  			int16(3),
   515  			int32(4),
   516  			int64(5),
   517  			//uint64(6),
   518  			uint8(7),
   519  			uint16(8),
   520  			uint32(9),
   521  			uint64(10),
   522  			float32(11),
   523  			float64(12),
   524  			complex64(-1),
   525  			complex128(-2),
   526  			[]byte("abc"),
   527  			*big.NewInt(1),
   528  			*big.NewRat(3, 2),
   529  			"string",
   530  			now,
   531  			dur,
   532  		}},
   533  	}
   534  	for iTest, test := range tab {
   535  		r, err := Marshal(test.inst)
   536  		if g, e := err != nil, test.err; g != e {
   537  			t.Fatal(iTest, g, e)
   538  		}
   539  
   540  		if err != nil {
   541  			t.Log(err)
   542  			continue
   543  		}
   544  
   545  		for i := 0; i < mathutil.Min(len(r), len(test.r)); i++ {
   546  			g, e := r[i], test.r[i]
   547  			use(e)
   548  			switch x := g.(type) {
   549  			case bool:
   550  				switch y := e.(type) {
   551  				case bool:
   552  					if x != y {
   553  						t.Fatal(iTest, x, y)
   554  					}
   555  				default:
   556  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   557  				}
   558  			case int:
   559  				switch y := e.(type) {
   560  				case int64:
   561  					if int64(x) != y {
   562  						t.Fatal(iTest, x, y)
   563  					}
   564  				default:
   565  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   566  				}
   567  			case int8:
   568  				switch y := e.(type) {
   569  				case int8:
   570  					if x != y {
   571  						t.Fatal(iTest, x, y)
   572  					}
   573  				default:
   574  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   575  				}
   576  			case int16:
   577  				switch y := e.(type) {
   578  				case int16:
   579  					if x != y {
   580  						t.Fatal(iTest, x, y)
   581  					}
   582  				default:
   583  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   584  				}
   585  			case int32:
   586  				switch y := e.(type) {
   587  				case int32:
   588  					if x != y {
   589  						t.Fatal(iTest, x, y)
   590  					}
   591  				default:
   592  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   593  				}
   594  			case int64:
   595  				switch y := e.(type) {
   596  				case int64:
   597  					if x != y {
   598  						t.Fatal(iTest, x, y)
   599  					}
   600  				default:
   601  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   602  				}
   603  			case uint:
   604  				switch y := e.(type) {
   605  				case uint64:
   606  					if uint64(x) != y {
   607  						t.Fatal(iTest, x, y)
   608  					}
   609  				default:
   610  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   611  				}
   612  			case uint8:
   613  				switch y := e.(type) {
   614  				case uint8:
   615  					if x != y {
   616  						t.Fatal(iTest, x, y)
   617  					}
   618  				default:
   619  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   620  				}
   621  			case uint16:
   622  				switch y := e.(type) {
   623  				case uint16:
   624  					if x != y {
   625  						t.Fatal(iTest, x, y)
   626  					}
   627  				default:
   628  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   629  				}
   630  			case uint32:
   631  				switch y := e.(type) {
   632  				case uint32:
   633  					if x != y {
   634  						t.Fatal(iTest, x, y)
   635  					}
   636  				default:
   637  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   638  				}
   639  			case uint64:
   640  				switch y := e.(type) {
   641  				case uint64:
   642  					if x != y {
   643  						t.Fatal(iTest, x, y)
   644  					}
   645  				default:
   646  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   647  				}
   648  			case float32:
   649  				switch y := e.(type) {
   650  				case float32:
   651  					if x != y {
   652  						t.Fatal(iTest, x, y)
   653  					}
   654  				default:
   655  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   656  				}
   657  			case float64:
   658  				switch y := e.(type) {
   659  				case float64:
   660  					if x != y {
   661  						t.Fatal(iTest, x, y)
   662  					}
   663  				default:
   664  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   665  				}
   666  			case complex64:
   667  				switch y := e.(type) {
   668  				case complex64:
   669  					if x != y {
   670  						t.Fatal(iTest, x, y)
   671  					}
   672  				default:
   673  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   674  				}
   675  			case complex128:
   676  				switch y := e.(type) {
   677  				case complex128:
   678  					if x != y {
   679  						t.Fatal(iTest, x, y)
   680  					}
   681  				default:
   682  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   683  				}
   684  			case []byte:
   685  				switch y := e.(type) {
   686  				case []byte:
   687  					if !bytes.Equal(x, y) {
   688  						t.Fatal(iTest, x, y)
   689  					}
   690  				default:
   691  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   692  				}
   693  			case big.Int:
   694  				switch y := e.(type) {
   695  				case big.Int:
   696  					if x.Cmp(&y) != 0 {
   697  						t.Fatal(iTest, &x, &y)
   698  					}
   699  				default:
   700  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   701  				}
   702  			case big.Rat:
   703  				switch y := e.(type) {
   704  				case big.Rat:
   705  					if x.Cmp(&y) != 0 {
   706  						t.Fatal(iTest, &x, &y)
   707  					}
   708  				default:
   709  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   710  				}
   711  			case string:
   712  				switch y := e.(type) {
   713  				case string:
   714  					if x != y {
   715  						t.Fatal(iTest, x, y)
   716  					}
   717  				default:
   718  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   719  				}
   720  			case time.Time:
   721  				switch y := e.(type) {
   722  				case time.Time:
   723  					if !x.Equal(y) {
   724  						t.Fatal(iTest, x, y)
   725  					}
   726  				default:
   727  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   728  				}
   729  			case time.Duration:
   730  				switch y := e.(type) {
   731  				case time.Duration:
   732  					if x != y {
   733  						t.Fatal(iTest, x, y)
   734  					}
   735  				default:
   736  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   737  				}
   738  			case nil:
   739  				switch y := e.(type) {
   740  				case nil:
   741  					// ok
   742  				default:
   743  					t.Fatalf("%d: %T <-> %T", iTest, x, y)
   744  				}
   745  			default:
   746  				panic(fmt.Errorf("%T", x))
   747  			}
   748  		}
   749  
   750  		if g, e := len(r), len(test.r); g != e {
   751  			t.Fatal(iTest, g, e)
   752  		}
   753  
   754  	}
   755  }
   756  
   757  func ExampleMarshal() {
   758  	type myInt int16
   759  
   760  	type myString string
   761  
   762  	type item struct {
   763  		ID   int64
   764  		Name myString
   765  		Qty  *myInt // pointer enables nil values
   766  		Bar  int8
   767  	}
   768  
   769  	schema := MustSchema((*item)(nil), "", nil)
   770  	ins := MustCompile(`
   771  		BEGIN TRANSACTION;
   772  			INSERT INTO item VALUES($1, $2, $3);
   773  		COMMIT;`,
   774  	)
   775  
   776  	db, err := OpenMem()
   777  	if err != nil {
   778  		panic(err)
   779  	}
   780  
   781  	ctx := NewRWCtx()
   782  	if _, _, err := db.Execute(ctx, schema); err != nil {
   783  		panic(err)
   784  	}
   785  
   786  	if _, _, err := db.Execute(ctx, ins, MustMarshal(&item{Name: "foo", Bar: -1})...); err != nil {
   787  		panic(err)
   788  	}
   789  
   790  	q := myInt(42)
   791  	if _, _, err := db.Execute(ctx, ins, MustMarshal(&item{Name: "bar", Qty: &q})...); err != nil {
   792  		panic(err)
   793  	}
   794  
   795  	rs, _, err := db.Run(nil, "SELECT * FROM item ORDER BY id();")
   796  	if err != nil {
   797  		panic(err)
   798  	}
   799  
   800  	if err = rs[0].Do(true, func(data []interface{}) (bool, error) {
   801  		fmt.Println(data)
   802  		return true, nil
   803  	}); err != nil {
   804  		panic(err)
   805  	}
   806  	// Output:
   807  	// [Name Qty Bar]
   808  	// [foo <nil> -1]
   809  	// [bar 42 0]
   810  }
   811  
   812  func TestUnmarshal0(t *testing.T) {
   813  	type t1 struct {
   814  		I, J int64
   815  	}
   816  
   817  	// ---- value field
   818  	v1 := &t1{-1, -2}
   819  	if err := Unmarshal(v1, []interface{}{int64(42), int64(314)}); err != nil {
   820  		t.Fatal(err)
   821  	}
   822  
   823  	if g, e := v1.I, int64(42); g != e {
   824  		t.Fatal(g, e)
   825  	}
   826  
   827  	if g, e := v1.J, int64(314); g != e {
   828  		t.Fatal(g, e)
   829  	}
   830  
   831  	type t2 struct {
   832  		P *int64
   833  	}
   834  
   835  	// ---- nil into nil ptr field
   836  	v2 := &t2{P: nil}
   837  	if err := Unmarshal(v2, []interface{}{nil}); err != nil {
   838  		t.Fatal(err)
   839  	}
   840  
   841  	if g, e := v2.P, (*int64)(nil); g != e {
   842  		t.Fatal(g, e)
   843  	}
   844  
   845  	v2 = &t2{P: nil}
   846  	if err := Unmarshal(v2, []interface{}{interface{}(nil)}); err != nil {
   847  		t.Fatal(err)
   848  	}
   849  
   850  	if g, e := v2.P, (*int64)(nil); g != e {
   851  		t.Fatal(g, e)
   852  	}
   853  
   854  	// ---- nil into non nil ptr field
   855  	i := int64(42)
   856  	v2 = &t2{P: &i}
   857  	if err := Unmarshal(v2, []interface{}{nil}); err != nil {
   858  		t.Fatal(err)
   859  	}
   860  
   861  	if g, e := v2.P, (*int64)(nil); g != e {
   862  		t.Fatal(g, e)
   863  	}
   864  
   865  	if g, e := i, int64(42); g != e {
   866  		t.Fatal(g, e)
   867  	}
   868  
   869  	v2 = &t2{P: &i}
   870  	if err := Unmarshal(v2, []interface{}{interface{}(nil)}); err != nil {
   871  		t.Fatal(err)
   872  	}
   873  
   874  	if g, e := v2.P, (*int64)(nil); g != e {
   875  		t.Fatal(g, e)
   876  	}
   877  
   878  	if g, e := i, int64(42); g != e {
   879  		t.Fatal(g, e)
   880  	}
   881  
   882  	// ---- non nil value into non nil ptr field
   883  	i = 42
   884  	v2 = &t2{P: &i}
   885  	if err := Unmarshal(v2, []interface{}{int64(314)}); err != nil {
   886  		t.Fatal(err)
   887  	}
   888  
   889  	if g, e := v2.P, &i; g != e {
   890  		t.Fatal(g, e)
   891  	}
   892  
   893  	if g, e := i, int64(314); g != e {
   894  		t.Fatal(g, e)
   895  	}
   896  
   897  	// ---- non nil value into nil ptr field
   898  	v2 = &t2{P: nil}
   899  	if err := Unmarshal(v2, []interface{}{int64(314)}); err != nil {
   900  		t.Fatal(err)
   901  	}
   902  
   903  	if g, e := v2.P != nil, true; g != e {
   904  		t.Fatal(g, e)
   905  	}
   906  
   907  	if g, e := *v2.P, int64(314); g != e {
   908  		t.Fatal(g, e)
   909  	}
   910  }
   911  
   912  func TestUnmarshal(t *testing.T) {
   913  	type myString string
   914  
   915  	type t1 struct {
   916  		A bool
   917  		B myString
   918  	}
   919  
   920  	type t2 struct {
   921  		A  bool
   922  		ID int64
   923  		B  myString
   924  	}
   925  
   926  	f := func(v interface{}) int64 {
   927  		if x, ok := v.(*t2); ok {
   928  			return x.ID
   929  		}
   930  
   931  		return -1
   932  	}
   933  
   934  	tab := []struct {
   935  		inst interface{}
   936  		data []interface{}
   937  		err  bool
   938  	}{
   939  		// 0
   940  		{t1{}, []interface{}{true, "foo"}, true},      // not a ptr
   941  		{&t1{}, []interface{}{true}, true},            // too few values
   942  		{&t1{}, []interface{}{"foo"}, true},           // too few values
   943  		{&t1{}, []interface{}{true, "foo", 42}, true}, // too many values
   944  		{&t1{}, []interface{}{"foo", true, 42}, true}, // too many values
   945  		// 5
   946  		{&t1{}, []interface{}{true, "foo"}, false},
   947  		{&t1{}, []interface{}{false, "bar"}, false},
   948  		{&t1{}, []interface{}{"bar", "baz"}, true},
   949  		{&t1{}, []interface{}{true, 42.7}, true},
   950  		{&t2{}, []interface{}{1}, true}, // too few values
   951  		// 10
   952  		{&t2{}, []interface{}{1, 2, 3, 4}, true}, // too many values
   953  		{&t2{}, []interface{}{false, int64(314), "foo"}, false},
   954  		{&t2{}, []interface{}{true, int64(42), "foo"}, false},
   955  		{&t2{}, []interface{}{false, "foo"}, false},
   956  		// 15
   957  		{&t2{}, []interface{}{true, "foo"}, false},
   958  	}
   959  
   960  	for iTest, test := range tab {
   961  		inst := test.inst
   962  		err := Unmarshal(inst, test.data)
   963  		if g, e := err != nil, test.err; g != e {
   964  			t.Fatal(iTest, g, e)
   965  		}
   966  
   967  		if err != nil {
   968  			t.Log(iTest, err)
   969  			continue
   970  		}
   971  
   972  		data, err := Marshal(inst)
   973  		if err != nil {
   974  			t.Fatal(iTest, err)
   975  		}
   976  
   977  		if g, e := len(data), len(test.data); g > e {
   978  			t.Fatal(iTest, g, e)
   979  		}
   980  
   981  		j := 0
   982  		for _, v := range data {
   983  			v2 := test.data[j]
   984  			j++
   985  			if _, ok := v2.(int64); ok {
   986  				if g, e := f(inst), v2; g != e {
   987  					t.Fatal(iTest, g, e)
   988  				}
   989  
   990  				continue
   991  			}
   992  
   993  			if g, e := v, v2; g != e {
   994  				t.Fatal(iTest, g, e)
   995  			}
   996  		}
   997  	}
   998  }
   999  
  1000  func ExampleUnmarshal() {
  1001  	type myString string
  1002  
  1003  	type row struct {
  1004  		ID int64
  1005  		S  myString
  1006  		P  *int64
  1007  	}
  1008  
  1009  	schema := MustSchema((*row)(nil), "", nil)
  1010  	ins := MustCompile(`
  1011  		BEGIN TRANSACTION;
  1012  			INSERT INTO row VALUES($1, $2);
  1013  		COMMIT;`,
  1014  	)
  1015  	sel := MustCompile(`
  1016  		SELECT id(), S, P FROM row ORDER by id();
  1017  		SELECT * FROM row ORDER by id();`,
  1018  	)
  1019  
  1020  	db, err := OpenMem()
  1021  	if err != nil {
  1022  		panic(err)
  1023  	}
  1024  
  1025  	ctx := NewRWCtx()
  1026  	if _, _, err = db.Execute(ctx, schema); err != nil {
  1027  		panic(err)
  1028  	}
  1029  
  1030  	r := &row{S: "foo"}
  1031  	if _, _, err = db.Execute(ctx, ins, MustMarshal(r)...); err != nil {
  1032  		panic(err)
  1033  	}
  1034  
  1035  	i42 := int64(42)
  1036  	r = &row{S: "bar", P: &i42}
  1037  	if _, _, err = db.Execute(ctx, ins, MustMarshal(r)...); err != nil {
  1038  		panic(err)
  1039  	}
  1040  
  1041  	rs, _, err := db.Execute(nil, sel)
  1042  	if err != nil {
  1043  		panic(err)
  1044  	}
  1045  
  1046  	for _, rs := range rs {
  1047  		fmt.Println("----")
  1048  		if err := rs.Do(false, func(data []interface{}) (bool, error) {
  1049  			r := &row{}
  1050  			if err := Unmarshal(r, data); err != nil {
  1051  				return false, err
  1052  			}
  1053  
  1054  			fmt.Printf("ID %d, S %q, P ", r.ID, r.S)
  1055  			switch r.P == nil {
  1056  			case true:
  1057  				fmt.Println("<nil>")
  1058  			default:
  1059  				fmt.Println(*r.P)
  1060  			}
  1061  			return true, nil
  1062  		}); err != nil {
  1063  			panic(err)
  1064  		}
  1065  	}
  1066  	// Output:
  1067  	// ----
  1068  	// ID 1, S "foo", P <nil>
  1069  	// ID 2, S "bar", P 42
  1070  	// ----
  1071  	// ID 0, S "foo", P <nil>
  1072  	// ID 0, S "bar", P 42
  1073  }