[Groonga-commit] groonga/grnxx at 420033e [master] Gnx: implement CreateColumn() and FindColumn().

Back to archive index

susumu.yata null+****@clear*****
Fri May 1 03:41:36 JST 2015


susumu.yata	2015-05-01 03:41:36 +0900 (Fri, 01 May 2015)

  New Revision: 420033e1c2eb350425ff567080fda71f65c9b361
  https://github.com/groonga/grnxx/commit/420033e1c2eb350425ff567080fda71f65c9b361

  Message:
    Gnx: implement CreateColumn() and FindColumn().

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

  Modified: go3/gnx/grn.go (+248 -18)
===================================================================
--- go3/gnx/grn.go    2015-04-28 19:27:43 +0900 (13c492e)
+++ go3/gnx/grn.go    2015-05-01 03:41:36 +0900 (506a3cd)
@@ -358,7 +358,48 @@ func (db *GrnDB) FindTable(name string) (*GrnTable, error) {
 			return nil, err
 		}
 	}
-	table := newGrnTable(db, obj, name, keyType, keyTable)
+	var valueInfo C.grn_cgo_type_info
+	if ok := C.grn_cgo_table_get_value_info(db.ctx, obj, &valueInfo); ok != C.GRN_TRUE {
+		return nil, fmt.Errorf("grn_cgo_table_get_value_info() failed: name = <%s>",
+			name)
+	}
+	// Check the value type.
+	var valueType TypeID
+	switch valueInfo.data_type {
+	case C.GRN_DB_VOID:
+		valueType = VoidID
+	case C.GRN_DB_BOOL:
+		valueType = BoolID
+	case C.GRN_DB_INT64:
+		valueType = IntID
+	case C.GRN_DB_FLOAT:
+		valueType = FloatID
+	case C.GRN_DB_WGS84_GEO_POINT:
+		valueType = GeoPointID
+	case C.GRN_DB_SHORT_TEXT:
+		valueType = TextID
+	default:
+		return nil, fmt.Errorf("unsupported value type: data_type = %d",
+			valueInfo.data_type)
+	}
+	// Find the destination table if the value is table reference.
+	var valueTable *GrnTable
+	if valueInfo.ref_table != nil {
+		if valueType == VoidID {
+			return nil, fmt.Errorf("reference to void: name = <%s>", name)
+		}
+		cValueTableName := C.grn_cgo_table_get_name(db.ctx, valueInfo.ref_table)
+		if cValueTableName == nil {
+			return nil, fmt.Errorf("grn_cgo_table_get_name() failed")
+		}
+		defer C.free(unsafe.Pointer(cValueTableName))
+		var err error
+		valueTable, err = db.FindTable(C.GoString(cValueTableName))
+		if err != nil {
+			return nil, err
+		}
+	}
+	table := newGrnTable(db, obj, name, keyType, keyTable, valueType, valueTable)
 	db.tables[name] = table
 	return table, nil
 }
@@ -389,37 +430,26 @@ type GrnTable struct {
 	name     string
 	keyType  TypeID
 	keyTable *GrnTable
+	valueType  TypeID
+	valueTable *GrnTable
 	columns  map[string]*GrnColumn
 }
 
 // newGrnTable() creates a new GrnTable object.
 func newGrnTable(db *GrnDB, obj *C.grn_obj, name string, keyType TypeID,
-	keyTable *GrnTable) *GrnTable {
+	keyTable *GrnTable, valueType TypeID, valueTable *GrnTable) *GrnTable {
 	var table GrnTable
 	table.db = db
 	table.obj = obj
 	table.name = name
 	table.keyType = keyType
 	table.keyTable = keyTable
+	table.valueType = valueType
+	table.valueTable = valueTable
 	table.columns = make(map[string]*GrnColumn)
 	return &table
 }
 
