diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:07:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 18:07:14 +0000 |
commit | a175314c3e5827eb193872241446f2f8f5c9d33c (patch) | |
tree | cd3d60ca99ae00829c52a6ca79150a5b6e62528b /storage/mroonga/vendor/groonga/plugins/functions | |
parent | Initial commit. (diff) | |
download | mariadb-10.5-upstream.tar.xz mariadb-10.5-upstream.zip |
Adding upstream version 1:10.5.12.upstream/1%10.5.12upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'storage/mroonga/vendor/groonga/plugins/functions')
14 files changed, 1857 insertions, 0 deletions
diff --git a/storage/mroonga/vendor/groonga/plugins/functions/CMakeLists.txt b/storage/mroonga/vendor/groonga/plugins/functions/CMakeLists.txt new file mode 100644 index 00000000..65a6d2c3 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/CMakeLists.txt @@ -0,0 +1,141 @@ +# Copyright(C) 2015-2017 Brazil +# +# 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-1335 USA + +include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/../../lib + ) + +set(GRN_FUNCTIONS_PLUGIN_DIR "${GRN_RELATIVE_PLUGINS_DIR}/functions") + +read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/vector_sources.am + VECTOR_SOURCES) +set_source_files_properties(${VECTOR_SOURCES} + PROPERTIES + COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") +if(GRN_EMBED) + add_library(vector_functions STATIC ${VECTOR_SOURCES}) + set_target_properties( + vector_functions + PROPERTIES + POSITION_INDEPENDENT_CODE ON) +else() + add_library(vector_functions MODULE ${VECTOR_SOURCES}) + set_target_properties(vector_functions PROPERTIES + PREFIX "" + OUTPUT_NAME "vector") + install(TARGETS vector_functions DESTINATION "${GRN_FUNCTIONS_PLUGIN_DIR}") +endif() +target_link_libraries(vector_functions libgroonga) + +read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/string_sources.am + STRING_SOURCES) +set_source_files_properties(${STRING_SOURCES} + PROPERTIES + COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") +if(GRN_EMBED) + add_library(string_functions STATIC ${STRING_SOURCES}) + set_target_properties( + string_functions + PROPERTIES + POSITION_INDEPENDENT_CODE ON) +else() + add_library(string_functions MODULE ${STRING_SOURCES}) + set_target_properties(string_functions PROPERTIES + PREFIX "" + OUTPUT_NAME "string") + install(TARGETS string_functions DESTINATION "${GRN_FUNCTIONS_PLUGIN_DIR}") +endif() +target_link_libraries(string_functions libgroonga) + +read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/number_sources.am + NUMBER_SOURCES) +set_source_files_properties(${NUMBER_SOURCES} + PROPERTIES + COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") +if(GRN_EMBED) + add_library(number_functions STATIC ${NUMBER_SOURCES}) + set_target_properties( + number_functions + PROPERTIES + POSITION_INDEPENDENT_CODE ON) +else() + add_library(number_functions MODULE ${NUMBER_SOURCES}) + set_target_properties(number_functions PROPERTIES + PREFIX "" + OUTPUT_NAME "number") + install(TARGETS number_functions DESTINATION "${GRN_FUNCTIONS_PLUGIN_DIR}") +endif() +target_link_libraries(number_functions libgroonga "${M_LIBS}") + +read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/time_sources.am + TIME_SOURCES) +set_source_files_properties(${TIME_SOURCES} + PROPERTIES + COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") +if(GRN_EMBED) + add_library(time_functions STATIC ${TIME_SOURCES}) + set_target_properties( + time_functions + PROPERTIES + POSITION_INDEPENDENT_CODE ON) +else() + add_library(time_functions MODULE ${TIME_SOURCES}) + set_target_properties(time_functions PROPERTIES + PREFIX "" + OUTPUT_NAME "time") + install(TARGETS time_functions DESTINATION "${GRN_FUNCTIONS_PLUGIN_DIR}") +endif() +target_link_libraries(time_functions libgroonga) + +read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/index_column_sources.am + INDEX_COLUMN_SOURCES) +set_source_files_properties(${INDEX_COLUMN_SOURCES} + PROPERTIES + COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") +if(GRN_EMBED) + add_library(index_column_functions STATIC ${INDEX_COLUMN_SOURCES}) + set_target_properties( + index_column_functions + PROPERTIES + POSITION_INDEPENDENT_CODE ON) +else() + add_library(index_column_functions MODULE ${INDEX_COLUMN_SOURCES}) + set_target_properties(index_column_functions PROPERTIES + PREFIX "" + OUTPUT_NAME "index_column") + install(TARGETS index_column_functions + DESTINATION "${GRN_FUNCTIONS_PLUGIN_DIR}") +endif() +target_link_libraries(index_column_functions libgroonga) + +read_file_list(${CMAKE_CURRENT_SOURCE_DIR}/math_sources.am + MATH_SOURCES) +set_source_files_properties(${MATH_SOURCES} + PROPERTIES + COMPILE_FLAGS "${GRN_C_COMPILE_FLAGS}") +if(GRN_EMBED) + add_library(math_functions STATIC ${MATH_SOURCES}) + set_target_properties( + math_functions + PROPERTIES + POSITION_INDEPENDENT_CODE ON) +else() + add_library(math_functions MODULE ${MATH_SOURCES}) + set_target_properties(math_functions PROPERTIES + PREFIX "" + OUTPUT_NAME "math") + install(TARGETS math_functions DESTINATION "${GRN_FUNCTIONS_PLUGIN_DIR}") +endif() +target_link_libraries(math_functions libgroonga) diff --git a/storage/mroonga/vendor/groonga/plugins/functions/Makefile.am b/storage/mroonga/vendor/groonga/plugins/functions/Makefile.am new file mode 100644 index 00000000..f57ee031 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/Makefile.am @@ -0,0 +1,33 @@ +EXTRA_DIST = \ + CMakeLists.txt + +AM_CPPFLAGS = \ + -I$(top_builddir) \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/lib + +AM_LDFLAGS = \ + -avoid-version \ + -module \ + -no-undefined + +LIBS = \ + $(top_builddir)/lib/libgroonga.la + +function_plugins_LTLIBRARIES = +function_plugins_LTLIBRARIES += vector.la +function_plugins_LTLIBRARIES += string.la +function_plugins_LTLIBRARIES += number.la +function_plugins_LTLIBRARIES += time.la +function_plugins_LTLIBRARIES += index_column.la +function_plugins_LTLIBRARIES += math.la + +include vector_sources.am +include string_sources.am +include number_sources.am +include time_sources.am +include index_column_sources.am +include math_sources.am + +number_la_LIBADD = -lm +math_la_LIBADD = -lm diff --git a/storage/mroonga/vendor/groonga/plugins/functions/index_column.c b/storage/mroonga/vendor/groonga/plugins/functions/index_column.c new file mode 100644 index 00000000..05010074 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/index_column.c @@ -0,0 +1,266 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2017 Brazil + + 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-1335 USA +*/ + +#ifdef GRN_EMBEDDED +# define GRN_PLUGIN_FUNCTION_TAG functions_time +#endif + +#include <groonga/plugin.h> + +static grn_rc +selector_index_column_df_ratio_between(grn_ctx *ctx, + grn_obj *table, + grn_obj *index, + int n_args, + grn_obj **args, + grn_obj *res, + grn_operator op) +{ + grn_rc rc = GRN_SUCCESS; + grn_obj *index_column; + grn_ii *ii; + double min; + double max; + grn_obj *source_table; + unsigned int n_documents; + grn_posting posting; + + if ((n_args - 1) != 3) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "index_column_df_ratio_between(): " + "wrong number of arguments (%d for 3)", n_args - 1); + rc = ctx->rc; + goto exit; + } + + index_column = args[1]; + ii = (grn_ii *)index_column; + min = GRN_FLOAT_VALUE(args[2]); + max = GRN_FLOAT_VALUE(args[3]); + + source_table = grn_ctx_at(ctx, grn_obj_get_range(ctx, index_column)); + n_documents = grn_table_size(ctx, source_table); + memset(&posting, 0, sizeof(grn_posting)); + posting.sid = 1; + + if (op == GRN_OP_AND) { + GRN_TABLE_EACH_BEGIN(ctx, res, cursor, record_id) { + void *key; + grn_id term_id; + uint32_t n_match_documents; + double df_ratio; + + grn_table_cursor_get_key(ctx, cursor, &key); + term_id = *(grn_id *)key; + n_match_documents = grn_ii_estimate_size(ctx, ii, term_id); + if (n_match_documents > n_documents) { + n_match_documents = n_documents; + } + df_ratio = (double)n_match_documents / (double)n_documents; + if (min <= df_ratio && df_ratio <= max) { + posting.rid = term_id; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); + } + } GRN_TABLE_EACH_END(ctx, cursor); + grn_ii_resolve_sel_and(ctx, (grn_hash *)res, op); + } else { + GRN_TABLE_EACH_BEGIN(ctx, table, cursor, term_id) { + uint32_t n_match_documents; + double df_ratio; + + n_match_documents = grn_ii_estimate_size(ctx, ii, term_id); + if (n_match_documents > n_documents) { + n_match_documents = n_documents; + } + df_ratio = (double)n_match_documents / (double)n_documents; + { + void *key; + int key_size; + key_size = grn_table_cursor_get_key(ctx, cursor, &key); + } + if (min <= df_ratio && df_ratio <= max) { + posting.rid = term_id; + grn_ii_posting_add(ctx, &posting, (grn_hash *)res, op); + } + } GRN_TABLE_EACH_END(ctx, cursor); + } + +exit : + return rc; +} + +static grn_obj * +func_index_column_df_ratio(grn_ctx *ctx, + int n_args, + grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *term_table; + grn_obj *index_column_name; + grn_obj *index_column; + grn_ii *ii; + grn_id term_id; + + if (n_args != 1) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "index_column_df_ratio(): " + "wrong number of arguments (%d for 1)", n_args - 1); + return NULL; + } + + { + grn_obj *expr; + grn_obj *variable; + + expr = grn_plugin_proc_get_caller(ctx, user_data); + if (!expr) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "index_column_df_ratio(): " + "called directly"); + return NULL; + } + + variable = grn_expr_get_var_by_offset(ctx, expr, 0); + if (!variable) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "index_column_df_ratio(): " + "caller expression must have target record information"); + return NULL; + } + + term_table = grn_ctx_at(ctx, variable->header.domain); + term_id = GRN_RECORD_VALUE(variable); + while (GRN_TRUE) { + grn_obj *key_type; + + key_type = grn_ctx_at(ctx, term_table->header.domain); + if (!grn_obj_is_table(ctx, key_type)) { + break; + } + + grn_table_get_key(ctx, term_table, term_id, &term_id, sizeof(grn_id)); + term_table = key_type; + } + } + + index_column_name = args[0]; + if (!grn_obj_is_text_family_bulk(ctx, index_column_name)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, index_column_name); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "index_column_df_ratio(): " + "the first argument must be index column name: %.*s", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + + index_column = grn_obj_column(ctx, + term_table, + GRN_TEXT_VALUE(index_column_name), + GRN_TEXT_LEN(index_column_name)); + if (!index_column) { + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "index_column_df_ratio(): " + "nonexistent object: <%.*s>", + (int)GRN_TEXT_LEN(index_column_name), + GRN_TEXT_VALUE(index_column_name)); + return NULL; + } + + if (!grn_obj_is_index_column(ctx, index_column)) { + grn_obj inspected; + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, index_column); + GRN_PLUGIN_ERROR(ctx, + GRN_INVALID_ARGUMENT, + "index_column_df_ratio(): " + "the first argument must be index column: %.*s", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + if (grn_obj_is_accessor(ctx, index_column)) { + grn_obj_unlink(ctx, index_column); + } + return NULL; + } + + ii = (grn_ii *)index_column; + + { + grn_obj *source_table; + unsigned int n_documents; + uint32_t n_match_documents; + double df_ratio; + grn_obj *df_ratio_value; + + source_table = grn_ctx_at(ctx, grn_obj_get_range(ctx, index_column)); + n_documents = grn_table_size(ctx, source_table); + n_match_documents = grn_ii_estimate_size(ctx, ii, term_id); + if (n_match_documents > n_documents) { + n_match_documents = n_documents; + } + df_ratio = (double)n_match_documents / (double)n_documents; + + df_ratio_value = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_FLOAT, 0); + if (!df_ratio_value) { + return NULL; + } + GRN_FLOAT_SET(ctx, df_ratio_value, df_ratio); + return df_ratio_value; + } +} + +grn_rc +GRN_PLUGIN_INIT(grn_ctx *ctx) +{ + return ctx->rc; +} + +grn_rc +GRN_PLUGIN_REGISTER(grn_ctx *ctx) +{ + grn_obj *selector_proc; + + selector_proc = grn_proc_create(ctx, "index_column_df_ratio_between", -1, + GRN_PROC_FUNCTION, + NULL, NULL, NULL, 0, NULL); + grn_proc_set_selector(ctx, selector_proc, + selector_index_column_df_ratio_between); + grn_proc_set_selector_operator(ctx, selector_proc, GRN_OP_NOP); + + grn_proc_create(ctx, "index_column_df_ratio", -1, + GRN_PROC_FUNCTION, + func_index_column_df_ratio, NULL, NULL, 0, NULL); + + return ctx->rc; +} + +grn_rc +GRN_PLUGIN_FIN(grn_ctx *ctx) +{ + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/plugins/functions/index_column_sources.am b/storage/mroonga/vendor/groonga/plugins/functions/index_column_sources.am new file mode 100644 index 00000000..261907bc --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/index_column_sources.am @@ -0,0 +1,2 @@ +index_column_la_SOURCES = \ + index_column.c diff --git a/storage/mroonga/vendor/groonga/plugins/functions/math.c b/storage/mroonga/vendor/groonga/plugins/functions/math.c new file mode 100644 index 00000000..a6a9e260 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/math.c @@ -0,0 +1,142 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2017 Brazil + + 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-1335 USA +*/ + +#ifdef GRN_EMBEDDED +# define GRN_PLUGIN_FUNCTION_TAG functions_math +#endif + +#include <groonga/plugin.h> + +#include <math.h> +#include <stdlib.h> + +static grn_obj * +func_math_abs(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *number; + grn_obj *grn_abs_number = NULL; + + if (n_args != 1) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "math_abs(): wrong number of arguments (%d for 1)", + n_args); + return NULL; + } + + number = args[0]; + if (!(number->header.type == GRN_BULK && + grn_type_id_is_number_family(ctx, number->header.domain))) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, number); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "math_abs(): the first argument must be a number: " + "<%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + +#define ABS_AS_IS(return_type, to_type, getter, setter) { \ + grn_abs_number = grn_plugin_proc_alloc(ctx, \ + user_data, \ + (return_type), \ + 0); \ + if (!grn_abs_number) { \ + return NULL; \ + } \ + setter(ctx, grn_abs_number, getter(number)); \ + } +#define ABS_CONVERT_TYPE(func, return_type, to_type, getter, setter) { \ + grn_abs_number = grn_plugin_proc_alloc(ctx, \ + user_data, \ + (return_type), \ + 0); \ + if (!grn_abs_number) { \ + return NULL; \ + } else { \ + to_type abs_number_raw = (to_type)(func)(getter(number)); \ + setter(ctx, grn_abs_number, abs_number_raw); \ + } \ + } + + switch (number->header.domain) { + case GRN_DB_INT8: + ABS_CONVERT_TYPE(abs, GRN_DB_UINT8, uint8_t, GRN_INT8_VALUE, GRN_UINT8_SET); + break; + case GRN_DB_UINT8: + ABS_AS_IS(GRN_DB_UINT8, uint8_t, GRN_UINT8_VALUE, GRN_UINT8_SET); + break; + case GRN_DB_INT16: + ABS_CONVERT_TYPE(abs, GRN_DB_UINT16, uint16_t, GRN_INT16_VALUE, GRN_UINT16_SET); + break; + case GRN_DB_UINT16: + ABS_AS_IS(GRN_DB_UINT16, uint16_t, GRN_UINT16_VALUE, GRN_UINT16_SET); + break; + case GRN_DB_INT32: + ABS_CONVERT_TYPE(labs, GRN_DB_UINT32, uint32_t, GRN_INT32_VALUE, GRN_UINT32_SET); + break; + case GRN_DB_UINT32: + ABS_AS_IS(GRN_DB_UINT32, uint32_t, GRN_UINT32_VALUE, GRN_UINT32_SET); + break; + case GRN_DB_INT64: + ABS_CONVERT_TYPE(llabs, GRN_DB_UINT64, uint64_t, GRN_INT64_VALUE, GRN_UINT64_SET); + break; + case GRN_DB_UINT64: + ABS_AS_IS(GRN_DB_UINT64, uint64_t, GRN_UINT64_VALUE, GRN_UINT64_SET); + break; + case GRN_DB_FLOAT: + ABS_CONVERT_TYPE(fabs, GRN_DB_FLOAT, double, GRN_FLOAT_VALUE, GRN_FLOAT_SET); + break; + default : + break; + } +#undef ABS_CONVERT_TYPE +#undef ABS_AS_IS + + return grn_abs_number; +} + +grn_rc +GRN_PLUGIN_INIT(grn_ctx *ctx) +{ + return ctx->rc; +} + +grn_rc +GRN_PLUGIN_REGISTER(grn_ctx *ctx) +{ + grn_rc rc = GRN_SUCCESS; + + grn_proc_create(ctx, + "math_abs", -1, + GRN_PROC_FUNCTION, + func_math_abs, + NULL, NULL, 0, NULL); + + return rc; +} + +grn_rc +GRN_PLUGIN_FIN(grn_ctx *ctx) +{ + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/plugins/functions/math_sources.am b/storage/mroonga/vendor/groonga/plugins/functions/math_sources.am new file mode 100644 index 00000000..8c14ca74 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/math_sources.am @@ -0,0 +1,2 @@ +math_la_SOURCES = \ + math.c diff --git a/storage/mroonga/vendor/groonga/plugins/functions/number.c b/storage/mroonga/vendor/groonga/plugins/functions/number.c new file mode 100644 index 00000000..7cdfc0e1 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/number.c @@ -0,0 +1,187 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + 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-1335 USA +*/ + +#ifdef GRN_EMBEDDED +# define GRN_PLUGIN_FUNCTION_TAG functions_number +#endif + +#include <groonga/plugin.h> + +#include <math.h> + +static grn_obj * +func_number_classify(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *number; + grn_obj *interval; + grn_obj casted_interval; + grn_obj *classed_number; + + if (n_args != 2) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "number_classify(): wrong number of arguments (%d for 2)", + n_args); + return NULL; + } + + number = args[0]; + if (!(number->header.type == GRN_BULK && + grn_type_id_is_number_family(ctx, number->header.domain))) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, number); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "number_classify(): the first argument must be a number: " + "<%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + + interval = args[1]; + if (!(interval->header.type == GRN_BULK && + grn_type_id_is_number_family(ctx, interval->header.domain))) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, interval); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "number_classify(): the second argument must be a number: " + "<%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + + classed_number = grn_plugin_proc_alloc(ctx, + user_data, + number->header.domain, + 0); + if (!classed_number) { + return NULL; + } + + GRN_VALUE_FIX_SIZE_INIT(&casted_interval, 0, number->header.domain); + grn_obj_cast(ctx, interval, &casted_interval, GRN_FALSE); + +#define CLASSIFY_RAW(type, getter, setter, classifier) { \ + type number_raw; \ + type interval_raw; \ + type class_raw; \ + type classed_number_raw; \ + \ + number_raw = getter(number); \ + interval_raw = getter(&casted_interval); \ + class_raw = classifier(number_raw, interval_raw); \ + classed_number_raw = class_raw * interval_raw; \ + setter(ctx, classed_number, classed_number_raw); \ + } + +#define CLASSIFIER_INT(number_raw, interval_raw) \ + (number_raw) < 0 ? \ + ((((number_raw) + 1) / (interval_raw)) - 1) : \ + (((number_raw) / (interval_raw))) + +#define CLASSIFY_INT(type, getter, setter) \ + CLASSIFY_RAW(type, getter, setter, CLASSIFIER_INT) + +#define CLASSIFIER_UINT(number_raw, interval_raw) \ + ((number_raw) / (interval_raw)) + +#define CLASSIFY_UINT(type, getter, setter) \ + CLASSIFY_RAW(type, getter, setter, CLASSIFIER_UINT) + +#define CLASSIFIER_FLOAT(number_raw, interval_raw) \ + floor((number_raw) / (interval_raw)) + +#define CLASSIFY_FLOAT(getter, setter) \ + CLASSIFY_RAW(double, getter, setter, CLASSIFIER_FLOAT) + + switch (number->header.domain) { + case GRN_DB_INT8 : + CLASSIFY_INT(int8_t, GRN_INT8_VALUE, GRN_INT8_SET); + break; + case GRN_DB_UINT8 : + CLASSIFY_UINT(uint8_t, GRN_UINT8_VALUE, GRN_UINT8_SET); + break; + case GRN_DB_INT16 : + CLASSIFY_INT(int16_t, GRN_INT16_VALUE, GRN_INT16_SET); + break; + case GRN_DB_UINT16 : + CLASSIFY_UINT(uint16_t, GRN_UINT16_VALUE, GRN_UINT16_SET); + break; + case GRN_DB_INT32 : + CLASSIFY_INT(int32_t, GRN_INT32_VALUE, GRN_INT32_SET); + break; + case GRN_DB_UINT32 : + CLASSIFY_UINT(uint32_t, GRN_UINT32_VALUE, GRN_UINT32_SET); + break; + case GRN_DB_INT64 : + CLASSIFY_INT(int64_t, GRN_INT64_VALUE, GRN_INT64_SET); + break; + case GRN_DB_UINT64 : + CLASSIFY_UINT(uint64_t, GRN_UINT64_VALUE, GRN_UINT64_SET); + break; + case GRN_DB_FLOAT : + CLASSIFY_FLOAT(GRN_FLOAT_VALUE, GRN_FLOAT_SET); + break; + default : + break; + } +#undef CLASSIFY_FLOAT +#undef CLASSIFIER_FLAOT +#undef CLASSIFY_UINT +#undef CLASSIFIER_UINT +#undef CLASSIFY_INT +#undef CLASSIFIER_INT +#undef CLASSIFY_RAW + + GRN_OBJ_FIN(ctx, &casted_interval); + + return classed_number; +} + +grn_rc +GRN_PLUGIN_INIT(grn_ctx *ctx) +{ + return ctx->rc; +} + +grn_rc +GRN_PLUGIN_REGISTER(grn_ctx *ctx) +{ + grn_rc rc = GRN_SUCCESS; + + grn_proc_create(ctx, + "number_classify", -1, + GRN_PROC_FUNCTION, + func_number_classify, + NULL, NULL, 0, NULL); + + return rc; +} + +grn_rc +GRN_PLUGIN_FIN(grn_ctx *ctx) +{ + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/plugins/functions/number_sources.am b/storage/mroonga/vendor/groonga/plugins/functions/number_sources.am new file mode 100644 index 00000000..b3d9483b --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/number_sources.am @@ -0,0 +1,2 @@ +number_la_SOURCES = \ + number.c diff --git a/storage/mroonga/vendor/groonga/plugins/functions/string.c b/storage/mroonga/vendor/groonga/plugins/functions/string.c new file mode 100644 index 00000000..0af2d6ab --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/string.c @@ -0,0 +1,299 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + 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-1335 USA +*/ + +#ifdef GRN_EMBEDDED +# define GRN_PLUGIN_FUNCTION_TAG functions_string +#endif + +#include <groonga/plugin.h> + +/* + * func_string_length() returns the number of characters in a string. + * If the string contains an invalid byte sequence, this function returns the + * number of characters before the invalid byte sequence. + */ +static grn_obj * +func_string_length(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *target; + unsigned int length = 0; + grn_obj *grn_length; + + if (n_args != 1) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "string_length(): wrong number of arguments (%d for 1)", + n_args); + return NULL; + } + + target = args[0]; + if (!(target->header.type == GRN_BULK && + ((target->header.domain == GRN_DB_SHORT_TEXT) || + (target->header.domain == GRN_DB_TEXT) || + (target->header.domain == GRN_DB_LONG_TEXT)))) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, target); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "string_length(): target object must be a text bulk: " + "<%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + + { + const char *s = GRN_TEXT_VALUE(target); + const char *e = GRN_TEXT_VALUE(target) + GRN_TEXT_LEN(target); + const char *p; + unsigned int cl = 0; + for (p = s; p < e && (cl = grn_charlen(ctx, p, e)); p += cl) { + length++; + } + } + + grn_length = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_UINT32, 0); + if (!grn_length) { + return NULL; + } + + GRN_UINT32_SET(ctx, grn_length, length); + + return grn_length; +} + +static grn_obj * +func_string_substring(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *target; + grn_obj *from_raw; + grn_obj *length_raw = NULL; + int64_t from = 0; + int64_t length = -1; + const char *start = NULL; + const char *end = NULL; + grn_obj *substring; + + if (n_args < 2) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "string_substring(): wrong number of arguments (%d for 2..3)", + n_args); + return NULL; + } + + target = args[0]; + from_raw = args[1]; + if (n_args == 3) { + length_raw = args[2]; + } + + if (!(target->header.type == GRN_BULK && + grn_type_id_is_text_family(ctx, target->header.domain))) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, target); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "string_substring(): target object must be a text bulk: " + "<%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + + /* TODO: extract as grn_func_arg_int64() */ + if (!grn_type_id_is_number_family(ctx, from_raw->header.domain)) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, from_raw); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "string_substring(): from must be a number: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + if (from_raw->header.domain == GRN_DB_INT32) { + from = GRN_INT32_VALUE(from_raw); + } else if (from_raw->header.domain == GRN_DB_INT64) { + from = GRN_INT64_VALUE(from_raw); + } else { + grn_obj buffer; + grn_rc rc; + + GRN_INT64_INIT(&buffer, 0); + rc = grn_obj_cast(ctx, from_raw, &buffer, GRN_FALSE); + if (rc == GRN_SUCCESS) { + from = GRN_INT64_VALUE(&buffer); + } + GRN_OBJ_FIN(ctx, &buffer); + + if (rc != GRN_SUCCESS) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, from_raw); + GRN_PLUGIN_ERROR(ctx, rc, + "string_substring(): " + "failed to cast from value to number: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + } + + if (length_raw) { + /* TODO: extract as grn_func_arg_int64() */ + if (!grn_type_id_is_number_family(ctx, length_raw->header.domain)) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, length_raw); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "string_substring(): length must be a number: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + if (length_raw->header.domain == GRN_DB_INT32) { + length = GRN_INT32_VALUE(length_raw); + } else if (length_raw->header.domain == GRN_DB_INT64) { + length = GRN_INT64_VALUE(length_raw); + } else { + grn_obj buffer; + grn_rc rc; + + GRN_INT64_INIT(&buffer, 0); + rc = grn_obj_cast(ctx, length_raw, &buffer, GRN_FALSE); + if (rc == GRN_SUCCESS) { + length = GRN_INT64_VALUE(&buffer); + } + GRN_OBJ_FIN(ctx, &buffer); + + if (rc != GRN_SUCCESS) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, length_raw); + GRN_PLUGIN_ERROR(ctx, rc, + "string_substring(): " + "failed to cast length value to number: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + } + } + + substring = grn_plugin_proc_alloc(ctx, user_data, target->header.domain, 0); + if (!substring) { + return NULL; + } + + GRN_BULK_REWIND(substring); + + if (GRN_TEXT_LEN(target) == 0) { + return substring; + } + if (length == 0) { + return substring; + } + + while (from < 0) { + from += GRN_TEXT_LEN(target); + } + + { + const char *p; + + start = NULL; + p = GRN_TEXT_VALUE(target); + end = p + GRN_TEXT_LEN(target); + + if (from == 0) { + start = p; + } else { + unsigned int char_length = 0; + int64_t n_chars = 0; + + for (; + p < end && (char_length = grn_charlen(ctx, p, end)); + p += char_length, n_chars++) { + if (n_chars == from) { + start = p; + break; + } + } + } + + if (start && length > 0) { + unsigned int char_length = 0; + int64_t n_chars = 0; + + for (; + p < end && (char_length = grn_charlen(ctx, p, end)); + p += char_length, n_chars++) { + if (n_chars == length) { + end = p; + break; + } + } + } + } + + if (start) { + GRN_TEXT_SET(ctx, substring, start, end - start); + } + + return substring; +} + +grn_rc +GRN_PLUGIN_INIT(grn_ctx *ctx) +{ + return ctx->rc; +} + +grn_rc +GRN_PLUGIN_REGISTER(grn_ctx *ctx) +{ + grn_rc rc = GRN_SUCCESS; + + grn_proc_create(ctx, "string_length", -1, GRN_PROC_FUNCTION, func_string_length, + NULL, NULL, 0, NULL); + + grn_proc_create(ctx, "string_substring", -1, GRN_PROC_FUNCTION, func_string_substring, + NULL, NULL, 0, NULL); + + return rc; +} + +grn_rc +GRN_PLUGIN_FIN(grn_ctx *ctx) +{ + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/plugins/functions/string_sources.am b/storage/mroonga/vendor/groonga/plugins/functions/string_sources.am new file mode 100644 index 00000000..3477e58a --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/string_sources.am @@ -0,0 +1,2 @@ +string_la_SOURCES = \ + string.c diff --git a/storage/mroonga/vendor/groonga/plugins/functions/time.c b/storage/mroonga/vendor/groonga/plugins/functions/time.c new file mode 100644 index 00000000..f82ea872 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/time.c @@ -0,0 +1,376 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2016 Brazil + + 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-1335 USA +*/ + +#ifdef GRN_EMBEDDED +# define GRN_PLUGIN_FUNCTION_TAG functions_time +#endif + +#include <groonga/plugin.h> + +#include <math.h> + +typedef enum { + GRN_TIME_CLASSIFY_UNIT_SECOND, + GRN_TIME_CLASSIFY_UNIT_MINUTE, + GRN_TIME_CLASSIFY_UNIT_HOUR, + GRN_TIME_CLASSIFY_UNIT_DAY, + GRN_TIME_CLASSIFY_UNIT_WEEK, + GRN_TIME_CLASSIFY_UNIT_MONTH, + GRN_TIME_CLASSIFY_UNIT_YEAR +} grn_time_classify_unit; + +static grn_obj * +func_time_classify_raw(grn_ctx *ctx, + int n_args, + grn_obj **args, + grn_user_data *user_data, + const char *function_name, + grn_time_classify_unit unit) +{ + grn_obj *time; + uint32_t interval_raw = 1; + grn_obj *classed_time; + grn_bool accept_interval = GRN_TRUE; + + switch (unit) { + case GRN_TIME_CLASSIFY_UNIT_SECOND : + case GRN_TIME_CLASSIFY_UNIT_MINUTE : + case GRN_TIME_CLASSIFY_UNIT_HOUR : + accept_interval = GRN_TRUE; + break; + case GRN_TIME_CLASSIFY_UNIT_DAY : + case GRN_TIME_CLASSIFY_UNIT_WEEK : + accept_interval = GRN_FALSE; + break; + case GRN_TIME_CLASSIFY_UNIT_MONTH : + case GRN_TIME_CLASSIFY_UNIT_YEAR : + accept_interval = GRN_TRUE; + break; + } + + if (accept_interval) { + if (!(n_args == 1 || n_args == 2)) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "%s(): " + "wrong number of arguments (%d for 1..2)", + function_name, + n_args); + return NULL; + } + } else { + if (n_args != 1) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "%s(): " + "wrong number of arguments (%d for 1)", + function_name, + n_args); + return NULL; + } + } + + time = args[0]; + if (!(time->header.type == GRN_BULK && + time->header.domain == GRN_DB_TIME)) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, time); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "%s(): " + "the first argument must be a time: " + "<%.*s>", + function_name, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + + if (n_args == 2) { + grn_obj *interval; + grn_obj casted_interval; + + interval = args[1]; + if (!(interval->header.type == GRN_BULK && + grn_type_id_is_number_family(ctx, interval->header.domain))) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, interval); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "%s(): " + "the second argument must be a number: " + "<%.*s>", + function_name, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + + GRN_VALUE_FIX_SIZE_INIT(&casted_interval, 0, GRN_DB_UINT32); + grn_obj_cast(ctx, interval, &casted_interval, GRN_FALSE); + interval_raw = GRN_UINT32_VALUE(&casted_interval); + GRN_OBJ_FIN(ctx, &casted_interval); + + if (interval_raw == 0) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, interval); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "%s(): " + "the second argument must not be zero: " + "<%.*s>", + function_name, + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + } + + { + int64_t time_raw; + struct tm tm; + int64_t classed_time_raw; + + time_raw = GRN_TIME_VALUE(time); + if (!grn_time_to_tm(ctx, time_raw, &tm)) { + return NULL; + } + + switch (unit) { + case GRN_TIME_CLASSIFY_UNIT_SECOND : + tm.tm_sec = (tm.tm_sec / interval_raw) * interval_raw; + break; + case GRN_TIME_CLASSIFY_UNIT_MINUTE : + tm.tm_min = (tm.tm_min / interval_raw) * interval_raw; + tm.tm_sec = 0; + break; + case GRN_TIME_CLASSIFY_UNIT_HOUR : + tm.tm_hour = (tm.tm_hour / interval_raw) * interval_raw; + tm.tm_min = 0; + tm.tm_sec = 0; + break; + case GRN_TIME_CLASSIFY_UNIT_DAY : + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + break; + case GRN_TIME_CLASSIFY_UNIT_WEEK : + if ((tm.tm_mday - tm.tm_wday) >= 0) { + tm.tm_mday -= tm.tm_wday; + } else { + int n_underflowed_mday = -(tm.tm_mday - tm.tm_wday); + int mday; + int max_mday = 31; + + if (tm.tm_mon == 0) { + tm.tm_year--; + tm.tm_mon = 11; + } else { + tm.tm_mon--; + } + + for (mday = max_mday; mday > n_underflowed_mday; mday--) { + int64_t unused; + tm.tm_mday = mday; + if (grn_time_from_tm(ctx, &unused, &tm)) { + break; + } + } + tm.tm_mday -= n_underflowed_mday; + } + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + break; + case GRN_TIME_CLASSIFY_UNIT_MONTH : + tm.tm_mon = (tm.tm_mon / interval_raw) * interval_raw; + tm.tm_mday = 1; + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + break; + case GRN_TIME_CLASSIFY_UNIT_YEAR : + tm.tm_year = (((1900 + tm.tm_year) / interval_raw) * interval_raw) - 1900; + tm.tm_mon = 0; + tm.tm_mday = 1; + tm.tm_hour = 0; + tm.tm_min = 0; + tm.tm_sec = 0; + break; + } + + if (!grn_time_from_tm(ctx, &classed_time_raw, &tm)) { + return NULL; + } + + classed_time = grn_plugin_proc_alloc(ctx, + user_data, + time->header.domain, + 0); + if (!classed_time) { + return NULL; + } + GRN_TIME_SET(ctx, classed_time, classed_time_raw); + + return classed_time; + } +} + +static grn_obj * +func_time_classify_second(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + return func_time_classify_raw(ctx, + n_args, + args, + user_data, + "time_classify_second", + GRN_TIME_CLASSIFY_UNIT_SECOND); +} + +static grn_obj * +func_time_classify_minute(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + return func_time_classify_raw(ctx, + n_args, + args, + user_data, + "time_classify_minute", + GRN_TIME_CLASSIFY_UNIT_MINUTE); +} + +static grn_obj * +func_time_classify_hour(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + return func_time_classify_raw(ctx, + n_args, + args, + user_data, + "time_classify_hour", + GRN_TIME_CLASSIFY_UNIT_HOUR); +} + +static grn_obj * +func_time_classify_day(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + return func_time_classify_raw(ctx, + n_args, + args, + user_data, + "time_classify_day", + GRN_TIME_CLASSIFY_UNIT_DAY); +} + +static grn_obj * +func_time_classify_week(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + return func_time_classify_raw(ctx, + n_args, + args, + user_data, + "time_classify_week", + GRN_TIME_CLASSIFY_UNIT_WEEK); +} + +static grn_obj * +func_time_classify_month(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + return func_time_classify_raw(ctx, + n_args, + args, + user_data, + "time_classify_month", + GRN_TIME_CLASSIFY_UNIT_MONTH); +} + +static grn_obj * +func_time_classify_year(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + return func_time_classify_raw(ctx, + n_args, + args, + user_data, + "time_classify_year", + GRN_TIME_CLASSIFY_UNIT_YEAR); +} + +grn_rc +GRN_PLUGIN_INIT(grn_ctx *ctx) +{ + return ctx->rc; +} + +grn_rc +GRN_PLUGIN_REGISTER(grn_ctx *ctx) +{ + grn_rc rc = GRN_SUCCESS; + + grn_proc_create(ctx, + "time_classify_second", -1, + GRN_PROC_FUNCTION, + func_time_classify_second, + NULL, NULL, 0, NULL); + grn_proc_create(ctx, + "time_classify_minute", -1, + GRN_PROC_FUNCTION, + func_time_classify_minute, + NULL, NULL, 0, NULL); + grn_proc_create(ctx, + "time_classify_hour", -1, + GRN_PROC_FUNCTION, + func_time_classify_hour, + NULL, NULL, 0, NULL); + grn_proc_create(ctx, + "time_classify_day", -1, + GRN_PROC_FUNCTION, + func_time_classify_day, + NULL, NULL, 0, NULL); + grn_proc_create(ctx, + "time_classify_week", -1, + GRN_PROC_FUNCTION, + func_time_classify_week, + NULL, NULL, 0, NULL); + grn_proc_create(ctx, + "time_classify_month", -1, + GRN_PROC_FUNCTION, + func_time_classify_month, + NULL, NULL, 0, NULL); + grn_proc_create(ctx, + "time_classify_year", -1, + GRN_PROC_FUNCTION, + func_time_classify_year, + NULL, NULL, 0, NULL); + + return rc; +} + +grn_rc +GRN_PLUGIN_FIN(grn_ctx *ctx) +{ + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/plugins/functions/time_sources.am b/storage/mroonga/vendor/groonga/plugins/functions/time_sources.am new file mode 100644 index 00000000..2c55a570 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/time_sources.am @@ -0,0 +1,2 @@ +time_la_SOURCES = \ + time.c diff --git a/storage/mroonga/vendor/groonga/plugins/functions/vector.c b/storage/mroonga/vendor/groonga/plugins/functions/vector.c new file mode 100644 index 00000000..1104b313 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/vector.c @@ -0,0 +1,401 @@ +/* -*- c-basic-offset: 2 -*- */ +/* + Copyright(C) 2015-2017 Brazil + + 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-1335 USA +*/ + +#ifdef GRN_EMBEDDED +# define GRN_PLUGIN_FUNCTION_TAG functions_vector +#endif + +#include <groonga/plugin.h> + +static grn_obj * +func_vector_size(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *target; + unsigned int size; + grn_obj *grn_size; + + if (n_args != 1) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "vector_size(): wrong number of arguments (%d for 1)", + n_args); + return NULL; + } + + target = args[0]; + switch (target->header.type) { + case GRN_VECTOR : + case GRN_PVECTOR : + case GRN_UVECTOR : + size = grn_vector_size(ctx, target); + break; + default : + { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, target, &inspected); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "vector_size(): target object must be vector: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + break; + } + + grn_size = grn_plugin_proc_alloc(ctx, user_data, GRN_DB_UINT32, 0); + if (!grn_size) { + return NULL; + } + + GRN_UINT32_SET(ctx, grn_size, size); + + return grn_size; +} + +static grn_obj * +func_vector_slice(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *target; + grn_obj *from_raw = NULL; + grn_obj *length_raw = NULL; + int64_t from = 0; + int64_t length = -1; + uint32_t to = 0; + uint32_t size = 0; + grn_obj *slice; + + if (n_args < 2 || n_args > 3) { + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "vector_slice(): wrong number of arguments (%d for 2..3)", + n_args); + return NULL; + } + + target = args[0]; + from_raw = args[1]; + if (n_args == 3) { + length_raw = args[2]; + } + switch (target->header.type) { + case GRN_VECTOR : + case GRN_PVECTOR : + case GRN_UVECTOR : + size = grn_vector_size(ctx, target); + break; + default : + { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, target, &inspected); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "vector_slice(): target object must be vector: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + break; + } + + if (!grn_type_id_is_number_family(ctx, from_raw->header.domain)) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, from_raw); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "vector_slice(): from must be a number: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + if (from_raw->header.domain == GRN_DB_INT32) { + from = GRN_INT32_VALUE(from_raw); + } else if (from_raw->header.domain == GRN_DB_INT64) { + from = GRN_INT64_VALUE(from_raw); + } else { + grn_obj buffer; + grn_rc rc; + + GRN_INT64_INIT(&buffer, 0); + rc = grn_obj_cast(ctx, from_raw, &buffer, GRN_FALSE); + if (rc == GRN_SUCCESS) { + from = GRN_INT64_VALUE(&buffer); + } + GRN_OBJ_FIN(ctx, &buffer); + + if (rc != GRN_SUCCESS) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, from_raw); + GRN_PLUGIN_ERROR(ctx, rc, + "vector_slice(): " + "failed to cast from value to number: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + } + + if (length_raw) { + if (!grn_type_id_is_number_family(ctx, length_raw->header.domain)) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, length_raw); + GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT, + "vector_slice(): length must be a number: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + if (length_raw->header.domain == GRN_DB_INT32) { + length = GRN_INT32_VALUE(length_raw); + } else if (length_raw->header.domain == GRN_DB_INT64) { + length = GRN_INT64_VALUE(length_raw); + } else { + grn_obj buffer; + grn_rc rc; + + GRN_INT64_INIT(&buffer, 0); + rc = grn_obj_cast(ctx, length_raw, &buffer, GRN_FALSE); + if (rc == GRN_SUCCESS) { + length = GRN_INT64_VALUE(&buffer); + } + GRN_OBJ_FIN(ctx, &buffer); + + if (rc != GRN_SUCCESS) { + grn_obj inspected; + + GRN_TEXT_INIT(&inspected, 0); + grn_inspect(ctx, &inspected, length_raw); + GRN_PLUGIN_ERROR(ctx, rc, + "vector_slice(): " + "failed to cast length value to number: <%.*s>", + (int)GRN_TEXT_LEN(&inspected), + GRN_TEXT_VALUE(&inspected)); + GRN_OBJ_FIN(ctx, &inspected); + return NULL; + } + } + } + + slice = grn_plugin_proc_alloc(ctx, user_data, target->header.domain, GRN_OBJ_VECTOR); + if (!slice) { + return NULL; + } + + if (target->header.flags & GRN_OBJ_WITH_WEIGHT) { + slice->header.flags |= GRN_OBJ_WITH_WEIGHT; + } + + if (length < 0) { + length = size + length + 1; + } + + if (length > size) { + length = size; + } + + if (length <= 0) { + return slice; + } + + while (from < 0) { + from += size; + } + + to = from + length; + if (to > size) { + to = size; + } + + switch (target->header.type) { + case GRN_VECTOR : + { + unsigned int i; + for (i = from; i < to; i++) { + const char *content; + unsigned int content_length; + unsigned int weight; + grn_id domain; + content_length = grn_vector_get_element(ctx, target, i, + &content, &weight, &domain); + grn_vector_add_element(ctx, slice, + content, content_length, weight, domain); + } + } + break; + case GRN_PVECTOR : + { + unsigned int i; + for (i = from; i < to; i++) { + grn_obj *element = GRN_PTR_VALUE_AT(target, i); + GRN_PTR_PUT(ctx, slice, element); + } + } + break; + case GRN_UVECTOR : + { + grn_obj *domain; + + domain = grn_ctx_at(ctx, target->header.domain); + if (grn_obj_is_table(ctx, domain)) { + unsigned int i; + for (i = from; i < to; i++) { + grn_id id; + unsigned int weight; + id = grn_uvector_get_element(ctx, target, i, &weight); + grn_uvector_add_element(ctx, slice, id, weight); + } + } else { +#define PUT_SLICE_VALUES(type) do { \ + unsigned int i; \ + for (i = from; i < to; i++) { \ + GRN_ ## type ## _PUT(ctx, \ + slice, \ + GRN_ ## type ## _VALUE_AT(target, i)); \ + } \ + } while (GRN_FALSE) + switch (target->header.domain) { + case GRN_DB_BOOL : + PUT_SLICE_VALUES(BOOL); + break; + case GRN_DB_INT8 : + PUT_SLICE_VALUES(INT8); + break; + case GRN_DB_UINT8 : + PUT_SLICE_VALUES(UINT8); + break; + case GRN_DB_INT16 : + PUT_SLICE_VALUES(INT16); + break; + case GRN_DB_UINT16 : + PUT_SLICE_VALUES(UINT16); + break; + case GRN_DB_INT32 : + PUT_SLICE_VALUES(INT32); + break; + case GRN_DB_UINT32 : + PUT_SLICE_VALUES(UINT32); + break; + case GRN_DB_INT64 : + PUT_SLICE_VALUES(INT64); + break; + case GRN_DB_UINT64 : + PUT_SLICE_VALUES(UINT64); + break; + case GRN_DB_FLOAT : + PUT_SLICE_VALUES(FLOAT); + break; + case GRN_DB_TIME : + PUT_SLICE_VALUES(TIME); + break; + } + } + } + break; +#undef PUT_SLICE_VALUES + } + + return slice; +} + +static grn_obj * +func_vector_new(grn_ctx *ctx, int n_args, grn_obj **args, + grn_user_data *user_data) +{ + grn_obj *vector = NULL; + int i; + + if (n_args == 0) { + return grn_plugin_proc_alloc(ctx, user_data, GRN_DB_UINT32, GRN_OBJ_VECTOR); + } + + vector = grn_plugin_proc_alloc(ctx, + user_data, + args[0]->header.domain, + GRN_OBJ_VECTOR); + if (!vector) { + return NULL; + } + + for (i = 0; i < n_args; i++) { + grn_obj *element = args[i]; + switch (vector->header.type) { + case GRN_VECTOR : + grn_vector_add_element(ctx, + vector, + GRN_BULK_HEAD(element), + GRN_BULK_VSIZE(element), + 0, + element->header.domain); + break; + case GRN_UVECTOR : + grn_bulk_write(ctx, + vector, + GRN_BULK_HEAD(element), + GRN_BULK_VSIZE(element)); + break; + case GRN_PVECTOR : + GRN_PTR_PUT(ctx, vector, element); + break; + default : + break; + } + } + + return vector; +} + +grn_rc +GRN_PLUGIN_INIT(grn_ctx *ctx) +{ + return ctx->rc; +} + +grn_rc +GRN_PLUGIN_REGISTER(grn_ctx *ctx) +{ + grn_rc rc = GRN_SUCCESS; + + grn_proc_create(ctx, "vector_size", -1, GRN_PROC_FUNCTION, func_vector_size, + NULL, NULL, 0, NULL); + + grn_proc_create(ctx, "vector_slice", -1, GRN_PROC_FUNCTION, func_vector_slice, + NULL, NULL, 0, NULL); + + grn_proc_create(ctx, "vector_new", -1, GRN_PROC_FUNCTION, func_vector_new, + NULL, NULL, 0, NULL); + + return rc; +} + +grn_rc +GRN_PLUGIN_FIN(grn_ctx *ctx) +{ + return GRN_SUCCESS; +} diff --git a/storage/mroonga/vendor/groonga/plugins/functions/vector_sources.am b/storage/mroonga/vendor/groonga/plugins/functions/vector_sources.am new file mode 100644 index 00000000..1d98e651 --- /dev/null +++ b/storage/mroonga/vendor/groonga/plugins/functions/vector_sources.am @@ -0,0 +1,2 @@ +vector_la_SOURCES = \ + vector.c |