Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 21 additions & 1 deletion ext/groonga/rb-grn-context.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
/*
Copyright (C) 2010-2021 Sutou Kouhei <kou@clear-code.com>
Copyright (C) 2016 Masafumi Yokoyama <yokoyama@clear-code.com>
Copyright (C) 2019 Horimoto Yasuhiro <horimoto@clear-code.com>
Copyright (C) 2019-2022 Horimoto Yasuhiro <horimoto@clear-code.com>

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
Expand Down Expand Up @@ -326,6 +326,26 @@ rb_grn_context_ensure (VALUE *context)
return SELF(*context);
}

/*
* If context has already implemented database, it returns +true+,
* otherwise it returns +false+.
*
* @return [Boolean] `true` if context has already implemented database.
* `false` if context does not implement database.
*/
VALUE
rb_grn_context_implement_db (grn_ctx *context)
{
grn_obj *database;

database = grn_ctx_db(context);
if (database) {
return Qtrue;
} else {
return Qfalse;
}
}

VALUE
rb_grn_context_rb_string_new (grn_ctx *context, const char *string, long length)
{
Expand Down
19 changes: 16 additions & 3 deletions ext/groonga/rb-grn-patricia-trie.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,12 @@ rb_grn_patricia_trie_s_create (int argc, VALUE *argv, VALUE klass)
grn_obj *key_type = NULL, *value_type = NULL, *table;
const char *name = NULL, *path = NULL;
unsigned name_size = 0;
unsigned int key_size = 0;
unsigned int value_size = 0;
grn_table_flags flags = GRN_OBJ_TABLE_PAT_KEY;
VALUE rb_table;
VALUE options, rb_context, rb_name, rb_path, rb_persistent;
VALUE rb_key_normalize, rb_key_with_sis, rb_key_type;
VALUE rb_key_normalize, rb_key_with_sis, rb_key_type, rb_key_size, rb_key_var_size;
VALUE rb_value_type;
VALUE rb_default_tokenizer;
VALUE rb_token_filters;
Expand All @@ -186,6 +188,8 @@ rb_grn_patricia_trie_s_create (int argc, VALUE *argv, VALUE klass)
"key_normalize", &rb_key_normalize,
"key_with_sis", &rb_key_with_sis,
"key_type", &rb_key_type,
"key_size", &rb_key_size,
"key_var_size", &rb_key_var_size,
"value_type", &rb_value_type,
"default_tokenizer", &rb_default_tokenizer,
"token_filters", &rb_token_filters,
Expand Down Expand Up @@ -227,8 +231,17 @@ rb_grn_patricia_trie_s_create (int argc, VALUE *argv, VALUE klass)
if (RVAL2CBOOL(rb_sub_records))
flags |= GRN_OBJ_WITH_SUBREC;

table = grn_table_create(context, name, name_size, path,
flags, key_type, value_type);
if (rb_grn_context_implement_db(context)) {
table = grn_table_create(context, name, name_size, path,
flags, key_type, value_type);
} else {
if (RVAL2CBOOL(rb_key_var_size))
flags |= GRN_OBJ_KEY_VAR_SIZE;
if (!NIL_P(rb_key_size))
key_size = NUM2UINT(rb_key_size);
value_size = 0;
table = (grn_obj *)grn_pat_create(context, path, key_size, value_size, flags);
}
if (!table)
rb_grn_context_check(context, rb_ary_new_from_values(argc, argv));
rb_table = GRNOBJECT2RVAL(klass, context, table, GRN_TRUE);
Expand Down
57 changes: 55 additions & 2 deletions ext/groonga/rb-grn-table.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ rb_grn_table_define_column (int argc, VALUE *argv, VALUE self)
unsigned name_size = 0;
grn_column_flags flags = 0;
VALUE rb_name, rb_value_type;
VALUE rb_value_size, rb_value_var_size;
VALUE options, rb_path, rb_persistent, rb_compress, rb_type, rb_with_weight;
VALUE rb_weight_float32;
VALUE rb_missing_mode;
Expand All @@ -319,6 +320,8 @@ rb_grn_table_define_column (int argc, VALUE *argv, VALUE self)
"path", &rb_path,
"persistent", &rb_persistent,
"type", &rb_type,
"value_size", &rb_value_size,
"value_var_size", &rb_value_var_size,
"with_weight", &rb_with_weight,
"compress", &rb_compress,
"weight_float32", &rb_weight_float32,
Expand Down Expand Up @@ -420,8 +423,58 @@ rb_grn_table_define_column (int argc, VALUE *argv, VALUE self)
rb_grn_inspect(rb_invalid_mode));
}

