github.com/matrixorigin/matrixone@v0.7.0/pkg/vm/engine/tae/db/hidden_test.go (about)

     1  // Copyright 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package db
    16  
    17  import (
    18  	"sort"
    19  	"testing"
    20  
    21  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/catalog"
    22  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/common"
    23  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/iface/data"
    24  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/model"
    25  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/tasks"
    26  	"github.com/matrixorigin/matrixone/pkg/vm/engine/tae/testutils"
    27  	"github.com/stretchr/testify/assert"
    28  )
    29  
    30  // Testing Steps
    31  // 1. Mock schema with PK.
    32  // 2. Append data (append rows less than a block) and commit. Scan hidden column and check.
    33  // 3. Append data and the total rows is more than a block. Commit and then compact the full block.
    34  // 4. Scan hidden column and check.
    35  // 5. Append data and the total rows is more than a segment. Commit and then merge sort the full segment.
    36  // 6. Scan hidden column and check.
    37  func TestHiddenWithPK1(t *testing.T) {
    38  	defer testutils.AfterTest(t)()
    39  	testutils.EnsureNoLeak(t)
    40  	tae := initDB(t, nil)
    41  	defer tae.Close()
    42  	schema := catalog.MockSchemaAll(13, 2)
    43  	schema.BlockMaxRows = 10
    44  	schema.SegmentMaxBlocks = 2
    45  	bat := catalog.MockBatch(schema, int(schema.BlockMaxRows*4))
    46  	defer bat.Close()
    47  	bats := bat.Split(10)
    48  
    49  	txn, _, rel := createRelationNoCommit(t, tae, defaultTestDB, schema, true)
    50  	err := rel.Append(bats[0])
    51  	{
    52  		offsets := make([]uint32, 0)
    53  		it := rel.MakeBlockIt()
    54  		for it.Valid() {
    55  			blk := it.GetBlock()
    56  			view, err := blk.GetColumnDataById(schema.PhyAddrKey.Idx, nil)
    57  			assert.NoError(t, err)
    58  			defer view.Close()
    59  			fp := blk.Fingerprint()
    60  			_ = view.GetData().Foreach(func(v any, _ int) (err error) {
    61  				sid, bid, offset := model.DecodePhyAddrKeyFromValue(v)
    62  				t.Logf("sid=%d,bid=%d,offset=%d", sid, bid, offset)
    63  				assert.Equal(t, fp.SegmentID, sid)
    64  				assert.Equal(t, fp.BlockID, bid)
    65  				offsets = append(offsets, offset)
    66  				return
    67  			}, nil)
    68  			it.Next()
    69  		}
    70  		// sort.Slice(offsets, func(i, j int) bool { return offsets[i] < offsets[j] })
    71  		// assert.Equal(t, []uint32{0, 1, 2, 3}, offsets)
    72  	}
    73  	assert.NoError(t, err)
    74  	assert.NoError(t, txn.Commit())
    75  
    76  	txn, rel = getDefaultRelation(t, tae, schema.Name)
    77  	{
    78  		blk := getOneBlock(rel)
    79  		view, err := blk.GetColumnDataByName(catalog.PhyAddrColumnName, nil)
    80  		assert.NoError(t, err)
    81  		defer view.Close()
    82  		offsets := make([]uint32, 0)
    83  		fp := blk.Fingerprint()
    84  		t.Log(fp.String())
    85  		_ = view.GetData().Foreach(func(v any, _ int) (err error) {
    86  			sid, bid, offset := model.DecodePhyAddrKeyFromValue(v)
    87  			t.Logf("sid=%d,bid=%d,offset=%d", sid, bid, offset)
    88  			assert.Equal(t, fp.SegmentID, sid)
    89  			assert.Equal(t, fp.BlockID, bid)
    90  			offsets = append(offsets, offset)
    91  			return
    92  		}, nil)
    93  		sort.Slice(offsets, func(i, j int) bool { return offsets[i] < offsets[j] })
    94  		assert.Equal(t, []uint32{0, 1, 2, 3}, offsets)
    95  	}
    96  
    97  	assert.NoError(t, err)
    98  	assert.NoError(t, txn.Commit())
    99  
   100  	txn, rel = getDefaultRelation(t, tae, schema.Name)
   101  	err = rel.Append(bats[1])
   102  	assert.NoError(t, err)
   103  	err = rel.Append(bats[2])
   104  	assert.NoError(t, err)
   105  	err = rel.Append(bats[3])
   106  	assert.NoError(t, err)
   107  	err = rel.Append(bats[4])
   108  	assert.NoError(t, err)
   109  	err = rel.Append(bats[5])
   110  	assert.NoError(t, err)
   111  	assert.NoError(t, txn.Commit())
   112  
   113  	compactBlocks(t, 0, tae, "db", schema, false)
   114  
   115  	txn, rel = getDefaultRelation(t, tae, schema.Name)
   116  	var segMeta *catalog.SegmentEntry
   117  	{
   118  		it := rel.MakeBlockIt()
   119  		for it.Valid() {
   120  			blk := it.GetBlock()
   121  			view, err := blk.GetColumnDataByName(catalog.PhyAddrColumnName, nil)
   122  			assert.NoError(t, err)
   123  			defer view.Close()
   124  			offsets := make([]uint32, 0)
   125  			meta := blk.GetMeta().(*catalog.BlockEntry)
   126  			t.Log(meta.String())
   127  			_ = view.GetData().Foreach(func(v any, _ int) (err error) {
   128  				sid, bid, offset := model.DecodePhyAddrKeyFromValue(v)
   129  				// t.Logf("sid=%d,bid=%d,offset=%d", sid, bid, offset)
   130  				assert.Equal(t, meta.GetSegment().ID, sid)
   131  				assert.Equal(t, meta.ID, bid)
   132  				offsets = append(offsets, offset)
   133  				return
   134  			}, nil)
   135  			sort.Slice(offsets, func(i, j int) bool { return offsets[i] < offsets[j] })
   136  			if meta.IsAppendable() {
   137  				assert.Equal(t, []uint32{0, 1, 2, 3}, offsets)
   138  			} else {
   139  				segMeta = meta.GetSegment()
   140  				assert.Equal(t, []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, offsets)
   141  			}
   142  			it.Next()
   143  		}
   144  	}
   145  
   146  	assert.NoError(t, txn.Commit())
   147  	{
   148  		seg := segMeta.GetSegmentData()
   149  		factory, taskType, scopes, err := seg.BuildCompactionTaskFactory()
   150  		assert.NoError(t, err)
   151  		task, err := tae.Scheduler.ScheduleMultiScopedTxnTask(tasks.WaitableCtx, taskType, scopes, factory)
   152  		assert.NoError(t, err)
   153  		err = task.WaitDone()
   154  		assert.NoError(t, err)
   155  	}
   156  
   157  	txn, rel = getDefaultRelation(t, tae, schema.Name)
   158  	{
   159  		it := rel.MakeBlockIt()
   160  		for it.Valid() {
   161  			blk := it.GetBlock()
   162  			view, err := blk.GetColumnDataByName(catalog.PhyAddrColumnName, nil)
   163  			assert.NoError(t, err)
   164  			defer view.Close()
   165  			offsets := make([]uint32, 0)
   166  			meta := blk.GetMeta().(*catalog.BlockEntry)
   167  			t.Log(meta.String())
   168  			t.Log(meta.GetSegment().String())
   169  			_ = view.GetData().Foreach(func(v any, _ int) (err error) {
   170  				sid, bid, offset := model.DecodePhyAddrKeyFromValue(v)
   171  				// t.Logf("sid=%d,bid=%d,offset=%d", sid, bid, offset)
   172  				assert.Equal(t, meta.GetSegment().ID, sid)
   173  				assert.Equal(t, meta.ID, bid)
   174  				offsets = append(offsets, offset)
   175  				return
   176  			}, nil)
   177  			sort.Slice(offsets, func(i, j int) bool { return offsets[i] < offsets[j] })
   178  			if meta.IsAppendable() {
   179  				assert.Equal(t, []uint32{0, 1, 2, 3}, offsets)
   180  			} else {
   181  				assert.Equal(t, []uint32{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, offsets)
   182  			}
   183  			it.Next()
   184  		}
   185  	}
   186  
   187  	assert.NoError(t, txn.Commit())
   188  	t.Log(tae.Catalog.SimplePPString(common.PPL1))
   189  }
   190  
   191  // Testing Steps
   192  // 1. Mock schema w/o primary key
   193  // 2. Append data (append rows less than a block)
   194  func TestHidden2(t *testing.T) {
   195  	defer testutils.AfterTest(t)()
   196  	testutils.EnsureNoLeak(t)
   197  	tae := initDB(t, nil)
   198  	defer tae.Close()
   199  	schema := catalog.MockSchemaAll(3, -1)
   200  	schema.BlockMaxRows = 10
   201  	schema.SegmentMaxBlocks = 2
   202  	bat := catalog.MockBatch(schema, int(schema.BlockMaxRows*4))
   203  	defer bat.Close()
   204  	bats := bat.Split(10)
   205  
   206  	txn, _, rel := createRelationNoCommit(t, tae, defaultTestDB, schema, true)
   207  	err := rel.Append(bats[0])
   208  	{
   209  		blk := getOneBlock(rel)
   210  		var hidden *model.ColumnView
   211  		for _, def := range schema.ColDefs {
   212  			view, err := blk.GetColumnDataById(def.Idx, nil)
   213  			assert.NoError(t, err)
   214  			defer view.Close()
   215  			assert.Equal(t, bats[0].Length(), view.Length())
   216  			if def.IsPhyAddr() {
   217  				hidden = view
   218  			}
   219  		}
   220  		_ = hidden.GetData().Foreach(func(key any, _ int) (err error) {
   221  			sid, bid, offset := model.DecodePhyAddrKeyFromValue(key)
   222  			t.Logf("sid=%d,bid=%d,offset=%d", sid, bid, offset)
   223  			v, err := rel.GetValueByPhyAddrKey(key, schema.PhyAddrKey.Idx)
   224  			assert.NoError(t, err)
   225  			assert.Equal(t, key, v)
   226  			if offset == 1 {
   227  				err = rel.DeleteByPhyAddrKey(key)
   228  				assert.NoError(t, err)
   229  			}
   230  			return
   231  		}, nil)
   232  		for _, def := range schema.ColDefs {
   233  			view, err := blk.GetColumnDataById(def.Idx, nil)
   234  			assert.NoError(t, err)
   235  			defer view.Close()
   236  			view.ApplyDeletes()
   237  			assert.Equal(t, bats[0].Length()-1, view.Length())
   238  		}
   239  	}
   240  	assert.NoError(t, err)
   241  	assert.NoError(t, txn.Commit())
   242  
   243  	txn, rel = getDefaultRelation(t, tae, schema.Name)
   244  	{
   245  		blk := getOneBlock(rel)
   246  		var hidden *model.ColumnView
   247  		for _, def := range schema.ColDefs {
   248  			view, err := blk.GetColumnDataById(def.Idx, nil)
   249  			assert.NoError(t, err)
   250  			defer view.Close()
   251  			assert.Equal(t, bats[0].Length()-1, view.Length())
   252  			if def.IsPhyAddr() {
   253  				hidden = view
   254  			}
   255  		}
   256  		_ = hidden.GetData().Foreach(func(key any, _ int) (err error) {
   257  			sid, bid, offset := model.DecodePhyAddrKeyFromValue(key)
   258  			t.Logf("sid=%d,bid=%d,offset=%d", sid, bid, offset)
   259  			v, err := rel.GetValueByPhyAddrKey(key, schema.PhyAddrKey.Idx)
   260  			assert.NoError(t, err)
   261  			assert.Equal(t, key, v)
   262  			if offset == 1 {
   263  				err = rel.DeleteByPhyAddrKey(key)
   264  				assert.NoError(t, err)
   265  			}
   266  			return
   267  		}, nil)
   268  	}
   269  	err = rel.Append(bats[1])
   270  	assert.NoError(t, err)
   271  	err = rel.Append(bats[1])
   272  	assert.NoError(t, err)
   273  	err = rel.Append(bats[1])
   274  	assert.NoError(t, err)
   275  	err = rel.Append(bats[2])
   276  	assert.NoError(t, err)
   277  	err = rel.Append(bats[2])
   278  	assert.NoError(t, err)
   279  	err = rel.Append(bats[2])
   280  	assert.NoError(t, err)
   281  	assert.NoError(t, txn.Commit())
   282  
   283  	txn, rel = getDefaultRelation(t, tae, schema.Name)
   284  	{
   285  		it := rel.MakeBlockIt()
   286  		blks := make([]data.Block, 0)
   287  		for it.Valid() {
   288  			blk := it.GetBlock().GetMeta().(*catalog.BlockEntry).GetBlockData()
   289  			blks = append(blks, blk)
   290  			it.Next()
   291  		}
   292  		for _, blk := range blks {
   293  			factory, taskType, scopes, err := blk.BuildCompactionTaskFactory()
   294  			assert.NoError(t, err)
   295  			task, err := tae.Scheduler.ScheduleMultiScopedTxnTask(tasks.WaitableCtx, taskType, scopes, factory)
   296  			assert.NoError(t, err)
   297  			err = task.WaitDone()
   298  			assert.NoError(t, err)
   299  		}
   300  	}
   301  	assert.NoError(t, txn.Commit())
   302  
   303  	t.Log(tae.Catalog.SimplePPString(common.PPL1))
   304  	txn, rel = getDefaultRelation(t, tae, schema.Name)
   305  	{
   306  		it := rel.MakeSegmentIt()
   307  		segs := make([]data.Segment, 0)
   308  		for it.Valid() {
   309  			seg := it.GetSegment().GetMeta().(*catalog.SegmentEntry).GetSegmentData()
   310  			segs = append(segs, seg)
   311  			it.Next()
   312  		}
   313  		for _, seg := range segs {
   314  			factory, taskType, scopes, err := seg.BuildCompactionTaskFactory()
   315  			assert.NoError(t, err)
   316  			if factory == nil {
   317  				continue
   318  			}
   319  			task, err := tae.Scheduler.ScheduleMultiScopedTxnTask(tasks.WaitableCtx, taskType, scopes, factory)
   320  			assert.NoError(t, err)
   321  			err = task.WaitDone()
   322  			assert.NoError(t, err)
   323  		}
   324  
   325  	}
   326  	assert.NoError(t, txn.Commit())
   327  
   328  	txn, rel = getDefaultRelation(t, tae, schema.Name)
   329  	t.Log(rel.Rows())
   330  	assert.Equal(t, int64(26), rel.Rows())
   331  	{
   332  		it := rel.MakeBlockIt()
   333  		rows := 0
   334  		for it.Valid() {
   335  			blk := it.GetBlock()
   336  			hidden, err := blk.GetColumnDataById(schema.PhyAddrKey.Idx, nil)
   337  			assert.NoError(t, err)
   338  			defer hidden.Close()
   339  			hidden.ApplyDeletes()
   340  			rows += hidden.Length()
   341  			it.Next()
   342  		}
   343  		assert.Equal(t, 26, rows)
   344  	}
   345  	assert.NoError(t, txn.Commit())
   346  	t.Log(tae.Catalog.SimplePPString(common.PPL1))
   347  }