[Groonga-commit] groonga/grnxx at 426c46b [master] Gnx: implement GrnColumn.SetValue() and add tests.

Back to archive index

susumu.yata null+****@clear*****
Fri May 1 10:32:07 JST 2015


susumu.yata	2015-05-01 10:32:07 +0900 (Fri, 01 May 2015)

  New Revision: 426c46b917a21862d443552ceec52a00a2de9417
  https://github.com/groonga/grnxx/commit/426c46b917a21862d443552ceec52a00a2de9417

  Message:
    Gnx: implement GrnColumn.SetValue() and add tests.

  Modified files:
    go3/gnx/grn.go
    go3/gnx/grn_cgo.c
    go3/gnx/grn_cgo.h
    go3/gnx/grn_test.go

  Modified: go3/gnx/grn.go (+184 -0)
===================================================================
--- go3/gnx/grn.go    2015-05-01 04:06:02 +0900 (cfa3983)
+++ go3/gnx/grn.go    2015-05-01 10:32:07 +0900 (391ec03)
@@ -771,3 +771,187 @@ func newGrnColumn(table *GrnTable, obj *C.grn_obj, name string,
 	column.valueTable = valueTable
 	return &column
 }
+
+// setBool() assigns a Bool value.
+func (column *GrnColumn) setBool(id Int, value Bool) error {
+	if (column.valueType != BoolID) || column.isVector {
+		return fmt.Errorf("value type conflict")
+	}
+	var grnValue C.grn_bool = C.GRN_FALSE
+	if value == True {
+		grnValue = C.GRN_TRUE
+	}
+	if ok := C.grn_cgo_column_set_bool(column.table.db.ctx, column.obj,
+		C.grn_id(id), grnValue); ok != C.GRN_TRUE {
+		return fmt.Errorf("grn_cgo_column_set_bool() failed")
+	}
+	return nil
+}
+
+// setInt() assigns an Int value.
+func (column *GrnColumn) setInt(id Int, value Int) error {
+	if (column.valueType != IntID) || column.isVector {
+		return fmt.Errorf("value type conflict")
+	}
+	grnValue := C.int64_t(value)
+	if ok := C.grn_cgo_column_set_int(column.table.db.ctx, column.obj,
+		C.grn_id(id), grnValue); ok != C.GRN_TRUE {
+		return fmt.Errorf("grn_cgo_column_set_int() failed")
+	}
+	return nil
+}
+
+// setFloat() assigns a Float value.
+func (column *GrnColumn) setFloat(id Int, value Float) error {
+	if (column.valueType != FloatID) || column.isVector {
+		return fmt.Errorf("value type conflict")
+	}
+	grnValue := C.double(value)
+	if ok := C.grn_cgo_column_set_float(column.table.db.ctx, column.obj,
+		C.grn_id(id), grnValue); ok != C.GRN_TRUE {
+		return fmt.Errorf("grn_cgo_column_set_float() failed")
+	}
+	return nil
+}
+
+// setGeoPoint() assigns a GeoPoint value.
+func (column *GrnColumn) setGeoPoint(id Int, value GeoPoint) error {
+	if (column.valueType != GeoPointID) || column.isVector {
+		return fmt.Errorf("value type conflict")
+	}
+	grnValue := C.grn_geo_point{C.int(value.Latitude), C.int(value.Longitude)}
+	if ok := C.grn_cgo_column_set_geo_point(column.table.db.ctx, column.obj,
+		C.grn_id(id), grnValue); ok != C.GRN_TRUE {
+		return fmt.Errorf("grn_cgo_column_set_geo_point() failed")
+	}
+	return nil
+}
+
+// setText() assigns a Text value.
+func (column *GrnColumn) setText(id Int, value Text) error {
+	if (column.valueType != TextID) || column.isVector {
+		return fmt.Errorf("value type conflict")
+	}
+	var grnValue C.grn_cgo_text
+	if len(value) != 0 {
+		grnValue.ptr = (*C.char)(unsafe.Pointer(&value[0]))
+		grnValue.size = C.size_t(len(value))
+	}
+	if ok := C.grn_cgo_column_set_text(column.table.db.ctx, column.obj,
+		C.grn_id(id), &grnValue); ok != C.GRN_TRUE {
+		return fmt.Errorf("grn_cgo_column_set_text() failed")
+	}
+	return nil
+}
+
+// setBoolVector() assigns a Bool vector.
+func (column *GrnColumn) setBoolVector(id Int, value []Bool) error {
+	grnValue := make([]C.grn_bool, len(value))
+	for i, v := range value {
+		if v == True {
+			grnValue[i] = C.GRN_TRUE
+		}
+	}
+	var grnVector C.grn_cgo_vector
+	if len(grnValue) != 0 {
+		grnVector.ptr = unsafe.Pointer(&grnValue[0])
+		grnVector.size = C.size_t(len(grnValue))
+	}
+	if ok := C.grn_cgo_column_set_bool_vector(column.table.db.ctx, column.obj,
+		C.grn_id(id), &grnVector); ok != C.GRN_TRUE {
+		return fmt.Errorf("grn_cgo_column_set_bool_vector() failed")
+	}
+	return nil
+}
+
+// setIntVector() assigns an Int vector.
+func (column *GrnColumn) setIntVector(id Int, value []Int) error {
+	var grnVector C.grn_cgo_vector
+	if len(value) != 0 {
+		grnVector.ptr = unsafe.Pointer(&value[0])
+		grnVector.size = C.size_t(len(value))
+	}
+	if ok := C.grn_cgo_column_set_int_vector(column.table.db.ctx, column.obj,
+		C.grn_id(id), &grnVector); ok != C.GRN_TRUE {
+		return fmt.Errorf("grn_cgo_column_set_int_vector() failed")
+	}
+	return nil
+}
+
+// setFloatVector() assigns a Float vector.
+func (column *GrnColumn) setFloatVector(id Int, value []Float) error {
+	var grnVector C.grn_cgo_vector
+	if len(value) != 0 {
+		grnVector.ptr = unsafe.Pointer(&value[0])
+		grnVector.size = C.size_t(len(value))
+	}
+	if ok := C.grn_cgo_column_set_float_vector(column.table.db.ctx, column.obj,
+		C.grn_id(id), &grnVector); ok != C.GRN_TRUE {
+		return fmt.Errorf("grn_cgo_column_set_float_vector() failed")
+	}
+	return nil
+}
+
+// setGeoPointVector() assigns a GeoPoint vector.
+func (column *GrnColumn) setGeoPointVector(id Int, value []GeoPoint) error {
+	var grnVector C.grn_cgo_vector
+	if len(value) != 0 {
+		grnVector.ptr = unsafe.Pointer(&value[0])
+		grnVector.size = C.size_t(len(value))
+	}
+	if ok := C.grn_cgo_column_set_geo_point_vector(column.table.db.ctx,
+		column.obj, C.grn_id(id), &grnVector); ok != C.GRN_TRUE {
+		return fmt.Errorf("grn_cgo_column_set_geo_point_vector() failed")
+	}
+	return nil
+}
+
+// setTextVector() assigns a Text vector.
+func (column *GrnColumn) setTextVector(id Int, value []Text) error {
+	grnValue := make([]C.grn_cgo_text, len(value))
+	for i, v := range value {
+		if len(v) != 0 {
+			grnValue[i].ptr = (*C.char)(unsafe.Pointer(&v[0]))
+			grnValue[i].size = C.size_t(len(v))
+		}
+	}
+	var grnVector C.grn_cgo_vector
+	if len(grnValue) != 0 {
+		grnVector.ptr = unsafe.Pointer(&grnValue[0])
+		grnVector.size = C.size_t(len(grnValue))
+	}
+	if ok := C.grn_cgo_column_set_text_vector(column.table.db.ctx,
+		column.obj, C.grn_id(id), &grnVector); ok != C.GRN_TRUE {
+		return fmt.Errorf("grn_cgo_column_set_text_vector() failed")
+	}
+	return nil
+}
+
+// SetValue() assigns a value.
+func (column *GrnColumn) SetValue(id Int, value interface{}) error {
+	switch v := value.(type) {
+	case Bool:
+		return column.setBool(id, v)
+	case Int:
+		return column.setInt(id, v)
+	case Float:
+		return column.setFloat(id, v)
+	case GeoPoint:
+		return column.setGeoPoint(id, v)
+	case Text:
+		return column.setText(id, v)
+	case []Bool:
+		return column.setBoolVector(id, v)
+	case []Int:
+		return column.setIntVector(id, v)
+	case []Float:
+		return column.setFloatVector(id, v)
+	case []GeoPoint:
+		return column.setGeoPointVector(id, v)
+	case []Text:
+		return column.setTextVector(id, v)
+	default:
+		return fmt.Errorf("unsupported value type: name = <%s>",
+			reflect.TypeOf(value).Name())
+	}
+}

  Modified: go3/gnx/grn_cgo.c (+127 -0)