column = grn_column_create(context, table, name, name_size,
path, flags, value_type);
if (rb_grn_context_implement_db(context)) {
column = grn_column_create(context, table, name, name_size,
path, flags, value_type);
} else {
char fullname[GRN_TABLE_MAX_KEY_SIZE];
unsigned int fullname_size;
int table_name_len = strlen(fullname);
if (name_size + 1 + table_name_len > GRN_TABLE_MAX_KEY_SIZE) {
rb_raise(rb_eArgError,
"[column][create] too long column name: required name_size(%d) < %d"
": <%.*s>.<%.*s>",
name_size, GRN_TABLE_MAX_KEY_SIZE - 1 - table_name_len,
table_name_len, fullname, name_size, name);
}
// fullname[table_name_len] = '.';
// grn_memcpy(fullname + table_name_len + 1, name, name_size);
// fullname_size = table_name_len + 1 + name_size;
// grn_ctx *target_ctx = context;
// grn_id id = GRN_ID_NIL;
// id = grn_pat_add(target_ctx,
// target_ctx->impl->temporary_columns,
// fullname, fullname_size,
// NULL,
// &added);
// id |= GRN_OBJ_TMP_OBJECT | GRN_OBJ_TMP_COLUMN;

if (RVAL2CBOOL(rb_value_var_size))
flags |= GRN_OBJ_KEY_VAR_SIZE;
int64_t value_size = 0;
if (!NIL_P(rb_value_size))
value_size = NUM2INT(rb_value_size);

grn_obj *res;
switch (flags & GRN_OBJ_COLUMN_TYPE_MASK) {
case GRN_OBJ_COLUMN_SCALAR :
if ((flags & GRN_OBJ_KEY_VAR_SIZE) || value_size > sizeof(int64_t)) {
res = (grn_obj *)grn_ja_create(context, path, value_size, flags);
} else {
res = (grn_obj *)grn_ra_create(context, path, value_size, flags);
}
break;
case GRN_OBJ_COLUMN_VECTOR :
res = (grn_obj *)grn_ja_create(context, path, value_size * 30/*todo*/, flags);
//todo : zlib support
break;
case GRN_OBJ_COLUMN_INDEX :
res = (grn_obj *)grn_ii_create(context, path, table, flags); //todo : ii layout support
break;
}
column = res;
}

if (context->rc) {
VALUE rb_related_object;
rb_related_object =
Expand Down
1 change: 1 addition & 0 deletions ext/groonga/rb-grn.h
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ void rb_grn_context_reset_floating_objects(RbGrnContext *rb_grn_contex
void rb_grn_context_mark_grn_id (grn_ctx *context,
grn_id id);
grn_ctx *rb_grn_context_ensure (VALUE *context);
VALUE rb_grn_context_implement_db (grn_ctx *context);
VALUE rb_grn_context_get_default (void);
VALUE rb_grn_context_to_exception (grn_ctx *context,
VALUE related_object);
Expand Down
109 changes: 109 additions & 0 deletions test/test-patricia-trie-no-db.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2022 Horimoto Yasuhiro <horimoto@clear-code.com>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License version 2.1 as published by the Free Software Foundation.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA

class PatriciaTrieTestNoDB < Test::Unit::TestCase
include GroongaTestUtils
include ERB::Util


def test_support_key?
assert_predicate(Groonga::PatriciaTrie.create(key_size: 4096,
key_var_size: true),
:support_key?)
end

def test_add
users = Groonga::PatriciaTrie.create(key_size: 4096, key_var_size: true)
users.define_column("address", value_size: 4096, value_var_size: true)
me = users.add("me", :address => "me@example.com")
assert_equal("me@example.com", me[:address])
end

def test_key?
users = Groonga::PatriciaTrie.create(key_size: 4096, key_var_size: true)
assert_false(users.key?("morita"))
users.add("morita")
assert_true(users.key?("morita"))
end

def test_has_key?
users = Groonga::PatriciaTrie.create(key_size: 4096, key_var_size: true)
assert_false(users.has_key?("morita"))
users.add("morita")
assert_true(users.has_key?("morita"))
end

def test_scan
Groonga::Context.default_options = {:encoding => "utf-8"}
words = Groonga::PatriciaTrie.create(key_size: 4096, key_var_size: true)
words.add("リンク")
arupaka = words.add("アルパカ")
words.add("アルパカ(生物)")
adventure_of_link = words.add('リンクの冒険')
words.add('冒険')
gaxtu = words.add('ガッ')
muteki = words.add('MUTEKI')
assert_equal([[muteki, "MUTEKI", 0, 6],
[adventure_of_link, "リンクの冒険", 7, 18],
[arupaka, "アルパカ", 42, 12],
[gaxtu, "ガッ", 55, 6]],
words.scan('MUTEKI リンクの冒険 ミリバール アルパカ ガッ'))
end

def test_added?
users = Groonga::PatriciaTrie.create(key_size: 4096, key_var_size: true)
bob = users.add("bob")
assert_predicate(bob, :added?)
bob_again = users.add("bob")
assert_not_predicate(bob_again, :added?)
end

def test_rename
users = Groonga::PatriciaTrie.create(key_size: 4096, key_var_size: true)
name = users.define_column("name", value_size: 4096, value_var_size: true)
address = users.define_column("address", value_size: 4096, value_var_size: true)

users.rename("People")
assert_equal(["People", "People.name", "People.address"],
[users.name, name.name, address.name])
end

def test_each
users = Groonga::PatriciaTrie.create(key_size: 4096, key_var_size: true)
users.add("Alice")
users.add("Bob")
users.add("Carl")

user_names = []
users.each do |user|
user_names << user.key
end
assert_equal(["Alice", "Bob", "Carl"], user_names)
end

def test_truncate
users = Groonga::PatriciaTrie.create(key_size: 4096, key_var_size: true)
users.add("Alice")
users.add("Bob")
users.add("Carl")
assert_equal(3, users.size)
assert_nothing_raised do
users.truncate
end
assert_equal(0, users.size)
end
end