@@ -98,6 +98,25 @@ func TestEnumeration(t *testing.T) {
9898 assert .Contains (t , contents , "Name: romanNumerals" )
9999 assert .Contains (t , contents , "Element Count: 16" )
100100 })
101+
102+ t .Run ("Extend" , func (t * testing.T ) {
103+ startValues , err := romanNumerals .Values ()
104+ require .NoError (t , err )
105+
106+ additionalValues := []string {"xvii" , "xviii" , "xix" }
107+ extendedRomanNumerals , err := ExtendEnumeration (tdbCtx , romanNumerals , additionalValues )
108+ require .NoError (t , err )
109+ extendedValues , err := extendedRomanNumerals .Values ()
110+ require .NoError (t , err )
111+
112+ require .Equal (t , append (startValues .([]string ), additionalValues ... ), extendedValues )
113+ })
114+
115+ t .Run ("ExtendTypeConformance" , func (t * testing.T ) {
116+ _ , err := ExtendEnumeration (tdbCtx , romanNumerals , []int32 {10 })
117+ require .Error (t , err )
118+ require .Contains (t , err .Error (), "type mismatch" )
119+ })
101120}
102121
103122func TestEnumerationAndSchema (t * testing.T ) {
@@ -246,6 +265,163 @@ func TestEnumerationQueryCondition(t *testing.T) {
246265 assert .Equal (t , []uint8 {1 , 5 , 0 }, greekBuffer [0 :3 ])
247266 assert .Equal (t , []uint8 {1 , 5 , 0 }, romanBuffer [0 :3 ])
248267 })
268+
269+ t .Run ("LabelNotExists" , func (t * testing.T ) {
270+ array , err := NewArray (tdbCtx , arrayPath )
271+ require .NoError (t , err )
272+ require .NoError (t , array .Open (TILEDB_READ ))
273+ rQuery , err := NewQuery (tdbCtx , array )
274+ require .NoError (t , err )
275+ qcR , err := NewQueryCondition (tdbCtx , "roman" , TILEDB_QUERY_CONDITION_EQ , "C" )
276+ require .NoError (t , err )
277+ require .NoError (t , rQuery .SetQueryCondition (qcR ))
278+
279+ rowsBuffer := make ([]uint8 , 16 )
280+ _ , err = rQuery .SetDataBuffer ("rows" , rowsBuffer )
281+ require .NoError (t , err )
282+ colsBuffer := make ([]uint8 , 16 )
283+ _ , err = rQuery .SetDataBuffer ("cols" , colsBuffer )
284+ require .NoError (t , err )
285+ err = rQuery .Submit ()
286+ require .Error (t , err )
287+ require .Contains (t , err .Error (), "Enumeration value not found" )
288+ require .NoError (t , array .Close ())
289+ })
290+ }
291+
292+ func TestEnumerationEmpty (t * testing.T ) {
293+ schema := arraySchemaWithEmptyEnumerations (t )
294+
295+ config , err := NewConfig ()
296+ require .NoError (t , err )
297+ tdbCtx , err := NewContext (config )
298+ require .NoError (t , err )
299+
300+ arrayPath := t .TempDir ()
301+ array , err := NewArray (tdbCtx , arrayPath )
302+ require .NoError (t , err )
303+ require .NoError (t , array .Create (schema ))
304+ }
305+
306+ func TestEnumerationEvolution (t * testing.T ) {
307+ schema := arraySchemaWithEnumerations (t )
308+
309+ config , err := NewConfig ()
310+ require .NoError (t , err )
311+ tdbCtx , err := NewContext (config )
312+ require .NoError (t , err )
313+
314+ arrayPath := t .TempDir ()
315+ array , err := NewArray (tdbCtx , arrayPath )
316+ require .NoError (t , err )
317+ require .NoError (t , array .Create (schema ))
318+
319+ //=====
320+ // write to the array. Each cell gets the row order rank + 10
321+ // The array will look like
322+ // 10 11 12 13
323+ // 14 15 16 17
324+ // 18 19 20 21
325+ // 22 23 24 25
326+
327+ array , err = NewArray (tdbCtx , arrayPath )
328+ require .NoError (t , err )
329+ require .NoError (t , array .Open (TILEDB_WRITE ))
330+ wQuery , err := NewQuery (tdbCtx , array )
331+ require .NoError (t , err )
332+ _ , err = wQuery .SetDataBuffer ("rows" , []uint8 {1 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 })
333+ require .NoError (t , err )
334+ _ , err = wQuery .SetDataBuffer ("cols" , []uint8 {1 , 2 , 3 , 4 , 1 , 2 , 3 , 4 , 1 , 2 , 3 , 4 , 1 , 2 , 3 , 4 })
335+ require .NoError (t , err )
336+ _ , err = wQuery .SetDataBuffer ("greek" , []uint8 {10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 })
337+ require .NoError (t , err )
338+ _ , err = wQuery .SetDataBuffer ("roman" , []uint8 {10 , 11 , 12 , 13 , 14 , 15 , 16 , 17 , 18 , 19 , 20 , 21 , 22 , 23 , 24 , 25 })
339+ require .NoError (t , err )
340+ require .NoError (t , wQuery .Submit ())
341+ require .NoError (t , array .Close ())
342+
343+ // the enumerations currently can handle values [1, 16]. We extend them to [1, 25]
344+ array , err = NewArray (tdbCtx , arrayPath )
345+ require .NoError (t , err )
346+ require .NoError (t , array .Open (TILEDB_READ ))
347+ romanEnum , err := array .GetEnumeration ("romanNumerals" )
348+ require .NoError (t , err )
349+ romanEnumExt , err := ExtendEnumeration (tdbCtx , romanEnum , []string {"xvii" , "xviii" , "xix" , "xx" , "xxi" , "xxii" , "xxiii" , "xxiv" , "xxv" })
350+ require .NoError (t , err )
351+ greekEnum , err := array .GetEnumeration ("greekNumerals" )
352+ require .NoError (t , err )
353+ greekEnumExt , err := ExtendEnumeration (tdbCtx , greekEnum , []string {"ιζ" , "ιη" , "ιθ" , "κ" , "κα" , "κβ" , "κγ" , "κδ" , "κε" })
354+ require .NoError (t , err )
355+ require .NoError (t , array .Close ())
356+
357+ // apply the schema evolution
358+ ase , err := NewArraySchemaEvolution (tdbCtx )
359+ require .NoError (t , err )
360+ ase .ApplyExtendedEnumeration (romanEnumExt )
361+ require .NoError (t , err )
362+ ase .ApplyExtendedEnumeration (greekEnumExt )
363+ require .NoError (t , err )
364+ err = ase .Evolve (arrayPath )
365+ require .NoError (t , err )
366+
367+ // now query the array to verify the new values can be applied
368+ array , err = NewArray (tdbCtx , arrayPath )
369+ require .NoError (t , err )
370+ require .NoError (t , array .Open (TILEDB_READ ))
371+ rQuery , err := NewQuery (tdbCtx , array )
372+ require .NoError (t , err )
373+ qcR , err := NewQueryCondition (tdbCtx , "roman" , TILEDB_QUERY_CONDITION_EQ , "xxv" )
374+ require .NoError (t , err )
375+ qcG , err := NewQueryCondition (tdbCtx , "greek" , TILEDB_QUERY_CONDITION_EQ , "κ" )
376+ require .NoError (t , err )
377+ qc , err := NewQueryConditionCombination (tdbCtx , qcR , TILEDB_QUERY_CONDITION_OR , qcG )
378+ require .NoError (t , err )
379+ require .NoError (t , rQuery .SetQueryCondition (qc ))
380+
381+ rowsBuffer := make ([]uint8 , 16 )
382+ _ , err = rQuery .SetDataBuffer ("rows" , rowsBuffer )
383+ require .NoError (t , err )
384+ colsBuffer := make ([]uint8 , 16 )
385+ _ , err = rQuery .SetDataBuffer ("cols" , colsBuffer )
386+ require .NoError (t , err )
387+ greekBuffer := make ([]uint8 , 16 )
388+ _ , err = rQuery .SetDataBuffer ("greek" , greekBuffer )
389+ require .NoError (t , err )
390+ romanBuffer := make ([]uint8 , 16 )
391+ _ , err = rQuery .SetDataBuffer ("roman" , romanBuffer )
392+ require .NoError (t , err )
393+
394+ require .NoError (t , rQuery .Submit ())
395+ require .NoError (t , array .Close ())
396+
397+ assert .Equal (t , []uint8 {3 , 4 , 0 }, rowsBuffer [0 :3 ])
398+ assert .Equal (t , []uint8 {2 , 3 , 0 }, colsBuffer [0 :3 ])
399+ assert .Equal (t , []uint8 {19 , 24 , 0 }, greekBuffer [0 :3 ])
400+ assert .Equal (t , []uint8 {19 , 24 , 0 }, romanBuffer [0 :3 ])
401+ }
402+
403+ type bogus string
404+
405+ func (b bogus ) String () string {
406+ return "i am " + string (b )
407+ }
408+
409+ func TestEnumerationDerivedValues (t * testing.T ) {
410+ // This tests that we use reflection correctly and we operate on the original
411+ // values of types based on strings. Check newEnumeration and ExtendEnumeration
412+ // which use reflect.ValueOf(v).String()
413+
414+ config , err := NewConfig ()
415+ require .NoError (t , err )
416+ tdbCtx , err := NewContext (config )
417+ require .NoError (t , err )
418+
419+ bogusEnum , err := NewOrderedEnumeration (tdbCtx , "bogusEnum" , []bogus {"bogus1" , "bogus2" })
420+ require .NoError (t , err )
421+
422+ bogusValues , err := bogusEnum .Values ()
423+ require .NoError (t , err )
424+ assert .EqualValues (t , bogusValues , []string {"bogus1" , "bogus2" })
249425}
250426
251427func arraySchemaWithEnumerations (t * testing.T ) * ArraySchema {
@@ -291,3 +467,45 @@ func arraySchemaWithEnumerations(t *testing.T) *ArraySchema {
291467
292468 return schema
293469}
470+
471+ func arraySchemaWithEmptyEnumerations (t * testing.T ) * ArraySchema {
472+ config , err := NewConfig ()
473+ require .NoError (t , err )
474+ tdbCtx , err := NewContext (config )
475+ require .NoError (t , err )
476+
477+ //=====
478+ // create a sparse array [1,4]x[1,4]
479+ //
480+
481+ schema , err := NewArraySchema (tdbCtx , TILEDB_SPARSE )
482+ require .NoError (t , err )
483+ require .NoError (t , schema .SetCellOrder (TILEDB_ROW_MAJOR ))
484+ require .NoError (t , schema .SetTileOrder (TILEDB_ROW_MAJOR ))
485+
486+ domain , err := NewDomain (tdbCtx )
487+ require .NoError (t , err )
488+ dimRows , err := NewDimension (tdbCtx , "rows" , TILEDB_UINT8 , []uint8 {1 , 4 }, uint8 (2 ))
489+ require .NoError (t , err )
490+ dimCols , err := NewDimension (tdbCtx , "cols" , TILEDB_UINT8 , []uint8 {1 , 4 }, uint8 (2 ))
491+ require .NoError (t , err )
492+ require .NoError (t , domain .AddDimensions (dimRows , dimCols ))
493+ require .NoError (t , schema .SetDomain (domain ))
494+
495+ greekNumerals , err := NewOrderedEnumeration [string ](tdbCtx , "greekNumerals" , nil )
496+ require .NoError (t , err )
497+ require .NoError (t , schema .AddEnumeration (greekNumerals ))
498+ romanNumerals , err := NewOrderedEnumeration [string ](tdbCtx , "romanNumerals" , nil )
499+ require .NoError (t , err )
500+ require .NoError (t , schema .AddEnumeration (romanNumerals ))
501+
502+ greekAttr , err := NewAttribute (tdbCtx , "greek" , TILEDB_UINT8 )
503+ require .NoError (t , err )
504+ require .NoError (t , greekAttr .SetEnumerationName ("greekNumerals" ))
505+ romanAttr , err := NewAttribute (tdbCtx , "roman" , TILEDB_UINT8 )
506+ require .NoError (t , err )
507+ require .NoError (t , romanAttr .SetEnumerationName ("romanNumerals" ))
508+ require .NoError (t , schema .AddAttributes (greekAttr , romanAttr ))
509+
510+ return schema
511+ }
0 commit comments