github.com/mithrandie/csvq@v1.18.1/lib/query/view_test.go (about)

     1  package query
     2  
     3  import (
     4  	"context"
     5  	"reflect"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/mithrandie/csvq/lib/parser"
    10  	"github.com/mithrandie/csvq/lib/value"
    11  )
    12  
    13  func TestNewViewFromGroupedRecord(t *testing.T) {
    14  	fr := ReferenceRecord{
    15  		view: &View{
    16  			Header: NewHeaderWithId("table1", []string{"column1", "column2"}),
    17  			RecordSet: []Record{
    18  				{
    19  					NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(2), value.NewInteger(3)}),
    20  					NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(2), value.NewInteger(3)}),
    21  					NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str2"), value.NewString("str3")}),
    22  				},
    23  			},
    24  		},
    25  		recordIndex: 0,
    26  		cache:       NewFieldIndexCache(10, LimitToUseFieldIndexSliceChache),
    27  	}
    28  	expect := &View{
    29  		Header: NewHeaderWithId("table1", []string{"column1", "column2"}),
    30  		RecordSet: []Record{
    31  			{NewCell(value.NewInteger(1)), NewCell(value.NewInteger(1)), NewCell(value.NewString("str1"))},
    32  			{NewCell(value.NewInteger(2)), NewCell(value.NewInteger(2)), NewCell(value.NewString("str2"))},
    33  			{NewCell(value.NewInteger(3)), NewCell(value.NewInteger(3)), NewCell(value.NewString("str3"))},
    34  		},
    35  	}
    36  
    37  	result, _ := NewViewFromGroupedRecord(context.Background(), TestTx.Flags, fr)
    38  	if !reflect.DeepEqual(result, expect) {
    39  		t.Errorf("result = %v, want %v", result, expect)
    40  	}
    41  }
    42  
    43  var viewWhereTests = []struct {
    44  	Name   string
    45  	CPU    int
    46  	View   *View
    47  	Where  parser.WhereClause
    48  	Result RecordSet
    49  	Error  string
    50  }{
    51  	{
    52  		Name: "Where",
    53  		View: &View{
    54  			Header: NewHeaderWithId("table1", []string{"column1", "column2"}),
    55  			RecordSet: RecordSet{
    56  				NewRecordWithId(1, []value.Primary{
    57  					value.NewString("1"),
    58  					value.NewString("str1"),
    59  				}),
    60  				NewRecordWithId(2, []value.Primary{
    61  					value.NewString("2"),
    62  					value.NewString("str2"),
    63  				}),
    64  				NewRecordWithId(3, []value.Primary{
    65  					value.NewString("3"),
    66  					value.NewString("str3"),
    67  				}),
    68  			},
    69  		},
    70  		Where: parser.WhereClause{
    71  			Filter: parser.Comparison{
    72  				LHS:      parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
    73  				RHS:      parser.NewIntegerValueFromString("2"),
    74  				Operator: parser.Token{Token: '=', Literal: "="},
    75  			},
    76  		},
    77  		Result: RecordSet{
    78  			NewRecordWithId(2, []value.Primary{
    79  				value.NewString("2"),
    80  				value.NewString("str2"),
    81  			}),
    82  		},
    83  	},
    84  	{
    85  		Name: "Where in Multi Threading",
    86  		CPU:  3,
    87  		View: &View{
    88  			Header: NewHeaderWithId("table1", []string{"column1", "column2"}),
    89  			RecordSet: RecordSet{
    90  				NewRecordWithId(1, []value.Primary{
    91  					value.NewString("1"),
    92  					value.NewString("str1"),
    93  				}),
    94  				NewRecordWithId(2, []value.Primary{
    95  					value.NewString("2"),
    96  					value.NewString("str2"),
    97  				}),
    98  				NewRecordWithId(3, []value.Primary{
    99  					value.NewString("3"),
   100  					value.NewString("str3"),
   101  				}),
   102  			},
   103  		},
   104  		Where: parser.WhereClause{
   105  			Filter: parser.Comparison{
   106  				LHS:      parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
   107  				RHS:      parser.NewIntegerValueFromString("2"),
   108  				Operator: parser.Token{Token: '=', Literal: "="},
   109  			},
   110  		},
   111  		Result: RecordSet{
   112  			NewRecordWithId(2, []value.Primary{
   113  				value.NewString("2"),
   114  				value.NewString("str2"),
   115  			}),
   116  		},
   117  	},
   118  	{
   119  		Name: "Where Filter Error",
   120  		View: &View{
   121  			Header: NewHeaderWithId("table1", []string{"column1", "column2"}),
   122  			RecordSet: []Record{
   123  				NewRecordWithId(1, []value.Primary{
   124  					value.NewString("1"),
   125  					value.NewString("str1"),
   126  				}),
   127  				NewRecordWithId(2, []value.Primary{
   128  					value.NewString("2"),
   129  					value.NewString("str2"),
   130  				}),
   131  				NewRecordWithId(3, []value.Primary{
   132  					value.NewString("3"),
   133  					value.NewString("str3"),
   134  				}),
   135  			},
   136  		},
   137  		Where: parser.WhereClause{
   138  			Filter: parser.Comparison{
   139  				LHS:      parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}},
   140  				RHS:      parser.NewIntegerValueFromString("2"),
   141  				Operator: parser.Token{Token: '=', Literal: "="},
   142  			},
   143  		},
   144  		Error: "field notexist does not exist",
   145  	},
   146  }
   147  
   148  func TestView_Where(t *testing.T) {
   149  	defer initFlag(TestTx.Flags)
   150  
   151  	scope := NewReferenceScope(TestTx)
   152  	ctx := context.Background()
   153  	for _, v := range viewWhereTests {
   154  		TestTx.Flags.CPU = 1
   155  		if v.CPU != 0 {
   156  			TestTx.Flags.CPU = v.CPU
   157  		}
   158  
   159  		err := v.View.Where(ctx, scope, v.Where)
   160  		if err != nil {
   161  			if len(v.Error) < 1 {
   162  				t.Errorf("%s: unexpected error %q", v.Name, err)
   163  			} else if err.Error() != v.Error {
   164  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
   165  			}
   166  			continue
   167  		}
   168  		if 0 < len(v.Error) {
   169  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
   170  			continue
   171  		}
   172  		if !reflect.DeepEqual(v.View.RecordSet, v.Result) {
   173  			t.Errorf("%s: result = %s, want %s", v.Name, v.View.RecordSet, v.Result)
   174  		}
   175  	}
   176  }
   177  
   178  var viewGroupByTests = []struct {
   179  	Name       string
   180  	View       *View
   181  	GroupBy    parser.GroupByClause
   182  	Result     *View
   183  	IsGrouped  bool
   184  	GroupItems []string
   185  	Error      string
   186  }{
   187  	{
   188  		Name: "Group By",
   189  		View: &View{
   190  			Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}),
   191  			RecordSet: []Record{
   192  				NewRecordWithId(1, []value.Primary{
   193  					value.NewString("1"),
   194  					value.NewString("str1"),
   195  					value.NewString("group1"),
   196  				}),
   197  				NewRecordWithId(2, []value.Primary{
   198  					value.NewString("2"),
   199  					value.NewString("str2"),
   200  					value.NewString("group2"),
   201  				}),
   202  				NewRecordWithId(3, []value.Primary{
   203  					value.NewString("3"),
   204  					value.NewString("str3"),
   205  					value.NewString("group1"),
   206  				}),
   207  				NewRecordWithId(4, []value.Primary{
   208  					value.NewString("4"),
   209  					value.NewString("str4"),
   210  					value.NewString("group2"),
   211  				}),
   212  			},
   213  		},
   214  		GroupBy: parser.GroupByClause{
   215  			Items: []parser.QueryExpression{
   216  				parser.FieldReference{Column: parser.Identifier{Literal: "column3"}},
   217  			},
   218  		},
   219  		Result: &View{
   220  			Header: []HeaderField{
   221  				{
   222  					View:   "table1",
   223  					Column: InternalIdColumn,
   224  				},
   225  				{
   226  					View:        "table1",
   227  					Column:      "column1",
   228  					Number:      1,
   229  					IsFromTable: true,
   230  				},
   231  				{
   232  					View:        "table1",
   233  					Column:      "column2",
   234  					Number:      2,
   235  					IsFromTable: true,
   236  				},
   237  				{
   238  					View:        "table1",
   239  					Column:      "column3",
   240  					Number:      3,
   241  					IsFromTable: true,
   242  					IsGroupKey:  true,
   243  				},
   244  			},
   245  			RecordSet: []Record{
   246  				{
   247  					NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(3)}),
   248  					NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("3")}),
   249  					NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str3")}),
   250  					NewGroupCell([]value.Primary{value.NewString("group1"), value.NewString("group1")}),
   251  				},
   252  				{
   253  					NewGroupCell([]value.Primary{value.NewInteger(2), value.NewInteger(4)}),
   254  					NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}),
   255  					NewGroupCell([]value.Primary{value.NewString("str2"), value.NewString("str4")}),
   256  					NewGroupCell([]value.Primary{value.NewString("group2"), value.NewString("group2")}),
   257  				},
   258  			},
   259  			isGrouped: true,
   260  		},
   261  	},
   262  	{
   263  		Name: "Group By With ColumnNumber",
   264  		View: &View{
   265  			Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}),
   266  			RecordSet: []Record{
   267  				NewRecordWithId(1, []value.Primary{
   268  					value.NewString("1"),
   269  					value.NewString("str1"),
   270  					value.NewString("group1"),
   271  				}),
   272  				NewRecordWithId(2, []value.Primary{
   273  					value.NewString("2"),
   274  					value.NewString("str2"),
   275  					value.NewString("group2"),
   276  				}),
   277  				NewRecordWithId(3, []value.Primary{
   278  					value.NewString("3"),
   279  					value.NewString("str3"),
   280  					value.NewString("group1"),
   281  				}),
   282  				NewRecordWithId(4, []value.Primary{
   283  					value.NewString("4"),
   284  					value.NewString("str4"),
   285  					value.NewString("group2"),
   286  				}),
   287  			},
   288  		},
   289  		GroupBy: parser.GroupByClause{
   290  			Items: []parser.QueryExpression{
   291  				parser.ColumnNumber{View: parser.Identifier{Literal: "table1"}, Number: value.NewInteger(3)},
   292  			},
   293  		},
   294  		Result: &View{
   295  			Header: []HeaderField{
   296  				{
   297  					View:   "table1",
   298  					Column: InternalIdColumn,
   299  				},
   300  				{
   301  					View:        "table1",
   302  					Column:      "column1",
   303  					Number:      1,
   304  					IsFromTable: true,
   305  				},
   306  				{
   307  					View:        "table1",
   308  					Column:      "column2",
   309  					Number:      2,
   310  					IsFromTable: true,
   311  				},
   312  				{
   313  					View:        "table1",
   314  					Column:      "column3",
   315  					Number:      3,
   316  					IsFromTable: true,
   317  					IsGroupKey:  true,
   318  				},
   319  			},
   320  			RecordSet: []Record{
   321  				{
   322  					NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(3)}),
   323  					NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("3")}),
   324  					NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str3")}),
   325  					NewGroupCell([]value.Primary{value.NewString("group1"), value.NewString("group1")}),
   326  				},
   327  				{
   328  					NewGroupCell([]value.Primary{value.NewInteger(2), value.NewInteger(4)}),
   329  					NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}),
   330  					NewGroupCell([]value.Primary{value.NewString("str2"), value.NewString("str4")}),
   331  					NewGroupCell([]value.Primary{value.NewString("group2"), value.NewString("group2")}),
   332  				},
   333  			},
   334  			isGrouped: true,
   335  		},
   336  	},
   337  	{
   338  		Name: "Group By Evaluation Error",
   339  		View: &View{
   340  			Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}),
   341  			RecordSet: []Record{
   342  				NewRecordWithId(1, []value.Primary{
   343  					value.NewString("1"),
   344  					value.NewString("str1"),
   345  					value.NewString("group1"),
   346  				}),
   347  				NewRecordWithId(2, []value.Primary{
   348  					value.NewString("2"),
   349  					value.NewString("str2"),
   350  					value.NewString("group2"),
   351  				}),
   352  				NewRecordWithId(3, []value.Primary{
   353  					value.NewString("3"),
   354  					value.NewString("str3"),
   355  					value.NewString("group1"),
   356  				}),
   357  				NewRecordWithId(4, []value.Primary{
   358  					value.NewString("4"),
   359  					value.NewString("str4"),
   360  					value.NewString("group2"),
   361  				}),
   362  			},
   363  		},
   364  		GroupBy: parser.GroupByClause{
   365  			Items: []parser.QueryExpression{
   366  				parser.ColumnNumber{View: parser.Identifier{Literal: "table1"}, Number: value.NewInteger(0)},
   367  			},
   368  		},
   369  		Error: "field table1.0 does not exist",
   370  	},
   371  	{
   372  		Name: "Group By Empty Record",
   373  		View: &View{
   374  			Header:    NewHeaderWithId("table1", []string{"column1", "column2", "column3"}),
   375  			RecordSet: []Record{},
   376  		},
   377  		GroupBy: parser.GroupByClause{
   378  			Items: []parser.QueryExpression{
   379  				parser.FieldReference{Column: parser.Identifier{Literal: "column3"}},
   380  			},
   381  		},
   382  		Result: &View{
   383  			Header: []HeaderField{
   384  				{
   385  					View:   "table1",
   386  					Column: InternalIdColumn,
   387  				},
   388  				{
   389  					View:        "table1",
   390  					Column:      "column1",
   391  					Number:      1,
   392  					IsFromTable: true,
   393  				},
   394  				{
   395  					View:        "table1",
   396  					Column:      "column2",
   397  					Number:      2,
   398  					IsFromTable: true,
   399  				},
   400  				{
   401  					View:        "table1",
   402  					Column:      "column3",
   403  					Number:      3,
   404  					IsFromTable: true,
   405  					IsGroupKey:  true,
   406  				},
   407  			},
   408  			RecordSet: []Record{},
   409  			isGrouped: true,
   410  		},
   411  	},
   412  	{
   413  		Name: "Group By Empty Record with No Condition",
   414  		View: &View{
   415  			Header:    NewHeaderWithId("table1", []string{"column1", "column2", "column3"}),
   416  			RecordSet: []Record{},
   417  		},
   418  		GroupBy: parser.GroupByClause{
   419  			Items: nil,
   420  		},
   421  		Result: &View{
   422  			Header: []HeaderField{
   423  				{
   424  					View:   "table1",
   425  					Column: InternalIdColumn,
   426  				},
   427  				{
   428  					View:        "table1",
   429  					Column:      "column1",
   430  					Number:      1,
   431  					IsFromTable: true,
   432  				},
   433  				{
   434  					View:        "table1",
   435  					Column:      "column2",
   436  					Number:      2,
   437  					IsFromTable: true,
   438  				},
   439  				{
   440  					View:        "table1",
   441  					Column:      "column3",
   442  					Number:      3,
   443  					IsFromTable: true,
   444  				},
   445  			},
   446  			RecordSet: []Record{},
   447  			isGrouped: true,
   448  		},
   449  	},
   450  }
   451  
   452  func TestView_GroupBy(t *testing.T) {
   453  	scope := NewReferenceScope(TestTx)
   454  	ctx := context.Background()
   455  	for _, v := range viewGroupByTests {
   456  		err := v.View.GroupBy(ctx, scope, v.GroupBy)
   457  		if err != nil {
   458  			if len(v.Error) < 1 {
   459  				t.Errorf("%s: unexpected error %q", v.Name, err)
   460  			} else if err.Error() != v.Error {
   461  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
   462  			}
   463  			continue
   464  		}
   465  		if 0 < len(v.Error) {
   466  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
   467  			continue
   468  		}
   469  		if !reflect.DeepEqual(v.View, v.Result) {
   470  			t.Errorf("%s: result = %v, want %v", v.Name, v.View, v.Result)
   471  		}
   472  	}
   473  }
   474  
   475  var viewHavingTests = []struct {
   476  	Name   string
   477  	View   *View
   478  	Having parser.HavingClause
   479  	Result RecordSet
   480  	Error  string
   481  }{
   482  	{
   483  		Name: "Having",
   484  		View: &View{
   485  			Header: []HeaderField{
   486  				{
   487  					View:   "table1",
   488  					Column: InternalIdColumn,
   489  				},
   490  				{
   491  					View:        "table1",
   492  					Column:      "column1",
   493  					IsFromTable: true,
   494  				},
   495  				{
   496  					View:        "table1",
   497  					Column:      "column2",
   498  					IsFromTable: true,
   499  				},
   500  				{
   501  					View:        "table1",
   502  					Column:      "column3",
   503  					IsFromTable: true,
   504  					IsGroupKey:  true,
   505  				},
   506  			},
   507  			isGrouped: true,
   508  			RecordSet: RecordSet{
   509  				{
   510  					NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("3")}),
   511  					NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("3")}),
   512  					NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str3")}),
   513  					NewGroupCell([]value.Primary{value.NewString("group1"), value.NewString("group1")}),
   514  				},
   515  				{
   516  					NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}),
   517  					NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}),
   518  					NewGroupCell([]value.Primary{value.NewString("str2"), value.NewString("str4")}),
   519  					NewGroupCell([]value.Primary{value.NewString("group2"), value.NewString("group2")}),
   520  				},
   521  			},
   522  		},
   523  		Having: parser.HavingClause{
   524  			Filter: parser.Comparison{
   525  				LHS: parser.AggregateFunction{
   526  					Name:     "sum",
   527  					Distinct: parser.Token{},
   528  					Args: []parser.QueryExpression{
   529  						parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
   530  					},
   531  				},
   532  				RHS:      parser.NewIntegerValueFromString("5"),
   533  				Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: ">"},
   534  			},
   535  		},
   536  		Result: RecordSet{
   537  			{
   538  				NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}),
   539  				NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}),
   540  				NewGroupCell([]value.Primary{value.NewString("str2"), value.NewString("str4")}),
   541  				NewGroupCell([]value.Primary{value.NewString("group2"), value.NewString("group2")}),
   542  			},
   543  		},
   544  	},
   545  	{
   546  		Name: "Having Filter Error",
   547  		View: &View{
   548  			Header: []HeaderField{
   549  				{
   550  					View:   "table1",
   551  					Column: InternalIdColumn,
   552  				},
   553  				{
   554  					View:        "table1",
   555  					Column:      "column1",
   556  					IsFromTable: true,
   557  				},
   558  				{
   559  					View:        "table1",
   560  					Column:      "column2",
   561  					IsFromTable: true,
   562  				},
   563  				{
   564  					View:        "table1",
   565  					Column:      "column3",
   566  					IsFromTable: true,
   567  					IsGroupKey:  true,
   568  				},
   569  			},
   570  			isGrouped: true,
   571  			RecordSet: RecordSet{
   572  				{
   573  					NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("3")}),
   574  					NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("3")}),
   575  					NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str3")}),
   576  					NewGroupCell([]value.Primary{value.NewString("group1"), value.NewString("group1")}),
   577  				},
   578  				{
   579  					NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}),
   580  					NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}),
   581  					NewGroupCell([]value.Primary{value.NewString("str2"), value.NewString("str4")}),
   582  					NewGroupCell([]value.Primary{value.NewString("group2"), value.NewString("group2")}),
   583  				},
   584  			},
   585  		},
   586  		Having: parser.HavingClause{
   587  			Filter: parser.Comparison{
   588  				LHS: parser.AggregateFunction{
   589  					Name:     "sum",
   590  					Distinct: parser.Token{},
   591  					Args: []parser.QueryExpression{
   592  						parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}},
   593  					},
   594  				},
   595  				RHS:      parser.NewIntegerValueFromString("5"),
   596  				Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: ">"},
   597  			},
   598  		},
   599  		Error: "field notexist does not exist",
   600  	},
   601  	{
   602  		Name: "Having Not Grouped",
   603  		View: &View{
   604  			Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}),
   605  			RecordSet: RecordSet{
   606  				NewRecordWithId(1, []value.Primary{
   607  					value.NewString("2"),
   608  					value.NewString("str2"),
   609  					value.NewString("group2"),
   610  				}),
   611  				NewRecordWithId(2, []value.Primary{
   612  					value.NewString("4"),
   613  					value.NewString("str4"),
   614  					value.NewString("group2"),
   615  				}),
   616  			},
   617  		},
   618  		Having: parser.HavingClause{
   619  			Filter: parser.Comparison{
   620  				LHS: parser.AggregateFunction{
   621  					Name:     "sum",
   622  					Distinct: parser.Token{},
   623  					Args: []parser.QueryExpression{
   624  						parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
   625  					},
   626  				},
   627  				RHS:      parser.NewIntegerValueFromString("5"),
   628  				Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: ">"},
   629  			},
   630  		},
   631  		Result: RecordSet{
   632  			{
   633  				NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(2)}),
   634  				NewGroupCell([]value.Primary{value.NewString("2"), value.NewString("4")}),
   635  				NewGroupCell([]value.Primary{value.NewString("str2"), value.NewString("str4")}),
   636  				NewGroupCell([]value.Primary{value.NewString("group2"), value.NewString("group2")}),
   637  			},
   638  		},
   639  	},
   640  	{
   641  		Name: "Having All RecordSet Filter Error",
   642  		View: &View{
   643  			Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}),
   644  			RecordSet: RecordSet{
   645  				NewRecordWithId(1, []value.Primary{
   646  					value.NewString("2"),
   647  					value.NewString("str2"),
   648  					value.NewString("group2"),
   649  				}),
   650  				NewRecordWithId(2, []value.Primary{
   651  					value.NewString("4"),
   652  					value.NewString("str4"),
   653  					value.NewString("group2"),
   654  				}),
   655  			},
   656  		},
   657  		Having: parser.HavingClause{
   658  			Filter: parser.Comparison{
   659  				LHS: parser.AggregateFunction{
   660  					Name:     "sum",
   661  					Distinct: parser.Token{},
   662  					Args: []parser.QueryExpression{
   663  						parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}},
   664  					},
   665  				},
   666  				RHS:      parser.NewIntegerValueFromString("5"),
   667  				Operator: parser.Token{Token: parser.COMPARISON_OP, Literal: ">"},
   668  			},
   669  		},
   670  		Error: "field notexist does not exist",
   671  	},
   672  }
   673  
   674  func TestView_Having(t *testing.T) {
   675  	scope := NewReferenceScope(TestTx)
   676  	ctx := context.Background()
   677  	for _, v := range viewHavingTests {
   678  		err := v.View.Having(ctx, scope, v.Having)
   679  		if err != nil {
   680  			if len(v.Error) < 1 {
   681  				t.Errorf("%s: unexpected error %q", v.Name, err)
   682  			} else if err.Error() != v.Error {
   683  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
   684  			}
   685  			continue
   686  		}
   687  		if 0 < len(v.Error) {
   688  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
   689  			continue
   690  		}
   691  		if !reflect.DeepEqual(v.View.RecordSet, v.Result) {
   692  			t.Errorf("%s: result = %s, want %s", v.Name, v.View.RecordSet, v.Result)
   693  		}
   694  	}
   695  }
   696  
   697  var viewSelectTests = []struct {
   698  	Name   string
   699  	View   *View
   700  	Scope  *ReferenceScope
   701  	Select parser.SelectClause
   702  	Result *View
   703  	Error  string
   704  }{
   705  	{
   706  		Name: "Select",
   707  		View: &View{
   708  			Header: []HeaderField{
   709  				{View: "table1", Column: InternalIdColumn},
   710  				{View: "table1", Column: "column1", Number: 1, IsFromTable: true},
   711  				{View: "table1", Column: "column2", Number: 2, IsFromTable: true},
   712  				{View: "table2", Column: InternalIdColumn},
   713  				{View: "table2", Column: "column3", Number: 1, IsFromTable: true},
   714  				{View: "table2", Column: "column4", Number: 2, IsFromTable: true},
   715  			},
   716  			RecordSet: []Record{
   717  				NewRecord([]value.Primary{
   718  					value.NewInteger(1),
   719  					value.NewString("1"),
   720  					value.NewString("str1"),
   721  					value.NewInteger(1),
   722  					value.NewString("2"),
   723  					value.NewString("str22"),
   724  				}),
   725  				NewRecord([]value.Primary{
   726  					value.NewInteger(1),
   727  					value.NewString("1"),
   728  					value.NewString("str1"),
   729  					value.NewInteger(2),
   730  					value.NewString("3"),
   731  					value.NewString("str33"),
   732  				}),
   733  				NewRecord([]value.Primary{
   734  					value.NewInteger(1),
   735  					value.NewString("1"),
   736  					value.NewString("str1"),
   737  					value.NewInteger(3),
   738  					value.NewString("1"),
   739  					value.NewString("str44"),
   740  				}),
   741  				NewRecord([]value.Primary{
   742  					value.NewInteger(2),
   743  					value.NewString("2"),
   744  					value.NewString("str2"),
   745  					value.NewInteger(1),
   746  					value.NewString("2"),
   747  					value.NewString("str22"),
   748  				}),
   749  			},
   750  		},
   751  		Select: parser.SelectClause{
   752  			Fields: []parser.QueryExpression{
   753  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, Alias: parser.Identifier{Literal: "c2"}},
   754  				parser.Field{Object: parser.AllColumns{}},
   755  				parser.Field{Object: parser.NewIntegerValueFromString("1"), Alias: parser.Identifier{Literal: "a"}},
   756  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, Alias: parser.Identifier{Literal: "c2a"}},
   757  				parser.Field{Object: parser.ColumnNumber{View: parser.Identifier{Literal: "table2"}, Number: value.NewInteger(1)}, Alias: parser.Identifier{Literal: "t21"}},
   758  				parser.Field{Object: parser.ColumnNumber{View: parser.Identifier{Literal: "table2"}, Number: value.NewInteger(1)}, Alias: parser.Identifier{Literal: "t21a"}},
   759  				parser.Field{Object: parser.PrimitiveType{
   760  					Literal: "2012-01-01",
   761  					Value:   value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())),
   762  				}},
   763  			},
   764  		},
   765  		Result: &View{
   766  			Header: []HeaderField{
   767  				{View: "table1", Column: InternalIdColumn},
   768  				{View: "table1", Column: "column1", Number: 1, IsFromTable: true},
   769  				{View: "table1", Column: "column2", Aliases: []string{"c2", "c2a"}, Number: 2, IsFromTable: true},
   770  				{View: "table2", Column: InternalIdColumn},
   771  				{View: "table2", Column: "column3", Aliases: []string{"t21", "t21a"}, Number: 1, IsFromTable: true},
   772  				{View: "table2", Column: "column4", Number: 2, IsFromTable: true},
   773  				{Identifier: "@__PT:I:1", Column: "1", Aliases: []string{"a"}},
   774  				{Identifier: "@__PT:D:2012-01-01T00:00:00Z", Column: "2012-01-01T00:00:00Z"},
   775  			},
   776  			RecordSet: []Record{
   777  				NewRecord([]value.Primary{
   778  					value.NewInteger(1),
   779  					value.NewString("1"),
   780  					value.NewString("str1"),
   781  					value.NewInteger(1),
   782  					value.NewString("2"),
   783  					value.NewString("str22"),
   784  					value.NewInteger(1),
   785  					value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())),
   786  				}),
   787  				NewRecord([]value.Primary{
   788  					value.NewInteger(1),
   789  					value.NewString("1"),
   790  					value.NewString("str1"),
   791  					value.NewInteger(2),
   792  					value.NewString("3"),
   793  					value.NewString("str33"),
   794  					value.NewInteger(1),
   795  					value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())),
   796  				}),
   797  				NewRecord([]value.Primary{
   798  					value.NewInteger(1),
   799  					value.NewString("1"),
   800  					value.NewString("str1"),
   801  					value.NewInteger(3),
   802  					value.NewString("1"),
   803  					value.NewString("str44"),
   804  					value.NewInteger(1),
   805  					value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())),
   806  				}),
   807  				NewRecord([]value.Primary{
   808  					value.NewInteger(2),
   809  					value.NewString("2"),
   810  					value.NewString("str2"),
   811  					value.NewInteger(1),
   812  					value.NewString("2"),
   813  					value.NewString("str22"),
   814  					value.NewInteger(1),
   815  					value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())),
   816  				}),
   817  			},
   818  			selectFields: []int{2, 1, 2, 4, 5, 6, 2, 4, 4, 7},
   819  		},
   820  	},
   821  	{
   822  		Name: "Select using Table Wildcard",
   823  		View: &View{
   824  			Header: []HeaderField{
   825  				{View: "table1", Column: InternalIdColumn},
   826  				{View: "table1", Column: "column1", Number: 1, IsFromTable: true},
   827  				{View: "table1", Column: "column2", Number: 2, IsFromTable: true},
   828  				{View: "table2", Column: InternalIdColumn},
   829  				{View: "table2", Column: "column3", Number: 1, IsFromTable: true},
   830  				{View: "table2", Column: "column4", Number: 2, IsFromTable: true},
   831  			},
   832  			RecordSet: []Record{
   833  				NewRecord([]value.Primary{
   834  					value.NewInteger(1),
   835  					value.NewString("1"),
   836  					value.NewString("str1"),
   837  					value.NewInteger(1),
   838  					value.NewString("2"),
   839  					value.NewString("str22"),
   840  				}),
   841  				NewRecord([]value.Primary{
   842  					value.NewInteger(1),
   843  					value.NewString("1"),
   844  					value.NewString("str1"),
   845  					value.NewInteger(2),
   846  					value.NewString("3"),
   847  					value.NewString("str33"),
   848  				}),
   849  				NewRecord([]value.Primary{
   850  					value.NewInteger(1),
   851  					value.NewString("1"),
   852  					value.NewString("str1"),
   853  					value.NewInteger(3),
   854  					value.NewString("1"),
   855  					value.NewString("str44"),
   856  				}),
   857  				NewRecord([]value.Primary{
   858  					value.NewInteger(2),
   859  					value.NewString("2"),
   860  					value.NewString("str2"),
   861  					value.NewInteger(1),
   862  					value.NewString("2"),
   863  					value.NewString("str22"),
   864  				}),
   865  			},
   866  		},
   867  		Select: parser.SelectClause{
   868  			Fields: []parser.QueryExpression{
   869  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, Alias: parser.Identifier{Literal: "c2"}},
   870  				parser.Field{Object: parser.FieldReference{View: parser.Identifier{Literal: "table2"}, Column: parser.AllColumns{}}},
   871  				parser.Field{Object: parser.NewIntegerValueFromString("1"), Alias: parser.Identifier{Literal: "a"}},
   872  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}, Alias: parser.Identifier{Literal: "c2a"}},
   873  				parser.Field{Object: parser.ColumnNumber{View: parser.Identifier{Literal: "table2"}, Number: value.NewInteger(1)}, Alias: parser.Identifier{Literal: "t21"}},
   874  				parser.Field{Object: parser.ColumnNumber{View: parser.Identifier{Literal: "table2"}, Number: value.NewInteger(1)}, Alias: parser.Identifier{Literal: "t21a"}},
   875  				parser.Field{Object: parser.PrimitiveType{
   876  					Literal: "2012-01-01",
   877  					Value:   value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())),
   878  				}},
   879  			},
   880  		},
   881  		Result: &View{
   882  			Header: []HeaderField{
   883  				{View: "table1", Column: InternalIdColumn},
   884  				{View: "table1", Column: "column1", Number: 1, IsFromTable: true},
   885  				{View: "table1", Column: "column2", Aliases: []string{"c2", "c2a"}, Number: 2, IsFromTable: true},
   886  				{View: "table2", Column: InternalIdColumn},
   887  				{View: "table2", Column: "column3", Aliases: []string{"t21", "t21a"}, Number: 1, IsFromTable: true},
   888  				{View: "table2", Column: "column4", Number: 2, IsFromTable: true},
   889  				{Identifier: "@__PT:I:1", Column: "1", Aliases: []string{"a"}},
   890  				{Identifier: "@__PT:D:2012-01-01T00:00:00Z", Column: "2012-01-01T00:00:00Z"},
   891  			},
   892  			RecordSet: []Record{
   893  				NewRecord([]value.Primary{
   894  					value.NewInteger(1),
   895  					value.NewString("1"),
   896  					value.NewString("str1"),
   897  					value.NewInteger(1),
   898  					value.NewString("2"),
   899  					value.NewString("str22"),
   900  					value.NewInteger(1),
   901  					value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())),
   902  				}),
   903  				NewRecord([]value.Primary{
   904  					value.NewInteger(1),
   905  					value.NewString("1"),
   906  					value.NewString("str1"),
   907  					value.NewInteger(2),
   908  					value.NewString("3"),
   909  					value.NewString("str33"),
   910  					value.NewInteger(1),
   911  					value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())),
   912  				}),
   913  				NewRecord([]value.Primary{
   914  					value.NewInteger(1),
   915  					value.NewString("1"),
   916  					value.NewString("str1"),
   917  					value.NewInteger(3),
   918  					value.NewString("1"),
   919  					value.NewString("str44"),
   920  					value.NewInteger(1),
   921  					value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())),
   922  				}),
   923  				NewRecord([]value.Primary{
   924  					value.NewInteger(2),
   925  					value.NewString("2"),
   926  					value.NewString("str2"),
   927  					value.NewInteger(1),
   928  					value.NewString("2"),
   929  					value.NewString("str22"),
   930  					value.NewInteger(1),
   931  					value.NewDatetime(time.Date(2012, 1, 1, 0, 0, 0, 0, GetTestLocation())),
   932  				}),
   933  			},
   934  			selectFields: []int{2, 4, 5, 6, 2, 4, 4, 7},
   935  		},
   936  	},
   937  	{
   938  		Name: "Select Distinct",
   939  		View: &View{
   940  			Header: []HeaderField{
   941  				{View: "table1", Column: InternalIdColumn},
   942  				{View: "table1", Column: "column1", IsFromTable: true},
   943  				{View: "table1", Column: "column2", IsFromTable: true},
   944  				{View: "table2", Column: InternalIdColumn},
   945  				{View: "table2", Column: "column3", IsFromTable: true},
   946  				{View: "table2", Column: "column4", IsFromTable: true},
   947  			},
   948  			RecordSet: []Record{
   949  				NewRecord([]value.Primary{
   950  					value.NewInteger(1),
   951  					value.NewString("1"),
   952  					value.NewString("str1"),
   953  					value.NewInteger(1),
   954  					value.NewString("2"),
   955  					value.NewString("str22"),
   956  				}),
   957  				NewRecord([]value.Primary{
   958  					value.NewInteger(1),
   959  					value.NewString("1"),
   960  					value.NewString("str1"),
   961  					value.NewInteger(2),
   962  					value.NewString("3"),
   963  					value.NewString("str33"),
   964  				}),
   965  				NewRecord([]value.Primary{
   966  					value.NewInteger(1),
   967  					value.NewString("1"),
   968  					value.NewString("str1"),
   969  					value.NewInteger(3),
   970  					value.NewString("4"),
   971  					value.NewString("str44"),
   972  				}),
   973  				NewRecord([]value.Primary{
   974  					value.NewInteger(2),
   975  					value.NewString("2"),
   976  					value.NewString("str2"),
   977  					value.NewInteger(1),
   978  					value.NewString("2"),
   979  					value.NewString("str22"),
   980  				}),
   981  			},
   982  		},
   983  		Select: parser.SelectClause{
   984  			Distinct: parser.Token{Token: parser.DISTINCT, Literal: "distinct"},
   985  			Fields: []parser.QueryExpression{
   986  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}},
   987  				parser.Field{Object: parser.NewIntegerValueFromString("1"), Alias: parser.Identifier{Literal: "a"}},
   988  			},
   989  		},
   990  		Result: &View{
   991  			Header: []HeaderField{
   992  				{View: "table1", Column: "column1", IsFromTable: true},
   993  				{Identifier: "@__PT:I:1", Column: "1", Aliases: []string{"a"}},
   994  			},
   995  			RecordSet: []Record{
   996  				NewRecord([]value.Primary{
   997  					value.NewString("1"),
   998  					value.NewInteger(1),
   999  				}),
  1000  				NewRecord([]value.Primary{
  1001  					value.NewString("2"),
  1002  					value.NewInteger(1),
  1003  				}),
  1004  			},
  1005  			selectFields: []int{0, 1},
  1006  		},
  1007  	},
  1008  	{
  1009  		Name: "Select Aggregate Function",
  1010  		View: &View{
  1011  			Header: []HeaderField{
  1012  				{View: "table1", Column: InternalIdColumn},
  1013  				{View: "table1", Column: "column1", IsFromTable: true},
  1014  				{View: "table1", Column: "column2", IsFromTable: true},
  1015  			},
  1016  			RecordSet: []Record{
  1017  				NewRecordWithId(1, []value.Primary{
  1018  					value.NewString("1"),
  1019  					value.NewString("str1"),
  1020  				}),
  1021  				NewRecordWithId(2, []value.Primary{
  1022  					value.NewString("2"),
  1023  					value.NewString("str2"),
  1024  				}),
  1025  			},
  1026  		},
  1027  		Select: parser.SelectClause{
  1028  			Fields: []parser.QueryExpression{
  1029  				parser.Field{
  1030  					Object: parser.AggregateFunction{
  1031  						Name:     "sum",
  1032  						Distinct: parser.Token{},
  1033  						Args: []parser.QueryExpression{
  1034  							parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  1035  						},
  1036  					},
  1037  				},
  1038  			},
  1039  		},
  1040  		Result: &View{
  1041  			Header: []HeaderField{
  1042  				{View: "table1", Column: InternalIdColumn},
  1043  				{View: "table1", Column: "column1", IsFromTable: true},
  1044  				{View: "table1", Column: "column2", IsFromTable: true},
  1045  				{Identifier: "SUM(column1)", Column: "SUM(column1)"},
  1046  			},
  1047  			RecordSet: []Record{
  1048  				{
  1049  					NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(2)}),
  1050  					NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("2")}),
  1051  					NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str2")}),
  1052  					NewCell(value.NewFloat(3)),
  1053  				},
  1054  			},
  1055  			selectFields: []int{3},
  1056  		},
  1057  	},
  1058  	{
  1059  		Name: "Select Aggregate Function Not Group Key Error",
  1060  		View: &View{
  1061  			Header: []HeaderField{
  1062  				{View: "table1", Column: InternalIdColumn},
  1063  				{View: "table1", Column: "column1", IsFromTable: true},
  1064  				{View: "table1", Column: "column2", IsFromTable: true},
  1065  			},
  1066  			RecordSet: []Record{
  1067  				NewRecordWithId(1, []value.Primary{
  1068  					value.NewString("1"),
  1069  					value.NewString("str1"),
  1070  				}),
  1071  				NewRecordWithId(2, []value.Primary{
  1072  					value.NewString("2"),
  1073  					value.NewString("str2"),
  1074  				}),
  1075  			},
  1076  		},
  1077  		Select: parser.SelectClause{
  1078  			Fields: []parser.QueryExpression{
  1079  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}},
  1080  				parser.Field{
  1081  					Object: parser.AggregateFunction{
  1082  						Name:     "sum",
  1083  						Distinct: parser.Token{},
  1084  						Args: []parser.QueryExpression{
  1085  							parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  1086  						},
  1087  					},
  1088  				},
  1089  			},
  1090  		},
  1091  		Error: "field column2 is not a group key",
  1092  	},
  1093  	{
  1094  		Name: "Select Aggregate Function All RecordSet Lazy Evaluation",
  1095  		View: &View{
  1096  			Header: []HeaderField{
  1097  				{View: "table1", Column: InternalIdColumn},
  1098  				{View: "table1", Column: "column1", IsFromTable: true},
  1099  				{View: "table1", Column: "column2", IsFromTable: true},
  1100  			},
  1101  			RecordSet: []Record{
  1102  				NewRecordWithId(1, []value.Primary{
  1103  					value.NewString("1"),
  1104  					value.NewString("str1"),
  1105  				}),
  1106  				NewRecordWithId(2, []value.Primary{
  1107  					value.NewString("2"),
  1108  					value.NewString("str2"),
  1109  				}),
  1110  			},
  1111  		},
  1112  		Select: parser.SelectClause{
  1113  			Fields: []parser.QueryExpression{
  1114  				parser.Field{Object: parser.NewIntegerValueFromString("1")},
  1115  				parser.Field{
  1116  					Object: parser.Arithmetic{
  1117  						LHS: parser.AggregateFunction{
  1118  							Name:     "sum",
  1119  							Distinct: parser.Token{},
  1120  							Args: []parser.QueryExpression{
  1121  								parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  1122  							},
  1123  						},
  1124  						RHS:      parser.NewIntegerValueFromString("1"),
  1125  						Operator: parser.Token{Token: '+', Literal: "+"},
  1126  					},
  1127  				},
  1128  			},
  1129  		},
  1130  		Result: &View{
  1131  			Header: []HeaderField{
  1132  				{View: "table1", Column: InternalIdColumn},
  1133  				{View: "table1", Column: "column1", IsFromTable: true},
  1134  				{View: "table1", Column: "column2", IsFromTable: true},
  1135  				{Identifier: "@__PT:I:1", Column: "1"},
  1136  				{Identifier: "SUM(column1) + 1", Column: "SUM(column1) + 1"},
  1137  			},
  1138  			RecordSet: []Record{
  1139  				{
  1140  					NewGroupCell([]value.Primary{value.NewInteger(1), value.NewInteger(2)}),
  1141  					NewGroupCell([]value.Primary{value.NewString("1"), value.NewString("2")}),
  1142  					NewGroupCell([]value.Primary{value.NewString("str1"), value.NewString("str2")}),
  1143  					NewCell(value.NewInteger(1)),
  1144  					NewCell(value.NewFloat(4)),
  1145  				},
  1146  			},
  1147  			selectFields: []int{3, 4},
  1148  		},
  1149  	},
  1150  	{
  1151  		Name: "Select Analytic Function",
  1152  		View: &View{
  1153  			Header: NewHeader("table1", []string{"column1", "column2"}),
  1154  			RecordSet: []Record{
  1155  				NewRecord([]value.Primary{
  1156  					value.NewString("a"),
  1157  					value.NewInteger(2),
  1158  				}),
  1159  				NewRecord([]value.Primary{
  1160  					value.NewString("b"),
  1161  					value.NewInteger(3),
  1162  				}),
  1163  				NewRecord([]value.Primary{
  1164  					value.NewString("b"),
  1165  					value.NewInteger(5),
  1166  				}),
  1167  				NewRecord([]value.Primary{
  1168  					value.NewString("a"),
  1169  					value.NewInteger(1),
  1170  				}),
  1171  				NewRecord([]value.Primary{
  1172  					value.NewString("b"),
  1173  					value.NewInteger(4),
  1174  				}),
  1175  			},
  1176  		},
  1177  		Select: parser.SelectClause{
  1178  			Fields: []parser.QueryExpression{
  1179  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}},
  1180  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}},
  1181  				parser.Field{
  1182  					Object: parser.AnalyticFunction{
  1183  						Name: "row_number",
  1184  						AnalyticClause: parser.AnalyticClause{
  1185  							PartitionClause: parser.PartitionClause{
  1186  								Values: []parser.QueryExpression{
  1187  									parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  1188  								},
  1189  							},
  1190  							OrderByClause: parser.OrderByClause{
  1191  								Items: []parser.QueryExpression{
  1192  									parser.OrderItem{
  1193  										Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  1194  									},
  1195  								},
  1196  							},
  1197  						},
  1198  					},
  1199  					Alias: parser.Identifier{Literal: "rownum"},
  1200  				},
  1201  			},
  1202  		},
  1203  		Result: &View{
  1204  			Header: []HeaderField{
  1205  				{View: "table1", Column: "column1", Number: 1, IsFromTable: true},
  1206  				{View: "table1", Column: "column2", Number: 2, IsFromTable: true},
  1207  				{Identifier: "ROW_NUMBER() OVER (PARTITION BY column1 ORDER BY column2)", Column: "ROW_NUMBER() OVER (PARTITION BY column1 ORDER BY column2)", Aliases: []string{"rownum"}},
  1208  			},
  1209  			RecordSet: []Record{
  1210  				NewRecord([]value.Primary{
  1211  					value.NewString("a"),
  1212  					value.NewInteger(1),
  1213  					value.NewInteger(1),
  1214  				}),
  1215  				NewRecord([]value.Primary{
  1216  					value.NewString("a"),
  1217  					value.NewInteger(2),
  1218  					value.NewInteger(2),
  1219  				}),
  1220  				NewRecord([]value.Primary{
  1221  					value.NewString("b"),
  1222  					value.NewInteger(3),
  1223  					value.NewInteger(1),
  1224  				}),
  1225  				NewRecord([]value.Primary{
  1226  					value.NewString("b"),
  1227  					value.NewInteger(4),
  1228  					value.NewInteger(2),
  1229  				}),
  1230  				NewRecord([]value.Primary{
  1231  					value.NewString("b"),
  1232  					value.NewInteger(5),
  1233  					value.NewInteger(3),
  1234  				}),
  1235  			},
  1236  			selectFields: []int{0, 1, 2},
  1237  		},
  1238  	},
  1239  	{
  1240  		Name: "Select Analytic Function Not Exist Error",
  1241  		View: &View{
  1242  			Header: NewHeader("table1", []string{"column1", "column2"}),
  1243  			RecordSet: []Record{
  1244  				NewRecord([]value.Primary{
  1245  					value.NewString("a"),
  1246  					value.NewInteger(2),
  1247  				}),
  1248  				NewRecord([]value.Primary{
  1249  					value.NewString("b"),
  1250  					value.NewInteger(3),
  1251  				}),
  1252  				NewRecord([]value.Primary{
  1253  					value.NewString("b"),
  1254  					value.NewInteger(5),
  1255  				}),
  1256  				NewRecord([]value.Primary{
  1257  					value.NewString("a"),
  1258  					value.NewInteger(1),
  1259  				}),
  1260  				NewRecord([]value.Primary{
  1261  					value.NewString("b"),
  1262  					value.NewInteger(4),
  1263  				}),
  1264  			},
  1265  		},
  1266  		Select: parser.SelectClause{
  1267  			Fields: []parser.QueryExpression{
  1268  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}},
  1269  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}},
  1270  				parser.Field{
  1271  					Object: parser.AnalyticFunction{
  1272  						Name: "notexist",
  1273  						AnalyticClause: parser.AnalyticClause{
  1274  							PartitionClause: parser.PartitionClause{
  1275  								Values: []parser.QueryExpression{
  1276  									parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  1277  								},
  1278  							},
  1279  							OrderByClause: parser.OrderByClause{
  1280  								Items: []parser.QueryExpression{
  1281  									parser.OrderItem{
  1282  										Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  1283  									},
  1284  								},
  1285  							},
  1286  						},
  1287  					},
  1288  					Alias: parser.Identifier{Literal: "rownum"},
  1289  				},
  1290  			},
  1291  		},
  1292  		Error: "function notexist does not exist",
  1293  	},
  1294  	{
  1295  		Name: "Select Analytic Function Partition Error",
  1296  		View: &View{
  1297  			Header: NewHeader("table1", []string{"column1", "column2"}),
  1298  			RecordSet: []Record{
  1299  				NewRecord([]value.Primary{
  1300  					value.NewString("a"),
  1301  					value.NewInteger(2),
  1302  				}),
  1303  				NewRecord([]value.Primary{
  1304  					value.NewString("b"),
  1305  					value.NewInteger(3),
  1306  				}),
  1307  				NewRecord([]value.Primary{
  1308  					value.NewString("b"),
  1309  					value.NewInteger(5),
  1310  				}),
  1311  				NewRecord([]value.Primary{
  1312  					value.NewString("a"),
  1313  					value.NewInteger(1),
  1314  				}),
  1315  				NewRecord([]value.Primary{
  1316  					value.NewString("b"),
  1317  					value.NewInteger(4),
  1318  				}),
  1319  			},
  1320  		},
  1321  		Select: parser.SelectClause{
  1322  			Fields: []parser.QueryExpression{
  1323  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}},
  1324  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}},
  1325  				parser.Field{
  1326  					Object: parser.AnalyticFunction{
  1327  						Name: "row_number",
  1328  						AnalyticClause: parser.AnalyticClause{
  1329  							PartitionClause: parser.PartitionClause{
  1330  								Values: []parser.QueryExpression{
  1331  									parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}},
  1332  								},
  1333  							},
  1334  							OrderByClause: parser.OrderByClause{
  1335  								Items: []parser.QueryExpression{
  1336  									parser.OrderItem{
  1337  										Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  1338  									},
  1339  								},
  1340  							},
  1341  						},
  1342  					},
  1343  					Alias: parser.Identifier{Literal: "rownum"},
  1344  				},
  1345  			},
  1346  		},
  1347  		Error: "field notexist does not exist",
  1348  	},
  1349  	{
  1350  		Name: "Select Analytic Function Order Error",
  1351  		View: &View{
  1352  			Header: NewHeader("table1", []string{"column1", "column2"}),
  1353  			RecordSet: []Record{
  1354  				NewRecord([]value.Primary{
  1355  					value.NewString("a"),
  1356  					value.NewInteger(2),
  1357  				}),
  1358  				NewRecord([]value.Primary{
  1359  					value.NewString("b"),
  1360  					value.NewInteger(3),
  1361  				}),
  1362  				NewRecord([]value.Primary{
  1363  					value.NewString("b"),
  1364  					value.NewInteger(5),
  1365  				}),
  1366  				NewRecord([]value.Primary{
  1367  					value.NewString("a"),
  1368  					value.NewInteger(1),
  1369  				}),
  1370  				NewRecord([]value.Primary{
  1371  					value.NewString("b"),
  1372  					value.NewInteger(4),
  1373  				}),
  1374  			},
  1375  		},
  1376  		Select: parser.SelectClause{
  1377  			Fields: []parser.QueryExpression{
  1378  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}},
  1379  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}},
  1380  				parser.Field{
  1381  					Object: parser.AnalyticFunction{
  1382  						Name: "row_number",
  1383  						AnalyticClause: parser.AnalyticClause{
  1384  							PartitionClause: parser.PartitionClause{
  1385  								Values: []parser.QueryExpression{
  1386  									parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  1387  								},
  1388  							},
  1389  							OrderByClause: parser.OrderByClause{
  1390  								Items: []parser.QueryExpression{
  1391  									parser.OrderItem{
  1392  										Value: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}},
  1393  									},
  1394  								},
  1395  							},
  1396  						},
  1397  					},
  1398  					Alias: parser.Identifier{Literal: "rownum"},
  1399  				},
  1400  			},
  1401  		},
  1402  		Error: "field notexist does not exist",
  1403  	},
  1404  	{
  1405  		Name: "Select User Defined Analytic Function",
  1406  		View: &View{
  1407  			Header: NewHeader("table1", []string{"column1", "column2"}),
  1408  			RecordSet: []Record{
  1409  				NewRecord([]value.Primary{
  1410  					value.NewString("a"),
  1411  					value.NewInteger(2),
  1412  				}),
  1413  				NewRecord([]value.Primary{
  1414  					value.NewString("b"),
  1415  					value.NewInteger(3),
  1416  				}),
  1417  				NewRecord([]value.Primary{
  1418  					value.NewString("b"),
  1419  					value.NewInteger(5),
  1420  				}),
  1421  				NewRecord([]value.Primary{
  1422  					value.NewString("a"),
  1423  					value.NewInteger(1),
  1424  				}),
  1425  				NewRecord([]value.Primary{
  1426  					value.NewString("b"),
  1427  					value.NewInteger(4),
  1428  				}),
  1429  			},
  1430  		},
  1431  		Scope: GenerateReferenceScope([]map[string]map[string]interface{}{
  1432  			{
  1433  				scopeNameFunctions: {
  1434  					"USERAGGFUNC": &UserDefinedFunction{
  1435  						Name:         parser.Identifier{Literal: "useraggfunc"},
  1436  						IsAggregate:  true,
  1437  						Cursor:       parser.Identifier{Literal: "list"},
  1438  						RequiredArgs: 0,
  1439  						Statements: []parser.Statement{
  1440  							parser.VariableDeclaration{
  1441  								Assignments: []parser.VariableAssignment{
  1442  									{
  1443  										Variable: parser.Variable{Name: "value"},
  1444  									},
  1445  									{
  1446  										Variable: parser.Variable{Name: "fetch"},
  1447  									},
  1448  								},
  1449  							},
  1450  							parser.WhileInCursor{
  1451  								Variables: []parser.Variable{
  1452  									{Name: "fetch"},
  1453  								},
  1454  								Cursor: parser.Identifier{Literal: "list"},
  1455  								Statements: []parser.Statement{
  1456  									parser.If{
  1457  										Condition: parser.Is{
  1458  											LHS: parser.Variable{Name: "value"},
  1459  											RHS: parser.NewNullValue(),
  1460  										},
  1461  										Statements: []parser.Statement{
  1462  											parser.VariableSubstitution{
  1463  												Variable: parser.Variable{Name: "value"},
  1464  												Value:    parser.Variable{Name: "fetch"},
  1465  											},
  1466  											parser.FlowControl{Token: parser.CONTINUE},
  1467  										},
  1468  									},
  1469  									parser.VariableSubstitution{
  1470  										Variable: parser.Variable{Name: "value"},
  1471  										Value: parser.Arithmetic{
  1472  											LHS:      parser.Variable{Name: "value"},
  1473  											RHS:      parser.Variable{Name: "fetch"},
  1474  											Operator: parser.Token{Token: '+', Literal: "+"},
  1475  										},
  1476  									},
  1477  								},
  1478  							},
  1479  
  1480  							parser.Return{
  1481  								Value: parser.Variable{Name: "value"},
  1482  							},
  1483  						},
  1484  					},
  1485  				},
  1486  			},
  1487  		}, nil, time.Time{}, nil),
  1488  		Select: parser.SelectClause{
  1489  			Fields: []parser.QueryExpression{
  1490  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}},
  1491  				parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}}},
  1492  				parser.Field{
  1493  					Object: parser.AnalyticFunction{
  1494  						Name: "useraggfunc",
  1495  						Args: []parser.QueryExpression{
  1496  							parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  1497  						},
  1498  						AnalyticClause: parser.AnalyticClause{},
  1499  					},
  1500  				},
  1501  			},
  1502  		},
  1503  		Result: &View{
  1504  			Header: []HeaderField{
  1505  				{View: "table1", Column: "column1", Number: 1, IsFromTable: true},
  1506  				{View: "table1", Column: "column2", Number: 2, IsFromTable: true},
  1507  				{Identifier: "USERAGGFUNC(column2) OVER ()", Column: "USERAGGFUNC(column2) OVER ()"},
  1508  			},
  1509  			RecordSet: []Record{
  1510  				NewRecord([]value.Primary{
  1511  					value.NewString("a"),
  1512  					value.NewInteger(2),
  1513  					value.NewInteger(15),
  1514  				}),
  1515  				NewRecord([]value.Primary{
  1516  					value.NewString("b"),
  1517  					value.NewInteger(3),
  1518  					value.NewInteger(15),
  1519  				}),
  1520  				NewRecord([]value.Primary{
  1521  					value.NewString("b"),
  1522  					value.NewInteger(5),
  1523  					value.NewInteger(15),
  1524  				}),
  1525  				NewRecord([]value.Primary{
  1526  					value.NewString("a"),
  1527  					value.NewInteger(1),
  1528  					value.NewInteger(15),
  1529  				}),
  1530  				NewRecord([]value.Primary{
  1531  					value.NewString("b"),
  1532  					value.NewInteger(4),
  1533  					value.NewInteger(15),
  1534  				}),
  1535  			},
  1536  			selectFields: []int{0, 1, 2},
  1537  		},
  1538  	},
  1539  	{
  1540  		Name: "Select Aggregate Empty Rows",
  1541  		View: &View{
  1542  			Header: []HeaderField{
  1543  				{View: "table1", Column: "column1", IsFromTable: true},
  1544  				{View: "table1", Column: "column2", IsFromTable: true},
  1545  			},
  1546  			RecordSet: []Record{},
  1547  		},
  1548  		Select: parser.SelectClause{
  1549  			Fields: []parser.QueryExpression{
  1550  				parser.Field{Object: parser.NewIntegerValue(1)},
  1551  				parser.Field{Object: parser.AggregateFunction{Name: "count", Args: []parser.QueryExpression{parser.AllColumns{}}}},
  1552  				parser.Field{Object: parser.AggregateFunction{Name: "sum", Args: []parser.QueryExpression{parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}}},
  1553  			},
  1554  		},
  1555  		Result: &View{
  1556  			Header: []HeaderField{
  1557  				{View: "table1", Column: "column1", IsFromTable: true},
  1558  				{View: "table1", Column: "column2", IsFromTable: true},
  1559  				{Identifier: "@__PT:I:1", Column: "1"},
  1560  				{Identifier: "COUNT(*)", Column: "COUNT(*)"},
  1561  				{Identifier: "SUM(column1)", Column: "SUM(column1)"},
  1562  			},
  1563  			RecordSet: []Record{
  1564  				NewRecord([]value.Primary{
  1565  					nil,
  1566  					nil,
  1567  					value.NewInteger(1),
  1568  					value.NewInteger(0),
  1569  					value.NewNull(),
  1570  				}),
  1571  			},
  1572  			selectFields: []int{2, 3, 4},
  1573  		},
  1574  	},
  1575  	{
  1576  		Name: "Select Compound Function with Aggregate Empty Rows",
  1577  		View: &View{
  1578  			Header: []HeaderField{
  1579  				{View: "table1", Column: "column1", IsFromTable: true},
  1580  				{View: "table1", Column: "column2", IsFromTable: true},
  1581  			},
  1582  			RecordSet: []Record{},
  1583  		},
  1584  		Select: parser.SelectClause{
  1585  			Fields: []parser.QueryExpression{
  1586  				parser.Field{
  1587  					Object: parser.Function{Name: "coalesce",
  1588  						Args: []parser.QueryExpression{
  1589  							parser.AggregateFunction{Name: "sum", Args: []parser.QueryExpression{parser.FieldReference{Column: parser.Identifier{Literal: "column1"}}}},
  1590  							parser.NewIntegerValue(0),
  1591  						},
  1592  					},
  1593  				},
  1594  			},
  1595  		},
  1596  		Result: &View{
  1597  			Header: []HeaderField{
  1598  				{View: "table1", Column: "column1", IsFromTable: true},
  1599  				{View: "table1", Column: "column2", IsFromTable: true},
  1600  				{Identifier: "COALESCE(SUM(column1), 0)", Column: "COALESCE(SUM(column1), 0)"},
  1601  			},
  1602  			RecordSet: []Record{
  1603  				NewRecord([]value.Primary{
  1604  					nil,
  1605  					nil,
  1606  					value.NewInteger(0),
  1607  				}),
  1608  			},
  1609  			selectFields: []int{2},
  1610  		},
  1611  	},
  1612  }
  1613  
  1614  func TestView_Select(t *testing.T) {
  1615  	ctx := context.Background()
  1616  	for _, v := range viewSelectTests {
  1617  		if v.Scope == nil {
  1618  			v.Scope = NewReferenceScope(TestTx)
  1619  		}
  1620  		err := v.View.Select(ctx, v.Scope, v.Select)
  1621  		if err != nil {
  1622  			if len(v.Error) < 1 {
  1623  				t.Errorf("%s: unexpected error %q", v.Name, err)
  1624  			} else if err.Error() != v.Error {
  1625  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
  1626  			}
  1627  			continue
  1628  		}
  1629  		if 0 < len(v.Error) {
  1630  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
  1631  			continue
  1632  		}
  1633  		if !reflect.DeepEqual(v.View.Header, v.Result.Header) {
  1634  			t.Errorf("%s: header = %v, want %v", v.Name, v.View.Header, v.Result.Header)
  1635  		}
  1636  		if !reflect.DeepEqual(v.View.RecordSet, v.Result.RecordSet) {
  1637  			t.Errorf("%s: records = %s, want %s", v.Name, v.View.RecordSet, v.Result.RecordSet)
  1638  		}
  1639  		if !reflect.DeepEqual(v.View.selectFields, v.Result.selectFields) {
  1640  			t.Errorf("%s: select indices = %v, want %v", v.Name, v.View.selectFields, v.Result.selectFields)
  1641  		}
  1642  	}
  1643  }
  1644  
  1645  var viewOrderByTests = []struct {
  1646  	Name    string
  1647  	View    *View
  1648  	OrderBy parser.OrderByClause
  1649  	Result  *View
  1650  	Error   string
  1651  }{
  1652  	{
  1653  		Name: "Order By",
  1654  		View: &View{
  1655  			Header: []HeaderField{
  1656  				{View: "table1", Column: InternalIdColumn},
  1657  				{View: "table1", Column: "column1", IsFromTable: true},
  1658  				{View: "table1", Column: "column2", IsFromTable: true},
  1659  				{View: "table1", Column: "column3", IsFromTable: true},
  1660  			},
  1661  			RecordSet: []Record{
  1662  				NewRecordWithId(1, []value.Primary{
  1663  					value.NewString("1"),
  1664  					value.NewString("3"),
  1665  					value.NewString("2"),
  1666  				}),
  1667  				NewRecordWithId(2, []value.Primary{
  1668  					value.NewString("1"),
  1669  					value.NewString("4"),
  1670  					value.NewString("3"),
  1671  				}),
  1672  				NewRecordWithId(3, []value.Primary{
  1673  					value.NewString("1"),
  1674  					value.NewString("4"),
  1675  					value.NewString("3"),
  1676  				}),
  1677  				NewRecordWithId(4, []value.Primary{
  1678  					value.NewString("1"),
  1679  					value.NewString("3"),
  1680  					value.NewNull(),
  1681  				}),
  1682  				NewRecordWithId(5, []value.Primary{
  1683  					value.NewNull(),
  1684  					value.NewString("2"),
  1685  					value.NewString("4"),
  1686  				}),
  1687  			},
  1688  		},
  1689  		OrderBy: parser.OrderByClause{
  1690  			Items: []parser.QueryExpression{
  1691  				parser.OrderItem{
  1692  					Value: parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  1693  				},
  1694  				parser.OrderItem{
  1695  					Value:     parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  1696  					Direction: parser.Token{Token: parser.DESC, Literal: "desc"},
  1697  				},
  1698  				parser.OrderItem{
  1699  					Value: parser.FieldReference{Column: parser.Identifier{Literal: "column3"}},
  1700  				},
  1701  				parser.OrderItem{
  1702  					Value: parser.NewIntegerValueFromString("1"),
  1703  				},
  1704  			},
  1705  		},
  1706  		Result: &View{
  1707  			Header: []HeaderField{
  1708  				{View: "table1", Column: InternalIdColumn},
  1709  				{View: "table1", Column: "column1", IsFromTable: true},
  1710  				{View: "table1", Column: "column2", IsFromTable: true},
  1711  				{View: "table1", Column: "column3", IsFromTable: true},
  1712  				{Identifier: "@__PT:I:1", Column: "1"},
  1713  			},
  1714  			RecordSet: []Record{
  1715  				NewRecordWithId(5, []value.Primary{
  1716  					value.NewNull(),
  1717  					value.NewString("2"),
  1718  					value.NewString("4"),
  1719  					value.NewInteger(1),
  1720  				}),
  1721  				NewRecordWithId(2, []value.Primary{
  1722  					value.NewString("1"),
  1723  					value.NewString("4"),
  1724  					value.NewString("3"),
  1725  					value.NewInteger(1),
  1726  				}),
  1727  				NewRecordWithId(3, []value.Primary{
  1728  					value.NewString("1"),
  1729  					value.NewString("4"),
  1730  					value.NewString("3"),
  1731  					value.NewInteger(1),
  1732  				}),
  1733  				NewRecordWithId(4, []value.Primary{
  1734  					value.NewString("1"),
  1735  					value.NewString("3"),
  1736  					value.NewNull(),
  1737  					value.NewInteger(1),
  1738  				}),
  1739  				NewRecordWithId(1, []value.Primary{
  1740  					value.NewString("1"),
  1741  					value.NewString("3"),
  1742  					value.NewString("2"),
  1743  					value.NewInteger(1),
  1744  				}),
  1745  			},
  1746  		},
  1747  	},
  1748  	{
  1749  		Name: "Order By with Cached SortValues",
  1750  		View: &View{
  1751  			Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}),
  1752  			RecordSet: []Record{
  1753  				NewRecordWithId(1, []value.Primary{
  1754  					value.NewString("1"),
  1755  					value.NewString("3"),
  1756  					value.NewString("2"),
  1757  				}),
  1758  				NewRecordWithId(2, []value.Primary{
  1759  					value.NewString("1"),
  1760  					value.NewString("4"),
  1761  					value.NewString("3"),
  1762  				}),
  1763  				NewRecordWithId(3, []value.Primary{
  1764  					value.NewString("1"),
  1765  					value.NewString("4"),
  1766  					value.NewString("3"),
  1767  				}),
  1768  				NewRecordWithId(4, []value.Primary{
  1769  					value.NewString("1"),
  1770  					value.NewString("3"),
  1771  					value.NewNull(),
  1772  				}),
  1773  				NewRecordWithId(5, []value.Primary{
  1774  					value.NewNull(),
  1775  					value.NewString("2"),
  1776  					value.NewString("4"),
  1777  				}),
  1778  			},
  1779  			sortValuesInEachCell: [][]*SortValue{
  1780  				{nil, nil, NewSortValue(value.NewString("3"), TestTx.Flags), nil},
  1781  				{nil, nil, NewSortValue(value.NewString("4"), TestTx.Flags), nil},
  1782  				{nil, nil, NewSortValue(value.NewString("4"), TestTx.Flags), nil},
  1783  				{nil, nil, NewSortValue(value.NewString("3"), TestTx.Flags), nil},
  1784  				{nil, nil, NewSortValue(value.NewString("2"), TestTx.Flags), nil},
  1785  			},
  1786  		},
  1787  		OrderBy: parser.OrderByClause{
  1788  			Items: []parser.QueryExpression{
  1789  				parser.OrderItem{
  1790  					Value: parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  1791  				},
  1792  			},
  1793  		},
  1794  		Result: &View{
  1795  			Header: NewHeaderWithId("table1", []string{"column1", "column2", "column3"}),
  1796  			RecordSet: []Record{
  1797  				NewRecordWithId(5, []value.Primary{
  1798  					value.NewNull(),
  1799  					value.NewString("2"),
  1800  					value.NewString("4"),
  1801  				}),
  1802  				NewRecordWithId(1, []value.Primary{
  1803  					value.NewString("1"),
  1804  					value.NewString("3"),
  1805  					value.NewString("2"),
  1806  				}),
  1807  				NewRecordWithId(4, []value.Primary{
  1808  					value.NewString("1"),
  1809  					value.NewString("3"),
  1810  					value.NewNull(),
  1811  				}),
  1812  				NewRecordWithId(2, []value.Primary{
  1813  					value.NewString("1"),
  1814  					value.NewString("4"),
  1815  					value.NewString("3"),
  1816  				}),
  1817  				NewRecordWithId(3, []value.Primary{
  1818  					value.NewString("1"),
  1819  					value.NewString("4"),
  1820  					value.NewString("3"),
  1821  				}),
  1822  			},
  1823  			sortValuesInEachCell: [][]*SortValue{
  1824  				{nil, nil, NewSortValue(value.NewString("2"), TestTx.Flags), nil},
  1825  				{nil, nil, NewSortValue(value.NewString("3"), TestTx.Flags), nil},
  1826  				{nil, nil, NewSortValue(value.NewString("3"), TestTx.Flags), nil},
  1827  				{nil, nil, NewSortValue(value.NewString("4"), TestTx.Flags), nil},
  1828  				{nil, nil, NewSortValue(value.NewString("4"), TestTx.Flags), nil},
  1829  			},
  1830  		},
  1831  	},
  1832  	{
  1833  		Name: "Order By With Null Positions",
  1834  		View: &View{
  1835  			Header: []HeaderField{
  1836  				{View: "table1", Column: InternalIdColumn},
  1837  				{View: "table1", Column: "column1", IsFromTable: true},
  1838  				{View: "table1", Column: "column2", IsFromTable: true},
  1839  			},
  1840  			RecordSet: []Record{
  1841  				NewRecordWithId(1, []value.Primary{
  1842  					value.NewString("1"),
  1843  					value.NewNull(),
  1844  				}),
  1845  				NewRecordWithId(2, []value.Primary{
  1846  					value.NewString("1"),
  1847  					value.NewString("2"),
  1848  				}),
  1849  				NewRecordWithId(3, []value.Primary{
  1850  					value.NewNull(),
  1851  					value.NewString("2"),
  1852  				}),
  1853  				NewRecordWithId(4, []value.Primary{
  1854  					value.NewString("1"),
  1855  					value.NewNull(),
  1856  				}),
  1857  				NewRecordWithId(5, []value.Primary{
  1858  					value.NewString("1"),
  1859  					value.NewString("2"),
  1860  				}),
  1861  			},
  1862  		},
  1863  		OrderBy: parser.OrderByClause{
  1864  			Items: []parser.QueryExpression{
  1865  				parser.OrderItem{
  1866  					Value:         parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  1867  					NullsPosition: parser.Token{Token: parser.LAST, Literal: "last"},
  1868  				},
  1869  				parser.OrderItem{
  1870  					Value:         parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  1871  					NullsPosition: parser.Token{Token: parser.FIRST, Literal: "first"},
  1872  				},
  1873  			},
  1874  		},
  1875  		Result: &View{
  1876  			Header: []HeaderField{
  1877  				{View: "table1", Column: InternalIdColumn},
  1878  				{View: "table1", Column: "column1", IsFromTable: true},
  1879  				{View: "table1", Column: "column2", IsFromTable: true},
  1880  			},
  1881  			RecordSet: []Record{
  1882  				NewRecordWithId(1, []value.Primary{
  1883  					value.NewString("1"),
  1884  					value.NewNull(),
  1885  				}),
  1886  				NewRecordWithId(4, []value.Primary{
  1887  					value.NewString("1"),
  1888  					value.NewNull(),
  1889  				}),
  1890  				NewRecordWithId(2, []value.Primary{
  1891  					value.NewString("1"),
  1892  					value.NewString("2"),
  1893  				}),
  1894  				NewRecordWithId(5, []value.Primary{
  1895  					value.NewString("1"),
  1896  					value.NewString("2"),
  1897  				}),
  1898  				NewRecordWithId(3, []value.Primary{
  1899  					value.NewNull(),
  1900  					value.NewString("2"),
  1901  				}),
  1902  			},
  1903  		},
  1904  	},
  1905  	{
  1906  		Name: "Order By Record Extend Error",
  1907  		View: &View{
  1908  			Header: []HeaderField{
  1909  				{View: "table1", Column: InternalIdColumn},
  1910  				{View: "table1", Column: "column1", IsFromTable: true},
  1911  				{View: "table1", Column: "column2", IsFromTable: true},
  1912  			},
  1913  			RecordSet: []Record{
  1914  				NewRecordWithId(1, []value.Primary{
  1915  					value.NewString("1"),
  1916  					value.NewNull(),
  1917  				}),
  1918  				NewRecordWithId(2, []value.Primary{
  1919  					value.NewString("1"),
  1920  					value.NewString("2"),
  1921  				}),
  1922  			},
  1923  		},
  1924  		OrderBy: parser.OrderByClause{
  1925  			Items: []parser.QueryExpression{
  1926  				parser.OrderItem{
  1927  					Value: parser.AggregateFunction{
  1928  						Name:     "sum",
  1929  						Distinct: parser.Token{},
  1930  						Args: []parser.QueryExpression{
  1931  							parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  1932  						},
  1933  					},
  1934  				},
  1935  			},
  1936  		},
  1937  		Error: "function sum cannot aggregate not grouping records",
  1938  	},
  1939  }
  1940  
  1941  func TestView_OrderBy(t *testing.T) {
  1942  	scope := NewReferenceScope(TestTx)
  1943  	ctx := context.Background()
  1944  	for _, v := range viewOrderByTests {
  1945  		err := v.View.OrderBy(ctx, scope, v.OrderBy)
  1946  		if err != nil {
  1947  			if len(v.Error) < 1 {
  1948  				t.Errorf("%s: unexpected error %q", v.Name, err)
  1949  			} else if err.Error() != v.Error {
  1950  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
  1951  			}
  1952  			continue
  1953  		}
  1954  		if 0 < len(v.Error) {
  1955  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
  1956  			continue
  1957  		}
  1958  		if !reflect.DeepEqual(v.View.Header, v.Result.Header) {
  1959  			t.Errorf("%s: header = %v, want %v", v.Name, v.View.Header, v.Result.Header)
  1960  		}
  1961  		if !reflect.DeepEqual(v.View.RecordSet, v.Result.RecordSet) {
  1962  			t.Errorf("%s: records = %s, want %s", v.Name, v.View.RecordSet, v.Result.RecordSet)
  1963  		}
  1964  	}
  1965  }
  1966  
  1967  var viewExtendRecordCapacityTests = []struct {
  1968  	Name   string
  1969  	View   *View
  1970  	Scope  *ReferenceScope
  1971  	Exprs  []parser.QueryExpression
  1972  	Result int
  1973  	Error  string
  1974  }{
  1975  	{
  1976  		Name: "ExtendRecordCapacity",
  1977  		View: &View{
  1978  			Header: NewHeader("table1", []string{"column1", "column2"}),
  1979  			RecordSet: RecordSet{
  1980  				NewRecord([]value.Primary{
  1981  					value.NewInteger(1),
  1982  					value.NewInteger(2),
  1983  				}),
  1984  			},
  1985  			isGrouped: true,
  1986  		},
  1987  		Scope: GenerateReferenceScope([]map[string]map[string]interface{}{
  1988  			{
  1989  				scopeNameFunctions: {
  1990  					"USERFUNC": &UserDefinedFunction{
  1991  						Name: parser.Identifier{Literal: "userfunc"},
  1992  						Parameters: []parser.Variable{
  1993  							{Name: "arg1"},
  1994  						},
  1995  						RequiredArgs: 1,
  1996  						Statements: []parser.Statement{
  1997  							parser.Return{Value: parser.Variable{Name: "arg1"}},
  1998  						},
  1999  						IsAggregate: true,
  2000  					},
  2001  				},
  2002  			},
  2003  		}, nil, time.Time{}, nil),
  2004  		Exprs: []parser.QueryExpression{
  2005  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  2006  			parser.ColumnNumber{View: parser.Identifier{Literal: "table1"}, Number: value.NewInteger(2)},
  2007  			parser.Function{
  2008  				Name: "userfunc",
  2009  				Args: []parser.QueryExpression{
  2010  					parser.NewIntegerValueFromString("1"),
  2011  				},
  2012  			},
  2013  			parser.AggregateFunction{
  2014  				Name:     "avg",
  2015  				Distinct: parser.Token{},
  2016  				Args: []parser.QueryExpression{
  2017  					parser.AggregateFunction{
  2018  						Name: "avg",
  2019  						Args: []parser.QueryExpression{
  2020  							parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  2021  						},
  2022  					},
  2023  				},
  2024  			},
  2025  			parser.AnalyticFunction{
  2026  				Name: "rank",
  2027  				AnalyticClause: parser.AnalyticClause{
  2028  					PartitionClause: parser.PartitionClause{
  2029  						Values: []parser.QueryExpression{
  2030  							parser.Arithmetic{
  2031  								LHS:      parser.NewIntegerValueFromString("1"),
  2032  								RHS:      parser.NewIntegerValueFromString("2"),
  2033  								Operator: parser.Token{Token: '+', Literal: "+"},
  2034  							},
  2035  						},
  2036  					},
  2037  					OrderByClause: parser.OrderByClause{
  2038  						Items: []parser.QueryExpression{
  2039  							parser.OrderItem{
  2040  								Value: parser.Arithmetic{
  2041  									LHS:      parser.NewIntegerValueFromString("3"),
  2042  									RHS:      parser.NewIntegerValueFromString("4"),
  2043  									Operator: parser.Token{Token: '+', Literal: "+"},
  2044  								},
  2045  							},
  2046  						},
  2047  					},
  2048  				},
  2049  			},
  2050  			parser.Arithmetic{
  2051  				LHS:      parser.NewIntegerValueFromString("5"),
  2052  				RHS:      parser.NewIntegerValueFromString("6"),
  2053  				Operator: parser.Token{Token: '+', Literal: "+"},
  2054  			},
  2055  		},
  2056  		Result: 8,
  2057  	},
  2058  }
  2059  
  2060  func TestView_ExtendRecordCapacity(t *testing.T) {
  2061  	ctx := context.Background()
  2062  	for _, v := range viewExtendRecordCapacityTests {
  2063  		if v.Scope == nil {
  2064  			v.Scope = NewReferenceScope(TestTx)
  2065  		}
  2066  
  2067  		err := v.View.ExtendRecordCapacity(ctx, v.Scope, v.Exprs, nil)
  2068  		if err != nil {
  2069  			if len(v.Error) < 1 {
  2070  				t.Errorf("%s: unexpected error %q", v.Name, err)
  2071  			} else if err.Error() != v.Error {
  2072  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
  2073  			}
  2074  			continue
  2075  		}
  2076  		if 0 < len(v.Error) {
  2077  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
  2078  			continue
  2079  		}
  2080  		if cap(v.View.RecordSet[0]) != v.Result {
  2081  			t.Errorf("%s: record capacity = %d, want %d", v.Name, cap(v.View.RecordSet[0]), v.Result)
  2082  		}
  2083  	}
  2084  }
  2085  
  2086  var viewLimitTests = []struct {
  2087  	Name   string
  2088  	View   *View
  2089  	Limit  parser.LimitClause
  2090  	Result *View
  2091  	Error  string
  2092  }{
  2093  	{
  2094  		Name: "Limit",
  2095  		View: &View{
  2096  			Header: []HeaderField{
  2097  				{View: "table1", Column: InternalIdColumn},
  2098  				{View: "table1", Column: "column1", IsFromTable: true},
  2099  				{View: "table1", Column: "column2", IsFromTable: true},
  2100  			},
  2101  			RecordSet: []Record{
  2102  				NewRecordWithId(1, []value.Primary{
  2103  					value.NewString("1"),
  2104  					value.NewString("str1"),
  2105  				}),
  2106  				NewRecordWithId(2, []value.Primary{
  2107  					value.NewString("1"),
  2108  					value.NewString("str1"),
  2109  				}),
  2110  				NewRecordWithId(3, []value.Primary{
  2111  					value.NewString("1"),
  2112  					value.NewString("str1"),
  2113  				}),
  2114  				NewRecordWithId(4, []value.Primary{
  2115  					value.NewString("2"),
  2116  					value.NewString("str2"),
  2117  				}),
  2118  				NewRecordWithId(4, []value.Primary{
  2119  					value.NewString("3"),
  2120  					value.NewString("str3"),
  2121  				}),
  2122  			},
  2123  		},
  2124  		Limit: parser.LimitClause{Value: parser.NewIntegerValueFromString("2")},
  2125  		Result: &View{
  2126  			Header: []HeaderField{
  2127  				{View: "table1", Column: InternalIdColumn},
  2128  				{View: "table1", Column: "column1", IsFromTable: true},
  2129  				{View: "table1", Column: "column2", IsFromTable: true},
  2130  			},
  2131  			RecordSet: []Record{
  2132  				NewRecordWithId(1, []value.Primary{
  2133  					value.NewString("1"),
  2134  					value.NewString("str1"),
  2135  				}),
  2136  				NewRecordWithId(2, []value.Primary{
  2137  					value.NewString("1"),
  2138  					value.NewString("str1"),
  2139  				}),
  2140  			},
  2141  		},
  2142  	},
  2143  	{
  2144  		Name: "Limit With Ties",
  2145  		View: &View{
  2146  			Header: []HeaderField{
  2147  				{View: "table1", Column: InternalIdColumn},
  2148  				{View: "table1", Column: "column1", IsFromTable: true},
  2149  				{View: "table1", Column: "column2", IsFromTable: true},
  2150  			},
  2151  			RecordSet: []Record{
  2152  				NewRecordWithId(1, []value.Primary{
  2153  					value.NewString("1"),
  2154  					value.NewString("str1"),
  2155  				}),
  2156  				NewRecordWithId(2, []value.Primary{
  2157  					value.NewString("1"),
  2158  					value.NewString("str1"),
  2159  				}),
  2160  				NewRecordWithId(3, []value.Primary{
  2161  					value.NewString("1"),
  2162  					value.NewString("str1"),
  2163  				}),
  2164  				NewRecordWithId(4, []value.Primary{
  2165  					value.NewString("2"),
  2166  					value.NewString("str2"),
  2167  				}),
  2168  				NewRecordWithId(4, []value.Primary{
  2169  					value.NewString("3"),
  2170  					value.NewString("str3"),
  2171  				}),
  2172  			},
  2173  			sortValuesInEachRecord: []SortValues{
  2174  				{
  2175  					&SortValue{Type: IntegerType, Integer: 1},
  2176  					&SortValue{Type: StringType, String: "str1"},
  2177  				},
  2178  				{
  2179  					&SortValue{Type: IntegerType, Integer: 1},
  2180  					&SortValue{Type: StringType, String: "str1"},
  2181  				},
  2182  				{
  2183  					&SortValue{Type: IntegerType, Integer: 1},
  2184  					&SortValue{Type: StringType, String: "str1"},
  2185  				},
  2186  				{
  2187  					&SortValue{Type: IntegerType, Integer: 2},
  2188  					&SortValue{Type: StringType, String: "str2"},
  2189  				},
  2190  				{
  2191  					&SortValue{Type: IntegerType, Integer: 3},
  2192  					&SortValue{Type: StringType, String: "str3"},
  2193  				},
  2194  			},
  2195  		},
  2196  		Limit: parser.LimitClause{Value: parser.NewIntegerValueFromString("2"), Restriction: parser.Token{Token: parser.TIES}},
  2197  		Result: &View{
  2198  			Header: []HeaderField{
  2199  				{View: "table1", Column: InternalIdColumn},
  2200  				{View: "table1", Column: "column1", IsFromTable: true},
  2201  				{View: "table1", Column: "column2", IsFromTable: true},
  2202  			},
  2203  			RecordSet: []Record{
  2204  				NewRecordWithId(1, []value.Primary{
  2205  					value.NewString("1"),
  2206  					value.NewString("str1"),
  2207  				}),
  2208  				NewRecordWithId(2, []value.Primary{
  2209  					value.NewString("1"),
  2210  					value.NewString("str1"),
  2211  				}),
  2212  				NewRecordWithId(3, []value.Primary{
  2213  					value.NewString("1"),
  2214  					value.NewString("str1"),
  2215  				}),
  2216  			},
  2217  			sortValuesInEachRecord: []SortValues{
  2218  				{
  2219  					&SortValue{Type: IntegerType, Integer: 1},
  2220  					&SortValue{Type: StringType, String: "str1"},
  2221  				},
  2222  				{
  2223  					&SortValue{Type: IntegerType, Integer: 1},
  2224  					&SortValue{Type: StringType, String: "str1"},
  2225  				},
  2226  				{
  2227  					&SortValue{Type: IntegerType, Integer: 1},
  2228  					&SortValue{Type: StringType, String: "str1"},
  2229  				},
  2230  				{
  2231  					&SortValue{Type: IntegerType, Integer: 2},
  2232  					&SortValue{Type: StringType, String: "str2"},
  2233  				},
  2234  				{
  2235  					&SortValue{Type: IntegerType, Integer: 3},
  2236  					&SortValue{Type: StringType, String: "str3"},
  2237  				},
  2238  			},
  2239  		},
  2240  	},
  2241  	{
  2242  		Name: "Limit By Percentage",
  2243  		View: &View{
  2244  			Header: []HeaderField{
  2245  				{View: "table1", Column: InternalIdColumn},
  2246  				{View: "table1", Column: "column1", IsFromTable: true},
  2247  				{View: "table1", Column: "column2", IsFromTable: true},
  2248  			},
  2249  			RecordSet: []Record{
  2250  				NewRecordWithId(2, []value.Primary{
  2251  					value.NewString("1"),
  2252  					value.NewString("str1"),
  2253  				}),
  2254  				NewRecordWithId(3, []value.Primary{
  2255  					value.NewString("1"),
  2256  					value.NewString("str1"),
  2257  				}),
  2258  				NewRecordWithId(4, []value.Primary{
  2259  					value.NewString("2"),
  2260  					value.NewString("str2"),
  2261  				}),
  2262  				NewRecordWithId(4, []value.Primary{
  2263  					value.NewString("3"),
  2264  					value.NewString("str3"),
  2265  				}),
  2266  			},
  2267  			offset: 1,
  2268  		},
  2269  		Limit: parser.LimitClause{Value: parser.NewFloatValue(50.5), Unit: parser.Token{Token: parser.PERCENT}},
  2270  		Result: &View{
  2271  			Header: []HeaderField{
  2272  				{View: "table1", Column: InternalIdColumn},
  2273  				{View: "table1", Column: "column1", IsFromTable: true},
  2274  				{View: "table1", Column: "column2", IsFromTable: true},
  2275  			},
  2276  			RecordSet: []Record{
  2277  				NewRecordWithId(2, []value.Primary{
  2278  					value.NewString("1"),
  2279  					value.NewString("str1"),
  2280  				}),
  2281  				NewRecordWithId(3, []value.Primary{
  2282  					value.NewString("1"),
  2283  					value.NewString("str1"),
  2284  				}),
  2285  				NewRecordWithId(4, []value.Primary{
  2286  					value.NewString("2"),
  2287  					value.NewString("str2"),
  2288  				}),
  2289  			},
  2290  			offset: 1,
  2291  		},
  2292  	},
  2293  	{
  2294  		Name: "Limit By Over 100 Percentage",
  2295  		View: &View{
  2296  			Header: []HeaderField{
  2297  				{View: "table1", Column: InternalIdColumn},
  2298  				{View: "table1", Column: "column1", IsFromTable: true},
  2299  				{View: "table1", Column: "column2", IsFromTable: true},
  2300  			},
  2301  			RecordSet: []Record{
  2302  				NewRecordWithId(1, []value.Primary{
  2303  					value.NewString("1"),
  2304  					value.NewString("str1"),
  2305  				}),
  2306  				NewRecordWithId(2, []value.Primary{
  2307  					value.NewString("1"),
  2308  					value.NewString("str1"),
  2309  				}),
  2310  				NewRecordWithId(3, []value.Primary{
  2311  					value.NewString("1"),
  2312  					value.NewString("str1"),
  2313  				}),
  2314  				NewRecordWithId(4, []value.Primary{
  2315  					value.NewString("2"),
  2316  					value.NewString("str2"),
  2317  				}),
  2318  				NewRecordWithId(4, []value.Primary{
  2319  					value.NewString("3"),
  2320  					value.NewString("str3"),
  2321  				}),
  2322  			},
  2323  		},
  2324  		Limit: parser.LimitClause{Value: parser.NewFloatValue(150), Unit: parser.Token{Token: parser.PERCENT}},
  2325  		Result: &View{
  2326  			Header: []HeaderField{
  2327  				{View: "table1", Column: InternalIdColumn},
  2328  				{View: "table1", Column: "column1", IsFromTable: true},
  2329  				{View: "table1", Column: "column2", IsFromTable: true},
  2330  			},
  2331  			RecordSet: []Record{
  2332  				NewRecordWithId(1, []value.Primary{
  2333  					value.NewString("1"),
  2334  					value.NewString("str1"),
  2335  				}),
  2336  				NewRecordWithId(2, []value.Primary{
  2337  					value.NewString("1"),
  2338  					value.NewString("str1"),
  2339  				}),
  2340  				NewRecordWithId(3, []value.Primary{
  2341  					value.NewString("1"),
  2342  					value.NewString("str1"),
  2343  				}),
  2344  				NewRecordWithId(4, []value.Primary{
  2345  					value.NewString("2"),
  2346  					value.NewString("str2"),
  2347  				}),
  2348  				NewRecordWithId(4, []value.Primary{
  2349  					value.NewString("3"),
  2350  					value.NewString("str3"),
  2351  				}),
  2352  			},
  2353  		},
  2354  	},
  2355  	{
  2356  		Name: "Limit By Negative Percentage",
  2357  		View: &View{
  2358  			Header: []HeaderField{
  2359  				{View: "table1", Column: InternalIdColumn},
  2360  				{View: "table1", Column: "column1", IsFromTable: true},
  2361  				{View: "table1", Column: "column2", IsFromTable: true},
  2362  			},
  2363  			RecordSet: []Record{
  2364  				NewRecordWithId(1, []value.Primary{
  2365  					value.NewString("1"),
  2366  					value.NewString("str1"),
  2367  				}),
  2368  				NewRecordWithId(2, []value.Primary{
  2369  					value.NewString("1"),
  2370  					value.NewString("str1"),
  2371  				}),
  2372  				NewRecordWithId(3, []value.Primary{
  2373  					value.NewString("1"),
  2374  					value.NewString("str1"),
  2375  				}),
  2376  				NewRecordWithId(4, []value.Primary{
  2377  					value.NewString("2"),
  2378  					value.NewString("str2"),
  2379  				}),
  2380  				NewRecordWithId(4, []value.Primary{
  2381  					value.NewString("3"),
  2382  					value.NewString("str3"),
  2383  				}),
  2384  			},
  2385  		},
  2386  		Limit: parser.LimitClause{Value: parser.NewFloatValue(-10), Unit: parser.Token{Token: parser.PERCENT}},
  2387  		Result: &View{
  2388  			Header: []HeaderField{
  2389  				{View: "table1", Column: InternalIdColumn},
  2390  				{View: "table1", Column: "column1", IsFromTable: true},
  2391  				{View: "table1", Column: "column2", IsFromTable: true},
  2392  			},
  2393  			RecordSet: []Record{},
  2394  		},
  2395  	},
  2396  	{
  2397  		Name: "Limit Greater Than RecordSet",
  2398  		View: &View{
  2399  			Header: []HeaderField{
  2400  				{View: "table1", Column: InternalIdColumn},
  2401  				{View: "table1", Column: "column1", IsFromTable: true},
  2402  				{View: "table1", Column: "column2", IsFromTable: true},
  2403  			},
  2404  			RecordSet: []Record{
  2405  				NewRecordWithId(1, []value.Primary{
  2406  					value.NewString("1"),
  2407  					value.NewString("str1"),
  2408  				}),
  2409  				NewRecordWithId(2, []value.Primary{
  2410  					value.NewString("1"),
  2411  					value.NewString("str1"),
  2412  				}),
  2413  			},
  2414  		},
  2415  		Limit: parser.LimitClause{Value: parser.NewIntegerValueFromString("5")},
  2416  		Result: &View{
  2417  			Header: []HeaderField{
  2418  				{View: "table1", Column: InternalIdColumn},
  2419  				{View: "table1", Column: "column1", IsFromTable: true},
  2420  				{View: "table1", Column: "column2", IsFromTable: true},
  2421  			},
  2422  			RecordSet: []Record{
  2423  				NewRecordWithId(1, []value.Primary{
  2424  					value.NewString("1"),
  2425  					value.NewString("str1"),
  2426  				}),
  2427  				NewRecordWithId(2, []value.Primary{
  2428  					value.NewString("1"),
  2429  					value.NewString("str1"),
  2430  				}),
  2431  			},
  2432  		},
  2433  	},
  2434  	{
  2435  		Name: "Limit Evaluate Error",
  2436  		View: &View{
  2437  			Header: []HeaderField{
  2438  				{View: "table1", Column: InternalIdColumn},
  2439  				{View: "table1", Column: "column1", IsFromTable: true},
  2440  				{View: "table1", Column: "column2", IsFromTable: true},
  2441  			},
  2442  			RecordSet: []Record{
  2443  				NewRecordWithId(1, []value.Primary{
  2444  					value.NewString("1"),
  2445  					value.NewString("str1"),
  2446  				}),
  2447  				NewRecordWithId(2, []value.Primary{
  2448  					value.NewString("1"),
  2449  					value.NewString("str1"),
  2450  				}),
  2451  			},
  2452  		},
  2453  		Limit: parser.LimitClause{Value: parser.Variable{Name: "notexist"}},
  2454  		Error: "variable @notexist is undeclared",
  2455  	},
  2456  	{
  2457  		Name: "Limit Value Error",
  2458  		View: &View{
  2459  			Header: []HeaderField{
  2460  				{View: "table1", Column: InternalIdColumn},
  2461  				{View: "table1", Column: "column1", IsFromTable: true},
  2462  				{View: "table1", Column: "column2", IsFromTable: true},
  2463  			},
  2464  			RecordSet: []Record{
  2465  				NewRecordWithId(1, []value.Primary{
  2466  					value.NewString("1"),
  2467  					value.NewString("str1"),
  2468  				}),
  2469  				NewRecordWithId(2, []value.Primary{
  2470  					value.NewString("1"),
  2471  					value.NewString("str1"),
  2472  				}),
  2473  			},
  2474  		},
  2475  		Limit: parser.LimitClause{Value: parser.NewStringValue("str")},
  2476  		Error: "limit number of records 'str' is not an integer value",
  2477  	},
  2478  	{
  2479  		Name: "Limit Negative Value",
  2480  		View: &View{
  2481  			Header: []HeaderField{
  2482  				{View: "table1", Column: InternalIdColumn},
  2483  				{View: "table1", Column: "column1", IsFromTable: true},
  2484  				{View: "table1", Column: "column2", IsFromTable: true},
  2485  			},
  2486  			RecordSet: []Record{
  2487  				NewRecordWithId(1, []value.Primary{
  2488  					value.NewString("1"),
  2489  					value.NewString("str1"),
  2490  				}),
  2491  				NewRecordWithId(2, []value.Primary{
  2492  					value.NewString("1"),
  2493  					value.NewString("str1"),
  2494  				}),
  2495  			},
  2496  		},
  2497  		Limit: parser.LimitClause{Value: parser.NewIntegerValue(-1)},
  2498  		Result: &View{
  2499  			Header: []HeaderField{
  2500  				{View: "table1", Column: InternalIdColumn},
  2501  				{View: "table1", Column: "column1", IsFromTable: true},
  2502  				{View: "table1", Column: "column2", IsFromTable: true},
  2503  			},
  2504  			RecordSet: []Record{},
  2505  		},
  2506  	},
  2507  	{
  2508  		Name: "Limit By Percentage Value Error",
  2509  		View: &View{
  2510  			Header: []HeaderField{
  2511  				{View: "table1", Column: InternalIdColumn},
  2512  				{View: "table1", Column: "column1", IsFromTable: true},
  2513  				{View: "table1", Column: "column2", IsFromTable: true},
  2514  			},
  2515  			RecordSet: []Record{
  2516  				NewRecordWithId(1, []value.Primary{
  2517  					value.NewString("1"),
  2518  					value.NewString("str1"),
  2519  				}),
  2520  				NewRecordWithId(2, []value.Primary{
  2521  					value.NewString("1"),
  2522  					value.NewString("str1"),
  2523  				}),
  2524  			},
  2525  		},
  2526  		Limit: parser.LimitClause{Value: parser.NewStringValue("str"), Unit: parser.Token{Token: parser.PERCENT}},
  2527  		Error: "limit percentage 'str' is not a float value",
  2528  	},
  2529  }
  2530  
  2531  func TestView_Limit(t *testing.T) {
  2532  	scope := NewReferenceScope(TestTx)
  2533  	ctx := context.Background()
  2534  	for _, v := range viewLimitTests {
  2535  		err := v.View.Limit(ctx, scope, v.Limit)
  2536  		if err != nil {
  2537  			if len(v.Error) < 1 {
  2538  				t.Errorf("%s: unexpected error %q", v.Name, err)
  2539  			} else if err.Error() != v.Error {
  2540  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
  2541  			}
  2542  			continue
  2543  		}
  2544  		if 0 < len(v.Error) {
  2545  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
  2546  			continue
  2547  		}
  2548  		if !reflect.DeepEqual(v.View, v.Result) {
  2549  			t.Errorf("%s: view = %v, want %v", v.Name, v.View, v.Result)
  2550  		}
  2551  	}
  2552  }
  2553  
  2554  var viewOffsetTests = []struct {
  2555  	Name   string
  2556  	View   *View
  2557  	Offset parser.OffsetClause
  2558  	Result *View
  2559  	Error  string
  2560  }{
  2561  	{
  2562  		Name: "Offset",
  2563  		View: &View{
  2564  			Header: []HeaderField{
  2565  				{View: "table1", Column: InternalIdColumn},
  2566  				{View: "table1", Column: "column1", IsFromTable: true},
  2567  				{View: "table1", Column: "column2", IsFromTable: true},
  2568  			},
  2569  			RecordSet: []Record{
  2570  				NewRecordWithId(1, []value.Primary{
  2571  					value.NewString("1"),
  2572  					value.NewString("str1"),
  2573  				}),
  2574  				NewRecordWithId(2, []value.Primary{
  2575  					value.NewString("1"),
  2576  					value.NewString("str1"),
  2577  				}),
  2578  				NewRecordWithId(3, []value.Primary{
  2579  					value.NewString("1"),
  2580  					value.NewString("str1"),
  2581  				}),
  2582  				NewRecordWithId(4, []value.Primary{
  2583  					value.NewString("2"),
  2584  					value.NewString("str2"),
  2585  				}),
  2586  			},
  2587  		},
  2588  		Offset: parser.OffsetClause{Value: parser.NewIntegerValueFromString("3")},
  2589  		Result: &View{
  2590  			Header: []HeaderField{
  2591  				{View: "table1", Column: InternalIdColumn},
  2592  				{View: "table1", Column: "column1", IsFromTable: true},
  2593  				{View: "table1", Column: "column2", IsFromTable: true},
  2594  			},
  2595  			RecordSet: []Record{
  2596  				NewRecordWithId(4, []value.Primary{
  2597  					value.NewString("2"),
  2598  					value.NewString("str2"),
  2599  				}),
  2600  			},
  2601  			offset: 3,
  2602  		},
  2603  	},
  2604  	{
  2605  		Name: "Offset Equal To Record Length",
  2606  		View: &View{
  2607  			Header: []HeaderField{
  2608  				{View: "table1", Column: InternalIdColumn},
  2609  				{View: "table1", Column: "column1", IsFromTable: true},
  2610  				{View: "table1", Column: "column2", IsFromTable: true},
  2611  			},
  2612  			RecordSet: []Record{
  2613  				NewRecordWithId(1, []value.Primary{
  2614  					value.NewString("1"),
  2615  					value.NewString("str1"),
  2616  				}),
  2617  				NewRecordWithId(2, []value.Primary{
  2618  					value.NewString("1"),
  2619  					value.NewString("str1"),
  2620  				}),
  2621  				NewRecordWithId(3, []value.Primary{
  2622  					value.NewString("1"),
  2623  					value.NewString("str1"),
  2624  				}),
  2625  				NewRecordWithId(4, []value.Primary{
  2626  					value.NewString("2"),
  2627  					value.NewString("str2"),
  2628  				}),
  2629  			},
  2630  		},
  2631  		Offset: parser.OffsetClause{Value: parser.NewIntegerValueFromString("4")},
  2632  		Result: &View{
  2633  			Header: []HeaderField{
  2634  				{View: "table1", Column: InternalIdColumn},
  2635  				{View: "table1", Column: "column1", IsFromTable: true},
  2636  				{View: "table1", Column: "column2", IsFromTable: true},
  2637  			},
  2638  			RecordSet: []Record{},
  2639  			offset:    4,
  2640  		},
  2641  	},
  2642  	{
  2643  		Name: "Offset Evaluate Error",
  2644  		View: &View{
  2645  			Header: []HeaderField{
  2646  				{View: "table1", Column: InternalIdColumn},
  2647  				{View: "table1", Column: "column1", IsFromTable: true},
  2648  				{View: "table1", Column: "column2", IsFromTable: true},
  2649  			},
  2650  			RecordSet: []Record{
  2651  				NewRecordWithId(1, []value.Primary{
  2652  					value.NewString("1"),
  2653  					value.NewString("str1"),
  2654  				}),
  2655  				NewRecordWithId(2, []value.Primary{
  2656  					value.NewString("1"),
  2657  					value.NewString("str1"),
  2658  				}),
  2659  				NewRecordWithId(3, []value.Primary{
  2660  					value.NewString("1"),
  2661  					value.NewString("str1"),
  2662  				}),
  2663  				NewRecordWithId(4, []value.Primary{
  2664  					value.NewString("2"),
  2665  					value.NewString("str2"),
  2666  				}),
  2667  			},
  2668  		},
  2669  		Offset: parser.OffsetClause{Value: parser.Variable{Name: "notexist"}},
  2670  		Error:  "variable @notexist is undeclared",
  2671  	},
  2672  	{
  2673  		Name: "Offset Value Error",
  2674  		View: &View{
  2675  			Header: []HeaderField{
  2676  				{View: "table1", Column: InternalIdColumn},
  2677  				{View: "table1", Column: "column1", IsFromTable: true},
  2678  				{View: "table1", Column: "column2", IsFromTable: true},
  2679  			},
  2680  			RecordSet: []Record{
  2681  				NewRecordWithId(1, []value.Primary{
  2682  					value.NewString("1"),
  2683  					value.NewString("str1"),
  2684  				}),
  2685  				NewRecordWithId(2, []value.Primary{
  2686  					value.NewString("1"),
  2687  					value.NewString("str1"),
  2688  				}),
  2689  				NewRecordWithId(3, []value.Primary{
  2690  					value.NewString("1"),
  2691  					value.NewString("str1"),
  2692  				}),
  2693  				NewRecordWithId(4, []value.Primary{
  2694  					value.NewString("2"),
  2695  					value.NewString("str2"),
  2696  				}),
  2697  			},
  2698  		},
  2699  		Offset: parser.OffsetClause{Value: parser.NewStringValue("str")},
  2700  		Error:  "offset number 'str' is not an integer value",
  2701  	},
  2702  	{
  2703  		Name: "Offset Negative Number",
  2704  		View: &View{
  2705  			Header: []HeaderField{
  2706  				{View: "table1", Column: InternalIdColumn},
  2707  				{View: "table1", Column: "column1", IsFromTable: true},
  2708  				{View: "table1", Column: "column2", IsFromTable: true},
  2709  			},
  2710  			RecordSet: []Record{
  2711  				NewRecordWithId(1, []value.Primary{
  2712  					value.NewString("1"),
  2713  					value.NewString("str1"),
  2714  				}),
  2715  				NewRecordWithId(2, []value.Primary{
  2716  					value.NewString("1"),
  2717  					value.NewString("str1"),
  2718  				}),
  2719  			},
  2720  		},
  2721  		Offset: parser.OffsetClause{Value: parser.NewIntegerValue(-3)},
  2722  		Result: &View{
  2723  			Header: []HeaderField{
  2724  				{View: "table1", Column: InternalIdColumn},
  2725  				{View: "table1", Column: "column1", IsFromTable: true},
  2726  				{View: "table1", Column: "column2", IsFromTable: true},
  2727  			},
  2728  			RecordSet: []Record{
  2729  				NewRecordWithId(1, []value.Primary{
  2730  					value.NewString("1"),
  2731  					value.NewString("str1"),
  2732  				}),
  2733  				NewRecordWithId(2, []value.Primary{
  2734  					value.NewString("1"),
  2735  					value.NewString("str1"),
  2736  				}),
  2737  			},
  2738  			offset: 0,
  2739  		},
  2740  	},
  2741  }
  2742  
  2743  func TestView_Offset(t *testing.T) {
  2744  	scope := NewReferenceScope(TestTx)
  2745  	ctx := context.Background()
  2746  	for _, v := range viewOffsetTests {
  2747  		err := v.View.Offset(ctx, scope, v.Offset)
  2748  		if err != nil {
  2749  			if len(v.Error) < 1 {
  2750  				t.Errorf("%s: unexpected error %q", v.Name, err)
  2751  			} else if err.Error() != v.Error {
  2752  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
  2753  			}
  2754  			continue
  2755  		}
  2756  		if 0 < len(v.Error) {
  2757  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
  2758  			continue
  2759  		}
  2760  		if !reflect.DeepEqual(v.View, v.Result) {
  2761  			t.Errorf("%s: view = %v, want %v", v.Name, v.View, v.Result)
  2762  		}
  2763  	}
  2764  }
  2765  
  2766  var viewInsertValuesTests = []struct {
  2767  	Name        string
  2768  	Fields      []parser.QueryExpression
  2769  	ValuesList  []parser.QueryExpression
  2770  	Result      *View
  2771  	UpdateCount int
  2772  	Error       string
  2773  }{
  2774  	{
  2775  		Name: "InsertValues",
  2776  		Fields: []parser.QueryExpression{
  2777  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  2778  		},
  2779  		ValuesList: []parser.QueryExpression{
  2780  			parser.RowValue{
  2781  				Value: parser.ValueList{
  2782  					Values: []parser.QueryExpression{
  2783  						parser.NewIntegerValueFromString("3"),
  2784  					},
  2785  				},
  2786  			},
  2787  			parser.RowValue{
  2788  				Value: parser.ValueList{
  2789  					Values: []parser.QueryExpression{
  2790  						parser.NewIntegerValueFromString("4"),
  2791  					},
  2792  				},
  2793  			},
  2794  		},
  2795  		Result: &View{
  2796  			Header: NewHeaderWithId("table1", []string{"column1", "column2"}),
  2797  			RecordSet: []Record{
  2798  				NewRecord([]value.Primary{
  2799  					value.NewInteger(1),
  2800  					value.NewString("1"),
  2801  					value.NewString("str1"),
  2802  				}),
  2803  				NewRecord([]value.Primary{
  2804  					value.NewInteger(2),
  2805  					value.NewString("2"),
  2806  					value.NewString("str2"),
  2807  				}),
  2808  				NewRecord([]value.Primary{
  2809  					value.NewNull(),
  2810  					value.NewInteger(3),
  2811  					value.NewNull(),
  2812  				}),
  2813  				NewRecord([]value.Primary{
  2814  					value.NewNull(),
  2815  					value.NewInteger(4),
  2816  					value.NewNull(),
  2817  				}),
  2818  			},
  2819  		},
  2820  		UpdateCount: 2,
  2821  	},
  2822  	{
  2823  		Name: "InsertValues Field Length Does Not Match Error",
  2824  		Fields: []parser.QueryExpression{
  2825  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  2826  			parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  2827  		},
  2828  		ValuesList: []parser.QueryExpression{
  2829  			parser.RowValue{
  2830  				Value: parser.ValueList{
  2831  					Values: []parser.QueryExpression{
  2832  						parser.NewIntegerValueFromString("3"),
  2833  					},
  2834  				},
  2835  			},
  2836  		},
  2837  		Error: "row value should contain exactly 2 values",
  2838  	},
  2839  	{
  2840  		Name: "InsertValues Value Evaluation Error",
  2841  		Fields: []parser.QueryExpression{
  2842  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  2843  		},
  2844  		ValuesList: []parser.QueryExpression{
  2845  			parser.RowValue{
  2846  				Value: parser.ValueList{
  2847  					Values: []parser.QueryExpression{
  2848  						parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}},
  2849  					},
  2850  				},
  2851  			},
  2852  		},
  2853  		Error: "field notexist does not exist",
  2854  	},
  2855  	{
  2856  		Name: "InsertValues Field Does Not Exist Error",
  2857  		Fields: []parser.QueryExpression{
  2858  			parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}},
  2859  		},
  2860  		ValuesList: []parser.QueryExpression{
  2861  			parser.RowValue{
  2862  				Value: parser.ValueList{
  2863  					Values: []parser.QueryExpression{
  2864  						parser.NewIntegerValueFromString("3"),
  2865  					},
  2866  				},
  2867  			},
  2868  		},
  2869  		Error: "field notexist does not exist",
  2870  	},
  2871  }
  2872  
  2873  func TestView_InsertValues(t *testing.T) {
  2874  	view := &View{
  2875  		Header: NewHeaderWithId("table1", []string{"column1", "column2"}),
  2876  		RecordSet: []Record{
  2877  			NewRecordWithId(1, []value.Primary{
  2878  				value.NewString("1"),
  2879  				value.NewString("str1"),
  2880  			}),
  2881  			NewRecordWithId(2, []value.Primary{
  2882  				value.NewString("2"),
  2883  				value.NewString("str2"),
  2884  			}),
  2885  		},
  2886  	}
  2887  
  2888  	scope := NewReferenceScope(TestTx)
  2889  	ctx := context.Background()
  2890  	for _, v := range viewInsertValuesTests {
  2891  		cnt, err := view.InsertValues(ctx, scope, v.Fields, v.ValuesList)
  2892  		if err != nil {
  2893  			if len(v.Error) < 1 {
  2894  				t.Errorf("%s: unexpected error %q", v.Name, err)
  2895  			} else if err.Error() != v.Error {
  2896  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
  2897  			}
  2898  			continue
  2899  		}
  2900  		if 0 < len(v.Error) {
  2901  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
  2902  			continue
  2903  		}
  2904  		if !reflect.DeepEqual(view, v.Result) {
  2905  			t.Errorf("%s: result = %v, want %v", v.Name, view, v.Result)
  2906  		}
  2907  		if cnt != v.UpdateCount {
  2908  			t.Errorf("%s: update count = %d, want %d", v.Name, cnt, v.UpdateCount)
  2909  		}
  2910  
  2911  	}
  2912  }
  2913  
  2914  var viewInsertFromQueryTests = []struct {
  2915  	Name        string
  2916  	Fields      []parser.QueryExpression
  2917  	Query       parser.SelectQuery
  2918  	Result      *View
  2919  	UpdateCount int
  2920  	Error       string
  2921  }{
  2922  	{
  2923  		Name: "InsertFromQuery",
  2924  		Fields: []parser.QueryExpression{
  2925  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  2926  		},
  2927  		Query: parser.SelectQuery{
  2928  			SelectEntity: parser.SelectEntity{
  2929  				SelectClause: parser.SelectClause{
  2930  					Fields: []parser.QueryExpression{
  2931  						parser.Field{Object: parser.NewIntegerValueFromString("3")},
  2932  					},
  2933  				},
  2934  			},
  2935  		},
  2936  		Result: &View{
  2937  			Header: NewHeaderWithId("table1", []string{"column1", "column2"}),
  2938  			RecordSet: []Record{
  2939  				NewRecord([]value.Primary{
  2940  					value.NewInteger(1),
  2941  					value.NewString("1"),
  2942  					value.NewString("str1"),
  2943  				}),
  2944  				NewRecord([]value.Primary{
  2945  					value.NewInteger(2),
  2946  					value.NewString("2"),
  2947  					value.NewString("str2"),
  2948  				}),
  2949  				NewRecord([]value.Primary{
  2950  					value.NewNull(),
  2951  					value.NewInteger(3),
  2952  					value.NewNull(),
  2953  				}),
  2954  			},
  2955  		},
  2956  		UpdateCount: 1,
  2957  	},
  2958  	{
  2959  		Name: "InsertFromQuery Field Lenght Does Not Match Error",
  2960  		Fields: []parser.QueryExpression{
  2961  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  2962  			parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  2963  		},
  2964  		Query: parser.SelectQuery{
  2965  			SelectEntity: parser.SelectEntity{
  2966  				SelectClause: parser.SelectClause{
  2967  					Fields: []parser.QueryExpression{
  2968  						parser.Field{Object: parser.NewIntegerValueFromString("3")},
  2969  					},
  2970  				},
  2971  			},
  2972  		},
  2973  		Error: "select query should return exactly 2 fields",
  2974  	},
  2975  	{
  2976  		Name: "InsertFromQuery Exuecution Error",
  2977  		Fields: []parser.QueryExpression{
  2978  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  2979  		},
  2980  		Query: parser.SelectQuery{
  2981  			SelectEntity: parser.SelectEntity{
  2982  				SelectClause: parser.SelectClause{
  2983  					Fields: []parser.QueryExpression{
  2984  						parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}}},
  2985  					},
  2986  				},
  2987  			},
  2988  		},
  2989  		Error: "field notexist does not exist",
  2990  	},
  2991  }
  2992  
  2993  func TestView_InsertFromQuery(t *testing.T) {
  2994  	view := &View{
  2995  		Header: NewHeaderWithId("table1", []string{"column1", "column2"}),
  2996  		RecordSet: []Record{
  2997  			NewRecordWithId(1, []value.Primary{
  2998  				value.NewString("1"),
  2999  				value.NewString("str1"),
  3000  			}),
  3001  			NewRecordWithId(2, []value.Primary{
  3002  				value.NewString("2"),
  3003  				value.NewString("str2"),
  3004  			}),
  3005  		},
  3006  	}
  3007  
  3008  	scope := NewReferenceScope(TestTx)
  3009  	ctx := context.Background()
  3010  	for _, v := range viewInsertFromQueryTests {
  3011  		cnt, err := view.InsertFromQuery(ctx, scope, v.Fields, v.Query)
  3012  		if err != nil {
  3013  			if len(v.Error) < 1 {
  3014  				t.Errorf("%s: unexpected error %q", v.Name, err)
  3015  			} else if err.Error() != v.Error {
  3016  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
  3017  			}
  3018  			continue
  3019  		}
  3020  		if 0 < len(v.Error) {
  3021  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
  3022  			continue
  3023  		}
  3024  		if !reflect.DeepEqual(view, v.Result) {
  3025  			t.Errorf("%s: result = %v, want %v", v.Name, view, v.Result)
  3026  		}
  3027  		if cnt != v.UpdateCount {
  3028  			t.Errorf("%s: update count = %d, want %d", v.Name, cnt, v.UpdateCount)
  3029  		}
  3030  	}
  3031  }
  3032  
  3033  var viewReplaceValuesTests = []struct {
  3034  	Name        string
  3035  	Fields      []parser.QueryExpression
  3036  	Keys        []parser.QueryExpression
  3037  	ValuesList  []parser.QueryExpression
  3038  	Result      *View
  3039  	UpdateCount int
  3040  	Error       string
  3041  }{
  3042  	{
  3043  		Name: "ReplaceValues",
  3044  		Fields: []parser.QueryExpression{
  3045  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  3046  			parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  3047  		},
  3048  		Keys: []parser.QueryExpression{
  3049  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  3050  		},
  3051  		ValuesList: []parser.QueryExpression{
  3052  			parser.RowValue{
  3053  				Value: parser.ValueList{
  3054  					Values: []parser.QueryExpression{
  3055  						parser.NewIntegerValueFromString("1"),
  3056  						parser.NewStringValue("str3"),
  3057  					},
  3058  				},
  3059  			},
  3060  			parser.RowValue{
  3061  				Value: parser.ValueList{
  3062  					Values: []parser.QueryExpression{
  3063  						parser.NewIntegerValueFromString("4"),
  3064  						parser.NewStringValue("str4"),
  3065  					},
  3066  				},
  3067  			},
  3068  		},
  3069  		Result: &View{
  3070  			Header: NewHeader("table1", []string{"column1", "column2"}),
  3071  			RecordSet: []Record{
  3072  				NewRecord([]value.Primary{
  3073  					value.NewString("1"),
  3074  					value.NewString("str3"),
  3075  				}),
  3076  				NewRecord([]value.Primary{
  3077  					value.NewString("2"),
  3078  					value.NewString("str2"),
  3079  				}),
  3080  				NewRecord([]value.Primary{
  3081  					value.NewInteger(4),
  3082  					value.NewString("str4"),
  3083  				}),
  3084  			},
  3085  		},
  3086  		UpdateCount: 2,
  3087  	},
  3088  	{
  3089  		Name: "ReplaceValues Field Length Does Not Match Error",
  3090  		Fields: []parser.QueryExpression{
  3091  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  3092  			parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  3093  		},
  3094  		Keys: []parser.QueryExpression{
  3095  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  3096  		},
  3097  		ValuesList: []parser.QueryExpression{
  3098  			parser.RowValue{
  3099  				Value: parser.ValueList{
  3100  					Values: []parser.QueryExpression{
  3101  						parser.NewIntegerValueFromString("3"),
  3102  					},
  3103  				},
  3104  			},
  3105  		},
  3106  		Error: "row value should contain exactly 2 values",
  3107  	},
  3108  	{
  3109  		Name: "ReplaceValues Value Evaluation Error",
  3110  		Fields: []parser.QueryExpression{
  3111  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  3112  		},
  3113  		Keys: []parser.QueryExpression{
  3114  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  3115  		},
  3116  		ValuesList: []parser.QueryExpression{
  3117  			parser.RowValue{
  3118  				Value: parser.ValueList{
  3119  					Values: []parser.QueryExpression{
  3120  						parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}},
  3121  					},
  3122  				},
  3123  			},
  3124  		},
  3125  		Error: "field notexist does not exist",
  3126  	},
  3127  	{
  3128  		Name: "ReplaceValues Field Does Not Exist Error",
  3129  		Fields: []parser.QueryExpression{
  3130  			parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}},
  3131  		},
  3132  		Keys: []parser.QueryExpression{
  3133  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  3134  		},
  3135  		ValuesList: []parser.QueryExpression{
  3136  			parser.RowValue{
  3137  				Value: parser.ValueList{
  3138  					Values: []parser.QueryExpression{
  3139  						parser.NewIntegerValueFromString("3"),
  3140  					},
  3141  				},
  3142  			},
  3143  		},
  3144  		Error: "field notexist does not exist",
  3145  	},
  3146  	{
  3147  		Name: "ReplaceValues Key Does Not Exist Error",
  3148  		Fields: []parser.QueryExpression{
  3149  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  3150  		},
  3151  		Keys: []parser.QueryExpression{
  3152  			parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}},
  3153  		},
  3154  		ValuesList: []parser.QueryExpression{
  3155  			parser.RowValue{
  3156  				Value: parser.ValueList{
  3157  					Values: []parser.QueryExpression{
  3158  						parser.NewIntegerValueFromString("3"),
  3159  					},
  3160  				},
  3161  			},
  3162  		},
  3163  		Error: "field notexist does not exist",
  3164  	},
  3165  	{
  3166  		Name: "ReplaceValues Key Not Set Error",
  3167  		Fields: []parser.QueryExpression{
  3168  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  3169  		},
  3170  		Keys: []parser.QueryExpression{
  3171  			parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  3172  		},
  3173  		ValuesList: []parser.QueryExpression{
  3174  			parser.RowValue{
  3175  				Value: parser.ValueList{
  3176  					Values: []parser.QueryExpression{
  3177  						parser.NewIntegerValueFromString("3"),
  3178  					},
  3179  				},
  3180  			},
  3181  		},
  3182  		Error: "replace Key column2 is not set",
  3183  	},
  3184  }
  3185  
  3186  func TestView_ReplaceValues(t *testing.T) {
  3187  	view := &View{
  3188  		Header: NewHeader("table1", []string{"column1", "column2"}),
  3189  		RecordSet: []Record{
  3190  			NewRecord([]value.Primary{
  3191  				value.NewString("1"),
  3192  				value.NewString("str1"),
  3193  			}),
  3194  			NewRecord([]value.Primary{
  3195  				value.NewString("2"),
  3196  				value.NewString("str2"),
  3197  			}),
  3198  		},
  3199  	}
  3200  
  3201  	scope := NewReferenceScope(TestTx)
  3202  	ctx := context.Background()
  3203  	for _, v := range viewReplaceValuesTests {
  3204  		cnt, err := view.ReplaceValues(ctx, scope, v.Fields, v.ValuesList, v.Keys)
  3205  		if err != nil {
  3206  			if len(v.Error) < 1 {
  3207  				t.Errorf("%s: unexpected error %q", v.Name, err)
  3208  			} else if err.Error() != v.Error {
  3209  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
  3210  			}
  3211  			continue
  3212  		}
  3213  		if 0 < len(v.Error) {
  3214  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
  3215  			continue
  3216  		}
  3217  		if !reflect.DeepEqual(view, v.Result) {
  3218  			t.Errorf("%s: result = %v, want %v", v.Name, view, v.Result)
  3219  		}
  3220  		if cnt != v.UpdateCount {
  3221  			t.Errorf("%s: update count = %d, want %d", v.Name, cnt, v.UpdateCount)
  3222  		}
  3223  
  3224  	}
  3225  }
  3226  
  3227  var viewReplaceFromQueryTests = []struct {
  3228  	Name        string
  3229  	Fields      []parser.QueryExpression
  3230  	Keys        []parser.QueryExpression
  3231  	Query       parser.SelectQuery
  3232  	Result      *View
  3233  	UpdateCount int
  3234  	Error       string
  3235  }{
  3236  	{
  3237  		Name: "ReplaceFromQuery",
  3238  		Fields: []parser.QueryExpression{
  3239  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  3240  			parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  3241  		},
  3242  		Keys: []parser.QueryExpression{
  3243  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  3244  		},
  3245  		Query: parser.SelectQuery{
  3246  			SelectEntity: parser.SelectEntity{
  3247  				SelectClause: parser.SelectClause{
  3248  					Fields: []parser.QueryExpression{
  3249  						parser.Field{Object: parser.NewIntegerValueFromString("1")},
  3250  						parser.Field{Object: parser.NewStringValue("str3")},
  3251  					},
  3252  				},
  3253  			},
  3254  		},
  3255  		Result: &View{
  3256  			Header: NewHeader("table1", []string{"column1", "column2"}),
  3257  			RecordSet: []Record{
  3258  				NewRecord([]value.Primary{
  3259  					value.NewString("1"),
  3260  					value.NewString("str3"),
  3261  				}),
  3262  				NewRecord([]value.Primary{
  3263  					value.NewString("2"),
  3264  					value.NewString("str2"),
  3265  				}),
  3266  			},
  3267  		},
  3268  		UpdateCount: 1,
  3269  	},
  3270  	{
  3271  		Name: "ReplaceFromQuery Field Lenght Does Not Match Error",
  3272  		Fields: []parser.QueryExpression{
  3273  			parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  3274  			parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  3275  		},
  3276  		Query: parser.SelectQuery{
  3277  			SelectEntity: parser.SelectEntity{
  3278  				SelectClause: parser.SelectClause{
  3279  					Fields: []parser.QueryExpression{
  3280  						parser.Field{Object: parser.NewIntegerValueFromString("3")},
  3281  					},
  3282  				},
  3283  			},
  3284  		},
  3285  		Error: "select query should return exactly 2 fields",
  3286  	},
  3287  }
  3288  
  3289  func TestView_ReplaceFromQuery(t *testing.T) {
  3290  	view := &View{
  3291  		Header: NewHeader("table1", []string{"column1", "column2"}),
  3292  		RecordSet: []Record{
  3293  			NewRecord([]value.Primary{
  3294  				value.NewString("1"),
  3295  				value.NewString("str1"),
  3296  			}),
  3297  			NewRecord([]value.Primary{
  3298  				value.NewString("2"),
  3299  				value.NewString("str2"),
  3300  			}),
  3301  		},
  3302  	}
  3303  
  3304  	scope := NewReferenceScope(TestTx)
  3305  	ctx := context.Background()
  3306  	for _, v := range viewReplaceFromQueryTests {
  3307  		cnt, err := view.ReplaceFromQuery(ctx, scope, v.Fields, v.Query, v.Keys)
  3308  		if err != nil {
  3309  			if len(v.Error) < 1 {
  3310  				t.Errorf("%s: unexpected error %q", v.Name, err)
  3311  			} else if err.Error() != v.Error {
  3312  				t.Errorf("%s: error %q, want error %q", v.Name, err.Error(), v.Error)
  3313  			}
  3314  			continue
  3315  		}
  3316  		if 0 < len(v.Error) {
  3317  			t.Errorf("%s: no error, want error %q", v.Name, v.Error)
  3318  			continue
  3319  		}
  3320  		if !reflect.DeepEqual(view, v.Result) {
  3321  			t.Errorf("%s: result = %v, want %v", v.Name, view, v.Result)
  3322  		}
  3323  		if cnt != v.UpdateCount {
  3324  			t.Errorf("%s: update count = %d, want %d", v.Name, cnt, v.UpdateCount)
  3325  		}
  3326  	}
  3327  }
  3328  
  3329  func TestView_Fix(t *testing.T) {
  3330  	view := &View{
  3331  		Header: []HeaderField{
  3332  			{View: "table1", Column: InternalIdColumn},
  3333  			{View: "table1", Column: "column1", IsFromTable: true},
  3334  			{View: "table1", Column: "column2", IsFromTable: true},
  3335  		},
  3336  		RecordSet: []Record{
  3337  			NewRecordWithId(1, []value.Primary{
  3338  				value.NewString("1"),
  3339  				value.NewString("str1"),
  3340  			}),
  3341  			NewRecordWithId(2, []value.Primary{
  3342  				value.NewString("1"),
  3343  				value.NewString("str1"),
  3344  			}),
  3345  		},
  3346  		selectFields: []int{2},
  3347  	}
  3348  	expect := &View{
  3349  		Header: NewHeader("table1", []string{"column2"}),
  3350  		RecordSet: []Record{
  3351  			NewRecord([]value.Primary{
  3352  				value.NewString("str1"),
  3353  			}),
  3354  			NewRecord([]value.Primary{
  3355  				value.NewString("str1"),
  3356  			}),
  3357  		},
  3358  		selectFields: []int(nil),
  3359  	}
  3360  
  3361  	_ = view.Fix(context.Background(), TestTx.Flags)
  3362  	if !reflect.DeepEqual(view, expect) {
  3363  		t.Errorf("fix: view = %v, want %v", view, expect)
  3364  	}
  3365  
  3366  	view = &View{
  3367  		Header: []HeaderField{
  3368  			{View: "table1", Column: InternalIdColumn},
  3369  			{View: "table1", Column: "column1", IsFromTable: true},
  3370  			{View: "table1", Column: "column2", IsFromTable: true},
  3371  		},
  3372  		RecordSet: []Record{
  3373  			NewRecordWithId(1, []value.Primary{
  3374  				value.NewString("1"),
  3375  				value.NewString("str1"),
  3376  			}),
  3377  			NewRecordWithId(2, []value.Primary{
  3378  				value.NewString("1"),
  3379  				value.NewString("str1"),
  3380  			}),
  3381  		},
  3382  		selectFields: []int{2, 2, 2, 2},
  3383  	}
  3384  	expect = &View{
  3385  		Header: NewHeader("table1", []string{"column2", "column2", "column2", "column2"}),
  3386  		RecordSet: []Record{
  3387  			NewRecord([]value.Primary{
  3388  				value.NewString("str1"),
  3389  				value.NewString("str1"),
  3390  				value.NewString("str1"),
  3391  				value.NewString("str1"),
  3392  			}),
  3393  			NewRecord([]value.Primary{
  3394  				value.NewString("str1"),
  3395  				value.NewString("str1"),
  3396  				value.NewString("str1"),
  3397  				value.NewString("str1"),
  3398  			}),
  3399  		},
  3400  		selectFields: []int(nil),
  3401  	}
  3402  
  3403  	_ = view.Fix(context.Background(), TestTx.Flags)
  3404  	if !reflect.DeepEqual(view, expect) {
  3405  		t.Errorf("fix: view = %v, want %v", view, expect)
  3406  	}
  3407  }
  3408  
  3409  func TestView_Union(t *testing.T) {
  3410  	view := &View{
  3411  		Header: []HeaderField{
  3412  			{View: "table1", Column: "column1", IsFromTable: true},
  3413  			{View: "table1", Column: "column2", IsFromTable: true},
  3414  		},
  3415  		RecordSet: RecordSet{
  3416  			NewRecord([]value.Primary{
  3417  				value.NewString("1"),
  3418  				value.NewString("str1"),
  3419  			}),
  3420  			NewRecord([]value.Primary{
  3421  				value.NewString("1"),
  3422  				value.NewString("str1"),
  3423  			}),
  3424  			NewRecord([]value.Primary{
  3425  				value.NewString("2"),
  3426  				value.NewString("str2"),
  3427  			}),
  3428  			NewRecord([]value.Primary{
  3429  				value.NewString("2"),
  3430  				value.NewString("str2"),
  3431  			}),
  3432  		},
  3433  	}
  3434  
  3435  	calcView := &View{
  3436  		Header: []HeaderField{
  3437  			{View: "table2", Column: "column3", IsFromTable: true},
  3438  			{View: "table2", Column: "column4", IsFromTable: true},
  3439  		},
  3440  		RecordSet: RecordSet{
  3441  			NewRecord([]value.Primary{
  3442  				value.NewString("2"),
  3443  				value.NewString("str2"),
  3444  			}),
  3445  			NewRecord([]value.Primary{
  3446  				value.NewString("3"),
  3447  				value.NewString("str3"),
  3448  			}),
  3449  		},
  3450  	}
  3451  
  3452  	expect := &View{
  3453  		Header: []HeaderField{
  3454  			{View: "table1", Column: "column1", IsFromTable: true},
  3455  			{View: "table1", Column: "column2", IsFromTable: true},
  3456  		},
  3457  		RecordSet: RecordSet{
  3458  			NewRecord([]value.Primary{
  3459  				value.NewString("1"),
  3460  				value.NewString("str1"),
  3461  			}),
  3462  			NewRecord([]value.Primary{
  3463  				value.NewString("2"),
  3464  				value.NewString("str2"),
  3465  			}),
  3466  			NewRecord([]value.Primary{
  3467  				value.NewString("3"),
  3468  				value.NewString("str3"),
  3469  			}),
  3470  		},
  3471  	}
  3472  
  3473  	ctx := context.Background()
  3474  	err := view.Union(ctx, TestTx.Flags, calcView, false)
  3475  	if err != nil {
  3476  		t.Errorf("unexpected error %q", err)
  3477  	}
  3478  	if !reflect.DeepEqual(view, expect) {
  3479  		t.Errorf("union: view = %v, want %v", view, expect)
  3480  	}
  3481  
  3482  	view = &View{
  3483  		Header: []HeaderField{
  3484  			{View: "table1", Column: "column1", IsFromTable: true},
  3485  			{View: "table1", Column: "column2", IsFromTable: true},
  3486  		},
  3487  		RecordSet: RecordSet{
  3488  			NewRecord([]value.Primary{
  3489  				value.NewString("1"),
  3490  				value.NewString("str1"),
  3491  			}),
  3492  			NewRecord([]value.Primary{
  3493  				value.NewString("1"),
  3494  				value.NewString("str1"),
  3495  			}),
  3496  			NewRecord([]value.Primary{
  3497  				value.NewString("2"),
  3498  				value.NewString("str2"),
  3499  			}),
  3500  			NewRecord([]value.Primary{
  3501  				value.NewString("2"),
  3502  				value.NewString("str2"),
  3503  			}),
  3504  		},
  3505  	}
  3506  
  3507  	expect = &View{
  3508  		Header: []HeaderField{
  3509  			{View: "table1", Column: "column1", IsFromTable: true},
  3510  			{View: "table1", Column: "column2", IsFromTable: true},
  3511  		},
  3512  		RecordSet: RecordSet{
  3513  			NewRecord([]value.Primary{
  3514  				value.NewString("1"),
  3515  				value.NewString("str1"),
  3516  			}),
  3517  			NewRecord([]value.Primary{
  3518  				value.NewString("1"),
  3519  				value.NewString("str1"),
  3520  			}),
  3521  			NewRecord([]value.Primary{
  3522  				value.NewString("2"),
  3523  				value.NewString("str2"),
  3524  			}),
  3525  			NewRecord([]value.Primary{
  3526  				value.NewString("2"),
  3527  				value.NewString("str2"),
  3528  			}),
  3529  			NewRecord([]value.Primary{
  3530  				value.NewString("2"),
  3531  				value.NewString("str2"),
  3532  			}),
  3533  			NewRecord([]value.Primary{
  3534  				value.NewString("3"),
  3535  				value.NewString("str3"),
  3536  			}),
  3537  		},
  3538  	}
  3539  
  3540  	err = view.Union(ctx, TestTx.Flags, calcView, true)
  3541  	if err != nil {
  3542  		t.Errorf("unexpected error %q", err)
  3543  	}
  3544  	if !reflect.DeepEqual(view, expect) {
  3545  		t.Errorf("union all: view = %v, want %v", view, expect)
  3546  	}
  3547  }
  3548  
  3549  func TestView_Except(t *testing.T) {
  3550  	view := &View{
  3551  		Header: []HeaderField{
  3552  			{View: "table1", Column: "column1", IsFromTable: true},
  3553  			{View: "table1", Column: "column2", IsFromTable: true},
  3554  		},
  3555  		RecordSet: RecordSet{
  3556  			NewRecord([]value.Primary{
  3557  				value.NewString("1"),
  3558  				value.NewString("str1"),
  3559  			}),
  3560  			NewRecord([]value.Primary{
  3561  				value.NewString("1"),
  3562  				value.NewString("str1"),
  3563  			}),
  3564  			NewRecord([]value.Primary{
  3565  				value.NewString("2"),
  3566  				value.NewString("str2"),
  3567  			}),
  3568  			NewRecord([]value.Primary{
  3569  				value.NewString("2"),
  3570  				value.NewString("str2"),
  3571  			}),
  3572  		},
  3573  	}
  3574  
  3575  	calcView := &View{
  3576  		Header: []HeaderField{
  3577  			{View: "table2", Column: "column3", IsFromTable: true},
  3578  			{View: "table2", Column: "column4", IsFromTable: true},
  3579  		},
  3580  		RecordSet: RecordSet{
  3581  			NewRecord([]value.Primary{
  3582  				value.NewString("2"),
  3583  				value.NewString("str2"),
  3584  			}),
  3585  			NewRecord([]value.Primary{
  3586  				value.NewString("3"),
  3587  				value.NewString("str3"),
  3588  			}),
  3589  		},
  3590  	}
  3591  
  3592  	expect := &View{
  3593  		Header: []HeaderField{
  3594  			{View: "table1", Column: "column1", IsFromTable: true},
  3595  			{View: "table1", Column: "column2", IsFromTable: true},
  3596  		},
  3597  		RecordSet: RecordSet{
  3598  			NewRecord([]value.Primary{
  3599  				value.NewString("1"),
  3600  				value.NewString("str1"),
  3601  			}),
  3602  		},
  3603  	}
  3604  
  3605  	ctx := context.Background()
  3606  	err := view.Except(ctx, TestTx.Flags, calcView, false)
  3607  	if err != nil {
  3608  		t.Errorf("unexpected error %q", err)
  3609  	}
  3610  	if !reflect.DeepEqual(view, expect) {
  3611  		t.Errorf("except: view = %v, want %v", view, expect)
  3612  	}
  3613  
  3614  	view = &View{
  3615  		Header: []HeaderField{
  3616  			{View: "table1", Column: "column1", IsFromTable: true},
  3617  			{View: "table1", Column: "column2", IsFromTable: true},
  3618  		},
  3619  		RecordSet: RecordSet{
  3620  			NewRecord([]value.Primary{
  3621  				value.NewString("1"),
  3622  				value.NewString("str1"),
  3623  			}),
  3624  			NewRecord([]value.Primary{
  3625  				value.NewString("1"),
  3626  				value.NewString("str1"),
  3627  			}),
  3628  			NewRecord([]value.Primary{
  3629  				value.NewString("2"),
  3630  				value.NewString("str2"),
  3631  			}),
  3632  			NewRecord([]value.Primary{
  3633  				value.NewString("2"),
  3634  				value.NewString("str2"),
  3635  			}),
  3636  		},
  3637  	}
  3638  
  3639  	expect = &View{
  3640  		Header: []HeaderField{
  3641  			{View: "table1", Column: "column1", IsFromTable: true},
  3642  			{View: "table1", Column: "column2", IsFromTable: true},
  3643  		},
  3644  		RecordSet: RecordSet{
  3645  			NewRecord([]value.Primary{
  3646  				value.NewString("1"),
  3647  				value.NewString("str1"),
  3648  			}),
  3649  			NewRecord([]value.Primary{
  3650  				value.NewString("1"),
  3651  				value.NewString("str1"),
  3652  			}),
  3653  		},
  3654  	}
  3655  
  3656  	err = view.Except(ctx, TestTx.Flags, calcView, true)
  3657  	if err != nil {
  3658  		t.Errorf("unexpected error %q", err)
  3659  	}
  3660  	if !reflect.DeepEqual(view, expect) {
  3661  		t.Errorf("except all: view = %v, want %v", view, expect)
  3662  	}
  3663  }
  3664  
  3665  func TestView_Intersect(t *testing.T) {
  3666  	view := &View{
  3667  		Header: []HeaderField{
  3668  			{View: "table1", Column: "column1", IsFromTable: true},
  3669  			{View: "table1", Column: "column2", IsFromTable: true},
  3670  		},
  3671  		RecordSet: RecordSet{
  3672  			NewRecord([]value.Primary{
  3673  				value.NewString("1"),
  3674  				value.NewString("str1"),
  3675  			}),
  3676  			NewRecord([]value.Primary{
  3677  				value.NewString("1"),
  3678  				value.NewString("str1"),
  3679  			}),
  3680  			NewRecord([]value.Primary{
  3681  				value.NewString("2"),
  3682  				value.NewString("str2"),
  3683  			}),
  3684  			NewRecord([]value.Primary{
  3685  				value.NewString("2"),
  3686  				value.NewString("str2"),
  3687  			}),
  3688  		},
  3689  	}
  3690  
  3691  	calcView := &View{
  3692  		Header: []HeaderField{
  3693  			{View: "table2", Column: "column3", IsFromTable: true},
  3694  			{View: "table2", Column: "column4", IsFromTable: true},
  3695  		},
  3696  		RecordSet: RecordSet{
  3697  			NewRecord([]value.Primary{
  3698  				value.NewString("2"),
  3699  				value.NewString("str2"),
  3700  			}),
  3701  			NewRecord([]value.Primary{
  3702  				value.NewString("3"),
  3703  				value.NewString("str3"),
  3704  			}),
  3705  		},
  3706  	}
  3707  
  3708  	expect := &View{
  3709  		Header: []HeaderField{
  3710  			{View: "table1", Column: "column1", IsFromTable: true},
  3711  			{View: "table1", Column: "column2", IsFromTable: true},
  3712  		},
  3713  		RecordSet: RecordSet{
  3714  			NewRecord([]value.Primary{
  3715  				value.NewString("2"),
  3716  				value.NewString("str2"),
  3717  			}),
  3718  		},
  3719  	}
  3720  
  3721  	ctx := context.Background()
  3722  	err := view.Intersect(ctx, TestTx.Flags, calcView, false)
  3723  	if err != nil {
  3724  		t.Errorf("unexpected error %q", err)
  3725  	}
  3726  	if !reflect.DeepEqual(view, expect) {
  3727  		t.Errorf("intersect: view = %v, want %v", view, expect)
  3728  	}
  3729  
  3730  	view = &View{
  3731  		Header: []HeaderField{
  3732  			{View: "table1", Column: "column1", IsFromTable: true},
  3733  			{View: "table1", Column: "column2", IsFromTable: true},
  3734  		},
  3735  		RecordSet: RecordSet{
  3736  			NewRecord([]value.Primary{
  3737  				value.NewString("1"),
  3738  				value.NewString("str1"),
  3739  			}),
  3740  			NewRecord([]value.Primary{
  3741  				value.NewString("1"),
  3742  				value.NewString("str1"),
  3743  			}),
  3744  			NewRecord([]value.Primary{
  3745  				value.NewString("2"),
  3746  				value.NewString("str2"),
  3747  			}),
  3748  			NewRecord([]value.Primary{
  3749  				value.NewString("2"),
  3750  				value.NewString("str2"),
  3751  			}),
  3752  		},
  3753  	}
  3754  
  3755  	expect = &View{
  3756  		Header: []HeaderField{
  3757  			{View: "table1", Column: "column1", IsFromTable: true},
  3758  			{View: "table1", Column: "column2", IsFromTable: true},
  3759  		},
  3760  		RecordSet: RecordSet{
  3761  			NewRecord([]value.Primary{
  3762  				value.NewString("2"),
  3763  				value.NewString("str2"),
  3764  			}),
  3765  			NewRecord([]value.Primary{
  3766  				value.NewString("2"),
  3767  				value.NewString("str2"),
  3768  			}),
  3769  		},
  3770  	}
  3771  
  3772  	err = view.Intersect(ctx, TestTx.Flags, calcView, true)
  3773  	if err != nil {
  3774  		t.Errorf("unexpected error %q", err)
  3775  	}
  3776  	if !reflect.DeepEqual(view, expect) {
  3777  		t.Errorf("intersect all: view = %v, want %v", view, expect)
  3778  	}
  3779  }
  3780  
  3781  func TestView_FieldIndex(t *testing.T) {
  3782  	view := &View{
  3783  		Header: []HeaderField{
  3784  			{View: "table1", Column: "column1", Number: 1, IsFromTable: true},
  3785  			{View: "table1", Column: "column2", Number: 2, IsFromTable: true},
  3786  		},
  3787  	}
  3788  	fieldRef := parser.FieldReference{
  3789  		Column: parser.Identifier{Literal: "column1"},
  3790  	}
  3791  	expect := 0
  3792  
  3793  	idx, _ := view.FieldIndex(fieldRef)
  3794  	if idx != expect {
  3795  		t.Errorf("field index = %d, want %d", idx, expect)
  3796  	}
  3797  
  3798  	columnNum := parser.ColumnNumber{
  3799  		View:   parser.Identifier{Literal: "table1"},
  3800  		Number: value.NewInteger(2),
  3801  	}
  3802  	expect = 1
  3803  
  3804  	idx, _ = view.FieldIndex(columnNum)
  3805  	if idx != expect {
  3806  		t.Errorf("field index = %d, want %d", idx, expect)
  3807  	}
  3808  }
  3809  
  3810  func TestView_FieldIndices(t *testing.T) {
  3811  	view := &View{
  3812  		Header: []HeaderField{
  3813  			{View: "table1", Column: "column1", IsFromTable: true},
  3814  			{View: "table1", Column: "column2", IsFromTable: true},
  3815  		},
  3816  	}
  3817  	fields := []parser.QueryExpression{
  3818  		parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  3819  		parser.FieldReference{Column: parser.Identifier{Literal: "column1"}},
  3820  	}
  3821  	expect := []int{1, 0}
  3822  
  3823  	indices, _ := view.FieldIndices(fields)
  3824  	if !reflect.DeepEqual(indices, expect) {
  3825  		t.Errorf("field indices = %v, want %v", indices, expect)
  3826  	}
  3827  
  3828  	fields = []parser.QueryExpression{
  3829  		parser.FieldReference{Column: parser.Identifier{Literal: "column2"}},
  3830  		parser.FieldReference{Column: parser.Identifier{Literal: "notexist"}},
  3831  	}
  3832  	expectErr := "field notexist does not exist"
  3833  	_, err := view.FieldIndices(fields)
  3834  	if err == nil {
  3835  		t.Errorf("no error, want error %s", expectErr)
  3836  	} else if err.Error() != expectErr {
  3837  		t.Errorf("error = %s, want %s", err, expectErr)
  3838  	}
  3839  }
  3840  
  3841  func TestView_FieldViewName(t *testing.T) {
  3842  	view := &View{
  3843  		Header: []HeaderField{
  3844  			{View: "table1", Column: "column1", IsFromTable: true},
  3845  			{View: "table2", Column: "column2", IsFromTable: true},
  3846  		},
  3847  	}
  3848  	fieldRef := parser.FieldReference{
  3849  		Column: parser.Identifier{Literal: "column1"},
  3850  	}
  3851  	expect := "table1"
  3852  
  3853  	ref, _ := view.FieldViewName(fieldRef)
  3854  	if ref != expect {
  3855  		t.Errorf("field reference = %s, want %s", ref, expect)
  3856  	}
  3857  
  3858  	fieldRef = parser.FieldReference{
  3859  		Column: parser.Identifier{Literal: "notexist"},
  3860  	}
  3861  	expectErr := "field notexist does not exist"
  3862  	_, err := view.FieldViewName(fieldRef)
  3863  	if err == nil {
  3864  		t.Errorf("no error, want error %s", expectErr)
  3865  	} else if err.Error() != expectErr {
  3866  		t.Errorf("error = %s, want %s", err, expectErr)
  3867  	}
  3868  }
  3869  
  3870  func TestView_InternalRecordId(t *testing.T) {
  3871  	view := &View{
  3872  		Header: NewHeaderWithId("table1", []string{"column1", "column2"}),
  3873  		RecordSet: []Record{
  3874  			NewRecordWithId(0, []value.Primary{value.NewInteger(1), value.NewString("str1")}),
  3875  			NewRecordWithId(1, []value.Primary{value.NewInteger(2), value.NewString("str2")}),
  3876  			NewRecordWithId(2, []value.Primary{value.NewInteger(3), value.NewString("str3")}),
  3877  		},
  3878  	}
  3879  	ref := "table1"
  3880  	recordIndex := 1
  3881  	expect := 1
  3882  
  3883  	id, _ := view.InternalRecordId(ref, recordIndex)
  3884  	if id != expect {
  3885  		t.Errorf("field internal id = %d, want %d", id, expect)
  3886  	}
  3887  
  3888  	view.RecordSet[1][0] = NewCell(value.NewNull())
  3889  	expectErr := "internal record id is empty"
  3890  	_, err := view.InternalRecordId(ref, recordIndex)
  3891  	if err == nil {
  3892  		t.Errorf("no error, want error %s", expectErr)
  3893  	} else if err.Error() != expectErr {
  3894  		t.Errorf("error = %s, want %s", err, expectErr)
  3895  	}
  3896  
  3897  	view = &View{
  3898  		Header: []HeaderField{
  3899  			{View: "table1", Column: "column1", IsFromTable: true},
  3900  			{View: "table2", Column: "column2", IsFromTable: true},
  3901  		},
  3902  	}
  3903  	expectErr = "internal record id does not exist"
  3904  	_, err = view.InternalRecordId(ref, recordIndex)
  3905  	if err == nil {
  3906  		t.Errorf("no error, want error %s", expectErr)
  3907  	} else if err.Error() != expectErr {
  3908  		t.Errorf("error = %s, want %s", err, expectErr)
  3909  	}
  3910  }
  3911  
  3912  func BenchmarkView_GroupBy(b *testing.B) {
  3913  	view := &View{
  3914  		Header:    NewHeader("t", []string{"c1", "c2", "c3"}),
  3915  		RecordSet: make(RecordSet, 10000),
  3916  	}
  3917  	for i := int64(0); i < 10000; i++ {
  3918  		view.RecordSet[i] = NewRecord([]value.Primary{
  3919  			value.NewInteger(i),
  3920  			value.NewString(randomStr(1)),
  3921  			value.NewString(randomStr(1)),
  3922  		})
  3923  	}
  3924  
  3925  	ctx := context.Background()
  3926  	scope := NewReferenceScope(TestTx)
  3927  	clause := parser.GroupByClause{
  3928  		Items: []parser.QueryExpression{
  3929  			parser.FieldReference{Column: parser.Identifier{Literal: "c2"}},
  3930  			parser.FieldReference{Column: parser.Identifier{Literal: "c3"}},
  3931  		},
  3932  	}
  3933  
  3934  	b.ResetTimer()
  3935  	for i := 0; i < b.N; i++ {
  3936  		v := &View{
  3937  			Header:    view.Header.Copy(),
  3938  			RecordSet: view.RecordSet.Copy(),
  3939  		}
  3940  		_ = v.GroupBy(ctx, scope, clause)
  3941  	}
  3942  }
  3943  
  3944  func BenchmarkView_SelectDistinct(b *testing.B) {
  3945  	view := &View{
  3946  		Header:    NewHeader("t", []string{"c1", "c2", "c3"}),
  3947  		RecordSet: make(RecordSet, 10000),
  3948  	}
  3949  	for i := int64(0); i < 10000; i++ {
  3950  		view.RecordSet[i] = NewRecord([]value.Primary{
  3951  			value.NewInteger(i),
  3952  			value.NewString(randomStr(1)),
  3953  			value.NewString(randomStr(1)),
  3954  		})
  3955  	}
  3956  
  3957  	ctx := context.Background()
  3958  	scope := NewReferenceScope(TestTx)
  3959  	clause := parser.SelectClause{
  3960  		Distinct: parser.Token{Token: parser.DISTINCT},
  3961  		Fields: []parser.QueryExpression{
  3962  			parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "c1"}}},
  3963  			parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "c2"}}},
  3964  			parser.Field{Object: parser.FieldReference{Column: parser.Identifier{Literal: "c3"}}},
  3965  		},
  3966  	}
  3967  
  3968  	b.ResetTimer()
  3969  	for i := 0; i < b.N; i++ {
  3970  		v := &View{
  3971  			Header:    view.Header.Copy(),
  3972  			RecordSet: view.RecordSet.Copy(),
  3973  		}
  3974  		_ = v.Select(ctx, scope, clause)
  3975  	}
  3976  }