===================================================================
--- go3/gnx/grn_cgo.c    2015-05-01 04:06:02 +0900 (c120c36)
+++ go3/gnx/grn_cgo.c    2015-05-01 10:32:07 +0900 (7e3300f)
@@ -195,3 +195,130 @@ grn_cgo_row_info grn_cgo_table_insert_text(grn_ctx *ctx, grn_obj *table,
                                            const grn_cgo_text *key) {
   return grn_cgo_table_insert_row(ctx, table, key->ptr, key->size);
 }
+
+grn_bool grn_cgo_column_set_bool(grn_ctx *ctx, grn_obj *column,
+                                 grn_id id, grn_bool value) {
+  grn_obj obj;
+  GRN_BOOL_INIT(&obj, 0);
+  GRN_BOOL_SET(ctx, &obj, value);
+  grn_rc rc = grn_obj_set_value(ctx, column, id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc == GRN_SUCCESS;
+}
+
+grn_bool grn_cgo_column_set_int(grn_ctx *ctx, grn_obj *column,
+                                grn_id id, int64_t value) {
+  grn_obj obj;
+  GRN_INT64_INIT(&obj, 0);
+  GRN_INT64_SET(ctx, &obj, value);
+  grn_rc rc = grn_obj_set_value(ctx, column, id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc == GRN_SUCCESS;
+}
+
+grn_bool grn_cgo_column_set_float(grn_ctx *ctx, grn_obj *column,
+                                  grn_id id, double value) {
+  grn_obj obj;
+  GRN_FLOAT_INIT(&obj, 0);
+  GRN_FLOAT_SET(ctx, &obj, value);
+  grn_rc rc = grn_obj_set_value(ctx, column, id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc == GRN_SUCCESS;
+}
+
+grn_bool grn_cgo_column_set_geo_point(grn_ctx *ctx, grn_obj *column,
+                                      grn_id id, grn_geo_point value) {
+  grn_obj obj;
+  GRN_WGS84_GEO_POINT_INIT(&obj, 0);
+  GRN_GEO_POINT_SET(ctx, &obj, value.latitude, value.longitude);
+  grn_rc rc = grn_obj_set_value(ctx, column, id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc == GRN_SUCCESS;
+}
+
+grn_bool grn_cgo_column_set_text(grn_ctx *ctx, grn_obj *column,
+                                 grn_id id, const grn_cgo_text *value) {
+  grn_obj obj;
+  GRN_TEXT_INIT(&obj, 0);
+  if (value) {
+    GRN_TEXT_SET(ctx, &obj, value->ptr, value->size);
+  } else {
+    GRN_TEXT_SET(ctx, &obj, NULL, 0);
+  }
+  grn_rc rc = grn_obj_set_value(ctx, column, id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc == GRN_SUCCESS;
+}
+
+grn_bool grn_cgo_column_set_bool_vector(grn_ctx *ctx, grn_obj *column,
+                                        grn_id id,
+                                        const grn_cgo_vector *value) {
+  grn_obj obj;
+  GRN_BOOL_INIT(&obj, GRN_OBJ_VECTOR);
+  size_t i;
+  for (i = 0; i < value->size; i++) {
+    GRN_BOOL_SET_AT(ctx, &obj, i, ((const grn_bool *)value->ptr)[i]);
+  }
+  grn_rc rc = grn_obj_set_value(ctx, column, id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc == GRN_SUCCESS;
+}
+
+grn_bool grn_cgo_column_set_int_vector(grn_ctx *ctx, grn_obj *column,
+                                       grn_id id,
+                                       const grn_cgo_vector *value) {
+  grn_obj obj;
+  GRN_INT64_INIT(&obj, GRN_OBJ_VECTOR);
+  size_t i;
+  for (i = 0; i < value->size; i++) {
+    GRN_INT64_SET_AT(ctx, &obj, i, ((const int64_t *)value->ptr)[i]);
+  }
+  grn_rc rc = grn_obj_set_value(ctx, column, id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc == GRN_SUCCESS;
+}
+
+grn_bool grn_cgo_column_set_float_vector(grn_ctx *ctx, grn_obj *column,
+                                         grn_id id,
+                                         const grn_cgo_vector *value) {
+  grn_obj obj;
+  GRN_FLOAT_INIT(&obj, GRN_OBJ_VECTOR);
+  size_t i;
+  for (i = 0; i < value->size; i++) {
+    GRN_FLOAT_SET_AT(ctx, &obj, i, ((const double *)value->ptr)[i]);
+  }
+  grn_rc rc = grn_obj_set_value(ctx, column, id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc == GRN_SUCCESS;
+}
+
+grn_bool grn_cgo_column_set_geo_point_vector(grn_ctx *ctx, grn_obj *column,
+                                             grn_id id,
+                                             const grn_cgo_vector *value) {
+  grn_obj obj;
+  GRN_WGS84_GEO_POINT_INIT(&obj, GRN_OBJ_VECTOR);
+  size_t i;
+  const grn_geo_point *values = (const grn_geo_point *)value->ptr;
+  for (i = 0; i < value->size; i++) {
+    grn_bulk_write(ctx, &obj, (const char *)&values[i], sizeof(values[i]));
+  }
+  grn_rc rc = grn_obj_set_value(ctx, column, id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc == GRN_SUCCESS;
+}
+
+grn_bool grn_cgo_column_set_text_vector(grn_ctx *ctx, grn_obj *column,
+                                        grn_id id,
+                                        const grn_cgo_vector *value) {
+  grn_obj obj;
+  GRN_TEXT_INIT(&obj, GRN_OBJ_VECTOR);
+  size_t i;
+  const grn_cgo_text *values = (const grn_cgo_text *)value->ptr;
+  for (i = 0; i < value->size; i++) {
+    grn_vector_add_element(ctx, &obj, values[i].ptr, values[i].size,
+                           0, obj.header.domain);
+  }
+  grn_rc rc = grn_obj_set_value(ctx, column, id, &obj, GRN_OBJ_SET);
+  GRN_OBJ_FIN(ctx, &obj);
+  return rc == GRN_SUCCESS;
+}

  Modified: go3/gnx/grn_cgo.h (+41 -0)
===================================================================
--- go3/gnx/grn_cgo.h    2015-05-01 04:06:02 +0900 (a9a25da)
+++ go3/gnx/grn_cgo.h    2015-05-01 10:32:07 +0900 (aa07704)
@@ -11,6 +11,11 @@ typedef struct {
   size_t size;
 } grn_cgo_text;
 
+typedef struct {
+  const void *ptr;
+  size_t size;
+} grn_cgo_vector;
+
 // grn_cgo_find_table() finds a table with the given name.
 // If found, an object associated with the table is returned.
 // If not found, NULL is returned.
@@ -62,4 +67,40 @@ grn_cgo_row_info grn_cgo_table_insert_geo_point(grn_ctx *ctx, grn_obj *table,
 grn_cgo_row_info grn_cgo_table_insert_text(grn_ctx *ctx, grn_obj *table,
                                            const grn_cgo_text *key);
 
+// grn_cgo_column_set_bool() assigns a Bool value.
+grn_bool grn_cgo_column_set_bool(grn_ctx *ctx, grn_obj *column,
+                                 grn_id id, grn_bool value);
+// grn_cgo_column_set_int() assigns an Int value.
+grn_bool grn_cgo_column_set_int(grn_ctx *ctx, grn_obj *column,
+                                grn_id id, int64_t value);
+// grn_cgo_column_set_float() assigns a Float value.
+grn_bool grn_cgo_column_set_float(grn_ctx *ctx, grn_obj *column,
+                                  grn_id id, double value);
+// grn_cgo_column_set_geo_point() assigns a GeoPoint value.
+grn_bool grn_cgo_column_set_geo_point(grn_ctx *ctx, grn_obj *column,
+                                      grn_id id, grn_geo_point value);
+// grn_cgo_column_set_text() assigns a Text value.
+grn_bool grn_cgo_column_set_text(grn_ctx *ctx, grn_obj *column,
+                                 grn_id id, const grn_cgo_text *value);
+// grn_cgo_column_set_bool_vector() assigns a Bool vector.
+grn_bool grn_cgo_column_set_bool_vector(grn_ctx *ctx, grn_obj *column,
+                                        grn_id id,
+                                        const grn_cgo_vector *value);
+// grn_cgo_column_set_int_vector() assigns an Int vector.
+grn_bool grn_cgo_column_set_int_vector(grn_ctx *ctx, grn_obj *column,
+                                       grn_id id,
+                                       const grn_cgo_vector *value);
+// grn_cgo_column_set_float_vector() assigns a Float vector.
+grn_bool grn_cgo_column_set_float_vector(grn_ctx *ctx, grn_obj *column,
+                                         grn_id id,
+                                         const grn_cgo_vector *value);
+// grn_cgo_column_set_geo_point_vector() assigns a GeoPoint vector.
+grn_bool grn_cgo_column_set_geo_point_vector(grn_ctx *ctx, grn_obj *column,
+                                             grn_id id,
+                                             const grn_cgo_vector *value);
+// grn_cgo_column_set_text_vector() assigns a Text vector.
+grn_bool grn_cgo_column_set_text_vector(grn_ctx *ctx, grn_obj *column,
+                                        grn_id id,
+                                        const grn_cgo_vector *value);
+
 #endif  // GRN_CGO_H

  Modified: go3/gnx/grn_test.go (+129 -0)
===================================================================
--- go3/gnx/grn_test.go    2015-05-01 04:06:02 +0900 (507108c)
+++ go3/gnx/grn_test.go    2015-05-01 10:32:07 +0900 (438c68a)
@@ -291,3 +291,132 @@ func TestGrnTableCreateColumn(t *testing.T) {
 	testGrnTableCreateVectorRefColumn(t, "GeoPoint")
 	testGrnTableCreateVectorRefColumn(t, "Text")
 }
+
+func generateRandomScalarValue(valueType string) interface{} {
+	switch valueType {
+	case "Bool":
+		if (rand.Int() & 1) == 1 {
+			return True
+		} else {
+			return False
+		}
+	case "Int":
+		return Int(rand.Int63())
+	case "Float":
+		return Float(rand.Float64())
+	case "GeoPoint":
+		const (
+			MinLatitude  = 73531000
+			MaxLatitude  = 164006000
+			MinLongitude = 439451000
+			MaxLongitude = 554351000
+		)
+		latitude := MinLatitude + rand.Intn(MaxLatitude-MinLatitude+1)
+		longitude := MinLongitude + rand.Intn(MaxLongitude-MinLongitude+1)
+		return GeoPoint{int32(latitude), int32(longitude)}
+	case "Text":
+		return Text(strconv.Itoa(rand.Int()))
+	default:
+		return nil
+	}
+}
+
+func testGrnColumnSetScalarValue(t *testing.T, valueType string) {
+	dirPath, _, db, table, column := createTempGrnColumn(t, "Table", nil, "Value", valueType, nil)
+	defer removeTempGrnDB(t, dirPath, db)
+
+	for i := 0; i < 100; i++ {
+		_, id, err := table.InsertRow(nil)
+		if err != nil {
+			t.Fatalf("GrnTable.InsertRow() failed: %v", err)
+		}
+		if err := column.SetValue(id, generateRandomScalarValue(valueType)); err != nil {
+			t.Fatalf("GrnColumn.SetValue() failed: %v", err)
+		}
+	}
+
+	bytes, _ := db.Query("select Table --limit 3")
+	t.Logf("valueType = <%s>, result = %s", valueType, string(bytes))
+}
+
+func generateRandomVectorValue(valueType string) interface{} {
+	size := rand.Int() % 10
+	switch valueType {
+	case "Bool":
+		value := make([]Bool, size)
+		for i := 0; i < size; i++ {
+			if (rand.Int() & 1) == 1 {
+				value[i] = True
+			}
+		}
+		return value
+	case "Int":
+		value := make([]Int, size)
+		for i := 0; i < size; i++ {
+			value[i] = Int(rand.Int63())
+		}
+		return value
+	case "Float":
+		value := make([]Float, size)
+		for i := 0; i < size; i++ {
+			value[i] = Float(rand.Float64())
+		}
+		return value
+	case "GeoPoint":
+		const (
+			MinLatitude  = 73531000
+			MaxLatitude  = 164006000
+			MinLongitude = 439451000
+			MaxLongitude = 554351000
+		)
+		value := make([]GeoPoint, size)
+		for i := 0; i < size; i++ {
+			latitude := MinLatitude + rand.Intn(MaxLatitude-MinLatitude+1)
+			longitude := MinLongitude + rand.Intn(MaxLongitude-MinLongitude+1)
+			value[i] = GeoPoint{int32(latitude), int32(longitude)}
+		}
+		return value
+	case "Text":
+		value := make([]Text, size)
+		for i := 0; i < size; i++ {
+			value[i] = Text(strconv.Itoa(rand.Int()))
+		}
+		return value
+	default:
+		return nil
+	}
+}
+
+func testGrnColumnSetVectorValue(t *testing.T, valueType string) {
+	options := NewColumnOptions()
+	options.ColumnType = VectorColumn
+	dirPath, _, db, table, column := createTempGrnColumn(t, "Table", nil, "Value", valueType, options)
+	defer removeTempGrnDB(t, dirPath, db)
+
+	for i := 0; i < 100; i++ {
+		_, id, err := table.InsertRow(nil)
+		if err != nil {
+			t.Fatalf("GrnTable.InsertRow() failed: %v", err)
+		}
+		if err := column.SetValue(id, generateRandomVectorValue(valueType)); err != nil {
+			t.Fatalf("GrnColumn.SetValue() failed: %v", err)
+		}
+	}
+
+	bytes, _ := db.Query("select Table --limit 3")
+	t.Logf("valueType = <%s>, result = %s", valueType, string(bytes))
+}
+
+func TestGrnColumnSetValue(t *testing.T) {
+	testGrnColumnSetScalarValue(t, "Bool")
+	testGrnColumnSetScalarValue(t, "Int")
+	testGrnColumnSetScalarValue(t, "Float")
+	testGrnColumnSetScalarValue(t, "GeoPoint")
+	testGrnColumnSetScalarValue(t, "Text")
+
+	testGrnColumnSetVectorValue(t, "Bool")
+	testGrnColumnSetVectorValue(t, "Int")
+	testGrnColumnSetVectorValue(t, "Float")
+	testGrnColumnSetVectorValue(t, "GeoPoint")
+	testGrnColumnSetVectorValue(t, "Text")
+}
-------------- next part --------------
HTML����������������������������...
Download 



More information about the Groonga-commit mailing list
Back to archive index