-// CreateColumn() creates a column.
-func (table *GrnTable) CreateColumn(name string, valueType string, options *ColumnOptions) (*GrnColumn, error) {
-	// TODO
-	return nil, fmt.Errorf("not supported yet")
-}
-
-// FindColumn() finds a column.
-func (table *GrnTable) FindColumn(name string) (*GrnColumn, error) {
-	if column, ok := table.columns[name]; ok {
-		return column, nil
-	}
-	// TODO
-	return nil, fmt.Errorf("not supported yet")
-}
-
 // InsertVoid() inserts an empty row.
 func (table *GrnTable) InsertVoid() (bool, Int, error) {
 	if table.keyType != VoidID {
@@ -527,8 +557,208 @@ func (table *GrnTable) InsertRow(key interface{}) (bool, Int, error) {
 	}
 }
 
+// CreateColumn() creates a column.
+func (table *GrnTable) CreateColumn(name string, valueType string, options *ColumnOptions) (*GrnColumn, error) {
+	if options == nil {
+		options = NewColumnOptions()
+	}
+	optionsMap := make(map[string]string)
+	optionsMap["table"] = table.name
+	optionsMap["name"] = name
+	switch valueType {
+	case "Bool":
+		optionsMap["type"] = "Bool"
+	case "Int":
+		optionsMap["type"] = "Int64"
+	case "Float":
+		optionsMap["type"] = "Float"
+	case "GeoPoint":
+		optionsMap["type"] = "WGS84GeoPoint"
+	case "Text":
+		optionsMap["type"] = "LongText"
+	default:
+		if _, err := table.db.FindTable(valueType); err != nil {
+			return nil, fmt.Errorf("unsupported value type: valueType = %s", valueType)
+		}
+		optionsMap["type"] = valueType
+	}
+	switch options.ColumnType {
+	case ScalarColumn:
+		optionsMap["flags"] = "COLUMN_SCALAR"
+	case VectorColumn:
+		optionsMap["flags"] = "COLUMN_VECTOR"
+	case IndexColumn:
+		optionsMap["flags"] = "COLUMN_INDEX"
+	default:
+		return nil, fmt.Errorf("undefined column type: options = %+v", options)
+	}
+	switch options.CompressionType {
+	case NoCompression:
+	case ZlibCompression:
+		optionsMap["flags"] = "|COMPRESS_ZLIB"
+	case LzoCompression:
+		optionsMap["flags"] = "|COMRESS_LZO"
+	default:
+		return nil, fmt.Errorf("undefined compression type: options = %+v", options)
+	}
+	if options.WithSection {
+		optionsMap["flags"] += "|WITH_SECTION"
+	}
+	if options.WithWeight {
+		optionsMap["flags"] += "|WITH_WEIGHT"
+	}
+	if options.WithPosition {
+		optionsMap["flags"] += "|WITH_POSITION"
+	}
+	if options.Source != "" {
+		optionsMap["source"] = options.Source
+	}
+	bytes, err := table.db.QueryEx("column_create", optionsMap)
+	if err != nil {
+		return nil, err
+	}
+	if string(bytes) != "true" {
+		return nil, fmt.Errorf("column_create failed: name = <%s>", name)
+	}
+	return table.FindColumn(name)
+}
+
+// findColumn() finds a column.
+func (table *GrnTable) findColumn(name string) (*GrnColumn, error) {
+	if column, ok := table.columns[name]; ok {
+		return column, nil
+	}
+	nameBytes := []byte(name)
+	var cName *C.char
+	if len(nameBytes) != 0 {
+		cName = (*C.char)(unsafe.Pointer(&nameBytes[0]))
+	}
+	obj := C.grn_obj_column(table.db.ctx, table.obj, cName, C.uint(len(name)))
+	if obj == nil {
+		return nil, fmt.Errorf("grn_obj_column() failed: table = %+v, name = <%s>", table, name)
+	}
+	var valueType TypeID
+	var valueTable *GrnTable
+	var isVector bool
+	switch name {
+	case "_id":
+		valueType = IntID
+	case "_key":
+		valueType = table.keyType
+		valueTable = table.keyTable
+	case "_value":
+		valueType = table.valueType
+		valueTable = table.valueTable
+	default:
+		var valueInfo C.grn_cgo_type_info
+		if ok := C.grn_cgo_column_get_value_info(table.db.ctx, obj, &valueInfo); ok != C.GRN_TRUE {
+			return nil, fmt.Errorf("grn_cgo_column_get_value_info() failed: name = <%s>",
+				name)
+		}
+		// Check the value type.
+		switch valueInfo.data_type {
+		case C.GRN_DB_BOOL:
+			valueType = BoolID
+		case C.GRN_DB_INT64:
+			valueType = IntID
+		case C.GRN_DB_FLOAT:
+			valueType = FloatID
+		case C.GRN_DB_WGS84_GEO_POINT:
+			valueType = GeoPointID
+		case C.GRN_DB_SHORT_TEXT, C.GRN_DB_LONG_TEXT:
+			valueType = TextID
+		default:
+			return nil, fmt.Errorf("unsupported value type: data_type = %d",
+				valueInfo.data_type)
+		}
+		isVector = valueInfo.dimension > 0
+		// Find the destination table if the value is table reference.
+		if valueInfo.ref_table != nil {
+			if valueType == VoidID {
+				return nil, fmt.Errorf("reference to void: name = <%s>", name)
+			}
+			cValueTableName := C.grn_cgo_table_get_name(table.db.ctx, valueInfo.ref_table)
+			if cValueTableName == nil {
+				return nil, fmt.Errorf("grn_cgo_table_get_name() failed")
+			}
+			defer C.free(unsafe.Pointer(cValueTableName))
+			var err error
+			valueTable, err = table.db.FindTable(C.GoString(cValueTableName))
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+	column := newGrnColumn(table, obj, name, valueType, isVector, valueTable)
+	table.columns[name] = column
+	return column, nil
+}
+
+// FindColumn() finds a column.
+func (table *GrnTable) FindColumn(name string) (*GrnColumn, error) {
+	if column, ok := table.columns[name]; ok {
+		return column, nil
+	}
+	delimPos := strings.IndexByte(name, '.')
+	if delimPos == -1 {
+		return table.findColumn(name)
+	}
+	columnNames := strings.Split(name, ".")
+	column, err := table.findColumn(columnNames[0])
+	if err != nil {
+		return nil, err
+	}
+	isVector := column.isVector
+	valueTable := column.valueTable
+	for _, columnName := range columnNames[1:] {
+		if column.valueTable == nil {
+			return nil, fmt.Errorf("not table reference: column.name = <%s>", column.name)
+		}
+		column, err = column.valueTable.findColumn(columnName)
+		if err != nil {
+			return nil, err
+		}
+		if column.isVector {
+			if isVector {
+				return nil, fmt.Errorf("vector of vector is not supported")
+			}
+			isVector = true
+		}
+	}
+	nameBytes := []byte(name)
+	var cName *C.char
+	if len(nameBytes) != 0 {
+		cName = (*C.char)(unsafe.Pointer(&nameBytes[0]))
+	}
+	obj := C.grn_obj_column(table.db.ctx, table.obj, cName, C.uint(len(name)))
+	if obj == nil {
+		return nil, fmt.Errorf("grn_obj_column() failed: name = <%s>", name)
+	}
+	column = newGrnColumn(table, obj, name, column.valueType, isVector, valueTable)
+	table.columns[name] = column
+	return column, nil
+}
+
 // -- GrnColumn --
 
 type GrnColumn struct {
-	obj *C.grn_obj
+	table      *GrnTable
+	obj        *C.grn_obj
+	name       string
+	valueType  TypeID
+	isVector   bool
+	valueTable *GrnTable
+}
+
+// newGrnColumn() creates a new GrnColumn object.
+func newGrnColumn(table *GrnTable, obj *C.grn_obj, name string,
+	valueType TypeID, isVector bool, valueTable *GrnTable) *GrnColumn {
+	var column GrnColumn
+	column.table = table
+	column.obj = obj
+	column.name = name
+	column.valueType = valueType
+	column.isVector = isVector
+	column.valueTable = valueTable
+	return &column
 }

  Modified: go3/gnx/grn_cgo.c (+68 -0)
===================================================================
--- go3/gnx/grn_cgo.c    2015-04-28 19:27:43 +0900 (e2b7523)
+++ go3/gnx/grn_cgo.c    2015-05-01 03:41:36 +0900 (c120c36)
@@ -44,6 +44,9 @@ grn_bool grn_cgo_table_get_key_info(grn_ctx *ctx, grn_obj *table,
           return GRN_TRUE;
         }
         table = grn_ctx_at(ctx, table->header.domain);
+        if (!table) {
+          return GRN_FALSE;
+        }
         if (!key_info->ref_table) {
           key_info->ref_table = table;
         }
@@ -60,6 +63,71 @@ grn_bool grn_cgo_table_get_key_info(grn_ctx *ctx, grn_obj *table,
   return GRN_FALSE;
 }
 
+grn_bool grn_cgo_table_get_value_info(grn_ctx *ctx, grn_obj *table,
+                                      grn_cgo_type_info *value_info) {
+  grn_cgo_init_type_info(value_info);
+  if (!table) {
+    return GRN_FALSE;
+  }
+  switch (table->header.type) {
+    case GRN_TABLE_HASH_KEY:
+    case GRN_TABLE_PAT_KEY:
+    case GRN_TABLE_DAT_KEY:
+    case GRN_TABLE_NO_KEY: {
+      grn_id range = grn_obj_get_range(ctx, table);
+      if (range <= GRN_CGO_MAX_DATA_TYPE_ID) {
+        value_info->data_type = range;
+        return GRN_TRUE;
+      }
+      value_info->ref_table = grn_ctx_at(ctx, range);
+      grn_cgo_type_info key_info;
+      if (!grn_cgo_table_get_key_info(ctx, value_info->ref_table, &key_info)) {
+        return GRN_FALSE;
+      }
+      value_info->data_type = key_info.data_type;
+      return GRN_TRUE;
+    }
+    default: {
+      return GRN_FALSE;
+    }
+  }
+}
+
+grn_bool grn_cgo_column_get_value_info(grn_ctx *ctx, grn_obj *column,
+                                       grn_cgo_type_info *value_info) {
+  grn_cgo_init_type_info(value_info);
+  if (!column) {
+    return GRN_FALSE;
+  }
+  switch (column->header.type) {
+    case GRN_COLUMN_FIX_SIZE: {
+      break;
+    }
+    case GRN_COLUMN_VAR_SIZE: {
+      grn_obj_flags type = column->header.flags & GRN_OBJ_COLUMN_TYPE_MASK;
+      if (type == GRN_OBJ_COLUMN_VECTOR) {
+        ++value_info->dimension;
+      }
+      break;
+    }
+    default: {
+      return GRN_FALSE;
+    }
+  }
+  grn_id range = grn_obj_get_range(ctx, column);
+  if (range <= GRN_CGO_MAX_DATA_TYPE_ID) {
+    value_info->data_type = range;
+    return GRN_TRUE;
+  }
+  value_info->ref_table = grn_ctx_at(ctx, range);
+  grn_cgo_type_info key_info;
+  if (!grn_cgo_table_get_key_info(ctx, value_info->ref_table, &key_info)) {
+    return GRN_FALSE;
+  }
+  value_info->data_type = key_info.data_type;
+  return GRN_TRUE;
+}
+
 char *grn_cgo_table_get_name(grn_ctx *ctx, grn_obj *table) {
   if (!table) {
     return NULL;

  Modified: go3/gnx/grn_cgo.h (+11 -5)
===================================================================
--- go3/gnx/grn_cgo.h    2015-04-28 19:27:43 +0900 (886f814)
+++ go3/gnx/grn_cgo.h    2015-05-01 03:41:36 +0900 (a9a25da)
@@ -17,16 +17,22 @@ typedef struct {
 grn_obj *grn_cgo_find_table(grn_ctx *ctx, const char *name, int name_len);
 
 typedef struct {
-	grn_id  data_type;  // Data type (GRN_DB_VOID, GRN_DB_BOOL, etc.).
-	                    // If the type is table reference, the key type of the
-	                    // referenced table is stored.
-	int     dimension;  // Vector depth, 0 means the type is scalar.
-	grn_obj *ref_table; // The referenced table of table reference.
+  grn_id  data_type;  // Data type (GRN_DB_VOID, GRN_DB_BOOL, etc.).
+                      // If the type is table reference, the key type of the
+                      // referenced table is stored.
+  int     dimension;  // Vector depth, 0 means the type is scalar.
+  grn_obj *ref_table; // The referenced table of table reference.
 } grn_cgo_type_info;
 
 // grn_cgo_table_get_key_info() gets information of the table key.
 grn_bool grn_cgo_table_get_key_info(grn_ctx *ctx, grn_obj *table,
                                     grn_cgo_type_info *key_info);
+// grn_cgo_table_get_value_info() gets information of the table value.
+grn_bool grn_cgo_table_get_value_info(grn_ctx *ctx, grn_obj *table,
+                                      grn_cgo_type_info *value_info);
+// grn_cgo_column_get_value_info() gets information of the column value.
+grn_bool grn_cgo_column_get_value_info(grn_ctx *ctx, grn_obj *column,
+                                       grn_cgo_type_info *value_info);
 
 // grn_cgo_table_get_name() returns the name of table.
 // On success, a non-NULL pointer is returned and it must be freed by free().

  Modified: go3/gnx/grn_test.go (+135 -0)
===================================================================
--- go3/gnx/grn_test.go    2015-04-28 19:27:43 +0900 (e9b99e4)
+++ go3/gnx/grn_test.go    2015-05-01 03:41:36 +0900 (3762a1d)
@@ -43,6 +43,19 @@ func createTempGrnTable(tb testing.TB, name string, options *TableOptions) (
 	return dirPath, dbPath, db, table
 }
 
+func createTempGrnColumn(tb testing.TB, tableName string,
+	tableOptions *TableOptions, columnName string, valueType string,
+	columnOptions *ColumnOptions) (
+	string, string, *GrnDB, *GrnTable, *GrnColumn) {
+	dirPath, dbPath, db, table := createTempGrnTable(tb, tableName, tableOptions)
+	column, err := table.CreateColumn(columnName, valueType, columnOptions)
+	if err != nil {
+		removeTempGrnDB(tb, dirPath, db)
+		tb.Fatalf("GrnDB.CreateTable() failed: %v", err)
+	}
+	return dirPath, dbPath, db, table, column
+}
+
 func TestCreateGrnDB(t *testing.T) {
 	dirPath, _, db := createTempGrnDB(t)
 	removeTempGrnDB(t, dirPath, db)
@@ -66,6 +79,13 @@ func testGrnDBCreateTableWithKey(t *testing.T, keyType string) {
 	removeTempGrnDB(t, dirPath, db)
 }
 
+func testGrnDBCreateTableWithValue(t *testing.T, valueType string) {
+	options := NewTableOptions()
+	options.ValueType = valueType
+	dirPath, _, db, _ := createTempGrnTable(t, "Table", options)
+	removeTempGrnDB(t, dirPath, db)
+}
+
 func testGrnDBCreateTableRef(t *testing.T, keyType string) {
 	options := NewTableOptions()
 	options.TableType = PatTable
@@ -90,6 +110,11 @@ func TestGrnDBCreateTable(t *testing.T) {
 	testGrnDBCreateTableWithKey(t, "GeoPoint")
 	testGrnDBCreateTableWithKey(t, "Text")
 
+	testGrnDBCreateTableWithValue(t, "Bool")
+	testGrnDBCreateTableWithValue(t, "Int")
+	testGrnDBCreateTableWithValue(t, "Float")
+	testGrnDBCreateTableWithValue(t, "GeoPoint")
+
 	testGrnDBCreateTableRef(t, "Bool")
 	testGrnDBCreateTableRef(t, "Int")
 	testGrnDBCreateTableRef(t, "Float")
@@ -156,3 +181,113 @@ func TestGrnTableInsertRow(t *testing.T) {
 	testGrnTableInsertRow(t, "GeoPoint")
 	testGrnTableInsertRow(t, "Text")
 }
+
+func testGrnTableCreateScalarColumn(t *testing.T, valueType string) {
+	dirPath, _, db, table, _ := createTempGrnColumn(t, "Table", nil, "Value", valueType, nil)
+	defer removeTempGrnDB(t, dirPath, db)
+
+	if column, err := table.FindColumn("_id"); err != nil {
+		t.Fatalf("Table.FindColumn() failed: %v", err)
+	} else {
+		t.Logf("_id: %+v", column)
+	}
+	if column, err := table.FindColumn("Value"); err != nil {
+		t.Fatalf("Table.FindColumn() failed: %v", err)
+	} else {
+		t.Logf("Value: %+v", column)
+	}
+}
+
+func testGrnTableCreateVectorColumn(t *testing.T, valueType string) {
+	options := NewColumnOptions()
+	options.ColumnType = VectorColumn
+	dirPath, _, db, table, _ := createTempGrnColumn(t, "Table", nil, "Value", valueType, options)
+	defer removeTempGrnDB(t, dirPath, db)
+
+	if column, err := table.FindColumn("_id"); err != nil {
+		t.Fatalf("Table.FindColumn() failed: %v", err)
+	} else {
+		t.Logf("_id: %+v", column)
+	}
+	if column, err := table.FindColumn("Value"); err != nil {
+		t.Fatalf("Table.FindColumn() failed: %v", err)
+	} else {
+		t.Logf("Value: %+v", column)
+	}
+}
+
+func testGrnTableCreateScalarRefColumn(t *testing.T, keyType string) {
+	options := NewTableOptions()
+	options.TableType = PatTable
+	options.KeyType = keyType
+	dirPath, _, db, table, _ := createTempGrnColumn(t, "Table", options, "Value", "Table", nil)
+	defer removeTempGrnDB(t, dirPath, db)
+
+	if column, err := table.FindColumn("Value"); err != nil {
+		t.Fatalf("Table.FindColumn() failed: %v", err)
+	} else {
+		t.Logf("Value: %+v", column)
+	}
+	if column, err := table.FindColumn("Value._id"); err != nil {
+		t.Fatalf("Table.FindColumn() failed: %v", err)
+	} else {
+		t.Logf("Value._id: %+v", column)
+	}
+	if column, err := table.FindColumn("Value._key"); err != nil {
+		t.Fatalf("Table.FindColumn() failed: %v", err)
+	} else {
+		t.Logf("Value._key: %+v", column)
+	}
+}
+
+func testGrnTableCreateVectorRefColumn(t *testing.T, keyType string) {
+	tableOptions := NewTableOptions()
+	tableOptions.TableType = PatTable
+	tableOptions.KeyType = keyType
+	columnOptions := NewColumnOptions()
+	columnOptions.ColumnType = VectorColumn
+	dirPath, _, db, table, _ := createTempGrnColumn(t, "Table", tableOptions, "Value", "Table", columnOptions)
+	defer removeTempGrnDB(t, dirPath, db)
+
+	if column, err := table.FindColumn("Value"); err != nil {
+		t.Fatalf("Table.FindColumn() failed: %v", err)
+	} else {
+		t.Logf("Value: %+v", column)
+	}
+	if column, err := table.FindColumn("Value._id"); err != nil {
+		t.Fatalf("Table.FindColumn() failed: %v", err)
+	} else {
+		t.Logf("Value._id: %+v", column)
+	}
+	if column, err := table.FindColumn("Value._key"); err != nil {
+		t.Fatalf("Table.FindColumn() failed: %v", err)
+	} else {
+		t.Logf("Value._key: %+v", column)
+	}
+}
+
+func TestGrnTableCreateColumn(t *testing.T) {
+	testGrnTableCreateScalarColumn(t, "Bool")
+	testGrnTableCreateScalarColumn(t, "Int")
+	testGrnTableCreateScalarColumn(t, "Float")
+	testGrnTableCreateScalarColumn(t, "GeoPoint")
+	testGrnTableCreateScalarColumn(t, "Text")
+
+	testGrnTableCreateVectorColumn(t, "Bool")
+	testGrnTableCreateVectorColumn(t, "Int")
+	testGrnTableCreateVectorColumn(t, "Float")
+	testGrnTableCreateVectorColumn(t, "GeoPoint")
+	testGrnTableCreateVectorColumn(t, "Text")
+
+	testGrnTableCreateScalarRefColumn(t, "Bool")
+	testGrnTableCreateScalarRefColumn(t, "Int")
+	testGrnTableCreateScalarRefColumn(t, "Float")
+	testGrnTableCreateScalarRefColumn(t, "GeoPoint")
+	testGrnTableCreateScalarRefColumn(t, "Text")
+
+	testGrnTableCreateVectorRefColumn(t, "Bool")
+	testGrnTableCreateVectorRefColumn(t, "Int")
+	testGrnTableCreateVectorRefColumn(t, "Float")
+	testGrnTableCreateVectorRefColumn(t, "GeoPoint")
+	testGrnTableCreateVectorRefColumn(t, "Text")
+}

  Modified: go3/gnx/options.go (+4 -0)
===================================================================
--- go3/gnx/options.go    2015-04-28 19:27:43 +0900 (6be939d)
+++ go3/gnx/options.go    2015-05-01 03:41:36 +0900 (4d984fb)
@@ -27,6 +27,8 @@ type TableOptions struct {
 	TokenFilters     []string // http://groonga.org/docs/reference/token_filters.html
 }
 
+// NewTableOptions() creates a new TableOptions object with the default
+// settings.
 func NewTableOptions() *TableOptions {
 	var options TableOptions
 	return &options
@@ -62,6 +64,8 @@ type ColumnOptions struct {
 	Source       string
 }
 
+// NewColumnOptions() creates a new ColumnOptions object with the default
+// settings.
 func NewColumnOptions() *ColumnOptions {
 	var options ColumnOptions
 	return &options
-------------- next part --------------
HTML����������������������������...
Download 



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